github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/third_party/react/react.js (about) 1 /** 2 * React v0.10.0 3 */ 4 !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ 5 /** 6 * Copyright 2013-2014 Facebook, Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 * @providesModule AutoFocusMixin 21 * @typechecks static-only 22 */ 23 24 "use strict"; 25 26 var focusNode = _dereq_("./focusNode"); 27 28 var AutoFocusMixin = { 29 componentDidMount: function() { 30 if (this.props.autoFocus) { 31 focusNode(this.getDOMNode()); 32 } 33 } 34 }; 35 36 module.exports = AutoFocusMixin; 37 38 },{"./focusNode":100}],2:[function(_dereq_,module,exports){ 39 /** 40 * Copyright 2013-2014 Facebook, Inc. 41 * 42 * Licensed under the Apache License, Version 2.0 (the "License"); 43 * you may not use this file except in compliance with the License. 44 * You may obtain a copy of the License at 45 * 46 * http://www.apache.org/licenses/LICENSE-2.0 47 * 48 * Unless required by applicable law or agreed to in writing, software 49 * distributed under the License is distributed on an "AS IS" BASIS, 50 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 51 * See the License for the specific language governing permissions and 52 * limitations under the License. 53 * 54 * @providesModule CSSProperty 55 */ 56 57 "use strict"; 58 59 /** 60 * CSS properties which accept numbers but are not in units of "px". 61 */ 62 var isUnitlessNumber = { 63 columnCount: true, 64 fillOpacity: true, 65 flex: true, 66 flexGrow: true, 67 flexShrink: true, 68 fontWeight: true, 69 lineClamp: true, 70 lineHeight: true, 71 opacity: true, 72 order: true, 73 orphans: true, 74 widows: true, 75 zIndex: true, 76 zoom: true 77 }; 78 79 /** 80 * @param {string} prefix vendor-specific prefix, eg: Webkit 81 * @param {string} key style name, eg: transitionDuration 82 * @return {string} style name prefixed with `prefix`, properly camelCased, eg: 83 * WebkitTransitionDuration 84 */ 85 function prefixKey(prefix, key) { 86 return prefix + key.charAt(0).toUpperCase() + key.substring(1); 87 } 88 89 /** 90 * Support style names that may come passed in prefixed by adding permutations 91 * of vendor prefixes. 92 */ 93 var prefixes = ['Webkit', 'ms', 'Moz', 'O']; 94 95 // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an 96 // infinite loop, because it iterates over the newly added props too. 97 Object.keys(isUnitlessNumber).forEach(function(prop) { 98 prefixes.forEach(function(prefix) { 99 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; 100 }); 101 }); 102 103 /** 104 * Most style properties can be unset by doing .style[prop] = '' but IE8 105 * doesn't like doing that with shorthand properties so for the properties that 106 * IE8 breaks on, which are listed here, we instead unset each of the 107 * individual properties. See http://bugs.jquery.com/ticket/12385. 108 * The 4-value 'clock' properties like margin, padding, border-width seem to 109 * behave without any problems. Curiously, list-style works too without any 110 * special prodding. 111 */ 112 var shorthandPropertyExpansions = { 113 background: { 114 backgroundImage: true, 115 backgroundPosition: true, 116 backgroundRepeat: true, 117 backgroundColor: true 118 }, 119 border: { 120 borderWidth: true, 121 borderStyle: true, 122 borderColor: true 123 }, 124 borderBottom: { 125 borderBottomWidth: true, 126 borderBottomStyle: true, 127 borderBottomColor: true 128 }, 129 borderLeft: { 130 borderLeftWidth: true, 131 borderLeftStyle: true, 132 borderLeftColor: true 133 }, 134 borderRight: { 135 borderRightWidth: true, 136 borderRightStyle: true, 137 borderRightColor: true 138 }, 139 borderTop: { 140 borderTopWidth: true, 141 borderTopStyle: true, 142 borderTopColor: true 143 }, 144 font: { 145 fontStyle: true, 146 fontVariant: true, 147 fontWeight: true, 148 fontSize: true, 149 lineHeight: true, 150 fontFamily: true 151 } 152 }; 153 154 var CSSProperty = { 155 isUnitlessNumber: isUnitlessNumber, 156 shorthandPropertyExpansions: shorthandPropertyExpansions 157 }; 158 159 module.exports = CSSProperty; 160 161 },{}],3:[function(_dereq_,module,exports){ 162 /** 163 * Copyright 2013-2014 Facebook, Inc. 164 * 165 * Licensed under the Apache License, Version 2.0 (the "License"); 166 * you may not use this file except in compliance with the License. 167 * You may obtain a copy of the License at 168 * 169 * http://www.apache.org/licenses/LICENSE-2.0 170 * 171 * Unless required by applicable law or agreed to in writing, software 172 * distributed under the License is distributed on an "AS IS" BASIS, 173 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 174 * See the License for the specific language governing permissions and 175 * limitations under the License. 176 * 177 * @providesModule CSSPropertyOperations 178 * @typechecks static-only 179 */ 180 181 "use strict"; 182 183 var CSSProperty = _dereq_("./CSSProperty"); 184 185 var dangerousStyleValue = _dereq_("./dangerousStyleValue"); 186 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); 187 var hyphenate = _dereq_("./hyphenate"); 188 var memoizeStringOnly = _dereq_("./memoizeStringOnly"); 189 190 var processStyleName = memoizeStringOnly(function(styleName) { 191 return escapeTextForBrowser(hyphenate(styleName)); 192 }); 193 194 /** 195 * Operations for dealing with CSS properties. 196 */ 197 var CSSPropertyOperations = { 198 199 /** 200 * Serializes a mapping of style properties for use as inline styles: 201 * 202 * > createMarkupForStyles({width: '200px', height: 0}) 203 * "width:200px;height:0;" 204 * 205 * Undefined values are ignored so that declarative programming is easier. 206 * 207 * @param {object} styles 208 * @return {?string} 209 */ 210 createMarkupForStyles: function(styles) { 211 var serialized = ''; 212 for (var styleName in styles) { 213 if (!styles.hasOwnProperty(styleName)) { 214 continue; 215 } 216 var styleValue = styles[styleName]; 217 if (styleValue != null) { 218 serialized += processStyleName(styleName) + ':'; 219 serialized += dangerousStyleValue(styleName, styleValue) + ';'; 220 } 221 } 222 return serialized || null; 223 }, 224 225 /** 226 * Sets the value for multiple styles on a node. If a value is specified as 227 * '' (empty string), the corresponding style property will be unset. 228 * 229 * @param {DOMElement} node 230 * @param {object} styles 231 */ 232 setValueForStyles: function(node, styles) { 233 var style = node.style; 234 for (var styleName in styles) { 235 if (!styles.hasOwnProperty(styleName)) { 236 continue; 237 } 238 var styleValue = dangerousStyleValue(styleName, styles[styleName]); 239 if (styleValue) { 240 style[styleName] = styleValue; 241 } else { 242 var expansion = CSSProperty.shorthandPropertyExpansions[styleName]; 243 if (expansion) { 244 // Shorthand property that IE8 won't like unsetting, so unset each 245 // component to placate it 246 for (var individualStyleName in expansion) { 247 style[individualStyleName] = ''; 248 } 249 } else { 250 style[styleName] = ''; 251 } 252 } 253 } 254 } 255 256 }; 257 258 module.exports = CSSPropertyOperations; 259 260 },{"./CSSProperty":2,"./dangerousStyleValue":95,"./escapeTextForBrowser":98,"./hyphenate":110,"./memoizeStringOnly":120}],4:[function(_dereq_,module,exports){ 261 /** 262 * Copyright 2013-2014 Facebook, Inc. 263 * 264 * Licensed under the Apache License, Version 2.0 (the "License"); 265 * you may not use this file except in compliance with the License. 266 * You may obtain a copy of the License at 267 * 268 * http://www.apache.org/licenses/LICENSE-2.0 269 * 270 * Unless required by applicable law or agreed to in writing, software 271 * distributed under the License is distributed on an "AS IS" BASIS, 272 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 273 * See the License for the specific language governing permissions and 274 * limitations under the License. 275 * 276 * @providesModule ChangeEventPlugin 277 */ 278 279 "use strict"; 280 281 var EventConstants = _dereq_("./EventConstants"); 282 var EventPluginHub = _dereq_("./EventPluginHub"); 283 var EventPropagators = _dereq_("./EventPropagators"); 284 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 285 var ReactUpdates = _dereq_("./ReactUpdates"); 286 var SyntheticEvent = _dereq_("./SyntheticEvent"); 287 288 var isEventSupported = _dereq_("./isEventSupported"); 289 var isTextInputElement = _dereq_("./isTextInputElement"); 290 var keyOf = _dereq_("./keyOf"); 291 292 var topLevelTypes = EventConstants.topLevelTypes; 293 294 var eventTypes = { 295 change: { 296 phasedRegistrationNames: { 297 bubbled: keyOf({onChange: null}), 298 captured: keyOf({onChangeCapture: null}) 299 }, 300 dependencies: [ 301 topLevelTypes.topBlur, 302 topLevelTypes.topChange, 303 topLevelTypes.topClick, 304 topLevelTypes.topFocus, 305 topLevelTypes.topInput, 306 topLevelTypes.topKeyDown, 307 topLevelTypes.topKeyUp, 308 topLevelTypes.topSelectionChange 309 ] 310 } 311 }; 312 313 /** 314 * For IE shims 315 */ 316 var activeElement = null; 317 var activeElementID = null; 318 var activeElementValue = null; 319 var activeElementValueProp = null; 320 321 /** 322 * SECTION: handle `change` event 323 */ 324 function shouldUseChangeEvent(elem) { 325 return ( 326 elem.nodeName === 'SELECT' || 327 (elem.nodeName === 'INPUT' && elem.type === 'file') 328 ); 329 } 330 331 var doesChangeEventBubble = false; 332 if (ExecutionEnvironment.canUseDOM) { 333 // See `handleChange` comment below 334 doesChangeEventBubble = isEventSupported('change') && ( 335 !('documentMode' in document) || document.documentMode > 8 336 ); 337 } 338 339 function manualDispatchChangeEvent(nativeEvent) { 340 var event = SyntheticEvent.getPooled( 341 eventTypes.change, 342 activeElementID, 343 nativeEvent 344 ); 345 EventPropagators.accumulateTwoPhaseDispatches(event); 346 347 // If change and propertychange bubbled, we'd just bind to it like all the 348 // other events and have it go through ReactEventTopLevelCallback. Since it 349 // doesn't, we manually listen for the events and so we have to enqueue and 350 // process the abstract event manually. 351 // 352 // Batching is necessary here in order to ensure that all event handlers run 353 // before the next rerender (including event handlers attached to ancestor 354 // elements instead of directly on the input). Without this, controlled 355 // components don't work properly in conjunction with event bubbling because 356 // the component is rerendered and the value reverted before all the event 357 // handlers can run. See https://github.com/facebook/react/issues/708. 358 ReactUpdates.batchedUpdates(runEventInBatch, event); 359 } 360 361 function runEventInBatch(event) { 362 EventPluginHub.enqueueEvents(event); 363 EventPluginHub.processEventQueue(); 364 } 365 366 function startWatchingForChangeEventIE8(target, targetID) { 367 activeElement = target; 368 activeElementID = targetID; 369 activeElement.attachEvent('onchange', manualDispatchChangeEvent); 370 } 371 372 function stopWatchingForChangeEventIE8() { 373 if (!activeElement) { 374 return; 375 } 376 activeElement.detachEvent('onchange', manualDispatchChangeEvent); 377 activeElement = null; 378 activeElementID = null; 379 } 380 381 function getTargetIDForChangeEvent( 382 topLevelType, 383 topLevelTarget, 384 topLevelTargetID) { 385 if (topLevelType === topLevelTypes.topChange) { 386 return topLevelTargetID; 387 } 388 } 389 function handleEventsForChangeEventIE8( 390 topLevelType, 391 topLevelTarget, 392 topLevelTargetID) { 393 if (topLevelType === topLevelTypes.topFocus) { 394 // stopWatching() should be a noop here but we call it just in case we 395 // missed a blur event somehow. 396 stopWatchingForChangeEventIE8(); 397 startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID); 398 } else if (topLevelType === topLevelTypes.topBlur) { 399 stopWatchingForChangeEventIE8(); 400 } 401 } 402 403 404 /** 405 * SECTION: handle `input` event 406 */ 407 var isInputEventSupported = false; 408 if (ExecutionEnvironment.canUseDOM) { 409 // IE9 claims to support the input event but fails to trigger it when 410 // deleting text, so we ignore its input events 411 isInputEventSupported = isEventSupported('input') && ( 412 !('documentMode' in document) || document.documentMode > 9 413 ); 414 } 415 416 /** 417 * (For old IE.) Replacement getter/setter for the `value` property that gets 418 * set on the active element. 419 */ 420 var newValueProp = { 421 get: function() { 422 return activeElementValueProp.get.call(this); 423 }, 424 set: function(val) { 425 // Cast to a string so we can do equality checks. 426 activeElementValue = '' + val; 427 activeElementValueProp.set.call(this, val); 428 } 429 }; 430 431 /** 432 * (For old IE.) Starts tracking propertychange events on the passed-in element 433 * and override the value property so that we can distinguish user events from 434 * value changes in JS. 435 */ 436 function startWatchingForValueChange(target, targetID) { 437 activeElement = target; 438 activeElementID = targetID; 439 activeElementValue = target.value; 440 activeElementValueProp = Object.getOwnPropertyDescriptor( 441 target.constructor.prototype, 442 'value' 443 ); 444 445 Object.defineProperty(activeElement, 'value', newValueProp); 446 activeElement.attachEvent('onpropertychange', handlePropertyChange); 447 } 448 449 /** 450 * (For old IE.) Removes the event listeners from the currently-tracked element, 451 * if any exists. 452 */ 453 function stopWatchingForValueChange() { 454 if (!activeElement) { 455 return; 456 } 457 458 // delete restores the original property definition 459 delete activeElement.value; 460 activeElement.detachEvent('onpropertychange', handlePropertyChange); 461 462 activeElement = null; 463 activeElementID = null; 464 activeElementValue = null; 465 activeElementValueProp = null; 466 } 467 468 /** 469 * (For old IE.) Handles a propertychange event, sending a `change` event if 470 * the value of the active element has changed. 471 */ 472 function handlePropertyChange(nativeEvent) { 473 if (nativeEvent.propertyName !== 'value') { 474 return; 475 } 476 var value = nativeEvent.srcElement.value; 477 if (value === activeElementValue) { 478 return; 479 } 480 activeElementValue = value; 481 482 manualDispatchChangeEvent(nativeEvent); 483 } 484 485 /** 486 * If a `change` event should be fired, returns the target's ID. 487 */ 488 function getTargetIDForInputEvent( 489 topLevelType, 490 topLevelTarget, 491 topLevelTargetID) { 492 if (topLevelType === topLevelTypes.topInput) { 493 // In modern browsers (i.e., not IE8 or IE9), the input event is exactly 494 // what we want so fall through here and trigger an abstract event 495 return topLevelTargetID; 496 } 497 } 498 499 // For IE8 and IE9. 500 function handleEventsForInputEventIE( 501 topLevelType, 502 topLevelTarget, 503 topLevelTargetID) { 504 if (topLevelType === topLevelTypes.topFocus) { 505 // In IE8, we can capture almost all .value changes by adding a 506 // propertychange handler and looking for events with propertyName 507 // equal to 'value' 508 // In IE9, propertychange fires for most input events but is buggy and 509 // doesn't fire when text is deleted, but conveniently, selectionchange 510 // appears to fire in all of the remaining cases so we catch those and 511 // forward the event if the value has changed 512 // In either case, we don't want to call the event handler if the value 513 // is changed from JS so we redefine a setter for `.value` that updates 514 // our activeElementValue variable, allowing us to ignore those changes 515 // 516 // stopWatching() should be a noop here but we call it just in case we 517 // missed a blur event somehow. 518 stopWatchingForValueChange(); 519 startWatchingForValueChange(topLevelTarget, topLevelTargetID); 520 } else if (topLevelType === topLevelTypes.topBlur) { 521 stopWatchingForValueChange(); 522 } 523 } 524 525 // For IE8 and IE9. 526 function getTargetIDForInputEventIE( 527 topLevelType, 528 topLevelTarget, 529 topLevelTargetID) { 530 if (topLevelType === topLevelTypes.topSelectionChange || 531 topLevelType === topLevelTypes.topKeyUp || 532 topLevelType === topLevelTypes.topKeyDown) { 533 // On the selectionchange event, the target is just document which isn't 534 // helpful for us so just check activeElement instead. 535 // 536 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 537 // propertychange on the first input event after setting `value` from a 538 // script and fires only keydown, keypress, keyup. Catching keyup usually 539 // gets it and catching keydown lets us fire an event for the first 540 // keystroke if user does a key repeat (it'll be a little delayed: right 541 // before the second keystroke). Other input methods (e.g., paste) seem to 542 // fire selectionchange normally. 543 if (activeElement && activeElement.value !== activeElementValue) { 544 activeElementValue = activeElement.value; 545 return activeElementID; 546 } 547 } 548 } 549 550 551 /** 552 * SECTION: handle `click` event 553 */ 554 function shouldUseClickEvent(elem) { 555 // Use the `click` event to detect changes to checkbox and radio inputs. 556 // This approach works across all browsers, whereas `change` does not fire 557 // until `blur` in IE8. 558 return ( 559 elem.nodeName === 'INPUT' && 560 (elem.type === 'checkbox' || elem.type === 'radio') 561 ); 562 } 563 564 function getTargetIDForClickEvent( 565 topLevelType, 566 topLevelTarget, 567 topLevelTargetID) { 568 if (topLevelType === topLevelTypes.topClick) { 569 return topLevelTargetID; 570 } 571 } 572 573 /** 574 * This plugin creates an `onChange` event that normalizes change events 575 * across form elements. This event fires at a time when it's possible to 576 * change the element's value without seeing a flicker. 577 * 578 * Supported elements are: 579 * - input (see `isTextInputElement`) 580 * - textarea 581 * - select 582 */ 583 var ChangeEventPlugin = { 584 585 eventTypes: eventTypes, 586 587 /** 588 * @param {string} topLevelType Record from `EventConstants`. 589 * @param {DOMEventTarget} topLevelTarget The listening component root node. 590 * @param {string} topLevelTargetID ID of `topLevelTarget`. 591 * @param {object} nativeEvent Native browser event. 592 * @return {*} An accumulation of synthetic events. 593 * @see {EventPluginHub.extractEvents} 594 */ 595 extractEvents: function( 596 topLevelType, 597 topLevelTarget, 598 topLevelTargetID, 599 nativeEvent) { 600 601 var getTargetIDFunc, handleEventFunc; 602 if (shouldUseChangeEvent(topLevelTarget)) { 603 if (doesChangeEventBubble) { 604 getTargetIDFunc = getTargetIDForChangeEvent; 605 } else { 606 handleEventFunc = handleEventsForChangeEventIE8; 607 } 608 } else if (isTextInputElement(topLevelTarget)) { 609 if (isInputEventSupported) { 610 getTargetIDFunc = getTargetIDForInputEvent; 611 } else { 612 getTargetIDFunc = getTargetIDForInputEventIE; 613 handleEventFunc = handleEventsForInputEventIE; 614 } 615 } else if (shouldUseClickEvent(topLevelTarget)) { 616 getTargetIDFunc = getTargetIDForClickEvent; 617 } 618 619 if (getTargetIDFunc) { 620 var targetID = getTargetIDFunc( 621 topLevelType, 622 topLevelTarget, 623 topLevelTargetID 624 ); 625 if (targetID) { 626 var event = SyntheticEvent.getPooled( 627 eventTypes.change, 628 targetID, 629 nativeEvent 630 ); 631 EventPropagators.accumulateTwoPhaseDispatches(event); 632 return event; 633 } 634 } 635 636 if (handleEventFunc) { 637 handleEventFunc( 638 topLevelType, 639 topLevelTarget, 640 topLevelTargetID 641 ); 642 } 643 } 644 645 }; 646 647 module.exports = ChangeEventPlugin; 648 649 },{"./EventConstants":14,"./EventPluginHub":16,"./EventPropagators":19,"./ExecutionEnvironment":20,"./ReactUpdates":71,"./SyntheticEvent":78,"./isEventSupported":113,"./isTextInputElement":115,"./keyOf":119}],5:[function(_dereq_,module,exports){ 650 /** 651 * Copyright 2013-2014 Facebook, Inc. 652 * 653 * Licensed under the Apache License, Version 2.0 (the "License"); 654 * you may not use this file except in compliance with the License. 655 * You may obtain a copy of the License at 656 * 657 * http://www.apache.org/licenses/LICENSE-2.0 658 * 659 * Unless required by applicable law or agreed to in writing, software 660 * distributed under the License is distributed on an "AS IS" BASIS, 661 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 662 * See the License for the specific language governing permissions and 663 * limitations under the License. 664 * 665 * @providesModule ClientReactRootIndex 666 * @typechecks 667 */ 668 669 "use strict"; 670 671 var nextReactRootIndex = 0; 672 673 var ClientReactRootIndex = { 674 createReactRootIndex: function() { 675 return nextReactRootIndex++; 676 } 677 }; 678 679 module.exports = ClientReactRootIndex; 680 681 },{}],6:[function(_dereq_,module,exports){ 682 /** 683 * Copyright 2013-2014 Facebook, Inc. 684 * 685 * Licensed under the Apache License, Version 2.0 (the "License"); 686 * you may not use this file except in compliance with the License. 687 * You may obtain a copy of the License at 688 * 689 * http://www.apache.org/licenses/LICENSE-2.0 690 * 691 * Unless required by applicable law or agreed to in writing, software 692 * distributed under the License is distributed on an "AS IS" BASIS, 693 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 694 * See the License for the specific language governing permissions and 695 * limitations under the License. 696 * 697 * @providesModule CompositionEventPlugin 698 * @typechecks static-only 699 */ 700 701 "use strict"; 702 703 var EventConstants = _dereq_("./EventConstants"); 704 var EventPropagators = _dereq_("./EventPropagators"); 705 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 706 var ReactInputSelection = _dereq_("./ReactInputSelection"); 707 var SyntheticCompositionEvent = _dereq_("./SyntheticCompositionEvent"); 708 709 var getTextContentAccessor = _dereq_("./getTextContentAccessor"); 710 var keyOf = _dereq_("./keyOf"); 711 712 var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 713 var START_KEYCODE = 229; 714 715 var useCompositionEvent = ( 716 ExecutionEnvironment.canUseDOM && 717 'CompositionEvent' in window 718 ); 719 720 // In IE9+, we have access to composition events, but the data supplied 721 // by the native compositionend event may be incorrect. In Korean, for example, 722 // the compositionend event contains only one character regardless of 723 // how many characters have been composed since compositionstart. 724 // We therefore use the fallback data while still using the native 725 // events as triggers. 726 var useFallbackData = ( 727 !useCompositionEvent || 728 'documentMode' in document && document.documentMode > 8 729 ); 730 731 var topLevelTypes = EventConstants.topLevelTypes; 732 var currentComposition = null; 733 734 // Events and their corresponding property names. 735 var eventTypes = { 736 compositionEnd: { 737 phasedRegistrationNames: { 738 bubbled: keyOf({onCompositionEnd: null}), 739 captured: keyOf({onCompositionEndCapture: null}) 740 }, 741 dependencies: [ 742 topLevelTypes.topBlur, 743 topLevelTypes.topCompositionEnd, 744 topLevelTypes.topKeyDown, 745 topLevelTypes.topKeyPress, 746 topLevelTypes.topKeyUp, 747 topLevelTypes.topMouseDown 748 ] 749 }, 750 compositionStart: { 751 phasedRegistrationNames: { 752 bubbled: keyOf({onCompositionStart: null}), 753 captured: keyOf({onCompositionStartCapture: null}) 754 }, 755 dependencies: [ 756 topLevelTypes.topBlur, 757 topLevelTypes.topCompositionStart, 758 topLevelTypes.topKeyDown, 759 topLevelTypes.topKeyPress, 760 topLevelTypes.topKeyUp, 761 topLevelTypes.topMouseDown 762 ] 763 }, 764 compositionUpdate: { 765 phasedRegistrationNames: { 766 bubbled: keyOf({onCompositionUpdate: null}), 767 captured: keyOf({onCompositionUpdateCapture: null}) 768 }, 769 dependencies: [ 770 topLevelTypes.topBlur, 771 topLevelTypes.topCompositionUpdate, 772 topLevelTypes.topKeyDown, 773 topLevelTypes.topKeyPress, 774 topLevelTypes.topKeyUp, 775 topLevelTypes.topMouseDown 776 ] 777 } 778 }; 779 780 /** 781 * Translate native top level events into event types. 782 * 783 * @param {string} topLevelType 784 * @return {object} 785 */ 786 function getCompositionEventType(topLevelType) { 787 switch (topLevelType) { 788 case topLevelTypes.topCompositionStart: 789 return eventTypes.compositionStart; 790 case topLevelTypes.topCompositionEnd: 791 return eventTypes.compositionEnd; 792 case topLevelTypes.topCompositionUpdate: 793 return eventTypes.compositionUpdate; 794 } 795 } 796 797 /** 798 * Does our fallback best-guess model think this event signifies that 799 * composition has begun? 800 * 801 * @param {string} topLevelType 802 * @param {object} nativeEvent 803 * @return {boolean} 804 */ 805 function isFallbackStart(topLevelType, nativeEvent) { 806 return ( 807 topLevelType === topLevelTypes.topKeyDown && 808 nativeEvent.keyCode === START_KEYCODE 809 ); 810 } 811 812 /** 813 * Does our fallback mode think that this event is the end of composition? 814 * 815 * @param {string} topLevelType 816 * @param {object} nativeEvent 817 * @return {boolean} 818 */ 819 function isFallbackEnd(topLevelType, nativeEvent) { 820 switch (topLevelType) { 821 case topLevelTypes.topKeyUp: 822 // Command keys insert or clear IME input. 823 return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); 824 case topLevelTypes.topKeyDown: 825 // Expect IME keyCode on each keydown. If we get any other 826 // code we must have exited earlier. 827 return (nativeEvent.keyCode !== START_KEYCODE); 828 case topLevelTypes.topKeyPress: 829 case topLevelTypes.topMouseDown: 830 case topLevelTypes.topBlur: 831 // Events are not possible without cancelling IME. 832 return true; 833 default: 834 return false; 835 } 836 } 837 838 /** 839 * Helper class stores information about selection and document state 840 * so we can figure out what changed at a later date. 841 * 842 * @param {DOMEventTarget} root 843 */ 844 function FallbackCompositionState(root) { 845 this.root = root; 846 this.startSelection = ReactInputSelection.getSelection(root); 847 this.startValue = this.getText(); 848 } 849 850 /** 851 * Get current text of input. 852 * 853 * @return {string} 854 */ 855 FallbackCompositionState.prototype.getText = function() { 856 return this.root.value || this.root[getTextContentAccessor()]; 857 }; 858 859 /** 860 * Text that has changed since the start of composition. 861 * 862 * @return {string} 863 */ 864 FallbackCompositionState.prototype.getData = function() { 865 var endValue = this.getText(); 866 var prefixLength = this.startSelection.start; 867 var suffixLength = this.startValue.length - this.startSelection.end; 868 869 return endValue.substr( 870 prefixLength, 871 endValue.length - suffixLength - prefixLength 872 ); 873 }; 874 875 /** 876 * This plugin creates `onCompositionStart`, `onCompositionUpdate` and 877 * `onCompositionEnd` events on inputs, textareas and contentEditable 878 * nodes. 879 */ 880 var CompositionEventPlugin = { 881 882 eventTypes: eventTypes, 883 884 /** 885 * @param {string} topLevelType Record from `EventConstants`. 886 * @param {DOMEventTarget} topLevelTarget The listening component root node. 887 * @param {string} topLevelTargetID ID of `topLevelTarget`. 888 * @param {object} nativeEvent Native browser event. 889 * @return {*} An accumulation of synthetic events. 890 * @see {EventPluginHub.extractEvents} 891 */ 892 extractEvents: function( 893 topLevelType, 894 topLevelTarget, 895 topLevelTargetID, 896 nativeEvent) { 897 898 var eventType; 899 var data; 900 901 if (useCompositionEvent) { 902 eventType = getCompositionEventType(topLevelType); 903 } else if (!currentComposition) { 904 if (isFallbackStart(topLevelType, nativeEvent)) { 905 eventType = eventTypes.compositionStart; 906 } 907 } else if (isFallbackEnd(topLevelType, nativeEvent)) { 908 eventType = eventTypes.compositionEnd; 909 } 910 911 if (useFallbackData) { 912 // The current composition is stored statically and must not be 913 // overwritten while composition continues. 914 if (!currentComposition && eventType === eventTypes.compositionStart) { 915 currentComposition = new FallbackCompositionState(topLevelTarget); 916 } else if (eventType === eventTypes.compositionEnd) { 917 if (currentComposition) { 918 data = currentComposition.getData(); 919 currentComposition = null; 920 } 921 } 922 } 923 924 if (eventType) { 925 var event = SyntheticCompositionEvent.getPooled( 926 eventType, 927 topLevelTargetID, 928 nativeEvent 929 ); 930 if (data) { 931 // Inject data generated from fallback path into the synthetic event. 932 // This matches the property of native CompositionEventInterface. 933 event.data = data; 934 } 935 EventPropagators.accumulateTwoPhaseDispatches(event); 936 return event; 937 } 938 } 939 }; 940 941 module.exports = CompositionEventPlugin; 942 943 },{"./EventConstants":14,"./EventPropagators":19,"./ExecutionEnvironment":20,"./ReactInputSelection":52,"./SyntheticCompositionEvent":76,"./getTextContentAccessor":108,"./keyOf":119}],7:[function(_dereq_,module,exports){ 944 /** 945 * Copyright 2013-2014 Facebook, Inc. 946 * 947 * Licensed under the Apache License, Version 2.0 (the "License"); 948 * you may not use this file except in compliance with the License. 949 * You may obtain a copy of the License at 950 * 951 * http://www.apache.org/licenses/LICENSE-2.0 952 * 953 * Unless required by applicable law or agreed to in writing, software 954 * distributed under the License is distributed on an "AS IS" BASIS, 955 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 956 * See the License for the specific language governing permissions and 957 * limitations under the License. 958 * 959 * @providesModule DOMChildrenOperations 960 * @typechecks static-only 961 */ 962 963 "use strict"; 964 965 var Danger = _dereq_("./Danger"); 966 var ReactMultiChildUpdateTypes = _dereq_("./ReactMultiChildUpdateTypes"); 967 968 var getTextContentAccessor = _dereq_("./getTextContentAccessor"); 969 970 /** 971 * The DOM property to use when setting text content. 972 * 973 * @type {string} 974 * @private 975 */ 976 var textContentAccessor = getTextContentAccessor(); 977 978 /** 979 * Inserts `childNode` as a child of `parentNode` at the `index`. 980 * 981 * @param {DOMElement} parentNode Parent node in which to insert. 982 * @param {DOMElement} childNode Child node to insert. 983 * @param {number} index Index at which to insert the child. 984 * @internal 985 */ 986 function insertChildAt(parentNode, childNode, index) { 987 var childNodes = parentNode.childNodes; 988 if (childNodes[index] === childNode) { 989 return; 990 } 991 // If `childNode` is already a child of `parentNode`, remove it so that 992 // computing `childNodes[index]` takes into account the removal. 993 if (childNode.parentNode === parentNode) { 994 parentNode.removeChild(childNode); 995 } 996 if (index >= childNodes.length) { 997 parentNode.appendChild(childNode); 998 } else { 999 parentNode.insertBefore(childNode, childNodes[index]); 1000 } 1001 } 1002 1003 var updateTextContent; 1004 if (textContentAccessor === 'textContent') { 1005 /** 1006 * Sets the text content of `node` to `text`. 1007 * 1008 * @param {DOMElement} node Node to change 1009 * @param {string} text New text content 1010 */ 1011 updateTextContent = function(node, text) { 1012 node.textContent = text; 1013 }; 1014 } else { 1015 /** 1016 * Sets the text content of `node` to `text`. 1017 * 1018 * @param {DOMElement} node Node to change 1019 * @param {string} text New text content 1020 */ 1021 updateTextContent = function(node, text) { 1022 // In order to preserve newlines correctly, we can't use .innerText to set 1023 // the contents (see #1080), so we empty the element then append a text node 1024 while (node.firstChild) { 1025 node.removeChild(node.firstChild); 1026 } 1027 if (text) { 1028 var doc = node.ownerDocument || document; 1029 node.appendChild(doc.createTextNode(text)); 1030 } 1031 }; 1032 } 1033 1034 /** 1035 * Operations for updating with DOM children. 1036 */ 1037 var DOMChildrenOperations = { 1038 1039 dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, 1040 1041 updateTextContent: updateTextContent, 1042 1043 /** 1044 * Updates a component's children by processing a series of updates. The 1045 * update configurations are each expected to have a `parentNode` property. 1046 * 1047 * @param {array<object>} updates List of update configurations. 1048 * @param {array<string>} markupList List of markup strings. 1049 * @internal 1050 */ 1051 processUpdates: function(updates, markupList) { 1052 var update; 1053 // Mapping from parent IDs to initial child orderings. 1054 var initialChildren = null; 1055 // List of children that will be moved or removed. 1056 var updatedChildren = null; 1057 1058 for (var i = 0; update = updates[i]; i++) { 1059 if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || 1060 update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { 1061 var updatedIndex = update.fromIndex; 1062 var updatedChild = update.parentNode.childNodes[updatedIndex]; 1063 var parentID = update.parentID; 1064 1065 initialChildren = initialChildren || {}; 1066 initialChildren[parentID] = initialChildren[parentID] || []; 1067 initialChildren[parentID][updatedIndex] = updatedChild; 1068 1069 updatedChildren = updatedChildren || []; 1070 updatedChildren.push(updatedChild); 1071 } 1072 } 1073 1074 var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); 1075 1076 // Remove updated children first so that `toIndex` is consistent. 1077 if (updatedChildren) { 1078 for (var j = 0; j < updatedChildren.length; j++) { 1079 updatedChildren[j].parentNode.removeChild(updatedChildren[j]); 1080 } 1081 } 1082 1083 for (var k = 0; update = updates[k]; k++) { 1084 switch (update.type) { 1085 case ReactMultiChildUpdateTypes.INSERT_MARKUP: 1086 insertChildAt( 1087 update.parentNode, 1088 renderedMarkup[update.markupIndex], 1089 update.toIndex 1090 ); 1091 break; 1092 case ReactMultiChildUpdateTypes.MOVE_EXISTING: 1093 insertChildAt( 1094 update.parentNode, 1095 initialChildren[update.parentID][update.fromIndex], 1096 update.toIndex 1097 ); 1098 break; 1099 case ReactMultiChildUpdateTypes.TEXT_CONTENT: 1100 updateTextContent( 1101 update.parentNode, 1102 update.textContent 1103 ); 1104 break; 1105 case ReactMultiChildUpdateTypes.REMOVE_NODE: 1106 // Already removed by the for-loop above. 1107 break; 1108 } 1109 } 1110 } 1111 1112 }; 1113 1114 module.exports = DOMChildrenOperations; 1115 1116 },{"./Danger":10,"./ReactMultiChildUpdateTypes":58,"./getTextContentAccessor":108}],8:[function(_dereq_,module,exports){ 1117 /** 1118 * Copyright 2013-2014 Facebook, Inc. 1119 * 1120 * Licensed under the Apache License, Version 2.0 (the "License"); 1121 * you may not use this file except in compliance with the License. 1122 * You may obtain a copy of the License at 1123 * 1124 * http://www.apache.org/licenses/LICENSE-2.0 1125 * 1126 * Unless required by applicable law or agreed to in writing, software 1127 * distributed under the License is distributed on an "AS IS" BASIS, 1128 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1129 * See the License for the specific language governing permissions and 1130 * limitations under the License. 1131 * 1132 * @providesModule DOMProperty 1133 * @typechecks static-only 1134 */ 1135 1136 /*jslint bitwise: true */ 1137 1138 "use strict"; 1139 1140 var invariant = _dereq_("./invariant"); 1141 1142 var DOMPropertyInjection = { 1143 /** 1144 * Mapping from normalized, camelcased property names to a configuration that 1145 * specifies how the associated DOM property should be accessed or rendered. 1146 */ 1147 MUST_USE_ATTRIBUTE: 0x1, 1148 MUST_USE_PROPERTY: 0x2, 1149 HAS_SIDE_EFFECTS: 0x4, 1150 HAS_BOOLEAN_VALUE: 0x8, 1151 HAS_POSITIVE_NUMERIC_VALUE: 0x10, 1152 1153 /** 1154 * Inject some specialized knowledge about the DOM. This takes a config object 1155 * with the following properties: 1156 * 1157 * isCustomAttribute: function that given an attribute name will return true 1158 * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* 1159 * attributes where it's impossible to enumerate all of the possible 1160 * attribute names, 1161 * 1162 * Properties: object mapping DOM property name to one of the 1163 * DOMPropertyInjection constants or null. If your attribute isn't in here, 1164 * it won't get written to the DOM. 1165 * 1166 * DOMAttributeNames: object mapping React attribute name to the DOM 1167 * attribute name. Attribute names not specified use the **lowercase** 1168 * normalized name. 1169 * 1170 * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. 1171 * Property names not specified use the normalized name. 1172 * 1173 * DOMMutationMethods: Properties that require special mutation methods. If 1174 * `value` is undefined, the mutation method should unset the property. 1175 * 1176 * @param {object} domPropertyConfig the config as described above. 1177 */ 1178 injectDOMPropertyConfig: function(domPropertyConfig) { 1179 var Properties = domPropertyConfig.Properties || {}; 1180 var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; 1181 var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; 1182 var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; 1183 1184 if (domPropertyConfig.isCustomAttribute) { 1185 DOMProperty._isCustomAttributeFunctions.push( 1186 domPropertyConfig.isCustomAttribute 1187 ); 1188 } 1189 1190 for (var propName in Properties) { 1191 ("production" !== "development" ? invariant( 1192 !DOMProperty.isStandardName[propName], 1193 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + 1194 '\'%s\' which has already been injected. You may be accidentally ' + 1195 'injecting the same DOM property config twice, or you may be ' + 1196 'injecting two configs that have conflicting property names.', 1197 propName 1198 ) : invariant(!DOMProperty.isStandardName[propName])); 1199 1200 DOMProperty.isStandardName[propName] = true; 1201 1202 var lowerCased = propName.toLowerCase(); 1203 DOMProperty.getPossibleStandardName[lowerCased] = propName; 1204 1205 var attributeName = DOMAttributeNames[propName]; 1206 if (attributeName) { 1207 DOMProperty.getPossibleStandardName[attributeName] = propName; 1208 } 1209 1210 DOMProperty.getAttributeName[propName] = attributeName || lowerCased; 1211 1212 DOMProperty.getPropertyName[propName] = 1213 DOMPropertyNames[propName] || propName; 1214 1215 var mutationMethod = DOMMutationMethods[propName]; 1216 if (mutationMethod) { 1217 DOMProperty.getMutationMethod[propName] = mutationMethod; 1218 } 1219 1220 var propConfig = Properties[propName]; 1221 DOMProperty.mustUseAttribute[propName] = 1222 propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; 1223 DOMProperty.mustUseProperty[propName] = 1224 propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; 1225 DOMProperty.hasSideEffects[propName] = 1226 propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; 1227 DOMProperty.hasBooleanValue[propName] = 1228 propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; 1229 DOMProperty.hasPositiveNumericValue[propName] = 1230 propConfig & DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE; 1231 1232 ("production" !== "development" ? invariant( 1233 !DOMProperty.mustUseAttribute[propName] || 1234 !DOMProperty.mustUseProperty[propName], 1235 'DOMProperty: Cannot require using both attribute and property: %s', 1236 propName 1237 ) : invariant(!DOMProperty.mustUseAttribute[propName] || 1238 !DOMProperty.mustUseProperty[propName])); 1239 ("production" !== "development" ? invariant( 1240 DOMProperty.mustUseProperty[propName] || 1241 !DOMProperty.hasSideEffects[propName], 1242 'DOMProperty: Properties that have side effects must use property: %s', 1243 propName 1244 ) : invariant(DOMProperty.mustUseProperty[propName] || 1245 !DOMProperty.hasSideEffects[propName])); 1246 ("production" !== "development" ? invariant( 1247 !DOMProperty.hasBooleanValue[propName] || 1248 !DOMProperty.hasPositiveNumericValue[propName], 1249 'DOMProperty: Cannot have both boolean and positive numeric value: %s', 1250 propName 1251 ) : invariant(!DOMProperty.hasBooleanValue[propName] || 1252 !DOMProperty.hasPositiveNumericValue[propName])); 1253 } 1254 } 1255 }; 1256 var defaultValueCache = {}; 1257 1258 /** 1259 * DOMProperty exports lookup objects that can be used like functions: 1260 * 1261 * > DOMProperty.isValid['id'] 1262 * true 1263 * > DOMProperty.isValid['foobar'] 1264 * undefined 1265 * 1266 * Although this may be confusing, it performs better in general. 1267 * 1268 * @see http://jsperf.com/key-exists 1269 * @see http://jsperf.com/key-missing 1270 */ 1271 var DOMProperty = { 1272 1273 ID_ATTRIBUTE_NAME: 'data-reactid', 1274 1275 /** 1276 * Checks whether a property name is a standard property. 1277 * @type {Object} 1278 */ 1279 isStandardName: {}, 1280 1281 /** 1282 * Mapping from lowercase property names to the properly cased version, used 1283 * to warn in the case of missing properties. 1284 * @type {Object} 1285 */ 1286 getPossibleStandardName: {}, 1287 1288 /** 1289 * Mapping from normalized names to attribute names that differ. Attribute 1290 * names are used when rendering markup or with `*Attribute()`. 1291 * @type {Object} 1292 */ 1293 getAttributeName: {}, 1294 1295 /** 1296 * Mapping from normalized names to properties on DOM node instances. 1297 * (This includes properties that mutate due to external factors.) 1298 * @type {Object} 1299 */ 1300 getPropertyName: {}, 1301 1302 /** 1303 * Mapping from normalized names to mutation methods. This will only exist if 1304 * mutation cannot be set simply by the property or `setAttribute()`. 1305 * @type {Object} 1306 */ 1307 getMutationMethod: {}, 1308 1309 /** 1310 * Whether the property must be accessed and mutated as an object property. 1311 * @type {Object} 1312 */ 1313 mustUseAttribute: {}, 1314 1315 /** 1316 * Whether the property must be accessed and mutated using `*Attribute()`. 1317 * (This includes anything that fails `<propName> in <element>`.) 1318 * @type {Object} 1319 */ 1320 mustUseProperty: {}, 1321 1322 /** 1323 * Whether or not setting a value causes side effects such as triggering 1324 * resources to be loaded or text selection changes. We must ensure that 1325 * the value is only set if it has changed. 1326 * @type {Object} 1327 */ 1328 hasSideEffects: {}, 1329 1330 /** 1331 * Whether the property should be removed when set to a falsey value. 1332 * @type {Object} 1333 */ 1334 hasBooleanValue: {}, 1335 1336 /** 1337 * Whether the property must be positive numeric or parse as a positive 1338 * numeric and should be removed when set to a falsey value. 1339 * @type {Object} 1340 */ 1341 hasPositiveNumericValue: {}, 1342 1343 /** 1344 * All of the isCustomAttribute() functions that have been injected. 1345 */ 1346 _isCustomAttributeFunctions: [], 1347 1348 /** 1349 * Checks whether a property name is a custom attribute. 1350 * @method 1351 */ 1352 isCustomAttribute: function(attributeName) { 1353 for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) { 1354 var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i]; 1355 if (isCustomAttributeFn(attributeName)) { 1356 return true; 1357 } 1358 } 1359 return false; 1360 }, 1361 1362 /** 1363 * Returns the default property value for a DOM property (i.e., not an 1364 * attribute). Most default values are '' or false, but not all. Worse yet, 1365 * some (in particular, `type`) vary depending on the type of element. 1366 * 1367 * TODO: Is it better to grab all the possible properties when creating an 1368 * element to avoid having to create the same element twice? 1369 */ 1370 getDefaultValueForProperty: function(nodeName, prop) { 1371 var nodeDefaults = defaultValueCache[nodeName]; 1372 var testElement; 1373 if (!nodeDefaults) { 1374 defaultValueCache[nodeName] = nodeDefaults = {}; 1375 } 1376 if (!(prop in nodeDefaults)) { 1377 testElement = document.createElement(nodeName); 1378 nodeDefaults[prop] = testElement[prop]; 1379 } 1380 return nodeDefaults[prop]; 1381 }, 1382 1383 injection: DOMPropertyInjection 1384 }; 1385 1386 module.exports = DOMProperty; 1387 1388 },{"./invariant":112}],9:[function(_dereq_,module,exports){ 1389 /** 1390 * Copyright 2013-2014 Facebook, Inc. 1391 * 1392 * Licensed under the Apache License, Version 2.0 (the "License"); 1393 * you may not use this file except in compliance with the License. 1394 * You may obtain a copy of the License at 1395 * 1396 * http://www.apache.org/licenses/LICENSE-2.0 1397 * 1398 * Unless required by applicable law or agreed to in writing, software 1399 * distributed under the License is distributed on an "AS IS" BASIS, 1400 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1401 * See the License for the specific language governing permissions and 1402 * limitations under the License. 1403 * 1404 * @providesModule DOMPropertyOperations 1405 * @typechecks static-only 1406 */ 1407 1408 "use strict"; 1409 1410 var DOMProperty = _dereq_("./DOMProperty"); 1411 1412 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); 1413 var memoizeStringOnly = _dereq_("./memoizeStringOnly"); 1414 var warning = _dereq_("./warning"); 1415 1416 function shouldIgnoreValue(name, value) { 1417 return value == null || 1418 DOMProperty.hasBooleanValue[name] && !value || 1419 DOMProperty.hasPositiveNumericValue[name] && (isNaN(value) || value < 1); 1420 } 1421 1422 var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { 1423 return escapeTextForBrowser(name) + '="'; 1424 }); 1425 1426 if ("production" !== "development") { 1427 var reactProps = { 1428 children: true, 1429 dangerouslySetInnerHTML: true, 1430 key: true, 1431 ref: true 1432 }; 1433 var warnedProperties = {}; 1434 1435 var warnUnknownProperty = function(name) { 1436 if (reactProps[name] || warnedProperties[name]) { 1437 return; 1438 } 1439 1440 warnedProperties[name] = true; 1441 var lowerCasedName = name.toLowerCase(); 1442 1443 // data-* attributes should be lowercase; suggest the lowercase version 1444 var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? 1445 lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName]; 1446 1447 // For now, only warn when we have a suggested correction. This prevents 1448 // logging too much when using transferPropsTo. 1449 ("production" !== "development" ? warning( 1450 standardName == null, 1451 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' 1452 ) : null); 1453 1454 }; 1455 } 1456 1457 /** 1458 * Operations for dealing with DOM properties. 1459 */ 1460 var DOMPropertyOperations = { 1461 1462 /** 1463 * Creates markup for the ID property. 1464 * 1465 * @param {string} id Unescaped ID. 1466 * @return {string} Markup string. 1467 */ 1468 createMarkupForID: function(id) { 1469 return processAttributeNameAndPrefix(DOMProperty.ID_ATTRIBUTE_NAME) + 1470 escapeTextForBrowser(id) + '"'; 1471 }, 1472 1473 /** 1474 * Creates markup for a property. 1475 * 1476 * @param {string} name 1477 * @param {*} value 1478 * @return {?string} Markup string, or null if the property was invalid. 1479 */ 1480 createMarkupForProperty: function(name, value) { 1481 if (DOMProperty.isStandardName[name]) { 1482 if (shouldIgnoreValue(name, value)) { 1483 return ''; 1484 } 1485 var attributeName = DOMProperty.getAttributeName[name]; 1486 if (DOMProperty.hasBooleanValue[name]) { 1487 return escapeTextForBrowser(attributeName); 1488 } 1489 return processAttributeNameAndPrefix(attributeName) + 1490 escapeTextForBrowser(value) + '"'; 1491 } else if (DOMProperty.isCustomAttribute(name)) { 1492 if (value == null) { 1493 return ''; 1494 } 1495 return processAttributeNameAndPrefix(name) + 1496 escapeTextForBrowser(value) + '"'; 1497 } else if ("production" !== "development") { 1498 warnUnknownProperty(name); 1499 } 1500 return null; 1501 }, 1502 1503 /** 1504 * Sets the value for a property on a node. 1505 * 1506 * @param {DOMElement} node 1507 * @param {string} name 1508 * @param {*} value 1509 */ 1510 setValueForProperty: function(node, name, value) { 1511 if (DOMProperty.isStandardName[name]) { 1512 var mutationMethod = DOMProperty.getMutationMethod[name]; 1513 if (mutationMethod) { 1514 mutationMethod(node, value); 1515 } else if (shouldIgnoreValue(name, value)) { 1516 this.deleteValueForProperty(node, name); 1517 } else if (DOMProperty.mustUseAttribute[name]) { 1518 node.setAttribute(DOMProperty.getAttributeName[name], '' + value); 1519 } else { 1520 var propName = DOMProperty.getPropertyName[name]; 1521 if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { 1522 node[propName] = value; 1523 } 1524 } 1525 } else if (DOMProperty.isCustomAttribute(name)) { 1526 if (value == null) { 1527 node.removeAttribute(DOMProperty.getAttributeName[name]); 1528 } else { 1529 node.setAttribute(name, '' + value); 1530 } 1531 } else if ("production" !== "development") { 1532 warnUnknownProperty(name); 1533 } 1534 }, 1535 1536 /** 1537 * Deletes the value for a property on a node. 1538 * 1539 * @param {DOMElement} node 1540 * @param {string} name 1541 */ 1542 deleteValueForProperty: function(node, name) { 1543 if (DOMProperty.isStandardName[name]) { 1544 var mutationMethod = DOMProperty.getMutationMethod[name]; 1545 if (mutationMethod) { 1546 mutationMethod(node, undefined); 1547 } else if (DOMProperty.mustUseAttribute[name]) { 1548 node.removeAttribute(DOMProperty.getAttributeName[name]); 1549 } else { 1550 var propName = DOMProperty.getPropertyName[name]; 1551 var defaultValue = DOMProperty.getDefaultValueForProperty( 1552 node.nodeName, 1553 propName 1554 ); 1555 if (!DOMProperty.hasSideEffects[name] || 1556 node[propName] !== defaultValue) { 1557 node[propName] = defaultValue; 1558 } 1559 } 1560 } else if (DOMProperty.isCustomAttribute(name)) { 1561 node.removeAttribute(name); 1562 } else if ("production" !== "development") { 1563 warnUnknownProperty(name); 1564 } 1565 } 1566 1567 }; 1568 1569 module.exports = DOMPropertyOperations; 1570 1571 },{"./DOMProperty":8,"./escapeTextForBrowser":98,"./memoizeStringOnly":120,"./warning":134}],10:[function(_dereq_,module,exports){ 1572 /** 1573 * Copyright 2013-2014 Facebook, Inc. 1574 * 1575 * Licensed under the Apache License, Version 2.0 (the "License"); 1576 * you may not use this file except in compliance with the License. 1577 * You may obtain a copy of the License at 1578 * 1579 * http://www.apache.org/licenses/LICENSE-2.0 1580 * 1581 * Unless required by applicable law or agreed to in writing, software 1582 * distributed under the License is distributed on an "AS IS" BASIS, 1583 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1584 * See the License for the specific language governing permissions and 1585 * limitations under the License. 1586 * 1587 * @providesModule Danger 1588 * @typechecks static-only 1589 */ 1590 1591 /*jslint evil: true, sub: true */ 1592 1593 "use strict"; 1594 1595 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 1596 1597 var createNodesFromMarkup = _dereq_("./createNodesFromMarkup"); 1598 var emptyFunction = _dereq_("./emptyFunction"); 1599 var getMarkupWrap = _dereq_("./getMarkupWrap"); 1600 var invariant = _dereq_("./invariant"); 1601 1602 var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; 1603 var RESULT_INDEX_ATTR = 'data-danger-index'; 1604 1605 /** 1606 * Extracts the `nodeName` from a string of markup. 1607 * 1608 * NOTE: Extracting the `nodeName` does not require a regular expression match 1609 * because we make assumptions about React-generated markup (i.e. there are no 1610 * spaces surrounding the opening tag and there is at least one attribute). 1611 * 1612 * @param {string} markup String of markup. 1613 * @return {string} Node name of the supplied markup. 1614 * @see http://jsperf.com/extract-nodename 1615 */ 1616 function getNodeName(markup) { 1617 return markup.substring(1, markup.indexOf(' ')); 1618 } 1619 1620 var Danger = { 1621 1622 /** 1623 * Renders markup into an array of nodes. The markup is expected to render 1624 * into a list of root nodes. Also, the length of `resultList` and 1625 * `markupList` should be the same. 1626 * 1627 * @param {array<string>} markupList List of markup strings to render. 1628 * @return {array<DOMElement>} List of rendered nodes. 1629 * @internal 1630 */ 1631 dangerouslyRenderMarkup: function(markupList) { 1632 ("production" !== "development" ? invariant( 1633 ExecutionEnvironment.canUseDOM, 1634 'dangerouslyRenderMarkup(...): Cannot render markup in a Worker ' + 1635 'thread. This is likely a bug in the framework. Please report ' + 1636 'immediately.' 1637 ) : invariant(ExecutionEnvironment.canUseDOM)); 1638 var nodeName; 1639 var markupByNodeName = {}; 1640 // Group markup by `nodeName` if a wrap is necessary, else by '*'. 1641 for (var i = 0; i < markupList.length; i++) { 1642 ("production" !== "development" ? invariant( 1643 markupList[i], 1644 'dangerouslyRenderMarkup(...): Missing markup.' 1645 ) : invariant(markupList[i])); 1646 nodeName = getNodeName(markupList[i]); 1647 nodeName = getMarkupWrap(nodeName) ? nodeName : '*'; 1648 markupByNodeName[nodeName] = markupByNodeName[nodeName] || []; 1649 markupByNodeName[nodeName][i] = markupList[i]; 1650 } 1651 var resultList = []; 1652 var resultListAssignmentCount = 0; 1653 for (nodeName in markupByNodeName) { 1654 if (!markupByNodeName.hasOwnProperty(nodeName)) { 1655 continue; 1656 } 1657 var markupListByNodeName = markupByNodeName[nodeName]; 1658 1659 // This for-in loop skips the holes of the sparse array. The order of 1660 // iteration should follow the order of assignment, which happens to match 1661 // numerical index order, but we don't rely on that. 1662 for (var resultIndex in markupListByNodeName) { 1663 if (markupListByNodeName.hasOwnProperty(resultIndex)) { 1664 var markup = markupListByNodeName[resultIndex]; 1665 1666 // Push the requested markup with an additional RESULT_INDEX_ATTR 1667 // attribute. If the markup does not start with a < character, it 1668 // will be discarded below (with an appropriate console.error). 1669 markupListByNodeName[resultIndex] = markup.replace( 1670 OPEN_TAG_NAME_EXP, 1671 // This index will be parsed back out below. 1672 '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ' 1673 ); 1674 } 1675 } 1676 1677 // Render each group of markup with similar wrapping `nodeName`. 1678 var renderNodes = createNodesFromMarkup( 1679 markupListByNodeName.join(''), 1680 emptyFunction // Do nothing special with <script> tags. 1681 ); 1682 1683 for (i = 0; i < renderNodes.length; ++i) { 1684 var renderNode = renderNodes[i]; 1685 if (renderNode.hasAttribute && 1686 renderNode.hasAttribute(RESULT_INDEX_ATTR)) { 1687 1688 resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR); 1689 renderNode.removeAttribute(RESULT_INDEX_ATTR); 1690 1691 ("production" !== "development" ? invariant( 1692 !resultList.hasOwnProperty(resultIndex), 1693 'Danger: Assigning to an already-occupied result index.' 1694 ) : invariant(!resultList.hasOwnProperty(resultIndex))); 1695 1696 resultList[resultIndex] = renderNode; 1697 1698 // This should match resultList.length and markupList.length when 1699 // we're done. 1700 resultListAssignmentCount += 1; 1701 1702 } else if ("production" !== "development") { 1703 console.error( 1704 "Danger: Discarding unexpected node:", 1705 renderNode 1706 ); 1707 } 1708 } 1709 } 1710 1711 // Although resultList was populated out of order, it should now be a dense 1712 // array. 1713 ("production" !== "development" ? invariant( 1714 resultListAssignmentCount === resultList.length, 1715 'Danger: Did not assign to every index of resultList.' 1716 ) : invariant(resultListAssignmentCount === resultList.length)); 1717 1718 ("production" !== "development" ? invariant( 1719 resultList.length === markupList.length, 1720 'Danger: Expected markup to render %s nodes, but rendered %s.', 1721 markupList.length, 1722 resultList.length 1723 ) : invariant(resultList.length === markupList.length)); 1724 1725 return resultList; 1726 }, 1727 1728 /** 1729 * Replaces a node with a string of markup at its current position within its 1730 * parent. The markup must render into a single root node. 1731 * 1732 * @param {DOMElement} oldChild Child node to replace. 1733 * @param {string} markup Markup to render in place of the child node. 1734 * @internal 1735 */ 1736 dangerouslyReplaceNodeWithMarkup: function(oldChild, markup) { 1737 ("production" !== "development" ? invariant( 1738 ExecutionEnvironment.canUseDOM, 1739 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + 1740 'worker thread. This is likely a bug in the framework. Please report ' + 1741 'immediately.' 1742 ) : invariant(ExecutionEnvironment.canUseDOM)); 1743 ("production" !== "development" ? invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(markup)); 1744 ("production" !== "development" ? invariant( 1745 oldChild.tagName.toLowerCase() !== 'html', 1746 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + 1747 '<html> node. This is because browser quirks make this unreliable ' + 1748 'and/or slow. If you want to render to the root you must use ' + 1749 'server rendering. See renderComponentToString().' 1750 ) : invariant(oldChild.tagName.toLowerCase() !== 'html')); 1751 1752 var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; 1753 oldChild.parentNode.replaceChild(newChild, oldChild); 1754 } 1755 1756 }; 1757 1758 module.exports = Danger; 1759 1760 },{"./ExecutionEnvironment":20,"./createNodesFromMarkup":93,"./emptyFunction":96,"./getMarkupWrap":105,"./invariant":112}],11:[function(_dereq_,module,exports){ 1761 /** 1762 * Copyright 2013-2014 Facebook, Inc. 1763 * 1764 * Licensed under the Apache License, Version 2.0 (the "License"); 1765 * you may not use this file except in compliance with the License. 1766 * You may obtain a copy of the License at 1767 * 1768 * http://www.apache.org/licenses/LICENSE-2.0 1769 * 1770 * Unless required by applicable law or agreed to in writing, software 1771 * distributed under the License is distributed on an "AS IS" BASIS, 1772 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1773 * See the License for the specific language governing permissions and 1774 * limitations under the License. 1775 * 1776 * @providesModule DefaultDOMPropertyConfig 1777 */ 1778 1779 /*jslint bitwise: true*/ 1780 1781 "use strict"; 1782 1783 var DOMProperty = _dereq_("./DOMProperty"); 1784 1785 var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE; 1786 var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY; 1787 var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE; 1788 var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS; 1789 var HAS_POSITIVE_NUMERIC_VALUE = 1790 DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE; 1791 1792 var DefaultDOMPropertyConfig = { 1793 isCustomAttribute: RegExp.prototype.test.bind( 1794 /^(data|aria)-[a-z_][a-z\d_.\-]*$/ 1795 ), 1796 Properties: { 1797 /** 1798 * Standard Properties 1799 */ 1800 accept: null, 1801 accessKey: null, 1802 action: null, 1803 allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1804 allowTransparency: MUST_USE_ATTRIBUTE, 1805 alt: null, 1806 async: HAS_BOOLEAN_VALUE, 1807 autoComplete: null, 1808 // autoFocus is polyfilled/normalized by AutoFocusMixin 1809 // autoFocus: HAS_BOOLEAN_VALUE, 1810 autoPlay: HAS_BOOLEAN_VALUE, 1811 cellPadding: null, 1812 cellSpacing: null, 1813 charSet: MUST_USE_ATTRIBUTE, 1814 checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1815 className: MUST_USE_PROPERTY, 1816 cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1817 colSpan: null, 1818 content: null, 1819 contentEditable: null, 1820 contextMenu: MUST_USE_ATTRIBUTE, 1821 controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1822 crossOrigin: null, 1823 data: null, // For `<object />` acts as `src`. 1824 dateTime: MUST_USE_ATTRIBUTE, 1825 defer: HAS_BOOLEAN_VALUE, 1826 dir: null, 1827 disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1828 download: null, 1829 draggable: null, 1830 encType: null, 1831 form: MUST_USE_ATTRIBUTE, 1832 formNoValidate: HAS_BOOLEAN_VALUE, 1833 frameBorder: MUST_USE_ATTRIBUTE, 1834 height: MUST_USE_ATTRIBUTE, 1835 hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1836 href: null, 1837 hrefLang: null, 1838 htmlFor: null, 1839 httpEquiv: null, 1840 icon: null, 1841 id: MUST_USE_PROPERTY, 1842 label: null, 1843 lang: null, 1844 list: null, 1845 loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1846 max: null, 1847 maxLength: MUST_USE_ATTRIBUTE, 1848 mediaGroup: null, 1849 method: null, 1850 min: null, 1851 multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1852 muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1853 name: null, 1854 noValidate: HAS_BOOLEAN_VALUE, 1855 pattern: null, 1856 placeholder: null, 1857 poster: null, 1858 preload: null, 1859 radioGroup: null, 1860 readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1861 rel: null, 1862 required: HAS_BOOLEAN_VALUE, 1863 role: MUST_USE_ATTRIBUTE, 1864 rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1865 rowSpan: null, 1866 sandbox: null, 1867 scope: null, 1868 scrollLeft: MUST_USE_PROPERTY, 1869 scrollTop: MUST_USE_PROPERTY, 1870 seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1871 selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1872 size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1873 span: HAS_POSITIVE_NUMERIC_VALUE, 1874 spellCheck: null, 1875 src: null, 1876 srcDoc: MUST_USE_PROPERTY, 1877 srcSet: null, 1878 step: null, 1879 style: null, 1880 tabIndex: null, 1881 target: null, 1882 title: null, 1883 type: null, 1884 value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS, 1885 width: MUST_USE_ATTRIBUTE, 1886 wmode: MUST_USE_ATTRIBUTE, 1887 1888 /** 1889 * Non-standard Properties 1890 */ 1891 autoCapitalize: null, // Supported in Mobile Safari for keyboard hints 1892 autoCorrect: null, // Supported in Mobile Safari for keyboard hints 1893 property: null, // Supports OG in meta tags 1894 1895 /** 1896 * SVG Properties 1897 */ 1898 cx: MUST_USE_ATTRIBUTE, 1899 cy: MUST_USE_ATTRIBUTE, 1900 d: MUST_USE_ATTRIBUTE, 1901 fill: MUST_USE_ATTRIBUTE, 1902 fx: MUST_USE_ATTRIBUTE, 1903 fy: MUST_USE_ATTRIBUTE, 1904 gradientTransform: MUST_USE_ATTRIBUTE, 1905 gradientUnits: MUST_USE_ATTRIBUTE, 1906 offset: MUST_USE_ATTRIBUTE, 1907 points: MUST_USE_ATTRIBUTE, 1908 r: MUST_USE_ATTRIBUTE, 1909 rx: MUST_USE_ATTRIBUTE, 1910 ry: MUST_USE_ATTRIBUTE, 1911 spreadMethod: MUST_USE_ATTRIBUTE, 1912 stopColor: MUST_USE_ATTRIBUTE, 1913 stopOpacity: MUST_USE_ATTRIBUTE, 1914 stroke: MUST_USE_ATTRIBUTE, 1915 strokeLinecap: MUST_USE_ATTRIBUTE, 1916 strokeWidth: MUST_USE_ATTRIBUTE, 1917 textAnchor: MUST_USE_ATTRIBUTE, 1918 transform: MUST_USE_ATTRIBUTE, 1919 version: MUST_USE_ATTRIBUTE, 1920 viewBox: MUST_USE_ATTRIBUTE, 1921 x1: MUST_USE_ATTRIBUTE, 1922 x2: MUST_USE_ATTRIBUTE, 1923 x: MUST_USE_ATTRIBUTE, 1924 y1: MUST_USE_ATTRIBUTE, 1925 y2: MUST_USE_ATTRIBUTE, 1926 y: MUST_USE_ATTRIBUTE 1927 }, 1928 DOMAttributeNames: { 1929 className: 'class', 1930 gradientTransform: 'gradientTransform', 1931 gradientUnits: 'gradientUnits', 1932 htmlFor: 'for', 1933 spreadMethod: 'spreadMethod', 1934 stopColor: 'stop-color', 1935 stopOpacity: 'stop-opacity', 1936 strokeLinecap: 'stroke-linecap', 1937 strokeWidth: 'stroke-width', 1938 textAnchor: 'text-anchor', 1939 viewBox: 'viewBox' 1940 }, 1941 DOMPropertyNames: { 1942 autoCapitalize: 'autocapitalize', 1943 autoComplete: 'autocomplete', 1944 autoCorrect: 'autocorrect', 1945 autoFocus: 'autofocus', 1946 autoPlay: 'autoplay', 1947 encType: 'enctype', 1948 hrefLang: 'hreflang', 1949 radioGroup: 'radiogroup', 1950 spellCheck: 'spellcheck', 1951 srcDoc: 'srcdoc', 1952 srcSet: 'srcset' 1953 } 1954 }; 1955 1956 module.exports = DefaultDOMPropertyConfig; 1957 1958 },{"./DOMProperty":8}],12:[function(_dereq_,module,exports){ 1959 /** 1960 * Copyright 2013-2014 Facebook, Inc. 1961 * 1962 * Licensed under the Apache License, Version 2.0 (the "License"); 1963 * you may not use this file except in compliance with the License. 1964 * You may obtain a copy of the License at 1965 * 1966 * http://www.apache.org/licenses/LICENSE-2.0 1967 * 1968 * Unless required by applicable law or agreed to in writing, software 1969 * distributed under the License is distributed on an "AS IS" BASIS, 1970 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1971 * See the License for the specific language governing permissions and 1972 * limitations under the License. 1973 * 1974 * @providesModule DefaultEventPluginOrder 1975 */ 1976 1977 "use strict"; 1978 1979 var keyOf = _dereq_("./keyOf"); 1980 1981 /** 1982 * Module that is injectable into `EventPluginHub`, that specifies a 1983 * deterministic ordering of `EventPlugin`s. A convenient way to reason about 1984 * plugins, without having to package every one of them. This is better than 1985 * having plugins be ordered in the same order that they are injected because 1986 * that ordering would be influenced by the packaging order. 1987 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that 1988 * preventing default on events is convenient in `SimpleEventPlugin` handlers. 1989 */ 1990 var DefaultEventPluginOrder = [ 1991 keyOf({ResponderEventPlugin: null}), 1992 keyOf({SimpleEventPlugin: null}), 1993 keyOf({TapEventPlugin: null}), 1994 keyOf({EnterLeaveEventPlugin: null}), 1995 keyOf({ChangeEventPlugin: null}), 1996 keyOf({SelectEventPlugin: null}), 1997 keyOf({CompositionEventPlugin: null}), 1998 keyOf({AnalyticsEventPlugin: null}), 1999 keyOf({MobileSafariClickEventPlugin: null}) 2000 ]; 2001 2002 module.exports = DefaultEventPluginOrder; 2003 2004 },{"./keyOf":119}],13:[function(_dereq_,module,exports){ 2005 /** 2006 * Copyright 2013-2014 Facebook, Inc. 2007 * 2008 * Licensed under the Apache License, Version 2.0 (the "License"); 2009 * you may not use this file except in compliance with the License. 2010 * You may obtain a copy of the License at 2011 * 2012 * http://www.apache.org/licenses/LICENSE-2.0 2013 * 2014 * Unless required by applicable law or agreed to in writing, software 2015 * distributed under the License is distributed on an "AS IS" BASIS, 2016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2017 * See the License for the specific language governing permissions and 2018 * limitations under the License. 2019 * 2020 * @providesModule EnterLeaveEventPlugin 2021 * @typechecks static-only 2022 */ 2023 2024 "use strict"; 2025 2026 var EventConstants = _dereq_("./EventConstants"); 2027 var EventPropagators = _dereq_("./EventPropagators"); 2028 var SyntheticMouseEvent = _dereq_("./SyntheticMouseEvent"); 2029 2030 var ReactMount = _dereq_("./ReactMount"); 2031 var keyOf = _dereq_("./keyOf"); 2032 2033 var topLevelTypes = EventConstants.topLevelTypes; 2034 var getFirstReactDOM = ReactMount.getFirstReactDOM; 2035 2036 var eventTypes = { 2037 mouseEnter: { 2038 registrationName: keyOf({onMouseEnter: null}), 2039 dependencies: [ 2040 topLevelTypes.topMouseOut, 2041 topLevelTypes.topMouseOver 2042 ] 2043 }, 2044 mouseLeave: { 2045 registrationName: keyOf({onMouseLeave: null}), 2046 dependencies: [ 2047 topLevelTypes.topMouseOut, 2048 topLevelTypes.topMouseOver 2049 ] 2050 } 2051 }; 2052 2053 var extractedEvents = [null, null]; 2054 2055 var EnterLeaveEventPlugin = { 2056 2057 eventTypes: eventTypes, 2058 2059 /** 2060 * For almost every interaction we care about, there will be both a top-level 2061 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 2062 * we do not extract duplicate events. However, moving the mouse into the 2063 * browser from outside will not fire a `mouseout` event. In this case, we use 2064 * the `mouseover` top-level event. 2065 * 2066 * @param {string} topLevelType Record from `EventConstants`. 2067 * @param {DOMEventTarget} topLevelTarget The listening component root node. 2068 * @param {string} topLevelTargetID ID of `topLevelTarget`. 2069 * @param {object} nativeEvent Native browser event. 2070 * @return {*} An accumulation of synthetic events. 2071 * @see {EventPluginHub.extractEvents} 2072 */ 2073 extractEvents: function( 2074 topLevelType, 2075 topLevelTarget, 2076 topLevelTargetID, 2077 nativeEvent) { 2078 if (topLevelType === topLevelTypes.topMouseOver && 2079 (nativeEvent.relatedTarget || nativeEvent.fromElement)) { 2080 return null; 2081 } 2082 if (topLevelType !== topLevelTypes.topMouseOut && 2083 topLevelType !== topLevelTypes.topMouseOver) { 2084 // Must not be a mouse in or mouse out - ignoring. 2085 return null; 2086 } 2087 2088 var win; 2089 if (topLevelTarget.window === topLevelTarget) { 2090 // `topLevelTarget` is probably a window object. 2091 win = topLevelTarget; 2092 } else { 2093 // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. 2094 var doc = topLevelTarget.ownerDocument; 2095 if (doc) { 2096 win = doc.defaultView || doc.parentWindow; 2097 } else { 2098 win = window; 2099 } 2100 } 2101 2102 var from, to; 2103 if (topLevelType === topLevelTypes.topMouseOut) { 2104 from = topLevelTarget; 2105 to = 2106 getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) || 2107 win; 2108 } else { 2109 from = win; 2110 to = topLevelTarget; 2111 } 2112 2113 if (from === to) { 2114 // Nothing pertains to our managed components. 2115 return null; 2116 } 2117 2118 var fromID = from ? ReactMount.getID(from) : ''; 2119 var toID = to ? ReactMount.getID(to) : ''; 2120 2121 var leave = SyntheticMouseEvent.getPooled( 2122 eventTypes.mouseLeave, 2123 fromID, 2124 nativeEvent 2125 ); 2126 leave.type = 'mouseleave'; 2127 leave.target = from; 2128 leave.relatedTarget = to; 2129 2130 var enter = SyntheticMouseEvent.getPooled( 2131 eventTypes.mouseEnter, 2132 toID, 2133 nativeEvent 2134 ); 2135 enter.type = 'mouseenter'; 2136 enter.target = to; 2137 enter.relatedTarget = from; 2138 2139 EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID); 2140 2141 extractedEvents[0] = leave; 2142 extractedEvents[1] = enter; 2143 2144 return extractedEvents; 2145 } 2146 2147 }; 2148 2149 module.exports = EnterLeaveEventPlugin; 2150 2151 },{"./EventConstants":14,"./EventPropagators":19,"./ReactMount":55,"./SyntheticMouseEvent":81,"./keyOf":119}],14:[function(_dereq_,module,exports){ 2152 /** 2153 * Copyright 2013-2014 Facebook, Inc. 2154 * 2155 * Licensed under the Apache License, Version 2.0 (the "License"); 2156 * you may not use this file except in compliance with the License. 2157 * You may obtain a copy of the License at 2158 * 2159 * http://www.apache.org/licenses/LICENSE-2.0 2160 * 2161 * Unless required by applicable law or agreed to in writing, software 2162 * distributed under the License is distributed on an "AS IS" BASIS, 2163 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2164 * See the License for the specific language governing permissions and 2165 * limitations under the License. 2166 * 2167 * @providesModule EventConstants 2168 */ 2169 2170 "use strict"; 2171 2172 var keyMirror = _dereq_("./keyMirror"); 2173 2174 var PropagationPhases = keyMirror({bubbled: null, captured: null}); 2175 2176 /** 2177 * Types of raw signals from the browser caught at the top level. 2178 */ 2179 var topLevelTypes = keyMirror({ 2180 topBlur: null, 2181 topChange: null, 2182 topClick: null, 2183 topCompositionEnd: null, 2184 topCompositionStart: null, 2185 topCompositionUpdate: null, 2186 topContextMenu: null, 2187 topCopy: null, 2188 topCut: null, 2189 topDoubleClick: null, 2190 topDrag: null, 2191 topDragEnd: null, 2192 topDragEnter: null, 2193 topDragExit: null, 2194 topDragLeave: null, 2195 topDragOver: null, 2196 topDragStart: null, 2197 topDrop: null, 2198 topError: null, 2199 topFocus: null, 2200 topInput: null, 2201 topKeyDown: null, 2202 topKeyPress: null, 2203 topKeyUp: null, 2204 topLoad: null, 2205 topMouseDown: null, 2206 topMouseMove: null, 2207 topMouseOut: null, 2208 topMouseOver: null, 2209 topMouseUp: null, 2210 topPaste: null, 2211 topReset: null, 2212 topScroll: null, 2213 topSelectionChange: null, 2214 topSubmit: null, 2215 topTouchCancel: null, 2216 topTouchEnd: null, 2217 topTouchMove: null, 2218 topTouchStart: null, 2219 topWheel: null 2220 }); 2221 2222 var EventConstants = { 2223 topLevelTypes: topLevelTypes, 2224 PropagationPhases: PropagationPhases 2225 }; 2226 2227 module.exports = EventConstants; 2228 2229 },{"./keyMirror":118}],15:[function(_dereq_,module,exports){ 2230 /** 2231 * @providesModule EventListener 2232 */ 2233 2234 var emptyFunction = _dereq_("./emptyFunction"); 2235 2236 /** 2237 * Upstream version of event listener. Does not take into account specific 2238 * nature of platform. 2239 */ 2240 var EventListener = { 2241 /** 2242 * Listen to DOM events during the bubble phase. 2243 * 2244 * @param {DOMEventTarget} target DOM element to register listener on. 2245 * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. 2246 * @param {function} callback Callback function. 2247 * @return {object} Object with a `remove` method. 2248 */ 2249 listen: function(target, eventType, callback) { 2250 if (target.addEventListener) { 2251 target.addEventListener(eventType, callback, false); 2252 return { 2253 remove: function() { 2254 target.removeEventListener(eventType, callback, false); 2255 } 2256 }; 2257 } else if (target.attachEvent) { 2258 target.attachEvent('on' + eventType, callback); 2259 return { 2260 remove: function() { 2261 target.detachEvent(eventType, callback); 2262 } 2263 }; 2264 } 2265 }, 2266 2267 /** 2268 * Listen to DOM events during the capture phase. 2269 * 2270 * @param {DOMEventTarget} target DOM element to register listener on. 2271 * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. 2272 * @param {function} callback Callback function. 2273 * @return {object} Object with a `remove` method. 2274 */ 2275 capture: function(target, eventType, callback) { 2276 if (!target.addEventListener) { 2277 if ("production" !== "development") { 2278 console.error( 2279 'Attempted to listen to events during the capture phase on a ' + 2280 'browser that does not support the capture phase. Your application ' + 2281 'will not receive some events.' 2282 ); 2283 } 2284 return { 2285 remove: emptyFunction 2286 }; 2287 } else { 2288 target.addEventListener(eventType, callback, true); 2289 return { 2290 remove: function() { 2291 target.removeEventListener(eventType, callback, true); 2292 } 2293 }; 2294 } 2295 } 2296 }; 2297 2298 module.exports = EventListener; 2299 2300 },{"./emptyFunction":96}],16:[function(_dereq_,module,exports){ 2301 /** 2302 * Copyright 2013-2014 Facebook, Inc. 2303 * 2304 * Licensed under the Apache License, Version 2.0 (the "License"); 2305 * you may not use this file except in compliance with the License. 2306 * You may obtain a copy of the License at 2307 * 2308 * http://www.apache.org/licenses/LICENSE-2.0 2309 * 2310 * Unless required by applicable law or agreed to in writing, software 2311 * distributed under the License is distributed on an "AS IS" BASIS, 2312 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2313 * See the License for the specific language governing permissions and 2314 * limitations under the License. 2315 * 2316 * @providesModule EventPluginHub 2317 */ 2318 2319 "use strict"; 2320 2321 var EventPluginRegistry = _dereq_("./EventPluginRegistry"); 2322 var EventPluginUtils = _dereq_("./EventPluginUtils"); 2323 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 2324 2325 var accumulate = _dereq_("./accumulate"); 2326 var forEachAccumulated = _dereq_("./forEachAccumulated"); 2327 var invariant = _dereq_("./invariant"); 2328 var isEventSupported = _dereq_("./isEventSupported"); 2329 var monitorCodeUse = _dereq_("./monitorCodeUse"); 2330 2331 /** 2332 * Internal store for event listeners 2333 */ 2334 var listenerBank = {}; 2335 2336 /** 2337 * Internal queue of events that have accumulated their dispatches and are 2338 * waiting to have their dispatches executed. 2339 */ 2340 var eventQueue = null; 2341 2342 /** 2343 * Dispatches an event and releases it back into the pool, unless persistent. 2344 * 2345 * @param {?object} event Synthetic event to be dispatched. 2346 * @private 2347 */ 2348 var executeDispatchesAndRelease = function(event) { 2349 if (event) { 2350 var executeDispatch = EventPluginUtils.executeDispatch; 2351 // Plugins can provide custom behavior when dispatching events. 2352 var PluginModule = EventPluginRegistry.getPluginModuleForEvent(event); 2353 if (PluginModule && PluginModule.executeDispatch) { 2354 executeDispatch = PluginModule.executeDispatch; 2355 } 2356 EventPluginUtils.executeDispatchesInOrder(event, executeDispatch); 2357 2358 if (!event.isPersistent()) { 2359 event.constructor.release(event); 2360 } 2361 } 2362 }; 2363 2364 /** 2365 * - `InstanceHandle`: [required] Module that performs logical traversals of DOM 2366 * hierarchy given ids of the logical DOM elements involved. 2367 */ 2368 var InstanceHandle = null; 2369 2370 function validateInstanceHandle() { 2371 var invalid = !InstanceHandle|| 2372 !InstanceHandle.traverseTwoPhase || 2373 !InstanceHandle.traverseEnterLeave; 2374 if (invalid) { 2375 throw new Error('InstanceHandle not injected before use!'); 2376 } 2377 } 2378 2379 /** 2380 * This is a unified interface for event plugins to be installed and configured. 2381 * 2382 * Event plugins can implement the following properties: 2383 * 2384 * `extractEvents` {function(string, DOMEventTarget, string, object): *} 2385 * Required. When a top-level event is fired, this method is expected to 2386 * extract synthetic events that will in turn be queued and dispatched. 2387 * 2388 * `eventTypes` {object} 2389 * Optional, plugins that fire events must publish a mapping of registration 2390 * names that are used to register listeners. Values of this mapping must 2391 * be objects that contain `registrationName` or `phasedRegistrationNames`. 2392 * 2393 * `executeDispatch` {function(object, function, string)} 2394 * Optional, allows plugins to override how an event gets dispatched. By 2395 * default, the listener is simply invoked. 2396 * 2397 * Each plugin that is injected into `EventsPluginHub` is immediately operable. 2398 * 2399 * @public 2400 */ 2401 var EventPluginHub = { 2402 2403 /** 2404 * Methods for injecting dependencies. 2405 */ 2406 injection: { 2407 2408 /** 2409 * @param {object} InjectedMount 2410 * @public 2411 */ 2412 injectMount: EventPluginUtils.injection.injectMount, 2413 2414 /** 2415 * @param {object} InjectedInstanceHandle 2416 * @public 2417 */ 2418 injectInstanceHandle: function(InjectedInstanceHandle) { 2419 InstanceHandle = InjectedInstanceHandle; 2420 if ("production" !== "development") { 2421 validateInstanceHandle(); 2422 } 2423 }, 2424 2425 getInstanceHandle: function() { 2426 if ("production" !== "development") { 2427 validateInstanceHandle(); 2428 } 2429 return InstanceHandle; 2430 }, 2431 2432 /** 2433 * @param {array} InjectedEventPluginOrder 2434 * @public 2435 */ 2436 injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder, 2437 2438 /** 2439 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 2440 */ 2441 injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName 2442 2443 }, 2444 2445 eventNameDispatchConfigs: EventPluginRegistry.eventNameDispatchConfigs, 2446 2447 registrationNameModules: EventPluginRegistry.registrationNameModules, 2448 2449 /** 2450 * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. 2451 * 2452 * @param {string} id ID of the DOM element. 2453 * @param {string} registrationName Name of listener (e.g. `onClick`). 2454 * @param {?function} listener The callback to store. 2455 */ 2456 putListener: function(id, registrationName, listener) { 2457 ("production" !== "development" ? invariant( 2458 ExecutionEnvironment.canUseDOM, 2459 'Cannot call putListener() in a non-DOM environment.' 2460 ) : invariant(ExecutionEnvironment.canUseDOM)); 2461 ("production" !== "development" ? invariant( 2462 !listener || typeof listener === 'function', 2463 'Expected %s listener to be a function, instead got type %s', 2464 registrationName, typeof listener 2465 ) : invariant(!listener || typeof listener === 'function')); 2466 2467 if ("production" !== "development") { 2468 // IE8 has no API for event capturing and the `onScroll` event doesn't 2469 // bubble. 2470 if (registrationName === 'onScroll' && 2471 !isEventSupported('scroll', true)) { 2472 monitorCodeUse('react_no_scroll_event'); 2473 console.warn('This browser doesn\'t support the `onScroll` event'); 2474 } 2475 } 2476 var bankForRegistrationName = 2477 listenerBank[registrationName] || (listenerBank[registrationName] = {}); 2478 bankForRegistrationName[id] = listener; 2479 }, 2480 2481 /** 2482 * @param {string} id ID of the DOM element. 2483 * @param {string} registrationName Name of listener (e.g. `onClick`). 2484 * @return {?function} The stored callback. 2485 */ 2486 getListener: function(id, registrationName) { 2487 var bankForRegistrationName = listenerBank[registrationName]; 2488 return bankForRegistrationName && bankForRegistrationName[id]; 2489 }, 2490 2491 /** 2492 * Deletes a listener from the registration bank. 2493 * 2494 * @param {string} id ID of the DOM element. 2495 * @param {string} registrationName Name of listener (e.g. `onClick`). 2496 */ 2497 deleteListener: function(id, registrationName) { 2498 var bankForRegistrationName = listenerBank[registrationName]; 2499 if (bankForRegistrationName) { 2500 delete bankForRegistrationName[id]; 2501 } 2502 }, 2503 2504 /** 2505 * Deletes all listeners for the DOM element with the supplied ID. 2506 * 2507 * @param {string} id ID of the DOM element. 2508 */ 2509 deleteAllListeners: function(id) { 2510 for (var registrationName in listenerBank) { 2511 delete listenerBank[registrationName][id]; 2512 } 2513 }, 2514 2515 /** 2516 * Allows registered plugins an opportunity to extract events from top-level 2517 * native browser events. 2518 * 2519 * @param {string} topLevelType Record from `EventConstants`. 2520 * @param {DOMEventTarget} topLevelTarget The listening component root node. 2521 * @param {string} topLevelTargetID ID of `topLevelTarget`. 2522 * @param {object} nativeEvent Native browser event. 2523 * @return {*} An accumulation of synthetic events. 2524 * @internal 2525 */ 2526 extractEvents: function( 2527 topLevelType, 2528 topLevelTarget, 2529 topLevelTargetID, 2530 nativeEvent) { 2531 var events; 2532 var plugins = EventPluginRegistry.plugins; 2533 for (var i = 0, l = plugins.length; i < l; i++) { 2534 // Not every plugin in the ordering may be loaded at runtime. 2535 var possiblePlugin = plugins[i]; 2536 if (possiblePlugin) { 2537 var extractedEvents = possiblePlugin.extractEvents( 2538 topLevelType, 2539 topLevelTarget, 2540 topLevelTargetID, 2541 nativeEvent 2542 ); 2543 if (extractedEvents) { 2544 events = accumulate(events, extractedEvents); 2545 } 2546 } 2547 } 2548 return events; 2549 }, 2550 2551 /** 2552 * Enqueues a synthetic event that should be dispatched when 2553 * `processEventQueue` is invoked. 2554 * 2555 * @param {*} events An accumulation of synthetic events. 2556 * @internal 2557 */ 2558 enqueueEvents: function(events) { 2559 if (events) { 2560 eventQueue = accumulate(eventQueue, events); 2561 } 2562 }, 2563 2564 /** 2565 * Dispatches all synthetic events on the event queue. 2566 * 2567 * @internal 2568 */ 2569 processEventQueue: function() { 2570 // Set `eventQueue` to null before processing it so that we can tell if more 2571 // events get enqueued while processing. 2572 var processingEventQueue = eventQueue; 2573 eventQueue = null; 2574 forEachAccumulated(processingEventQueue, executeDispatchesAndRelease); 2575 ("production" !== "development" ? invariant( 2576 !eventQueue, 2577 'processEventQueue(): Additional events were enqueued while processing ' + 2578 'an event queue. Support for this has not yet been implemented.' 2579 ) : invariant(!eventQueue)); 2580 }, 2581 2582 /** 2583 * These are needed for tests only. Do not use! 2584 */ 2585 __purge: function() { 2586 listenerBank = {}; 2587 }, 2588 2589 __getListenerBank: function() { 2590 return listenerBank; 2591 } 2592 2593 }; 2594 2595 module.exports = EventPluginHub; 2596 2597 },{"./EventPluginRegistry":17,"./EventPluginUtils":18,"./ExecutionEnvironment":20,"./accumulate":87,"./forEachAccumulated":101,"./invariant":112,"./isEventSupported":113,"./monitorCodeUse":125}],17:[function(_dereq_,module,exports){ 2598 /** 2599 * Copyright 2013-2014 Facebook, Inc. 2600 * 2601 * Licensed under the Apache License, Version 2.0 (the "License"); 2602 * you may not use this file except in compliance with the License. 2603 * You may obtain a copy of the License at 2604 * 2605 * http://www.apache.org/licenses/LICENSE-2.0 2606 * 2607 * Unless required by applicable law or agreed to in writing, software 2608 * distributed under the License is distributed on an "AS IS" BASIS, 2609 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2610 * See the License for the specific language governing permissions and 2611 * limitations under the License. 2612 * 2613 * @providesModule EventPluginRegistry 2614 * @typechecks static-only 2615 */ 2616 2617 "use strict"; 2618 2619 var invariant = _dereq_("./invariant"); 2620 2621 /** 2622 * Injectable ordering of event plugins. 2623 */ 2624 var EventPluginOrder = null; 2625 2626 /** 2627 * Injectable mapping from names to event plugin modules. 2628 */ 2629 var namesToPlugins = {}; 2630 2631 /** 2632 * Recomputes the plugin list using the injected plugins and plugin ordering. 2633 * 2634 * @private 2635 */ 2636 function recomputePluginOrdering() { 2637 if (!EventPluginOrder) { 2638 // Wait until an `EventPluginOrder` is injected. 2639 return; 2640 } 2641 for (var pluginName in namesToPlugins) { 2642 var PluginModule = namesToPlugins[pluginName]; 2643 var pluginIndex = EventPluginOrder.indexOf(pluginName); 2644 ("production" !== "development" ? invariant( 2645 pluginIndex > -1, 2646 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 2647 'the plugin ordering, `%s`.', 2648 pluginName 2649 ) : invariant(pluginIndex > -1)); 2650 if (EventPluginRegistry.plugins[pluginIndex]) { 2651 continue; 2652 } 2653 ("production" !== "development" ? invariant( 2654 PluginModule.extractEvents, 2655 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 2656 'method, but `%s` does not.', 2657 pluginName 2658 ) : invariant(PluginModule.extractEvents)); 2659 EventPluginRegistry.plugins[pluginIndex] = PluginModule; 2660 var publishedEvents = PluginModule.eventTypes; 2661 for (var eventName in publishedEvents) { 2662 ("production" !== "development" ? invariant( 2663 publishEventForPlugin( 2664 publishedEvents[eventName], 2665 PluginModule, 2666 eventName 2667 ), 2668 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', 2669 eventName, 2670 pluginName 2671 ) : invariant(publishEventForPlugin( 2672 publishedEvents[eventName], 2673 PluginModule, 2674 eventName 2675 ))); 2676 } 2677 } 2678 } 2679 2680 /** 2681 * Publishes an event so that it can be dispatched by the supplied plugin. 2682 * 2683 * @param {object} dispatchConfig Dispatch configuration for the event. 2684 * @param {object} PluginModule Plugin publishing the event. 2685 * @return {boolean} True if the event was successfully published. 2686 * @private 2687 */ 2688 function publishEventForPlugin(dispatchConfig, PluginModule, eventName) { 2689 ("production" !== "development" ? invariant( 2690 !EventPluginRegistry.eventNameDispatchConfigs[eventName], 2691 'EventPluginHub: More than one plugin attempted to publish the same ' + 2692 'event name, `%s`.', 2693 eventName 2694 ) : invariant(!EventPluginRegistry.eventNameDispatchConfigs[eventName])); 2695 EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig; 2696 2697 var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; 2698 if (phasedRegistrationNames) { 2699 for (var phaseName in phasedRegistrationNames) { 2700 if (phasedRegistrationNames.hasOwnProperty(phaseName)) { 2701 var phasedRegistrationName = phasedRegistrationNames[phaseName]; 2702 publishRegistrationName( 2703 phasedRegistrationName, 2704 PluginModule, 2705 eventName 2706 ); 2707 } 2708 } 2709 return true; 2710 } else if (dispatchConfig.registrationName) { 2711 publishRegistrationName( 2712 dispatchConfig.registrationName, 2713 PluginModule, 2714 eventName 2715 ); 2716 return true; 2717 } 2718 return false; 2719 } 2720 2721 /** 2722 * Publishes a registration name that is used to identify dispatched events and 2723 * can be used with `EventPluginHub.putListener` to register listeners. 2724 * 2725 * @param {string} registrationName Registration name to add. 2726 * @param {object} PluginModule Plugin publishing the event. 2727 * @private 2728 */ 2729 function publishRegistrationName(registrationName, PluginModule, eventName) { 2730 ("production" !== "development" ? invariant( 2731 !EventPluginRegistry.registrationNameModules[registrationName], 2732 'EventPluginHub: More than one plugin attempted to publish the same ' + 2733 'registration name, `%s`.', 2734 registrationName 2735 ) : invariant(!EventPluginRegistry.registrationNameModules[registrationName])); 2736 EventPluginRegistry.registrationNameModules[registrationName] = PluginModule; 2737 EventPluginRegistry.registrationNameDependencies[registrationName] = 2738 PluginModule.eventTypes[eventName].dependencies; 2739 } 2740 2741 /** 2742 * Registers plugins so that they can extract and dispatch events. 2743 * 2744 * @see {EventPluginHub} 2745 */ 2746 var EventPluginRegistry = { 2747 2748 /** 2749 * Ordered list of injected plugins. 2750 */ 2751 plugins: [], 2752 2753 /** 2754 * Mapping from event name to dispatch config 2755 */ 2756 eventNameDispatchConfigs: {}, 2757 2758 /** 2759 * Mapping from registration name to plugin module 2760 */ 2761 registrationNameModules: {}, 2762 2763 /** 2764 * Mapping from registration name to event name 2765 */ 2766 registrationNameDependencies: {}, 2767 2768 /** 2769 * Injects an ordering of plugins (by plugin name). This allows the ordering 2770 * to be decoupled from injection of the actual plugins so that ordering is 2771 * always deterministic regardless of packaging, on-the-fly injection, etc. 2772 * 2773 * @param {array} InjectedEventPluginOrder 2774 * @internal 2775 * @see {EventPluginHub.injection.injectEventPluginOrder} 2776 */ 2777 injectEventPluginOrder: function(InjectedEventPluginOrder) { 2778 ("production" !== "development" ? invariant( 2779 !EventPluginOrder, 2780 'EventPluginRegistry: Cannot inject event plugin ordering more than once.' 2781 ) : invariant(!EventPluginOrder)); 2782 // Clone the ordering so it cannot be dynamically mutated. 2783 EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder); 2784 recomputePluginOrdering(); 2785 }, 2786 2787 /** 2788 * Injects plugins to be used by `EventPluginHub`. The plugin names must be 2789 * in the ordering injected by `injectEventPluginOrder`. 2790 * 2791 * Plugins can be injected as part of page initialization or on-the-fly. 2792 * 2793 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 2794 * @internal 2795 * @see {EventPluginHub.injection.injectEventPluginsByName} 2796 */ 2797 injectEventPluginsByName: function(injectedNamesToPlugins) { 2798 var isOrderingDirty = false; 2799 for (var pluginName in injectedNamesToPlugins) { 2800 if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { 2801 continue; 2802 } 2803 var PluginModule = injectedNamesToPlugins[pluginName]; 2804 if (namesToPlugins[pluginName] !== PluginModule) { 2805 ("production" !== "development" ? invariant( 2806 !namesToPlugins[pluginName], 2807 'EventPluginRegistry: Cannot inject two different event plugins ' + 2808 'using the same name, `%s`.', 2809 pluginName 2810 ) : invariant(!namesToPlugins[pluginName])); 2811 namesToPlugins[pluginName] = PluginModule; 2812 isOrderingDirty = true; 2813 } 2814 } 2815 if (isOrderingDirty) { 2816 recomputePluginOrdering(); 2817 } 2818 }, 2819 2820 /** 2821 * Looks up the plugin for the supplied event. 2822 * 2823 * @param {object} event A synthetic event. 2824 * @return {?object} The plugin that created the supplied event. 2825 * @internal 2826 */ 2827 getPluginModuleForEvent: function(event) { 2828 var dispatchConfig = event.dispatchConfig; 2829 if (dispatchConfig.registrationName) { 2830 return EventPluginRegistry.registrationNameModules[ 2831 dispatchConfig.registrationName 2832 ] || null; 2833 } 2834 for (var phase in dispatchConfig.phasedRegistrationNames) { 2835 if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) { 2836 continue; 2837 } 2838 var PluginModule = EventPluginRegistry.registrationNameModules[ 2839 dispatchConfig.phasedRegistrationNames[phase] 2840 ]; 2841 if (PluginModule) { 2842 return PluginModule; 2843 } 2844 } 2845 return null; 2846 }, 2847 2848 /** 2849 * Exposed for unit testing. 2850 * @private 2851 */ 2852 _resetEventPlugins: function() { 2853 EventPluginOrder = null; 2854 for (var pluginName in namesToPlugins) { 2855 if (namesToPlugins.hasOwnProperty(pluginName)) { 2856 delete namesToPlugins[pluginName]; 2857 } 2858 } 2859 EventPluginRegistry.plugins.length = 0; 2860 2861 var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs; 2862 for (var eventName in eventNameDispatchConfigs) { 2863 if (eventNameDispatchConfigs.hasOwnProperty(eventName)) { 2864 delete eventNameDispatchConfigs[eventName]; 2865 } 2866 } 2867 2868 var registrationNameModules = EventPluginRegistry.registrationNameModules; 2869 for (var registrationName in registrationNameModules) { 2870 if (registrationNameModules.hasOwnProperty(registrationName)) { 2871 delete registrationNameModules[registrationName]; 2872 } 2873 } 2874 } 2875 2876 }; 2877 2878 module.exports = EventPluginRegistry; 2879 2880 },{"./invariant":112}],18:[function(_dereq_,module,exports){ 2881 /** 2882 * Copyright 2013-2014 Facebook, Inc. 2883 * 2884 * Licensed under the Apache License, Version 2.0 (the "License"); 2885 * you may not use this file except in compliance with the License. 2886 * You may obtain a copy of the License at 2887 * 2888 * http://www.apache.org/licenses/LICENSE-2.0 2889 * 2890 * Unless required by applicable law or agreed to in writing, software 2891 * distributed under the License is distributed on an "AS IS" BASIS, 2892 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2893 * See the License for the specific language governing permissions and 2894 * limitations under the License. 2895 * 2896 * @providesModule EventPluginUtils 2897 */ 2898 2899 "use strict"; 2900 2901 var EventConstants = _dereq_("./EventConstants"); 2902 2903 var invariant = _dereq_("./invariant"); 2904 2905 /** 2906 * Injected dependencies: 2907 */ 2908 2909 /** 2910 * - `Mount`: [required] Module that can convert between React dom IDs and 2911 * actual node references. 2912 */ 2913 var injection = { 2914 Mount: null, 2915 injectMount: function(InjectedMount) { 2916 injection.Mount = InjectedMount; 2917 if ("production" !== "development") { 2918 ("production" !== "development" ? invariant( 2919 InjectedMount && InjectedMount.getNode, 2920 'EventPluginUtils.injection.injectMount(...): Injected Mount module ' + 2921 'is missing getNode.' 2922 ) : invariant(InjectedMount && InjectedMount.getNode)); 2923 } 2924 } 2925 }; 2926 2927 var topLevelTypes = EventConstants.topLevelTypes; 2928 2929 function isEndish(topLevelType) { 2930 return topLevelType === topLevelTypes.topMouseUp || 2931 topLevelType === topLevelTypes.topTouchEnd || 2932 topLevelType === topLevelTypes.topTouchCancel; 2933 } 2934 2935 function isMoveish(topLevelType) { 2936 return topLevelType === topLevelTypes.topMouseMove || 2937 topLevelType === topLevelTypes.topTouchMove; 2938 } 2939 function isStartish(topLevelType) { 2940 return topLevelType === topLevelTypes.topMouseDown || 2941 topLevelType === topLevelTypes.topTouchStart; 2942 } 2943 2944 2945 var validateEventDispatches; 2946 if ("production" !== "development") { 2947 validateEventDispatches = function(event) { 2948 var dispatchListeners = event._dispatchListeners; 2949 var dispatchIDs = event._dispatchIDs; 2950 2951 var listenersIsArr = Array.isArray(dispatchListeners); 2952 var idsIsArr = Array.isArray(dispatchIDs); 2953 var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0; 2954 var listenersLen = listenersIsArr ? 2955 dispatchListeners.length : 2956 dispatchListeners ? 1 : 0; 2957 2958 ("production" !== "development" ? invariant( 2959 idsIsArr === listenersIsArr && IDsLen === listenersLen, 2960 'EventPluginUtils: Invalid `event`.' 2961 ) : invariant(idsIsArr === listenersIsArr && IDsLen === listenersLen)); 2962 }; 2963 } 2964 2965 /** 2966 * Invokes `cb(event, listener, id)`. Avoids using call if no scope is 2967 * provided. The `(listener,id)` pair effectively forms the "dispatch" but are 2968 * kept separate to conserve memory. 2969 */ 2970 function forEachEventDispatch(event, cb) { 2971 var dispatchListeners = event._dispatchListeners; 2972 var dispatchIDs = event._dispatchIDs; 2973 if ("production" !== "development") { 2974 validateEventDispatches(event); 2975 } 2976 if (Array.isArray(dispatchListeners)) { 2977 for (var i = 0; i < dispatchListeners.length; i++) { 2978 if (event.isPropagationStopped()) { 2979 break; 2980 } 2981 // Listeners and IDs are two parallel arrays that are always in sync. 2982 cb(event, dispatchListeners[i], dispatchIDs[i]); 2983 } 2984 } else if (dispatchListeners) { 2985 cb(event, dispatchListeners, dispatchIDs); 2986 } 2987 } 2988 2989 /** 2990 * Default implementation of PluginModule.executeDispatch(). 2991 * @param {SyntheticEvent} SyntheticEvent to handle 2992 * @param {function} Application-level callback 2993 * @param {string} domID DOM id to pass to the callback. 2994 */ 2995 function executeDispatch(event, listener, domID) { 2996 event.currentTarget = injection.Mount.getNode(domID); 2997 var returnValue = listener(event, domID); 2998 event.currentTarget = null; 2999 return returnValue; 3000 } 3001 3002 /** 3003 * Standard/simple iteration through an event's collected dispatches. 3004 */ 3005 function executeDispatchesInOrder(event, executeDispatch) { 3006 forEachEventDispatch(event, executeDispatch); 3007 event._dispatchListeners = null; 3008 event._dispatchIDs = null; 3009 } 3010 3011 /** 3012 * Standard/simple iteration through an event's collected dispatches, but stops 3013 * at the first dispatch execution returning true, and returns that id. 3014 * 3015 * @return id of the first dispatch execution who's listener returns true, or 3016 * null if no listener returned true. 3017 */ 3018 function executeDispatchesInOrderStopAtTrue(event) { 3019 var dispatchListeners = event._dispatchListeners; 3020 var dispatchIDs = event._dispatchIDs; 3021 if ("production" !== "development") { 3022 validateEventDispatches(event); 3023 } 3024 if (Array.isArray(dispatchListeners)) { 3025 for (var i = 0; i < dispatchListeners.length; i++) { 3026 if (event.isPropagationStopped()) { 3027 break; 3028 } 3029 // Listeners and IDs are two parallel arrays that are always in sync. 3030 if (dispatchListeners[i](event, dispatchIDs[i])) { 3031 return dispatchIDs[i]; 3032 } 3033 } 3034 } else if (dispatchListeners) { 3035 if (dispatchListeners(event, dispatchIDs)) { 3036 return dispatchIDs; 3037 } 3038 } 3039 return null; 3040 } 3041 3042 /** 3043 * Execution of a "direct" dispatch - there must be at most one dispatch 3044 * accumulated on the event or it is considered an error. It doesn't really make 3045 * sense for an event with multiple dispatches (bubbled) to keep track of the 3046 * return values at each dispatch execution, but it does tend to make sense when 3047 * dealing with "direct" dispatches. 3048 * 3049 * @return The return value of executing the single dispatch. 3050 */ 3051 function executeDirectDispatch(event) { 3052 if ("production" !== "development") { 3053 validateEventDispatches(event); 3054 } 3055 var dispatchListener = event._dispatchListeners; 3056 var dispatchID = event._dispatchIDs; 3057 ("production" !== "development" ? invariant( 3058 !Array.isArray(dispatchListener), 3059 'executeDirectDispatch(...): Invalid `event`.' 3060 ) : invariant(!Array.isArray(dispatchListener))); 3061 var res = dispatchListener ? 3062 dispatchListener(event, dispatchID) : 3063 null; 3064 event._dispatchListeners = null; 3065 event._dispatchIDs = null; 3066 return res; 3067 } 3068 3069 /** 3070 * @param {SyntheticEvent} event 3071 * @return {bool} True iff number of dispatches accumulated is greater than 0. 3072 */ 3073 function hasDispatches(event) { 3074 return !!event._dispatchListeners; 3075 } 3076 3077 /** 3078 * General utilities that are useful in creating custom Event Plugins. 3079 */ 3080 var EventPluginUtils = { 3081 isEndish: isEndish, 3082 isMoveish: isMoveish, 3083 isStartish: isStartish, 3084 3085 executeDirectDispatch: executeDirectDispatch, 3086 executeDispatch: executeDispatch, 3087 executeDispatchesInOrder: executeDispatchesInOrder, 3088 executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, 3089 hasDispatches: hasDispatches, 3090 injection: injection, 3091 useTouchEvents: false 3092 }; 3093 3094 module.exports = EventPluginUtils; 3095 3096 },{"./EventConstants":14,"./invariant":112}],19:[function(_dereq_,module,exports){ 3097 /** 3098 * Copyright 2013-2014 Facebook, Inc. 3099 * 3100 * Licensed under the Apache License, Version 2.0 (the "License"); 3101 * you may not use this file except in compliance with the License. 3102 * You may obtain a copy of the License at 3103 * 3104 * http://www.apache.org/licenses/LICENSE-2.0 3105 * 3106 * Unless required by applicable law or agreed to in writing, software 3107 * distributed under the License is distributed on an "AS IS" BASIS, 3108 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3109 * See the License for the specific language governing permissions and 3110 * limitations under the License. 3111 * 3112 * @providesModule EventPropagators 3113 */ 3114 3115 "use strict"; 3116 3117 var EventConstants = _dereq_("./EventConstants"); 3118 var EventPluginHub = _dereq_("./EventPluginHub"); 3119 3120 var accumulate = _dereq_("./accumulate"); 3121 var forEachAccumulated = _dereq_("./forEachAccumulated"); 3122 3123 var PropagationPhases = EventConstants.PropagationPhases; 3124 var getListener = EventPluginHub.getListener; 3125 3126 /** 3127 * Some event types have a notion of different registration names for different 3128 * "phases" of propagation. This finds listeners by a given phase. 3129 */ 3130 function listenerAtPhase(id, event, propagationPhase) { 3131 var registrationName = 3132 event.dispatchConfig.phasedRegistrationNames[propagationPhase]; 3133 return getListener(id, registrationName); 3134 } 3135 3136 /** 3137 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function 3138 * here, allows us to not have to bind or create functions for each event. 3139 * Mutating the event's members allows us to not have to create a wrapping 3140 * "dispatch" object that pairs the event with the listener. 3141 */ 3142 function accumulateDirectionalDispatches(domID, upwards, event) { 3143 if ("production" !== "development") { 3144 if (!domID) { 3145 throw new Error('Dispatching id must not be null'); 3146 } 3147 } 3148 var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; 3149 var listener = listenerAtPhase(domID, event, phase); 3150 if (listener) { 3151 event._dispatchListeners = accumulate(event._dispatchListeners, listener); 3152 event._dispatchIDs = accumulate(event._dispatchIDs, domID); 3153 } 3154 } 3155 3156 /** 3157 * Collect dispatches (must be entirely collected before dispatching - see unit 3158 * tests). Lazily allocate the array to conserve memory. We must loop through 3159 * each event and perform the traversal for each one. We can not perform a 3160 * single traversal for the entire collection of events because each event may 3161 * have a different target. 3162 */ 3163 function accumulateTwoPhaseDispatchesSingle(event) { 3164 if (event && event.dispatchConfig.phasedRegistrationNames) { 3165 EventPluginHub.injection.getInstanceHandle().traverseTwoPhase( 3166 event.dispatchMarker, 3167 accumulateDirectionalDispatches, 3168 event 3169 ); 3170 } 3171 } 3172 3173 3174 /** 3175 * Accumulates without regard to direction, does not look for phased 3176 * registration names. Same as `accumulateDirectDispatchesSingle` but without 3177 * requiring that the `dispatchMarker` be the same as the dispatched ID. 3178 */ 3179 function accumulateDispatches(id, ignoredDirection, event) { 3180 if (event && event.dispatchConfig.registrationName) { 3181 var registrationName = event.dispatchConfig.registrationName; 3182 var listener = getListener(id, registrationName); 3183 if (listener) { 3184 event._dispatchListeners = accumulate(event._dispatchListeners, listener); 3185 event._dispatchIDs = accumulate(event._dispatchIDs, id); 3186 } 3187 } 3188 } 3189 3190 /** 3191 * Accumulates dispatches on an `SyntheticEvent`, but only for the 3192 * `dispatchMarker`. 3193 * @param {SyntheticEvent} event 3194 */ 3195 function accumulateDirectDispatchesSingle(event) { 3196 if (event && event.dispatchConfig.registrationName) { 3197 accumulateDispatches(event.dispatchMarker, null, event); 3198 } 3199 } 3200 3201 function accumulateTwoPhaseDispatches(events) { 3202 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); 3203 } 3204 3205 function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) { 3206 EventPluginHub.injection.getInstanceHandle().traverseEnterLeave( 3207 fromID, 3208 toID, 3209 accumulateDispatches, 3210 leave, 3211 enter 3212 ); 3213 } 3214 3215 3216 function accumulateDirectDispatches(events) { 3217 forEachAccumulated(events, accumulateDirectDispatchesSingle); 3218 } 3219 3220 3221 3222 /** 3223 * A small set of propagation patterns, each of which will accept a small amount 3224 * of information, and generate a set of "dispatch ready event objects" - which 3225 * are sets of events that have already been annotated with a set of dispatched 3226 * listener functions/ids. The API is designed this way to discourage these 3227 * propagation strategies from actually executing the dispatches, since we 3228 * always want to collect the entire set of dispatches before executing event a 3229 * single one. 3230 * 3231 * @constructor EventPropagators 3232 */ 3233 var EventPropagators = { 3234 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, 3235 accumulateDirectDispatches: accumulateDirectDispatches, 3236 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches 3237 }; 3238 3239 module.exports = EventPropagators; 3240 3241 },{"./EventConstants":14,"./EventPluginHub":16,"./accumulate":87,"./forEachAccumulated":101}],20:[function(_dereq_,module,exports){ 3242 /** 3243 * Copyright 2013-2014 Facebook, Inc. 3244 * 3245 * Licensed under the Apache License, Version 2.0 (the "License"); 3246 * you may not use this file except in compliance with the License. 3247 * You may obtain a copy of the License at 3248 * 3249 * http://www.apache.org/licenses/LICENSE-2.0 3250 * 3251 * Unless required by applicable law or agreed to in writing, software 3252 * distributed under the License is distributed on an "AS IS" BASIS, 3253 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3254 * See the License for the specific language governing permissions and 3255 * limitations under the License. 3256 * 3257 * @providesModule ExecutionEnvironment 3258 */ 3259 3260 /*jslint evil: true */ 3261 3262 "use strict"; 3263 3264 var canUseDOM = typeof window !== 'undefined'; 3265 3266 /** 3267 * Simple, lightweight module assisting with the detection and context of 3268 * Worker. Helps avoid circular dependencies and allows code to reason about 3269 * whether or not they are in a Worker, even if they never include the main 3270 * `ReactWorker` dependency. 3271 */ 3272 var ExecutionEnvironment = { 3273 3274 canUseDOM: canUseDOM, 3275 3276 canUseWorkers: typeof Worker !== 'undefined', 3277 3278 canUseEventListeners: 3279 canUseDOM && (window.addEventListener || window.attachEvent), 3280 3281 isInWorker: !canUseDOM // For now, this is true - might change in the future. 3282 3283 }; 3284 3285 module.exports = ExecutionEnvironment; 3286 3287 },{}],21:[function(_dereq_,module,exports){ 3288 /** 3289 * Copyright 2013-2014 Facebook, Inc. 3290 * 3291 * Licensed under the Apache License, Version 2.0 (the "License"); 3292 * you may not use this file except in compliance with the License. 3293 * You may obtain a copy of the License at 3294 * 3295 * http://www.apache.org/licenses/LICENSE-2.0 3296 * 3297 * Unless required by applicable law or agreed to in writing, software 3298 * distributed under the License is distributed on an "AS IS" BASIS, 3299 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3300 * See the License for the specific language governing permissions and 3301 * limitations under the License. 3302 * 3303 * @providesModule LinkedValueUtils 3304 * @typechecks static-only 3305 */ 3306 3307 "use strict"; 3308 3309 var ReactPropTypes = _dereq_("./ReactPropTypes"); 3310 3311 var invariant = _dereq_("./invariant"); 3312 var warning = _dereq_("./warning"); 3313 3314 var hasReadOnlyValue = { 3315 'button': true, 3316 'checkbox': true, 3317 'image': true, 3318 'hidden': true, 3319 'radio': true, 3320 'reset': true, 3321 'submit': true 3322 }; 3323 3324 function _assertSingleLink(input) { 3325 ("production" !== "development" ? invariant( 3326 input.props.checkedLink == null || input.props.valueLink == null, 3327 'Cannot provide a checkedLink and a valueLink. If you want to use ' + 3328 'checkedLink, you probably don\'t want to use valueLink and vice versa.' 3329 ) : invariant(input.props.checkedLink == null || input.props.valueLink == null)); 3330 } 3331 function _assertValueLink(input) { 3332 _assertSingleLink(input); 3333 ("production" !== "development" ? invariant( 3334 input.props.value == null && input.props.onChange == null, 3335 'Cannot provide a valueLink and a value or onChange event. If you want ' + 3336 'to use value or onChange, you probably don\'t want to use valueLink.' 3337 ) : invariant(input.props.value == null && input.props.onChange == null)); 3338 } 3339 3340 function _assertCheckedLink(input) { 3341 _assertSingleLink(input); 3342 ("production" !== "development" ? invariant( 3343 input.props.checked == null && input.props.onChange == null, 3344 'Cannot provide a checkedLink and a checked property or onChange event. ' + 3345 'If you want to use checked or onChange, you probably don\'t want to ' + 3346 'use checkedLink' 3347 ) : invariant(input.props.checked == null && input.props.onChange == null)); 3348 } 3349 3350 /** 3351 * @param {SyntheticEvent} e change event to handle 3352 */ 3353 function _handleLinkedValueChange(e) { 3354 /*jshint validthis:true */ 3355 this.props.valueLink.requestChange(e.target.value); 3356 } 3357 3358 /** 3359 * @param {SyntheticEvent} e change event to handle 3360 */ 3361 function _handleLinkedCheckChange(e) { 3362 /*jshint validthis:true */ 3363 this.props.checkedLink.requestChange(e.target.checked); 3364 } 3365 3366 /** 3367 * Provide a linked `value` attribute for controlled forms. You should not use 3368 * this outside of the ReactDOM controlled form components. 3369 */ 3370 var LinkedValueUtils = { 3371 Mixin: { 3372 propTypes: { 3373 value: function(props, propName, componentName) { 3374 if ("production" !== "development") { 3375 ("production" !== "development" ? warning( 3376 !props[propName] || 3377 hasReadOnlyValue[props.type] || 3378 props.onChange || 3379 props.readOnly || 3380 props.disabled, 3381 'You provided a `value` prop to a form field without an ' + 3382 '`onChange` handler. This will render a read-only field. If ' + 3383 'the field should be mutable use `defaultValue`. Otherwise, ' + 3384 'set either `onChange` or `readOnly`.' 3385 ) : null); 3386 } 3387 }, 3388 checked: function(props, propName, componentName) { 3389 if ("production" !== "development") { 3390 ("production" !== "development" ? warning( 3391 !props[propName] || 3392 props.onChange || 3393 props.readOnly || 3394 props.disabled, 3395 'You provided a `checked` prop to a form field without an ' + 3396 '`onChange` handler. This will render a read-only field. If ' + 3397 'the field should be mutable use `defaultChecked`. Otherwise, ' + 3398 'set either `onChange` or `readOnly`.' 3399 ) : null); 3400 } 3401 }, 3402 onChange: ReactPropTypes.func 3403 } 3404 }, 3405 3406 /** 3407 * @param {ReactComponent} input Form component 3408 * @return {*} current value of the input either from value prop or link. 3409 */ 3410 getValue: function(input) { 3411 if (input.props.valueLink) { 3412 _assertValueLink(input); 3413 return input.props.valueLink.value; 3414 } 3415 return input.props.value; 3416 }, 3417 3418 /** 3419 * @param {ReactComponent} input Form component 3420 * @return {*} current checked status of the input either from checked prop 3421 * or link. 3422 */ 3423 getChecked: function(input) { 3424 if (input.props.checkedLink) { 3425 _assertCheckedLink(input); 3426 return input.props.checkedLink.value; 3427 } 3428 return input.props.checked; 3429 }, 3430 3431 /** 3432 * @param {ReactComponent} input Form component 3433 * @return {function} change callback either from onChange prop or link. 3434 */ 3435 getOnChange: function(input) { 3436 if (input.props.valueLink) { 3437 _assertValueLink(input); 3438 return _handleLinkedValueChange; 3439 } else if (input.props.checkedLink) { 3440 _assertCheckedLink(input); 3441 return _handleLinkedCheckChange; 3442 } 3443 return input.props.onChange; 3444 } 3445 }; 3446 3447 module.exports = LinkedValueUtils; 3448 3449 },{"./ReactPropTypes":64,"./invariant":112,"./warning":134}],22:[function(_dereq_,module,exports){ 3450 /** 3451 * Copyright 2013-2014 Facebook, Inc. 3452 * 3453 * Licensed under the Apache License, Version 2.0 (the "License"); 3454 * you may not use this file except in compliance with the License. 3455 * You may obtain a copy of the License at 3456 * 3457 * http://www.apache.org/licenses/LICENSE-2.0 3458 * 3459 * Unless required by applicable law or agreed to in writing, software 3460 * distributed under the License is distributed on an "AS IS" BASIS, 3461 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3462 * See the License for the specific language governing permissions and 3463 * limitations under the License. 3464 * 3465 * @providesModule MobileSafariClickEventPlugin 3466 * @typechecks static-only 3467 */ 3468 3469 "use strict"; 3470 3471 var EventConstants = _dereq_("./EventConstants"); 3472 3473 var emptyFunction = _dereq_("./emptyFunction"); 3474 3475 var topLevelTypes = EventConstants.topLevelTypes; 3476 3477 /** 3478 * Mobile Safari does not fire properly bubble click events on non-interactive 3479 * elements, which means delegated click listeners do not fire. The workaround 3480 * for this bug involves attaching an empty click listener on the target node. 3481 * 3482 * This particular plugin works around the bug by attaching an empty click 3483 * listener on `touchstart` (which does fire on every element). 3484 */ 3485 var MobileSafariClickEventPlugin = { 3486 3487 eventTypes: null, 3488 3489 /** 3490 * @param {string} topLevelType Record from `EventConstants`. 3491 * @param {DOMEventTarget} topLevelTarget The listening component root node. 3492 * @param {string} topLevelTargetID ID of `topLevelTarget`. 3493 * @param {object} nativeEvent Native browser event. 3494 * @return {*} An accumulation of synthetic events. 3495 * @see {EventPluginHub.extractEvents} 3496 */ 3497 extractEvents: function( 3498 topLevelType, 3499 topLevelTarget, 3500 topLevelTargetID, 3501 nativeEvent) { 3502 if (topLevelType === topLevelTypes.topTouchStart) { 3503 var target = nativeEvent.target; 3504 if (target && !target.onclick) { 3505 target.onclick = emptyFunction; 3506 } 3507 } 3508 } 3509 3510 }; 3511 3512 module.exports = MobileSafariClickEventPlugin; 3513 3514 },{"./EventConstants":14,"./emptyFunction":96}],23:[function(_dereq_,module,exports){ 3515 /** 3516 * Copyright 2013-2014 Facebook, Inc. 3517 * 3518 * Licensed under the Apache License, Version 2.0 (the "License"); 3519 * you may not use this file except in compliance with the License. 3520 * You may obtain a copy of the License at 3521 * 3522 * http://www.apache.org/licenses/LICENSE-2.0 3523 * 3524 * Unless required by applicable law or agreed to in writing, software 3525 * distributed under the License is distributed on an "AS IS" BASIS, 3526 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3527 * See the License for the specific language governing permissions and 3528 * limitations under the License. 3529 * 3530 * @providesModule PooledClass 3531 */ 3532 3533 "use strict"; 3534 3535 var invariant = _dereq_("./invariant"); 3536 3537 /** 3538 * Static poolers. Several custom versions for each potential number of 3539 * arguments. A completely generic pooler is easy to implement, but would 3540 * require accessing the `arguments` object. In each of these, `this` refers to 3541 * the Class itself, not an instance. If any others are needed, simply add them 3542 * here, or in their own files. 3543 */ 3544 var oneArgumentPooler = function(copyFieldsFrom) { 3545 var Klass = this; 3546 if (Klass.instancePool.length) { 3547 var instance = Klass.instancePool.pop(); 3548 Klass.call(instance, copyFieldsFrom); 3549 return instance; 3550 } else { 3551 return new Klass(copyFieldsFrom); 3552 } 3553 }; 3554 3555 var twoArgumentPooler = function(a1, a2) { 3556 var Klass = this; 3557 if (Klass.instancePool.length) { 3558 var instance = Klass.instancePool.pop(); 3559 Klass.call(instance, a1, a2); 3560 return instance; 3561 } else { 3562 return new Klass(a1, a2); 3563 } 3564 }; 3565 3566 var threeArgumentPooler = function(a1, a2, a3) { 3567 var Klass = this; 3568 if (Klass.instancePool.length) { 3569 var instance = Klass.instancePool.pop(); 3570 Klass.call(instance, a1, a2, a3); 3571 return instance; 3572 } else { 3573 return new Klass(a1, a2, a3); 3574 } 3575 }; 3576 3577 var fiveArgumentPooler = function(a1, a2, a3, a4, a5) { 3578 var Klass = this; 3579 if (Klass.instancePool.length) { 3580 var instance = Klass.instancePool.pop(); 3581 Klass.call(instance, a1, a2, a3, a4, a5); 3582 return instance; 3583 } else { 3584 return new Klass(a1, a2, a3, a4, a5); 3585 } 3586 }; 3587 3588 var standardReleaser = function(instance) { 3589 var Klass = this; 3590 ("production" !== "development" ? invariant( 3591 instance instanceof Klass, 3592 'Trying to release an instance into a pool of a different type.' 3593 ) : invariant(instance instanceof Klass)); 3594 if (instance.destructor) { 3595 instance.destructor(); 3596 } 3597 if (Klass.instancePool.length < Klass.poolSize) { 3598 Klass.instancePool.push(instance); 3599 } 3600 }; 3601 3602 var DEFAULT_POOL_SIZE = 10; 3603 var DEFAULT_POOLER = oneArgumentPooler; 3604 3605 /** 3606 * Augments `CopyConstructor` to be a poolable class, augmenting only the class 3607 * itself (statically) not adding any prototypical fields. Any CopyConstructor 3608 * you give this may have a `poolSize` property, and will look for a 3609 * prototypical `destructor` on instances (optional). 3610 * 3611 * @param {Function} CopyConstructor Constructor that can be used to reset. 3612 * @param {Function} pooler Customizable pooler. 3613 */ 3614 var addPoolingTo = function(CopyConstructor, pooler) { 3615 var NewKlass = CopyConstructor; 3616 NewKlass.instancePool = []; 3617 NewKlass.getPooled = pooler || DEFAULT_POOLER; 3618 if (!NewKlass.poolSize) { 3619 NewKlass.poolSize = DEFAULT_POOL_SIZE; 3620 } 3621 NewKlass.release = standardReleaser; 3622 return NewKlass; 3623 }; 3624 3625 var PooledClass = { 3626 addPoolingTo: addPoolingTo, 3627 oneArgumentPooler: oneArgumentPooler, 3628 twoArgumentPooler: twoArgumentPooler, 3629 threeArgumentPooler: threeArgumentPooler, 3630 fiveArgumentPooler: fiveArgumentPooler 3631 }; 3632 3633 module.exports = PooledClass; 3634 3635 },{"./invariant":112}],24:[function(_dereq_,module,exports){ 3636 /** 3637 * Copyright 2013-2014 Facebook, Inc. 3638 * 3639 * Licensed under the Apache License, Version 2.0 (the "License"); 3640 * you may not use this file except in compliance with the License. 3641 * You may obtain a copy of the License at 3642 * 3643 * http://www.apache.org/licenses/LICENSE-2.0 3644 * 3645 * Unless required by applicable law or agreed to in writing, software 3646 * distributed under the License is distributed on an "AS IS" BASIS, 3647 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3648 * See the License for the specific language governing permissions and 3649 * limitations under the License. 3650 * 3651 * @providesModule React 3652 */ 3653 3654 "use strict"; 3655 3656 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 3657 var EventPluginUtils = _dereq_("./EventPluginUtils"); 3658 var ReactChildren = _dereq_("./ReactChildren"); 3659 var ReactComponent = _dereq_("./ReactComponent"); 3660 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 3661 var ReactContext = _dereq_("./ReactContext"); 3662 var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); 3663 var ReactDOM = _dereq_("./ReactDOM"); 3664 var ReactDOMComponent = _dereq_("./ReactDOMComponent"); 3665 var ReactDefaultInjection = _dereq_("./ReactDefaultInjection"); 3666 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 3667 var ReactMount = _dereq_("./ReactMount"); 3668 var ReactMultiChild = _dereq_("./ReactMultiChild"); 3669 var ReactPerf = _dereq_("./ReactPerf"); 3670 var ReactPropTypes = _dereq_("./ReactPropTypes"); 3671 var ReactServerRendering = _dereq_("./ReactServerRendering"); 3672 var ReactTextComponent = _dereq_("./ReactTextComponent"); 3673 3674 var onlyChild = _dereq_("./onlyChild"); 3675 3676 ReactDefaultInjection.inject(); 3677 3678 var React = { 3679 Children: { 3680 map: ReactChildren.map, 3681 forEach: ReactChildren.forEach, 3682 only: onlyChild 3683 }, 3684 DOM: ReactDOM, 3685 PropTypes: ReactPropTypes, 3686 initializeTouchEvents: function(shouldUseTouch) { 3687 EventPluginUtils.useTouchEvents = shouldUseTouch; 3688 }, 3689 createClass: ReactCompositeComponent.createClass, 3690 constructAndRenderComponent: ReactMount.constructAndRenderComponent, 3691 constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, 3692 renderComponent: ReactPerf.measure( 3693 'React', 3694 'renderComponent', 3695 ReactMount.renderComponent 3696 ), 3697 renderComponentToString: ReactServerRendering.renderComponentToString, 3698 renderComponentToStaticMarkup: 3699 ReactServerRendering.renderComponentToStaticMarkup, 3700 unmountComponentAtNode: ReactMount.unmountComponentAtNode, 3701 isValidClass: ReactCompositeComponent.isValidClass, 3702 isValidComponent: ReactComponent.isValidComponent, 3703 withContext: ReactContext.withContext, 3704 __internals: { 3705 Component: ReactComponent, 3706 CurrentOwner: ReactCurrentOwner, 3707 DOMComponent: ReactDOMComponent, 3708 DOMPropertyOperations: DOMPropertyOperations, 3709 InstanceHandles: ReactInstanceHandles, 3710 Mount: ReactMount, 3711 MultiChild: ReactMultiChild, 3712 TextComponent: ReactTextComponent 3713 } 3714 }; 3715 3716 if ("production" !== "development") { 3717 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 3718 if (ExecutionEnvironment.canUseDOM && 3719 window.top === window.self && 3720 navigator.userAgent.indexOf('Chrome') > -1) { 3721 console.debug( 3722 'Download the React DevTools for a better development experience: ' + 3723 'http://fb.me/react-devtools' 3724 ); 3725 } 3726 } 3727 3728 // Version exists only in the open-source version of React, not in Facebook's 3729 // internal version. 3730 React.version = '0.10.0'; 3731 3732 module.exports = React; 3733 3734 },{"./DOMPropertyOperations":9,"./EventPluginUtils":18,"./ExecutionEnvironment":20,"./ReactChildren":26,"./ReactComponent":27,"./ReactCompositeComponent":29,"./ReactContext":30,"./ReactCurrentOwner":31,"./ReactDOM":32,"./ReactDOMComponent":34,"./ReactDefaultInjection":44,"./ReactInstanceHandles":53,"./ReactMount":55,"./ReactMultiChild":57,"./ReactPerf":60,"./ReactPropTypes":64,"./ReactServerRendering":68,"./ReactTextComponent":70,"./onlyChild":128}],25:[function(_dereq_,module,exports){ 3735 /** 3736 * Copyright 2013-2014 Facebook, Inc. 3737 * 3738 * Licensed under the Apache License, Version 2.0 (the "License"); 3739 * you may not use this file except in compliance with the License. 3740 * You may obtain a copy of the License at 3741 * 3742 * http://www.apache.org/licenses/LICENSE-2.0 3743 * 3744 * Unless required by applicable law or agreed to in writing, software 3745 * distributed under the License is distributed on an "AS IS" BASIS, 3746 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3747 * See the License for the specific language governing permissions and 3748 * limitations under the License. 3749 * 3750 * @providesModule ReactBrowserComponentMixin 3751 */ 3752 3753 "use strict"; 3754 3755 var ReactMount = _dereq_("./ReactMount"); 3756 3757 var invariant = _dereq_("./invariant"); 3758 3759 var ReactBrowserComponentMixin = { 3760 /** 3761 * Returns the DOM node rendered by this component. 3762 * 3763 * @return {DOMElement} The root node of this component. 3764 * @final 3765 * @protected 3766 */ 3767 getDOMNode: function() { 3768 ("production" !== "development" ? invariant( 3769 this.isMounted(), 3770 'getDOMNode(): A component must be mounted to have a DOM node.' 3771 ) : invariant(this.isMounted())); 3772 return ReactMount.getNode(this._rootNodeID); 3773 } 3774 }; 3775 3776 module.exports = ReactBrowserComponentMixin; 3777 3778 },{"./ReactMount":55,"./invariant":112}],26:[function(_dereq_,module,exports){ 3779 /** 3780 * Copyright 2013-2014 Facebook, Inc. 3781 * 3782 * Licensed under the Apache License, Version 2.0 (the "License"); 3783 * you may not use this file except in compliance with the License. 3784 * You may obtain a copy of the License at 3785 * 3786 * http://www.apache.org/licenses/LICENSE-2.0 3787 * 3788 * Unless required by applicable law or agreed to in writing, software 3789 * distributed under the License is distributed on an "AS IS" BASIS, 3790 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3791 * See the License for the specific language governing permissions and 3792 * limitations under the License. 3793 * 3794 * @providesModule ReactChildren 3795 */ 3796 3797 "use strict"; 3798 3799 var PooledClass = _dereq_("./PooledClass"); 3800 3801 var invariant = _dereq_("./invariant"); 3802 var traverseAllChildren = _dereq_("./traverseAllChildren"); 3803 3804 var twoArgumentPooler = PooledClass.twoArgumentPooler; 3805 var threeArgumentPooler = PooledClass.threeArgumentPooler; 3806 3807 /** 3808 * PooledClass representing the bookkeeping associated with performing a child 3809 * traversal. Allows avoiding binding callbacks. 3810 * 3811 * @constructor ForEachBookKeeping 3812 * @param {!function} forEachFunction Function to perform traversal with. 3813 * @param {?*} forEachContext Context to perform context with. 3814 */ 3815 function ForEachBookKeeping(forEachFunction, forEachContext) { 3816 this.forEachFunction = forEachFunction; 3817 this.forEachContext = forEachContext; 3818 } 3819 PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); 3820 3821 function forEachSingleChild(traverseContext, child, name, i) { 3822 var forEachBookKeeping = traverseContext; 3823 forEachBookKeeping.forEachFunction.call( 3824 forEachBookKeeping.forEachContext, child, i); 3825 } 3826 3827 /** 3828 * Iterates through children that are typically specified as `props.children`. 3829 * 3830 * The provided forEachFunc(child, index) will be called for each 3831 * leaf child. 3832 * 3833 * @param {?*} children Children tree container. 3834 * @param {function(*, int)} forEachFunc. 3835 * @param {*} forEachContext Context for forEachContext. 3836 */ 3837 function forEachChildren(children, forEachFunc, forEachContext) { 3838 if (children == null) { 3839 return children; 3840 } 3841 3842 var traverseContext = 3843 ForEachBookKeeping.getPooled(forEachFunc, forEachContext); 3844 traverseAllChildren(children, forEachSingleChild, traverseContext); 3845 ForEachBookKeeping.release(traverseContext); 3846 } 3847 3848 /** 3849 * PooledClass representing the bookkeeping associated with performing a child 3850 * mapping. Allows avoiding binding callbacks. 3851 * 3852 * @constructor MapBookKeeping 3853 * @param {!*} mapResult Object containing the ordered map of results. 3854 * @param {!function} mapFunction Function to perform mapping with. 3855 * @param {?*} mapContext Context to perform mapping with. 3856 */ 3857 function MapBookKeeping(mapResult, mapFunction, mapContext) { 3858 this.mapResult = mapResult; 3859 this.mapFunction = mapFunction; 3860 this.mapContext = mapContext; 3861 } 3862 PooledClass.addPoolingTo(MapBookKeeping, threeArgumentPooler); 3863 3864 function mapSingleChildIntoContext(traverseContext, child, name, i) { 3865 var mapBookKeeping = traverseContext; 3866 var mapResult = mapBookKeeping.mapResult; 3867 var mappedChild = 3868 mapBookKeeping.mapFunction.call(mapBookKeeping.mapContext, child, i); 3869 // We found a component instance 3870 ("production" !== "development" ? invariant( 3871 !mapResult.hasOwnProperty(name), 3872 'ReactChildren.map(...): Encountered two children with the same key, ' + 3873 '`%s`. Children keys must be unique.', 3874 name 3875 ) : invariant(!mapResult.hasOwnProperty(name))); 3876 mapResult[name] = mappedChild; 3877 } 3878 3879 /** 3880 * Maps children that are typically specified as `props.children`. 3881 * 3882 * The provided mapFunction(child, key, index) will be called for each 3883 * leaf child. 3884 * 3885 * TODO: This may likely break any calls to `ReactChildren.map` that were 3886 * previously relying on the fact that we guarded against null children. 3887 * 3888 * @param {?*} children Children tree container. 3889 * @param {function(*, int)} mapFunction. 3890 * @param {*} mapContext Context for mapFunction. 3891 * @return {object} Object containing the ordered map of results. 3892 */ 3893 function mapChildren(children, func, context) { 3894 if (children == null) { 3895 return children; 3896 } 3897 3898 var mapResult = {}; 3899 var traverseContext = MapBookKeeping.getPooled(mapResult, func, context); 3900 traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); 3901 MapBookKeeping.release(traverseContext); 3902 return mapResult; 3903 } 3904 3905 var ReactChildren = { 3906 forEach: forEachChildren, 3907 map: mapChildren 3908 }; 3909 3910 module.exports = ReactChildren; 3911 3912 },{"./PooledClass":23,"./invariant":112,"./traverseAllChildren":133}],27:[function(_dereq_,module,exports){ 3913 /** 3914 * Copyright 2013-2014 Facebook, Inc. 3915 * 3916 * Licensed under the Apache License, Version 2.0 (the "License"); 3917 * you may not use this file except in compliance with the License. 3918 * You may obtain a copy of the License at 3919 * 3920 * http://www.apache.org/licenses/LICENSE-2.0 3921 * 3922 * Unless required by applicable law or agreed to in writing, software 3923 * distributed under the License is distributed on an "AS IS" BASIS, 3924 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3925 * See the License for the specific language governing permissions and 3926 * limitations under the License. 3927 * 3928 * @providesModule ReactComponent 3929 */ 3930 3931 "use strict"; 3932 3933 var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); 3934 var ReactOwner = _dereq_("./ReactOwner"); 3935 var ReactUpdates = _dereq_("./ReactUpdates"); 3936 3937 var invariant = _dereq_("./invariant"); 3938 var keyMirror = _dereq_("./keyMirror"); 3939 var merge = _dereq_("./merge"); 3940 var monitorCodeUse = _dereq_("./monitorCodeUse"); 3941 3942 /** 3943 * Every React component is in one of these life cycles. 3944 */ 3945 var ComponentLifeCycle = keyMirror({ 3946 /** 3947 * Mounted components have a DOM node representation and are capable of 3948 * receiving new props. 3949 */ 3950 MOUNTED: null, 3951 /** 3952 * Unmounted components are inactive and cannot receive new props. 3953 */ 3954 UNMOUNTED: null 3955 }); 3956 3957 /** 3958 * Warn if there's no key explicitly set on dynamic arrays of children or 3959 * object keys are not valid. This allows us to keep track of children between 3960 * updates. 3961 */ 3962 3963 var ownerHasExplicitKeyWarning = {}; 3964 var ownerHasPropertyWarning = {}; 3965 var ownerHasMonitoredObjectMap = {}; 3966 3967 var NUMERIC_PROPERTY_REGEX = /^\d+$/; 3968 3969 var injected = false; 3970 3971 /** 3972 * Optionally injectable environment dependent cleanup hook. (server vs. 3973 * browser etc). Example: A browser system caches DOM nodes based on component 3974 * ID and must remove that cache entry when this instance is unmounted. 3975 * 3976 * @private 3977 */ 3978 var unmountIDFromEnvironment = null; 3979 3980 /** 3981 * The "image" of a component tree, is the platform specific (typically 3982 * serialized) data that represents a tree of lower level UI building blocks. 3983 * On the web, this "image" is HTML markup which describes a construction of 3984 * low level `div` and `span` nodes. Other platforms may have different 3985 * encoding of this "image". This must be injected. 3986 * 3987 * @private 3988 */ 3989 var mountImageIntoNode = null; 3990 3991 /** 3992 * Warn if the component doesn't have an explicit key assigned to it. 3993 * This component is in an array. The array could grow and shrink or be 3994 * reordered. All children that haven't already been validated are required to 3995 * have a "key" property assigned to it. 3996 * 3997 * @internal 3998 * @param {ReactComponent} component Component that requires a key. 3999 */ 4000 function validateExplicitKey(component) { 4001 if (component.__keyValidated__ || component.props.key != null) { 4002 return; 4003 } 4004 component.__keyValidated__ = true; 4005 4006 // We can't provide friendly warnings for top level components. 4007 if (!ReactCurrentOwner.current) { 4008 return; 4009 } 4010 4011 // Name of the component whose render method tried to pass children. 4012 var currentName = ReactCurrentOwner.current.constructor.displayName; 4013 if (ownerHasExplicitKeyWarning.hasOwnProperty(currentName)) { 4014 return; 4015 } 4016 ownerHasExplicitKeyWarning[currentName] = true; 4017 4018 var message = 'Each child in an array should have a unique "key" prop. ' + 4019 'Check the render method of ' + currentName + '.'; 4020 4021 var childOwnerName = null; 4022 if (!component.isOwnedBy(ReactCurrentOwner.current)) { 4023 // Name of the component that originally created this child. 4024 childOwnerName = 4025 component._owner && 4026 component._owner.constructor.displayName; 4027 4028 // Usually the current owner is the offender, but if it accepts 4029 // children as a property, it may be the creator of the child that's 4030 // responsible for assigning it a key. 4031 message += ' It was passed a child from ' + childOwnerName + '.'; 4032 } 4033 4034 message += ' See http://fb.me/react-warning-keys for more information.'; 4035 monitorCodeUse('react_key_warning', { 4036 component: currentName, 4037 componentOwner: childOwnerName 4038 }); 4039 console.warn(message); 4040 } 4041 4042 /** 4043 * Warn if the key is being defined as an object property but has an incorrect 4044 * value. 4045 * 4046 * @internal 4047 * @param {string} name Property name of the key. 4048 * @param {ReactComponent} component Component that requires a key. 4049 */ 4050 function validatePropertyKey(name) { 4051 if (NUMERIC_PROPERTY_REGEX.test(name)) { 4052 // Name of the component whose render method tried to pass children. 4053 var currentName = ReactCurrentOwner.current.constructor.displayName; 4054 if (ownerHasPropertyWarning.hasOwnProperty(currentName)) { 4055 return; 4056 } 4057 ownerHasPropertyWarning[currentName] = true; 4058 4059 monitorCodeUse('react_numeric_key_warning'); 4060 console.warn( 4061 'Child objects should have non-numeric keys so ordering is preserved. ' + 4062 'Check the render method of ' + currentName + '. ' + 4063 'See http://fb.me/react-warning-keys for more information.' 4064 ); 4065 } 4066 } 4067 4068 /** 4069 * Log that we're using an object map. We're considering deprecating this 4070 * feature and replace it with proper Map and ImmutableMap data structures. 4071 * 4072 * @internal 4073 */ 4074 function monitorUseOfObjectMap() { 4075 // Name of the component whose render method tried to pass children. 4076 // We only use this to avoid spewing the logs. We lose additional 4077 // owner stacks but hopefully one level is enough to trace the source. 4078 var currentName = (ReactCurrentOwner.current && 4079 ReactCurrentOwner.current.constructor.displayName) || ''; 4080 if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) { 4081 return; 4082 } 4083 ownerHasMonitoredObjectMap[currentName] = true; 4084 monitorCodeUse('react_object_map_children'); 4085 } 4086 4087 /** 4088 * Ensure that every component either is passed in a static location, in an 4089 * array with an explicit keys property defined, or in an object literal 4090 * with valid key property. 4091 * 4092 * @internal 4093 * @param {*} component Statically passed child of any type. 4094 * @return {boolean} 4095 */ 4096 function validateChildKeys(component) { 4097 if (Array.isArray(component)) { 4098 for (var i = 0; i < component.length; i++) { 4099 var child = component[i]; 4100 if (ReactComponent.isValidComponent(child)) { 4101 validateExplicitKey(child); 4102 } 4103 } 4104 } else if (ReactComponent.isValidComponent(component)) { 4105 // This component was passed in a valid location. 4106 component.__keyValidated__ = true; 4107 } else if (component && typeof component === 'object') { 4108 monitorUseOfObjectMap(); 4109 for (var name in component) { 4110 validatePropertyKey(name, component); 4111 } 4112 } 4113 } 4114 4115 /** 4116 * Components are the basic units of composition in React. 4117 * 4118 * Every component accepts a set of keyed input parameters known as "props" that 4119 * are initialized by the constructor. Once a component is mounted, the props 4120 * can be mutated using `setProps` or `replaceProps`. 4121 * 4122 * Every component is capable of the following operations: 4123 * 4124 * `mountComponent` 4125 * Initializes the component, renders markup, and registers event listeners. 4126 * 4127 * `receiveComponent` 4128 * Updates the rendered DOM nodes to match the given component. 4129 * 4130 * `unmountComponent` 4131 * Releases any resources allocated by this component. 4132 * 4133 * Components can also be "owned" by other components. Being owned by another 4134 * component means being constructed by that component. This is different from 4135 * being the child of a component, which means having a DOM representation that 4136 * is a child of the DOM representation of that component. 4137 * 4138 * @class ReactComponent 4139 */ 4140 var ReactComponent = { 4141 4142 injection: { 4143 injectEnvironment: function(ReactComponentEnvironment) { 4144 ("production" !== "development" ? invariant( 4145 !injected, 4146 'ReactComponent: injectEnvironment() can only be called once.' 4147 ) : invariant(!injected)); 4148 mountImageIntoNode = ReactComponentEnvironment.mountImageIntoNode; 4149 unmountIDFromEnvironment = 4150 ReactComponentEnvironment.unmountIDFromEnvironment; 4151 ReactComponent.BackendIDOperations = 4152 ReactComponentEnvironment.BackendIDOperations; 4153 ReactComponent.ReactReconcileTransaction = 4154 ReactComponentEnvironment.ReactReconcileTransaction; 4155 injected = true; 4156 } 4157 }, 4158 4159 /** 4160 * @param {?object} object 4161 * @return {boolean} True if `object` is a valid component. 4162 * @final 4163 */ 4164 isValidComponent: function(object) { 4165 if (!object || !object.type || !object.type.prototype) { 4166 return false; 4167 } 4168 // This is the safer way of duck checking the type of instance this is. 4169 // The object can be a generic descriptor but the type property refers to 4170 // the constructor and it's prototype can be used to inspect the type that 4171 // will actually get mounted. 4172 var prototype = object.type.prototype; 4173 return ( 4174 typeof prototype.mountComponentIntoNode === 'function' && 4175 typeof prototype.receiveComponent === 'function' 4176 ); 4177 }, 4178 4179 /** 4180 * @internal 4181 */ 4182 LifeCycle: ComponentLifeCycle, 4183 4184 /** 4185 * Injected module that provides ability to mutate individual properties. 4186 * Injected into the base class because many different subclasses need access 4187 * to this. 4188 * 4189 * @internal 4190 */ 4191 BackendIDOperations: null, 4192 4193 /** 4194 * React references `ReactReconcileTransaction` using this property in order 4195 * to allow dependency injection. 4196 * 4197 * @internal 4198 */ 4199 ReactReconcileTransaction: null, 4200 4201 /** 4202 * Base functionality for every ReactComponent constructor. Mixed into the 4203 * `ReactComponent` prototype, but exposed statically for easy access. 4204 * 4205 * @lends {ReactComponent.prototype} 4206 */ 4207 Mixin: { 4208 4209 /** 4210 * Checks whether or not this component is mounted. 4211 * 4212 * @return {boolean} True if mounted, false otherwise. 4213 * @final 4214 * @protected 4215 */ 4216 isMounted: function() { 4217 return this._lifeCycleState === ComponentLifeCycle.MOUNTED; 4218 }, 4219 4220 /** 4221 * Sets a subset of the props. 4222 * 4223 * @param {object} partialProps Subset of the next props. 4224 * @param {?function} callback Called after props are updated. 4225 * @final 4226 * @public 4227 */ 4228 setProps: function(partialProps, callback) { 4229 // Merge with `_pendingProps` if it exists, otherwise with existing props. 4230 this.replaceProps( 4231 merge(this._pendingProps || this.props, partialProps), 4232 callback 4233 ); 4234 }, 4235 4236 /** 4237 * Replaces all of the props. 4238 * 4239 * @param {object} props New props. 4240 * @param {?function} callback Called after props are updated. 4241 * @final 4242 * @public 4243 */ 4244 replaceProps: function(props, callback) { 4245 ("production" !== "development" ? invariant( 4246 this.isMounted(), 4247 'replaceProps(...): Can only update a mounted component.' 4248 ) : invariant(this.isMounted())); 4249 ("production" !== "development" ? invariant( 4250 this._mountDepth === 0, 4251 'replaceProps(...): You called `setProps` or `replaceProps` on a ' + 4252 'component with a parent. This is an anti-pattern since props will ' + 4253 'get reactively updated when rendered. Instead, change the owner\'s ' + 4254 '`render` method to pass the correct value as props to the component ' + 4255 'where it is created.' 4256 ) : invariant(this._mountDepth === 0)); 4257 this._pendingProps = props; 4258 ReactUpdates.enqueueUpdate(this, callback); 4259 }, 4260 4261 /** 4262 * Base constructor for all React components. 4263 * 4264 * Subclasses that override this method should make sure to invoke 4265 * `ReactComponent.Mixin.construct.call(this, ...)`. 4266 * 4267 * @param {?object} initialProps 4268 * @param {*} children 4269 * @internal 4270 */ 4271 construct: function(initialProps, children) { 4272 this.props = initialProps || {}; 4273 // Record the component responsible for creating this component. 4274 this._owner = ReactCurrentOwner.current; 4275 // All components start unmounted. 4276 this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; 4277 4278 this._pendingProps = null; 4279 this._pendingCallbacks = null; 4280 4281 // Unlike _pendingProps and _pendingCallbacks, we won't use null to 4282 // indicate that nothing is pending because it's possible for a component 4283 // to have a null owner. Instead, an owner change is pending when 4284 // this._owner !== this._pendingOwner. 4285 this._pendingOwner = this._owner; 4286 4287 // Children can be more than one argument 4288 var childrenLength = arguments.length - 1; 4289 if (childrenLength === 1) { 4290 if ("production" !== "development") { 4291 validateChildKeys(children); 4292 } 4293 this.props.children = children; 4294 } else if (childrenLength > 1) { 4295 var childArray = Array(childrenLength); 4296 for (var i = 0; i < childrenLength; i++) { 4297 if ("production" !== "development") { 4298 validateChildKeys(arguments[i + 1]); 4299 } 4300 childArray[i] = arguments[i + 1]; 4301 } 4302 this.props.children = childArray; 4303 } 4304 }, 4305 4306 /** 4307 * Initializes the component, renders markup, and registers event listeners. 4308 * 4309 * NOTE: This does not insert any nodes into the DOM. 4310 * 4311 * Subclasses that override this method should make sure to invoke 4312 * `ReactComponent.Mixin.mountComponent.call(this, ...)`. 4313 * 4314 * @param {string} rootID DOM ID of the root node. 4315 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 4316 * @param {number} mountDepth number of components in the owner hierarchy. 4317 * @return {?string} Rendered markup to be inserted into the DOM. 4318 * @internal 4319 */ 4320 mountComponent: function(rootID, transaction, mountDepth) { 4321 ("production" !== "development" ? invariant( 4322 !this.isMounted(), 4323 'mountComponent(%s, ...): Can only mount an unmounted component. ' + 4324 'Make sure to avoid storing components between renders or reusing a ' + 4325 'single component instance in multiple places.', 4326 rootID 4327 ) : invariant(!this.isMounted())); 4328 var props = this.props; 4329 if (props.ref != null) { 4330 ReactOwner.addComponentAsRefTo(this, props.ref, this._owner); 4331 } 4332 this._rootNodeID = rootID; 4333 this._lifeCycleState = ComponentLifeCycle.MOUNTED; 4334 this._mountDepth = mountDepth; 4335 // Effectively: return ''; 4336 }, 4337 4338 /** 4339 * Releases any resources allocated by `mountComponent`. 4340 * 4341 * NOTE: This does not remove any nodes from the DOM. 4342 * 4343 * Subclasses that override this method should make sure to invoke 4344 * `ReactComponent.Mixin.unmountComponent.call(this)`. 4345 * 4346 * @internal 4347 */ 4348 unmountComponent: function() { 4349 ("production" !== "development" ? invariant( 4350 this.isMounted(), 4351 'unmountComponent(): Can only unmount a mounted component.' 4352 ) : invariant(this.isMounted())); 4353 var props = this.props; 4354 if (props.ref != null) { 4355 ReactOwner.removeComponentAsRefFrom(this, props.ref, this._owner); 4356 } 4357 unmountIDFromEnvironment(this._rootNodeID); 4358 this._rootNodeID = null; 4359 this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; 4360 }, 4361 4362 /** 4363 * Given a new instance of this component, updates the rendered DOM nodes 4364 * as if that instance was rendered instead. 4365 * 4366 * Subclasses that override this method should make sure to invoke 4367 * `ReactComponent.Mixin.receiveComponent.call(this, ...)`. 4368 * 4369 * @param {object} nextComponent Next set of properties. 4370 * @param {ReactReconcileTransaction} transaction 4371 * @internal 4372 */ 4373 receiveComponent: function(nextComponent, transaction) { 4374 ("production" !== "development" ? invariant( 4375 this.isMounted(), 4376 'receiveComponent(...): Can only update a mounted component.' 4377 ) : invariant(this.isMounted())); 4378 this._pendingOwner = nextComponent._owner; 4379 this._pendingProps = nextComponent.props; 4380 this._performUpdateIfNecessary(transaction); 4381 }, 4382 4383 /** 4384 * Call `_performUpdateIfNecessary` within a new transaction. 4385 * 4386 * @internal 4387 */ 4388 performUpdateIfNecessary: function() { 4389 var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); 4390 transaction.perform(this._performUpdateIfNecessary, this, transaction); 4391 ReactComponent.ReactReconcileTransaction.release(transaction); 4392 }, 4393 4394 /** 4395 * If `_pendingProps` is set, update the component. 4396 * 4397 * @param {ReactReconcileTransaction} transaction 4398 * @internal 4399 */ 4400 _performUpdateIfNecessary: function(transaction) { 4401 if (this._pendingProps == null) { 4402 return; 4403 } 4404 var prevProps = this.props; 4405 var prevOwner = this._owner; 4406 this.props = this._pendingProps; 4407 this._owner = this._pendingOwner; 4408 this._pendingProps = null; 4409 this.updateComponent(transaction, prevProps, prevOwner); 4410 }, 4411 4412 /** 4413 * Updates the component's currently mounted representation. 4414 * 4415 * @param {ReactReconcileTransaction} transaction 4416 * @param {object} prevProps 4417 * @internal 4418 */ 4419 updateComponent: function(transaction, prevProps, prevOwner) { 4420 var props = this.props; 4421 // If either the owner or a `ref` has changed, make sure the newest owner 4422 // has stored a reference to `this`, and the previous owner (if different) 4423 // has forgotten the reference to `this`. 4424 if (this._owner !== prevOwner || props.ref !== prevProps.ref) { 4425 if (prevProps.ref != null) { 4426 ReactOwner.removeComponentAsRefFrom( 4427 this, prevProps.ref, prevOwner 4428 ); 4429 } 4430 // Correct, even if the owner is the same, and only the ref has changed. 4431 if (props.ref != null) { 4432 ReactOwner.addComponentAsRefTo(this, props.ref, this._owner); 4433 } 4434 } 4435 }, 4436 4437 /** 4438 * Mounts this component and inserts it into the DOM. 4439 * 4440 * @param {string} rootID DOM ID of the root node. 4441 * @param {DOMElement} container DOM element to mount into. 4442 * @param {boolean} shouldReuseMarkup If true, do not insert markup 4443 * @final 4444 * @internal 4445 * @see {ReactMount.renderComponent} 4446 */ 4447 mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { 4448 var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); 4449 transaction.perform( 4450 this._mountComponentIntoNode, 4451 this, 4452 rootID, 4453 container, 4454 transaction, 4455 shouldReuseMarkup 4456 ); 4457 ReactComponent.ReactReconcileTransaction.release(transaction); 4458 }, 4459 4460 /** 4461 * @param {string} rootID DOM ID of the root node. 4462 * @param {DOMElement} container DOM element to mount into. 4463 * @param {ReactReconcileTransaction} transaction 4464 * @param {boolean} shouldReuseMarkup If true, do not insert markup 4465 * @final 4466 * @private 4467 */ 4468 _mountComponentIntoNode: function( 4469 rootID, 4470 container, 4471 transaction, 4472 shouldReuseMarkup) { 4473 var markup = this.mountComponent(rootID, transaction, 0); 4474 mountImageIntoNode(markup, container, shouldReuseMarkup); 4475 }, 4476 4477 /** 4478 * Checks if this component is owned by the supplied `owner` component. 4479 * 4480 * @param {ReactComponent} owner Component to check. 4481 * @return {boolean} True if `owners` owns this component. 4482 * @final 4483 * @internal 4484 */ 4485 isOwnedBy: function(owner) { 4486 return this._owner === owner; 4487 }, 4488 4489 /** 4490 * Gets another component, that shares the same owner as this one, by ref. 4491 * 4492 * @param {string} ref of a sibling Component. 4493 * @return {?ReactComponent} the actual sibling Component. 4494 * @final 4495 * @internal 4496 */ 4497 getSiblingByRef: function(ref) { 4498 var owner = this._owner; 4499 if (!owner || !owner.refs) { 4500 return null; 4501 } 4502 return owner.refs[ref]; 4503 } 4504 } 4505 }; 4506 4507 module.exports = ReactComponent; 4508 4509 },{"./ReactCurrentOwner":31,"./ReactOwner":59,"./ReactUpdates":71,"./invariant":112,"./keyMirror":118,"./merge":121,"./monitorCodeUse":125}],28:[function(_dereq_,module,exports){ 4510 /** 4511 * Copyright 2013-2014 Facebook, Inc. 4512 * 4513 * Licensed under the Apache License, Version 2.0 (the "License"); 4514 * you may not use this file except in compliance with the License. 4515 * You may obtain a copy of the License at 4516 * 4517 * http://www.apache.org/licenses/LICENSE-2.0 4518 * 4519 * Unless required by applicable law or agreed to in writing, software 4520 * distributed under the License is distributed on an "AS IS" BASIS, 4521 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4522 * See the License for the specific language governing permissions and 4523 * limitations under the License. 4524 * 4525 * @providesModule ReactComponentBrowserEnvironment 4526 */ 4527 4528 /*jslint evil: true */ 4529 4530 "use strict"; 4531 4532 var ReactDOMIDOperations = _dereq_("./ReactDOMIDOperations"); 4533 var ReactMarkupChecksum = _dereq_("./ReactMarkupChecksum"); 4534 var ReactMount = _dereq_("./ReactMount"); 4535 var ReactPerf = _dereq_("./ReactPerf"); 4536 var ReactReconcileTransaction = _dereq_("./ReactReconcileTransaction"); 4537 4538 var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer"); 4539 var invariant = _dereq_("./invariant"); 4540 4541 4542 var ELEMENT_NODE_TYPE = 1; 4543 var DOC_NODE_TYPE = 9; 4544 4545 4546 /** 4547 * Abstracts away all functionality of `ReactComponent` requires knowledge of 4548 * the browser context. 4549 */ 4550 var ReactComponentBrowserEnvironment = { 4551 ReactReconcileTransaction: ReactReconcileTransaction, 4552 4553 BackendIDOperations: ReactDOMIDOperations, 4554 4555 /** 4556 * If a particular environment requires that some resources be cleaned up, 4557 * specify this in the injected Mixin. In the DOM, we would likely want to 4558 * purge any cached node ID lookups. 4559 * 4560 * @private 4561 */ 4562 unmountIDFromEnvironment: function(rootNodeID) { 4563 ReactMount.purgeID(rootNodeID); 4564 }, 4565 4566 /** 4567 * @param {string} markup Markup string to place into the DOM Element. 4568 * @param {DOMElement} container DOM Element to insert markup into. 4569 * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the 4570 * container if possible. 4571 */ 4572 mountImageIntoNode: ReactPerf.measure( 4573 'ReactComponentBrowserEnvironment', 4574 'mountImageIntoNode', 4575 function(markup, container, shouldReuseMarkup) { 4576 ("production" !== "development" ? invariant( 4577 container && ( 4578 container.nodeType === ELEMENT_NODE_TYPE || 4579 container.nodeType === DOC_NODE_TYPE 4580 ), 4581 'mountComponentIntoNode(...): Target container is not valid.' 4582 ) : invariant(container && ( 4583 container.nodeType === ELEMENT_NODE_TYPE || 4584 container.nodeType === DOC_NODE_TYPE 4585 ))); 4586 4587 if (shouldReuseMarkup) { 4588 if (ReactMarkupChecksum.canReuseMarkup( 4589 markup, 4590 getReactRootElementInContainer(container))) { 4591 return; 4592 } else { 4593 ("production" !== "development" ? invariant( 4594 container.nodeType !== DOC_NODE_TYPE, 4595 'You\'re trying to render a component to the document using ' + 4596 'server rendering but the checksum was invalid. This usually ' + 4597 'means you rendered a different component type or props on ' + 4598 'the client from the one on the server, or your render() ' + 4599 'methods are impure. React cannot handle this case due to ' + 4600 'cross-browser quirks by rendering at the document root. You ' + 4601 'should look for environment dependent code in your components ' + 4602 'and ensure the props are the same client and server side.' 4603 ) : invariant(container.nodeType !== DOC_NODE_TYPE)); 4604 4605 if ("production" !== "development") { 4606 console.warn( 4607 'React attempted to use reuse markup in a container but the ' + 4608 'checksum was invalid. This generally means that you are ' + 4609 'using server rendering and the markup generated on the ' + 4610 'server was not what the client was expecting. React injected' + 4611 'new markup to compensate which works but you have lost many ' + 4612 'of the benefits of server rendering. Instead, figure out ' + 4613 'why the markup being generated is different on the client ' + 4614 'or server.' 4615 ); 4616 } 4617 } 4618 } 4619 4620 ("production" !== "development" ? invariant( 4621 container.nodeType !== DOC_NODE_TYPE, 4622 'You\'re trying to render a component to the document but ' + 4623 'you didn\'t use server rendering. We can\'t do this ' + 4624 'without using server rendering due to cross-browser quirks. ' + 4625 'See renderComponentToString() for server rendering.' 4626 ) : invariant(container.nodeType !== DOC_NODE_TYPE)); 4627 4628 container.innerHTML = markup; 4629 } 4630 ) 4631 }; 4632 4633 module.exports = ReactComponentBrowserEnvironment; 4634 4635 },{"./ReactDOMIDOperations":36,"./ReactMarkupChecksum":54,"./ReactMount":55,"./ReactPerf":60,"./ReactReconcileTransaction":66,"./getReactRootElementInContainer":107,"./invariant":112}],29:[function(_dereq_,module,exports){ 4636 /** 4637 * Copyright 2013-2014 Facebook, Inc. 4638 * 4639 * Licensed under the Apache License, Version 2.0 (the "License"); 4640 * you may not use this file except in compliance with the License. 4641 * You may obtain a copy of the License at 4642 * 4643 * http://www.apache.org/licenses/LICENSE-2.0 4644 * 4645 * Unless required by applicable law or agreed to in writing, software 4646 * distributed under the License is distributed on an "AS IS" BASIS, 4647 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4648 * See the License for the specific language governing permissions and 4649 * limitations under the License. 4650 * 4651 * @providesModule ReactCompositeComponent 4652 */ 4653 4654 "use strict"; 4655 4656 var ReactComponent = _dereq_("./ReactComponent"); 4657 var ReactContext = _dereq_("./ReactContext"); 4658 var ReactCurrentOwner = _dereq_("./ReactCurrentOwner"); 4659 var ReactErrorUtils = _dereq_("./ReactErrorUtils"); 4660 var ReactOwner = _dereq_("./ReactOwner"); 4661 var ReactPerf = _dereq_("./ReactPerf"); 4662 var ReactPropTransferer = _dereq_("./ReactPropTransferer"); 4663 var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations"); 4664 var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames"); 4665 var ReactUpdates = _dereq_("./ReactUpdates"); 4666 4667 var instantiateReactComponent = _dereq_("./instantiateReactComponent"); 4668 var invariant = _dereq_("./invariant"); 4669 var keyMirror = _dereq_("./keyMirror"); 4670 var merge = _dereq_("./merge"); 4671 var mixInto = _dereq_("./mixInto"); 4672 var monitorCodeUse = _dereq_("./monitorCodeUse"); 4673 var objMap = _dereq_("./objMap"); 4674 var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); 4675 var warning = _dereq_("./warning"); 4676 4677 /** 4678 * Policies that describe methods in `ReactCompositeComponentInterface`. 4679 */ 4680 var SpecPolicy = keyMirror({ 4681 /** 4682 * These methods may be defined only once by the class specification or mixin. 4683 */ 4684 DEFINE_ONCE: null, 4685 /** 4686 * These methods may be defined by both the class specification and mixins. 4687 * Subsequent definitions will be chained. These methods must return void. 4688 */ 4689 DEFINE_MANY: null, 4690 /** 4691 * These methods are overriding the base ReactCompositeComponent class. 4692 */ 4693 OVERRIDE_BASE: null, 4694 /** 4695 * These methods are similar to DEFINE_MANY, except we assume they return 4696 * objects. We try to merge the keys of the return values of all the mixed in 4697 * functions. If there is a key conflict we throw. 4698 */ 4699 DEFINE_MANY_MERGED: null 4700 }); 4701 4702 4703 var injectedMixins = []; 4704 4705 /** 4706 * Composite components are higher-level components that compose other composite 4707 * or native components. 4708 * 4709 * To create a new type of `ReactCompositeComponent`, pass a specification of 4710 * your new class to `React.createClass`. The only requirement of your class 4711 * specification is that you implement a `render` method. 4712 * 4713 * var MyComponent = React.createClass({ 4714 * render: function() { 4715 * return <div>Hello World</div>; 4716 * } 4717 * }); 4718 * 4719 * The class specification supports a specific protocol of methods that have 4720 * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for 4721 * more the comprehensive protocol. Any other properties and methods in the 4722 * class specification will available on the prototype. 4723 * 4724 * @interface ReactCompositeComponentInterface 4725 * @internal 4726 */ 4727 var ReactCompositeComponentInterface = { 4728 4729 /** 4730 * An array of Mixin objects to include when defining your component. 4731 * 4732 * @type {array} 4733 * @optional 4734 */ 4735 mixins: SpecPolicy.DEFINE_MANY, 4736 4737 /** 4738 * An object containing properties and methods that should be defined on 4739 * the component's constructor instead of its prototype (static methods). 4740 * 4741 * @type {object} 4742 * @optional 4743 */ 4744 statics: SpecPolicy.DEFINE_MANY, 4745 4746 /** 4747 * Definition of prop types for this component. 4748 * 4749 * @type {object} 4750 * @optional 4751 */ 4752 propTypes: SpecPolicy.DEFINE_MANY, 4753 4754 /** 4755 * Definition of context types for this component. 4756 * 4757 * @type {object} 4758 * @optional 4759 */ 4760 contextTypes: SpecPolicy.DEFINE_MANY, 4761 4762 /** 4763 * Definition of context types this component sets for its children. 4764 * 4765 * @type {object} 4766 * @optional 4767 */ 4768 childContextTypes: SpecPolicy.DEFINE_MANY, 4769 4770 // ==== Definition methods ==== 4771 4772 /** 4773 * Invoked when the component is mounted. Values in the mapping will be set on 4774 * `this.props` if that prop is not specified (i.e. using an `in` check). 4775 * 4776 * This method is invoked before `getInitialState` and therefore cannot rely 4777 * on `this.state` or use `this.setState`. 4778 * 4779 * @return {object} 4780 * @optional 4781 */ 4782 getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, 4783 4784 /** 4785 * Invoked once before the component is mounted. The return value will be used 4786 * as the initial value of `this.state`. 4787 * 4788 * getInitialState: function() { 4789 * return { 4790 * isOn: false, 4791 * fooBaz: new BazFoo() 4792 * } 4793 * } 4794 * 4795 * @return {object} 4796 * @optional 4797 */ 4798 getInitialState: SpecPolicy.DEFINE_MANY_MERGED, 4799 4800 /** 4801 * @return {object} 4802 * @optional 4803 */ 4804 getChildContext: SpecPolicy.DEFINE_MANY_MERGED, 4805 4806 /** 4807 * Uses props from `this.props` and state from `this.state` to render the 4808 * structure of the component. 4809 * 4810 * No guarantees are made about when or how often this method is invoked, so 4811 * it must not have side effects. 4812 * 4813 * render: function() { 4814 * var name = this.props.name; 4815 * return <div>Hello, {name}!</div>; 4816 * } 4817 * 4818 * @return {ReactComponent} 4819 * @nosideeffects 4820 * @required 4821 */ 4822 render: SpecPolicy.DEFINE_ONCE, 4823 4824 4825 4826 // ==== Delegate methods ==== 4827 4828 /** 4829 * Invoked when the component is initially created and about to be mounted. 4830 * This may have side effects, but any external subscriptions or data created 4831 * by this method must be cleaned up in `componentWillUnmount`. 4832 * 4833 * @optional 4834 */ 4835 componentWillMount: SpecPolicy.DEFINE_MANY, 4836 4837 /** 4838 * Invoked when the component has been mounted and has a DOM representation. 4839 * However, there is no guarantee that the DOM node is in the document. 4840 * 4841 * Use this as an opportunity to operate on the DOM when the component has 4842 * been mounted (initialized and rendered) for the first time. 4843 * 4844 * @param {DOMElement} rootNode DOM element representing the component. 4845 * @optional 4846 */ 4847 componentDidMount: SpecPolicy.DEFINE_MANY, 4848 4849 /** 4850 * Invoked before the component receives new props. 4851 * 4852 * Use this as an opportunity to react to a prop transition by updating the 4853 * state using `this.setState`. Current props are accessed via `this.props`. 4854 * 4855 * componentWillReceiveProps: function(nextProps, nextContext) { 4856 * this.setState({ 4857 * likesIncreasing: nextProps.likeCount > this.props.likeCount 4858 * }); 4859 * } 4860 * 4861 * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop 4862 * transition may cause a state change, but the opposite is not true. If you 4863 * need it, you are probably looking for `componentWillUpdate`. 4864 * 4865 * @param {object} nextProps 4866 * @optional 4867 */ 4868 componentWillReceiveProps: SpecPolicy.DEFINE_MANY, 4869 4870 /** 4871 * Invoked while deciding if the component should be updated as a result of 4872 * receiving new props, state and/or context. 4873 * 4874 * Use this as an opportunity to `return false` when you're certain that the 4875 * transition to the new props/state/context will not require a component 4876 * update. 4877 * 4878 * shouldComponentUpdate: function(nextProps, nextState, nextContext) { 4879 * return !equal(nextProps, this.props) || 4880 * !equal(nextState, this.state) || 4881 * !equal(nextContext, this.context); 4882 * } 4883 * 4884 * @param {object} nextProps 4885 * @param {?object} nextState 4886 * @param {?object} nextContext 4887 * @return {boolean} True if the component should update. 4888 * @optional 4889 */ 4890 shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, 4891 4892 /** 4893 * Invoked when the component is about to update due to a transition from 4894 * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState` 4895 * and `nextContext`. 4896 * 4897 * Use this as an opportunity to perform preparation before an update occurs. 4898 * 4899 * NOTE: You **cannot** use `this.setState()` in this method. 4900 * 4901 * @param {object} nextProps 4902 * @param {?object} nextState 4903 * @param {?object} nextContext 4904 * @param {ReactReconcileTransaction} transaction 4905 * @optional 4906 */ 4907 componentWillUpdate: SpecPolicy.DEFINE_MANY, 4908 4909 /** 4910 * Invoked when the component's DOM representation has been updated. 4911 * 4912 * Use this as an opportunity to operate on the DOM when the component has 4913 * been updated. 4914 * 4915 * @param {object} prevProps 4916 * @param {?object} prevState 4917 * @param {?object} prevContext 4918 * @param {DOMElement} rootNode DOM element representing the component. 4919 * @optional 4920 */ 4921 componentDidUpdate: SpecPolicy.DEFINE_MANY, 4922 4923 /** 4924 * Invoked when the component is about to be removed from its parent and have 4925 * its DOM representation destroyed. 4926 * 4927 * Use this as an opportunity to deallocate any external resources. 4928 * 4929 * NOTE: There is no `componentDidUnmount` since your component will have been 4930 * destroyed by that point. 4931 * 4932 * @optional 4933 */ 4934 componentWillUnmount: SpecPolicy.DEFINE_MANY, 4935 4936 4937 4938 // ==== Advanced methods ==== 4939 4940 /** 4941 * Updates the component's currently mounted DOM representation. 4942 * 4943 * By default, this implements React's rendering and reconciliation algorithm. 4944 * Sophisticated clients may wish to override this. 4945 * 4946 * @param {ReactReconcileTransaction} transaction 4947 * @internal 4948 * @overridable 4949 */ 4950 updateComponent: SpecPolicy.OVERRIDE_BASE 4951 4952 }; 4953 4954 /** 4955 * Mapping from class specification keys to special processing functions. 4956 * 4957 * Although these are declared like instance properties in the specification 4958 * when defining classes using `React.createClass`, they are actually static 4959 * and are accessible on the constructor instead of the prototype. Despite 4960 * being static, they must be defined outside of the "statics" key under 4961 * which all other static methods are defined. 4962 */ 4963 var RESERVED_SPEC_KEYS = { 4964 displayName: function(ConvenienceConstructor, displayName) { 4965 ConvenienceConstructor.componentConstructor.displayName = displayName; 4966 }, 4967 mixins: function(ConvenienceConstructor, mixins) { 4968 if (mixins) { 4969 for (var i = 0; i < mixins.length; i++) { 4970 mixSpecIntoComponent(ConvenienceConstructor, mixins[i]); 4971 } 4972 } 4973 }, 4974 childContextTypes: function(ConvenienceConstructor, childContextTypes) { 4975 var Constructor = ConvenienceConstructor.componentConstructor; 4976 validateTypeDef( 4977 Constructor, 4978 childContextTypes, 4979 ReactPropTypeLocations.childContext 4980 ); 4981 Constructor.childContextTypes = merge( 4982 Constructor.childContextTypes, 4983 childContextTypes 4984 ); 4985 }, 4986 contextTypes: function(ConvenienceConstructor, contextTypes) { 4987 var Constructor = ConvenienceConstructor.componentConstructor; 4988 validateTypeDef( 4989 Constructor, 4990 contextTypes, 4991 ReactPropTypeLocations.context 4992 ); 4993 Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes); 4994 }, 4995 propTypes: function(ConvenienceConstructor, propTypes) { 4996 var Constructor = ConvenienceConstructor.componentConstructor; 4997 validateTypeDef( 4998 Constructor, 4999 propTypes, 5000 ReactPropTypeLocations.prop 5001 ); 5002 Constructor.propTypes = merge(Constructor.propTypes, propTypes); 5003 }, 5004 statics: function(ConvenienceConstructor, statics) { 5005 mixStaticSpecIntoComponent(ConvenienceConstructor, statics); 5006 } 5007 }; 5008 5009 function validateTypeDef(Constructor, typeDef, location) { 5010 for (var propName in typeDef) { 5011 if (typeDef.hasOwnProperty(propName)) { 5012 ("production" !== "development" ? invariant( 5013 typeof typeDef[propName] == 'function', 5014 '%s: %s type `%s` is invalid; it must be a function, usually from ' + 5015 'React.PropTypes.', 5016 Constructor.displayName || 'ReactCompositeComponent', 5017 ReactPropTypeLocationNames[location], 5018 propName 5019 ) : invariant(typeof typeDef[propName] == 'function')); 5020 } 5021 } 5022 } 5023 5024 function validateMethodOverride(proto, name) { 5025 var specPolicy = ReactCompositeComponentInterface[name]; 5026 5027 // Disallow overriding of base class methods unless explicitly allowed. 5028 if (ReactCompositeComponentMixin.hasOwnProperty(name)) { 5029 ("production" !== "development" ? invariant( 5030 specPolicy === SpecPolicy.OVERRIDE_BASE, 5031 'ReactCompositeComponentInterface: You are attempting to override ' + 5032 '`%s` from your class specification. Ensure that your method names ' + 5033 'do not overlap with React methods.', 5034 name 5035 ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE)); 5036 } 5037 5038 // Disallow defining methods more than once unless explicitly allowed. 5039 if (proto.hasOwnProperty(name)) { 5040 ("production" !== "development" ? invariant( 5041 specPolicy === SpecPolicy.DEFINE_MANY || 5042 specPolicy === SpecPolicy.DEFINE_MANY_MERGED, 5043 'ReactCompositeComponentInterface: You are attempting to define ' + 5044 '`%s` on your component more than once. This conflict may be due ' + 5045 'to a mixin.', 5046 name 5047 ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY || 5048 specPolicy === SpecPolicy.DEFINE_MANY_MERGED)); 5049 } 5050 } 5051 5052 function validateLifeCycleOnReplaceState(instance) { 5053 var compositeLifeCycleState = instance._compositeLifeCycleState; 5054 ("production" !== "development" ? invariant( 5055 instance.isMounted() || 5056 compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 5057 'replaceState(...): Can only update a mounted or mounting component.' 5058 ) : invariant(instance.isMounted() || 5059 compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); 5060 ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE, 5061 'replaceState(...): Cannot update during an existing state transition ' + 5062 '(such as within `render`). This could potentially cause an infinite ' + 5063 'loop so it is forbidden.' 5064 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE)); 5065 ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 5066 'replaceState(...): Cannot update while unmounting component. This ' + 5067 'usually means you called setState() on an unmounted component.' 5068 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); 5069 } 5070 5071 /** 5072 * Custom version of `mixInto` which handles policy validation and reserved 5073 * specification keys when building `ReactCompositeComponent` classses. 5074 */ 5075 function mixSpecIntoComponent(ConvenienceConstructor, spec) { 5076 ("production" !== "development" ? invariant( 5077 !isValidClass(spec), 5078 'ReactCompositeComponent: You\'re attempting to ' + 5079 'use a component class as a mixin. Instead, just use a regular object.' 5080 ) : invariant(!isValidClass(spec))); 5081 ("production" !== "development" ? invariant( 5082 !ReactComponent.isValidComponent(spec), 5083 'ReactCompositeComponent: You\'re attempting to ' + 5084 'use a component as a mixin. Instead, just use a regular object.' 5085 ) : invariant(!ReactComponent.isValidComponent(spec))); 5086 5087 var Constructor = ConvenienceConstructor.componentConstructor; 5088 var proto = Constructor.prototype; 5089 for (var name in spec) { 5090 var property = spec[name]; 5091 if (!spec.hasOwnProperty(name)) { 5092 continue; 5093 } 5094 5095 validateMethodOverride(proto, name); 5096 5097 if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { 5098 RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property); 5099 } else { 5100 // Setup methods on prototype: 5101 // The following member methods should not be automatically bound: 5102 // 1. Expected ReactCompositeComponent methods (in the "interface"). 5103 // 2. Overridden methods (that were mixed in). 5104 var isCompositeComponentMethod = name in ReactCompositeComponentInterface; 5105 var isInherited = name in proto; 5106 var markedDontBind = property && property.__reactDontBind; 5107 var isFunction = typeof property === 'function'; 5108 var shouldAutoBind = 5109 isFunction && 5110 !isCompositeComponentMethod && 5111 !isInherited && 5112 !markedDontBind; 5113 5114 if (shouldAutoBind) { 5115 if (!proto.__reactAutoBindMap) { 5116 proto.__reactAutoBindMap = {}; 5117 } 5118 proto.__reactAutoBindMap[name] = property; 5119 proto[name] = property; 5120 } else { 5121 if (isInherited) { 5122 // For methods which are defined more than once, call the existing 5123 // methods before calling the new property. 5124 if (ReactCompositeComponentInterface[name] === 5125 SpecPolicy.DEFINE_MANY_MERGED) { 5126 proto[name] = createMergedResultFunction(proto[name], property); 5127 } else { 5128 proto[name] = createChainedFunction(proto[name], property); 5129 } 5130 } else { 5131 proto[name] = property; 5132 } 5133 } 5134 } 5135 } 5136 } 5137 5138 function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) { 5139 if (!statics) { 5140 return; 5141 } 5142 for (var name in statics) { 5143 var property = statics[name]; 5144 if (!statics.hasOwnProperty(name)) { 5145 return; 5146 } 5147 5148 var isInherited = name in ConvenienceConstructor; 5149 var result = property; 5150 if (isInherited) { 5151 var existingProperty = ConvenienceConstructor[name]; 5152 var existingType = typeof existingProperty; 5153 var propertyType = typeof property; 5154 ("production" !== "development" ? invariant( 5155 existingType === 'function' && propertyType === 'function', 5156 'ReactCompositeComponent: You are attempting to define ' + 5157 '`%s` on your component more than once, but that is only supported ' + 5158 'for functions, which are chained together. This conflict may be ' + 5159 'due to a mixin.', 5160 name 5161 ) : invariant(existingType === 'function' && propertyType === 'function')); 5162 result = createChainedFunction(existingProperty, property); 5163 } 5164 ConvenienceConstructor[name] = result; 5165 ConvenienceConstructor.componentConstructor[name] = result; 5166 } 5167 } 5168 5169 /** 5170 * Merge two objects, but throw if both contain the same key. 5171 * 5172 * @param {object} one The first object, which is mutated. 5173 * @param {object} two The second object 5174 * @return {object} one after it has been mutated to contain everything in two. 5175 */ 5176 function mergeObjectsWithNoDuplicateKeys(one, two) { 5177 ("production" !== "development" ? invariant( 5178 one && two && typeof one === 'object' && typeof two === 'object', 5179 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects' 5180 ) : invariant(one && two && typeof one === 'object' && typeof two === 'object')); 5181 5182 objMap(two, function(value, key) { 5183 ("production" !== "development" ? invariant( 5184 one[key] === undefined, 5185 'mergeObjectsWithNoDuplicateKeys(): ' + 5186 'Tried to merge two objects with the same key: %s', 5187 key 5188 ) : invariant(one[key] === undefined)); 5189 one[key] = value; 5190 }); 5191 return one; 5192 } 5193 5194 /** 5195 * Creates a function that invokes two functions and merges their return values. 5196 * 5197 * @param {function} one Function to invoke first. 5198 * @param {function} two Function to invoke second. 5199 * @return {function} Function that invokes the two argument functions. 5200 * @private 5201 */ 5202 function createMergedResultFunction(one, two) { 5203 return function mergedResult() { 5204 var a = one.apply(this, arguments); 5205 var b = two.apply(this, arguments); 5206 if (a == null) { 5207 return b; 5208 } else if (b == null) { 5209 return a; 5210 } 5211 return mergeObjectsWithNoDuplicateKeys(a, b); 5212 }; 5213 } 5214 5215 /** 5216 * Creates a function that invokes two functions and ignores their return vales. 5217 * 5218 * @param {function} one Function to invoke first. 5219 * @param {function} two Function to invoke second. 5220 * @return {function} Function that invokes the two argument functions. 5221 * @private 5222 */ 5223 function createChainedFunction(one, two) { 5224 return function chainedFunction() { 5225 one.apply(this, arguments); 5226 two.apply(this, arguments); 5227 }; 5228 } 5229 5230 if ("production" !== "development") { 5231 5232 var unmountedPropertyWhitelist = { 5233 constructor: true, 5234 construct: true, 5235 isOwnedBy: true, // should be deprecated but can have code mod (internal) 5236 type: true, 5237 props: true, 5238 // currently private but belong on the descriptor and are valid for use 5239 // inside the framework: 5240 __keyValidated__: true, 5241 _owner: true, 5242 _currentContext: true 5243 }; 5244 5245 var componentInstanceProperties = { 5246 __keyValidated__: true, 5247 __keySetters: true, 5248 _compositeLifeCycleState: true, 5249 _currentContext: true, 5250 _defaultProps: true, 5251 _instance: true, 5252 _lifeCycleState: true, 5253 _mountDepth: true, 5254 _owner: true, 5255 _pendingCallbacks: true, 5256 _pendingContext: true, 5257 _pendingForceUpdate: true, 5258 _pendingOwner: true, 5259 _pendingProps: true, 5260 _pendingState: true, 5261 _renderedComponent: true, 5262 _rootNodeID: true, 5263 context: true, 5264 props: true, 5265 refs: true, 5266 state: true, 5267 5268 // These are known instance properties coming from other sources 5269 _pendingQueries: true, 5270 _queryPropListeners: true, 5271 queryParams: true 5272 5273 }; 5274 5275 var hasWarnedOnComponentType = {}; 5276 5277 var warningStackCounter = 0; 5278 5279 var issueMembraneWarning = function(instance, key) { 5280 var isWhitelisted = unmountedPropertyWhitelist.hasOwnProperty(key); 5281 if (warningStackCounter > 0 || isWhitelisted) { 5282 return; 5283 } 5284 var name = instance.constructor.displayName || 'Unknown'; 5285 var owner = ReactCurrentOwner.current; 5286 var ownerName = (owner && owner.constructor.displayName) || 'Unknown'; 5287 var warningKey = key + '|' + name + '|' + ownerName; 5288 if (hasWarnedOnComponentType.hasOwnProperty(warningKey)) { 5289 // We have already warned for this combination. Skip it this time. 5290 return; 5291 } 5292 hasWarnedOnComponentType[warningKey] = true; 5293 5294 var context = owner ? ' in ' + ownerName + '.' : ' at the top level.'; 5295 var staticMethodExample = '<' + name + ' />.type.' + key + '(...)'; 5296 5297 monitorCodeUse('react_descriptor_property_access', { component: name }); 5298 console.warn( 5299 'Invalid access to component property "' + key + '" on ' + name + 5300 context + ' See http://fb.me/react-warning-descriptors .' + 5301 ' Use a static method instead: ' + staticMethodExample 5302 ); 5303 }; 5304 5305 var wrapInMembraneFunction = function(fn, thisBinding) { 5306 if (fn.__reactMembraneFunction && fn.__reactMembraneSelf === thisBinding) { 5307 return fn.__reactMembraneFunction; 5308 } 5309 return fn.__reactMembraneFunction = function() { 5310 /** 5311 * By getting this function, you've already received a warning. The 5312 * internals of this function will likely cause more warnings. To avoid 5313 * Spamming too much we disable any warning triggered inside of this 5314 * stack. 5315 */ 5316 warningStackCounter++; 5317 try { 5318 // If the this binding is unchanged, we defer to the real component. 5319 // This is important to keep some referential integrity in the 5320 // internals. E.g. owner equality check. 5321 var self = this === thisBinding ? this.__realComponentInstance : this; 5322 return fn.apply(self, arguments); 5323 } finally { 5324 warningStackCounter--; 5325 } 5326 }; 5327 }; 5328 5329 var defineMembraneProperty = function(membrane, prototype, key) { 5330 Object.defineProperty(membrane, key, { 5331 5332 configurable: false, 5333 enumerable: true, 5334 5335 get: function() { 5336 if (this === membrane) { 5337 // We're allowed to access the prototype directly. 5338 return prototype[key]; 5339 } 5340 issueMembraneWarning(this, key); 5341 5342 var realValue = this.__realComponentInstance[key]; 5343 // If the real value is a function, we need to provide a wrapper that 5344 // disables nested warnings. The properties type and constructors are 5345 // expected to the be constructors and therefore is often use with an 5346 // equality check and we shouldn't try to rebind those. 5347 if (typeof realValue === 'function' && 5348 key !== 'type' && 5349 key !== 'constructor') { 5350 return wrapInMembraneFunction(realValue, this); 5351 } 5352 return realValue; 5353 }, 5354 5355 set: function(value) { 5356 if (this === membrane) { 5357 // We're allowed to set a value on the prototype directly. 5358 prototype[key] = value; 5359 return; 5360 } 5361 issueMembraneWarning(this, key); 5362 this.__realComponentInstance[key] = value; 5363 } 5364 5365 }); 5366 }; 5367 5368 /** 5369 * Creates a membrane prototype which wraps the original prototype. If any 5370 * property is accessed in an unmounted state, a warning is issued. 5371 * 5372 * @param {object} prototype Original prototype. 5373 * @return {object} The membrane prototype. 5374 * @private 5375 */ 5376 var createMountWarningMembrane = function(prototype) { 5377 var membrane = {}; 5378 var key; 5379 for (key in prototype) { 5380 defineMembraneProperty(membrane, prototype, key); 5381 } 5382 // These are properties that goes into the instance but not the prototype. 5383 // We can create the membrane on the prototype even though this will 5384 // result in a faulty hasOwnProperty check it's better perf. 5385 for (key in componentInstanceProperties) { 5386 if (componentInstanceProperties.hasOwnProperty(key) && 5387 !(key in prototype)) { 5388 defineMembraneProperty(membrane, prototype, key); 5389 } 5390 } 5391 return membrane; 5392 }; 5393 5394 /** 5395 * Creates a membrane constructor which wraps the component that gets mounted. 5396 * 5397 * @param {function} constructor Original constructor. 5398 * @return {function} The membrane constructor. 5399 * @private 5400 */ 5401 var createDescriptorProxy = function(constructor) { 5402 try { 5403 var ProxyConstructor = function() { 5404 this.__realComponentInstance = new constructor(); 5405 5406 // We can only safely pass through known instance variables. Unknown 5407 // expandos are not safe. Use the real mounted instance to avoid this 5408 // problem if it blows something up. 5409 Object.freeze(this); 5410 }; 5411 5412 ProxyConstructor.prototype = createMountWarningMembrane( 5413 constructor.prototype 5414 ); 5415 5416 return ProxyConstructor; 5417 } catch(x) { 5418 // In IE8 define property will fail on non-DOM objects. If anything in 5419 // the membrane creation fails, we'll bail out and just use the plain 5420 // constructor without warnings. 5421 return constructor; 5422 } 5423 }; 5424 5425 } 5426 5427 /** 5428 * `ReactCompositeComponent` maintains an auxiliary life cycle state in 5429 * `this._compositeLifeCycleState` (which can be null). 5430 * 5431 * This is different from the life cycle state maintained by `ReactComponent` in 5432 * `this._lifeCycleState`. The following diagram shows how the states overlap in 5433 * time. There are times when the CompositeLifeCycle is null - at those times it 5434 * is only meaningful to look at ComponentLifeCycle alone. 5435 * 5436 * Top Row: ReactComponent.ComponentLifeCycle 5437 * Low Row: ReactComponent.CompositeLifeCycle 5438 * 5439 * +-------+------------------------------------------------------+--------+ 5440 * | UN | MOUNTED | UN | 5441 * |MOUNTED| | MOUNTED| 5442 * +-------+------------------------------------------------------+--------+ 5443 * | ^--------+ +------+ +------+ +------+ +--------^ | 5444 * | | | | | | | | | | | | 5445 * | 0--|MOUNTING|-0-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 | 5446 * | | | |PROPS | | PROPS| | STATE| |MOUNTING| | 5447 * | | | | | | | | | | | | 5448 * | | | | | | | | | | | | 5449 * | +--------+ +------+ +------+ +------+ +--------+ | 5450 * | | | | 5451 * +-------+------------------------------------------------------+--------+ 5452 */ 5453 var CompositeLifeCycle = keyMirror({ 5454 /** 5455 * Components in the process of being mounted respond to state changes 5456 * differently. 5457 */ 5458 MOUNTING: null, 5459 /** 5460 * Components in the process of being unmounted are guarded against state 5461 * changes. 5462 */ 5463 UNMOUNTING: null, 5464 /** 5465 * Components that are mounted and receiving new props respond to state 5466 * changes differently. 5467 */ 5468 RECEIVING_PROPS: null, 5469 /** 5470 * Components that are mounted and receiving new state are guarded against 5471 * additional state changes. 5472 */ 5473 RECEIVING_STATE: null 5474 }); 5475 5476 /** 5477 * @lends {ReactCompositeComponent.prototype} 5478 */ 5479 var ReactCompositeComponentMixin = { 5480 5481 /** 5482 * Base constructor for all composite component. 5483 * 5484 * @param {?object} initialProps 5485 * @param {*} children 5486 * @final 5487 * @internal 5488 */ 5489 construct: function(initialProps, children) { 5490 // Children can be either an array or more than one argument 5491 ReactComponent.Mixin.construct.apply(this, arguments); 5492 ReactOwner.Mixin.construct.apply(this, arguments); 5493 5494 this.state = null; 5495 this._pendingState = null; 5496 5497 this.context = null; 5498 this._currentContext = ReactContext.current; 5499 this._pendingContext = null; 5500 5501 // The descriptor that was used to instantiate this component. Will be 5502 // set by the instantiator instead of the constructor since this 5503 // constructor is currently used by both instances and descriptors. 5504 this._descriptor = null; 5505 5506 this._compositeLifeCycleState = null; 5507 }, 5508 5509 /** 5510 * Components in the intermediate state now has cyclic references. To avoid 5511 * breaking JSON serialization we expose a custom JSON format. 5512 * @return {object} JSON compatible representation. 5513 * @internal 5514 * @final 5515 */ 5516 toJSON: function() { 5517 return { type: this.type, props: this.props }; 5518 }, 5519 5520 /** 5521 * Checks whether or not this composite component is mounted. 5522 * @return {boolean} True if mounted, false otherwise. 5523 * @protected 5524 * @final 5525 */ 5526 isMounted: function() { 5527 return ReactComponent.Mixin.isMounted.call(this) && 5528 this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING; 5529 }, 5530 5531 /** 5532 * Initializes the component, renders markup, and registers event listeners. 5533 * 5534 * @param {string} rootID DOM ID of the root node. 5535 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 5536 * @param {number} mountDepth number of components in the owner hierarchy 5537 * @return {?string} Rendered markup to be inserted into the DOM. 5538 * @final 5539 * @internal 5540 */ 5541 mountComponent: ReactPerf.measure( 5542 'ReactCompositeComponent', 5543 'mountComponent', 5544 function(rootID, transaction, mountDepth) { 5545 ReactComponent.Mixin.mountComponent.call( 5546 this, 5547 rootID, 5548 transaction, 5549 mountDepth 5550 ); 5551 this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; 5552 5553 this.context = this._processContext(this._currentContext); 5554 this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null; 5555 this.props = this._processProps(this.props); 5556 5557 if (this.__reactAutoBindMap) { 5558 this._bindAutoBindMethods(); 5559 } 5560 5561 this.state = this.getInitialState ? this.getInitialState() : null; 5562 ("production" !== "development" ? invariant( 5563 typeof this.state === 'object' && !Array.isArray(this.state), 5564 '%s.getInitialState(): must return an object or null', 5565 this.constructor.displayName || 'ReactCompositeComponent' 5566 ) : invariant(typeof this.state === 'object' && !Array.isArray(this.state))); 5567 5568 this._pendingState = null; 5569 this._pendingForceUpdate = false; 5570 5571 if (this.componentWillMount) { 5572 this.componentWillMount(); 5573 // When mounting, calls to `setState` by `componentWillMount` will set 5574 // `this._pendingState` without triggering a re-render. 5575 if (this._pendingState) { 5576 this.state = this._pendingState; 5577 this._pendingState = null; 5578 } 5579 } 5580 5581 this._renderedComponent = instantiateReactComponent( 5582 this._renderValidatedComponent() 5583 ); 5584 5585 // Done with mounting, `setState` will now trigger UI changes. 5586 this._compositeLifeCycleState = null; 5587 var markup = this._renderedComponent.mountComponent( 5588 rootID, 5589 transaction, 5590 mountDepth + 1 5591 ); 5592 if (this.componentDidMount) { 5593 transaction.getReactMountReady().enqueue(this, this.componentDidMount); 5594 } 5595 return markup; 5596 } 5597 ), 5598 5599 /** 5600 * Releases any resources allocated by `mountComponent`. 5601 * 5602 * @final 5603 * @internal 5604 */ 5605 unmountComponent: function() { 5606 this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING; 5607 if (this.componentWillUnmount) { 5608 this.componentWillUnmount(); 5609 } 5610 this._compositeLifeCycleState = null; 5611 5612 this._defaultProps = null; 5613 5614 this._renderedComponent.unmountComponent(); 5615 this._renderedComponent = null; 5616 5617 ReactComponent.Mixin.unmountComponent.call(this); 5618 5619 // Some existing components rely on this.props even after they've been 5620 // destroyed (in event handlers). 5621 // TODO: this.props = null; 5622 // TODO: this.state = null; 5623 }, 5624 5625 /** 5626 * Sets a subset of the state. Always use this or `replaceState` to mutate 5627 * state. You should treat `this.state` as immutable. 5628 * 5629 * There is no guarantee that `this.state` will be immediately updated, so 5630 * accessing `this.state` after calling this method may return the old value. 5631 * 5632 * There is no guarantee that calls to `setState` will run synchronously, 5633 * as they may eventually be batched together. You can provide an optional 5634 * callback that will be executed when the call to setState is actually 5635 * completed. 5636 * 5637 * @param {object} partialState Next partial state to be merged with state. 5638 * @param {?function} callback Called after state is updated. 5639 * @final 5640 * @protected 5641 */ 5642 setState: function(partialState, callback) { 5643 ("production" !== "development" ? invariant( 5644 typeof partialState === 'object' || partialState == null, 5645 'setState(...): takes an object of state variables to update.' 5646 ) : invariant(typeof partialState === 'object' || partialState == null)); 5647 if ("production" !== "development") { 5648 ("production" !== "development" ? warning( 5649 partialState != null, 5650 'setState(...): You passed an undefined or null state object; ' + 5651 'instead, use forceUpdate().' 5652 ) : null); 5653 } 5654 // Merge with `_pendingState` if it exists, otherwise with existing state. 5655 this.replaceState( 5656 merge(this._pendingState || this.state, partialState), 5657 callback 5658 ); 5659 }, 5660 5661 /** 5662 * Replaces all of the state. Always use this or `setState` to mutate state. 5663 * You should treat `this.state` as immutable. 5664 * 5665 * There is no guarantee that `this.state` will be immediately updated, so 5666 * accessing `this.state` after calling this method may return the old value. 5667 * 5668 * @param {object} completeState Next state. 5669 * @param {?function} callback Called after state is updated. 5670 * @final 5671 * @protected 5672 */ 5673 replaceState: function(completeState, callback) { 5674 validateLifeCycleOnReplaceState(this); 5675 this._pendingState = completeState; 5676 ReactUpdates.enqueueUpdate(this, callback); 5677 }, 5678 5679 /** 5680 * Filters the context object to only contain keys specified in 5681 * `contextTypes`, and asserts that they are valid. 5682 * 5683 * @param {object} context 5684 * @return {?object} 5685 * @private 5686 */ 5687 _processContext: function(context) { 5688 var maskedContext = null; 5689 var contextTypes = this.constructor.contextTypes; 5690 if (contextTypes) { 5691 maskedContext = {}; 5692 for (var contextName in contextTypes) { 5693 maskedContext[contextName] = context[contextName]; 5694 } 5695 if ("production" !== "development") { 5696 this._checkPropTypes( 5697 contextTypes, 5698 maskedContext, 5699 ReactPropTypeLocations.context 5700 ); 5701 } 5702 } 5703 return maskedContext; 5704 }, 5705 5706 /** 5707 * @param {object} currentContext 5708 * @return {object} 5709 * @private 5710 */ 5711 _processChildContext: function(currentContext) { 5712 var childContext = this.getChildContext && this.getChildContext(); 5713 var displayName = this.constructor.displayName || 'ReactCompositeComponent'; 5714 if (childContext) { 5715 ("production" !== "development" ? invariant( 5716 typeof this.constructor.childContextTypes === 'object', 5717 '%s.getChildContext(): childContextTypes must be defined in order to ' + 5718 'use getChildContext().', 5719 displayName 5720 ) : invariant(typeof this.constructor.childContextTypes === 'object')); 5721 if ("production" !== "development") { 5722 this._checkPropTypes( 5723 this.constructor.childContextTypes, 5724 childContext, 5725 ReactPropTypeLocations.childContext 5726 ); 5727 } 5728 for (var name in childContext) { 5729 ("production" !== "development" ? invariant( 5730 name in this.constructor.childContextTypes, 5731 '%s.getChildContext(): key "%s" is not defined in childContextTypes.', 5732 displayName, 5733 name 5734 ) : invariant(name in this.constructor.childContextTypes)); 5735 } 5736 return merge(currentContext, childContext); 5737 } 5738 return currentContext; 5739 }, 5740 5741 /** 5742 * Processes props by setting default values for unspecified props and 5743 * asserting that the props are valid. Does not mutate its argument; returns 5744 * a new props object with defaults merged in. 5745 * 5746 * @param {object} newProps 5747 * @return {object} 5748 * @private 5749 */ 5750 _processProps: function(newProps) { 5751 var props = merge(newProps); 5752 var defaultProps = this._defaultProps; 5753 for (var propName in defaultProps) { 5754 if (typeof props[propName] === 'undefined') { 5755 props[propName] = defaultProps[propName]; 5756 } 5757 } 5758 if ("production" !== "development") { 5759 var propTypes = this.constructor.propTypes; 5760 if (propTypes) { 5761 this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop); 5762 } 5763 } 5764 return props; 5765 }, 5766 5767 /** 5768 * Assert that the props are valid 5769 * 5770 * @param {object} propTypes Map of prop name to a ReactPropType 5771 * @param {object} props 5772 * @param {string} location e.g. "prop", "context", "child context" 5773 * @private 5774 */ 5775 _checkPropTypes: function(propTypes, props, location) { 5776 var componentName = this.constructor.displayName; 5777 for (var propName in propTypes) { 5778 if (propTypes.hasOwnProperty(propName)) { 5779 propTypes[propName](props, propName, componentName, location); 5780 } 5781 } 5782 }, 5783 5784 performUpdateIfNecessary: function() { 5785 var compositeLifeCycleState = this._compositeLifeCycleState; 5786 // Do not trigger a state transition if we are in the middle of mounting or 5787 // receiving props because both of those will already be doing this. 5788 if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING || 5789 compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) { 5790 return; 5791 } 5792 ReactComponent.Mixin.performUpdateIfNecessary.call(this); 5793 }, 5794 5795 /** 5796 * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is 5797 * set, update the component. 5798 * 5799 * @param {ReactReconcileTransaction} transaction 5800 * @internal 5801 */ 5802 _performUpdateIfNecessary: function(transaction) { 5803 if (this._pendingProps == null && 5804 this._pendingState == null && 5805 this._pendingContext == null && 5806 !this._pendingForceUpdate) { 5807 return; 5808 } 5809 5810 var nextFullContext = this._pendingContext || this._currentContext; 5811 var nextContext = this._processContext(nextFullContext); 5812 this._pendingContext = null; 5813 5814 var nextProps = this.props; 5815 if (this._pendingProps != null) { 5816 nextProps = this._processProps(this._pendingProps); 5817 this._pendingProps = null; 5818 5819 this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS; 5820 if (this.componentWillReceiveProps) { 5821 this.componentWillReceiveProps(nextProps, nextContext); 5822 } 5823 } 5824 5825 this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE; 5826 5827 // Unlike props, state, and context, we specifically don't want to set 5828 // _pendingOwner to null here because it's possible for a component to have 5829 // a null owner, so we instead make `this._owner === this._pendingOwner` 5830 // mean that there's no owner change pending. 5831 var nextOwner = this._pendingOwner; 5832 5833 var nextState = this._pendingState || this.state; 5834 this._pendingState = null; 5835 5836 try { 5837 if (this._pendingForceUpdate || 5838 !this.shouldComponentUpdate || 5839 this.shouldComponentUpdate(nextProps, nextState, nextContext)) { 5840 this._pendingForceUpdate = false; 5841 // Will set `this.props`, `this.state` and `this.context`. 5842 this._performComponentUpdate( 5843 nextProps, 5844 nextOwner, 5845 nextState, 5846 nextFullContext, 5847 nextContext, 5848 transaction 5849 ); 5850 } else { 5851 // If it's determined that a component should not update, we still want 5852 // to set props and state. 5853 this.props = nextProps; 5854 this._owner = nextOwner; 5855 this.state = nextState; 5856 this._currentContext = nextFullContext; 5857 this.context = nextContext; 5858 } 5859 } finally { 5860 this._compositeLifeCycleState = null; 5861 } 5862 }, 5863 5864 /** 5865 * Merges new props and state, notifies delegate methods of update and 5866 * performs update. 5867 * 5868 * @param {object} nextProps Next object to set as properties. 5869 * @param {?ReactComponent} nextOwner Next component to set as owner 5870 * @param {?object} nextState Next object to set as state. 5871 * @param {?object} nextFullContext Next object to set as _currentContext. 5872 * @param {?object} nextContext Next object to set as context. 5873 * @param {ReactReconcileTransaction} transaction 5874 * @private 5875 */ 5876 _performComponentUpdate: function( 5877 nextProps, 5878 nextOwner, 5879 nextState, 5880 nextFullContext, 5881 nextContext, 5882 transaction 5883 ) { 5884 var prevProps = this.props; 5885 var prevOwner = this._owner; 5886 var prevState = this.state; 5887 var prevContext = this.context; 5888 5889 if (this.componentWillUpdate) { 5890 this.componentWillUpdate(nextProps, nextState, nextContext); 5891 } 5892 5893 this.props = nextProps; 5894 this._owner = nextOwner; 5895 this.state = nextState; 5896 this._currentContext = nextFullContext; 5897 this.context = nextContext; 5898 5899 this.updateComponent( 5900 transaction, 5901 prevProps, 5902 prevOwner, 5903 prevState, 5904 prevContext 5905 ); 5906 5907 if (this.componentDidUpdate) { 5908 transaction.getReactMountReady().enqueue( 5909 this, 5910 this.componentDidUpdate.bind(this, prevProps, prevState, prevContext) 5911 ); 5912 } 5913 }, 5914 5915 receiveComponent: function(nextComponent, transaction) { 5916 if (nextComponent === this._descriptor) { 5917 // Since props and context are immutable after the component is 5918 // mounted, we can do a cheap identity compare here to determine 5919 // if this is a superfluous reconcile. 5920 return; 5921 } 5922 5923 // Update the descriptor that was last used by this component instance 5924 this._descriptor = nextComponent; 5925 5926 this._pendingContext = nextComponent._currentContext; 5927 ReactComponent.Mixin.receiveComponent.call( 5928 this, 5929 nextComponent, 5930 transaction 5931 ); 5932 }, 5933 5934 /** 5935 * Updates the component's currently mounted DOM representation. 5936 * 5937 * By default, this implements React's rendering and reconciliation algorithm. 5938 * Sophisticated clients may wish to override this. 5939 * 5940 * @param {ReactReconcileTransaction} transaction 5941 * @param {object} prevProps 5942 * @param {?ReactComponent} prevOwner 5943 * @param {?object} prevState 5944 * @param {?object} prevContext 5945 * @internal 5946 * @overridable 5947 */ 5948 updateComponent: ReactPerf.measure( 5949 'ReactCompositeComponent', 5950 'updateComponent', 5951 function(transaction, prevProps, prevOwner, prevState, prevContext) { 5952 ReactComponent.Mixin.updateComponent.call( 5953 this, 5954 transaction, 5955 prevProps, 5956 prevOwner 5957 ); 5958 5959 5960 var prevComponentInstance = this._renderedComponent; 5961 var nextComponent = this._renderValidatedComponent(); 5962 if (shouldUpdateReactComponent(prevComponentInstance, nextComponent)) { 5963 prevComponentInstance.receiveComponent(nextComponent, transaction); 5964 } else { 5965 // These two IDs are actually the same! But nothing should rely on that. 5966 var thisID = this._rootNodeID; 5967 var prevComponentID = prevComponentInstance._rootNodeID; 5968 prevComponentInstance.unmountComponent(); 5969 this._renderedComponent = instantiateReactComponent(nextComponent); 5970 var nextMarkup = this._renderedComponent.mountComponent( 5971 thisID, 5972 transaction, 5973 this._mountDepth + 1 5974 ); 5975 ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID( 5976 prevComponentID, 5977 nextMarkup 5978 ); 5979 } 5980 } 5981 ), 5982 5983 /** 5984 * Forces an update. This should only be invoked when it is known with 5985 * certainty that we are **not** in a DOM transaction. 5986 * 5987 * You may want to call this when you know that some deeper aspect of the 5988 * component's state has changed but `setState` was not called. 5989 * 5990 * This will not invoke `shouldUpdateComponent`, but it will invoke 5991 * `componentWillUpdate` and `componentDidUpdate`. 5992 * 5993 * @param {?function} callback Called after update is complete. 5994 * @final 5995 * @protected 5996 */ 5997 forceUpdate: function(callback) { 5998 var compositeLifeCycleState = this._compositeLifeCycleState; 5999 ("production" !== "development" ? invariant( 6000 this.isMounted() || 6001 compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 6002 'forceUpdate(...): Can only force an update on mounted or mounting ' + 6003 'components.' 6004 ) : invariant(this.isMounted() || 6005 compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); 6006 ("production" !== "development" ? invariant( 6007 compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && 6008 compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 6009 'forceUpdate(...): Cannot force an update while unmounting component ' + 6010 'or during an existing state transition (such as within `render`).' 6011 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && 6012 compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); 6013 this._pendingForceUpdate = true; 6014 ReactUpdates.enqueueUpdate(this, callback); 6015 }, 6016 6017 /** 6018 * @private 6019 */ 6020 _renderValidatedComponent: ReactPerf.measure( 6021 'ReactCompositeComponent', 6022 '_renderValidatedComponent', 6023 function() { 6024 var renderedComponent; 6025 var previousContext = ReactContext.current; 6026 ReactContext.current = this._processChildContext(this._currentContext); 6027 ReactCurrentOwner.current = this; 6028 try { 6029 renderedComponent = this.render(); 6030 } finally { 6031 ReactContext.current = previousContext; 6032 ReactCurrentOwner.current = null; 6033 } 6034 ("production" !== "development" ? invariant( 6035 ReactComponent.isValidComponent(renderedComponent), 6036 '%s.render(): A valid ReactComponent must be returned. You may have ' + 6037 'returned null, undefined, an array, or some other invalid object.', 6038 this.constructor.displayName || 'ReactCompositeComponent' 6039 ) : invariant(ReactComponent.isValidComponent(renderedComponent))); 6040 return renderedComponent; 6041 } 6042 ), 6043 6044 /** 6045 * @private 6046 */ 6047 _bindAutoBindMethods: function() { 6048 for (var autoBindKey in this.__reactAutoBindMap) { 6049 if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { 6050 continue; 6051 } 6052 var method = this.__reactAutoBindMap[autoBindKey]; 6053 this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard( 6054 method, 6055 this.constructor.displayName + '.' + autoBindKey 6056 )); 6057 } 6058 }, 6059 6060 /** 6061 * Binds a method to the component. 6062 * 6063 * @param {function} method Method to be bound. 6064 * @private 6065 */ 6066 _bindAutoBindMethod: function(method) { 6067 var component = this; 6068 var boundMethod = function() { 6069 return method.apply(component, arguments); 6070 }; 6071 if ("production" !== "development") { 6072 boundMethod.__reactBoundContext = component; 6073 boundMethod.__reactBoundMethod = method; 6074 boundMethod.__reactBoundArguments = null; 6075 var componentName = component.constructor.displayName; 6076 var _bind = boundMethod.bind; 6077 boundMethod.bind = function(newThis ) {var args=Array.prototype.slice.call(arguments,1); 6078 // User is trying to bind() an autobound method; we effectively will 6079 // ignore the value of "this" that the user is trying to use, so 6080 // let's warn. 6081 if (newThis !== component && newThis !== null) { 6082 monitorCodeUse('react_bind_warning', { component: componentName }); 6083 console.warn( 6084 'bind(): React component methods may only be bound to the ' + 6085 'component instance. See ' + componentName 6086 ); 6087 } else if (!args.length) { 6088 monitorCodeUse('react_bind_warning', { component: componentName }); 6089 console.warn( 6090 'bind(): You are binding a component method to the component. ' + 6091 'React does this for you automatically in a high-performance ' + 6092 'way, so you can safely remove this call. See ' + componentName 6093 ); 6094 return boundMethod; 6095 } 6096 var reboundMethod = _bind.apply(boundMethod, arguments); 6097 reboundMethod.__reactBoundContext = component; 6098 reboundMethod.__reactBoundMethod = method; 6099 reboundMethod.__reactBoundArguments = args; 6100 return reboundMethod; 6101 }; 6102 } 6103 return boundMethod; 6104 } 6105 }; 6106 6107 var ReactCompositeComponentBase = function() {}; 6108 mixInto(ReactCompositeComponentBase, ReactComponent.Mixin); 6109 mixInto(ReactCompositeComponentBase, ReactOwner.Mixin); 6110 mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin); 6111 mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin); 6112 6113 /** 6114 * Checks if a value is a valid component constructor. 6115 * 6116 * @param {*} 6117 * @return {boolean} 6118 * @public 6119 */ 6120 function isValidClass(componentClass) { 6121 return componentClass instanceof Function && 6122 'componentConstructor' in componentClass && 6123 componentClass.componentConstructor instanceof Function; 6124 } 6125 /** 6126 * Module for creating composite components. 6127 * 6128 * @class ReactCompositeComponent 6129 * @extends ReactComponent 6130 * @extends ReactOwner 6131 * @extends ReactPropTransferer 6132 */ 6133 var ReactCompositeComponent = { 6134 6135 LifeCycle: CompositeLifeCycle, 6136 6137 Base: ReactCompositeComponentBase, 6138 6139 /** 6140 * Creates a composite component class given a class specification. 6141 * 6142 * @param {object} spec Class specification (which must define `render`). 6143 * @return {function} Component constructor function. 6144 * @public 6145 */ 6146 createClass: function(spec) { 6147 var Constructor = function() {}; 6148 Constructor.prototype = new ReactCompositeComponentBase(); 6149 Constructor.prototype.constructor = Constructor; 6150 6151 var DescriptorConstructor = Constructor; 6152 6153 var ConvenienceConstructor = function(props, children) { 6154 var descriptor = new DescriptorConstructor(); 6155 descriptor.construct.apply(descriptor, arguments); 6156 return descriptor; 6157 }; 6158 ConvenienceConstructor.componentConstructor = Constructor; 6159 Constructor.ConvenienceConstructor = ConvenienceConstructor; 6160 ConvenienceConstructor.originalSpec = spec; 6161 6162 injectedMixins.forEach( 6163 mixSpecIntoComponent.bind(null, ConvenienceConstructor) 6164 ); 6165 6166 mixSpecIntoComponent(ConvenienceConstructor, spec); 6167 6168 ("production" !== "development" ? invariant( 6169 Constructor.prototype.render, 6170 'createClass(...): Class specification must implement a `render` method.' 6171 ) : invariant(Constructor.prototype.render)); 6172 6173 if ("production" !== "development") { 6174 if (Constructor.prototype.componentShouldUpdate) { 6175 monitorCodeUse( 6176 'react_component_should_update_warning', 6177 { component: spec.displayName } 6178 ); 6179 console.warn( 6180 (spec.displayName || 'A component') + ' has a method called ' + 6181 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 6182 'The name is phrased as a question because the function is ' + 6183 'expected to return a value.' 6184 ); 6185 } 6186 } 6187 6188 // Expose the convience constructor on the prototype so that it can be 6189 // easily accessed on descriptors. E.g. <Foo />.type === Foo.type and for 6190 // static methods like <Foo />.type.staticMethod(); 6191 // This should not be named constructor since this may not be the function 6192 // that created the descriptor, and it may not even be a constructor. 6193 ConvenienceConstructor.type = Constructor; 6194 Constructor.prototype.type = Constructor; 6195 6196 // Reduce time spent doing lookups by setting these on the prototype. 6197 for (var methodName in ReactCompositeComponentInterface) { 6198 if (!Constructor.prototype[methodName]) { 6199 Constructor.prototype[methodName] = null; 6200 } 6201 } 6202 6203 if ("production" !== "development") { 6204 // In DEV the convenience constructor generates a proxy to another 6205 // instance around it to warn about access to properties on the 6206 // descriptor. 6207 DescriptorConstructor = createDescriptorProxy(Constructor); 6208 } 6209 6210 return ConvenienceConstructor; 6211 }, 6212 6213 isValidClass: isValidClass, 6214 6215 injection: { 6216 injectMixin: function(mixin) { 6217 injectedMixins.push(mixin); 6218 } 6219 } 6220 }; 6221 6222 module.exports = ReactCompositeComponent; 6223 6224 },{"./ReactComponent":27,"./ReactContext":30,"./ReactCurrentOwner":31,"./ReactErrorUtils":47,"./ReactOwner":59,"./ReactPerf":60,"./ReactPropTransferer":61,"./ReactPropTypeLocationNames":62,"./ReactPropTypeLocations":63,"./ReactUpdates":71,"./instantiateReactComponent":111,"./invariant":112,"./keyMirror":118,"./merge":121,"./mixInto":124,"./monitorCodeUse":125,"./objMap":126,"./shouldUpdateReactComponent":131,"./warning":134}],30:[function(_dereq_,module,exports){ 6225 /** 6226 * Copyright 2013-2014 Facebook, Inc. 6227 * 6228 * Licensed under the Apache License, Version 2.0 (the "License"); 6229 * you may not use this file except in compliance with the License. 6230 * You may obtain a copy of the License at 6231 * 6232 * http://www.apache.org/licenses/LICENSE-2.0 6233 * 6234 * Unless required by applicable law or agreed to in writing, software 6235 * distributed under the License is distributed on an "AS IS" BASIS, 6236 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6237 * See the License for the specific language governing permissions and 6238 * limitations under the License. 6239 * 6240 * @providesModule ReactContext 6241 */ 6242 6243 "use strict"; 6244 6245 var merge = _dereq_("./merge"); 6246 6247 /** 6248 * Keeps track of the current context. 6249 * 6250 * The context is automatically passed down the component ownership hierarchy 6251 * and is accessible via `this.context` on ReactCompositeComponents. 6252 */ 6253 var ReactContext = { 6254 6255 /** 6256 * @internal 6257 * @type {object} 6258 */ 6259 current: {}, 6260 6261 /** 6262 * Temporarily extends the current context while executing scopedCallback. 6263 * 6264 * A typical use case might look like 6265 * 6266 * render: function() { 6267 * var children = ReactContext.withContext({foo: 'foo'} () => ( 6268 * 6269 * )); 6270 * return <div>{children}</div>; 6271 * } 6272 * 6273 * @param {object} newContext New context to merge into the existing context 6274 * @param {function} scopedCallback Callback to run with the new context 6275 * @return {ReactComponent|array<ReactComponent>} 6276 */ 6277 withContext: function(newContext, scopedCallback) { 6278 var result; 6279 var previousContext = ReactContext.current; 6280 ReactContext.current = merge(previousContext, newContext); 6281 try { 6282 result = scopedCallback(); 6283 } finally { 6284 ReactContext.current = previousContext; 6285 } 6286 return result; 6287 } 6288 6289 }; 6290 6291 module.exports = ReactContext; 6292 6293 },{"./merge":121}],31:[function(_dereq_,module,exports){ 6294 /** 6295 * Copyright 2013-2014 Facebook, Inc. 6296 * 6297 * Licensed under the Apache License, Version 2.0 (the "License"); 6298 * you may not use this file except in compliance with the License. 6299 * You may obtain a copy of the License at 6300 * 6301 * http://www.apache.org/licenses/LICENSE-2.0 6302 * 6303 * Unless required by applicable law or agreed to in writing, software 6304 * distributed under the License is distributed on an "AS IS" BASIS, 6305 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6306 * See the License for the specific language governing permissions and 6307 * limitations under the License. 6308 * 6309 * @providesModule ReactCurrentOwner 6310 */ 6311 6312 "use strict"; 6313 6314 /** 6315 * Keeps track of the current owner. 6316 * 6317 * The current owner is the component who should own any components that are 6318 * currently being constructed. 6319 * 6320 * The depth indicate how many composite components are above this render level. 6321 */ 6322 var ReactCurrentOwner = { 6323 6324 /** 6325 * @internal 6326 * @type {ReactComponent} 6327 */ 6328 current: null 6329 6330 }; 6331 6332 module.exports = ReactCurrentOwner; 6333 6334 },{}],32:[function(_dereq_,module,exports){ 6335 /** 6336 * Copyright 2013-2014 Facebook, Inc. 6337 * 6338 * Licensed under the Apache License, Version 2.0 (the "License"); 6339 * you may not use this file except in compliance with the License. 6340 * You may obtain a copy of the License at 6341 * 6342 * http://www.apache.org/licenses/LICENSE-2.0 6343 * 6344 * Unless required by applicable law or agreed to in writing, software 6345 * distributed under the License is distributed on an "AS IS" BASIS, 6346 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6347 * See the License for the specific language governing permissions and 6348 * limitations under the License. 6349 * 6350 * @providesModule ReactDOM 6351 * @typechecks static-only 6352 */ 6353 6354 "use strict"; 6355 6356 var ReactDOMComponent = _dereq_("./ReactDOMComponent"); 6357 6358 var mergeInto = _dereq_("./mergeInto"); 6359 var objMapKeyVal = _dereq_("./objMapKeyVal"); 6360 6361 /** 6362 * Creates a new React class that is idempotent and capable of containing other 6363 * React components. It accepts event listeners and DOM properties that are 6364 * valid according to `DOMProperty`. 6365 * 6366 * - Event listeners: `onClick`, `onMouseDown`, etc. 6367 * - DOM properties: `className`, `name`, `title`, etc. 6368 * 6369 * The `style` property functions differently from the DOM API. It accepts an 6370 * object mapping of style properties to values. 6371 * 6372 * @param {string} tag Tag name (e.g. `div`). 6373 * @param {boolean} omitClose True if the close tag should be omitted. 6374 * @private 6375 */ 6376 function createDOMComponentClass(tag, omitClose) { 6377 var Constructor = function() {}; 6378 Constructor.prototype = new ReactDOMComponent(tag, omitClose); 6379 Constructor.prototype.constructor = Constructor; 6380 Constructor.displayName = tag; 6381 6382 var ConvenienceConstructor = function(props, children) { 6383 var instance = new Constructor(); 6384 instance.construct.apply(instance, arguments); 6385 return instance; 6386 }; 6387 6388 // Expose the constructor on the ConvenienceConstructor and prototype so that 6389 // it can be easily easily accessed on descriptors. 6390 // E.g. <div />.type === div.type 6391 ConvenienceConstructor.type = Constructor; 6392 Constructor.prototype.type = Constructor; 6393 6394 Constructor.ConvenienceConstructor = ConvenienceConstructor; 6395 ConvenienceConstructor.componentConstructor = Constructor; 6396 return ConvenienceConstructor; 6397 } 6398 6399 /** 6400 * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes. 6401 * This is also accessible via `React.DOM`. 6402 * 6403 * @public 6404 */ 6405 var ReactDOM = objMapKeyVal({ 6406 a: false, 6407 abbr: false, 6408 address: false, 6409 area: true, 6410 article: false, 6411 aside: false, 6412 audio: false, 6413 b: false, 6414 base: true, 6415 bdi: false, 6416 bdo: false, 6417 big: false, 6418 blockquote: false, 6419 body: false, 6420 br: true, 6421 button: false, 6422 canvas: false, 6423 caption: false, 6424 cite: false, 6425 code: false, 6426 col: true, 6427 colgroup: false, 6428 data: false, 6429 datalist: false, 6430 dd: false, 6431 del: false, 6432 details: false, 6433 dfn: false, 6434 div: false, 6435 dl: false, 6436 dt: false, 6437 em: false, 6438 embed: true, 6439 fieldset: false, 6440 figcaption: false, 6441 figure: false, 6442 footer: false, 6443 form: false, // NOTE: Injected, see `ReactDOMForm`. 6444 h1: false, 6445 h2: false, 6446 h3: false, 6447 h4: false, 6448 h5: false, 6449 h6: false, 6450 head: false, 6451 header: false, 6452 hr: true, 6453 html: false, 6454 i: false, 6455 iframe: false, 6456 img: true, 6457 input: true, 6458 ins: false, 6459 kbd: false, 6460 keygen: true, 6461 label: false, 6462 legend: false, 6463 li: false, 6464 link: true, 6465 main: false, 6466 map: false, 6467 mark: false, 6468 menu: false, 6469 menuitem: false, // NOTE: Close tag should be omitted, but causes problems. 6470 meta: true, 6471 meter: false, 6472 nav: false, 6473 noscript: false, 6474 object: false, 6475 ol: false, 6476 optgroup: false, 6477 option: false, 6478 output: false, 6479 p: false, 6480 param: true, 6481 pre: false, 6482 progress: false, 6483 q: false, 6484 rp: false, 6485 rt: false, 6486 ruby: false, 6487 s: false, 6488 samp: false, 6489 script: false, 6490 section: false, 6491 select: false, 6492 small: false, 6493 source: true, 6494 span: false, 6495 strong: false, 6496 style: false, 6497 sub: false, 6498 summary: false, 6499 sup: false, 6500 table: false, 6501 tbody: false, 6502 td: false, 6503 textarea: false, // NOTE: Injected, see `ReactDOMTextarea`. 6504 tfoot: false, 6505 th: false, 6506 thead: false, 6507 time: false, 6508 title: false, 6509 tr: false, 6510 track: true, 6511 u: false, 6512 ul: false, 6513 'var': false, 6514 video: false, 6515 wbr: true, 6516 6517 // SVG 6518 circle: false, 6519 defs: false, 6520 g: false, 6521 line: false, 6522 linearGradient: false, 6523 path: false, 6524 polygon: false, 6525 polyline: false, 6526 radialGradient: false, 6527 rect: false, 6528 stop: false, 6529 svg: false, 6530 text: false 6531 }, createDOMComponentClass); 6532 6533 var injection = { 6534 injectComponentClasses: function(componentClasses) { 6535 mergeInto(ReactDOM, componentClasses); 6536 } 6537 }; 6538 6539 ReactDOM.injection = injection; 6540 6541 module.exports = ReactDOM; 6542 6543 },{"./ReactDOMComponent":34,"./mergeInto":123,"./objMapKeyVal":127}],33:[function(_dereq_,module,exports){ 6544 /** 6545 * Copyright 2013-2014 Facebook, Inc. 6546 * 6547 * Licensed under the Apache License, Version 2.0 (the "License"); 6548 * you may not use this file except in compliance with the License. 6549 * You may obtain a copy of the License at 6550 * 6551 * http://www.apache.org/licenses/LICENSE-2.0 6552 * 6553 * Unless required by applicable law or agreed to in writing, software 6554 * distributed under the License is distributed on an "AS IS" BASIS, 6555 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6556 * See the License for the specific language governing permissions and 6557 * limitations under the License. 6558 * 6559 * @providesModule ReactDOMButton 6560 */ 6561 6562 "use strict"; 6563 6564 var AutoFocusMixin = _dereq_("./AutoFocusMixin"); 6565 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 6566 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 6567 var ReactDOM = _dereq_("./ReactDOM"); 6568 6569 var keyMirror = _dereq_("./keyMirror"); 6570 6571 // Store a reference to the <button> `ReactDOMComponent`. 6572 var button = ReactDOM.button; 6573 6574 var mouseListenerNames = keyMirror({ 6575 onClick: true, 6576 onDoubleClick: true, 6577 onMouseDown: true, 6578 onMouseMove: true, 6579 onMouseUp: true, 6580 onClickCapture: true, 6581 onDoubleClickCapture: true, 6582 onMouseDownCapture: true, 6583 onMouseMoveCapture: true, 6584 onMouseUpCapture: true 6585 }); 6586 6587 /** 6588 * Implements a <button> native component that does not receive mouse events 6589 * when `disabled` is set. 6590 */ 6591 var ReactDOMButton = ReactCompositeComponent.createClass({ 6592 displayName: 'ReactDOMButton', 6593 6594 mixins: [AutoFocusMixin, ReactBrowserComponentMixin], 6595 6596 render: function() { 6597 var props = {}; 6598 6599 // Copy the props; except the mouse listeners if we're disabled 6600 for (var key in this.props) { 6601 if (this.props.hasOwnProperty(key) && 6602 (!this.props.disabled || !mouseListenerNames[key])) { 6603 props[key] = this.props[key]; 6604 } 6605 } 6606 6607 return button(props, this.props.children); 6608 } 6609 6610 }); 6611 6612 module.exports = ReactDOMButton; 6613 6614 },{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./keyMirror":118}],34:[function(_dereq_,module,exports){ 6615 /** 6616 * Copyright 2013-2014 Facebook, Inc. 6617 * 6618 * Licensed under the Apache License, Version 2.0 (the "License"); 6619 * you may not use this file except in compliance with the License. 6620 * You may obtain a copy of the License at 6621 * 6622 * http://www.apache.org/licenses/LICENSE-2.0 6623 * 6624 * Unless required by applicable law or agreed to in writing, software 6625 * distributed under the License is distributed on an "AS IS" BASIS, 6626 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6627 * See the License for the specific language governing permissions and 6628 * limitations under the License. 6629 * 6630 * @providesModule ReactDOMComponent 6631 * @typechecks static-only 6632 */ 6633 6634 "use strict"; 6635 6636 var CSSPropertyOperations = _dereq_("./CSSPropertyOperations"); 6637 var DOMProperty = _dereq_("./DOMProperty"); 6638 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 6639 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 6640 var ReactComponent = _dereq_("./ReactComponent"); 6641 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 6642 var ReactMount = _dereq_("./ReactMount"); 6643 var ReactMultiChild = _dereq_("./ReactMultiChild"); 6644 var ReactPerf = _dereq_("./ReactPerf"); 6645 6646 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); 6647 var invariant = _dereq_("./invariant"); 6648 var keyOf = _dereq_("./keyOf"); 6649 var merge = _dereq_("./merge"); 6650 var mixInto = _dereq_("./mixInto"); 6651 6652 var deleteListener = ReactEventEmitter.deleteListener; 6653 var listenTo = ReactEventEmitter.listenTo; 6654 var registrationNameModules = ReactEventEmitter.registrationNameModules; 6655 6656 // For quickly matching children type, to test if can be treated as content. 6657 var CONTENT_TYPES = {'string': true, 'number': true}; 6658 6659 var STYLE = keyOf({style: null}); 6660 6661 var ELEMENT_NODE_TYPE = 1; 6662 6663 /** 6664 * @param {?object} props 6665 */ 6666 function assertValidProps(props) { 6667 if (!props) { 6668 return; 6669 } 6670 // Note the use of `==` which checks for null or undefined. 6671 ("production" !== "development" ? invariant( 6672 props.children == null || props.dangerouslySetInnerHTML == null, 6673 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' 6674 ) : invariant(props.children == null || props.dangerouslySetInnerHTML == null)); 6675 ("production" !== "development" ? invariant( 6676 props.style == null || typeof props.style === 'object', 6677 'The `style` prop expects a mapping from style properties to values, ' + 6678 'not a string.' 6679 ) : invariant(props.style == null || typeof props.style === 'object')); 6680 } 6681 6682 function putListener(id, registrationName, listener, transaction) { 6683 var container = ReactMount.findReactContainerForID(id); 6684 if (container) { 6685 var doc = container.nodeType === ELEMENT_NODE_TYPE ? 6686 container.ownerDocument : 6687 container; 6688 listenTo(registrationName, doc); 6689 } 6690 transaction.getPutListenerQueue().enqueuePutListener( 6691 id, 6692 registrationName, 6693 listener 6694 ); 6695 } 6696 6697 6698 /** 6699 * @constructor ReactDOMComponent 6700 * @extends ReactComponent 6701 * @extends ReactMultiChild 6702 */ 6703 function ReactDOMComponent(tag, omitClose) { 6704 this._tagOpen = '<' + tag; 6705 this._tagClose = omitClose ? '' : '</' + tag + '>'; 6706 this.tagName = tag.toUpperCase(); 6707 } 6708 6709 ReactDOMComponent.Mixin = { 6710 6711 /** 6712 * Generates root tag markup then recurses. This method has side effects and 6713 * is not idempotent. 6714 * 6715 * @internal 6716 * @param {string} rootID The root DOM ID for this node. 6717 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 6718 * @param {number} mountDepth number of components in the owner hierarchy 6719 * @return {string} The computed markup. 6720 */ 6721 mountComponent: ReactPerf.measure( 6722 'ReactDOMComponent', 6723 'mountComponent', 6724 function(rootID, transaction, mountDepth) { 6725 ReactComponent.Mixin.mountComponent.call( 6726 this, 6727 rootID, 6728 transaction, 6729 mountDepth 6730 ); 6731 assertValidProps(this.props); 6732 return ( 6733 this._createOpenTagMarkupAndPutListeners(transaction) + 6734 this._createContentMarkup(transaction) + 6735 this._tagClose 6736 ); 6737 } 6738 ), 6739 6740 /** 6741 * Creates markup for the open tag and all attributes. 6742 * 6743 * This method has side effects because events get registered. 6744 * 6745 * Iterating over object properties is faster than iterating over arrays. 6746 * @see http://jsperf.com/obj-vs-arr-iteration 6747 * 6748 * @private 6749 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 6750 * @return {string} Markup of opening tag. 6751 */ 6752 _createOpenTagMarkupAndPutListeners: function(transaction) { 6753 var props = this.props; 6754 var ret = this._tagOpen; 6755 6756 for (var propKey in props) { 6757 if (!props.hasOwnProperty(propKey)) { 6758 continue; 6759 } 6760 var propValue = props[propKey]; 6761 if (propValue == null) { 6762 continue; 6763 } 6764 if (registrationNameModules[propKey]) { 6765 putListener(this._rootNodeID, propKey, propValue, transaction); 6766 } else { 6767 if (propKey === STYLE) { 6768 if (propValue) { 6769 propValue = props.style = merge(props.style); 6770 } 6771 propValue = CSSPropertyOperations.createMarkupForStyles(propValue); 6772 } 6773 var markup = 6774 DOMPropertyOperations.createMarkupForProperty(propKey, propValue); 6775 if (markup) { 6776 ret += ' ' + markup; 6777 } 6778 } 6779 } 6780 6781 // For static pages, no need to put React ID and checksum. Saves lots of 6782 // bytes. 6783 if (transaction.renderToStaticMarkup) { 6784 return ret + '>'; 6785 } 6786 6787 var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID); 6788 return ret + ' ' + markupForID + '>'; 6789 }, 6790 6791 /** 6792 * Creates markup for the content between the tags. 6793 * 6794 * @private 6795 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 6796 * @return {string} Content markup. 6797 */ 6798 _createContentMarkup: function(transaction) { 6799 // Intentional use of != to avoid catching zero/false. 6800 var innerHTML = this.props.dangerouslySetInnerHTML; 6801 if (innerHTML != null) { 6802 if (innerHTML.__html != null) { 6803 return innerHTML.__html; 6804 } 6805 } else { 6806 var contentToUse = 6807 CONTENT_TYPES[typeof this.props.children] ? this.props.children : null; 6808 var childrenToUse = contentToUse != null ? null : this.props.children; 6809 if (contentToUse != null) { 6810 return escapeTextForBrowser(contentToUse); 6811 } else if (childrenToUse != null) { 6812 var mountImages = this.mountChildren( 6813 childrenToUse, 6814 transaction 6815 ); 6816 return mountImages.join(''); 6817 } 6818 } 6819 return ''; 6820 }, 6821 6822 receiveComponent: function(nextComponent, transaction) { 6823 if (nextComponent === this) { 6824 // Since props and context are immutable after the component is 6825 // mounted, we can do a cheap identity compare here to determine 6826 // if this is a superfluous reconcile. 6827 6828 // TODO: compare the descriptor 6829 return; 6830 } 6831 6832 assertValidProps(nextComponent.props); 6833 ReactComponent.Mixin.receiveComponent.call( 6834 this, 6835 nextComponent, 6836 transaction 6837 ); 6838 }, 6839 6840 /** 6841 * Updates a native DOM component after it has already been allocated and 6842 * attached to the DOM. Reconciles the root DOM node, then recurses. 6843 * 6844 * @param {ReactReconcileTransaction} transaction 6845 * @param {object} prevProps 6846 * @internal 6847 * @overridable 6848 */ 6849 updateComponent: ReactPerf.measure( 6850 'ReactDOMComponent', 6851 'updateComponent', 6852 function(transaction, prevProps, prevOwner) { 6853 ReactComponent.Mixin.updateComponent.call( 6854 this, 6855 transaction, 6856 prevProps, 6857 prevOwner 6858 ); 6859 this._updateDOMProperties(prevProps, transaction); 6860 this._updateDOMChildren(prevProps, transaction); 6861 } 6862 ), 6863 6864 /** 6865 * Reconciles the properties by detecting differences in property values and 6866 * updating the DOM as necessary. This function is probably the single most 6867 * critical path for performance optimization. 6868 * 6869 * TODO: Benchmark whether checking for changed values in memory actually 6870 * improves performance (especially statically positioned elements). 6871 * TODO: Benchmark the effects of putting this at the top since 99% of props 6872 * do not change for a given reconciliation. 6873 * TODO: Benchmark areas that can be improved with caching. 6874 * 6875 * @private 6876 * @param {object} lastProps 6877 * @param {ReactReconcileTransaction} transaction 6878 */ 6879 _updateDOMProperties: function(lastProps, transaction) { 6880 var nextProps = this.props; 6881 var propKey; 6882 var styleName; 6883 var styleUpdates; 6884 for (propKey in lastProps) { 6885 if (nextProps.hasOwnProperty(propKey) || 6886 !lastProps.hasOwnProperty(propKey)) { 6887 continue; 6888 } 6889 if (propKey === STYLE) { 6890 var lastStyle = lastProps[propKey]; 6891 for (styleName in lastStyle) { 6892 if (lastStyle.hasOwnProperty(styleName)) { 6893 styleUpdates = styleUpdates || {}; 6894 styleUpdates[styleName] = ''; 6895 } 6896 } 6897 } else if (registrationNameModules[propKey]) { 6898 deleteListener(this._rootNodeID, propKey); 6899 } else if ( 6900 DOMProperty.isStandardName[propKey] || 6901 DOMProperty.isCustomAttribute(propKey)) { 6902 ReactComponent.BackendIDOperations.deletePropertyByID( 6903 this._rootNodeID, 6904 propKey 6905 ); 6906 } 6907 } 6908 for (propKey in nextProps) { 6909 var nextProp = nextProps[propKey]; 6910 var lastProp = lastProps[propKey]; 6911 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) { 6912 continue; 6913 } 6914 if (propKey === STYLE) { 6915 if (nextProp) { 6916 nextProp = nextProps.style = merge(nextProp); 6917 } 6918 if (lastProp) { 6919 // Unset styles on `lastProp` but not on `nextProp`. 6920 for (styleName in lastProp) { 6921 if (lastProp.hasOwnProperty(styleName) && 6922 !nextProp.hasOwnProperty(styleName)) { 6923 styleUpdates = styleUpdates || {}; 6924 styleUpdates[styleName] = ''; 6925 } 6926 } 6927 // Update styles that changed since `lastProp`. 6928 for (styleName in nextProp) { 6929 if (nextProp.hasOwnProperty(styleName) && 6930 lastProp[styleName] !== nextProp[styleName]) { 6931 styleUpdates = styleUpdates || {}; 6932 styleUpdates[styleName] = nextProp[styleName]; 6933 } 6934 } 6935 } else { 6936 // Relies on `updateStylesByID` not mutating `styleUpdates`. 6937 styleUpdates = nextProp; 6938 } 6939 } else if (registrationNameModules[propKey]) { 6940 putListener(this._rootNodeID, propKey, nextProp, transaction); 6941 } else if ( 6942 DOMProperty.isStandardName[propKey] || 6943 DOMProperty.isCustomAttribute(propKey)) { 6944 ReactComponent.BackendIDOperations.updatePropertyByID( 6945 this._rootNodeID, 6946 propKey, 6947 nextProp 6948 ); 6949 } 6950 } 6951 if (styleUpdates) { 6952 ReactComponent.BackendIDOperations.updateStylesByID( 6953 this._rootNodeID, 6954 styleUpdates 6955 ); 6956 } 6957 }, 6958 6959 /** 6960 * Reconciles the children with the various properties that affect the 6961 * children content. 6962 * 6963 * @param {object} lastProps 6964 * @param {ReactReconcileTransaction} transaction 6965 */ 6966 _updateDOMChildren: function(lastProps, transaction) { 6967 var nextProps = this.props; 6968 6969 var lastContent = 6970 CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null; 6971 var nextContent = 6972 CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null; 6973 6974 var lastHtml = 6975 lastProps.dangerouslySetInnerHTML && 6976 lastProps.dangerouslySetInnerHTML.__html; 6977 var nextHtml = 6978 nextProps.dangerouslySetInnerHTML && 6979 nextProps.dangerouslySetInnerHTML.__html; 6980 6981 // Note the use of `!=` which checks for null or undefined. 6982 var lastChildren = lastContent != null ? null : lastProps.children; 6983 var nextChildren = nextContent != null ? null : nextProps.children; 6984 6985 // If we're switching from children to content/html or vice versa, remove 6986 // the old content 6987 var lastHasContentOrHtml = lastContent != null || lastHtml != null; 6988 var nextHasContentOrHtml = nextContent != null || nextHtml != null; 6989 if (lastChildren != null && nextChildren == null) { 6990 this.updateChildren(null, transaction); 6991 } else if (lastHasContentOrHtml && !nextHasContentOrHtml) { 6992 this.updateTextContent(''); 6993 } 6994 6995 if (nextContent != null) { 6996 if (lastContent !== nextContent) { 6997 this.updateTextContent('' + nextContent); 6998 } 6999 } else if (nextHtml != null) { 7000 if (lastHtml !== nextHtml) { 7001 ReactComponent.BackendIDOperations.updateInnerHTMLByID( 7002 this._rootNodeID, 7003 nextHtml 7004 ); 7005 } 7006 } else if (nextChildren != null) { 7007 this.updateChildren(nextChildren, transaction); 7008 } 7009 }, 7010 7011 /** 7012 * Destroys all event registrations for this instance. Does not remove from 7013 * the DOM. That must be done by the parent. 7014 * 7015 * @internal 7016 */ 7017 unmountComponent: function() { 7018 this.unmountChildren(); 7019 ReactEventEmitter.deleteAllListeners(this._rootNodeID); 7020 ReactComponent.Mixin.unmountComponent.call(this); 7021 } 7022 7023 }; 7024 7025 mixInto(ReactDOMComponent, ReactComponent.Mixin); 7026 mixInto(ReactDOMComponent, ReactDOMComponent.Mixin); 7027 mixInto(ReactDOMComponent, ReactMultiChild.Mixin); 7028 mixInto(ReactDOMComponent, ReactBrowserComponentMixin); 7029 7030 module.exports = ReactDOMComponent; 7031 7032 },{"./CSSPropertyOperations":3,"./DOMProperty":8,"./DOMPropertyOperations":9,"./ReactBrowserComponentMixin":25,"./ReactComponent":27,"./ReactEventEmitter":48,"./ReactMount":55,"./ReactMultiChild":57,"./ReactPerf":60,"./escapeTextForBrowser":98,"./invariant":112,"./keyOf":119,"./merge":121,"./mixInto":124}],35:[function(_dereq_,module,exports){ 7033 /** 7034 * Copyright 2013-2014 Facebook, Inc. 7035 * 7036 * Licensed under the Apache License, Version 2.0 (the "License"); 7037 * you may not use this file except in compliance with the License. 7038 * You may obtain a copy of the License at 7039 * 7040 * http://www.apache.org/licenses/LICENSE-2.0 7041 * 7042 * Unless required by applicable law or agreed to in writing, software 7043 * distributed under the License is distributed on an "AS IS" BASIS, 7044 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7045 * See the License for the specific language governing permissions and 7046 * limitations under the License. 7047 * 7048 * @providesModule ReactDOMForm 7049 */ 7050 7051 "use strict"; 7052 7053 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 7054 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 7055 var ReactDOM = _dereq_("./ReactDOM"); 7056 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 7057 var EventConstants = _dereq_("./EventConstants"); 7058 7059 // Store a reference to the <form> `ReactDOMComponent`. 7060 var form = ReactDOM.form; 7061 7062 /** 7063 * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need 7064 * to capture it on the <form> element itself. There are lots of hacks we could 7065 * do to accomplish this, but the most reliable is to make <form> a 7066 * composite component and use `componentDidMount` to attach the event handlers. 7067 */ 7068 var ReactDOMForm = ReactCompositeComponent.createClass({ 7069 displayName: 'ReactDOMForm', 7070 7071 mixins: [ReactBrowserComponentMixin], 7072 7073 render: function() { 7074 // TODO: Instead of using `ReactDOM` directly, we should use JSX. However, 7075 // `jshint` fails to parse JSX so in order for linting to work in the open 7076 // source repo, we need to just use `ReactDOM.form`. 7077 return this.transferPropsTo(form(null, this.props.children)); 7078 }, 7079 7080 componentDidMount: function() { 7081 ReactEventEmitter.trapBubbledEvent( 7082 EventConstants.topLevelTypes.topReset, 7083 'reset', 7084 this.getDOMNode() 7085 ); 7086 ReactEventEmitter.trapBubbledEvent( 7087 EventConstants.topLevelTypes.topSubmit, 7088 'submit', 7089 this.getDOMNode() 7090 ); 7091 } 7092 }); 7093 7094 module.exports = ReactDOMForm; 7095 7096 },{"./EventConstants":14,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./ReactEventEmitter":48}],36:[function(_dereq_,module,exports){ 7097 /** 7098 * Copyright 2013-2014 Facebook, Inc. 7099 * 7100 * Licensed under the Apache License, Version 2.0 (the "License"); 7101 * you may not use this file except in compliance with the License. 7102 * You may obtain a copy of the License at 7103 * 7104 * http://www.apache.org/licenses/LICENSE-2.0 7105 * 7106 * Unless required by applicable law or agreed to in writing, software 7107 * distributed under the License is distributed on an "AS IS" BASIS, 7108 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7109 * See the License for the specific language governing permissions and 7110 * limitations under the License. 7111 * 7112 * @providesModule ReactDOMIDOperations 7113 * @typechecks static-only 7114 */ 7115 7116 /*jslint evil: true */ 7117 7118 "use strict"; 7119 7120 var CSSPropertyOperations = _dereq_("./CSSPropertyOperations"); 7121 var DOMChildrenOperations = _dereq_("./DOMChildrenOperations"); 7122 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 7123 var ReactMount = _dereq_("./ReactMount"); 7124 var ReactPerf = _dereq_("./ReactPerf"); 7125 7126 var invariant = _dereq_("./invariant"); 7127 7128 /** 7129 * Errors for properties that should not be updated with `updatePropertyById()`. 7130 * 7131 * @type {object} 7132 * @private 7133 */ 7134 var INVALID_PROPERTY_ERRORS = { 7135 dangerouslySetInnerHTML: 7136 '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.', 7137 style: '`style` must be set using `updateStylesByID()`.' 7138 }; 7139 7140 var useWhitespaceWorkaround; 7141 7142 /** 7143 * Operations used to process updates to DOM nodes. This is made injectable via 7144 * `ReactComponent.BackendIDOperations`. 7145 */ 7146 var ReactDOMIDOperations = { 7147 7148 /** 7149 * Updates a DOM node with new property values. This should only be used to 7150 * update DOM properties in `DOMProperty`. 7151 * 7152 * @param {string} id ID of the node to update. 7153 * @param {string} name A valid property name, see `DOMProperty`. 7154 * @param {*} value New value of the property. 7155 * @internal 7156 */ 7157 updatePropertyByID: ReactPerf.measure( 7158 'ReactDOMIDOperations', 7159 'updatePropertyByID', 7160 function(id, name, value) { 7161 var node = ReactMount.getNode(id); 7162 ("production" !== "development" ? invariant( 7163 !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 7164 'updatePropertyByID(...): %s', 7165 INVALID_PROPERTY_ERRORS[name] 7166 ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); 7167 7168 // If we're updating to null or undefined, we should remove the property 7169 // from the DOM node instead of inadvertantly setting to a string. This 7170 // brings us in line with the same behavior we have on initial render. 7171 if (value != null) { 7172 DOMPropertyOperations.setValueForProperty(node, name, value); 7173 } else { 7174 DOMPropertyOperations.deleteValueForProperty(node, name); 7175 } 7176 } 7177 ), 7178 7179 /** 7180 * Updates a DOM node to remove a property. This should only be used to remove 7181 * DOM properties in `DOMProperty`. 7182 * 7183 * @param {string} id ID of the node to update. 7184 * @param {string} name A property name to remove, see `DOMProperty`. 7185 * @internal 7186 */ 7187 deletePropertyByID: ReactPerf.measure( 7188 'ReactDOMIDOperations', 7189 'deletePropertyByID', 7190 function(id, name, value) { 7191 var node = ReactMount.getNode(id); 7192 ("production" !== "development" ? invariant( 7193 !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 7194 'updatePropertyByID(...): %s', 7195 INVALID_PROPERTY_ERRORS[name] 7196 ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); 7197 DOMPropertyOperations.deleteValueForProperty(node, name, value); 7198 } 7199 ), 7200 7201 /** 7202 * Updates a DOM node with new style values. If a value is specified as '', 7203 * the corresponding style property will be unset. 7204 * 7205 * @param {string} id ID of the node to update. 7206 * @param {object} styles Mapping from styles to values. 7207 * @internal 7208 */ 7209 updateStylesByID: ReactPerf.measure( 7210 'ReactDOMIDOperations', 7211 'updateStylesByID', 7212 function(id, styles) { 7213 var node = ReactMount.getNode(id); 7214 CSSPropertyOperations.setValueForStyles(node, styles); 7215 } 7216 ), 7217 7218 /** 7219 * Updates a DOM node's innerHTML. 7220 * 7221 * @param {string} id ID of the node to update. 7222 * @param {string} html An HTML string. 7223 * @internal 7224 */ 7225 updateInnerHTMLByID: ReactPerf.measure( 7226 'ReactDOMIDOperations', 7227 'updateInnerHTMLByID', 7228 function(id, html) { 7229 var node = ReactMount.getNode(id); 7230 7231 // IE8: When updating a just created node with innerHTML only leading 7232 // whitespace is removed. When updating an existing node with innerHTML 7233 // whitespace in root TextNodes is also collapsed. 7234 // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html 7235 7236 if (useWhitespaceWorkaround === undefined) { 7237 // Feature detection; only IE8 is known to behave improperly like this. 7238 var temp = document.createElement('div'); 7239 temp.innerHTML = ' '; 7240 useWhitespaceWorkaround = temp.innerHTML === ''; 7241 } 7242 7243 if (useWhitespaceWorkaround) { 7244 // Magic theory: IE8 supposedly differentiates between added and updated 7245 // nodes when processing innerHTML, innerHTML on updated nodes suffers 7246 // from worse whitespace behavior. Re-adding a node like this triggers 7247 // the initial and more favorable whitespace behavior. 7248 node.parentNode.replaceChild(node, node); 7249 } 7250 7251 if (useWhitespaceWorkaround && html.match(/^[ \r\n\t\f]/)) { 7252 // Recover leading whitespace by temporarily prepending any character. 7253 // \uFEFF has the potential advantage of being zero-width/invisible. 7254 node.innerHTML = '\uFEFF' + html; 7255 node.firstChild.deleteData(0, 1); 7256 } else { 7257 node.innerHTML = html; 7258 } 7259 } 7260 ), 7261 7262 /** 7263 * Updates a DOM node's text content set by `props.content`. 7264 * 7265 * @param {string} id ID of the node to update. 7266 * @param {string} content Text content. 7267 * @internal 7268 */ 7269 updateTextContentByID: ReactPerf.measure( 7270 'ReactDOMIDOperations', 7271 'updateTextContentByID', 7272 function(id, content) { 7273 var node = ReactMount.getNode(id); 7274 DOMChildrenOperations.updateTextContent(node, content); 7275 } 7276 ), 7277 7278 /** 7279 * Replaces a DOM node that exists in the document with markup. 7280 * 7281 * @param {string} id ID of child to be replaced. 7282 * @param {string} markup Dangerous markup to inject in place of child. 7283 * @internal 7284 * @see {Danger.dangerouslyReplaceNodeWithMarkup} 7285 */ 7286 dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure( 7287 'ReactDOMIDOperations', 7288 'dangerouslyReplaceNodeWithMarkupByID', 7289 function(id, markup) { 7290 var node = ReactMount.getNode(id); 7291 DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); 7292 } 7293 ), 7294 7295 /** 7296 * Updates a component's children by processing a series of updates. 7297 * 7298 * @param {array<object>} updates List of update configurations. 7299 * @param {array<string>} markup List of markup strings. 7300 * @internal 7301 */ 7302 dangerouslyProcessChildrenUpdates: ReactPerf.measure( 7303 'ReactDOMIDOperations', 7304 'dangerouslyProcessChildrenUpdates', 7305 function(updates, markup) { 7306 for (var i = 0; i < updates.length; i++) { 7307 updates[i].parentNode = ReactMount.getNode(updates[i].parentID); 7308 } 7309 DOMChildrenOperations.processUpdates(updates, markup); 7310 } 7311 ) 7312 }; 7313 7314 module.exports = ReactDOMIDOperations; 7315 7316 },{"./CSSPropertyOperations":3,"./DOMChildrenOperations":7,"./DOMPropertyOperations":9,"./ReactMount":55,"./ReactPerf":60,"./invariant":112}],37:[function(_dereq_,module,exports){ 7317 /** 7318 * Copyright 2013-2014 Facebook, Inc. 7319 * 7320 * Licensed under the Apache License, Version 2.0 (the "License"); 7321 * you may not use this file except in compliance with the License. 7322 * You may obtain a copy of the License at 7323 * 7324 * http://www.apache.org/licenses/LICENSE-2.0 7325 * 7326 * Unless required by applicable law or agreed to in writing, software 7327 * distributed under the License is distributed on an "AS IS" BASIS, 7328 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7329 * See the License for the specific language governing permissions and 7330 * limitations under the License. 7331 * 7332 * @providesModule ReactDOMImg 7333 */ 7334 7335 "use strict"; 7336 7337 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 7338 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 7339 var ReactDOM = _dereq_("./ReactDOM"); 7340 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 7341 var EventConstants = _dereq_("./EventConstants"); 7342 7343 // Store a reference to the <img> `ReactDOMComponent`. 7344 var img = ReactDOM.img; 7345 7346 /** 7347 * Since onLoad doesn't bubble OR capture on the top level in IE8, we need to 7348 * capture it on the <img> element itself. There are lots of hacks we could do 7349 * to accomplish this, but the most reliable is to make <img> a composite 7350 * component and use `componentDidMount` to attach the event handlers. 7351 */ 7352 var ReactDOMImg = ReactCompositeComponent.createClass({ 7353 displayName: 'ReactDOMImg', 7354 tagName: 'IMG', 7355 7356 mixins: [ReactBrowserComponentMixin], 7357 7358 render: function() { 7359 return img(this.props); 7360 }, 7361 7362 componentDidMount: function() { 7363 var node = this.getDOMNode(); 7364 ReactEventEmitter.trapBubbledEvent( 7365 EventConstants.topLevelTypes.topLoad, 7366 'load', 7367 node 7368 ); 7369 ReactEventEmitter.trapBubbledEvent( 7370 EventConstants.topLevelTypes.topError, 7371 'error', 7372 node 7373 ); 7374 } 7375 }); 7376 7377 module.exports = ReactDOMImg; 7378 7379 },{"./EventConstants":14,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./ReactEventEmitter":48}],38:[function(_dereq_,module,exports){ 7380 /** 7381 * Copyright 2013-2014 Facebook, Inc. 7382 * 7383 * Licensed under the Apache License, Version 2.0 (the "License"); 7384 * you may not use this file except in compliance with the License. 7385 * You may obtain a copy of the License at 7386 * 7387 * http://www.apache.org/licenses/LICENSE-2.0 7388 * 7389 * Unless required by applicable law or agreed to in writing, software 7390 * distributed under the License is distributed on an "AS IS" BASIS, 7391 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7392 * See the License for the specific language governing permissions and 7393 * limitations under the License. 7394 * 7395 * @providesModule ReactDOMInput 7396 */ 7397 7398 "use strict"; 7399 7400 var AutoFocusMixin = _dereq_("./AutoFocusMixin"); 7401 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 7402 var LinkedValueUtils = _dereq_("./LinkedValueUtils"); 7403 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 7404 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 7405 var ReactDOM = _dereq_("./ReactDOM"); 7406 var ReactMount = _dereq_("./ReactMount"); 7407 7408 var invariant = _dereq_("./invariant"); 7409 var merge = _dereq_("./merge"); 7410 7411 // Store a reference to the <input> `ReactDOMComponent`. 7412 var input = ReactDOM.input; 7413 7414 var instancesByReactID = {}; 7415 7416 /** 7417 * Implements an <input> native component that allows setting these optional 7418 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 7419 * 7420 * If `checked` or `value` are not supplied (or null/undefined), user actions 7421 * that affect the checked state or value will trigger updates to the element. 7422 * 7423 * If they are supplied (and not null/undefined), the rendered element will not 7424 * trigger updates to the element. Instead, the props must change in order for 7425 * the rendered element to be updated. 7426 * 7427 * The rendered element will be initialized as unchecked (or `defaultChecked`) 7428 * with an empty value (or `defaultValue`). 7429 * 7430 * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 7431 */ 7432 var ReactDOMInput = ReactCompositeComponent.createClass({ 7433 displayName: 'ReactDOMInput', 7434 7435 mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], 7436 7437 getInitialState: function() { 7438 var defaultValue = this.props.defaultValue; 7439 return { 7440 checked: this.props.defaultChecked || false, 7441 value: defaultValue != null ? defaultValue : null 7442 }; 7443 }, 7444 7445 shouldComponentUpdate: function() { 7446 // Defer any updates to this component during the `onChange` handler. 7447 return !this._isChanging; 7448 }, 7449 7450 render: function() { 7451 // Clone `this.props` so we don't mutate the input. 7452 var props = merge(this.props); 7453 7454 props.defaultChecked = null; 7455 props.defaultValue = null; 7456 7457 var value = LinkedValueUtils.getValue(this); 7458 props.value = value != null ? value : this.state.value; 7459 7460 var checked = LinkedValueUtils.getChecked(this); 7461 props.checked = checked != null ? checked : this.state.checked; 7462 7463 props.onChange = this._handleChange; 7464 7465 return input(props, this.props.children); 7466 }, 7467 7468 componentDidMount: function() { 7469 var id = ReactMount.getID(this.getDOMNode()); 7470 instancesByReactID[id] = this; 7471 }, 7472 7473 componentWillUnmount: function() { 7474 var rootNode = this.getDOMNode(); 7475 var id = ReactMount.getID(rootNode); 7476 delete instancesByReactID[id]; 7477 }, 7478 7479 componentDidUpdate: function(prevProps, prevState, prevContext) { 7480 var rootNode = this.getDOMNode(); 7481 if (this.props.checked != null) { 7482 DOMPropertyOperations.setValueForProperty( 7483 rootNode, 7484 'checked', 7485 this.props.checked || false 7486 ); 7487 } 7488 7489 var value = LinkedValueUtils.getValue(this); 7490 if (value != null) { 7491 // Cast `value` to a string to ensure the value is set correctly. While 7492 // browsers typically do this as necessary, jsdom doesn't. 7493 DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value); 7494 } 7495 }, 7496 7497 _handleChange: function(event) { 7498 var returnValue; 7499 var onChange = LinkedValueUtils.getOnChange(this); 7500 if (onChange) { 7501 this._isChanging = true; 7502 returnValue = onChange.call(this, event); 7503 this._isChanging = false; 7504 } 7505 this.setState({ 7506 checked: event.target.checked, 7507 value: event.target.value 7508 }); 7509 7510 var name = this.props.name; 7511 if (this.props.type === 'radio' && name != null) { 7512 var rootNode = this.getDOMNode(); 7513 var queryRoot = rootNode; 7514 7515 while (queryRoot.parentNode) { 7516 queryRoot = queryRoot.parentNode; 7517 } 7518 7519 // If `rootNode.form` was non-null, then we could try `form.elements`, 7520 // but that sometimes behaves strangely in IE8. We could also try using 7521 // `form.getElementsByName`, but that will only return direct children 7522 // and won't include inputs that use the HTML5 `form=` attribute. Since 7523 // the input might not even be in a form, let's just use the global 7524 // `querySelectorAll` to ensure we don't miss anything. 7525 var group = queryRoot.querySelectorAll( 7526 'input[name=' + JSON.stringify('' + name) + '][type="radio"]'); 7527 7528 for (var i = 0, groupLen = group.length; i < groupLen; i++) { 7529 var otherNode = group[i]; 7530 if (otherNode === rootNode || 7531 otherNode.form !== rootNode.form) { 7532 continue; 7533 } 7534 var otherID = ReactMount.getID(otherNode); 7535 ("production" !== "development" ? invariant( 7536 otherID, 7537 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 7538 'same `name` is not supported.' 7539 ) : invariant(otherID)); 7540 var otherInstance = instancesByReactID[otherID]; 7541 ("production" !== "development" ? invariant( 7542 otherInstance, 7543 'ReactDOMInput: Unknown radio button ID %s.', 7544 otherID 7545 ) : invariant(otherInstance)); 7546 // In some cases, this will actually change the `checked` state value. 7547 // In other cases, there's no change but this forces a reconcile upon 7548 // which componentDidUpdate will reset the DOM property to whatever it 7549 // should be. 7550 otherInstance.setState({ 7551 checked: false 7552 }); 7553 } 7554 } 7555 7556 return returnValue; 7557 } 7558 7559 }); 7560 7561 module.exports = ReactDOMInput; 7562 7563 },{"./AutoFocusMixin":1,"./DOMPropertyOperations":9,"./LinkedValueUtils":21,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./ReactMount":55,"./invariant":112,"./merge":121}],39:[function(_dereq_,module,exports){ 7564 /** 7565 * Copyright 2013-2014 Facebook, Inc. 7566 * 7567 * Licensed under the Apache License, Version 2.0 (the "License"); 7568 * you may not use this file except in compliance with the License. 7569 * You may obtain a copy of the License at 7570 * 7571 * http://www.apache.org/licenses/LICENSE-2.0 7572 * 7573 * Unless required by applicable law or agreed to in writing, software 7574 * distributed under the License is distributed on an "AS IS" BASIS, 7575 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7576 * See the License for the specific language governing permissions and 7577 * limitations under the License. 7578 * 7579 * @providesModule ReactDOMOption 7580 */ 7581 7582 "use strict"; 7583 7584 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 7585 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 7586 var ReactDOM = _dereq_("./ReactDOM"); 7587 7588 var warning = _dereq_("./warning"); 7589 7590 // Store a reference to the <option> `ReactDOMComponent`. 7591 var option = ReactDOM.option; 7592 7593 /** 7594 * Implements an <option> native component that warns when `selected` is set. 7595 */ 7596 var ReactDOMOption = ReactCompositeComponent.createClass({ 7597 displayName: 'ReactDOMOption', 7598 7599 mixins: [ReactBrowserComponentMixin], 7600 7601 componentWillMount: function() { 7602 // TODO (yungsters): Remove support for `selected` in <option>. 7603 if ("production" !== "development") { 7604 ("production" !== "development" ? warning( 7605 this.props.selected == null, 7606 'Use the `defaultValue` or `value` props on <select> instead of ' + 7607 'setting `selected` on <option>.' 7608 ) : null); 7609 } 7610 }, 7611 7612 render: function() { 7613 return option(this.props, this.props.children); 7614 } 7615 7616 }); 7617 7618 module.exports = ReactDOMOption; 7619 7620 },{"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./warning":134}],40:[function(_dereq_,module,exports){ 7621 /** 7622 * Copyright 2013-2014 Facebook, Inc. 7623 * 7624 * Licensed under the Apache License, Version 2.0 (the "License"); 7625 * you may not use this file except in compliance with the License. 7626 * You may obtain a copy of the License at 7627 * 7628 * http://www.apache.org/licenses/LICENSE-2.0 7629 * 7630 * Unless required by applicable law or agreed to in writing, software 7631 * distributed under the License is distributed on an "AS IS" BASIS, 7632 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7633 * See the License for the specific language governing permissions and 7634 * limitations under the License. 7635 * 7636 * @providesModule ReactDOMSelect 7637 */ 7638 7639 "use strict"; 7640 7641 var AutoFocusMixin = _dereq_("./AutoFocusMixin"); 7642 var LinkedValueUtils = _dereq_("./LinkedValueUtils"); 7643 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 7644 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 7645 var ReactDOM = _dereq_("./ReactDOM"); 7646 7647 var invariant = _dereq_("./invariant"); 7648 var merge = _dereq_("./merge"); 7649 7650 // Store a reference to the <select> `ReactDOMComponent`. 7651 var select = ReactDOM.select; 7652 7653 /** 7654 * Validation function for `value` and `defaultValue`. 7655 * @private 7656 */ 7657 function selectValueType(props, propName, componentName) { 7658 if (props[propName] == null) { 7659 return; 7660 } 7661 if (props.multiple) { 7662 ("production" !== "development" ? invariant( 7663 Array.isArray(props[propName]), 7664 'The `%s` prop supplied to <select> must be an array if `multiple` is ' + 7665 'true.', 7666 propName 7667 ) : invariant(Array.isArray(props[propName]))); 7668 } else { 7669 ("production" !== "development" ? invariant( 7670 !Array.isArray(props[propName]), 7671 'The `%s` prop supplied to <select> must be a scalar value if ' + 7672 '`multiple` is false.', 7673 propName 7674 ) : invariant(!Array.isArray(props[propName]))); 7675 } 7676 } 7677 7678 /** 7679 * If `value` is supplied, updates <option> elements on mount and update. 7680 * @param {ReactComponent} component Instance of ReactDOMSelect 7681 * @param {?*} propValue For uncontrolled components, null/undefined. For 7682 * controlled components, a string (or with `multiple`, a list of strings). 7683 * @private 7684 */ 7685 function updateOptions(component, propValue) { 7686 var multiple = component.props.multiple; 7687 var value = propValue != null ? propValue : component.state.value; 7688 var options = component.getDOMNode().options; 7689 var selectedValue, i, l; 7690 if (multiple) { 7691 selectedValue = {}; 7692 for (i = 0, l = value.length; i < l; ++i) { 7693 selectedValue['' + value[i]] = true; 7694 } 7695 } else { 7696 selectedValue = '' + value; 7697 } 7698 for (i = 0, l = options.length; i < l; i++) { 7699 var selected = multiple ? 7700 selectedValue.hasOwnProperty(options[i].value) : 7701 options[i].value === selectedValue; 7702 7703 if (selected !== options[i].selected) { 7704 options[i].selected = selected; 7705 } 7706 } 7707 } 7708 7709 /** 7710 * Implements a <select> native component that allows optionally setting the 7711 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 7712 * string. If `multiple` is true, the prop must be an array of strings. 7713 * 7714 * If `value` is not supplied (or null/undefined), user actions that change the 7715 * selected option will trigger updates to the rendered options. 7716 * 7717 * If it is supplied (and not null/undefined), the rendered options will not 7718 * update in response to user actions. Instead, the `value` prop must change in 7719 * order for the rendered options to update. 7720 * 7721 * If `defaultValue` is provided, any options with the supplied values will be 7722 * selected. 7723 */ 7724 var ReactDOMSelect = ReactCompositeComponent.createClass({ 7725 displayName: 'ReactDOMSelect', 7726 7727 mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], 7728 7729 propTypes: { 7730 defaultValue: selectValueType, 7731 value: selectValueType 7732 }, 7733 7734 getInitialState: function() { 7735 return {value: this.props.defaultValue || (this.props.multiple ? [] : '')}; 7736 }, 7737 7738 componentWillReceiveProps: function(nextProps) { 7739 if (!this.props.multiple && nextProps.multiple) { 7740 this.setState({value: [this.state.value]}); 7741 } else if (this.props.multiple && !nextProps.multiple) { 7742 this.setState({value: this.state.value[0]}); 7743 } 7744 }, 7745 7746 shouldComponentUpdate: function() { 7747 // Defer any updates to this component during the `onChange` handler. 7748 return !this._isChanging; 7749 }, 7750 7751 render: function() { 7752 // Clone `this.props` so we don't mutate the input. 7753 var props = merge(this.props); 7754 7755 props.onChange = this._handleChange; 7756 props.value = null; 7757 7758 return select(props, this.props.children); 7759 }, 7760 7761 componentDidMount: function() { 7762 updateOptions(this, LinkedValueUtils.getValue(this)); 7763 }, 7764 7765 componentDidUpdate: function() { 7766 var value = LinkedValueUtils.getValue(this); 7767 if (value != null) { 7768 updateOptions(this, value); 7769 } 7770 }, 7771 7772 _handleChange: function(event) { 7773 var returnValue; 7774 var onChange = LinkedValueUtils.getOnChange(this); 7775 if (onChange) { 7776 this._isChanging = true; 7777 returnValue = onChange.call(this, event); 7778 this._isChanging = false; 7779 } 7780 7781 var selectedValue; 7782 if (this.props.multiple) { 7783 selectedValue = []; 7784 var options = event.target.options; 7785 for (var i = 0, l = options.length; i < l; i++) { 7786 if (options[i].selected) { 7787 selectedValue.push(options[i].value); 7788 } 7789 } 7790 } else { 7791 selectedValue = event.target.value; 7792 } 7793 7794 this.setState({value: selectedValue}); 7795 return returnValue; 7796 } 7797 7798 }); 7799 7800 module.exports = ReactDOMSelect; 7801 7802 },{"./AutoFocusMixin":1,"./LinkedValueUtils":21,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./invariant":112,"./merge":121}],41:[function(_dereq_,module,exports){ 7803 /** 7804 * Copyright 2013-2014 Facebook, Inc. 7805 * 7806 * Licensed under the Apache License, Version 2.0 (the "License"); 7807 * you may not use this file except in compliance with the License. 7808 * You may obtain a copy of the License at 7809 * 7810 * http://www.apache.org/licenses/LICENSE-2.0 7811 * 7812 * Unless required by applicable law or agreed to in writing, software 7813 * distributed under the License is distributed on an "AS IS" BASIS, 7814 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7815 * See the License for the specific language governing permissions and 7816 * limitations under the License. 7817 * 7818 * @providesModule ReactDOMSelection 7819 */ 7820 7821 "use strict"; 7822 7823 var getNodeForCharacterOffset = _dereq_("./getNodeForCharacterOffset"); 7824 var getTextContentAccessor = _dereq_("./getTextContentAccessor"); 7825 7826 /** 7827 * Get the appropriate anchor and focus node/offset pairs for IE. 7828 * 7829 * The catch here is that IE's selection API doesn't provide information 7830 * about whether the selection is forward or backward, so we have to 7831 * behave as though it's always forward. 7832 * 7833 * IE text differs from modern selection in that it behaves as though 7834 * block elements end with a new line. This means character offsets will 7835 * differ between the two APIs. 7836 * 7837 * @param {DOMElement} node 7838 * @return {object} 7839 */ 7840 function getIEOffsets(node) { 7841 var selection = document.selection; 7842 var selectedRange = selection.createRange(); 7843 var selectedLength = selectedRange.text.length; 7844 7845 // Duplicate selection so we can move range without breaking user selection. 7846 var fromStart = selectedRange.duplicate(); 7847 fromStart.moveToElementText(node); 7848 fromStart.setEndPoint('EndToStart', selectedRange); 7849 7850 var startOffset = fromStart.text.length; 7851 var endOffset = startOffset + selectedLength; 7852 7853 return { 7854 start: startOffset, 7855 end: endOffset 7856 }; 7857 } 7858 7859 /** 7860 * @param {DOMElement} node 7861 * @return {?object} 7862 */ 7863 function getModernOffsets(node) { 7864 var selection = window.getSelection(); 7865 7866 if (selection.rangeCount === 0) { 7867 return null; 7868 } 7869 7870 var anchorNode = selection.anchorNode; 7871 var anchorOffset = selection.anchorOffset; 7872 var focusNode = selection.focusNode; 7873 var focusOffset = selection.focusOffset; 7874 7875 var currentRange = selection.getRangeAt(0); 7876 var rangeLength = currentRange.toString().length; 7877 7878 var tempRange = currentRange.cloneRange(); 7879 tempRange.selectNodeContents(node); 7880 tempRange.setEnd(currentRange.startContainer, currentRange.startOffset); 7881 7882 var start = tempRange.toString().length; 7883 var end = start + rangeLength; 7884 7885 // Detect whether the selection is backward. 7886 var detectionRange = document.createRange(); 7887 detectionRange.setStart(anchorNode, anchorOffset); 7888 detectionRange.setEnd(focusNode, focusOffset); 7889 var isBackward = detectionRange.collapsed; 7890 detectionRange.detach(); 7891 7892 return { 7893 start: isBackward ? end : start, 7894 end: isBackward ? start : end 7895 }; 7896 } 7897 7898 /** 7899 * @param {DOMElement|DOMTextNode} node 7900 * @param {object} offsets 7901 */ 7902 function setIEOffsets(node, offsets) { 7903 var range = document.selection.createRange().duplicate(); 7904 var start, end; 7905 7906 if (typeof offsets.end === 'undefined') { 7907 start = offsets.start; 7908 end = start; 7909 } else if (offsets.start > offsets.end) { 7910 start = offsets.end; 7911 end = offsets.start; 7912 } else { 7913 start = offsets.start; 7914 end = offsets.end; 7915 } 7916 7917 range.moveToElementText(node); 7918 range.moveStart('character', start); 7919 range.setEndPoint('EndToStart', range); 7920 range.moveEnd('character', end - start); 7921 range.select(); 7922 } 7923 7924 /** 7925 * In modern non-IE browsers, we can support both forward and backward 7926 * selections. 7927 * 7928 * Note: IE10+ supports the Selection object, but it does not support 7929 * the `extend` method, which means that even in modern IE, it's not possible 7930 * to programatically create a backward selection. Thus, for all IE 7931 * versions, we use the old IE API to create our selections. 7932 * 7933 * @param {DOMElement|DOMTextNode} node 7934 * @param {object} offsets 7935 */ 7936 function setModernOffsets(node, offsets) { 7937 var selection = window.getSelection(); 7938 7939 var length = node[getTextContentAccessor()].length; 7940 var start = Math.min(offsets.start, length); 7941 var end = typeof offsets.end === 'undefined' ? 7942 start : Math.min(offsets.end, length); 7943 7944 // IE 11 uses modern selection, but doesn't support the extend method. 7945 // Flip backward selections, so we can set with a single range. 7946 if (!selection.extend && start > end) { 7947 var temp = end; 7948 end = start; 7949 start = temp; 7950 } 7951 7952 var startMarker = getNodeForCharacterOffset(node, start); 7953 var endMarker = getNodeForCharacterOffset(node, end); 7954 7955 if (startMarker && endMarker) { 7956 var range = document.createRange(); 7957 range.setStart(startMarker.node, startMarker.offset); 7958 selection.removeAllRanges(); 7959 7960 if (start > end) { 7961 selection.addRange(range); 7962 selection.extend(endMarker.node, endMarker.offset); 7963 } else { 7964 range.setEnd(endMarker.node, endMarker.offset); 7965 selection.addRange(range); 7966 } 7967 7968 range.detach(); 7969 } 7970 } 7971 7972 var ReactDOMSelection = { 7973 /** 7974 * @param {DOMElement} node 7975 */ 7976 getOffsets: function(node) { 7977 var getOffsets = document.selection ? getIEOffsets : getModernOffsets; 7978 return getOffsets(node); 7979 }, 7980 7981 /** 7982 * @param {DOMElement|DOMTextNode} node 7983 * @param {object} offsets 7984 */ 7985 setOffsets: function(node, offsets) { 7986 var setOffsets = document.selection ? setIEOffsets : setModernOffsets; 7987 setOffsets(node, offsets); 7988 } 7989 }; 7990 7991 module.exports = ReactDOMSelection; 7992 7993 },{"./getNodeForCharacterOffset":106,"./getTextContentAccessor":108}],42:[function(_dereq_,module,exports){ 7994 /** 7995 * Copyright 2013-2014 Facebook, Inc. 7996 * 7997 * Licensed under the Apache License, Version 2.0 (the "License"); 7998 * you may not use this file except in compliance with the License. 7999 * You may obtain a copy of the License at 8000 * 8001 * http://www.apache.org/licenses/LICENSE-2.0 8002 * 8003 * Unless required by applicable law or agreed to in writing, software 8004 * distributed under the License is distributed on an "AS IS" BASIS, 8005 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8006 * See the License for the specific language governing permissions and 8007 * limitations under the License. 8008 * 8009 * @providesModule ReactDOMTextarea 8010 */ 8011 8012 "use strict"; 8013 8014 var AutoFocusMixin = _dereq_("./AutoFocusMixin"); 8015 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 8016 var LinkedValueUtils = _dereq_("./LinkedValueUtils"); 8017 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 8018 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 8019 var ReactDOM = _dereq_("./ReactDOM"); 8020 8021 var invariant = _dereq_("./invariant"); 8022 var merge = _dereq_("./merge"); 8023 8024 var warning = _dereq_("./warning"); 8025 8026 // Store a reference to the <textarea> `ReactDOMComponent`. 8027 var textarea = ReactDOM.textarea; 8028 8029 /** 8030 * Implements a <textarea> native component that allows setting `value`, and 8031 * `defaultValue`. This differs from the traditional DOM API because value is 8032 * usually set as PCDATA children. 8033 * 8034 * If `value` is not supplied (or null/undefined), user actions that affect the 8035 * value will trigger updates to the element. 8036 * 8037 * If `value` is supplied (and not null/undefined), the rendered element will 8038 * not trigger updates to the element. Instead, the `value` prop must change in 8039 * order for the rendered element to be updated. 8040 * 8041 * The rendered element will be initialized with an empty value, the prop 8042 * `defaultValue` if specified, or the children content (deprecated). 8043 */ 8044 var ReactDOMTextarea = ReactCompositeComponent.createClass({ 8045 displayName: 'ReactDOMTextarea', 8046 8047 mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin], 8048 8049 getInitialState: function() { 8050 var defaultValue = this.props.defaultValue; 8051 // TODO (yungsters): Remove support for children content in <textarea>. 8052 var children = this.props.children; 8053 if (children != null) { 8054 if ("production" !== "development") { 8055 ("production" !== "development" ? warning( 8056 false, 8057 'Use the `defaultValue` or `value` props instead of setting ' + 8058 'children on <textarea>.' 8059 ) : null); 8060 } 8061 ("production" !== "development" ? invariant( 8062 defaultValue == null, 8063 'If you supply `defaultValue` on a <textarea>, do not pass children.' 8064 ) : invariant(defaultValue == null)); 8065 if (Array.isArray(children)) { 8066 ("production" !== "development" ? invariant( 8067 children.length <= 1, 8068 '<textarea> can only have at most one child.' 8069 ) : invariant(children.length <= 1)); 8070 children = children[0]; 8071 } 8072 8073 defaultValue = '' + children; 8074 } 8075 if (defaultValue == null) { 8076 defaultValue = ''; 8077 } 8078 var value = LinkedValueUtils.getValue(this); 8079 return { 8080 // We save the initial value so that `ReactDOMComponent` doesn't update 8081 // `textContent` (unnecessary since we update value). 8082 // The initial value can be a boolean or object so that's why it's 8083 // forced to be a string. 8084 initialValue: '' + (value != null ? value : defaultValue), 8085 value: defaultValue 8086 }; 8087 }, 8088 8089 shouldComponentUpdate: function() { 8090 // Defer any updates to this component during the `onChange` handler. 8091 return !this._isChanging; 8092 }, 8093 8094 render: function() { 8095 // Clone `this.props` so we don't mutate the input. 8096 var props = merge(this.props); 8097 var value = LinkedValueUtils.getValue(this); 8098 8099 ("production" !== "development" ? invariant( 8100 props.dangerouslySetInnerHTML == null, 8101 '`dangerouslySetInnerHTML` does not make sense on <textarea>.' 8102 ) : invariant(props.dangerouslySetInnerHTML == null)); 8103 8104 props.defaultValue = null; 8105 props.value = value != null ? value : this.state.value; 8106 props.onChange = this._handleChange; 8107 8108 // Always set children to the same thing. In IE9, the selection range will 8109 // get reset if `textContent` is mutated. 8110 return textarea(props, this.state.initialValue); 8111 }, 8112 8113 componentDidUpdate: function(prevProps, prevState, prevContext) { 8114 var value = LinkedValueUtils.getValue(this); 8115 if (value != null) { 8116 var rootNode = this.getDOMNode(); 8117 // Cast `value` to a string to ensure the value is set correctly. While 8118 // browsers typically do this as necessary, jsdom doesn't. 8119 DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value); 8120 } 8121 }, 8122 8123 _handleChange: function(event) { 8124 var returnValue; 8125 var onChange = LinkedValueUtils.getOnChange(this); 8126 if (onChange) { 8127 this._isChanging = true; 8128 returnValue = onChange.call(this, event); 8129 this._isChanging = false; 8130 } 8131 this.setState({value: event.target.value}); 8132 return returnValue; 8133 } 8134 8135 }); 8136 8137 module.exports = ReactDOMTextarea; 8138 8139 },{"./AutoFocusMixin":1,"./DOMPropertyOperations":9,"./LinkedValueUtils":21,"./ReactBrowserComponentMixin":25,"./ReactCompositeComponent":29,"./ReactDOM":32,"./invariant":112,"./merge":121,"./warning":134}],43:[function(_dereq_,module,exports){ 8140 /** 8141 * Copyright 2013-2014 Facebook, Inc. 8142 * 8143 * Licensed under the Apache License, Version 2.0 (the "License"); 8144 * you may not use this file except in compliance with the License. 8145 * You may obtain a copy of the License at 8146 * 8147 * http://www.apache.org/licenses/LICENSE-2.0 8148 * 8149 * Unless required by applicable law or agreed to in writing, software 8150 * distributed under the License is distributed on an "AS IS" BASIS, 8151 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8152 * See the License for the specific language governing permissions and 8153 * limitations under the License. 8154 * 8155 * @providesModule ReactDefaultBatchingStrategy 8156 */ 8157 8158 "use strict"; 8159 8160 var ReactUpdates = _dereq_("./ReactUpdates"); 8161 var Transaction = _dereq_("./Transaction"); 8162 8163 var emptyFunction = _dereq_("./emptyFunction"); 8164 var mixInto = _dereq_("./mixInto"); 8165 8166 var RESET_BATCHED_UPDATES = { 8167 initialize: emptyFunction, 8168 close: function() { 8169 ReactDefaultBatchingStrategy.isBatchingUpdates = false; 8170 } 8171 }; 8172 8173 var FLUSH_BATCHED_UPDATES = { 8174 initialize: emptyFunction, 8175 close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates) 8176 }; 8177 8178 var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES]; 8179 8180 function ReactDefaultBatchingStrategyTransaction() { 8181 this.reinitializeTransaction(); 8182 } 8183 8184 mixInto(ReactDefaultBatchingStrategyTransaction, Transaction.Mixin); 8185 mixInto(ReactDefaultBatchingStrategyTransaction, { 8186 getTransactionWrappers: function() { 8187 return TRANSACTION_WRAPPERS; 8188 } 8189 }); 8190 8191 var transaction = new ReactDefaultBatchingStrategyTransaction(); 8192 8193 var ReactDefaultBatchingStrategy = { 8194 isBatchingUpdates: false, 8195 8196 /** 8197 * Call the provided function in a context within which calls to `setState` 8198 * and friends are batched such that components aren't updated unnecessarily. 8199 */ 8200 batchedUpdates: function(callback, param) { 8201 var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates; 8202 8203 ReactDefaultBatchingStrategy.isBatchingUpdates = true; 8204 8205 // The code is written this way to avoid extra allocations 8206 if (alreadyBatchingUpdates) { 8207 callback(param); 8208 } else { 8209 transaction.perform(callback, null, param); 8210 } 8211 } 8212 }; 8213 8214 module.exports = ReactDefaultBatchingStrategy; 8215 8216 },{"./ReactUpdates":71,"./Transaction":85,"./emptyFunction":96,"./mixInto":124}],44:[function(_dereq_,module,exports){ 8217 /** 8218 * Copyright 2013-2014 Facebook, Inc. 8219 * 8220 * Licensed under the Apache License, Version 2.0 (the "License"); 8221 * you may not use this file except in compliance with the License. 8222 * You may obtain a copy of the License at 8223 * 8224 * http://www.apache.org/licenses/LICENSE-2.0 8225 * 8226 * Unless required by applicable law or agreed to in writing, software 8227 * distributed under the License is distributed on an "AS IS" BASIS, 8228 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8229 * See the License for the specific language governing permissions and 8230 * limitations under the License. 8231 * 8232 * @providesModule ReactDefaultInjection 8233 */ 8234 8235 "use strict"; 8236 8237 var ReactInjection = _dereq_("./ReactInjection"); 8238 8239 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 8240 8241 var DefaultDOMPropertyConfig = _dereq_("./DefaultDOMPropertyConfig"); 8242 8243 var ChangeEventPlugin = _dereq_("./ChangeEventPlugin"); 8244 var ClientReactRootIndex = _dereq_("./ClientReactRootIndex"); 8245 var CompositionEventPlugin = _dereq_("./CompositionEventPlugin"); 8246 var DefaultEventPluginOrder = _dereq_("./DefaultEventPluginOrder"); 8247 var EnterLeaveEventPlugin = _dereq_("./EnterLeaveEventPlugin"); 8248 var MobileSafariClickEventPlugin = _dereq_("./MobileSafariClickEventPlugin"); 8249 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 8250 var ReactComponentBrowserEnvironment = 8251 _dereq_("./ReactComponentBrowserEnvironment"); 8252 var ReactEventTopLevelCallback = _dereq_("./ReactEventTopLevelCallback"); 8253 var ReactDOM = _dereq_("./ReactDOM"); 8254 var ReactDOMButton = _dereq_("./ReactDOMButton"); 8255 var ReactDOMForm = _dereq_("./ReactDOMForm"); 8256 var ReactDOMImg = _dereq_("./ReactDOMImg"); 8257 var ReactDOMInput = _dereq_("./ReactDOMInput"); 8258 var ReactDOMOption = _dereq_("./ReactDOMOption"); 8259 var ReactDOMSelect = _dereq_("./ReactDOMSelect"); 8260 var ReactDOMTextarea = _dereq_("./ReactDOMTextarea"); 8261 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 8262 var ReactMount = _dereq_("./ReactMount"); 8263 var SelectEventPlugin = _dereq_("./SelectEventPlugin"); 8264 var ServerReactRootIndex = _dereq_("./ServerReactRootIndex"); 8265 var SimpleEventPlugin = _dereq_("./SimpleEventPlugin"); 8266 8267 var ReactDefaultBatchingStrategy = _dereq_("./ReactDefaultBatchingStrategy"); 8268 8269 var createFullPageComponent = _dereq_("./createFullPageComponent"); 8270 8271 function inject() { 8272 ReactInjection.EventEmitter.injectTopLevelCallbackCreator( 8273 ReactEventTopLevelCallback 8274 ); 8275 8276 /** 8277 * Inject modules for resolving DOM hierarchy and plugin ordering. 8278 */ 8279 ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder); 8280 ReactInjection.EventPluginHub.injectInstanceHandle(ReactInstanceHandles); 8281 ReactInjection.EventPluginHub.injectMount(ReactMount); 8282 8283 /** 8284 * Some important event plugins included by default (without having to require 8285 * them). 8286 */ 8287 ReactInjection.EventPluginHub.injectEventPluginsByName({ 8288 SimpleEventPlugin: SimpleEventPlugin, 8289 EnterLeaveEventPlugin: EnterLeaveEventPlugin, 8290 ChangeEventPlugin: ChangeEventPlugin, 8291 CompositionEventPlugin: CompositionEventPlugin, 8292 MobileSafariClickEventPlugin: MobileSafariClickEventPlugin, 8293 SelectEventPlugin: SelectEventPlugin 8294 }); 8295 8296 ReactInjection.DOM.injectComponentClasses({ 8297 button: ReactDOMButton, 8298 form: ReactDOMForm, 8299 img: ReactDOMImg, 8300 input: ReactDOMInput, 8301 option: ReactDOMOption, 8302 select: ReactDOMSelect, 8303 textarea: ReactDOMTextarea, 8304 8305 html: createFullPageComponent(ReactDOM.html), 8306 head: createFullPageComponent(ReactDOM.head), 8307 title: createFullPageComponent(ReactDOM.title), 8308 body: createFullPageComponent(ReactDOM.body) 8309 }); 8310 8311 8312 // This needs to happen after createFullPageComponent() otherwise the mixin 8313 // gets double injected. 8314 ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin); 8315 8316 ReactInjection.DOMProperty.injectDOMPropertyConfig(DefaultDOMPropertyConfig); 8317 8318 ReactInjection.Updates.injectBatchingStrategy( 8319 ReactDefaultBatchingStrategy 8320 ); 8321 8322 ReactInjection.RootIndex.injectCreateReactRootIndex( 8323 ExecutionEnvironment.canUseDOM ? 8324 ClientReactRootIndex.createReactRootIndex : 8325 ServerReactRootIndex.createReactRootIndex 8326 ); 8327 8328 ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment); 8329 8330 if ("production" !== "development") { 8331 var url = (ExecutionEnvironment.canUseDOM && window.location.href) || ''; 8332 if ((/[?&]react_perf\b/).test(url)) { 8333 var ReactDefaultPerf = _dereq_("./ReactDefaultPerf"); 8334 ReactDefaultPerf.start(); 8335 } 8336 } 8337 } 8338 8339 module.exports = { 8340 inject: inject 8341 }; 8342 8343 },{"./ChangeEventPlugin":4,"./ClientReactRootIndex":5,"./CompositionEventPlugin":6,"./DefaultDOMPropertyConfig":11,"./DefaultEventPluginOrder":12,"./EnterLeaveEventPlugin":13,"./ExecutionEnvironment":20,"./MobileSafariClickEventPlugin":22,"./ReactBrowserComponentMixin":25,"./ReactComponentBrowserEnvironment":28,"./ReactDOM":32,"./ReactDOMButton":33,"./ReactDOMForm":35,"./ReactDOMImg":37,"./ReactDOMInput":38,"./ReactDOMOption":39,"./ReactDOMSelect":40,"./ReactDOMTextarea":42,"./ReactDefaultBatchingStrategy":43,"./ReactDefaultPerf":45,"./ReactEventTopLevelCallback":50,"./ReactInjection":51,"./ReactInstanceHandles":53,"./ReactMount":55,"./SelectEventPlugin":72,"./ServerReactRootIndex":73,"./SimpleEventPlugin":74,"./createFullPageComponent":92}],45:[function(_dereq_,module,exports){ 8344 /** 8345 * Copyright 2013-2014 Facebook, Inc. 8346 * 8347 * Licensed under the Apache License, Version 2.0 (the "License"); 8348 * you may not use this file except in compliance with the License. 8349 * You may obtain a copy of the License at 8350 * 8351 * http://www.apache.org/licenses/LICENSE-2.0 8352 * 8353 * Unless required by applicable law or agreed to in writing, software 8354 * distributed under the License is distributed on an "AS IS" BASIS, 8355 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8356 * See the License for the specific language governing permissions and 8357 * limitations under the License. 8358 * 8359 * @providesModule ReactDefaultPerf 8360 * @typechecks static-only 8361 */ 8362 8363 "use strict"; 8364 8365 var DOMProperty = _dereq_("./DOMProperty"); 8366 var ReactDefaultPerfAnalysis = _dereq_("./ReactDefaultPerfAnalysis"); 8367 var ReactMount = _dereq_("./ReactMount"); 8368 var ReactPerf = _dereq_("./ReactPerf"); 8369 8370 var performanceNow = _dereq_("./performanceNow"); 8371 8372 function roundFloat(val) { 8373 return Math.floor(val * 100) / 100; 8374 } 8375 8376 var ReactDefaultPerf = { 8377 _allMeasurements: [], // last item in the list is the current one 8378 _injected: false, 8379 8380 start: function() { 8381 if (!ReactDefaultPerf._injected) { 8382 ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure); 8383 } 8384 8385 ReactDefaultPerf._allMeasurements.length = 0; 8386 ReactPerf.enableMeasure = true; 8387 }, 8388 8389 stop: function() { 8390 ReactPerf.enableMeasure = false; 8391 }, 8392 8393 getLastMeasurements: function() { 8394 return ReactDefaultPerf._allMeasurements; 8395 }, 8396 8397 printExclusive: function(measurements) { 8398 measurements = measurements || ReactDefaultPerf._allMeasurements; 8399 var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements); 8400 console.table(summary.map(function(item) { 8401 return { 8402 'Component class name': item.componentName, 8403 'Total inclusive time (ms)': roundFloat(item.inclusive), 8404 'Total exclusive time (ms)': roundFloat(item.exclusive), 8405 'Exclusive time per instance (ms)': roundFloat(item.exclusive / item.count), 8406 'Instances': item.count 8407 }; 8408 })); 8409 console.log( 8410 'Total time:', 8411 ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms' 8412 ); 8413 }, 8414 8415 printInclusive: function(measurements) { 8416 measurements = measurements || ReactDefaultPerf._allMeasurements; 8417 var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements); 8418 console.table(summary.map(function(item) { 8419 return { 8420 'Owner > component': item.componentName, 8421 'Inclusive time (ms)': roundFloat(item.time), 8422 'Instances': item.count 8423 }; 8424 })); 8425 console.log( 8426 'Total time:', 8427 ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms' 8428 ); 8429 }, 8430 8431 printWasted: function(measurements) { 8432 measurements = measurements || ReactDefaultPerf._allMeasurements; 8433 var summary = ReactDefaultPerfAnalysis.getInclusiveSummary( 8434 measurements, 8435 true 8436 ); 8437 console.table(summary.map(function(item) { 8438 return { 8439 'Owner > component': item.componentName, 8440 'Wasted time (ms)': item.time, 8441 'Instances': item.count 8442 }; 8443 })); 8444 console.log( 8445 'Total time:', 8446 ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms' 8447 ); 8448 }, 8449 8450 printDOM: function(measurements) { 8451 measurements = measurements || ReactDefaultPerf._allMeasurements; 8452 var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements); 8453 console.table(summary.map(function(item) { 8454 var result = {}; 8455 result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id; 8456 result['type'] = item.type; 8457 result['args'] = JSON.stringify(item.args); 8458 return result; 8459 })); 8460 console.log( 8461 'Total time:', 8462 ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms' 8463 ); 8464 }, 8465 8466 _recordWrite: function(id, fnName, totalTime, args) { 8467 // TODO: totalTime isn't that useful since it doesn't count paints/reflows 8468 var writes = 8469 ReactDefaultPerf 8470 ._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1] 8471 .writes; 8472 writes[id] = writes[id] || []; 8473 writes[id].push({ 8474 type: fnName, 8475 time: totalTime, 8476 args: args 8477 }); 8478 }, 8479 8480 measure: function(moduleName, fnName, func) { 8481 return function() {var args=Array.prototype.slice.call(arguments,0); 8482 var totalTime; 8483 var rv; 8484 var start; 8485 8486 if (fnName === '_renderNewRootComponent' || 8487 fnName === 'flushBatchedUpdates') { 8488 // A "measurement" is a set of metrics recorded for each flush. We want 8489 // to group the metrics for a given flush together so we can look at the 8490 // components that rendered and the DOM operations that actually 8491 // happened to determine the amount of "wasted work" performed. 8492 ReactDefaultPerf._allMeasurements.push({ 8493 exclusive: {}, 8494 inclusive: {}, 8495 counts: {}, 8496 writes: {}, 8497 displayNames: {}, 8498 totalTime: 0 8499 }); 8500 start = performanceNow(); 8501 rv = func.apply(this, args); 8502 ReactDefaultPerf._allMeasurements[ 8503 ReactDefaultPerf._allMeasurements.length - 1 8504 ].totalTime = performanceNow() - start; 8505 return rv; 8506 } else if (moduleName === 'ReactDOMIDOperations' || 8507 moduleName === 'ReactComponentBrowserEnvironment') { 8508 start = performanceNow(); 8509 rv = func.apply(this, args); 8510 totalTime = performanceNow() - start; 8511 8512 if (fnName === 'mountImageIntoNode') { 8513 var mountID = ReactMount.getID(args[1]); 8514 ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]); 8515 } else if (fnName === 'dangerouslyProcessChildrenUpdates') { 8516 // special format 8517 args[0].forEach(function(update) { 8518 var writeArgs = {}; 8519 if (update.fromIndex !== null) { 8520 writeArgs.fromIndex = update.fromIndex; 8521 } 8522 if (update.toIndex !== null) { 8523 writeArgs.toIndex = update.toIndex; 8524 } 8525 if (update.textContent !== null) { 8526 writeArgs.textContent = update.textContent; 8527 } 8528 if (update.markupIndex !== null) { 8529 writeArgs.markup = args[1][update.markupIndex]; 8530 } 8531 ReactDefaultPerf._recordWrite( 8532 update.parentID, 8533 update.type, 8534 totalTime, 8535 writeArgs 8536 ); 8537 }); 8538 } else { 8539 // basic format 8540 ReactDefaultPerf._recordWrite( 8541 args[0], 8542 fnName, 8543 totalTime, 8544 Array.prototype.slice.call(args, 1) 8545 ); 8546 } 8547 return rv; 8548 } else if (moduleName === 'ReactCompositeComponent' && ( 8549 fnName === 'mountComponent' || 8550 fnName === 'updateComponent' || // TODO: receiveComponent()? 8551 fnName === '_renderValidatedComponent')) { 8552 8553 var rootNodeID = fnName === 'mountComponent' ? 8554 args[0] : 8555 this._rootNodeID; 8556 var isRender = fnName === '_renderValidatedComponent'; 8557 var entry = ReactDefaultPerf._allMeasurements[ 8558 ReactDefaultPerf._allMeasurements.length - 1 8559 ]; 8560 8561 if (isRender) { 8562 entry.counts[rootNodeID] = entry.counts[rootNodeID] || 0; 8563 entry.counts[rootNodeID] += 1; 8564 } 8565 8566 start = performanceNow(); 8567 rv = func.apply(this, args); 8568 totalTime = performanceNow() - start; 8569 8570 var typeOfLog = isRender ? entry.exclusive : entry.inclusive; 8571 typeOfLog[rootNodeID] = typeOfLog[rootNodeID] || 0; 8572 typeOfLog[rootNodeID] += totalTime; 8573 8574 entry.displayNames[rootNodeID] = { 8575 current: this.constructor.displayName, 8576 owner: this._owner ? this._owner.constructor.displayName : '<root>' 8577 }; 8578 8579 return rv; 8580 } else { 8581 return func.apply(this, args); 8582 } 8583 }; 8584 } 8585 }; 8586 8587 module.exports = ReactDefaultPerf; 8588 8589 },{"./DOMProperty":8,"./ReactDefaultPerfAnalysis":46,"./ReactMount":55,"./ReactPerf":60,"./performanceNow":129}],46:[function(_dereq_,module,exports){ 8590 /** 8591 * Copyright 2013-2014 Facebook, Inc. 8592 * 8593 * Licensed under the Apache License, Version 2.0 (the "License"); 8594 * you may not use this file except in compliance with the License. 8595 * You may obtain a copy of the License at 8596 * 8597 * http://www.apache.org/licenses/LICENSE-2.0 8598 * 8599 * Unless required by applicable law or agreed to in writing, software 8600 * distributed under the License is distributed on an "AS IS" BASIS, 8601 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8602 * See the License for the specific language governing permissions and 8603 * limitations under the License. 8604 * 8605 * @providesModule ReactDefaultPerfAnalysis 8606 */ 8607 8608 var merge = _dereq_("./merge"); 8609 8610 // Don't try to save users less than 1.2ms (a number I made up) 8611 var DONT_CARE_THRESHOLD = 1.2; 8612 var DOM_OPERATION_TYPES = { 8613 'mountImageIntoNode': 'set innerHTML', 8614 INSERT_MARKUP: 'set innerHTML', 8615 MOVE_EXISTING: 'move', 8616 REMOVE_NODE: 'remove', 8617 TEXT_CONTENT: 'set textContent', 8618 'updatePropertyByID': 'update attribute', 8619 'deletePropertyByID': 'delete attribute', 8620 'updateStylesByID': 'update styles', 8621 'updateInnerHTMLByID': 'set innerHTML', 8622 'dangerouslyReplaceNodeWithMarkupByID': 'replace' 8623 }; 8624 8625 function getTotalTime(measurements) { 8626 // TODO: return number of DOM ops? could be misleading. 8627 // TODO: measure dropped frames after reconcile? 8628 // TODO: log total time of each reconcile and the top-level component 8629 // class that triggered it. 8630 var totalTime = 0; 8631 for (var i = 0; i < measurements.length; i++) { 8632 var measurement = measurements[i]; 8633 totalTime += measurement.totalTime; 8634 } 8635 return totalTime; 8636 } 8637 8638 function getDOMSummary(measurements) { 8639 var items = []; 8640 for (var i = 0; i < measurements.length; i++) { 8641 var measurement = measurements[i]; 8642 var id; 8643 8644 for (id in measurement.writes) { 8645 measurement.writes[id].forEach(function(write) { 8646 items.push({ 8647 id: id, 8648 type: DOM_OPERATION_TYPES[write.type] || write.type, 8649 args: write.args 8650 }); 8651 }); 8652 } 8653 } 8654 return items; 8655 } 8656 8657 function getExclusiveSummary(measurements) { 8658 var candidates = {}; 8659 var displayName; 8660 8661 for (var i = 0; i < measurements.length; i++) { 8662 var measurement = measurements[i]; 8663 var allIDs = merge(measurement.exclusive, measurement.inclusive); 8664 8665 for (var id in allIDs) { 8666 displayName = measurement.displayNames[id].current; 8667 8668 candidates[displayName] = candidates[displayName] || { 8669 componentName: displayName, 8670 inclusive: 0, 8671 exclusive: 0, 8672 count: 0 8673 }; 8674 if (measurement.exclusive[id]) { 8675 candidates[displayName].exclusive += measurement.exclusive[id]; 8676 } 8677 if (measurement.inclusive[id]) { 8678 candidates[displayName].inclusive += measurement.inclusive[id]; 8679 } 8680 if (measurement.counts[id]) { 8681 candidates[displayName].count += measurement.counts[id]; 8682 } 8683 } 8684 } 8685 8686 // Now make a sorted array with the results. 8687 var arr = []; 8688 for (displayName in candidates) { 8689 if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) { 8690 arr.push(candidates[displayName]); 8691 } 8692 } 8693 8694 arr.sort(function(a, b) { 8695 return b.exclusive - a.exclusive; 8696 }); 8697 8698 return arr; 8699 } 8700 8701 function getInclusiveSummary(measurements, onlyClean) { 8702 var candidates = {}; 8703 var inclusiveKey; 8704 8705 for (var i = 0; i < measurements.length; i++) { 8706 var measurement = measurements[i]; 8707 var allIDs = merge(measurement.exclusive, measurement.inclusive); 8708 var cleanComponents; 8709 8710 if (onlyClean) { 8711 cleanComponents = getUnchangedComponents(measurement); 8712 } 8713 8714 for (var id in allIDs) { 8715 if (onlyClean && !cleanComponents[id]) { 8716 continue; 8717 } 8718 8719 var displayName = measurement.displayNames[id]; 8720 8721 // Inclusive time is not useful for many components without knowing where 8722 // they are instantiated. So we aggregate inclusive time with both the 8723 // owner and current displayName as the key. 8724 inclusiveKey = displayName.owner + ' > ' + displayName.current; 8725 8726 candidates[inclusiveKey] = candidates[inclusiveKey] || { 8727 componentName: inclusiveKey, 8728 time: 0, 8729 count: 0 8730 }; 8731 8732 if (measurement.inclusive[id]) { 8733 candidates[inclusiveKey].time += measurement.inclusive[id]; 8734 } 8735 if (measurement.counts[id]) { 8736 candidates[inclusiveKey].count += measurement.counts[id]; 8737 } 8738 } 8739 } 8740 8741 // Now make a sorted array with the results. 8742 var arr = []; 8743 for (inclusiveKey in candidates) { 8744 if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) { 8745 arr.push(candidates[inclusiveKey]); 8746 } 8747 } 8748 8749 arr.sort(function(a, b) { 8750 return b.time - a.time; 8751 }); 8752 8753 return arr; 8754 } 8755 8756 function getUnchangedComponents(measurement) { 8757 // For a given reconcile, look at which components did not actually 8758 // render anything to the DOM and return a mapping of their ID to 8759 // the amount of time it took to render the entire subtree. 8760 var cleanComponents = {}; 8761 var dirtyLeafIDs = Object.keys(measurement.writes); 8762 var allIDs = merge(measurement.exclusive, measurement.inclusive); 8763 8764 for (var id in allIDs) { 8765 var isDirty = false; 8766 // For each component that rendered, see if a component that triggerd 8767 // a DOM op is in its subtree. 8768 for (var i = 0; i < dirtyLeafIDs.length; i++) { 8769 if (dirtyLeafIDs[i].indexOf(id) === 0) { 8770 isDirty = true; 8771 break; 8772 } 8773 } 8774 if (!isDirty && measurement.counts[id] > 0) { 8775 cleanComponents[id] = true; 8776 } 8777 } 8778 return cleanComponents; 8779 } 8780 8781 var ReactDefaultPerfAnalysis = { 8782 getExclusiveSummary: getExclusiveSummary, 8783 getInclusiveSummary: getInclusiveSummary, 8784 getDOMSummary: getDOMSummary, 8785 getTotalTime: getTotalTime 8786 }; 8787 8788 module.exports = ReactDefaultPerfAnalysis; 8789 8790 },{"./merge":121}],47:[function(_dereq_,module,exports){ 8791 /** 8792 * Copyright 2013-2014 Facebook, Inc. 8793 * 8794 * Licensed under the Apache License, Version 2.0 (the "License"); 8795 * you may not use this file except in compliance with the License. 8796 * You may obtain a copy of the License at 8797 * 8798 * http://www.apache.org/licenses/LICENSE-2.0 8799 * 8800 * Unless required by applicable law or agreed to in writing, software 8801 * distributed under the License is distributed on an "AS IS" BASIS, 8802 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8803 * See the License for the specific language governing permissions and 8804 * limitations under the License. 8805 * 8806 * @providesModule ReactErrorUtils 8807 * @typechecks 8808 */ 8809 8810 "use strict"; 8811 8812 var ReactErrorUtils = { 8813 /** 8814 * Creates a guarded version of a function. This is supposed to make debugging 8815 * of event handlers easier. To aid debugging with the browser's debugger, 8816 * this currently simply returns the original function. 8817 * 8818 * @param {function} func Function to be executed 8819 * @param {string} name The name of the guard 8820 * @return {function} 8821 */ 8822 guard: function(func, name) { 8823 return func; 8824 } 8825 }; 8826 8827 module.exports = ReactErrorUtils; 8828 8829 },{}],48:[function(_dereq_,module,exports){ 8830 /** 8831 * Copyright 2013-2014 Facebook, Inc. 8832 * 8833 * Licensed under the Apache License, Version 2.0 (the "License"); 8834 * you may not use this file except in compliance with the License. 8835 * You may obtain a copy of the License at 8836 * 8837 * http://www.apache.org/licenses/LICENSE-2.0 8838 * 8839 * Unless required by applicable law or agreed to in writing, software 8840 * distributed under the License is distributed on an "AS IS" BASIS, 8841 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8842 * See the License for the specific language governing permissions and 8843 * limitations under the License. 8844 * 8845 * @providesModule ReactEventEmitter 8846 * @typechecks static-only 8847 */ 8848 8849 "use strict"; 8850 8851 var EventConstants = _dereq_("./EventConstants"); 8852 var EventListener = _dereq_("./EventListener"); 8853 var EventPluginHub = _dereq_("./EventPluginHub"); 8854 var EventPluginRegistry = _dereq_("./EventPluginRegistry"); 8855 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 8856 var ReactEventEmitterMixin = _dereq_("./ReactEventEmitterMixin"); 8857 var ViewportMetrics = _dereq_("./ViewportMetrics"); 8858 8859 var invariant = _dereq_("./invariant"); 8860 var isEventSupported = _dereq_("./isEventSupported"); 8861 var merge = _dereq_("./merge"); 8862 8863 /** 8864 * Summary of `ReactEventEmitter` event handling: 8865 * 8866 * - Top-level delegation is used to trap native browser events. We normalize 8867 * and de-duplicate events to account for browser quirks. 8868 * 8869 * - Forward these native events (with the associated top-level type used to 8870 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want 8871 * to extract any synthetic events. 8872 * 8873 * - The `EventPluginHub` will then process each event by annotating them with 8874 * "dispatches", a sequence of listeners and IDs that care about that event. 8875 * 8876 * - The `EventPluginHub` then dispatches the events. 8877 * 8878 * Overview of React and the event system: 8879 * 8880 * . 8881 * +------------+ . 8882 * | DOM | . 8883 * +------------+ . +-----------+ 8884 * + . +--------+|SimpleEvent| 8885 * | . | |Plugin | 8886 * +-----|------+ . v +-----------+ 8887 * | | | . +--------------+ +------------+ 8888 * | +-----------.--->|EventPluginHub| | Event | 8889 * | | . | | +-----------+ | Propagators| 8890 * | ReactEvent | . | | |TapEvent | |------------| 8891 * | Emitter | . | |<---+|Plugin | |other plugin| 8892 * | | . | | +-----------+ | utilities | 8893 * | +-----------.--->| | +------------+ 8894 * | | | . +--------------+ 8895 * +-----|------+ . ^ +-----------+ 8896 * | . | |Enter/Leave| 8897 * + . +-------+|Plugin | 8898 * +-------------+ . +-----------+ 8899 * | application | . 8900 * |-------------| . 8901 * | | . 8902 * | | . 8903 * +-------------+ . 8904 * . 8905 * React Core . General Purpose Event Plugin System 8906 */ 8907 8908 var alreadyListeningTo = {}; 8909 var isMonitoringScrollValue = false; 8910 var reactTopListenersCounter = 0; 8911 8912 // For events like 'submit' which don't consistently bubble (which we trap at a 8913 // lower node than `document`), binding at `document` would cause duplicate 8914 // events so we don't include them here 8915 var topEventMapping = { 8916 topBlur: 'blur', 8917 topChange: 'change', 8918 topClick: 'click', 8919 topCompositionEnd: 'compositionend', 8920 topCompositionStart: 'compositionstart', 8921 topCompositionUpdate: 'compositionupdate', 8922 topContextMenu: 'contextmenu', 8923 topCopy: 'copy', 8924 topCut: 'cut', 8925 topDoubleClick: 'dblclick', 8926 topDrag: 'drag', 8927 topDragEnd: 'dragend', 8928 topDragEnter: 'dragenter', 8929 topDragExit: 'dragexit', 8930 topDragLeave: 'dragleave', 8931 topDragOver: 'dragover', 8932 topDragStart: 'dragstart', 8933 topDrop: 'drop', 8934 topFocus: 'focus', 8935 topInput: 'input', 8936 topKeyDown: 'keydown', 8937 topKeyPress: 'keypress', 8938 topKeyUp: 'keyup', 8939 topMouseDown: 'mousedown', 8940 topMouseMove: 'mousemove', 8941 topMouseOut: 'mouseout', 8942 topMouseOver: 'mouseover', 8943 topMouseUp: 'mouseup', 8944 topPaste: 'paste', 8945 topScroll: 'scroll', 8946 topSelectionChange: 'selectionchange', 8947 topTouchCancel: 'touchcancel', 8948 topTouchEnd: 'touchend', 8949 topTouchMove: 'touchmove', 8950 topTouchStart: 'touchstart', 8951 topWheel: 'wheel' 8952 }; 8953 8954 /** 8955 * To ensure no conflicts with other potential React instances on the page 8956 */ 8957 var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2); 8958 8959 function getListeningForDocument(mountAt) { 8960 if (mountAt[topListenersIDKey] == null) { 8961 mountAt[topListenersIDKey] = reactTopListenersCounter++; 8962 alreadyListeningTo[mountAt[topListenersIDKey]] = {}; 8963 } 8964 return alreadyListeningTo[mountAt[topListenersIDKey]]; 8965 } 8966 8967 /** 8968 * Traps top-level events by using event bubbling. 8969 * 8970 * @param {string} topLevelType Record from `EventConstants`. 8971 * @param {string} handlerBaseName Event name (e.g. "click"). 8972 * @param {DOMEventTarget} element Element on which to attach listener. 8973 * @internal 8974 */ 8975 function trapBubbledEvent(topLevelType, handlerBaseName, element) { 8976 EventListener.listen( 8977 element, 8978 handlerBaseName, 8979 ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback( 8980 topLevelType 8981 ) 8982 ); 8983 } 8984 8985 /** 8986 * Traps a top-level event by using event capturing. 8987 * 8988 * @param {string} topLevelType Record from `EventConstants`. 8989 * @param {string} handlerBaseName Event name (e.g. "click"). 8990 * @param {DOMEventTarget} element Element on which to attach listener. 8991 * @internal 8992 */ 8993 function trapCapturedEvent(topLevelType, handlerBaseName, element) { 8994 EventListener.capture( 8995 element, 8996 handlerBaseName, 8997 ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback( 8998 topLevelType 8999 ) 9000 ); 9001 } 9002 9003 /** 9004 * `ReactEventEmitter` is used to attach top-level event listeners. For example: 9005 * 9006 * ReactEventEmitter.putListener('myID', 'onClick', myFunction); 9007 * 9008 * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. 9009 * 9010 * @internal 9011 */ 9012 var ReactEventEmitter = merge(ReactEventEmitterMixin, { 9013 9014 /** 9015 * React references `ReactEventTopLevelCallback` using this property in order 9016 * to allow dependency injection. 9017 */ 9018 TopLevelCallbackCreator: null, 9019 9020 injection: { 9021 /** 9022 * @param {function} TopLevelCallbackCreator 9023 */ 9024 injectTopLevelCallbackCreator: function(TopLevelCallbackCreator) { 9025 ReactEventEmitter.TopLevelCallbackCreator = TopLevelCallbackCreator; 9026 } 9027 }, 9028 9029 /** 9030 * Sets whether or not any created callbacks should be enabled. 9031 * 9032 * @param {boolean} enabled True if callbacks should be enabled. 9033 */ 9034 setEnabled: function(enabled) { 9035 ("production" !== "development" ? invariant( 9036 ExecutionEnvironment.canUseDOM, 9037 'setEnabled(...): Cannot toggle event listening in a Worker thread. ' + 9038 'This is likely a bug in the framework. Please report immediately.' 9039 ) : invariant(ExecutionEnvironment.canUseDOM)); 9040 if (ReactEventEmitter.TopLevelCallbackCreator) { 9041 ReactEventEmitter.TopLevelCallbackCreator.setEnabled(enabled); 9042 } 9043 }, 9044 9045 /** 9046 * @return {boolean} True if callbacks are enabled. 9047 */ 9048 isEnabled: function() { 9049 return !!( 9050 ReactEventEmitter.TopLevelCallbackCreator && 9051 ReactEventEmitter.TopLevelCallbackCreator.isEnabled() 9052 ); 9053 }, 9054 9055 /** 9056 * We listen for bubbled touch events on the document object. 9057 * 9058 * Firefox v8.01 (and possibly others) exhibited strange behavior when 9059 * mounting `onmousemove` events at some node that was not the document 9060 * element. The symptoms were that if your mouse is not moving over something 9061 * contained within that mount point (for example on the background) the 9062 * top-level listeners for `onmousemove` won't be called. However, if you 9063 * register the `mousemove` on the document object, then it will of course 9064 * catch all `mousemove`s. This along with iOS quirks, justifies restricting 9065 * top-level listeners to the document object only, at least for these 9066 * movement types of events and possibly all events. 9067 * 9068 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html 9069 * 9070 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but 9071 * they bubble to document. 9072 * 9073 * @param {string} registrationName Name of listener (e.g. `onClick`). 9074 * @param {DOMDocument} contentDocument Document which owns the container 9075 */ 9076 listenTo: function(registrationName, contentDocument) { 9077 var mountAt = contentDocument; 9078 var isListening = getListeningForDocument(mountAt); 9079 var dependencies = EventPluginRegistry. 9080 registrationNameDependencies[registrationName]; 9081 9082 var topLevelTypes = EventConstants.topLevelTypes; 9083 for (var i = 0, l = dependencies.length; i < l; i++) { 9084 var dependency = dependencies[i]; 9085 if (!isListening[dependency]) { 9086 var topLevelType = topLevelTypes[dependency]; 9087 9088 if (topLevelType === topLevelTypes.topWheel) { 9089 if (isEventSupported('wheel')) { 9090 trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt); 9091 } else if (isEventSupported('mousewheel')) { 9092 trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt); 9093 } else { 9094 // Firefox needs to capture a different mouse scroll event. 9095 // @see http://www.quirksmode.org/dom/events/tests/scroll.html 9096 trapBubbledEvent( 9097 topLevelTypes.topWheel, 9098 'DOMMouseScroll', 9099 mountAt); 9100 } 9101 } else if (topLevelType === topLevelTypes.topScroll) { 9102 9103 if (isEventSupported('scroll', true)) { 9104 trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt); 9105 } else { 9106 trapBubbledEvent(topLevelTypes.topScroll, 'scroll', window); 9107 } 9108 } else if (topLevelType === topLevelTypes.topFocus || 9109 topLevelType === topLevelTypes.topBlur) { 9110 9111 if (isEventSupported('focus', true)) { 9112 trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt); 9113 trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt); 9114 } else if (isEventSupported('focusin')) { 9115 // IE has `focusin` and `focusout` events which bubble. 9116 // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html 9117 trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); 9118 trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); 9119 } 9120 9121 // to make sure blur and focus event listeners are only attached once 9122 isListening[topLevelTypes.topBlur] = true; 9123 isListening[topLevelTypes.topFocus] = true; 9124 } else if (topEventMapping[dependency]) { 9125 trapBubbledEvent(topLevelType, topEventMapping[dependency], mountAt); 9126 } 9127 9128 isListening[dependency] = true; 9129 } 9130 } 9131 }, 9132 9133 /** 9134 * Listens to window scroll and resize events. We cache scroll values so that 9135 * application code can access them without triggering reflows. 9136 * 9137 * NOTE: Scroll events do not bubble. 9138 * 9139 * @see http://www.quirksmode.org/dom/events/scroll.html 9140 */ 9141 ensureScrollValueMonitoring: function(){ 9142 if (!isMonitoringScrollValue) { 9143 var refresh = ViewportMetrics.refreshScrollValues; 9144 EventListener.listen(window, 'scroll', refresh); 9145 EventListener.listen(window, 'resize', refresh); 9146 isMonitoringScrollValue = true; 9147 } 9148 }, 9149 9150 eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs, 9151 9152 registrationNameModules: EventPluginHub.registrationNameModules, 9153 9154 putListener: EventPluginHub.putListener, 9155 9156 getListener: EventPluginHub.getListener, 9157 9158 deleteListener: EventPluginHub.deleteListener, 9159 9160 deleteAllListeners: EventPluginHub.deleteAllListeners, 9161 9162 trapBubbledEvent: trapBubbledEvent, 9163 9164 trapCapturedEvent: trapCapturedEvent 9165 9166 }); 9167 9168 module.exports = ReactEventEmitter; 9169 9170 },{"./EventConstants":14,"./EventListener":15,"./EventPluginHub":16,"./EventPluginRegistry":17,"./ExecutionEnvironment":20,"./ReactEventEmitterMixin":49,"./ViewportMetrics":86,"./invariant":112,"./isEventSupported":113,"./merge":121}],49:[function(_dereq_,module,exports){ 9171 /** 9172 * Copyright 2013-2014 Facebook, Inc. 9173 * 9174 * Licensed under the Apache License, Version 2.0 (the "License"); 9175 * you may not use this file except in compliance with the License. 9176 * You may obtain a copy of the License at 9177 * 9178 * http://www.apache.org/licenses/LICENSE-2.0 9179 * 9180 * Unless required by applicable law or agreed to in writing, software 9181 * distributed under the License is distributed on an "AS IS" BASIS, 9182 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9183 * See the License for the specific language governing permissions and 9184 * limitations under the License. 9185 * 9186 * @providesModule ReactEventEmitterMixin 9187 */ 9188 9189 "use strict"; 9190 9191 var EventPluginHub = _dereq_("./EventPluginHub"); 9192 var ReactUpdates = _dereq_("./ReactUpdates"); 9193 9194 function runEventQueueInBatch(events) { 9195 EventPluginHub.enqueueEvents(events); 9196 EventPluginHub.processEventQueue(); 9197 } 9198 9199 var ReactEventEmitterMixin = { 9200 9201 /** 9202 * Streams a fired top-level event to `EventPluginHub` where plugins have the 9203 * opportunity to create `ReactEvent`s to be dispatched. 9204 * 9205 * @param {string} topLevelType Record from `EventConstants`. 9206 * @param {object} topLevelTarget The listening component root node. 9207 * @param {string} topLevelTargetID ID of `topLevelTarget`. 9208 * @param {object} nativeEvent Native environment event. 9209 */ 9210 handleTopLevel: function( 9211 topLevelType, 9212 topLevelTarget, 9213 topLevelTargetID, 9214 nativeEvent) { 9215 var events = EventPluginHub.extractEvents( 9216 topLevelType, 9217 topLevelTarget, 9218 topLevelTargetID, 9219 nativeEvent 9220 ); 9221 9222 // Event queue being processed in the same cycle allows `preventDefault`. 9223 ReactUpdates.batchedUpdates(runEventQueueInBatch, events); 9224 } 9225 }; 9226 9227 module.exports = ReactEventEmitterMixin; 9228 9229 },{"./EventPluginHub":16,"./ReactUpdates":71}],50:[function(_dereq_,module,exports){ 9230 /** 9231 * Copyright 2013-2014 Facebook, Inc. 9232 * 9233 * Licensed under the Apache License, Version 2.0 (the "License"); 9234 * you may not use this file except in compliance with the License. 9235 * You may obtain a copy of the License at 9236 * 9237 * http://www.apache.org/licenses/LICENSE-2.0 9238 * 9239 * Unless required by applicable law or agreed to in writing, software 9240 * distributed under the License is distributed on an "AS IS" BASIS, 9241 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9242 * See the License for the specific language governing permissions and 9243 * limitations under the License. 9244 * 9245 * @providesModule ReactEventTopLevelCallback 9246 * @typechecks static-only 9247 */ 9248 9249 "use strict"; 9250 9251 var PooledClass = _dereq_("./PooledClass"); 9252 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 9253 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 9254 var ReactMount = _dereq_("./ReactMount"); 9255 9256 var getEventTarget = _dereq_("./getEventTarget"); 9257 var mixInto = _dereq_("./mixInto"); 9258 9259 /** 9260 * @type {boolean} 9261 * @private 9262 */ 9263 var _topLevelListenersEnabled = true; 9264 9265 /** 9266 * Finds the parent React component of `node`. 9267 * 9268 * @param {*} node 9269 * @return {?DOMEventTarget} Parent container, or `null` if the specified node 9270 * is not nested. 9271 */ 9272 function findParent(node) { 9273 // TODO: It may be a good idea to cache this to prevent unnecessary DOM 9274 // traversal, but caching is difficult to do correctly without using a 9275 // mutation observer to listen for all DOM changes. 9276 var nodeID = ReactMount.getID(node); 9277 var rootID = ReactInstanceHandles.getReactRootIDFromNodeID(nodeID); 9278 var container = ReactMount.findReactContainerForID(rootID); 9279 var parent = ReactMount.getFirstReactDOM(container); 9280 return parent; 9281 } 9282 9283 /** 9284 * Calls ReactEventEmitter.handleTopLevel for each node stored in bookKeeping's 9285 * ancestor list. Separated from createTopLevelCallback to avoid try/finally 9286 * deoptimization. 9287 * 9288 * @param {string} topLevelType 9289 * @param {DOMEvent} nativeEvent 9290 * @param {TopLevelCallbackBookKeeping} bookKeeping 9291 */ 9292 function handleTopLevelImpl(topLevelType, nativeEvent, bookKeeping) { 9293 var topLevelTarget = ReactMount.getFirstReactDOM( 9294 getEventTarget(nativeEvent) 9295 ) || window; 9296 9297 // Loop through the hierarchy, in case there's any nested components. 9298 // It's important that we build the array of ancestors before calling any 9299 // event handlers, because event handlers can modify the DOM, leading to 9300 // inconsistencies with ReactMount's node cache. See #1105. 9301 var ancestor = topLevelTarget; 9302 while (ancestor) { 9303 bookKeeping.ancestors.push(ancestor); 9304 ancestor = findParent(ancestor); 9305 } 9306 9307 for (var i = 0, l = bookKeeping.ancestors.length; i < l; i++) { 9308 topLevelTarget = bookKeeping.ancestors[i]; 9309 var topLevelTargetID = ReactMount.getID(topLevelTarget) || ''; 9310 ReactEventEmitter.handleTopLevel( 9311 topLevelType, 9312 topLevelTarget, 9313 topLevelTargetID, 9314 nativeEvent 9315 ); 9316 } 9317 } 9318 9319 // Used to store ancestor hierarchy in top level callback 9320 function TopLevelCallbackBookKeeping() { 9321 this.ancestors = []; 9322 } 9323 mixInto(TopLevelCallbackBookKeeping, { 9324 destructor: function() { 9325 this.ancestors.length = 0; 9326 } 9327 }); 9328 PooledClass.addPoolingTo(TopLevelCallbackBookKeeping); 9329 9330 /** 9331 * Top-level callback creator used to implement event handling using delegation. 9332 * This is used via dependency injection. 9333 */ 9334 var ReactEventTopLevelCallback = { 9335 9336 /** 9337 * Sets whether or not any created callbacks should be enabled. 9338 * 9339 * @param {boolean} enabled True if callbacks should be enabled. 9340 */ 9341 setEnabled: function(enabled) { 9342 _topLevelListenersEnabled = !!enabled; 9343 }, 9344 9345 /** 9346 * @return {boolean} True if callbacks are enabled. 9347 */ 9348 isEnabled: function() { 9349 return _topLevelListenersEnabled; 9350 }, 9351 9352 /** 9353 * Creates a callback for the supplied `topLevelType` that could be added as 9354 * a listener to the document. The callback computes a `topLevelTarget` which 9355 * should be the root node of a mounted React component where the listener 9356 * is attached. 9357 * 9358 * @param {string} topLevelType Record from `EventConstants`. 9359 * @return {function} Callback for handling top-level events. 9360 */ 9361 createTopLevelCallback: function(topLevelType) { 9362 return function(nativeEvent) { 9363 if (!_topLevelListenersEnabled) { 9364 return; 9365 } 9366 9367 var bookKeeping = TopLevelCallbackBookKeeping.getPooled(); 9368 try { 9369 handleTopLevelImpl(topLevelType, nativeEvent, bookKeeping); 9370 } finally { 9371 TopLevelCallbackBookKeeping.release(bookKeeping); 9372 } 9373 }; 9374 } 9375 9376 }; 9377 9378 module.exports = ReactEventTopLevelCallback; 9379 9380 },{"./PooledClass":23,"./ReactEventEmitter":48,"./ReactInstanceHandles":53,"./ReactMount":55,"./getEventTarget":104,"./mixInto":124}],51:[function(_dereq_,module,exports){ 9381 /** 9382 * Copyright 2013-2014 Facebook, Inc. 9383 * 9384 * Licensed under the Apache License, Version 2.0 (the "License"); 9385 * you may not use this file except in compliance with the License. 9386 * You may obtain a copy of the License at 9387 * 9388 * http://www.apache.org/licenses/LICENSE-2.0 9389 * 9390 * Unless required by applicable law or agreed to in writing, software 9391 * distributed under the License is distributed on an "AS IS" BASIS, 9392 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9393 * See the License for the specific language governing permissions and 9394 * limitations under the License. 9395 * 9396 * @providesModule ReactInjection 9397 */ 9398 9399 "use strict"; 9400 9401 var DOMProperty = _dereq_("./DOMProperty"); 9402 var EventPluginHub = _dereq_("./EventPluginHub"); 9403 var ReactComponent = _dereq_("./ReactComponent"); 9404 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 9405 var ReactDOM = _dereq_("./ReactDOM"); 9406 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 9407 var ReactPerf = _dereq_("./ReactPerf"); 9408 var ReactRootIndex = _dereq_("./ReactRootIndex"); 9409 var ReactUpdates = _dereq_("./ReactUpdates"); 9410 9411 var ReactInjection = { 9412 Component: ReactComponent.injection, 9413 CompositeComponent: ReactCompositeComponent.injection, 9414 DOMProperty: DOMProperty.injection, 9415 EventPluginHub: EventPluginHub.injection, 9416 DOM: ReactDOM.injection, 9417 EventEmitter: ReactEventEmitter.injection, 9418 Perf: ReactPerf.injection, 9419 RootIndex: ReactRootIndex.injection, 9420 Updates: ReactUpdates.injection 9421 }; 9422 9423 module.exports = ReactInjection; 9424 9425 },{"./DOMProperty":8,"./EventPluginHub":16,"./ReactComponent":27,"./ReactCompositeComponent":29,"./ReactDOM":32,"./ReactEventEmitter":48,"./ReactPerf":60,"./ReactRootIndex":67,"./ReactUpdates":71}],52:[function(_dereq_,module,exports){ 9426 /** 9427 * Copyright 2013-2014 Facebook, Inc. 9428 * 9429 * Licensed under the Apache License, Version 2.0 (the "License"); 9430 * you may not use this file except in compliance with the License. 9431 * You may obtain a copy of the License at 9432 * 9433 * http://www.apache.org/licenses/LICENSE-2.0 9434 * 9435 * Unless required by applicable law or agreed to in writing, software 9436 * distributed under the License is distributed on an "AS IS" BASIS, 9437 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9438 * See the License for the specific language governing permissions and 9439 * limitations under the License. 9440 * 9441 * @providesModule ReactInputSelection 9442 */ 9443 9444 "use strict"; 9445 9446 var ReactDOMSelection = _dereq_("./ReactDOMSelection"); 9447 9448 var containsNode = _dereq_("./containsNode"); 9449 var focusNode = _dereq_("./focusNode"); 9450 var getActiveElement = _dereq_("./getActiveElement"); 9451 9452 function isInDocument(node) { 9453 return containsNode(document.documentElement, node); 9454 } 9455 9456 /** 9457 * @ReactInputSelection: React input selection module. Based on Selection.js, 9458 * but modified to be suitable for react and has a couple of bug fixes (doesn't 9459 * assume buttons have range selections allowed). 9460 * Input selection module for React. 9461 */ 9462 var ReactInputSelection = { 9463 9464 hasSelectionCapabilities: function(elem) { 9465 return elem && ( 9466 (elem.nodeName === 'INPUT' && elem.type === 'text') || 9467 elem.nodeName === 'TEXTAREA' || 9468 elem.contentEditable === 'true' 9469 ); 9470 }, 9471 9472 getSelectionInformation: function() { 9473 var focusedElem = getActiveElement(); 9474 return { 9475 focusedElem: focusedElem, 9476 selectionRange: 9477 ReactInputSelection.hasSelectionCapabilities(focusedElem) ? 9478 ReactInputSelection.getSelection(focusedElem) : 9479 null 9480 }; 9481 }, 9482 9483 /** 9484 * @restoreSelection: If any selection information was potentially lost, 9485 * restore it. This is useful when performing operations that could remove dom 9486 * nodes and place them back in, resulting in focus being lost. 9487 */ 9488 restoreSelection: function(priorSelectionInformation) { 9489 var curFocusedElem = getActiveElement(); 9490 var priorFocusedElem = priorSelectionInformation.focusedElem; 9491 var priorSelectionRange = priorSelectionInformation.selectionRange; 9492 if (curFocusedElem !== priorFocusedElem && 9493 isInDocument(priorFocusedElem)) { 9494 if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) { 9495 ReactInputSelection.setSelection( 9496 priorFocusedElem, 9497 priorSelectionRange 9498 ); 9499 } 9500 focusNode(priorFocusedElem); 9501 } 9502 }, 9503 9504 /** 9505 * @getSelection: Gets the selection bounds of a focused textarea, input or 9506 * contentEditable node. 9507 * -@input: Look up selection bounds of this input 9508 * -@return {start: selectionStart, end: selectionEnd} 9509 */ 9510 getSelection: function(input) { 9511 var selection; 9512 9513 if ('selectionStart' in input) { 9514 // Modern browser with input or textarea. 9515 selection = { 9516 start: input.selectionStart, 9517 end: input.selectionEnd 9518 }; 9519 } else if (document.selection && input.nodeName === 'INPUT') { 9520 // IE8 input. 9521 var range = document.selection.createRange(); 9522 // There can only be one selection per document in IE, so it must 9523 // be in our element. 9524 if (range.parentElement() === input) { 9525 selection = { 9526 start: -range.moveStart('character', -input.value.length), 9527 end: -range.moveEnd('character', -input.value.length) 9528 }; 9529 } 9530 } else { 9531 // Content editable or old IE textarea. 9532 selection = ReactDOMSelection.getOffsets(input); 9533 } 9534 9535 return selection || {start: 0, end: 0}; 9536 }, 9537 9538 /** 9539 * @setSelection: Sets the selection bounds of a textarea or input and focuses 9540 * the input. 9541 * -@input Set selection bounds of this input or textarea 9542 * -@offsets Object of same form that is returned from get* 9543 */ 9544 setSelection: function(input, offsets) { 9545 var start = offsets.start; 9546 var end = offsets.end; 9547 if (typeof end === 'undefined') { 9548 end = start; 9549 } 9550 9551 if ('selectionStart' in input) { 9552 input.selectionStart = start; 9553 input.selectionEnd = Math.min(end, input.value.length); 9554 } else if (document.selection && input.nodeName === 'INPUT') { 9555 var range = input.createTextRange(); 9556 range.collapse(true); 9557 range.moveStart('character', start); 9558 range.moveEnd('character', end - start); 9559 range.select(); 9560 } else { 9561 ReactDOMSelection.setOffsets(input, offsets); 9562 } 9563 } 9564 }; 9565 9566 module.exports = ReactInputSelection; 9567 9568 },{"./ReactDOMSelection":41,"./containsNode":89,"./focusNode":100,"./getActiveElement":102}],53:[function(_dereq_,module,exports){ 9569 /** 9570 * Copyright 2013-2014 Facebook, Inc. 9571 * 9572 * Licensed under the Apache License, Version 2.0 (the "License"); 9573 * you may not use this file except in compliance with the License. 9574 * You may obtain a copy of the License at 9575 * 9576 * http://www.apache.org/licenses/LICENSE-2.0 9577 * 9578 * Unless required by applicable law or agreed to in writing, software 9579 * distributed under the License is distributed on an "AS IS" BASIS, 9580 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9581 * See the License for the specific language governing permissions and 9582 * limitations under the License. 9583 * 9584 * @providesModule ReactInstanceHandles 9585 * @typechecks static-only 9586 */ 9587 9588 "use strict"; 9589 9590 var ReactRootIndex = _dereq_("./ReactRootIndex"); 9591 9592 var invariant = _dereq_("./invariant"); 9593 9594 var SEPARATOR = '.'; 9595 var SEPARATOR_LENGTH = SEPARATOR.length; 9596 9597 /** 9598 * Maximum depth of traversals before we consider the possibility of a bad ID. 9599 */ 9600 var MAX_TREE_DEPTH = 100; 9601 9602 /** 9603 * Creates a DOM ID prefix to use when mounting React components. 9604 * 9605 * @param {number} index A unique integer 9606 * @return {string} React root ID. 9607 * @internal 9608 */ 9609 function getReactRootIDString(index) { 9610 return SEPARATOR + index.toString(36); 9611 } 9612 9613 /** 9614 * Checks if a character in the supplied ID is a separator or the end. 9615 * 9616 * @param {string} id A React DOM ID. 9617 * @param {number} index Index of the character to check. 9618 * @return {boolean} True if the character is a separator or end of the ID. 9619 * @private 9620 */ 9621 function isBoundary(id, index) { 9622 return id.charAt(index) === SEPARATOR || index === id.length; 9623 } 9624 9625 /** 9626 * Checks if the supplied string is a valid React DOM ID. 9627 * 9628 * @param {string} id A React DOM ID, maybe. 9629 * @return {boolean} True if the string is a valid React DOM ID. 9630 * @private 9631 */ 9632 function isValidID(id) { 9633 return id === '' || ( 9634 id.charAt(0) === SEPARATOR && id.charAt(id.length - 1) !== SEPARATOR 9635 ); 9636 } 9637 9638 /** 9639 * Checks if the first ID is an ancestor of or equal to the second ID. 9640 * 9641 * @param {string} ancestorID 9642 * @param {string} descendantID 9643 * @return {boolean} True if `ancestorID` is an ancestor of `descendantID`. 9644 * @internal 9645 */ 9646 function isAncestorIDOf(ancestorID, descendantID) { 9647 return ( 9648 descendantID.indexOf(ancestorID) === 0 && 9649 isBoundary(descendantID, ancestorID.length) 9650 ); 9651 } 9652 9653 /** 9654 * Gets the parent ID of the supplied React DOM ID, `id`. 9655 * 9656 * @param {string} id ID of a component. 9657 * @return {string} ID of the parent, or an empty string. 9658 * @private 9659 */ 9660 function getParentID(id) { 9661 return id ? id.substr(0, id.lastIndexOf(SEPARATOR)) : ''; 9662 } 9663 9664 /** 9665 * Gets the next DOM ID on the tree path from the supplied `ancestorID` to the 9666 * supplied `destinationID`. If they are equal, the ID is returned. 9667 * 9668 * @param {string} ancestorID ID of an ancestor node of `destinationID`. 9669 * @param {string} destinationID ID of the destination node. 9670 * @return {string} Next ID on the path from `ancestorID` to `destinationID`. 9671 * @private 9672 */ 9673 function getNextDescendantID(ancestorID, destinationID) { 9674 ("production" !== "development" ? invariant( 9675 isValidID(ancestorID) && isValidID(destinationID), 9676 'getNextDescendantID(%s, %s): Received an invalid React DOM ID.', 9677 ancestorID, 9678 destinationID 9679 ) : invariant(isValidID(ancestorID) && isValidID(destinationID))); 9680 ("production" !== "development" ? invariant( 9681 isAncestorIDOf(ancestorID, destinationID), 9682 'getNextDescendantID(...): React has made an invalid assumption about ' + 9683 'the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.', 9684 ancestorID, 9685 destinationID 9686 ) : invariant(isAncestorIDOf(ancestorID, destinationID))); 9687 if (ancestorID === destinationID) { 9688 return ancestorID; 9689 } 9690 // Skip over the ancestor and the immediate separator. Traverse until we hit 9691 // another separator or we reach the end of `destinationID`. 9692 var start = ancestorID.length + SEPARATOR_LENGTH; 9693 for (var i = start; i < destinationID.length; i++) { 9694 if (isBoundary(destinationID, i)) { 9695 break; 9696 } 9697 } 9698 return destinationID.substr(0, i); 9699 } 9700 9701 /** 9702 * Gets the nearest common ancestor ID of two IDs. 9703 * 9704 * Using this ID scheme, the nearest common ancestor ID is the longest common 9705 * prefix of the two IDs that immediately preceded a "marker" in both strings. 9706 * 9707 * @param {string} oneID 9708 * @param {string} twoID 9709 * @return {string} Nearest common ancestor ID, or the empty string if none. 9710 * @private 9711 */ 9712 function getFirstCommonAncestorID(oneID, twoID) { 9713 var minLength = Math.min(oneID.length, twoID.length); 9714 if (minLength === 0) { 9715 return ''; 9716 } 9717 var lastCommonMarkerIndex = 0; 9718 // Use `<=` to traverse until the "EOL" of the shorter string. 9719 for (var i = 0; i <= minLength; i++) { 9720 if (isBoundary(oneID, i) && isBoundary(twoID, i)) { 9721 lastCommonMarkerIndex = i; 9722 } else if (oneID.charAt(i) !== twoID.charAt(i)) { 9723 break; 9724 } 9725 } 9726 var longestCommonID = oneID.substr(0, lastCommonMarkerIndex); 9727 ("production" !== "development" ? invariant( 9728 isValidID(longestCommonID), 9729 'getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s', 9730 oneID, 9731 twoID, 9732 longestCommonID 9733 ) : invariant(isValidID(longestCommonID))); 9734 return longestCommonID; 9735 } 9736 9737 /** 9738 * Traverses the parent path between two IDs (either up or down). The IDs must 9739 * not be the same, and there must exist a parent path between them. If the 9740 * callback returns `false`, traversal is stopped. 9741 * 9742 * @param {?string} start ID at which to start traversal. 9743 * @param {?string} stop ID at which to end traversal. 9744 * @param {function} cb Callback to invoke each ID with. 9745 * @param {?boolean} skipFirst Whether or not to skip the first node. 9746 * @param {?boolean} skipLast Whether or not to skip the last node. 9747 * @private 9748 */ 9749 function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) { 9750 start = start || ''; 9751 stop = stop || ''; 9752 ("production" !== "development" ? invariant( 9753 start !== stop, 9754 'traverseParentPath(...): Cannot traverse from and to the same ID, `%s`.', 9755 start 9756 ) : invariant(start !== stop)); 9757 var traverseUp = isAncestorIDOf(stop, start); 9758 ("production" !== "development" ? invariant( 9759 traverseUp || isAncestorIDOf(start, stop), 9760 'traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do ' + 9761 'not have a parent path.', 9762 start, 9763 stop 9764 ) : invariant(traverseUp || isAncestorIDOf(start, stop))); 9765 // Traverse from `start` to `stop` one depth at a time. 9766 var depth = 0; 9767 var traverse = traverseUp ? getParentID : getNextDescendantID; 9768 for (var id = start; /* until break */; id = traverse(id, stop)) { 9769 var ret; 9770 if ((!skipFirst || id !== start) && (!skipLast || id !== stop)) { 9771 ret = cb(id, traverseUp, arg); 9772 } 9773 if (ret === false || id === stop) { 9774 // Only break //after// visiting `stop`. 9775 break; 9776 } 9777 ("production" !== "development" ? invariant( 9778 depth++ < MAX_TREE_DEPTH, 9779 'traverseParentPath(%s, %s, ...): Detected an infinite loop while ' + 9780 'traversing the React DOM ID tree. This may be due to malformed IDs: %s', 9781 start, stop 9782 ) : invariant(depth++ < MAX_TREE_DEPTH)); 9783 } 9784 } 9785 9786 /** 9787 * Manages the IDs assigned to DOM representations of React components. This 9788 * uses a specific scheme in order to traverse the DOM efficiently (e.g. in 9789 * order to simulate events). 9790 * 9791 * @internal 9792 */ 9793 var ReactInstanceHandles = { 9794 9795 /** 9796 * Constructs a React root ID 9797 * @return {string} A React root ID. 9798 */ 9799 createReactRootID: function() { 9800 return getReactRootIDString(ReactRootIndex.createReactRootIndex()); 9801 }, 9802 9803 /** 9804 * Constructs a React ID by joining a root ID with a name. 9805 * 9806 * @param {string} rootID Root ID of a parent component. 9807 * @param {string} name A component's name (as flattened children). 9808 * @return {string} A React ID. 9809 * @internal 9810 */ 9811 createReactID: function(rootID, name) { 9812 return rootID + name; 9813 }, 9814 9815 /** 9816 * Gets the DOM ID of the React component that is the root of the tree that 9817 * contains the React component with the supplied DOM ID. 9818 * 9819 * @param {string} id DOM ID of a React component. 9820 * @return {?string} DOM ID of the React component that is the root. 9821 * @internal 9822 */ 9823 getReactRootIDFromNodeID: function(id) { 9824 if (id && id.charAt(0) === SEPARATOR && id.length > 1) { 9825 var index = id.indexOf(SEPARATOR, 1); 9826 return index > -1 ? id.substr(0, index) : id; 9827 } 9828 return null; 9829 }, 9830 9831 /** 9832 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that 9833 * should would receive a `mouseEnter` or `mouseLeave` event. 9834 * 9835 * NOTE: Does not invoke the callback on the nearest common ancestor because 9836 * nothing "entered" or "left" that element. 9837 * 9838 * @param {string} leaveID ID being left. 9839 * @param {string} enterID ID being entered. 9840 * @param {function} cb Callback to invoke on each entered/left ID. 9841 * @param {*} upArg Argument to invoke the callback with on left IDs. 9842 * @param {*} downArg Argument to invoke the callback with on entered IDs. 9843 * @internal 9844 */ 9845 traverseEnterLeave: function(leaveID, enterID, cb, upArg, downArg) { 9846 var ancestorID = getFirstCommonAncestorID(leaveID, enterID); 9847 if (ancestorID !== leaveID) { 9848 traverseParentPath(leaveID, ancestorID, cb, upArg, false, true); 9849 } 9850 if (ancestorID !== enterID) { 9851 traverseParentPath(ancestorID, enterID, cb, downArg, true, false); 9852 } 9853 }, 9854 9855 /** 9856 * Simulates the traversal of a two-phase, capture/bubble event dispatch. 9857 * 9858 * NOTE: This traversal happens on IDs without touching the DOM. 9859 * 9860 * @param {string} targetID ID of the target node. 9861 * @param {function} cb Callback to invoke. 9862 * @param {*} arg Argument to invoke the callback with. 9863 * @internal 9864 */ 9865 traverseTwoPhase: function(targetID, cb, arg) { 9866 if (targetID) { 9867 traverseParentPath('', targetID, cb, arg, true, false); 9868 traverseParentPath(targetID, '', cb, arg, false, true); 9869 } 9870 }, 9871 9872 /** 9873 * Traverse a node ID, calling the supplied `cb` for each ancestor ID. For 9874 * example, passing `.0.$row-0.1` would result in `cb` getting called 9875 * with `.0`, `.0.$row-0`, and `.0.$row-0.1`. 9876 * 9877 * NOTE: This traversal happens on IDs without touching the DOM. 9878 * 9879 * @param {string} targetID ID of the target node. 9880 * @param {function} cb Callback to invoke. 9881 * @param {*} arg Argument to invoke the callback with. 9882 * @internal 9883 */ 9884 traverseAncestors: function(targetID, cb, arg) { 9885 traverseParentPath('', targetID, cb, arg, true, false); 9886 }, 9887 9888 /** 9889 * Exposed for unit testing. 9890 * @private 9891 */ 9892 _getFirstCommonAncestorID: getFirstCommonAncestorID, 9893 9894 /** 9895 * Exposed for unit testing. 9896 * @private 9897 */ 9898 _getNextDescendantID: getNextDescendantID, 9899 9900 isAncestorIDOf: isAncestorIDOf, 9901 9902 SEPARATOR: SEPARATOR 9903 9904 }; 9905 9906 module.exports = ReactInstanceHandles; 9907 9908 },{"./ReactRootIndex":67,"./invariant":112}],54:[function(_dereq_,module,exports){ 9909 /** 9910 * Copyright 2013-2014 Facebook, Inc. 9911 * 9912 * Licensed under the Apache License, Version 2.0 (the "License"); 9913 * you may not use this file except in compliance with the License. 9914 * You may obtain a copy of the License at 9915 * 9916 * http://www.apache.org/licenses/LICENSE-2.0 9917 * 9918 * Unless required by applicable law or agreed to in writing, software 9919 * distributed under the License is distributed on an "AS IS" BASIS, 9920 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9921 * See the License for the specific language governing permissions and 9922 * limitations under the License. 9923 * 9924 * @providesModule ReactMarkupChecksum 9925 */ 9926 9927 "use strict"; 9928 9929 var adler32 = _dereq_("./adler32"); 9930 9931 var ReactMarkupChecksum = { 9932 CHECKSUM_ATTR_NAME: 'data-react-checksum', 9933 9934 /** 9935 * @param {string} markup Markup string 9936 * @return {string} Markup string with checksum attribute attached 9937 */ 9938 addChecksumToMarkup: function(markup) { 9939 var checksum = adler32(markup); 9940 return markup.replace( 9941 '>', 9942 ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '">' 9943 ); 9944 }, 9945 9946 /** 9947 * @param {string} markup to use 9948 * @param {DOMElement} element root React element 9949 * @returns {boolean} whether or not the markup is the same 9950 */ 9951 canReuseMarkup: function(markup, element) { 9952 var existingChecksum = element.getAttribute( 9953 ReactMarkupChecksum.CHECKSUM_ATTR_NAME 9954 ); 9955 existingChecksum = existingChecksum && parseInt(existingChecksum, 10); 9956 var markupChecksum = adler32(markup); 9957 return markupChecksum === existingChecksum; 9958 } 9959 }; 9960 9961 module.exports = ReactMarkupChecksum; 9962 9963 },{"./adler32":88}],55:[function(_dereq_,module,exports){ 9964 /** 9965 * Copyright 2013-2014 Facebook, Inc. 9966 * 9967 * Licensed under the Apache License, Version 2.0 (the "License"); 9968 * you may not use this file except in compliance with the License. 9969 * You may obtain a copy of the License at 9970 * 9971 * http://www.apache.org/licenses/LICENSE-2.0 9972 * 9973 * Unless required by applicable law or agreed to in writing, software 9974 * distributed under the License is distributed on an "AS IS" BASIS, 9975 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9976 * See the License for the specific language governing permissions and 9977 * limitations under the License. 9978 * 9979 * @providesModule ReactMount 9980 */ 9981 9982 "use strict"; 9983 9984 var DOMProperty = _dereq_("./DOMProperty"); 9985 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 9986 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 9987 var ReactPerf = _dereq_("./ReactPerf"); 9988 9989 var containsNode = _dereq_("./containsNode"); 9990 var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer"); 9991 var instantiateReactComponent = _dereq_("./instantiateReactComponent"); 9992 var invariant = _dereq_("./invariant"); 9993 var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); 9994 9995 var SEPARATOR = ReactInstanceHandles.SEPARATOR; 9996 9997 var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; 9998 var nodeCache = {}; 9999 10000 var ELEMENT_NODE_TYPE = 1; 10001 var DOC_NODE_TYPE = 9; 10002 10003 /** Mapping from reactRootID to React component instance. */ 10004 var instancesByReactRootID = {}; 10005 10006 /** Mapping from reactRootID to `container` nodes. */ 10007 var containersByReactRootID = {}; 10008 10009 if ("production" !== "development") { 10010 /** __DEV__-only mapping from reactRootID to root elements. */ 10011 var rootElementsByReactRootID = {}; 10012 } 10013 10014 // Used to store breadth-first search state in findComponentRoot. 10015 var findComponentRootReusableArray = []; 10016 10017 /** 10018 * @param {DOMElement} container DOM element that may contain a React component. 10019 * @return {?string} A "reactRoot" ID, if a React component is rendered. 10020 */ 10021 function getReactRootID(container) { 10022 var rootElement = getReactRootElementInContainer(container); 10023 return rootElement && ReactMount.getID(rootElement); 10024 } 10025 10026 /** 10027 * Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form 10028 * element can return its control whose name or ID equals ATTR_NAME. All 10029 * DOM nodes support `getAttributeNode` but this can also get called on 10030 * other objects so just return '' if we're given something other than a 10031 * DOM node (such as window). 10032 * 10033 * @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node. 10034 * @return {string} ID of the supplied `domNode`. 10035 */ 10036 function getID(node) { 10037 var id = internalGetID(node); 10038 if (id) { 10039 if (nodeCache.hasOwnProperty(id)) { 10040 var cached = nodeCache[id]; 10041 if (cached !== node) { 10042 ("production" !== "development" ? invariant( 10043 !isValid(cached, id), 10044 'ReactMount: Two valid but unequal nodes with the same `%s`: %s', 10045 ATTR_NAME, id 10046 ) : invariant(!isValid(cached, id))); 10047 10048 nodeCache[id] = node; 10049 } 10050 } else { 10051 nodeCache[id] = node; 10052 } 10053 } 10054 10055 return id; 10056 } 10057 10058 function internalGetID(node) { 10059 // If node is something like a window, document, or text node, none of 10060 // which support attributes or a .getAttribute method, gracefully return 10061 // the empty string, as if the attribute were missing. 10062 return node && node.getAttribute && node.getAttribute(ATTR_NAME) || ''; 10063 } 10064 10065 /** 10066 * Sets the React-specific ID of the given node. 10067 * 10068 * @param {DOMElement} node The DOM node whose ID will be set. 10069 * @param {string} id The value of the ID attribute. 10070 */ 10071 function setID(node, id) { 10072 var oldID = internalGetID(node); 10073 if (oldID !== id) { 10074 delete nodeCache[oldID]; 10075 } 10076 node.setAttribute(ATTR_NAME, id); 10077 nodeCache[id] = node; 10078 } 10079 10080 /** 10081 * Finds the node with the supplied React-generated DOM ID. 10082 * 10083 * @param {string} id A React-generated DOM ID. 10084 * @return {DOMElement} DOM node with the suppled `id`. 10085 * @internal 10086 */ 10087 function getNode(id) { 10088 if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) { 10089 nodeCache[id] = ReactMount.findReactNodeByID(id); 10090 } 10091 return nodeCache[id]; 10092 } 10093 10094 /** 10095 * A node is "valid" if it is contained by a currently mounted container. 10096 * 10097 * This means that the node does not have to be contained by a document in 10098 * order to be considered valid. 10099 * 10100 * @param {?DOMElement} node The candidate DOM node. 10101 * @param {string} id The expected ID of the node. 10102 * @return {boolean} Whether the node is contained by a mounted container. 10103 */ 10104 function isValid(node, id) { 10105 if (node) { 10106 ("production" !== "development" ? invariant( 10107 internalGetID(node) === id, 10108 'ReactMount: Unexpected modification of `%s`', 10109 ATTR_NAME 10110 ) : invariant(internalGetID(node) === id)); 10111 10112 var container = ReactMount.findReactContainerForID(id); 10113 if (container && containsNode(container, node)) { 10114 return true; 10115 } 10116 } 10117 10118 return false; 10119 } 10120 10121 /** 10122 * Causes the cache to forget about one React-specific ID. 10123 * 10124 * @param {string} id The ID to forget. 10125 */ 10126 function purgeID(id) { 10127 delete nodeCache[id]; 10128 } 10129 10130 var deepestNodeSoFar = null; 10131 function findDeepestCachedAncestorImpl(ancestorID) { 10132 var ancestor = nodeCache[ancestorID]; 10133 if (ancestor && isValid(ancestor, ancestorID)) { 10134 deepestNodeSoFar = ancestor; 10135 } else { 10136 // This node isn't populated in the cache, so presumably none of its 10137 // descendants are. Break out of the loop. 10138 return false; 10139 } 10140 } 10141 10142 /** 10143 * Return the deepest cached node whose ID is a prefix of `targetID`. 10144 */ 10145 function findDeepestCachedAncestor(targetID) { 10146 deepestNodeSoFar = null; 10147 ReactInstanceHandles.traverseAncestors( 10148 targetID, 10149 findDeepestCachedAncestorImpl 10150 ); 10151 10152 var foundNode = deepestNodeSoFar; 10153 deepestNodeSoFar = null; 10154 return foundNode; 10155 } 10156 10157 /** 10158 * Mounting is the process of initializing a React component by creatings its 10159 * representative DOM elements and inserting them into a supplied `container`. 10160 * Any prior content inside `container` is destroyed in the process. 10161 * 10162 * ReactMount.renderComponent( 10163 * component, 10164 * document.getElementById('container') 10165 * ); 10166 * 10167 * <div id="container"> <-- Supplied `container`. 10168 * <div data-reactid=".3"> <-- Rendered reactRoot of React 10169 * // ... component. 10170 * </div> 10171 * </div> 10172 * 10173 * Inside of `container`, the first element rendered is the "reactRoot". 10174 */ 10175 var ReactMount = { 10176 /** Time spent generating markup. */ 10177 totalInstantiationTime: 0, 10178 10179 /** Time spent inserting markup into the DOM. */ 10180 totalInjectionTime: 0, 10181 10182 /** Whether support for touch events should be initialized. */ 10183 useTouchEvents: false, 10184 10185 /** Exposed for debugging purposes **/ 10186 _instancesByReactRootID: instancesByReactRootID, 10187 10188 /** 10189 * This is a hook provided to support rendering React components while 10190 * ensuring that the apparent scroll position of its `container` does not 10191 * change. 10192 * 10193 * @param {DOMElement} container The `container` being rendered into. 10194 * @param {function} renderCallback This must be called once to do the render. 10195 */ 10196 scrollMonitor: function(container, renderCallback) { 10197 renderCallback(); 10198 }, 10199 10200 /** 10201 * Take a component that's already mounted into the DOM and replace its props 10202 * @param {ReactComponent} prevComponent component instance already in the DOM 10203 * @param {ReactComponent} nextComponent component instance to render 10204 * @param {DOMElement} container container to render into 10205 * @param {?function} callback function triggered on completion 10206 */ 10207 _updateRootComponent: function( 10208 prevComponent, 10209 nextComponent, 10210 container, 10211 callback) { 10212 var nextProps = nextComponent.props; 10213 ReactMount.scrollMonitor(container, function() { 10214 prevComponent.replaceProps(nextProps, callback); 10215 }); 10216 10217 if ("production" !== "development") { 10218 // Record the root element in case it later gets transplanted. 10219 rootElementsByReactRootID[getReactRootID(container)] = 10220 getReactRootElementInContainer(container); 10221 } 10222 10223 return prevComponent; 10224 }, 10225 10226 /** 10227 * Register a component into the instance map and starts scroll value 10228 * monitoring 10229 * @param {ReactComponent} nextComponent component instance to render 10230 * @param {DOMElement} container container to render into 10231 * @return {string} reactRoot ID prefix 10232 */ 10233 _registerComponent: function(nextComponent, container) { 10234 ("production" !== "development" ? invariant( 10235 container && ( 10236 container.nodeType === ELEMENT_NODE_TYPE || 10237 container.nodeType === DOC_NODE_TYPE 10238 ), 10239 '_registerComponent(...): Target container is not a DOM element.' 10240 ) : invariant(container && ( 10241 container.nodeType === ELEMENT_NODE_TYPE || 10242 container.nodeType === DOC_NODE_TYPE 10243 ))); 10244 10245 ReactEventEmitter.ensureScrollValueMonitoring(); 10246 10247 var reactRootID = ReactMount.registerContainer(container); 10248 instancesByReactRootID[reactRootID] = nextComponent; 10249 return reactRootID; 10250 }, 10251 10252 /** 10253 * Render a new component into the DOM. 10254 * @param {ReactComponent} nextComponent component instance to render 10255 * @param {DOMElement} container container to render into 10256 * @param {boolean} shouldReuseMarkup if we should skip the markup insertion 10257 * @return {ReactComponent} nextComponent 10258 */ 10259 _renderNewRootComponent: ReactPerf.measure( 10260 'ReactMount', 10261 '_renderNewRootComponent', 10262 function( 10263 nextComponent, 10264 container, 10265 shouldReuseMarkup) { 10266 10267 var componentInstance = instantiateReactComponent(nextComponent); 10268 var reactRootID = ReactMount._registerComponent( 10269 componentInstance, 10270 container 10271 ); 10272 componentInstance.mountComponentIntoNode( 10273 reactRootID, 10274 container, 10275 shouldReuseMarkup 10276 ); 10277 10278 if ("production" !== "development") { 10279 // Record the root element in case it later gets transplanted. 10280 rootElementsByReactRootID[reactRootID] = 10281 getReactRootElementInContainer(container); 10282 } 10283 10284 return componentInstance; 10285 } 10286 ), 10287 10288 /** 10289 * Renders a React component into the DOM in the supplied `container`. 10290 * 10291 * If the React component was previously rendered into `container`, this will 10292 * perform an update on it and only mutate the DOM as necessary to reflect the 10293 * latest React component. 10294 * 10295 * @param {ReactComponent} nextComponent Component instance to render. 10296 * @param {DOMElement} container DOM element to render into. 10297 * @param {?function} callback function triggered on completion 10298 * @return {ReactComponent} Component instance rendered in `container`. 10299 */ 10300 renderComponent: function(nextComponent, container, callback) { 10301 var prevComponent = instancesByReactRootID[getReactRootID(container)]; 10302 10303 if (prevComponent) { 10304 if (shouldUpdateReactComponent(prevComponent, nextComponent)) { 10305 return ReactMount._updateRootComponent( 10306 prevComponent, 10307 nextComponent, 10308 container, 10309 callback 10310 ); 10311 } else { 10312 ReactMount.unmountComponentAtNode(container); 10313 } 10314 } 10315 10316 var reactRootElement = getReactRootElementInContainer(container); 10317 var containerHasReactMarkup = 10318 reactRootElement && ReactMount.isRenderedByReact(reactRootElement); 10319 10320 var shouldReuseMarkup = containerHasReactMarkup && !prevComponent; 10321 10322 var component = ReactMount._renderNewRootComponent( 10323 nextComponent, 10324 container, 10325 shouldReuseMarkup 10326 ); 10327 callback && callback.call(component); 10328 return component; 10329 }, 10330 10331 /** 10332 * Constructs a component instance of `constructor` with `initialProps` and 10333 * renders it into the supplied `container`. 10334 * 10335 * @param {function} constructor React component constructor. 10336 * @param {?object} props Initial props of the component instance. 10337 * @param {DOMElement} container DOM element to render into. 10338 * @return {ReactComponent} Component instance rendered in `container`. 10339 */ 10340 constructAndRenderComponent: function(constructor, props, container) { 10341 return ReactMount.renderComponent(constructor(props), container); 10342 }, 10343 10344 /** 10345 * Constructs a component instance of `constructor` with `initialProps` and 10346 * renders it into a container node identified by supplied `id`. 10347 * 10348 * @param {function} componentConstructor React component constructor 10349 * @param {?object} props Initial props of the component instance. 10350 * @param {string} id ID of the DOM element to render into. 10351 * @return {ReactComponent} Component instance rendered in the container node. 10352 */ 10353 constructAndRenderComponentByID: function(constructor, props, id) { 10354 var domNode = document.getElementById(id); 10355 ("production" !== "development" ? invariant( 10356 domNode, 10357 'Tried to get element with id of "%s" but it is not present on the page.', 10358 id 10359 ) : invariant(domNode)); 10360 return ReactMount.constructAndRenderComponent(constructor, props, domNode); 10361 }, 10362 10363 /** 10364 * Registers a container node into which React components will be rendered. 10365 * This also creates the "reactRoot" ID that will be assigned to the element 10366 * rendered within. 10367 * 10368 * @param {DOMElement} container DOM element to register as a container. 10369 * @return {string} The "reactRoot" ID of elements rendered within. 10370 */ 10371 registerContainer: function(container) { 10372 var reactRootID = getReactRootID(container); 10373 if (reactRootID) { 10374 // If one exists, make sure it is a valid "reactRoot" ID. 10375 reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID); 10376 } 10377 if (!reactRootID) { 10378 // No valid "reactRoot" ID found, create one. 10379 reactRootID = ReactInstanceHandles.createReactRootID(); 10380 } 10381 containersByReactRootID[reactRootID] = container; 10382 return reactRootID; 10383 }, 10384 10385 /** 10386 * Unmounts and destroys the React component rendered in the `container`. 10387 * 10388 * @param {DOMElement} container DOM element containing a React component. 10389 * @return {boolean} True if a component was found in and unmounted from 10390 * `container` 10391 */ 10392 unmountComponentAtNode: function(container) { 10393 var reactRootID = getReactRootID(container); 10394 var component = instancesByReactRootID[reactRootID]; 10395 if (!component) { 10396 return false; 10397 } 10398 ReactMount.unmountComponentFromNode(component, container); 10399 delete instancesByReactRootID[reactRootID]; 10400 delete containersByReactRootID[reactRootID]; 10401 if ("production" !== "development") { 10402 delete rootElementsByReactRootID[reactRootID]; 10403 } 10404 return true; 10405 }, 10406 10407 /** 10408 * Unmounts a component and removes it from the DOM. 10409 * 10410 * @param {ReactComponent} instance React component instance. 10411 * @param {DOMElement} container DOM element to unmount from. 10412 * @final 10413 * @internal 10414 * @see {ReactMount.unmountComponentAtNode} 10415 */ 10416 unmountComponentFromNode: function(instance, container) { 10417 instance.unmountComponent(); 10418 10419 if (container.nodeType === DOC_NODE_TYPE) { 10420 container = container.documentElement; 10421 } 10422 10423 // http://jsperf.com/emptying-a-node 10424 while (container.lastChild) { 10425 container.removeChild(container.lastChild); 10426 } 10427 }, 10428 10429 /** 10430 * Finds the container DOM element that contains React component to which the 10431 * supplied DOM `id` belongs. 10432 * 10433 * @param {string} id The ID of an element rendered by a React component. 10434 * @return {?DOMElement} DOM element that contains the `id`. 10435 */ 10436 findReactContainerForID: function(id) { 10437 var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(id); 10438 var container = containersByReactRootID[reactRootID]; 10439 10440 if ("production" !== "development") { 10441 var rootElement = rootElementsByReactRootID[reactRootID]; 10442 if (rootElement && rootElement.parentNode !== container) { 10443 ("production" !== "development" ? invariant( 10444 // Call internalGetID here because getID calls isValid which calls 10445 // findReactContainerForID (this function). 10446 internalGetID(rootElement) === reactRootID, 10447 'ReactMount: Root element ID differed from reactRootID.' 10448 ) : invariant(// Call internalGetID here because getID calls isValid which calls 10449 // findReactContainerForID (this function). 10450 internalGetID(rootElement) === reactRootID)); 10451 10452 var containerChild = container.firstChild; 10453 if (containerChild && 10454 reactRootID === internalGetID(containerChild)) { 10455 // If the container has a new child with the same ID as the old 10456 // root element, then rootElementsByReactRootID[reactRootID] is 10457 // just stale and needs to be updated. The case that deserves a 10458 // warning is when the container is empty. 10459 rootElementsByReactRootID[reactRootID] = containerChild; 10460 } else { 10461 console.warn( 10462 'ReactMount: Root element has been removed from its original ' + 10463 'container. New container:', rootElement.parentNode 10464 ); 10465 } 10466 } 10467 } 10468 10469 return container; 10470 }, 10471 10472 /** 10473 * Finds an element rendered by React with the supplied ID. 10474 * 10475 * @param {string} id ID of a DOM node in the React component. 10476 * @return {DOMElement} Root DOM node of the React component. 10477 */ 10478 findReactNodeByID: function(id) { 10479 var reactRoot = ReactMount.findReactContainerForID(id); 10480 return ReactMount.findComponentRoot(reactRoot, id); 10481 }, 10482 10483 /** 10484 * True if the supplied `node` is rendered by React. 10485 * 10486 * @param {*} node DOM Element to check. 10487 * @return {boolean} True if the DOM Element appears to be rendered by React. 10488 * @internal 10489 */ 10490 isRenderedByReact: function(node) { 10491 if (node.nodeType !== 1) { 10492 // Not a DOMElement, therefore not a React component 10493 return false; 10494 } 10495 var id = ReactMount.getID(node); 10496 return id ? id.charAt(0) === SEPARATOR : false; 10497 }, 10498 10499 /** 10500 * Traverses up the ancestors of the supplied node to find a node that is a 10501 * DOM representation of a React component. 10502 * 10503 * @param {*} node 10504 * @return {?DOMEventTarget} 10505 * @internal 10506 */ 10507 getFirstReactDOM: function(node) { 10508 var current = node; 10509 while (current && current.parentNode !== current) { 10510 if (ReactMount.isRenderedByReact(current)) { 10511 return current; 10512 } 10513 current = current.parentNode; 10514 } 10515 return null; 10516 }, 10517 10518 /** 10519 * Finds a node with the supplied `targetID` inside of the supplied 10520 * `ancestorNode`. Exploits the ID naming scheme to perform the search 10521 * quickly. 10522 * 10523 * @param {DOMEventTarget} ancestorNode Search from this root. 10524 * @pararm {string} targetID ID of the DOM representation of the component. 10525 * @return {DOMEventTarget} DOM node with the supplied `targetID`. 10526 * @internal 10527 */ 10528 findComponentRoot: function(ancestorNode, targetID) { 10529 var firstChildren = findComponentRootReusableArray; 10530 var childIndex = 0; 10531 10532 var deepestAncestor = findDeepestCachedAncestor(targetID) || ancestorNode; 10533 10534 firstChildren[0] = deepestAncestor.firstChild; 10535 firstChildren.length = 1; 10536 10537 while (childIndex < firstChildren.length) { 10538 var child = firstChildren[childIndex++]; 10539 var targetChild; 10540 10541 while (child) { 10542 var childID = ReactMount.getID(child); 10543 if (childID) { 10544 // Even if we find the node we're looking for, we finish looping 10545 // through its siblings to ensure they're cached so that we don't have 10546 // to revisit this node again. Otherwise, we make n^2 calls to getID 10547 // when visiting the many children of a single node in order. 10548 10549 if (targetID === childID) { 10550 targetChild = child; 10551 } else if (ReactInstanceHandles.isAncestorIDOf(childID, targetID)) { 10552 // If we find a child whose ID is an ancestor of the given ID, 10553 // then we can be sure that we only want to search the subtree 10554 // rooted at this child, so we can throw out the rest of the 10555 // search state. 10556 firstChildren.length = childIndex = 0; 10557 firstChildren.push(child.firstChild); 10558 } 10559 10560 } else { 10561 // If this child had no ID, then there's a chance that it was 10562 // injected automatically by the browser, as when a `<table>` 10563 // element sprouts an extra `<tbody>` child as a side effect of 10564 // `.innerHTML` parsing. Optimistically continue down this 10565 // branch, but not before examining the other siblings. 10566 firstChildren.push(child.firstChild); 10567 } 10568 10569 child = child.nextSibling; 10570 } 10571 10572 if (targetChild) { 10573 // Emptying firstChildren/findComponentRootReusableArray is 10574 // not necessary for correctness, but it helps the GC reclaim 10575 // any nodes that were left at the end of the search. 10576 firstChildren.length = 0; 10577 10578 return targetChild; 10579 } 10580 } 10581 10582 firstChildren.length = 0; 10583 10584 ("production" !== "development" ? invariant( 10585 false, 10586 'findComponentRoot(..., %s): Unable to find element. This probably ' + 10587 'means the DOM was unexpectedly mutated (e.g., by the browser), ' + 10588 'usually due to forgetting a <tbody> when using tables or nesting <p> ' + 10589 'or <a> tags. Try inspecting the child nodes of the element with React ' + 10590 'ID `%s`.', 10591 targetID, 10592 ReactMount.getID(ancestorNode) 10593 ) : invariant(false)); 10594 }, 10595 10596 10597 /** 10598 * React ID utilities. 10599 */ 10600 10601 getReactRootID: getReactRootID, 10602 10603 getID: getID, 10604 10605 setID: setID, 10606 10607 getNode: getNode, 10608 10609 purgeID: purgeID 10610 }; 10611 10612 module.exports = ReactMount; 10613 10614 },{"./DOMProperty":8,"./ReactEventEmitter":48,"./ReactInstanceHandles":53,"./ReactPerf":60,"./containsNode":89,"./getReactRootElementInContainer":107,"./instantiateReactComponent":111,"./invariant":112,"./shouldUpdateReactComponent":131}],56:[function(_dereq_,module,exports){ 10615 /** 10616 * Copyright 2013-2014 Facebook, Inc. 10617 * 10618 * Licensed under the Apache License, Version 2.0 (the "License"); 10619 * you may not use this file except in compliance with the License. 10620 * You may obtain a copy of the License at 10621 * 10622 * http://www.apache.org/licenses/LICENSE-2.0 10623 * 10624 * Unless required by applicable law or agreed to in writing, software 10625 * distributed under the License is distributed on an "AS IS" BASIS, 10626 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10627 * See the License for the specific language governing permissions and 10628 * limitations under the License. 10629 * 10630 * @providesModule ReactMountReady 10631 */ 10632 10633 "use strict"; 10634 10635 var PooledClass = _dereq_("./PooledClass"); 10636 10637 var mixInto = _dereq_("./mixInto"); 10638 10639 /** 10640 * A specialized pseudo-event module to help keep track of components waiting to 10641 * be notified when their DOM representations are available for use. 10642 * 10643 * This implements `PooledClass`, so you should never need to instantiate this. 10644 * Instead, use `ReactMountReady.getPooled()`. 10645 * 10646 * @param {?array<function>} initialCollection 10647 * @class ReactMountReady 10648 * @implements PooledClass 10649 * @internal 10650 */ 10651 function ReactMountReady(initialCollection) { 10652 this._queue = initialCollection || null; 10653 } 10654 10655 mixInto(ReactMountReady, { 10656 10657 /** 10658 * Enqueues a callback to be invoked when `notifyAll` is invoked. This is used 10659 * to enqueue calls to `componentDidMount` and `componentDidUpdate`. 10660 * 10661 * @param {ReactComponent} component Component being rendered. 10662 * @param {function(DOMElement)} callback Invoked when `notifyAll` is invoked. 10663 * @internal 10664 */ 10665 enqueue: function(component, callback) { 10666 this._queue = this._queue || []; 10667 this._queue.push({component: component, callback: callback}); 10668 }, 10669 10670 /** 10671 * Invokes all enqueued callbacks and clears the queue. This is invoked after 10672 * the DOM representation of a component has been created or updated. 10673 * 10674 * @internal 10675 */ 10676 notifyAll: function() { 10677 var queue = this._queue; 10678 if (queue) { 10679 this._queue = null; 10680 for (var i = 0, l = queue.length; i < l; i++) { 10681 var component = queue[i].component; 10682 var callback = queue[i].callback; 10683 callback.call(component); 10684 } 10685 queue.length = 0; 10686 } 10687 }, 10688 10689 /** 10690 * Resets the internal queue. 10691 * 10692 * @internal 10693 */ 10694 reset: function() { 10695 this._queue = null; 10696 }, 10697 10698 /** 10699 * `PooledClass` looks for this. 10700 */ 10701 destructor: function() { 10702 this.reset(); 10703 } 10704 10705 }); 10706 10707 PooledClass.addPoolingTo(ReactMountReady); 10708 10709 module.exports = ReactMountReady; 10710 10711 },{"./PooledClass":23,"./mixInto":124}],57:[function(_dereq_,module,exports){ 10712 /** 10713 * Copyright 2013-2014 Facebook, Inc. 10714 * 10715 * Licensed under the Apache License, Version 2.0 (the "License"); 10716 * you may not use this file except in compliance with the License. 10717 * You may obtain a copy of the License at 10718 * 10719 * http://www.apache.org/licenses/LICENSE-2.0 10720 * 10721 * Unless required by applicable law or agreed to in writing, software 10722 * distributed under the License is distributed on an "AS IS" BASIS, 10723 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10724 * See the License for the specific language governing permissions and 10725 * limitations under the License. 10726 * 10727 * @providesModule ReactMultiChild 10728 * @typechecks static-only 10729 */ 10730 10731 "use strict"; 10732 10733 var ReactComponent = _dereq_("./ReactComponent"); 10734 var ReactMultiChildUpdateTypes = _dereq_("./ReactMultiChildUpdateTypes"); 10735 10736 var flattenChildren = _dereq_("./flattenChildren"); 10737 var instantiateReactComponent = _dereq_("./instantiateReactComponent"); 10738 var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent"); 10739 10740 /** 10741 * Updating children of a component may trigger recursive updates. The depth is 10742 * used to batch recursive updates to render markup more efficiently. 10743 * 10744 * @type {number} 10745 * @private 10746 */ 10747 var updateDepth = 0; 10748 10749 /** 10750 * Queue of update configuration objects. 10751 * 10752 * Each object has a `type` property that is in `ReactMultiChildUpdateTypes`. 10753 * 10754 * @type {array<object>} 10755 * @private 10756 */ 10757 var updateQueue = []; 10758 10759 /** 10760 * Queue of markup to be rendered. 10761 * 10762 * @type {array<string>} 10763 * @private 10764 */ 10765 var markupQueue = []; 10766 10767 /** 10768 * Enqueues markup to be rendered and inserted at a supplied index. 10769 * 10770 * @param {string} parentID ID of the parent component. 10771 * @param {string} markup Markup that renders into an element. 10772 * @param {number} toIndex Destination index. 10773 * @private 10774 */ 10775 function enqueueMarkup(parentID, markup, toIndex) { 10776 // NOTE: Null values reduce hidden classes. 10777 updateQueue.push({ 10778 parentID: parentID, 10779 parentNode: null, 10780 type: ReactMultiChildUpdateTypes.INSERT_MARKUP, 10781 markupIndex: markupQueue.push(markup) - 1, 10782 textContent: null, 10783 fromIndex: null, 10784 toIndex: toIndex 10785 }); 10786 } 10787 10788 /** 10789 * Enqueues moving an existing element to another index. 10790 * 10791 * @param {string} parentID ID of the parent component. 10792 * @param {number} fromIndex Source index of the existing element. 10793 * @param {number} toIndex Destination index of the element. 10794 * @private 10795 */ 10796 function enqueueMove(parentID, fromIndex, toIndex) { 10797 // NOTE: Null values reduce hidden classes. 10798 updateQueue.push({ 10799 parentID: parentID, 10800 parentNode: null, 10801 type: ReactMultiChildUpdateTypes.MOVE_EXISTING, 10802 markupIndex: null, 10803 textContent: null, 10804 fromIndex: fromIndex, 10805 toIndex: toIndex 10806 }); 10807 } 10808 10809 /** 10810 * Enqueues removing an element at an index. 10811 * 10812 * @param {string} parentID ID of the parent component. 10813 * @param {number} fromIndex Index of the element to remove. 10814 * @private 10815 */ 10816 function enqueueRemove(parentID, fromIndex) { 10817 // NOTE: Null values reduce hidden classes. 10818 updateQueue.push({ 10819 parentID: parentID, 10820 parentNode: null, 10821 type: ReactMultiChildUpdateTypes.REMOVE_NODE, 10822 markupIndex: null, 10823 textContent: null, 10824 fromIndex: fromIndex, 10825 toIndex: null 10826 }); 10827 } 10828 10829 /** 10830 * Enqueues setting the text content. 10831 * 10832 * @param {string} parentID ID of the parent component. 10833 * @param {string} textContent Text content to set. 10834 * @private 10835 */ 10836 function enqueueTextContent(parentID, textContent) { 10837 // NOTE: Null values reduce hidden classes. 10838 updateQueue.push({ 10839 parentID: parentID, 10840 parentNode: null, 10841 type: ReactMultiChildUpdateTypes.TEXT_CONTENT, 10842 markupIndex: null, 10843 textContent: textContent, 10844 fromIndex: null, 10845 toIndex: null 10846 }); 10847 } 10848 10849 /** 10850 * Processes any enqueued updates. 10851 * 10852 * @private 10853 */ 10854 function processQueue() { 10855 if (updateQueue.length) { 10856 ReactComponent.BackendIDOperations.dangerouslyProcessChildrenUpdates( 10857 updateQueue, 10858 markupQueue 10859 ); 10860 clearQueue(); 10861 } 10862 } 10863 10864 /** 10865 * Clears any enqueued updates. 10866 * 10867 * @private 10868 */ 10869 function clearQueue() { 10870 updateQueue.length = 0; 10871 markupQueue.length = 0; 10872 } 10873 10874 /** 10875 * ReactMultiChild are capable of reconciling multiple children. 10876 * 10877 * @class ReactMultiChild 10878 * @internal 10879 */ 10880 var ReactMultiChild = { 10881 10882 /** 10883 * Provides common functionality for components that must reconcile multiple 10884 * children. This is used by `ReactDOMComponent` to mount, update, and 10885 * unmount child components. 10886 * 10887 * @lends {ReactMultiChild.prototype} 10888 */ 10889 Mixin: { 10890 10891 /** 10892 * Generates a "mount image" for each of the supplied children. In the case 10893 * of `ReactDOMComponent`, a mount image is a string of markup. 10894 * 10895 * @param {?object} nestedChildren Nested child maps. 10896 * @return {array} An array of mounted representations. 10897 * @internal 10898 */ 10899 mountChildren: function(nestedChildren, transaction) { 10900 var children = flattenChildren(nestedChildren); 10901 var mountImages = []; 10902 var index = 0; 10903 this._renderedChildren = children; 10904 for (var name in children) { 10905 var child = children[name]; 10906 if (children.hasOwnProperty(name)) { 10907 // The rendered children must be turned into instances as they're 10908 // mounted. 10909 var childInstance = instantiateReactComponent(child); 10910 children[name] = childInstance; 10911 // Inlined for performance, see `ReactInstanceHandles.createReactID`. 10912 var rootID = this._rootNodeID + name; 10913 var mountImage = childInstance.mountComponent( 10914 rootID, 10915 transaction, 10916 this._mountDepth + 1 10917 ); 10918 childInstance._mountIndex = index; 10919 mountImages.push(mountImage); 10920 index++; 10921 } 10922 } 10923 return mountImages; 10924 }, 10925 10926 /** 10927 * Replaces any rendered children with a text content string. 10928 * 10929 * @param {string} nextContent String of content. 10930 * @internal 10931 */ 10932 updateTextContent: function(nextContent) { 10933 updateDepth++; 10934 var errorThrown = true; 10935 try { 10936 var prevChildren = this._renderedChildren; 10937 // Remove any rendered children. 10938 for (var name in prevChildren) { 10939 if (prevChildren.hasOwnProperty(name)) { 10940 this._unmountChildByName(prevChildren[name], name); 10941 } 10942 } 10943 // Set new text content. 10944 this.setTextContent(nextContent); 10945 errorThrown = false; 10946 } finally { 10947 updateDepth--; 10948 if (!updateDepth) { 10949 errorThrown ? clearQueue() : processQueue(); 10950 } 10951 } 10952 }, 10953 10954 /** 10955 * Updates the rendered children with new children. 10956 * 10957 * @param {?object} nextNestedChildren Nested child maps. 10958 * @param {ReactReconcileTransaction} transaction 10959 * @internal 10960 */ 10961 updateChildren: function(nextNestedChildren, transaction) { 10962 updateDepth++; 10963 var errorThrown = true; 10964 try { 10965 this._updateChildren(nextNestedChildren, transaction); 10966 errorThrown = false; 10967 } finally { 10968 updateDepth--; 10969 if (!updateDepth) { 10970 errorThrown ? clearQueue() : processQueue(); 10971 } 10972 } 10973 }, 10974 10975 /** 10976 * Improve performance by isolating this hot code path from the try/catch 10977 * block in `updateChildren`. 10978 * 10979 * @param {?object} nextNestedChildren Nested child maps. 10980 * @param {ReactReconcileTransaction} transaction 10981 * @final 10982 * @protected 10983 */ 10984 _updateChildren: function(nextNestedChildren, transaction) { 10985 var nextChildren = flattenChildren(nextNestedChildren); 10986 var prevChildren = this._renderedChildren; 10987 if (!nextChildren && !prevChildren) { 10988 return; 10989 } 10990 var name; 10991 // `nextIndex` will increment for each child in `nextChildren`, but 10992 // `lastIndex` will be the last index visited in `prevChildren`. 10993 var lastIndex = 0; 10994 var nextIndex = 0; 10995 for (name in nextChildren) { 10996 if (!nextChildren.hasOwnProperty(name)) { 10997 continue; 10998 } 10999 var prevChild = prevChildren && prevChildren[name]; 11000 var nextChild = nextChildren[name]; 11001 if (shouldUpdateReactComponent(prevChild, nextChild)) { 11002 this.moveChild(prevChild, nextIndex, lastIndex); 11003 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 11004 prevChild.receiveComponent(nextChild, transaction); 11005 prevChild._mountIndex = nextIndex; 11006 } else { 11007 if (prevChild) { 11008 // Update `lastIndex` before `_mountIndex` gets unset by unmounting. 11009 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 11010 this._unmountChildByName(prevChild, name); 11011 } 11012 // The child must be instantiated before it's mounted. 11013 var nextChildInstance = instantiateReactComponent(nextChild); 11014 this._mountChildByNameAtIndex( 11015 nextChildInstance, name, nextIndex, transaction 11016 ); 11017 } 11018 nextIndex++; 11019 } 11020 // Remove children that are no longer present. 11021 for (name in prevChildren) { 11022 if (prevChildren.hasOwnProperty(name) && 11023 !(nextChildren && nextChildren[name])) { 11024 this._unmountChildByName(prevChildren[name], name); 11025 } 11026 } 11027 }, 11028 11029 /** 11030 * Unmounts all rendered children. This should be used to clean up children 11031 * when this component is unmounted. 11032 * 11033 * @internal 11034 */ 11035 unmountChildren: function() { 11036 var renderedChildren = this._renderedChildren; 11037 for (var name in renderedChildren) { 11038 var renderedChild = renderedChildren[name]; 11039 // TODO: When is this not true? 11040 if (renderedChild.unmountComponent) { 11041 renderedChild.unmountComponent(); 11042 } 11043 } 11044 this._renderedChildren = null; 11045 }, 11046 11047 /** 11048 * Moves a child component to the supplied index. 11049 * 11050 * @param {ReactComponent} child Component to move. 11051 * @param {number} toIndex Destination index of the element. 11052 * @param {number} lastIndex Last index visited of the siblings of `child`. 11053 * @protected 11054 */ 11055 moveChild: function(child, toIndex, lastIndex) { 11056 // If the index of `child` is less than `lastIndex`, then it needs to 11057 // be moved. Otherwise, we do not need to move it because a child will be 11058 // inserted or moved before `child`. 11059 if (child._mountIndex < lastIndex) { 11060 enqueueMove(this._rootNodeID, child._mountIndex, toIndex); 11061 } 11062 }, 11063 11064 /** 11065 * Creates a child component. 11066 * 11067 * @param {ReactComponent} child Component to create. 11068 * @param {string} mountImage Markup to insert. 11069 * @protected 11070 */ 11071 createChild: function(child, mountImage) { 11072 enqueueMarkup(this._rootNodeID, mountImage, child._mountIndex); 11073 }, 11074 11075 /** 11076 * Removes a child component. 11077 * 11078 * @param {ReactComponent} child Child to remove. 11079 * @protected 11080 */ 11081 removeChild: function(child) { 11082 enqueueRemove(this._rootNodeID, child._mountIndex); 11083 }, 11084 11085 /** 11086 * Sets this text content string. 11087 * 11088 * @param {string} textContent Text content to set. 11089 * @protected 11090 */ 11091 setTextContent: function(textContent) { 11092 enqueueTextContent(this._rootNodeID, textContent); 11093 }, 11094 11095 /** 11096 * Mounts a child with the supplied name. 11097 * 11098 * NOTE: This is part of `updateChildren` and is here for readability. 11099 * 11100 * @param {ReactComponent} child Component to mount. 11101 * @param {string} name Name of the child. 11102 * @param {number} index Index at which to insert the child. 11103 * @param {ReactReconcileTransaction} transaction 11104 * @private 11105 */ 11106 _mountChildByNameAtIndex: function(child, name, index, transaction) { 11107 // Inlined for performance, see `ReactInstanceHandles.createReactID`. 11108 var rootID = this._rootNodeID + name; 11109 var mountImage = child.mountComponent( 11110 rootID, 11111 transaction, 11112 this._mountDepth + 1 11113 ); 11114 child._mountIndex = index; 11115 this.createChild(child, mountImage); 11116 this._renderedChildren = this._renderedChildren || {}; 11117 this._renderedChildren[name] = child; 11118 }, 11119 11120 /** 11121 * Unmounts a rendered child by name. 11122 * 11123 * NOTE: This is part of `updateChildren` and is here for readability. 11124 * 11125 * @param {ReactComponent} child Component to unmount. 11126 * @param {string} name Name of the child in `this._renderedChildren`. 11127 * @private 11128 */ 11129 _unmountChildByName: function(child, name) { 11130 // TODO: When is this not true? 11131 if (ReactComponent.isValidComponent(child)) { 11132 this.removeChild(child); 11133 child._mountIndex = null; 11134 child.unmountComponent(); 11135 delete this._renderedChildren[name]; 11136 } 11137 } 11138 11139 } 11140 11141 }; 11142 11143 module.exports = ReactMultiChild; 11144 11145 },{"./ReactComponent":27,"./ReactMultiChildUpdateTypes":58,"./flattenChildren":99,"./instantiateReactComponent":111,"./shouldUpdateReactComponent":131}],58:[function(_dereq_,module,exports){ 11146 /** 11147 * Copyright 2013-2014 Facebook, Inc. 11148 * 11149 * Licensed under the Apache License, Version 2.0 (the "License"); 11150 * you may not use this file except in compliance with the License. 11151 * You may obtain a copy of the License at 11152 * 11153 * http://www.apache.org/licenses/LICENSE-2.0 11154 * 11155 * Unless required by applicable law or agreed to in writing, software 11156 * distributed under the License is distributed on an "AS IS" BASIS, 11157 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11158 * See the License for the specific language governing permissions and 11159 * limitations under the License. 11160 * 11161 * @providesModule ReactMultiChildUpdateTypes 11162 */ 11163 11164 "use strict"; 11165 11166 var keyMirror = _dereq_("./keyMirror"); 11167 11168 /** 11169 * When a component's children are updated, a series of update configuration 11170 * objects are created in order to batch and serialize the required changes. 11171 * 11172 * Enumerates all the possible types of update configurations. 11173 * 11174 * @internal 11175 */ 11176 var ReactMultiChildUpdateTypes = keyMirror({ 11177 INSERT_MARKUP: null, 11178 MOVE_EXISTING: null, 11179 REMOVE_NODE: null, 11180 TEXT_CONTENT: null 11181 }); 11182 11183 module.exports = ReactMultiChildUpdateTypes; 11184 11185 },{"./keyMirror":118}],59:[function(_dereq_,module,exports){ 11186 /** 11187 * Copyright 2013-2014 Facebook, Inc. 11188 * 11189 * Licensed under the Apache License, Version 2.0 (the "License"); 11190 * you may not use this file except in compliance with the License. 11191 * You may obtain a copy of the License at 11192 * 11193 * http://www.apache.org/licenses/LICENSE-2.0 11194 * 11195 * Unless required by applicable law or agreed to in writing, software 11196 * distributed under the License is distributed on an "AS IS" BASIS, 11197 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11198 * See the License for the specific language governing permissions and 11199 * limitations under the License. 11200 * 11201 * @providesModule ReactOwner 11202 */ 11203 11204 "use strict"; 11205 11206 var emptyObject = _dereq_("./emptyObject"); 11207 var invariant = _dereq_("./invariant"); 11208 11209 /** 11210 * ReactOwners are capable of storing references to owned components. 11211 * 11212 * All components are capable of //being// referenced by owner components, but 11213 * only ReactOwner components are capable of //referencing// owned components. 11214 * The named reference is known as a "ref". 11215 * 11216 * Refs are available when mounted and updated during reconciliation. 11217 * 11218 * var MyComponent = React.createClass({ 11219 * render: function() { 11220 * return ( 11221 * <div onClick={this.handleClick}> 11222 * <CustomComponent ref="custom" /> 11223 * </div> 11224 * ); 11225 * }, 11226 * handleClick: function() { 11227 * this.refs.custom.handleClick(); 11228 * }, 11229 * componentDidMount: function() { 11230 * this.refs.custom.initialize(); 11231 * } 11232 * }); 11233 * 11234 * Refs should rarely be used. When refs are used, they should only be done to 11235 * control data that is not handled by React's data flow. 11236 * 11237 * @class ReactOwner 11238 */ 11239 var ReactOwner = { 11240 11241 /** 11242 * @param {?object} object 11243 * @return {boolean} True if `object` is a valid owner. 11244 * @final 11245 */ 11246 isValidOwner: function(object) { 11247 return !!( 11248 object && 11249 typeof object.attachRef === 'function' && 11250 typeof object.detachRef === 'function' 11251 ); 11252 }, 11253 11254 /** 11255 * Adds a component by ref to an owner component. 11256 * 11257 * @param {ReactComponent} component Component to reference. 11258 * @param {string} ref Name by which to refer to the component. 11259 * @param {ReactOwner} owner Component on which to record the ref. 11260 * @final 11261 * @internal 11262 */ 11263 addComponentAsRefTo: function(component, ref, owner) { 11264 ("production" !== "development" ? invariant( 11265 ReactOwner.isValidOwner(owner), 11266 'addComponentAsRefTo(...): Only a ReactOwner can have refs. This ' + 11267 'usually means that you\'re trying to add a ref to a component that ' + 11268 'doesn\'t have an owner (that is, was not created inside of another ' + 11269 'component\'s `render` method). Try rendering this component inside of ' + 11270 'a new top-level component which will hold the ref.' 11271 ) : invariant(ReactOwner.isValidOwner(owner))); 11272 owner.attachRef(ref, component); 11273 }, 11274 11275 /** 11276 * Removes a component by ref from an owner component. 11277 * 11278 * @param {ReactComponent} component Component to dereference. 11279 * @param {string} ref Name of the ref to remove. 11280 * @param {ReactOwner} owner Component on which the ref is recorded. 11281 * @final 11282 * @internal 11283 */ 11284 removeComponentAsRefFrom: function(component, ref, owner) { 11285 ("production" !== "development" ? invariant( 11286 ReactOwner.isValidOwner(owner), 11287 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. This ' + 11288 'usually means that you\'re trying to remove a ref to a component that ' + 11289 'doesn\'t have an owner (that is, was not created inside of another ' + 11290 'component\'s `render` method). Try rendering this component inside of ' + 11291 'a new top-level component which will hold the ref.' 11292 ) : invariant(ReactOwner.isValidOwner(owner))); 11293 // Check that `component` is still the current ref because we do not want to 11294 // detach the ref if another component stole it. 11295 if (owner.refs[ref] === component) { 11296 owner.detachRef(ref); 11297 } 11298 }, 11299 11300 /** 11301 * A ReactComponent must mix this in to have refs. 11302 * 11303 * @lends {ReactOwner.prototype} 11304 */ 11305 Mixin: { 11306 11307 construct: function() { 11308 this.refs = emptyObject; 11309 }, 11310 11311 /** 11312 * Lazily allocates the refs object and stores `component` as `ref`. 11313 * 11314 * @param {string} ref Reference name. 11315 * @param {component} component Component to store as `ref`. 11316 * @final 11317 * @private 11318 */ 11319 attachRef: function(ref, component) { 11320 ("production" !== "development" ? invariant( 11321 component.isOwnedBy(this), 11322 'attachRef(%s, ...): Only a component\'s owner can store a ref to it.', 11323 ref 11324 ) : invariant(component.isOwnedBy(this))); 11325 var refs = this.refs === emptyObject ? (this.refs = {}) : this.refs; 11326 refs[ref] = component; 11327 }, 11328 11329 /** 11330 * Detaches a reference name. 11331 * 11332 * @param {string} ref Name to dereference. 11333 * @final 11334 * @private 11335 */ 11336 detachRef: function(ref) { 11337 delete this.refs[ref]; 11338 } 11339 11340 } 11341 11342 }; 11343 11344 module.exports = ReactOwner; 11345 11346 },{"./emptyObject":97,"./invariant":112}],60:[function(_dereq_,module,exports){ 11347 /** 11348 * Copyright 2013-2014 Facebook, Inc. 11349 * 11350 * Licensed under the Apache License, Version 2.0 (the "License"); 11351 * you may not use this file except in compliance with the License. 11352 * You may obtain a copy of the License at 11353 * 11354 * http://www.apache.org/licenses/LICENSE-2.0 11355 * 11356 * Unless required by applicable law or agreed to in writing, software 11357 * distributed under the License is distributed on an "AS IS" BASIS, 11358 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11359 * See the License for the specific language governing permissions and 11360 * limitations under the License. 11361 * 11362 * @providesModule ReactPerf 11363 * @typechecks static-only 11364 */ 11365 11366 "use strict"; 11367 11368 /** 11369 * ReactPerf is a general AOP system designed to measure performance. This 11370 * module only has the hooks: see ReactDefaultPerf for the analysis tool. 11371 */ 11372 var ReactPerf = { 11373 /** 11374 * Boolean to enable/disable measurement. Set to false by default to prevent 11375 * accidental logging and perf loss. 11376 */ 11377 enableMeasure: false, 11378 11379 /** 11380 * Holds onto the measure function in use. By default, don't measure 11381 * anything, but we'll override this if we inject a measure function. 11382 */ 11383 storedMeasure: _noMeasure, 11384 11385 /** 11386 * Use this to wrap methods you want to measure. Zero overhead in production. 11387 * 11388 * @param {string} objName 11389 * @param {string} fnName 11390 * @param {function} func 11391 * @return {function} 11392 */ 11393 measure: function(objName, fnName, func) { 11394 if ("production" !== "development") { 11395 var measuredFunc = null; 11396 return function() { 11397 if (ReactPerf.enableMeasure) { 11398 if (!measuredFunc) { 11399 measuredFunc = ReactPerf.storedMeasure(objName, fnName, func); 11400 } 11401 return measuredFunc.apply(this, arguments); 11402 } 11403 return func.apply(this, arguments); 11404 }; 11405 } 11406 return func; 11407 }, 11408 11409 injection: { 11410 /** 11411 * @param {function} measure 11412 */ 11413 injectMeasure: function(measure) { 11414 ReactPerf.storedMeasure = measure; 11415 } 11416 } 11417 }; 11418 11419 /** 11420 * Simply passes through the measured function, without measuring it. 11421 * 11422 * @param {string} objName 11423 * @param {string} fnName 11424 * @param {function} func 11425 * @return {function} 11426 */ 11427 function _noMeasure(objName, fnName, func) { 11428 return func; 11429 } 11430 11431 module.exports = ReactPerf; 11432 11433 },{}],61:[function(_dereq_,module,exports){ 11434 /** 11435 * Copyright 2013-2014 Facebook, Inc. 11436 * 11437 * Licensed under the Apache License, Version 2.0 (the "License"); 11438 * you may not use this file except in compliance with the License. 11439 * You may obtain a copy of the License at 11440 * 11441 * http://www.apache.org/licenses/LICENSE-2.0 11442 * 11443 * Unless required by applicable law or agreed to in writing, software 11444 * distributed under the License is distributed on an "AS IS" BASIS, 11445 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11446 * See the License for the specific language governing permissions and 11447 * limitations under the License. 11448 * 11449 * @providesModule ReactPropTransferer 11450 */ 11451 11452 "use strict"; 11453 11454 var emptyFunction = _dereq_("./emptyFunction"); 11455 var invariant = _dereq_("./invariant"); 11456 var joinClasses = _dereq_("./joinClasses"); 11457 var merge = _dereq_("./merge"); 11458 11459 /** 11460 * Creates a transfer strategy that will merge prop values using the supplied 11461 * `mergeStrategy`. If a prop was previously unset, this just sets it. 11462 * 11463 * @param {function} mergeStrategy 11464 * @return {function} 11465 */ 11466 function createTransferStrategy(mergeStrategy) { 11467 return function(props, key, value) { 11468 if (!props.hasOwnProperty(key)) { 11469 props[key] = value; 11470 } else { 11471 props[key] = mergeStrategy(props[key], value); 11472 } 11473 }; 11474 } 11475 11476 /** 11477 * Transfer strategies dictate how props are transferred by `transferPropsTo`. 11478 * NOTE: if you add any more exceptions to this list you should be sure to 11479 * update `cloneWithProps()` accordingly. 11480 */ 11481 var TransferStrategies = { 11482 /** 11483 * Never transfer `children`. 11484 */ 11485 children: emptyFunction, 11486 /** 11487 * Transfer the `className` prop by merging them. 11488 */ 11489 className: createTransferStrategy(joinClasses), 11490 /** 11491 * Never transfer the `key` prop. 11492 */ 11493 key: emptyFunction, 11494 /** 11495 * Never transfer the `ref` prop. 11496 */ 11497 ref: emptyFunction, 11498 /** 11499 * Transfer the `style` prop (which is an object) by merging them. 11500 */ 11501 style: createTransferStrategy(merge) 11502 }; 11503 11504 /** 11505 * ReactPropTransferer are capable of transferring props to another component 11506 * using a `transferPropsTo` method. 11507 * 11508 * @class ReactPropTransferer 11509 */ 11510 var ReactPropTransferer = { 11511 11512 TransferStrategies: TransferStrategies, 11513 11514 /** 11515 * Merge two props objects using TransferStrategies. 11516 * 11517 * @param {object} oldProps original props (they take precedence) 11518 * @param {object} newProps new props to merge in 11519 * @return {object} a new object containing both sets of props merged. 11520 */ 11521 mergeProps: function(oldProps, newProps) { 11522 var props = merge(oldProps); 11523 11524 for (var thisKey in newProps) { 11525 if (!newProps.hasOwnProperty(thisKey)) { 11526 continue; 11527 } 11528 11529 var transferStrategy = TransferStrategies[thisKey]; 11530 11531 if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) { 11532 transferStrategy(props, thisKey, newProps[thisKey]); 11533 } else if (!props.hasOwnProperty(thisKey)) { 11534 props[thisKey] = newProps[thisKey]; 11535 } 11536 } 11537 11538 return props; 11539 }, 11540 11541 /** 11542 * @lends {ReactPropTransferer.prototype} 11543 */ 11544 Mixin: { 11545 11546 /** 11547 * Transfer props from this component to a target component. 11548 * 11549 * Props that do not have an explicit transfer strategy will be transferred 11550 * only if the target component does not already have the prop set. 11551 * 11552 * This is usually used to pass down props to a returned root component. 11553 * 11554 * @param {ReactComponent} component Component receiving the properties. 11555 * @return {ReactComponent} The supplied `component`. 11556 * @final 11557 * @protected 11558 */ 11559 transferPropsTo: function(component) { 11560 ("production" !== "development" ? invariant( 11561 component._owner === this, 11562 '%s: You can\'t call transferPropsTo() on a component that you ' + 11563 'don\'t own, %s. This usually means you are calling ' + 11564 'transferPropsTo() on a component passed in as props or children.', 11565 this.constructor.displayName, 11566 component.constructor.displayName 11567 ) : invariant(component._owner === this)); 11568 11569 component.props = ReactPropTransferer.mergeProps( 11570 component.props, 11571 this.props 11572 ); 11573 11574 return component; 11575 } 11576 11577 } 11578 }; 11579 11580 module.exports = ReactPropTransferer; 11581 11582 },{"./emptyFunction":96,"./invariant":112,"./joinClasses":117,"./merge":121}],62:[function(_dereq_,module,exports){ 11583 /** 11584 * Copyright 2013-2014 Facebook, Inc. 11585 * 11586 * Licensed under the Apache License, Version 2.0 (the "License"); 11587 * you may not use this file except in compliance with the License. 11588 * You may obtain a copy of the License at 11589 * 11590 * http://www.apache.org/licenses/LICENSE-2.0 11591 * 11592 * Unless required by applicable law or agreed to in writing, software 11593 * distributed under the License is distributed on an "AS IS" BASIS, 11594 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11595 * See the License for the specific language governing permissions and 11596 * limitations under the License. 11597 * 11598 * @providesModule ReactPropTypeLocationNames 11599 */ 11600 11601 "use strict"; 11602 11603 var ReactPropTypeLocationNames = {}; 11604 11605 if ("production" !== "development") { 11606 ReactPropTypeLocationNames = { 11607 prop: 'prop', 11608 context: 'context', 11609 childContext: 'child context' 11610 }; 11611 } 11612 11613 module.exports = ReactPropTypeLocationNames; 11614 11615 },{}],63:[function(_dereq_,module,exports){ 11616 /** 11617 * Copyright 2013-2014 Facebook, Inc. 11618 * 11619 * Licensed under the Apache License, Version 2.0 (the "License"); 11620 * you may not use this file except in compliance with the License. 11621 * You may obtain a copy of the License at 11622 * 11623 * http://www.apache.org/licenses/LICENSE-2.0 11624 * 11625 * Unless required by applicable law or agreed to in writing, software 11626 * distributed under the License is distributed on an "AS IS" BASIS, 11627 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11628 * See the License for the specific language governing permissions and 11629 * limitations under the License. 11630 * 11631 * @providesModule ReactPropTypeLocations 11632 */ 11633 11634 "use strict"; 11635 11636 var keyMirror = _dereq_("./keyMirror"); 11637 11638 var ReactPropTypeLocations = keyMirror({ 11639 prop: null, 11640 context: null, 11641 childContext: null 11642 }); 11643 11644 module.exports = ReactPropTypeLocations; 11645 11646 },{"./keyMirror":118}],64:[function(_dereq_,module,exports){ 11647 /** 11648 * Copyright 2013-2014 Facebook, Inc. 11649 * 11650 * Licensed under the Apache License, Version 2.0 (the "License"); 11651 * you may not use this file except in compliance with the License. 11652 * You may obtain a copy of the License at 11653 * 11654 * http://www.apache.org/licenses/LICENSE-2.0 11655 * 11656 * Unless required by applicable law or agreed to in writing, software 11657 * distributed under the License is distributed on an "AS IS" BASIS, 11658 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11659 * See the License for the specific language governing permissions and 11660 * limitations under the License. 11661 * 11662 * @providesModule ReactPropTypes 11663 */ 11664 11665 "use strict"; 11666 11667 var ReactComponent = _dereq_("./ReactComponent"); 11668 var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames"); 11669 11670 var warning = _dereq_("./warning"); 11671 var createObjectFrom = _dereq_("./createObjectFrom"); 11672 11673 /** 11674 * Collection of methods that allow declaration and validation of props that are 11675 * supplied to React components. Example usage: 11676 * 11677 * var Props = require('ReactPropTypes'); 11678 * var MyArticle = React.createClass({ 11679 * propTypes: { 11680 * // An optional string prop named "description". 11681 * description: Props.string, 11682 * 11683 * // A required enum prop named "category". 11684 * category: Props.oneOf(['News','Photos']).isRequired, 11685 * 11686 * // A prop named "dialog" that requires an instance of Dialog. 11687 * dialog: Props.instanceOf(Dialog).isRequired 11688 * }, 11689 * render: function() { ... } 11690 * }); 11691 * 11692 * A more formal specification of how these methods are used: 11693 * 11694 * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 11695 * decl := ReactPropTypes.{type}(.isRequired)? 11696 * 11697 * Each and every declaration produces a function with the same signature. This 11698 * allows the creation of custom validation functions. For example: 11699 * 11700 * var Props = require('ReactPropTypes'); 11701 * var MyLink = React.createClass({ 11702 * propTypes: { 11703 * // An optional string or URI prop named "href". 11704 * href: function(props, propName, componentName) { 11705 * var propValue = props[propName]; 11706 * warning( 11707 * propValue == null || 11708 * typeof propValue === 'string' || 11709 * propValue instanceof URI, 11710 * 'Invalid `%s` supplied to `%s`, expected string or URI.', 11711 * propName, 11712 * componentName 11713 * ); 11714 * } 11715 * }, 11716 * render: function() { ... } 11717 * }); 11718 * 11719 * @internal 11720 */ 11721 var Props = { 11722 11723 array: createPrimitiveTypeChecker('array'), 11724 bool: createPrimitiveTypeChecker('boolean'), 11725 func: createPrimitiveTypeChecker('function'), 11726 number: createPrimitiveTypeChecker('number'), 11727 object: createPrimitiveTypeChecker('object'), 11728 string: createPrimitiveTypeChecker('string'), 11729 11730 shape: createShapeTypeChecker, 11731 oneOf: createEnumTypeChecker, 11732 oneOfType: createUnionTypeChecker, 11733 arrayOf: createArrayOfTypeChecker, 11734 11735 instanceOf: createInstanceTypeChecker, 11736 11737 renderable: createRenderableTypeChecker(), 11738 11739 component: createComponentTypeChecker(), 11740 11741 any: createAnyTypeChecker() 11742 }; 11743 11744 var ANONYMOUS = '<<anonymous>>'; 11745 11746 function isRenderable(propValue) { 11747 switch(typeof propValue) { 11748 case 'number': 11749 case 'string': 11750 return true; 11751 case 'object': 11752 if (Array.isArray(propValue)) { 11753 return propValue.every(isRenderable); 11754 } 11755 if (ReactComponent.isValidComponent(propValue)) { 11756 return true; 11757 } 11758 for (var k in propValue) { 11759 if (!isRenderable(propValue[k])) { 11760 return false; 11761 } 11762 } 11763 return true; 11764 default: 11765 return false; 11766 } 11767 } 11768 11769 // Equivalent of typeof but with special handling for arrays 11770 function getPropType(propValue) { 11771 var propType = typeof propValue; 11772 if (propType === 'object' && Array.isArray(propValue)) { 11773 return 'array'; 11774 } 11775 return propType; 11776 } 11777 11778 function createAnyTypeChecker() { 11779 function validateAnyType( 11780 shouldWarn, propValue, propName, componentName, location 11781 ) { 11782 return true; // is always valid 11783 } 11784 return createChainableTypeChecker(validateAnyType); 11785 } 11786 11787 function createPrimitiveTypeChecker(expectedType) { 11788 function validatePrimitiveType( 11789 shouldWarn, propValue, propName, componentName, location 11790 ) { 11791 var propType = getPropType(propValue); 11792 var isValid = propType === expectedType; 11793 if (shouldWarn) { 11794 ("production" !== "development" ? warning( 11795 isValid, 11796 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `%s`.', 11797 ReactPropTypeLocationNames[location], 11798 propName, 11799 propType, 11800 componentName, 11801 expectedType 11802 ) : null); 11803 } 11804 return isValid; 11805 } 11806 return createChainableTypeChecker(validatePrimitiveType); 11807 } 11808 11809 function createEnumTypeChecker(expectedValues) { 11810 var expectedEnum = createObjectFrom(expectedValues); 11811 function validateEnumType( 11812 shouldWarn, propValue, propName, componentName, location 11813 ) { 11814 var isValid = expectedEnum[propValue]; 11815 if (shouldWarn) { 11816 ("production" !== "development" ? warning( 11817 isValid, 11818 'Invalid %s `%s` supplied to `%s`, expected one of %s.', 11819 ReactPropTypeLocationNames[location], 11820 propName, 11821 componentName, 11822 JSON.stringify(Object.keys(expectedEnum)) 11823 ) : null); 11824 } 11825 return isValid; 11826 } 11827 return createChainableTypeChecker(validateEnumType); 11828 } 11829 11830 function createShapeTypeChecker(shapeTypes) { 11831 function validateShapeType( 11832 shouldWarn, propValue, propName, componentName, location 11833 ) { 11834 var propType = getPropType(propValue); 11835 var isValid = propType === 'object'; 11836 if (isValid) { 11837 for (var key in shapeTypes) { 11838 var checker = shapeTypes[key]; 11839 if (checker && !checker(propValue, key, componentName, location)) { 11840 return false; 11841 } 11842 } 11843 } 11844 if (shouldWarn) { 11845 ("production" !== "development" ? warning( 11846 isValid, 11847 'Invalid %s `%s` of type `%s` supplied to `%s`, expected `object`.', 11848 ReactPropTypeLocationNames[location], 11849 propName, 11850 propType, 11851 componentName 11852 ) : null); 11853 } 11854 return isValid; 11855 } 11856 return createChainableTypeChecker(validateShapeType); 11857 } 11858 11859 function createInstanceTypeChecker(expectedClass) { 11860 function validateInstanceType( 11861 shouldWarn, propValue, propName, componentName, location 11862 ) { 11863 var isValid = propValue instanceof expectedClass; 11864 if (shouldWarn) { 11865 ("production" !== "development" ? warning( 11866 isValid, 11867 'Invalid %s `%s` supplied to `%s`, expected instance of `%s`.', 11868 ReactPropTypeLocationNames[location], 11869 propName, 11870 componentName, 11871 expectedClass.name || ANONYMOUS 11872 ) : null); 11873 } 11874 return isValid; 11875 } 11876 return createChainableTypeChecker(validateInstanceType); 11877 } 11878 11879 function createArrayOfTypeChecker(propTypeChecker) { 11880 function validateArrayType( 11881 shouldWarn, propValue, propName, componentName, location 11882 ) { 11883 var isValid = Array.isArray(propValue); 11884 if (isValid) { 11885 for (var i = 0; i < propValue.length; i++) { 11886 if (!propTypeChecker(propValue, i, componentName, location)) { 11887 return false; 11888 } 11889 } 11890 } 11891 if (shouldWarn) { 11892 ("production" !== "development" ? warning( 11893 isValid, 11894 'Invalid %s `%s` supplied to `%s`, expected an array.', 11895 ReactPropTypeLocationNames[location], 11896 propName, 11897 componentName 11898 ) : null); 11899 } 11900 return isValid; 11901 } 11902 return createChainableTypeChecker(validateArrayType); 11903 } 11904 11905 function createRenderableTypeChecker() { 11906 function validateRenderableType( 11907 shouldWarn, propValue, propName, componentName, location 11908 ) { 11909 var isValid = isRenderable(propValue); 11910 if (shouldWarn) { 11911 ("production" !== "development" ? warning( 11912 isValid, 11913 'Invalid %s `%s` supplied to `%s`, expected a renderable prop.', 11914 ReactPropTypeLocationNames[location], 11915 propName, 11916 componentName 11917 ) : null); 11918 } 11919 return isValid; 11920 } 11921 return createChainableTypeChecker(validateRenderableType); 11922 } 11923 11924 function createComponentTypeChecker() { 11925 function validateComponentType( 11926 shouldWarn, propValue, propName, componentName, location 11927 ) { 11928 var isValid = ReactComponent.isValidComponent(propValue); 11929 if (shouldWarn) { 11930 ("production" !== "development" ? warning( 11931 isValid, 11932 'Invalid %s `%s` supplied to `%s`, expected a React component.', 11933 ReactPropTypeLocationNames[location], 11934 propName, 11935 componentName 11936 ) : null); 11937 } 11938 return isValid; 11939 } 11940 return createChainableTypeChecker(validateComponentType); 11941 } 11942 11943 function createUnionTypeChecker(arrayOfValidators) { 11944 return function(props, propName, componentName, location) { 11945 var isValid = false; 11946 for (var ii = 0; ii < arrayOfValidators.length; ii++) { 11947 var validate = arrayOfValidators[ii]; 11948 if (typeof validate.weak === 'function') { 11949 validate = validate.weak; 11950 } 11951 if (validate(props, propName, componentName, location)) { 11952 isValid = true; 11953 break; 11954 } 11955 } 11956 ("production" !== "development" ? warning( 11957 isValid, 11958 'Invalid %s `%s` supplied to `%s`.', 11959 ReactPropTypeLocationNames[location], 11960 propName, 11961 componentName || ANONYMOUS 11962 ) : null); 11963 return isValid; 11964 }; 11965 } 11966 11967 function createChainableTypeChecker(validate) { 11968 function checkType( 11969 isRequired, shouldWarn, props, propName, componentName, location 11970 ) { 11971 var propValue = props[propName]; 11972 if (propValue != null) { 11973 // Only validate if there is a value to check. 11974 return validate( 11975 shouldWarn, 11976 propValue, 11977 propName, 11978 componentName || ANONYMOUS, 11979 location 11980 ); 11981 } else { 11982 var isValid = !isRequired; 11983 if (shouldWarn) { 11984 ("production" !== "development" ? warning( 11985 isValid, 11986 'Required %s `%s` was not specified in `%s`.', 11987 ReactPropTypeLocationNames[location], 11988 propName, 11989 componentName || ANONYMOUS 11990 ) : null); 11991 } 11992 return isValid; 11993 } 11994 } 11995 11996 var checker = checkType.bind(null, false, true); 11997 checker.weak = checkType.bind(null, false, false); 11998 checker.isRequired = checkType.bind(null, true, true); 11999 checker.weak.isRequired = checkType.bind(null, true, false); 12000 checker.isRequired.weak = checker.weak.isRequired; 12001 12002 return checker; 12003 } 12004 12005 module.exports = Props; 12006 12007 },{"./ReactComponent":27,"./ReactPropTypeLocationNames":62,"./createObjectFrom":94,"./warning":134}],65:[function(_dereq_,module,exports){ 12008 /** 12009 * Copyright 2013-2014 Facebook, Inc. 12010 * 12011 * Licensed under the Apache License, Version 2.0 (the "License"); 12012 * you may not use this file except in compliance with the License. 12013 * You may obtain a copy of the License at 12014 * 12015 * http://www.apache.org/licenses/LICENSE-2.0 12016 * 12017 * Unless required by applicable law or agreed to in writing, software 12018 * distributed under the License is distributed on an "AS IS" BASIS, 12019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020 * See the License for the specific language governing permissions and 12021 * limitations under the License. 12022 * 12023 * @providesModule ReactPutListenerQueue 12024 */ 12025 12026 "use strict"; 12027 12028 var PooledClass = _dereq_("./PooledClass"); 12029 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 12030 12031 var mixInto = _dereq_("./mixInto"); 12032 12033 function ReactPutListenerQueue() { 12034 this.listenersToPut = []; 12035 } 12036 12037 mixInto(ReactPutListenerQueue, { 12038 enqueuePutListener: function(rootNodeID, propKey, propValue) { 12039 this.listenersToPut.push({ 12040 rootNodeID: rootNodeID, 12041 propKey: propKey, 12042 propValue: propValue 12043 }); 12044 }, 12045 12046 putListeners: function() { 12047 for (var i = 0; i < this.listenersToPut.length; i++) { 12048 var listenerToPut = this.listenersToPut[i]; 12049 ReactEventEmitter.putListener( 12050 listenerToPut.rootNodeID, 12051 listenerToPut.propKey, 12052 listenerToPut.propValue 12053 ); 12054 } 12055 }, 12056 12057 reset: function() { 12058 this.listenersToPut.length = 0; 12059 }, 12060 12061 destructor: function() { 12062 this.reset(); 12063 } 12064 }); 12065 12066 PooledClass.addPoolingTo(ReactPutListenerQueue); 12067 12068 module.exports = ReactPutListenerQueue; 12069 12070 },{"./PooledClass":23,"./ReactEventEmitter":48,"./mixInto":124}],66:[function(_dereq_,module,exports){ 12071 /** 12072 * Copyright 2013-2014 Facebook, Inc. 12073 * 12074 * Licensed under the Apache License, Version 2.0 (the "License"); 12075 * you may not use this file except in compliance with the License. 12076 * You may obtain a copy of the License at 12077 * 12078 * http://www.apache.org/licenses/LICENSE-2.0 12079 * 12080 * Unless required by applicable law or agreed to in writing, software 12081 * distributed under the License is distributed on an "AS IS" BASIS, 12082 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12083 * See the License for the specific language governing permissions and 12084 * limitations under the License. 12085 * 12086 * @providesModule ReactReconcileTransaction 12087 * @typechecks static-only 12088 */ 12089 12090 "use strict"; 12091 12092 var PooledClass = _dereq_("./PooledClass"); 12093 var ReactEventEmitter = _dereq_("./ReactEventEmitter"); 12094 var ReactInputSelection = _dereq_("./ReactInputSelection"); 12095 var ReactMountReady = _dereq_("./ReactMountReady"); 12096 var ReactPutListenerQueue = _dereq_("./ReactPutListenerQueue"); 12097 var Transaction = _dereq_("./Transaction"); 12098 12099 var mixInto = _dereq_("./mixInto"); 12100 12101 /** 12102 * Ensures that, when possible, the selection range (currently selected text 12103 * input) is not disturbed by performing the transaction. 12104 */ 12105 var SELECTION_RESTORATION = { 12106 /** 12107 * @return {Selection} Selection information. 12108 */ 12109 initialize: ReactInputSelection.getSelectionInformation, 12110 /** 12111 * @param {Selection} sel Selection information returned from `initialize`. 12112 */ 12113 close: ReactInputSelection.restoreSelection 12114 }; 12115 12116 /** 12117 * Suppresses events (blur/focus) that could be inadvertently dispatched due to 12118 * high level DOM manipulations (like temporarily removing a text input from the 12119 * DOM). 12120 */ 12121 var EVENT_SUPPRESSION = { 12122 /** 12123 * @return {boolean} The enabled status of `ReactEventEmitter` before the 12124 * reconciliation. 12125 */ 12126 initialize: function() { 12127 var currentlyEnabled = ReactEventEmitter.isEnabled(); 12128 ReactEventEmitter.setEnabled(false); 12129 return currentlyEnabled; 12130 }, 12131 12132 /** 12133 * @param {boolean} previouslyEnabled Enabled status of `ReactEventEmitter` 12134 * before the reconciliation occured. `close` restores the previous value. 12135 */ 12136 close: function(previouslyEnabled) { 12137 ReactEventEmitter.setEnabled(previouslyEnabled); 12138 } 12139 }; 12140 12141 /** 12142 * Provides a `ReactMountReady` queue for collecting `onDOMReady` callbacks 12143 * during the performing of the transaction. 12144 */ 12145 var ON_DOM_READY_QUEUEING = { 12146 /** 12147 * Initializes the internal `onDOMReady` queue. 12148 */ 12149 initialize: function() { 12150 this.reactMountReady.reset(); 12151 }, 12152 12153 /** 12154 * After DOM is flushed, invoke all registered `onDOMReady` callbacks. 12155 */ 12156 close: function() { 12157 this.reactMountReady.notifyAll(); 12158 } 12159 }; 12160 12161 var PUT_LISTENER_QUEUEING = { 12162 initialize: function() { 12163 this.putListenerQueue.reset(); 12164 }, 12165 12166 close: function() { 12167 this.putListenerQueue.putListeners(); 12168 } 12169 }; 12170 12171 /** 12172 * Executed within the scope of the `Transaction` instance. Consider these as 12173 * being member methods, but with an implied ordering while being isolated from 12174 * each other. 12175 */ 12176 var TRANSACTION_WRAPPERS = [ 12177 PUT_LISTENER_QUEUEING, 12178 SELECTION_RESTORATION, 12179 EVENT_SUPPRESSION, 12180 ON_DOM_READY_QUEUEING 12181 ]; 12182 12183 /** 12184 * Currently: 12185 * - The order that these are listed in the transaction is critical: 12186 * - Suppresses events. 12187 * - Restores selection range. 12188 * 12189 * Future: 12190 * - Restore document/overflow scroll positions that were unintentionally 12191 * modified via DOM insertions above the top viewport boundary. 12192 * - Implement/integrate with customized constraint based layout system and keep 12193 * track of which dimensions must be remeasured. 12194 * 12195 * @class ReactReconcileTransaction 12196 */ 12197 function ReactReconcileTransaction() { 12198 this.reinitializeTransaction(); 12199 // Only server-side rendering really needs this option (see 12200 // `ReactServerRendering`), but server-side uses 12201 // `ReactServerRenderingTransaction` instead. This option is here so that it's 12202 // accessible and defaults to false when `ReactDOMComponent` and 12203 // `ReactTextComponent` checks it in `mountComponent`.` 12204 this.renderToStaticMarkup = false; 12205 this.reactMountReady = ReactMountReady.getPooled(null); 12206 this.putListenerQueue = ReactPutListenerQueue.getPooled(); 12207 } 12208 12209 var Mixin = { 12210 /** 12211 * @see Transaction 12212 * @abstract 12213 * @final 12214 * @return {array<object>} List of operation wrap proceedures. 12215 * TODO: convert to array<TransactionWrapper> 12216 */ 12217 getTransactionWrappers: function() { 12218 return TRANSACTION_WRAPPERS; 12219 }, 12220 12221 /** 12222 * @return {object} The queue to collect `onDOMReady` callbacks with. 12223 * TODO: convert to ReactMountReady 12224 */ 12225 getReactMountReady: function() { 12226 return this.reactMountReady; 12227 }, 12228 12229 getPutListenerQueue: function() { 12230 return this.putListenerQueue; 12231 }, 12232 12233 /** 12234 * `PooledClass` looks for this, and will invoke this before allowing this 12235 * instance to be resused. 12236 */ 12237 destructor: function() { 12238 ReactMountReady.release(this.reactMountReady); 12239 this.reactMountReady = null; 12240 12241 ReactPutListenerQueue.release(this.putListenerQueue); 12242 this.putListenerQueue = null; 12243 } 12244 }; 12245 12246 12247 mixInto(ReactReconcileTransaction, Transaction.Mixin); 12248 mixInto(ReactReconcileTransaction, Mixin); 12249 12250 PooledClass.addPoolingTo(ReactReconcileTransaction); 12251 12252 module.exports = ReactReconcileTransaction; 12253 12254 },{"./PooledClass":23,"./ReactEventEmitter":48,"./ReactInputSelection":52,"./ReactMountReady":56,"./ReactPutListenerQueue":65,"./Transaction":85,"./mixInto":124}],67:[function(_dereq_,module,exports){ 12255 /** 12256 * Copyright 2013-2014 Facebook, Inc. 12257 * 12258 * Licensed under the Apache License, Version 2.0 (the "License"); 12259 * you may not use this file except in compliance with the License. 12260 * You may obtain a copy of the License at 12261 * 12262 * http://www.apache.org/licenses/LICENSE-2.0 12263 * 12264 * Unless required by applicable law or agreed to in writing, software 12265 * distributed under the License is distributed on an "AS IS" BASIS, 12266 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12267 * See the License for the specific language governing permissions and 12268 * limitations under the License. 12269 * 12270 * @providesModule ReactRootIndex 12271 * @typechecks 12272 */ 12273 12274 "use strict"; 12275 12276 var ReactRootIndexInjection = { 12277 /** 12278 * @param {function} _createReactRootIndex 12279 */ 12280 injectCreateReactRootIndex: function(_createReactRootIndex) { 12281 ReactRootIndex.createReactRootIndex = _createReactRootIndex; 12282 } 12283 }; 12284 12285 var ReactRootIndex = { 12286 createReactRootIndex: null, 12287 injection: ReactRootIndexInjection 12288 }; 12289 12290 module.exports = ReactRootIndex; 12291 12292 },{}],68:[function(_dereq_,module,exports){ 12293 /** 12294 * Copyright 2013-2014 Facebook, Inc. 12295 * 12296 * Licensed under the Apache License, Version 2.0 (the "License"); 12297 * you may not use this file except in compliance with the License. 12298 * You may obtain a copy of the License at 12299 * 12300 * http://www.apache.org/licenses/LICENSE-2.0 12301 * 12302 * Unless required by applicable law or agreed to in writing, software 12303 * distributed under the License is distributed on an "AS IS" BASIS, 12304 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12305 * See the License for the specific language governing permissions and 12306 * limitations under the License. 12307 * 12308 * @typechecks static-only 12309 * @providesModule ReactServerRendering 12310 */ 12311 "use strict"; 12312 12313 var ReactComponent = _dereq_("./ReactComponent"); 12314 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 12315 var ReactMarkupChecksum = _dereq_("./ReactMarkupChecksum"); 12316 var ReactServerRenderingTransaction = 12317 _dereq_("./ReactServerRenderingTransaction"); 12318 12319 var instantiateReactComponent = _dereq_("./instantiateReactComponent"); 12320 var invariant = _dereq_("./invariant"); 12321 12322 /** 12323 * @param {ReactComponent} component 12324 * @return {string} the HTML markup 12325 */ 12326 function renderComponentToString(component) { 12327 ("production" !== "development" ? invariant( 12328 ReactComponent.isValidComponent(component), 12329 'renderComponentToString(): You must pass a valid ReactComponent.' 12330 ) : invariant(ReactComponent.isValidComponent(component))); 12331 12332 ("production" !== "development" ? invariant( 12333 !(arguments.length === 2 && typeof arguments[1] === 'function'), 12334 'renderComponentToString(): This function became synchronous and now ' + 12335 'returns the generated markup. Please remove the second parameter.' 12336 ) : invariant(!(arguments.length === 2 && typeof arguments[1] === 'function'))); 12337 12338 var transaction; 12339 try { 12340 var id = ReactInstanceHandles.createReactRootID(); 12341 transaction = ReactServerRenderingTransaction.getPooled(false); 12342 12343 return transaction.perform(function() { 12344 var componentInstance = instantiateReactComponent(component); 12345 var markup = componentInstance.mountComponent(id, transaction, 0); 12346 return ReactMarkupChecksum.addChecksumToMarkup(markup); 12347 }, null); 12348 } finally { 12349 ReactServerRenderingTransaction.release(transaction); 12350 } 12351 } 12352 12353 /** 12354 * @param {ReactComponent} component 12355 * @return {string} the HTML markup, without the extra React ID and checksum 12356 * (for generating static pages) 12357 */ 12358 function renderComponentToStaticMarkup(component) { 12359 ("production" !== "development" ? invariant( 12360 ReactComponent.isValidComponent(component), 12361 'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.' 12362 ) : invariant(ReactComponent.isValidComponent(component))); 12363 12364 var transaction; 12365 try { 12366 var id = ReactInstanceHandles.createReactRootID(); 12367 transaction = ReactServerRenderingTransaction.getPooled(true); 12368 12369 return transaction.perform(function() { 12370 var componentInstance = instantiateReactComponent(component); 12371 return componentInstance.mountComponent(id, transaction, 0); 12372 }, null); 12373 } finally { 12374 ReactServerRenderingTransaction.release(transaction); 12375 } 12376 } 12377 12378 module.exports = { 12379 renderComponentToString: renderComponentToString, 12380 renderComponentToStaticMarkup: renderComponentToStaticMarkup 12381 }; 12382 12383 },{"./ReactComponent":27,"./ReactInstanceHandles":53,"./ReactMarkupChecksum":54,"./ReactServerRenderingTransaction":69,"./instantiateReactComponent":111,"./invariant":112}],69:[function(_dereq_,module,exports){ 12384 /** 12385 * Copyright 2014 Facebook, Inc. 12386 * 12387 * Licensed under the Apache License, Version 2.0 (the "License"); 12388 * you may not use this file except in compliance with the License. 12389 * You may obtain a copy of the License at 12390 * 12391 * http://www.apache.org/licenses/LICENSE-2.0 12392 * 12393 * Unless required by applicable law or agreed to in writing, software 12394 * distributed under the License is distributed on an "AS IS" BASIS, 12395 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12396 * See the License for the specific language governing permissions and 12397 * limitations under the License. 12398 * 12399 * @providesModule ReactServerRenderingTransaction 12400 * @typechecks 12401 */ 12402 12403 "use strict"; 12404 12405 var PooledClass = _dereq_("./PooledClass"); 12406 var ReactMountReady = _dereq_("./ReactMountReady"); 12407 var ReactPutListenerQueue = _dereq_("./ReactPutListenerQueue"); 12408 var Transaction = _dereq_("./Transaction"); 12409 12410 var emptyFunction = _dereq_("./emptyFunction"); 12411 var mixInto = _dereq_("./mixInto"); 12412 12413 /** 12414 * Provides a `ReactMountReady` queue for collecting `onDOMReady` callbacks 12415 * during the performing of the transaction. 12416 */ 12417 var ON_DOM_READY_QUEUEING = { 12418 /** 12419 * Initializes the internal `onDOMReady` queue. 12420 */ 12421 initialize: function() { 12422 this.reactMountReady.reset(); 12423 }, 12424 12425 close: emptyFunction 12426 }; 12427 12428 var PUT_LISTENER_QUEUEING = { 12429 initialize: function() { 12430 this.putListenerQueue.reset(); 12431 }, 12432 12433 close: emptyFunction 12434 }; 12435 12436 /** 12437 * Executed within the scope of the `Transaction` instance. Consider these as 12438 * being member methods, but with an implied ordering while being isolated from 12439 * each other. 12440 */ 12441 var TRANSACTION_WRAPPERS = [ 12442 PUT_LISTENER_QUEUEING, 12443 ON_DOM_READY_QUEUEING 12444 ]; 12445 12446 /** 12447 * @class ReactServerRenderingTransaction 12448 * @param {boolean} renderToStaticMarkup 12449 */ 12450 function ReactServerRenderingTransaction(renderToStaticMarkup) { 12451 this.reinitializeTransaction(); 12452 this.renderToStaticMarkup = renderToStaticMarkup; 12453 this.reactMountReady = ReactMountReady.getPooled(null); 12454 this.putListenerQueue = ReactPutListenerQueue.getPooled(); 12455 } 12456 12457 var Mixin = { 12458 /** 12459 * @see Transaction 12460 * @abstract 12461 * @final 12462 * @return {array} Empty list of operation wrap proceedures. 12463 */ 12464 getTransactionWrappers: function() { 12465 return TRANSACTION_WRAPPERS; 12466 }, 12467 12468 /** 12469 * @return {object} The queue to collect `onDOMReady` callbacks with. 12470 * TODO: convert to ReactMountReady 12471 */ 12472 getReactMountReady: function() { 12473 return this.reactMountReady; 12474 }, 12475 12476 getPutListenerQueue: function() { 12477 return this.putListenerQueue; 12478 }, 12479 12480 /** 12481 * `PooledClass` looks for this, and will invoke this before allowing this 12482 * instance to be resused. 12483 */ 12484 destructor: function() { 12485 ReactMountReady.release(this.reactMountReady); 12486 this.reactMountReady = null; 12487 12488 ReactPutListenerQueue.release(this.putListenerQueue); 12489 this.putListenerQueue = null; 12490 } 12491 }; 12492 12493 12494 mixInto(ReactServerRenderingTransaction, Transaction.Mixin); 12495 mixInto(ReactServerRenderingTransaction, Mixin); 12496 12497 PooledClass.addPoolingTo(ReactServerRenderingTransaction); 12498 12499 module.exports = ReactServerRenderingTransaction; 12500 12501 },{"./PooledClass":23,"./ReactMountReady":56,"./ReactPutListenerQueue":65,"./Transaction":85,"./emptyFunction":96,"./mixInto":124}],70:[function(_dereq_,module,exports){ 12502 /** 12503 * Copyright 2013-2014 Facebook, Inc. 12504 * 12505 * Licensed under the Apache License, Version 2.0 (the "License"); 12506 * you may not use this file except in compliance with the License. 12507 * You may obtain a copy of the License at 12508 * 12509 * http://www.apache.org/licenses/LICENSE-2.0 12510 * 12511 * Unless required by applicable law or agreed to in writing, software 12512 * distributed under the License is distributed on an "AS IS" BASIS, 12513 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12514 * See the License for the specific language governing permissions and 12515 * limitations under the License. 12516 * 12517 * @providesModule ReactTextComponent 12518 * @typechecks static-only 12519 */ 12520 12521 "use strict"; 12522 12523 var DOMPropertyOperations = _dereq_("./DOMPropertyOperations"); 12524 var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin"); 12525 var ReactComponent = _dereq_("./ReactComponent"); 12526 12527 var escapeTextForBrowser = _dereq_("./escapeTextForBrowser"); 12528 var mixInto = _dereq_("./mixInto"); 12529 12530 /** 12531 * Text nodes violate a couple assumptions that React makes about components: 12532 * 12533 * - When mounting text into the DOM, adjacent text nodes are merged. 12534 * - Text nodes cannot be assigned a React root ID. 12535 * 12536 * This component is used to wrap strings in elements so that they can undergo 12537 * the same reconciliation that is applied to elements. 12538 * 12539 * TODO: Investigate representing React components in the DOM with text nodes. 12540 * 12541 * @class ReactTextComponent 12542 * @extends ReactComponent 12543 * @internal 12544 */ 12545 var ReactTextComponent = function(initialText) { 12546 this.construct({text: initialText}); 12547 }; 12548 12549 /** 12550 * Used to clone the text descriptor object before it's mounted. 12551 * 12552 * @param {object} props 12553 * @return {object} A new ReactTextComponent instance 12554 */ 12555 ReactTextComponent.ConvenienceConstructor = function(props) { 12556 return new ReactTextComponent(props.text); 12557 }; 12558 12559 mixInto(ReactTextComponent, ReactComponent.Mixin); 12560 mixInto(ReactTextComponent, ReactBrowserComponentMixin); 12561 mixInto(ReactTextComponent, { 12562 12563 /** 12564 * Creates the markup for this text node. This node is not intended to have 12565 * any features besides containing text content. 12566 * 12567 * @param {string} rootID DOM ID of the root node. 12568 * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction 12569 * @param {number} mountDepth number of components in the owner hierarchy 12570 * @return {string} Markup for this text node. 12571 * @internal 12572 */ 12573 mountComponent: function(rootID, transaction, mountDepth) { 12574 ReactComponent.Mixin.mountComponent.call( 12575 this, 12576 rootID, 12577 transaction, 12578 mountDepth 12579 ); 12580 12581 var escapedText = escapeTextForBrowser(this.props.text); 12582 12583 if (transaction.renderToStaticMarkup) { 12584 // Normally we'd wrap this in a `span` for the reasons stated above, but 12585 // since this is a situation where React won't take over (static pages), 12586 // we can simply return the text as it is. 12587 return escapedText; 12588 } 12589 12590 return ( 12591 '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' + 12592 escapedText + 12593 '</span>' 12594 ); 12595 }, 12596 12597 /** 12598 * Updates this component by updating the text content. 12599 * 12600 * @param {object} nextComponent Contains the next text content. 12601 * @param {ReactReconcileTransaction} transaction 12602 * @internal 12603 */ 12604 receiveComponent: function(nextComponent, transaction) { 12605 var nextProps = nextComponent.props; 12606 if (nextProps.text !== this.props.text) { 12607 this.props.text = nextProps.text; 12608 ReactComponent.BackendIDOperations.updateTextContentByID( 12609 this._rootNodeID, 12610 nextProps.text 12611 ); 12612 } 12613 } 12614 12615 }); 12616 12617 // Expose the constructor on itself and the prototype for consistency with other 12618 // descriptors. 12619 ReactTextComponent.type = ReactTextComponent; 12620 ReactTextComponent.prototype.type = ReactTextComponent; 12621 12622 module.exports = ReactTextComponent; 12623 12624 },{"./DOMPropertyOperations":9,"./ReactBrowserComponentMixin":25,"./ReactComponent":27,"./escapeTextForBrowser":98,"./mixInto":124}],71:[function(_dereq_,module,exports){ 12625 /** 12626 * Copyright 2013-2014 Facebook, Inc. 12627 * 12628 * Licensed under the Apache License, Version 2.0 (the "License"); 12629 * you may not use this file except in compliance with the License. 12630 * You may obtain a copy of the License at 12631 * 12632 * http://www.apache.org/licenses/LICENSE-2.0 12633 * 12634 * Unless required by applicable law or agreed to in writing, software 12635 * distributed under the License is distributed on an "AS IS" BASIS, 12636 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12637 * See the License for the specific language governing permissions and 12638 * limitations under the License. 12639 * 12640 * @providesModule ReactUpdates 12641 */ 12642 12643 "use strict"; 12644 12645 var ReactPerf = _dereq_("./ReactPerf"); 12646 12647 var invariant = _dereq_("./invariant"); 12648 12649 var dirtyComponents = []; 12650 12651 var batchingStrategy = null; 12652 12653 function ensureBatchingStrategy() { 12654 ("production" !== "development" ? invariant(batchingStrategy, 'ReactUpdates: must inject a batching strategy') : invariant(batchingStrategy)); 12655 } 12656 12657 function batchedUpdates(callback, param) { 12658 ensureBatchingStrategy(); 12659 batchingStrategy.batchedUpdates(callback, param); 12660 } 12661 12662 /** 12663 * Array comparator for ReactComponents by owner depth 12664 * 12665 * @param {ReactComponent} c1 first component you're comparing 12666 * @param {ReactComponent} c2 second component you're comparing 12667 * @return {number} Return value usable by Array.prototype.sort(). 12668 */ 12669 function mountDepthComparator(c1, c2) { 12670 return c1._mountDepth - c2._mountDepth; 12671 } 12672 12673 function runBatchedUpdates() { 12674 // Since reconciling a component higher in the owner hierarchy usually (not 12675 // always -- see shouldComponentUpdate()) will reconcile children, reconcile 12676 // them before their children by sorting the array. 12677 12678 dirtyComponents.sort(mountDepthComparator); 12679 12680 for (var i = 0; i < dirtyComponents.length; i++) { 12681 // If a component is unmounted before pending changes apply, ignore them 12682 // TODO: Queue unmounts in the same list to avoid this happening at all 12683 var component = dirtyComponents[i]; 12684 if (component.isMounted()) { 12685 // If performUpdateIfNecessary happens to enqueue any new updates, we 12686 // shouldn't execute the callbacks until the next render happens, so 12687 // stash the callbacks first 12688 var callbacks = component._pendingCallbacks; 12689 component._pendingCallbacks = null; 12690 component.performUpdateIfNecessary(); 12691 if (callbacks) { 12692 for (var j = 0; j < callbacks.length; j++) { 12693 callbacks[j].call(component); 12694 } 12695 } 12696 } 12697 } 12698 } 12699 12700 function clearDirtyComponents() { 12701 dirtyComponents.length = 0; 12702 } 12703 12704 var flushBatchedUpdates = ReactPerf.measure( 12705 'ReactUpdates', 12706 'flushBatchedUpdates', 12707 function() { 12708 // Run these in separate functions so the JIT can optimize 12709 try { 12710 runBatchedUpdates(); 12711 } finally { 12712 clearDirtyComponents(); 12713 } 12714 } 12715 ); 12716 12717 /** 12718 * Mark a component as needing a rerender, adding an optional callback to a 12719 * list of functions which will be executed once the rerender occurs. 12720 */ 12721 function enqueueUpdate(component, callback) { 12722 ("production" !== "development" ? invariant( 12723 !callback || typeof callback === "function", 12724 'enqueueUpdate(...): You called `setProps`, `replaceProps`, ' + 12725 '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + 12726 'isn\'t callable.' 12727 ) : invariant(!callback || typeof callback === "function")); 12728 ensureBatchingStrategy(); 12729 12730 if (!batchingStrategy.isBatchingUpdates) { 12731 component.performUpdateIfNecessary(); 12732 callback && callback.call(component); 12733 return; 12734 } 12735 12736 dirtyComponents.push(component); 12737 12738 if (callback) { 12739 if (component._pendingCallbacks) { 12740 component._pendingCallbacks.push(callback); 12741 } else { 12742 component._pendingCallbacks = [callback]; 12743 } 12744 } 12745 } 12746 12747 var ReactUpdatesInjection = { 12748 injectBatchingStrategy: function(_batchingStrategy) { 12749 ("production" !== "development" ? invariant( 12750 _batchingStrategy, 12751 'ReactUpdates: must provide a batching strategy' 12752 ) : invariant(_batchingStrategy)); 12753 ("production" !== "development" ? invariant( 12754 typeof _batchingStrategy.batchedUpdates === 'function', 12755 'ReactUpdates: must provide a batchedUpdates() function' 12756 ) : invariant(typeof _batchingStrategy.batchedUpdates === 'function')); 12757 ("production" !== "development" ? invariant( 12758 typeof _batchingStrategy.isBatchingUpdates === 'boolean', 12759 'ReactUpdates: must provide an isBatchingUpdates boolean attribute' 12760 ) : invariant(typeof _batchingStrategy.isBatchingUpdates === 'boolean')); 12761 batchingStrategy = _batchingStrategy; 12762 } 12763 }; 12764 12765 var ReactUpdates = { 12766 batchedUpdates: batchedUpdates, 12767 enqueueUpdate: enqueueUpdate, 12768 flushBatchedUpdates: flushBatchedUpdates, 12769 injection: ReactUpdatesInjection 12770 }; 12771 12772 module.exports = ReactUpdates; 12773 12774 },{"./ReactPerf":60,"./invariant":112}],72:[function(_dereq_,module,exports){ 12775 /** 12776 * Copyright 2013-2014 Facebook, Inc. 12777 * 12778 * Licensed under the Apache License, Version 2.0 (the "License"); 12779 * you may not use this file except in compliance with the License. 12780 * You may obtain a copy of the License at 12781 * 12782 * http://www.apache.org/licenses/LICENSE-2.0 12783 * 12784 * Unless required by applicable law or agreed to in writing, software 12785 * distributed under the License is distributed on an "AS IS" BASIS, 12786 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12787 * See the License for the specific language governing permissions and 12788 * limitations under the License. 12789 * 12790 * @providesModule SelectEventPlugin 12791 */ 12792 12793 "use strict"; 12794 12795 var EventConstants = _dereq_("./EventConstants"); 12796 var EventPropagators = _dereq_("./EventPropagators"); 12797 var ReactInputSelection = _dereq_("./ReactInputSelection"); 12798 var SyntheticEvent = _dereq_("./SyntheticEvent"); 12799 12800 var getActiveElement = _dereq_("./getActiveElement"); 12801 var isTextInputElement = _dereq_("./isTextInputElement"); 12802 var keyOf = _dereq_("./keyOf"); 12803 var shallowEqual = _dereq_("./shallowEqual"); 12804 12805 var topLevelTypes = EventConstants.topLevelTypes; 12806 12807 var eventTypes = { 12808 select: { 12809 phasedRegistrationNames: { 12810 bubbled: keyOf({onSelect: null}), 12811 captured: keyOf({onSelectCapture: null}) 12812 }, 12813 dependencies: [ 12814 topLevelTypes.topBlur, 12815 topLevelTypes.topContextMenu, 12816 topLevelTypes.topFocus, 12817 topLevelTypes.topKeyDown, 12818 topLevelTypes.topMouseDown, 12819 topLevelTypes.topMouseUp, 12820 topLevelTypes.topSelectionChange 12821 ] 12822 } 12823 }; 12824 12825 var activeElement = null; 12826 var activeElementID = null; 12827 var lastSelection = null; 12828 var mouseDown = false; 12829 12830 /** 12831 * Get an object which is a unique representation of the current selection. 12832 * 12833 * The return value will not be consistent across nodes or browsers, but 12834 * two identical selections on the same node will return identical objects. 12835 * 12836 * @param {DOMElement} node 12837 * @param {object} 12838 */ 12839 function getSelection(node) { 12840 if ('selectionStart' in node && 12841 ReactInputSelection.hasSelectionCapabilities(node)) { 12842 return { 12843 start: node.selectionStart, 12844 end: node.selectionEnd 12845 }; 12846 } else if (document.selection) { 12847 var range = document.selection.createRange(); 12848 return { 12849 parentElement: range.parentElement(), 12850 text: range.text, 12851 top: range.boundingTop, 12852 left: range.boundingLeft 12853 }; 12854 } else { 12855 var selection = window.getSelection(); 12856 return { 12857 anchorNode: selection.anchorNode, 12858 anchorOffset: selection.anchorOffset, 12859 focusNode: selection.focusNode, 12860 focusOffset: selection.focusOffset 12861 }; 12862 } 12863 } 12864 12865 /** 12866 * Poll selection to see whether it's changed. 12867 * 12868 * @param {object} nativeEvent 12869 * @return {?SyntheticEvent} 12870 */ 12871 function constructSelectEvent(nativeEvent) { 12872 // Ensure we have the right element, and that the user is not dragging a 12873 // selection (this matches native `select` event behavior). In HTML5, select 12874 // fires only on input and textarea thus if there's no focused element we 12875 // won't dispatch. 12876 if (mouseDown || 12877 activeElement == null || 12878 activeElement != getActiveElement()) { 12879 return; 12880 } 12881 12882 // Only fire when selection has actually changed. 12883 var currentSelection = getSelection(activeElement); 12884 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 12885 lastSelection = currentSelection; 12886 12887 var syntheticEvent = SyntheticEvent.getPooled( 12888 eventTypes.select, 12889 activeElementID, 12890 nativeEvent 12891 ); 12892 12893 syntheticEvent.type = 'select'; 12894 syntheticEvent.target = activeElement; 12895 12896 EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent); 12897 12898 return syntheticEvent; 12899 } 12900 } 12901 12902 /** 12903 * This plugin creates an `onSelect` event that normalizes select events 12904 * across form elements. 12905 * 12906 * Supported elements are: 12907 * - input (see `isTextInputElement`) 12908 * - textarea 12909 * - contentEditable 12910 * 12911 * This differs from native browser implementations in the following ways: 12912 * - Fires on contentEditable fields as well as inputs. 12913 * - Fires for collapsed selection. 12914 * - Fires after user input. 12915 */ 12916 var SelectEventPlugin = { 12917 12918 eventTypes: eventTypes, 12919 12920 /** 12921 * @param {string} topLevelType Record from `EventConstants`. 12922 * @param {DOMEventTarget} topLevelTarget The listening component root node. 12923 * @param {string} topLevelTargetID ID of `topLevelTarget`. 12924 * @param {object} nativeEvent Native browser event. 12925 * @return {*} An accumulation of synthetic events. 12926 * @see {EventPluginHub.extractEvents} 12927 */ 12928 extractEvents: function( 12929 topLevelType, 12930 topLevelTarget, 12931 topLevelTargetID, 12932 nativeEvent) { 12933 12934 switch (topLevelType) { 12935 // Track the input node that has focus. 12936 case topLevelTypes.topFocus: 12937 if (isTextInputElement(topLevelTarget) || 12938 topLevelTarget.contentEditable === 'true') { 12939 activeElement = topLevelTarget; 12940 activeElementID = topLevelTargetID; 12941 lastSelection = null; 12942 } 12943 break; 12944 case topLevelTypes.topBlur: 12945 activeElement = null; 12946 activeElementID = null; 12947 lastSelection = null; 12948 break; 12949 12950 // Don't fire the event while the user is dragging. This matches the 12951 // semantics of the native select event. 12952 case topLevelTypes.topMouseDown: 12953 mouseDown = true; 12954 break; 12955 case topLevelTypes.topContextMenu: 12956 case topLevelTypes.topMouseUp: 12957 mouseDown = false; 12958 return constructSelectEvent(nativeEvent); 12959 12960 // Chrome and IE fire non-standard event when selection is changed (and 12961 // sometimes when it hasn't). 12962 // Firefox doesn't support selectionchange, so check selection status 12963 // after each key entry. The selection changes after keydown and before 12964 // keyup, but we check on keydown as well in the case of holding down a 12965 // key, when multiple keydown events are fired but only one keyup is. 12966 case topLevelTypes.topSelectionChange: 12967 case topLevelTypes.topKeyDown: 12968 case topLevelTypes.topKeyUp: 12969 return constructSelectEvent(nativeEvent); 12970 } 12971 } 12972 }; 12973 12974 module.exports = SelectEventPlugin; 12975 12976 },{"./EventConstants":14,"./EventPropagators":19,"./ReactInputSelection":52,"./SyntheticEvent":78,"./getActiveElement":102,"./isTextInputElement":115,"./keyOf":119,"./shallowEqual":130}],73:[function(_dereq_,module,exports){ 12977 /** 12978 * Copyright 2013-2014 Facebook, Inc. 12979 * 12980 * Licensed under the Apache License, Version 2.0 (the "License"); 12981 * you may not use this file except in compliance with the License. 12982 * You may obtain a copy of the License at 12983 * 12984 * http://www.apache.org/licenses/LICENSE-2.0 12985 * 12986 * Unless required by applicable law or agreed to in writing, software 12987 * distributed under the License is distributed on an "AS IS" BASIS, 12988 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12989 * See the License for the specific language governing permissions and 12990 * limitations under the License. 12991 * 12992 * @providesModule ServerReactRootIndex 12993 * @typechecks 12994 */ 12995 12996 "use strict"; 12997 12998 /** 12999 * Size of the reactRoot ID space. We generate random numbers for React root 13000 * IDs and if there's a collision the events and DOM update system will 13001 * get confused. In the future we need a way to generate GUIDs but for 13002 * now this will work on a smaller scale. 13003 */ 13004 var GLOBAL_MOUNT_POINT_MAX = Math.pow(2, 53); 13005 13006 var ServerReactRootIndex = { 13007 createReactRootIndex: function() { 13008 return Math.ceil(Math.random() * GLOBAL_MOUNT_POINT_MAX); 13009 } 13010 }; 13011 13012 module.exports = ServerReactRootIndex; 13013 13014 },{}],74:[function(_dereq_,module,exports){ 13015 /** 13016 * Copyright 2013-2014 Facebook, Inc. 13017 * 13018 * Licensed under the Apache License, Version 2.0 (the "License"); 13019 * you may not use this file except in compliance with the License. 13020 * You may obtain a copy of the License at 13021 * 13022 * http://www.apache.org/licenses/LICENSE-2.0 13023 * 13024 * Unless required by applicable law or agreed to in writing, software 13025 * distributed under the License is distributed on an "AS IS" BASIS, 13026 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13027 * See the License for the specific language governing permissions and 13028 * limitations under the License. 13029 * 13030 * @providesModule SimpleEventPlugin 13031 */ 13032 13033 "use strict"; 13034 13035 var EventConstants = _dereq_("./EventConstants"); 13036 var EventPluginUtils = _dereq_("./EventPluginUtils"); 13037 var EventPropagators = _dereq_("./EventPropagators"); 13038 var SyntheticClipboardEvent = _dereq_("./SyntheticClipboardEvent"); 13039 var SyntheticEvent = _dereq_("./SyntheticEvent"); 13040 var SyntheticFocusEvent = _dereq_("./SyntheticFocusEvent"); 13041 var SyntheticKeyboardEvent = _dereq_("./SyntheticKeyboardEvent"); 13042 var SyntheticMouseEvent = _dereq_("./SyntheticMouseEvent"); 13043 var SyntheticDragEvent = _dereq_("./SyntheticDragEvent"); 13044 var SyntheticTouchEvent = _dereq_("./SyntheticTouchEvent"); 13045 var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); 13046 var SyntheticWheelEvent = _dereq_("./SyntheticWheelEvent"); 13047 13048 var invariant = _dereq_("./invariant"); 13049 var keyOf = _dereq_("./keyOf"); 13050 13051 var topLevelTypes = EventConstants.topLevelTypes; 13052 13053 var eventTypes = { 13054 blur: { 13055 phasedRegistrationNames: { 13056 bubbled: keyOf({onBlur: true}), 13057 captured: keyOf({onBlurCapture: true}) 13058 } 13059 }, 13060 click: { 13061 phasedRegistrationNames: { 13062 bubbled: keyOf({onClick: true}), 13063 captured: keyOf({onClickCapture: true}) 13064 } 13065 }, 13066 contextMenu: { 13067 phasedRegistrationNames: { 13068 bubbled: keyOf({onContextMenu: true}), 13069 captured: keyOf({onContextMenuCapture: true}) 13070 } 13071 }, 13072 copy: { 13073 phasedRegistrationNames: { 13074 bubbled: keyOf({onCopy: true}), 13075 captured: keyOf({onCopyCapture: true}) 13076 } 13077 }, 13078 cut: { 13079 phasedRegistrationNames: { 13080 bubbled: keyOf({onCut: true}), 13081 captured: keyOf({onCutCapture: true}) 13082 } 13083 }, 13084 doubleClick: { 13085 phasedRegistrationNames: { 13086 bubbled: keyOf({onDoubleClick: true}), 13087 captured: keyOf({onDoubleClickCapture: true}) 13088 } 13089 }, 13090 drag: { 13091 phasedRegistrationNames: { 13092 bubbled: keyOf({onDrag: true}), 13093 captured: keyOf({onDragCapture: true}) 13094 } 13095 }, 13096 dragEnd: { 13097 phasedRegistrationNames: { 13098 bubbled: keyOf({onDragEnd: true}), 13099 captured: keyOf({onDragEndCapture: true}) 13100 } 13101 }, 13102 dragEnter: { 13103 phasedRegistrationNames: { 13104 bubbled: keyOf({onDragEnter: true}), 13105 captured: keyOf({onDragEnterCapture: true}) 13106 } 13107 }, 13108 dragExit: { 13109 phasedRegistrationNames: { 13110 bubbled: keyOf({onDragExit: true}), 13111 captured: keyOf({onDragExitCapture: true}) 13112 } 13113 }, 13114 dragLeave: { 13115 phasedRegistrationNames: { 13116 bubbled: keyOf({onDragLeave: true}), 13117 captured: keyOf({onDragLeaveCapture: true}) 13118 } 13119 }, 13120 dragOver: { 13121 phasedRegistrationNames: { 13122 bubbled: keyOf({onDragOver: true}), 13123 captured: keyOf({onDragOverCapture: true}) 13124 } 13125 }, 13126 dragStart: { 13127 phasedRegistrationNames: { 13128 bubbled: keyOf({onDragStart: true}), 13129 captured: keyOf({onDragStartCapture: true}) 13130 } 13131 }, 13132 drop: { 13133 phasedRegistrationNames: { 13134 bubbled: keyOf({onDrop: true}), 13135 captured: keyOf({onDropCapture: true}) 13136 } 13137 }, 13138 focus: { 13139 phasedRegistrationNames: { 13140 bubbled: keyOf({onFocus: true}), 13141 captured: keyOf({onFocusCapture: true}) 13142 } 13143 }, 13144 input: { 13145 phasedRegistrationNames: { 13146 bubbled: keyOf({onInput: true}), 13147 captured: keyOf({onInputCapture: true}) 13148 } 13149 }, 13150 keyDown: { 13151 phasedRegistrationNames: { 13152 bubbled: keyOf({onKeyDown: true}), 13153 captured: keyOf({onKeyDownCapture: true}) 13154 } 13155 }, 13156 keyPress: { 13157 phasedRegistrationNames: { 13158 bubbled: keyOf({onKeyPress: true}), 13159 captured: keyOf({onKeyPressCapture: true}) 13160 } 13161 }, 13162 keyUp: { 13163 phasedRegistrationNames: { 13164 bubbled: keyOf({onKeyUp: true}), 13165 captured: keyOf({onKeyUpCapture: true}) 13166 } 13167 }, 13168 load: { 13169 phasedRegistrationNames: { 13170 bubbled: keyOf({onLoad: true}), 13171 captured: keyOf({onLoadCapture: true}) 13172 } 13173 }, 13174 error: { 13175 phasedRegistrationNames: { 13176 bubbled: keyOf({onError: true}), 13177 captured: keyOf({onErrorCapture: true}) 13178 } 13179 }, 13180 // Note: We do not allow listening to mouseOver events. Instead, use the 13181 // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. 13182 mouseDown: { 13183 phasedRegistrationNames: { 13184 bubbled: keyOf({onMouseDown: true}), 13185 captured: keyOf({onMouseDownCapture: true}) 13186 } 13187 }, 13188 mouseMove: { 13189 phasedRegistrationNames: { 13190 bubbled: keyOf({onMouseMove: true}), 13191 captured: keyOf({onMouseMoveCapture: true}) 13192 } 13193 }, 13194 mouseOut: { 13195 phasedRegistrationNames: { 13196 bubbled: keyOf({onMouseOut: true}), 13197 captured: keyOf({onMouseOutCapture: true}) 13198 } 13199 }, 13200 mouseOver: { 13201 phasedRegistrationNames: { 13202 bubbled: keyOf({onMouseOver: true}), 13203 captured: keyOf({onMouseOverCapture: true}) 13204 } 13205 }, 13206 mouseUp: { 13207 phasedRegistrationNames: { 13208 bubbled: keyOf({onMouseUp: true}), 13209 captured: keyOf({onMouseUpCapture: true}) 13210 } 13211 }, 13212 paste: { 13213 phasedRegistrationNames: { 13214 bubbled: keyOf({onPaste: true}), 13215 captured: keyOf({onPasteCapture: true}) 13216 } 13217 }, 13218 reset: { 13219 phasedRegistrationNames: { 13220 bubbled: keyOf({onReset: true}), 13221 captured: keyOf({onResetCapture: true}) 13222 } 13223 }, 13224 scroll: { 13225 phasedRegistrationNames: { 13226 bubbled: keyOf({onScroll: true}), 13227 captured: keyOf({onScrollCapture: true}) 13228 } 13229 }, 13230 submit: { 13231 phasedRegistrationNames: { 13232 bubbled: keyOf({onSubmit: true}), 13233 captured: keyOf({onSubmitCapture: true}) 13234 } 13235 }, 13236 touchCancel: { 13237 phasedRegistrationNames: { 13238 bubbled: keyOf({onTouchCancel: true}), 13239 captured: keyOf({onTouchCancelCapture: true}) 13240 } 13241 }, 13242 touchEnd: { 13243 phasedRegistrationNames: { 13244 bubbled: keyOf({onTouchEnd: true}), 13245 captured: keyOf({onTouchEndCapture: true}) 13246 } 13247 }, 13248 touchMove: { 13249 phasedRegistrationNames: { 13250 bubbled: keyOf({onTouchMove: true}), 13251 captured: keyOf({onTouchMoveCapture: true}) 13252 } 13253 }, 13254 touchStart: { 13255 phasedRegistrationNames: { 13256 bubbled: keyOf({onTouchStart: true}), 13257 captured: keyOf({onTouchStartCapture: true}) 13258 } 13259 }, 13260 wheel: { 13261 phasedRegistrationNames: { 13262 bubbled: keyOf({onWheel: true}), 13263 captured: keyOf({onWheelCapture: true}) 13264 } 13265 } 13266 }; 13267 13268 var topLevelEventsToDispatchConfig = { 13269 topBlur: eventTypes.blur, 13270 topClick: eventTypes.click, 13271 topContextMenu: eventTypes.contextMenu, 13272 topCopy: eventTypes.copy, 13273 topCut: eventTypes.cut, 13274 topDoubleClick: eventTypes.doubleClick, 13275 topDrag: eventTypes.drag, 13276 topDragEnd: eventTypes.dragEnd, 13277 topDragEnter: eventTypes.dragEnter, 13278 topDragExit: eventTypes.dragExit, 13279 topDragLeave: eventTypes.dragLeave, 13280 topDragOver: eventTypes.dragOver, 13281 topDragStart: eventTypes.dragStart, 13282 topDrop: eventTypes.drop, 13283 topError: eventTypes.error, 13284 topFocus: eventTypes.focus, 13285 topInput: eventTypes.input, 13286 topKeyDown: eventTypes.keyDown, 13287 topKeyPress: eventTypes.keyPress, 13288 topKeyUp: eventTypes.keyUp, 13289 topLoad: eventTypes.load, 13290 topMouseDown: eventTypes.mouseDown, 13291 topMouseMove: eventTypes.mouseMove, 13292 topMouseOut: eventTypes.mouseOut, 13293 topMouseOver: eventTypes.mouseOver, 13294 topMouseUp: eventTypes.mouseUp, 13295 topPaste: eventTypes.paste, 13296 topReset: eventTypes.reset, 13297 topScroll: eventTypes.scroll, 13298 topSubmit: eventTypes.submit, 13299 topTouchCancel: eventTypes.touchCancel, 13300 topTouchEnd: eventTypes.touchEnd, 13301 topTouchMove: eventTypes.touchMove, 13302 topTouchStart: eventTypes.touchStart, 13303 topWheel: eventTypes.wheel 13304 }; 13305 13306 for (var topLevelType in topLevelEventsToDispatchConfig) { 13307 topLevelEventsToDispatchConfig[topLevelType].dependencies = [topLevelType]; 13308 } 13309 13310 var SimpleEventPlugin = { 13311 13312 eventTypes: eventTypes, 13313 13314 /** 13315 * Same as the default implementation, except cancels the event when return 13316 * value is false. 13317 * 13318 * @param {object} Event to be dispatched. 13319 * @param {function} Application-level callback. 13320 * @param {string} domID DOM ID to pass to the callback. 13321 */ 13322 executeDispatch: function(event, listener, domID) { 13323 var returnValue = EventPluginUtils.executeDispatch(event, listener, domID); 13324 if (returnValue === false) { 13325 event.stopPropagation(); 13326 event.preventDefault(); 13327 } 13328 }, 13329 13330 /** 13331 * @param {string} topLevelType Record from `EventConstants`. 13332 * @param {DOMEventTarget} topLevelTarget The listening component root node. 13333 * @param {string} topLevelTargetID ID of `topLevelTarget`. 13334 * @param {object} nativeEvent Native browser event. 13335 * @return {*} An accumulation of synthetic events. 13336 * @see {EventPluginHub.extractEvents} 13337 */ 13338 extractEvents: function( 13339 topLevelType, 13340 topLevelTarget, 13341 topLevelTargetID, 13342 nativeEvent) { 13343 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; 13344 if (!dispatchConfig) { 13345 return null; 13346 } 13347 var EventConstructor; 13348 switch (topLevelType) { 13349 case topLevelTypes.topInput: 13350 case topLevelTypes.topLoad: 13351 case topLevelTypes.topError: 13352 case topLevelTypes.topReset: 13353 case topLevelTypes.topSubmit: 13354 // HTML Events 13355 // @see http://www.w3.org/TR/html5/index.html#events-0 13356 EventConstructor = SyntheticEvent; 13357 break; 13358 case topLevelTypes.topKeyDown: 13359 case topLevelTypes.topKeyPress: 13360 case topLevelTypes.topKeyUp: 13361 EventConstructor = SyntheticKeyboardEvent; 13362 break; 13363 case topLevelTypes.topBlur: 13364 case topLevelTypes.topFocus: 13365 EventConstructor = SyntheticFocusEvent; 13366 break; 13367 case topLevelTypes.topClick: 13368 // Firefox creates a click event on right mouse clicks. This removes the 13369 // unwanted click events. 13370 if (nativeEvent.button === 2) { 13371 return null; 13372 } 13373 /* falls through */ 13374 case topLevelTypes.topContextMenu: 13375 case topLevelTypes.topDoubleClick: 13376 case topLevelTypes.topMouseDown: 13377 case topLevelTypes.topMouseMove: 13378 case topLevelTypes.topMouseOut: 13379 case topLevelTypes.topMouseOver: 13380 case topLevelTypes.topMouseUp: 13381 EventConstructor = SyntheticMouseEvent; 13382 break; 13383 case topLevelTypes.topDrag: 13384 case topLevelTypes.topDragEnd: 13385 case topLevelTypes.topDragEnter: 13386 case topLevelTypes.topDragExit: 13387 case topLevelTypes.topDragLeave: 13388 case topLevelTypes.topDragOver: 13389 case topLevelTypes.topDragStart: 13390 case topLevelTypes.topDrop: 13391 EventConstructor = SyntheticDragEvent; 13392 break; 13393 case topLevelTypes.topTouchCancel: 13394 case topLevelTypes.topTouchEnd: 13395 case topLevelTypes.topTouchMove: 13396 case topLevelTypes.topTouchStart: 13397 EventConstructor = SyntheticTouchEvent; 13398 break; 13399 case topLevelTypes.topScroll: 13400 EventConstructor = SyntheticUIEvent; 13401 break; 13402 case topLevelTypes.topWheel: 13403 EventConstructor = SyntheticWheelEvent; 13404 break; 13405 case topLevelTypes.topCopy: 13406 case topLevelTypes.topCut: 13407 case topLevelTypes.topPaste: 13408 EventConstructor = SyntheticClipboardEvent; 13409 break; 13410 } 13411 ("production" !== "development" ? invariant( 13412 EventConstructor, 13413 'SimpleEventPlugin: Unhandled event type, `%s`.', 13414 topLevelType 13415 ) : invariant(EventConstructor)); 13416 var event = EventConstructor.getPooled( 13417 dispatchConfig, 13418 topLevelTargetID, 13419 nativeEvent 13420 ); 13421 EventPropagators.accumulateTwoPhaseDispatches(event); 13422 return event; 13423 } 13424 13425 }; 13426 13427 module.exports = SimpleEventPlugin; 13428 13429 },{"./EventConstants":14,"./EventPluginUtils":18,"./EventPropagators":19,"./SyntheticClipboardEvent":75,"./SyntheticDragEvent":77,"./SyntheticEvent":78,"./SyntheticFocusEvent":79,"./SyntheticKeyboardEvent":80,"./SyntheticMouseEvent":81,"./SyntheticTouchEvent":82,"./SyntheticUIEvent":83,"./SyntheticWheelEvent":84,"./invariant":112,"./keyOf":119}],75:[function(_dereq_,module,exports){ 13430 /** 13431 * Copyright 2013-2014 Facebook, Inc. 13432 * 13433 * Licensed under the Apache License, Version 2.0 (the "License"); 13434 * you may not use this file except in compliance with the License. 13435 * You may obtain a copy of the License at 13436 * 13437 * http://www.apache.org/licenses/LICENSE-2.0 13438 * 13439 * Unless required by applicable law or agreed to in writing, software 13440 * distributed under the License is distributed on an "AS IS" BASIS, 13441 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13442 * See the License for the specific language governing permissions and 13443 * limitations under the License. 13444 * 13445 * @providesModule SyntheticClipboardEvent 13446 * @typechecks static-only 13447 */ 13448 13449 "use strict"; 13450 13451 var SyntheticEvent = _dereq_("./SyntheticEvent"); 13452 13453 /** 13454 * @interface Event 13455 * @see http://www.w3.org/TR/clipboard-apis/ 13456 */ 13457 var ClipboardEventInterface = { 13458 clipboardData: function(event) { 13459 return ( 13460 'clipboardData' in event ? 13461 event.clipboardData : 13462 window.clipboardData 13463 ); 13464 } 13465 }; 13466 13467 /** 13468 * @param {object} dispatchConfig Configuration used to dispatch this event. 13469 * @param {string} dispatchMarker Marker identifying the event target. 13470 * @param {object} nativeEvent Native browser event. 13471 * @extends {SyntheticUIEvent} 13472 */ 13473 function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13474 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13475 } 13476 13477 SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); 13478 13479 module.exports = SyntheticClipboardEvent; 13480 13481 13482 },{"./SyntheticEvent":78}],76:[function(_dereq_,module,exports){ 13483 /** 13484 * Copyright 2013-2014 Facebook, Inc. 13485 * 13486 * Licensed under the Apache License, Version 2.0 (the "License"); 13487 * you may not use this file except in compliance with the License. 13488 * You may obtain a copy of the License at 13489 * 13490 * http://www.apache.org/licenses/LICENSE-2.0 13491 * 13492 * Unless required by applicable law or agreed to in writing, software 13493 * distributed under the License is distributed on an "AS IS" BASIS, 13494 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13495 * See the License for the specific language governing permissions and 13496 * limitations under the License. 13497 * 13498 * @providesModule SyntheticCompositionEvent 13499 * @typechecks static-only 13500 */ 13501 13502 "use strict"; 13503 13504 var SyntheticEvent = _dereq_("./SyntheticEvent"); 13505 13506 /** 13507 * @interface Event 13508 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 13509 */ 13510 var CompositionEventInterface = { 13511 data: null 13512 }; 13513 13514 /** 13515 * @param {object} dispatchConfig Configuration used to dispatch this event. 13516 * @param {string} dispatchMarker Marker identifying the event target. 13517 * @param {object} nativeEvent Native browser event. 13518 * @extends {SyntheticUIEvent} 13519 */ 13520 function SyntheticCompositionEvent( 13521 dispatchConfig, 13522 dispatchMarker, 13523 nativeEvent) { 13524 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13525 } 13526 13527 SyntheticEvent.augmentClass( 13528 SyntheticCompositionEvent, 13529 CompositionEventInterface 13530 ); 13531 13532 module.exports = SyntheticCompositionEvent; 13533 13534 13535 },{"./SyntheticEvent":78}],77:[function(_dereq_,module,exports){ 13536 /** 13537 * Copyright 2013-2014 Facebook, Inc. 13538 * 13539 * Licensed under the Apache License, Version 2.0 (the "License"); 13540 * you may not use this file except in compliance with the License. 13541 * You may obtain a copy of the License at 13542 * 13543 * http://www.apache.org/licenses/LICENSE-2.0 13544 * 13545 * Unless required by applicable law or agreed to in writing, software 13546 * distributed under the License is distributed on an "AS IS" BASIS, 13547 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13548 * See the License for the specific language governing permissions and 13549 * limitations under the License. 13550 * 13551 * @providesModule SyntheticDragEvent 13552 * @typechecks static-only 13553 */ 13554 13555 "use strict"; 13556 13557 var SyntheticMouseEvent = _dereq_("./SyntheticMouseEvent"); 13558 13559 /** 13560 * @interface DragEvent 13561 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 13562 */ 13563 var DragEventInterface = { 13564 dataTransfer: null 13565 }; 13566 13567 /** 13568 * @param {object} dispatchConfig Configuration used to dispatch this event. 13569 * @param {string} dispatchMarker Marker identifying the event target. 13570 * @param {object} nativeEvent Native browser event. 13571 * @extends {SyntheticUIEvent} 13572 */ 13573 function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13574 SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13575 } 13576 13577 SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface); 13578 13579 module.exports = SyntheticDragEvent; 13580 13581 },{"./SyntheticMouseEvent":81}],78:[function(_dereq_,module,exports){ 13582 /** 13583 * Copyright 2013-2014 Facebook, Inc. 13584 * 13585 * Licensed under the Apache License, Version 2.0 (the "License"); 13586 * you may not use this file except in compliance with the License. 13587 * You may obtain a copy of the License at 13588 * 13589 * http://www.apache.org/licenses/LICENSE-2.0 13590 * 13591 * Unless required by applicable law or agreed to in writing, software 13592 * distributed under the License is distributed on an "AS IS" BASIS, 13593 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13594 * See the License for the specific language governing permissions and 13595 * limitations under the License. 13596 * 13597 * @providesModule SyntheticEvent 13598 * @typechecks static-only 13599 */ 13600 13601 "use strict"; 13602 13603 var PooledClass = _dereq_("./PooledClass"); 13604 13605 var emptyFunction = _dereq_("./emptyFunction"); 13606 var getEventTarget = _dereq_("./getEventTarget"); 13607 var merge = _dereq_("./merge"); 13608 var mergeInto = _dereq_("./mergeInto"); 13609 13610 /** 13611 * @interface Event 13612 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 13613 */ 13614 var EventInterface = { 13615 type: null, 13616 target: getEventTarget, 13617 // currentTarget is set when dispatching; no use in copying it here 13618 currentTarget: emptyFunction.thatReturnsNull, 13619 eventPhase: null, 13620 bubbles: null, 13621 cancelable: null, 13622 timeStamp: function(event) { 13623 return event.timeStamp || Date.now(); 13624 }, 13625 defaultPrevented: null, 13626 isTrusted: null 13627 }; 13628 13629 /** 13630 * Synthetic events are dispatched by event plugins, typically in response to a 13631 * top-level event delegation handler. 13632 * 13633 * These systems should generally use pooling to reduce the frequency of garbage 13634 * collection. The system should check `isPersistent` to determine whether the 13635 * event should be released into the pool after being dispatched. Users that 13636 * need a persisted event should invoke `persist`. 13637 * 13638 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 13639 * normalizing browser quirks. Subclasses do not necessarily have to implement a 13640 * DOM interface; custom application-specific events can also subclass this. 13641 * 13642 * @param {object} dispatchConfig Configuration used to dispatch this event. 13643 * @param {string} dispatchMarker Marker identifying the event target. 13644 * @param {object} nativeEvent Native browser event. 13645 */ 13646 function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13647 this.dispatchConfig = dispatchConfig; 13648 this.dispatchMarker = dispatchMarker; 13649 this.nativeEvent = nativeEvent; 13650 13651 var Interface = this.constructor.Interface; 13652 for (var propName in Interface) { 13653 if (!Interface.hasOwnProperty(propName)) { 13654 continue; 13655 } 13656 var normalize = Interface[propName]; 13657 if (normalize) { 13658 this[propName] = normalize(nativeEvent); 13659 } else { 13660 this[propName] = nativeEvent[propName]; 13661 } 13662 } 13663 13664 var defaultPrevented = nativeEvent.defaultPrevented != null ? 13665 nativeEvent.defaultPrevented : 13666 nativeEvent.returnValue === false; 13667 if (defaultPrevented) { 13668 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 13669 } else { 13670 this.isDefaultPrevented = emptyFunction.thatReturnsFalse; 13671 } 13672 this.isPropagationStopped = emptyFunction.thatReturnsFalse; 13673 } 13674 13675 mergeInto(SyntheticEvent.prototype, { 13676 13677 preventDefault: function() { 13678 this.defaultPrevented = true; 13679 var event = this.nativeEvent; 13680 event.preventDefault ? event.preventDefault() : event.returnValue = false; 13681 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 13682 }, 13683 13684 stopPropagation: function() { 13685 var event = this.nativeEvent; 13686 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; 13687 this.isPropagationStopped = emptyFunction.thatReturnsTrue; 13688 }, 13689 13690 /** 13691 * We release all dispatched `SyntheticEvent`s after each event loop, adding 13692 * them back into the pool. This allows a way to hold onto a reference that 13693 * won't be added back into the pool. 13694 */ 13695 persist: function() { 13696 this.isPersistent = emptyFunction.thatReturnsTrue; 13697 }, 13698 13699 /** 13700 * Checks if this event should be released back into the pool. 13701 * 13702 * @return {boolean} True if this should not be released, false otherwise. 13703 */ 13704 isPersistent: emptyFunction.thatReturnsFalse, 13705 13706 /** 13707 * `PooledClass` looks for `destructor` on each instance it releases. 13708 */ 13709 destructor: function() { 13710 var Interface = this.constructor.Interface; 13711 for (var propName in Interface) { 13712 this[propName] = null; 13713 } 13714 this.dispatchConfig = null; 13715 this.dispatchMarker = null; 13716 this.nativeEvent = null; 13717 } 13718 13719 }); 13720 13721 SyntheticEvent.Interface = EventInterface; 13722 13723 /** 13724 * Helper to reduce boilerplate when creating subclasses. 13725 * 13726 * @param {function} Class 13727 * @param {?object} Interface 13728 */ 13729 SyntheticEvent.augmentClass = function(Class, Interface) { 13730 var Super = this; 13731 13732 var prototype = Object.create(Super.prototype); 13733 mergeInto(prototype, Class.prototype); 13734 Class.prototype = prototype; 13735 Class.prototype.constructor = Class; 13736 13737 Class.Interface = merge(Super.Interface, Interface); 13738 Class.augmentClass = Super.augmentClass; 13739 13740 PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler); 13741 }; 13742 13743 PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler); 13744 13745 module.exports = SyntheticEvent; 13746 13747 },{"./PooledClass":23,"./emptyFunction":96,"./getEventTarget":104,"./merge":121,"./mergeInto":123}],79:[function(_dereq_,module,exports){ 13748 /** 13749 * Copyright 2013-2014 Facebook, Inc. 13750 * 13751 * Licensed under the Apache License, Version 2.0 (the "License"); 13752 * you may not use this file except in compliance with the License. 13753 * You may obtain a copy of the License at 13754 * 13755 * http://www.apache.org/licenses/LICENSE-2.0 13756 * 13757 * Unless required by applicable law or agreed to in writing, software 13758 * distributed under the License is distributed on an "AS IS" BASIS, 13759 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13760 * See the License for the specific language governing permissions and 13761 * limitations under the License. 13762 * 13763 * @providesModule SyntheticFocusEvent 13764 * @typechecks static-only 13765 */ 13766 13767 "use strict"; 13768 13769 var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); 13770 13771 /** 13772 * @interface FocusEvent 13773 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 13774 */ 13775 var FocusEventInterface = { 13776 relatedTarget: null 13777 }; 13778 13779 /** 13780 * @param {object} dispatchConfig Configuration used to dispatch this event. 13781 * @param {string} dispatchMarker Marker identifying the event target. 13782 * @param {object} nativeEvent Native browser event. 13783 * @extends {SyntheticUIEvent} 13784 */ 13785 function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13786 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13787 } 13788 13789 SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); 13790 13791 module.exports = SyntheticFocusEvent; 13792 13793 },{"./SyntheticUIEvent":83}],80:[function(_dereq_,module,exports){ 13794 /** 13795 * Copyright 2013-2014 Facebook, Inc. 13796 * 13797 * Licensed under the Apache License, Version 2.0 (the "License"); 13798 * you may not use this file except in compliance with the License. 13799 * You may obtain a copy of the License at 13800 * 13801 * http://www.apache.org/licenses/LICENSE-2.0 13802 * 13803 * Unless required by applicable law or agreed to in writing, software 13804 * distributed under the License is distributed on an "AS IS" BASIS, 13805 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13806 * See the License for the specific language governing permissions and 13807 * limitations under the License. 13808 * 13809 * @providesModule SyntheticKeyboardEvent 13810 * @typechecks static-only 13811 */ 13812 13813 "use strict"; 13814 13815 var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); 13816 13817 var getEventKey = _dereq_("./getEventKey"); 13818 13819 /** 13820 * @interface KeyboardEvent 13821 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 13822 */ 13823 var KeyboardEventInterface = { 13824 key: getEventKey, 13825 location: null, 13826 ctrlKey: null, 13827 shiftKey: null, 13828 altKey: null, 13829 metaKey: null, 13830 repeat: null, 13831 locale: null, 13832 // Legacy Interface 13833 'char': null, 13834 charCode: null, 13835 keyCode: null, 13836 which: null 13837 }; 13838 13839 /** 13840 * @param {object} dispatchConfig Configuration used to dispatch this event. 13841 * @param {string} dispatchMarker Marker identifying the event target. 13842 * @param {object} nativeEvent Native browser event. 13843 * @extends {SyntheticUIEvent} 13844 */ 13845 function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13846 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13847 } 13848 13849 SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); 13850 13851 module.exports = SyntheticKeyboardEvent; 13852 13853 },{"./SyntheticUIEvent":83,"./getEventKey":103}],81:[function(_dereq_,module,exports){ 13854 /** 13855 * Copyright 2013-2014 Facebook, Inc. 13856 * 13857 * Licensed under the Apache License, Version 2.0 (the "License"); 13858 * you may not use this file except in compliance with the License. 13859 * You may obtain a copy of the License at 13860 * 13861 * http://www.apache.org/licenses/LICENSE-2.0 13862 * 13863 * Unless required by applicable law or agreed to in writing, software 13864 * distributed under the License is distributed on an "AS IS" BASIS, 13865 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13866 * See the License for the specific language governing permissions and 13867 * limitations under the License. 13868 * 13869 * @providesModule SyntheticMouseEvent 13870 * @typechecks static-only 13871 */ 13872 13873 "use strict"; 13874 13875 var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); 13876 var ViewportMetrics = _dereq_("./ViewportMetrics"); 13877 13878 /** 13879 * @interface MouseEvent 13880 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 13881 */ 13882 var MouseEventInterface = { 13883 screenX: null, 13884 screenY: null, 13885 clientX: null, 13886 clientY: null, 13887 ctrlKey: null, 13888 shiftKey: null, 13889 altKey: null, 13890 metaKey: null, 13891 button: function(event) { 13892 // Webkit, Firefox, IE9+ 13893 // which: 1 2 3 13894 // button: 0 1 2 (standard) 13895 var button = event.button; 13896 if ('which' in event) { 13897 return button; 13898 } 13899 // IE<9 13900 // which: undefined 13901 // button: 0 0 0 13902 // button: 1 4 2 (onmouseup) 13903 return button === 2 ? 2 : button === 4 ? 1 : 0; 13904 }, 13905 buttons: null, 13906 relatedTarget: function(event) { 13907 return event.relatedTarget || ( 13908 event.fromElement === event.srcElement ? 13909 event.toElement : 13910 event.fromElement 13911 ); 13912 }, 13913 // "Proprietary" Interface. 13914 pageX: function(event) { 13915 return 'pageX' in event ? 13916 event.pageX : 13917 event.clientX + ViewportMetrics.currentScrollLeft; 13918 }, 13919 pageY: function(event) { 13920 return 'pageY' in event ? 13921 event.pageY : 13922 event.clientY + ViewportMetrics.currentScrollTop; 13923 } 13924 }; 13925 13926 /** 13927 * @param {object} dispatchConfig Configuration used to dispatch this event. 13928 * @param {string} dispatchMarker Marker identifying the event target. 13929 * @param {object} nativeEvent Native browser event. 13930 * @extends {SyntheticUIEvent} 13931 */ 13932 function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13933 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13934 } 13935 13936 SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); 13937 13938 module.exports = SyntheticMouseEvent; 13939 13940 },{"./SyntheticUIEvent":83,"./ViewportMetrics":86}],82:[function(_dereq_,module,exports){ 13941 /** 13942 * Copyright 2013-2014 Facebook, Inc. 13943 * 13944 * Licensed under the Apache License, Version 2.0 (the "License"); 13945 * you may not use this file except in compliance with the License. 13946 * You may obtain a copy of the License at 13947 * 13948 * http://www.apache.org/licenses/LICENSE-2.0 13949 * 13950 * Unless required by applicable law or agreed to in writing, software 13951 * distributed under the License is distributed on an "AS IS" BASIS, 13952 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13953 * See the License for the specific language governing permissions and 13954 * limitations under the License. 13955 * 13956 * @providesModule SyntheticTouchEvent 13957 * @typechecks static-only 13958 */ 13959 13960 "use strict"; 13961 13962 var SyntheticUIEvent = _dereq_("./SyntheticUIEvent"); 13963 13964 /** 13965 * @interface TouchEvent 13966 * @see http://www.w3.org/TR/touch-events/ 13967 */ 13968 var TouchEventInterface = { 13969 touches: null, 13970 targetTouches: null, 13971 changedTouches: null, 13972 altKey: null, 13973 metaKey: null, 13974 ctrlKey: null, 13975 shiftKey: null 13976 }; 13977 13978 /** 13979 * @param {object} dispatchConfig Configuration used to dispatch this event. 13980 * @param {string} dispatchMarker Marker identifying the event target. 13981 * @param {object} nativeEvent Native browser event. 13982 * @extends {SyntheticUIEvent} 13983 */ 13984 function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent) { 13985 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 13986 } 13987 13988 SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); 13989 13990 module.exports = SyntheticTouchEvent; 13991 13992 },{"./SyntheticUIEvent":83}],83:[function(_dereq_,module,exports){ 13993 /** 13994 * Copyright 2013-2014 Facebook, Inc. 13995 * 13996 * Licensed under the Apache License, Version 2.0 (the "License"); 13997 * you may not use this file except in compliance with the License. 13998 * You may obtain a copy of the License at 13999 * 14000 * http://www.apache.org/licenses/LICENSE-2.0 14001 * 14002 * Unless required by applicable law or agreed to in writing, software 14003 * distributed under the License is distributed on an "AS IS" BASIS, 14004 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14005 * See the License for the specific language governing permissions and 14006 * limitations under the License. 14007 * 14008 * @providesModule SyntheticUIEvent 14009 * @typechecks static-only 14010 */ 14011 14012 "use strict"; 14013 14014 var SyntheticEvent = _dereq_("./SyntheticEvent"); 14015 14016 /** 14017 * @interface UIEvent 14018 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 14019 */ 14020 var UIEventInterface = { 14021 view: null, 14022 detail: null 14023 }; 14024 14025 /** 14026 * @param {object} dispatchConfig Configuration used to dispatch this event. 14027 * @param {string} dispatchMarker Marker identifying the event target. 14028 * @param {object} nativeEvent Native browser event. 14029 * @extends {SyntheticEvent} 14030 */ 14031 function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) { 14032 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 14033 } 14034 14035 SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface); 14036 14037 module.exports = SyntheticUIEvent; 14038 14039 },{"./SyntheticEvent":78}],84:[function(_dereq_,module,exports){ 14040 /** 14041 * Copyright 2013-2014 Facebook, Inc. 14042 * 14043 * Licensed under the Apache License, Version 2.0 (the "License"); 14044 * you may not use this file except in compliance with the License. 14045 * You may obtain a copy of the License at 14046 * 14047 * http://www.apache.org/licenses/LICENSE-2.0 14048 * 14049 * Unless required by applicable law or agreed to in writing, software 14050 * distributed under the License is distributed on an "AS IS" BASIS, 14051 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14052 * See the License for the specific language governing permissions and 14053 * limitations under the License. 14054 * 14055 * @providesModule SyntheticWheelEvent 14056 * @typechecks static-only 14057 */ 14058 14059 "use strict"; 14060 14061 var SyntheticMouseEvent = _dereq_("./SyntheticMouseEvent"); 14062 14063 /** 14064 * @interface WheelEvent 14065 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 14066 */ 14067 var WheelEventInterface = { 14068 deltaX: function(event) { 14069 return ( 14070 'deltaX' in event ? event.deltaX : 14071 // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 14072 'wheelDeltaX' in event ? -event.wheelDeltaX : 0 14073 ); 14074 }, 14075 deltaY: function(event) { 14076 return ( 14077 'deltaY' in event ? event.deltaY : 14078 // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). 14079 'wheelDeltaY' in event ? -event.wheelDeltaY : 14080 // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). 14081 'wheelDelta' in event ? -event.wheelDelta : 0 14082 ); 14083 }, 14084 deltaZ: null, 14085 14086 // Browsers without "deltaMode" is reporting in raw wheel delta where one 14087 // notch on the scroll is always +/- 120, roughly equivalent to pixels. 14088 // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or 14089 // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. 14090 deltaMode: null 14091 }; 14092 14093 /** 14094 * @param {object} dispatchConfig Configuration used to dispatch this event. 14095 * @param {string} dispatchMarker Marker identifying the event target. 14096 * @param {object} nativeEvent Native browser event. 14097 * @extends {SyntheticMouseEvent} 14098 */ 14099 function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent) { 14100 SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 14101 } 14102 14103 SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); 14104 14105 module.exports = SyntheticWheelEvent; 14106 14107 },{"./SyntheticMouseEvent":81}],85:[function(_dereq_,module,exports){ 14108 /** 14109 * Copyright 2013-2014 Facebook, Inc. 14110 * 14111 * Licensed under the Apache License, Version 2.0 (the "License"); 14112 * you may not use this file except in compliance with the License. 14113 * You may obtain a copy of the License at 14114 * 14115 * http://www.apache.org/licenses/LICENSE-2.0 14116 * 14117 * Unless required by applicable law or agreed to in writing, software 14118 * distributed under the License is distributed on an "AS IS" BASIS, 14119 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14120 * See the License for the specific language governing permissions and 14121 * limitations under the License. 14122 * 14123 * @providesModule Transaction 14124 */ 14125 14126 "use strict"; 14127 14128 var invariant = _dereq_("./invariant"); 14129 14130 /** 14131 * `Transaction` creates a black box that is able to wrap any method such that 14132 * certain invariants are maintained before and after the method is invoked 14133 * (Even if an exception is thrown while invoking the wrapped method). Whoever 14134 * instantiates a transaction can provide enforcers of the invariants at 14135 * creation time. The `Transaction` class itself will supply one additional 14136 * automatic invariant for you - the invariant that any transaction instance 14137 * should not be run while it is already being run. You would typically create a 14138 * single instance of a `Transaction` for reuse multiple times, that potentially 14139 * is used to wrap several different methods. Wrappers are extremely simple - 14140 * they only require implementing two methods. 14141 * 14142 * <pre> 14143 * wrappers (injected at creation time) 14144 * + + 14145 * | | 14146 * +-----------------|--------|--------------+ 14147 * | v | | 14148 * | +---------------+ | | 14149 * | +--| wrapper1 |---|----+ | 14150 * | | +---------------+ v | | 14151 * | | +-------------+ | | 14152 * | | +----| wrapper2 |--------+ | 14153 * | | | +-------------+ | | | 14154 * | | | | | | 14155 * | v v v v | wrapper 14156 * | +---+ +---+ +---------+ +---+ +---+ | invariants 14157 * perform(anyMethod) | | | | | | | | | | | | maintained 14158 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|--------> 14159 * | | | | | | | | | | | | 14160 * | | | | | | | | | | | | 14161 * | | | | | | | | | | | | 14162 * | +---+ +---+ +---------+ +---+ +---+ | 14163 * | initialize close | 14164 * +-----------------------------------------+ 14165 * </pre> 14166 * 14167 * Bonus: 14168 * - Reports timing metrics by method name and wrapper index. 14169 * 14170 * Use cases: 14171 * - Preserving the input selection ranges before/after reconciliation. 14172 * Restoring selection even in the event of an unexpected error. 14173 * - Deactivating events while rearranging the DOM, preventing blurs/focuses, 14174 * while guaranteeing that afterwards, the event system is reactivated. 14175 * - Flushing a queue of collected DOM mutations to the main UI thread after a 14176 * reconciliation takes place in a worker thread. 14177 * - Invoking any collected `componentDidUpdate` callbacks after rendering new 14178 * content. 14179 * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue 14180 * to preserve the `scrollTop` (an automatic scroll aware DOM). 14181 * - (Future use case): Layout calculations before and after DOM upates. 14182 * 14183 * Transactional plugin API: 14184 * - A module that has an `initialize` method that returns any precomputation. 14185 * - and a `close` method that accepts the precomputation. `close` is invoked 14186 * when the wrapped process is completed, or has failed. 14187 * 14188 * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules 14189 * that implement `initialize` and `close`. 14190 * @return {Transaction} Single transaction for reuse in thread. 14191 * 14192 * @class Transaction 14193 */ 14194 var Mixin = { 14195 /** 14196 * Sets up this instance so that it is prepared for collecting metrics. Does 14197 * so such that this setup method may be used on an instance that is already 14198 * initialized, in a way that does not consume additional memory upon reuse. 14199 * That can be useful if you decide to make your subclass of this mixin a 14200 * "PooledClass". 14201 */ 14202 reinitializeTransaction: function() { 14203 this.transactionWrappers = this.getTransactionWrappers(); 14204 if (!this.wrapperInitData) { 14205 this.wrapperInitData = []; 14206 } else { 14207 this.wrapperInitData.length = 0; 14208 } 14209 if (!this.timingMetrics) { 14210 this.timingMetrics = {}; 14211 } 14212 this.timingMetrics.methodInvocationTime = 0; 14213 if (!this.timingMetrics.wrapperInitTimes) { 14214 this.timingMetrics.wrapperInitTimes = []; 14215 } else { 14216 this.timingMetrics.wrapperInitTimes.length = 0; 14217 } 14218 if (!this.timingMetrics.wrapperCloseTimes) { 14219 this.timingMetrics.wrapperCloseTimes = []; 14220 } else { 14221 this.timingMetrics.wrapperCloseTimes.length = 0; 14222 } 14223 this._isInTransaction = false; 14224 }, 14225 14226 _isInTransaction: false, 14227 14228 /** 14229 * @abstract 14230 * @return {Array<TransactionWrapper>} Array of transaction wrappers. 14231 */ 14232 getTransactionWrappers: null, 14233 14234 isInTransaction: function() { 14235 return !!this._isInTransaction; 14236 }, 14237 14238 /** 14239 * Executes the function within a safety window. Use this for the top level 14240 * methods that result in large amounts of computation/mutations that would 14241 * need to be safety checked. 14242 * 14243 * @param {function} method Member of scope to call. 14244 * @param {Object} scope Scope to invoke from. 14245 * @param {Object?=} args... Arguments to pass to the method (optional). 14246 * Helps prevent need to bind in many cases. 14247 * @return Return value from `method`. 14248 */ 14249 perform: function(method, scope, a, b, c, d, e, f) { 14250 ("production" !== "development" ? invariant( 14251 !this.isInTransaction(), 14252 'Transaction.perform(...): Cannot initialize a transaction when there ' + 14253 'is already an outstanding transaction.' 14254 ) : invariant(!this.isInTransaction())); 14255 var memberStart = Date.now(); 14256 var errorThrown; 14257 var ret; 14258 try { 14259 this._isInTransaction = true; 14260 // Catching errors makes debugging more difficult, so we start with 14261 // errorThrown set to true before setting it to false after calling 14262 // close -- if it's still set to true in the finally block, it means 14263 // one of these calls threw. 14264 errorThrown = true; 14265 this.initializeAll(0); 14266 ret = method.call(scope, a, b, c, d, e, f); 14267 errorThrown = false; 14268 } finally { 14269 var memberEnd = Date.now(); 14270 this.methodInvocationTime += (memberEnd - memberStart); 14271 try { 14272 if (errorThrown) { 14273 // If `method` throws, prefer to show that stack trace over any thrown 14274 // by invoking `closeAll`. 14275 try { 14276 this.closeAll(0); 14277 } catch (err) { 14278 } 14279 } else { 14280 // Since `method` didn't throw, we don't want to silence the exception 14281 // here. 14282 this.closeAll(0); 14283 } 14284 } finally { 14285 this._isInTransaction = false; 14286 } 14287 } 14288 return ret; 14289 }, 14290 14291 initializeAll: function(startIndex) { 14292 var transactionWrappers = this.transactionWrappers; 14293 var wrapperInitTimes = this.timingMetrics.wrapperInitTimes; 14294 for (var i = startIndex; i < transactionWrappers.length; i++) { 14295 var initStart = Date.now(); 14296 var wrapper = transactionWrappers[i]; 14297 try { 14298 // Catching errors makes debugging more difficult, so we start with the 14299 // OBSERVED_ERROR state before overwriting it with the real return value 14300 // of initialize -- if it's still set to OBSERVED_ERROR in the finally 14301 // block, it means wrapper.initialize threw. 14302 this.wrapperInitData[i] = Transaction.OBSERVED_ERROR; 14303 this.wrapperInitData[i] = wrapper.initialize ? 14304 wrapper.initialize.call(this) : 14305 null; 14306 } finally { 14307 var curInitTime = wrapperInitTimes[i]; 14308 var initEnd = Date.now(); 14309 wrapperInitTimes[i] = (curInitTime || 0) + (initEnd - initStart); 14310 14311 if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) { 14312 // The initializer for wrapper i threw an error; initialize the 14313 // remaining wrappers but silence any exceptions from them to ensure 14314 // that the first error is the one to bubble up. 14315 try { 14316 this.initializeAll(i + 1); 14317 } catch (err) { 14318 } 14319 } 14320 } 14321 } 14322 }, 14323 14324 /** 14325 * Invokes each of `this.transactionWrappers.close[i]` functions, passing into 14326 * them the respective return values of `this.transactionWrappers.init[i]` 14327 * (`close`rs that correspond to initializers that failed will not be 14328 * invoked). 14329 */ 14330 closeAll: function(startIndex) { 14331 ("production" !== "development" ? invariant( 14332 this.isInTransaction(), 14333 'Transaction.closeAll(): Cannot close transaction when none are open.' 14334 ) : invariant(this.isInTransaction())); 14335 var transactionWrappers = this.transactionWrappers; 14336 var wrapperCloseTimes = this.timingMetrics.wrapperCloseTimes; 14337 for (var i = startIndex; i < transactionWrappers.length; i++) { 14338 var wrapper = transactionWrappers[i]; 14339 var closeStart = Date.now(); 14340 var initData = this.wrapperInitData[i]; 14341 var errorThrown; 14342 try { 14343 // Catching errors makes debugging more difficult, so we start with 14344 // errorThrown set to true before setting it to false after calling 14345 // close -- if it's still set to true in the finally block, it means 14346 // wrapper.close threw. 14347 errorThrown = true; 14348 if (initData !== Transaction.OBSERVED_ERROR) { 14349 wrapper.close && wrapper.close.call(this, initData); 14350 } 14351 errorThrown = false; 14352 } finally { 14353 var closeEnd = Date.now(); 14354 var curCloseTime = wrapperCloseTimes[i]; 14355 wrapperCloseTimes[i] = (curCloseTime || 0) + (closeEnd - closeStart); 14356 14357 if (errorThrown) { 14358 // The closer for wrapper i threw an error; close the remaining 14359 // wrappers but silence any exceptions from them to ensure that the 14360 // first error is the one to bubble up. 14361 try { 14362 this.closeAll(i + 1); 14363 } catch (e) { 14364 } 14365 } 14366 } 14367 } 14368 this.wrapperInitData.length = 0; 14369 } 14370 }; 14371 14372 var Transaction = { 14373 14374 Mixin: Mixin, 14375 14376 /** 14377 * Token to look for to determine if an error occured. 14378 */ 14379 OBSERVED_ERROR: {} 14380 14381 }; 14382 14383 module.exports = Transaction; 14384 14385 },{"./invariant":112}],86:[function(_dereq_,module,exports){ 14386 /** 14387 * Copyright 2013-2014 Facebook, Inc. 14388 * 14389 * Licensed under the Apache License, Version 2.0 (the "License"); 14390 * you may not use this file except in compliance with the License. 14391 * You may obtain a copy of the License at 14392 * 14393 * http://www.apache.org/licenses/LICENSE-2.0 14394 * 14395 * Unless required by applicable law or agreed to in writing, software 14396 * distributed under the License is distributed on an "AS IS" BASIS, 14397 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14398 * See the License for the specific language governing permissions and 14399 * limitations under the License. 14400 * 14401 * @providesModule ViewportMetrics 14402 */ 14403 14404 "use strict"; 14405 14406 var getUnboundedScrollPosition = _dereq_("./getUnboundedScrollPosition"); 14407 14408 var ViewportMetrics = { 14409 14410 currentScrollLeft: 0, 14411 14412 currentScrollTop: 0, 14413 14414 refreshScrollValues: function() { 14415 var scrollPosition = getUnboundedScrollPosition(window); 14416 ViewportMetrics.currentScrollLeft = scrollPosition.x; 14417 ViewportMetrics.currentScrollTop = scrollPosition.y; 14418 } 14419 14420 }; 14421 14422 module.exports = ViewportMetrics; 14423 14424 },{"./getUnboundedScrollPosition":109}],87:[function(_dereq_,module,exports){ 14425 /** 14426 * Copyright 2013-2014 Facebook, Inc. 14427 * 14428 * Licensed under the Apache License, Version 2.0 (the "License"); 14429 * you may not use this file except in compliance with the License. 14430 * You may obtain a copy of the License at 14431 * 14432 * http://www.apache.org/licenses/LICENSE-2.0 14433 * 14434 * Unless required by applicable law or agreed to in writing, software 14435 * distributed under the License is distributed on an "AS IS" BASIS, 14436 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14437 * See the License for the specific language governing permissions and 14438 * limitations under the License. 14439 * 14440 * @providesModule accumulate 14441 */ 14442 14443 "use strict"; 14444 14445 var invariant = _dereq_("./invariant"); 14446 14447 /** 14448 * Accumulates items that must not be null or undefined. 14449 * 14450 * This is used to conserve memory by avoiding array allocations. 14451 * 14452 * @return {*|array<*>} An accumulation of items. 14453 */ 14454 function accumulate(current, next) { 14455 ("production" !== "development" ? invariant( 14456 next != null, 14457 'accumulate(...): Accumulated items must be not be null or undefined.' 14458 ) : invariant(next != null)); 14459 if (current == null) { 14460 return next; 14461 } else { 14462 // Both are not empty. Warning: Never call x.concat(y) when you are not 14463 // certain that x is an Array (x could be a string with concat method). 14464 var currentIsArray = Array.isArray(current); 14465 var nextIsArray = Array.isArray(next); 14466 if (currentIsArray) { 14467 return current.concat(next); 14468 } else { 14469 if (nextIsArray) { 14470 return [current].concat(next); 14471 } else { 14472 return [current, next]; 14473 } 14474 } 14475 } 14476 } 14477 14478 module.exports = accumulate; 14479 14480 },{"./invariant":112}],88:[function(_dereq_,module,exports){ 14481 /** 14482 * Copyright 2013-2014 Facebook, Inc. 14483 * 14484 * Licensed under the Apache License, Version 2.0 (the "License"); 14485 * you may not use this file except in compliance with the License. 14486 * You may obtain a copy of the License at 14487 * 14488 * http://www.apache.org/licenses/LICENSE-2.0 14489 * 14490 * Unless required by applicable law or agreed to in writing, software 14491 * distributed under the License is distributed on an "AS IS" BASIS, 14492 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14493 * See the License for the specific language governing permissions and 14494 * limitations under the License. 14495 * 14496 * @providesModule adler32 14497 */ 14498 14499 /* jslint bitwise:true */ 14500 14501 "use strict"; 14502 14503 var MOD = 65521; 14504 14505 // This is a clean-room implementation of adler32 designed for detecting 14506 // if markup is not what we expect it to be. It does not need to be 14507 // cryptographically strong, only reasonable good at detecting if markup 14508 // generated on the server is different than that on the client. 14509 function adler32(data) { 14510 var a = 1; 14511 var b = 0; 14512 for (var i = 0; i < data.length; i++) { 14513 a = (a + data.charCodeAt(i)) % MOD; 14514 b = (b + a) % MOD; 14515 } 14516 return a | (b << 16); 14517 } 14518 14519 module.exports = adler32; 14520 14521 },{}],89:[function(_dereq_,module,exports){ 14522 /** 14523 * Copyright 2013-2014 Facebook, Inc. 14524 * 14525 * Licensed under the Apache License, Version 2.0 (the "License"); 14526 * you may not use this file except in compliance with the License. 14527 * You may obtain a copy of the License at 14528 * 14529 * http://www.apache.org/licenses/LICENSE-2.0 14530 * 14531 * Unless required by applicable law or agreed to in writing, software 14532 * distributed under the License is distributed on an "AS IS" BASIS, 14533 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14534 * See the License for the specific language governing permissions and 14535 * limitations under the License. 14536 * 14537 * @providesModule containsNode 14538 * @typechecks 14539 */ 14540 14541 var isTextNode = _dereq_("./isTextNode"); 14542 14543 /*jslint bitwise:true */ 14544 14545 /** 14546 * Checks if a given DOM node contains or is another DOM node. 14547 * 14548 * @param {?DOMNode} outerNode Outer DOM node. 14549 * @param {?DOMNode} innerNode Inner DOM node. 14550 * @return {boolean} True if `outerNode` contains or is `innerNode`. 14551 */ 14552 function containsNode(outerNode, innerNode) { 14553 if (!outerNode || !innerNode) { 14554 return false; 14555 } else if (outerNode === innerNode) { 14556 return true; 14557 } else if (isTextNode(outerNode)) { 14558 return false; 14559 } else if (isTextNode(innerNode)) { 14560 return containsNode(outerNode, innerNode.parentNode); 14561 } else if (outerNode.contains) { 14562 return outerNode.contains(innerNode); 14563 } else if (outerNode.compareDocumentPosition) { 14564 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 14565 } else { 14566 return false; 14567 } 14568 } 14569 14570 module.exports = containsNode; 14571 14572 },{"./isTextNode":116}],90:[function(_dereq_,module,exports){ 14573 /** 14574 * Copyright 2013-2014 Facebook, Inc. 14575 * 14576 * Licensed under the Apache License, Version 2.0 (the "License"); 14577 * you may not use this file except in compliance with the License. 14578 * You may obtain a copy of the License at 14579 * 14580 * http://www.apache.org/licenses/LICENSE-2.0 14581 * 14582 * Unless required by applicable law or agreed to in writing, software 14583 * distributed under the License is distributed on an "AS IS" BASIS, 14584 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14585 * See the License for the specific language governing permissions and 14586 * limitations under the License. 14587 * 14588 * @providesModule copyProperties 14589 */ 14590 14591 /** 14592 * Copy properties from one or more objects (up to 5) into the first object. 14593 * This is a shallow copy. It mutates the first object and also returns it. 14594 * 14595 * NOTE: `arguments` has a very significant performance penalty, which is why 14596 * we don't support unlimited arguments. 14597 */ 14598 function copyProperties(obj, a, b, c, d, e, f) { 14599 obj = obj || {}; 14600 14601 if ("production" !== "development") { 14602 if (f) { 14603 throw new Error('Too many arguments passed to copyProperties'); 14604 } 14605 } 14606 14607 var args = [a, b, c, d, e]; 14608 var ii = 0, v; 14609 while (args[ii]) { 14610 v = args[ii++]; 14611 for (var k in v) { 14612 obj[k] = v[k]; 14613 } 14614 14615 // IE ignores toString in object iteration.. See: 14616 // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html 14617 if (v.hasOwnProperty && v.hasOwnProperty('toString') && 14618 (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { 14619 obj.toString = v.toString; 14620 } 14621 } 14622 14623 return obj; 14624 } 14625 14626 module.exports = copyProperties; 14627 14628 },{}],91:[function(_dereq_,module,exports){ 14629 /** 14630 * Copyright 2013-2014 Facebook, Inc. 14631 * 14632 * Licensed under the Apache License, Version 2.0 (the "License"); 14633 * you may not use this file except in compliance with the License. 14634 * You may obtain a copy of the License at 14635 * 14636 * http://www.apache.org/licenses/LICENSE-2.0 14637 * 14638 * Unless required by applicable law or agreed to in writing, software 14639 * distributed under the License is distributed on an "AS IS" BASIS, 14640 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14641 * See the License for the specific language governing permissions and 14642 * limitations under the License. 14643 * 14644 * @providesModule createArrayFrom 14645 * @typechecks 14646 */ 14647 14648 var toArray = _dereq_("./toArray"); 14649 14650 /** 14651 * Perform a heuristic test to determine if an object is "array-like". 14652 * 14653 * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" 14654 * Joshu replied: "Mu." 14655 * 14656 * This function determines if its argument has "array nature": it returns 14657 * true if the argument is an actual array, an `arguments' object, or an 14658 * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). 14659 * 14660 * It will return false for other array-like objects like Filelist. 14661 * 14662 * @param {*} obj 14663 * @return {boolean} 14664 */ 14665 function hasArrayNature(obj) { 14666 return ( 14667 // not null/false 14668 !!obj && 14669 // arrays are objects, NodeLists are functions in Safari 14670 (typeof obj == 'object' || typeof obj == 'function') && 14671 // quacks like an array 14672 ('length' in obj) && 14673 // not window 14674 !('setInterval' in obj) && 14675 // no DOM node should be considered an array-like 14676 // a 'select' element has 'length' and 'item' properties on IE8 14677 (typeof obj.nodeType != 'number') && 14678 ( 14679 // a real array 14680 (// HTMLCollection/NodeList 14681 (Array.isArray(obj) || 14682 // arguments 14683 ('callee' in obj) || 'item' in obj)) 14684 ) 14685 ); 14686 } 14687 14688 /** 14689 * Ensure that the argument is an array by wrapping it in an array if it is not. 14690 * Creates a copy of the argument if it is already an array. 14691 * 14692 * This is mostly useful idiomatically: 14693 * 14694 * var createArrayFrom = require('createArrayFrom'); 14695 * 14696 * function takesOneOrMoreThings(things) { 14697 * things = createArrayFrom(things); 14698 * ... 14699 * } 14700 * 14701 * This allows you to treat `things' as an array, but accept scalars in the API. 14702 * 14703 * If you need to convert an array-like object, like `arguments`, into an array 14704 * use toArray instead. 14705 * 14706 * @param {*} obj 14707 * @return {array} 14708 */ 14709 function createArrayFrom(obj) { 14710 if (!hasArrayNature(obj)) { 14711 return [obj]; 14712 } else if (Array.isArray(obj)) { 14713 return obj.slice(); 14714 } else { 14715 return toArray(obj); 14716 } 14717 } 14718 14719 module.exports = createArrayFrom; 14720 14721 },{"./toArray":132}],92:[function(_dereq_,module,exports){ 14722 /** 14723 * Copyright 2013-2014 Facebook, Inc. 14724 * 14725 * Licensed under the Apache License, Version 2.0 (the "License"); 14726 * you may not use this file except in compliance with the License. 14727 * You may obtain a copy of the License at 14728 * 14729 * http://www.apache.org/licenses/LICENSE-2.0 14730 * 14731 * Unless required by applicable law or agreed to in writing, software 14732 * distributed under the License is distributed on an "AS IS" BASIS, 14733 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14734 * See the License for the specific language governing permissions and 14735 * limitations under the License. 14736 * 14737 * @providesModule createFullPageComponent 14738 * @typechecks 14739 */ 14740 14741 "use strict"; 14742 14743 // Defeat circular references by requiring this directly. 14744 var ReactCompositeComponent = _dereq_("./ReactCompositeComponent"); 14745 14746 var invariant = _dereq_("./invariant"); 14747 14748 /** 14749 * Create a component that will throw an exception when unmounted. 14750 * 14751 * Components like <html> <head> and <body> can't be removed or added 14752 * easily in a cross-browser way, however it's valuable to be able to 14753 * take advantage of React's reconciliation for styling and <title> 14754 * management. So we just document it and throw in dangerous cases. 14755 * 14756 * @param {function} componentClass convenience constructor to wrap 14757 * @return {function} convenience constructor of new component 14758 */ 14759 function createFullPageComponent(componentClass) { 14760 var FullPageComponent = ReactCompositeComponent.createClass({ 14761 displayName: 'ReactFullPageComponent' + ( 14762 componentClass.componentConstructor.displayName || '' 14763 ), 14764 14765 componentWillUnmount: function() { 14766 ("production" !== "development" ? invariant( 14767 false, 14768 '%s tried to unmount. Because of cross-browser quirks it is ' + 14769 'impossible to unmount some top-level components (eg <html>, <head>, ' + 14770 'and <body>) reliably and efficiently. To fix this, have a single ' + 14771 'top-level component that never unmounts render these elements.', 14772 this.constructor.displayName 14773 ) : invariant(false)); 14774 }, 14775 14776 render: function() { 14777 return this.transferPropsTo(componentClass(null, this.props.children)); 14778 } 14779 }); 14780 14781 return FullPageComponent; 14782 } 14783 14784 module.exports = createFullPageComponent; 14785 14786 },{"./ReactCompositeComponent":29,"./invariant":112}],93:[function(_dereq_,module,exports){ 14787 /** 14788 * Copyright 2013-2014 Facebook, Inc. 14789 * 14790 * Licensed under the Apache License, Version 2.0 (the "License"); 14791 * you may not use this file except in compliance with the License. 14792 * You may obtain a copy of the License at 14793 * 14794 * http://www.apache.org/licenses/LICENSE-2.0 14795 * 14796 * Unless required by applicable law or agreed to in writing, software 14797 * distributed under the License is distributed on an "AS IS" BASIS, 14798 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14799 * See the License for the specific language governing permissions and 14800 * limitations under the License. 14801 * 14802 * @providesModule createNodesFromMarkup 14803 * @typechecks 14804 */ 14805 14806 /*jslint evil: true, sub: true */ 14807 14808 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 14809 14810 var createArrayFrom = _dereq_("./createArrayFrom"); 14811 var getMarkupWrap = _dereq_("./getMarkupWrap"); 14812 var invariant = _dereq_("./invariant"); 14813 14814 /** 14815 * Dummy container used to render all markup. 14816 */ 14817 var dummyNode = 14818 ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 14819 14820 /** 14821 * Pattern used by `getNodeName`. 14822 */ 14823 var nodeNamePattern = /^\s*<(\w+)/; 14824 14825 /** 14826 * Extracts the `nodeName` of the first element in a string of markup. 14827 * 14828 * @param {string} markup String of markup. 14829 * @return {?string} Node name of the supplied markup. 14830 */ 14831 function getNodeName(markup) { 14832 var nodeNameMatch = markup.match(nodeNamePattern); 14833 return nodeNameMatch && nodeNameMatch[1].toLowerCase(); 14834 } 14835 14836 /** 14837 * Creates an array containing the nodes rendered from the supplied markup. The 14838 * optionally supplied `handleScript` function will be invoked once for each 14839 * <script> element that is rendered. If no `handleScript` function is supplied, 14840 * an exception is thrown if any <script> elements are rendered. 14841 * 14842 * @param {string} markup A string of valid HTML markup. 14843 * @param {?function} handleScript Invoked once for each rendered <script>. 14844 * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes. 14845 */ 14846 function createNodesFromMarkup(markup, handleScript) { 14847 var node = dummyNode; 14848 ("production" !== "development" ? invariant(!!dummyNode, 'createNodesFromMarkup dummy not initialized') : invariant(!!dummyNode)); 14849 var nodeName = getNodeName(markup); 14850 14851 var wrap = nodeName && getMarkupWrap(nodeName); 14852 if (wrap) { 14853 node.innerHTML = wrap[1] + markup + wrap[2]; 14854 14855 var wrapDepth = wrap[0]; 14856 while (wrapDepth--) { 14857 node = node.lastChild; 14858 } 14859 } else { 14860 node.innerHTML = markup; 14861 } 14862 14863 var scripts = node.getElementsByTagName('script'); 14864 if (scripts.length) { 14865 ("production" !== "development" ? invariant( 14866 handleScript, 14867 'createNodesFromMarkup(...): Unexpected <script> element rendered.' 14868 ) : invariant(handleScript)); 14869 createArrayFrom(scripts).forEach(handleScript); 14870 } 14871 14872 var nodes = createArrayFrom(node.childNodes); 14873 while (node.lastChild) { 14874 node.removeChild(node.lastChild); 14875 } 14876 return nodes; 14877 } 14878 14879 module.exports = createNodesFromMarkup; 14880 14881 },{"./ExecutionEnvironment":20,"./createArrayFrom":91,"./getMarkupWrap":105,"./invariant":112}],94:[function(_dereq_,module,exports){ 14882 /** 14883 * Copyright 2013-2014 Facebook, Inc. 14884 * 14885 * Licensed under the Apache License, Version 2.0 (the "License"); 14886 * you may not use this file except in compliance with the License. 14887 * You may obtain a copy of the License at 14888 * 14889 * http://www.apache.org/licenses/LICENSE-2.0 14890 * 14891 * Unless required by applicable law or agreed to in writing, software 14892 * distributed under the License is distributed on an "AS IS" BASIS, 14893 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14894 * See the License for the specific language governing permissions and 14895 * limitations under the License. 14896 * 14897 * @providesModule createObjectFrom 14898 */ 14899 14900 /** 14901 * Construct an object from an array of keys 14902 * and optionally specified value or list of values. 14903 * 14904 * >>> createObjectFrom(['a','b','c']); 14905 * {a: true, b: true, c: true} 14906 * 14907 * >>> createObjectFrom(['a','b','c'], false); 14908 * {a: false, b: false, c: false} 14909 * 14910 * >>> createObjectFrom(['a','b','c'], 'monkey'); 14911 * {c:'monkey', b:'monkey' c:'monkey'} 14912 * 14913 * >>> createObjectFrom(['a','b','c'], [1,2,3]); 14914 * {a: 1, b: 2, c: 3} 14915 * 14916 * >>> createObjectFrom(['women', 'men'], [true, false]); 14917 * {women: true, men: false} 14918 * 14919 * @param Array list of keys 14920 * @param mixed optional value or value array. defaults true. 14921 * @returns object 14922 */ 14923 function createObjectFrom(keys, values /* = true */) { 14924 if ("production" !== "development") { 14925 if (!Array.isArray(keys)) { 14926 throw new TypeError('Must pass an array of keys.'); 14927 } 14928 } 14929 14930 var object = {}; 14931 var isArray = Array.isArray(values); 14932 if (typeof values == 'undefined') { 14933 values = true; 14934 } 14935 14936 for (var ii = keys.length; ii--;) { 14937 object[keys[ii]] = isArray ? values[ii] : values; 14938 } 14939 return object; 14940 } 14941 14942 module.exports = createObjectFrom; 14943 14944 },{}],95:[function(_dereq_,module,exports){ 14945 /** 14946 * Copyright 2013-2014 Facebook, Inc. 14947 * 14948 * Licensed under the Apache License, Version 2.0 (the "License"); 14949 * you may not use this file except in compliance with the License. 14950 * You may obtain a copy of the License at 14951 * 14952 * http://www.apache.org/licenses/LICENSE-2.0 14953 * 14954 * Unless required by applicable law or agreed to in writing, software 14955 * distributed under the License is distributed on an "AS IS" BASIS, 14956 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14957 * See the License for the specific language governing permissions and 14958 * limitations under the License. 14959 * 14960 * @providesModule dangerousStyleValue 14961 * @typechecks static-only 14962 */ 14963 14964 "use strict"; 14965 14966 var CSSProperty = _dereq_("./CSSProperty"); 14967 14968 /** 14969 * Convert a value into the proper css writable value. The `styleName` name 14970 * name should be logical (no hyphens), as specified 14971 * in `CSSProperty.isUnitlessNumber`. 14972 * 14973 * @param {string} styleName CSS property name such as `topMargin`. 14974 * @param {*} value CSS property value such as `10px`. 14975 * @return {string} Normalized style value with dimensions applied. 14976 */ 14977 function dangerousStyleValue(styleName, value) { 14978 // Note that we've removed escapeTextForBrowser() calls here since the 14979 // whole string will be escaped when the attribute is injected into 14980 // the markup. If you provide unsafe user data here they can inject 14981 // arbitrary CSS which may be problematic (I couldn't repro this): 14982 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 14983 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 14984 // This is not an XSS hole but instead a potential CSS injection issue 14985 // which has lead to a greater discussion about how we're going to 14986 // trust URLs moving forward. See #2115901 14987 14988 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 14989 if (isEmpty) { 14990 return ''; 14991 } 14992 14993 var isNonNumeric = isNaN(value); 14994 if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) { 14995 return '' + value; // cast to string 14996 } 14997 14998 return value + 'px'; 14999 } 15000 15001 module.exports = dangerousStyleValue; 15002 15003 },{"./CSSProperty":2}],96:[function(_dereq_,module,exports){ 15004 /** 15005 * Copyright 2013-2014 Facebook, Inc. 15006 * 15007 * Licensed under the Apache License, Version 2.0 (the "License"); 15008 * you may not use this file except in compliance with the License. 15009 * You may obtain a copy of the License at 15010 * 15011 * http://www.apache.org/licenses/LICENSE-2.0 15012 * 15013 * Unless required by applicable law or agreed to in writing, software 15014 * distributed under the License is distributed on an "AS IS" BASIS, 15015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15016 * See the License for the specific language governing permissions and 15017 * limitations under the License. 15018 * 15019 * @providesModule emptyFunction 15020 */ 15021 15022 var copyProperties = _dereq_("./copyProperties"); 15023 15024 function makeEmptyFunction(arg) { 15025 return function() { 15026 return arg; 15027 }; 15028 } 15029 15030 /** 15031 * This function accepts and discards inputs; it has no side effects. This is 15032 * primarily useful idiomatically for overridable function endpoints which 15033 * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 15034 */ 15035 function emptyFunction() {} 15036 15037 copyProperties(emptyFunction, { 15038 thatReturns: makeEmptyFunction, 15039 thatReturnsFalse: makeEmptyFunction(false), 15040 thatReturnsTrue: makeEmptyFunction(true), 15041 thatReturnsNull: makeEmptyFunction(null), 15042 thatReturnsThis: function() { return this; }, 15043 thatReturnsArgument: function(arg) { return arg; } 15044 }); 15045 15046 module.exports = emptyFunction; 15047 15048 },{"./copyProperties":90}],97:[function(_dereq_,module,exports){ 15049 /** 15050 * Copyright 2013-2014 Facebook, Inc. 15051 * 15052 * Licensed under the Apache License, Version 2.0 (the "License"); 15053 * you may not use this file except in compliance with the License. 15054 * You may obtain a copy of the License at 15055 * 15056 * http://www.apache.org/licenses/LICENSE-2.0 15057 * 15058 * Unless required by applicable law or agreed to in writing, software 15059 * distributed under the License is distributed on an "AS IS" BASIS, 15060 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15061 * See the License for the specific language governing permissions and 15062 * limitations under the License. 15063 * 15064 * @providesModule emptyObject 15065 */ 15066 15067 "use strict"; 15068 15069 var emptyObject = {}; 15070 15071 if ("production" !== "development") { 15072 Object.freeze(emptyObject); 15073 } 15074 15075 module.exports = emptyObject; 15076 15077 },{}],98:[function(_dereq_,module,exports){ 15078 /** 15079 * Copyright 2013-2014 Facebook, Inc. 15080 * 15081 * Licensed under the Apache License, Version 2.0 (the "License"); 15082 * you may not use this file except in compliance with the License. 15083 * You may obtain a copy of the License at 15084 * 15085 * http://www.apache.org/licenses/LICENSE-2.0 15086 * 15087 * Unless required by applicable law or agreed to in writing, software 15088 * distributed under the License is distributed on an "AS IS" BASIS, 15089 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15090 * See the License for the specific language governing permissions and 15091 * limitations under the License. 15092 * 15093 * @providesModule escapeTextForBrowser 15094 * @typechecks static-only 15095 */ 15096 15097 "use strict"; 15098 15099 var ESCAPE_LOOKUP = { 15100 "&": "&", 15101 ">": ">", 15102 "<": "<", 15103 "\"": """, 15104 "'": "'", 15105 "/": "/" 15106 }; 15107 15108 var ESCAPE_REGEX = /[&><"'\/]/g; 15109 15110 function escaper(match) { 15111 return ESCAPE_LOOKUP[match]; 15112 } 15113 15114 /** 15115 * Escapes text to prevent scripting attacks. 15116 * 15117 * @param {*} text Text value to escape. 15118 * @return {string} An escaped string. 15119 */ 15120 function escapeTextForBrowser(text) { 15121 return ('' + text).replace(ESCAPE_REGEX, escaper); 15122 } 15123 15124 module.exports = escapeTextForBrowser; 15125 15126 },{}],99:[function(_dereq_,module,exports){ 15127 /** 15128 * Copyright 2013-2014 Facebook, Inc. 15129 * 15130 * Licensed under the Apache License, Version 2.0 (the "License"); 15131 * you may not use this file except in compliance with the License. 15132 * You may obtain a copy of the License at 15133 * 15134 * http://www.apache.org/licenses/LICENSE-2.0 15135 * 15136 * Unless required by applicable law or agreed to in writing, software 15137 * distributed under the License is distributed on an "AS IS" BASIS, 15138 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15139 * See the License for the specific language governing permissions and 15140 * limitations under the License. 15141 * 15142 * @providesModule flattenChildren 15143 */ 15144 15145 "use strict"; 15146 15147 var invariant = _dereq_("./invariant"); 15148 var traverseAllChildren = _dereq_("./traverseAllChildren"); 15149 15150 /** 15151 * @param {function} traverseContext Context passed through traversal. 15152 * @param {?ReactComponent} child React child component. 15153 * @param {!string} name String name of key path to child. 15154 */ 15155 function flattenSingleChildIntoContext(traverseContext, child, name) { 15156 // We found a component instance. 15157 var result = traverseContext; 15158 ("production" !== "development" ? invariant( 15159 !result.hasOwnProperty(name), 15160 'flattenChildren(...): Encountered two children with the same key, `%s`. ' + 15161 'Children keys must be unique.', 15162 name 15163 ) : invariant(!result.hasOwnProperty(name))); 15164 if (child != null) { 15165 result[name] = child; 15166 } 15167 } 15168 15169 /** 15170 * Flattens children that are typically specified as `props.children`. Any null 15171 * children will not be included in the resulting object. 15172 * @return {!object} flattened children keyed by name. 15173 */ 15174 function flattenChildren(children) { 15175 if (children == null) { 15176 return children; 15177 } 15178 var result = {}; 15179 traverseAllChildren(children, flattenSingleChildIntoContext, result); 15180 return result; 15181 } 15182 15183 module.exports = flattenChildren; 15184 15185 },{"./invariant":112,"./traverseAllChildren":133}],100:[function(_dereq_,module,exports){ 15186 /** 15187 * Copyright 2014 Facebook, Inc. 15188 * 15189 * Licensed under the Apache License, Version 2.0 (the "License"); 15190 * you may not use this file except in compliance with the License. 15191 * You may obtain a copy of the License at 15192 * 15193 * http://www.apache.org/licenses/LICENSE-2.0 15194 * 15195 * Unless required by applicable law or agreed to in writing, software 15196 * distributed under the License is distributed on an "AS IS" BASIS, 15197 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15198 * See the License for the specific language governing permissions and 15199 * limitations under the License. 15200 * 15201 * @providesModule focusNode 15202 */ 15203 15204 "use strict"; 15205 15206 /** 15207 * IE8 throws if an input/textarea is disabled and we try to focus it. 15208 * Focus only when necessary. 15209 * 15210 * @param {DOMElement} node input/textarea to focus 15211 */ 15212 function focusNode(node) { 15213 if (!node.disabled) { 15214 node.focus(); 15215 } 15216 } 15217 15218 module.exports = focusNode; 15219 15220 },{}],101:[function(_dereq_,module,exports){ 15221 /** 15222 * Copyright 2013-2014 Facebook, Inc. 15223 * 15224 * Licensed under the Apache License, Version 2.0 (the "License"); 15225 * you may not use this file except in compliance with the License. 15226 * You may obtain a copy of the License at 15227 * 15228 * http://www.apache.org/licenses/LICENSE-2.0 15229 * 15230 * Unless required by applicable law or agreed to in writing, software 15231 * distributed under the License is distributed on an "AS IS" BASIS, 15232 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15233 * See the License for the specific language governing permissions and 15234 * limitations under the License. 15235 * 15236 * @providesModule forEachAccumulated 15237 */ 15238 15239 "use strict"; 15240 15241 /** 15242 * @param {array} an "accumulation" of items which is either an Array or 15243 * a single item. Useful when paired with the `accumulate` module. This is a 15244 * simple utility that allows us to reason about a collection of items, but 15245 * handling the case when there is exactly one item (and we do not need to 15246 * allocate an array). 15247 */ 15248 var forEachAccumulated = function(arr, cb, scope) { 15249 if (Array.isArray(arr)) { 15250 arr.forEach(cb, scope); 15251 } else if (arr) { 15252 cb.call(scope, arr); 15253 } 15254 }; 15255 15256 module.exports = forEachAccumulated; 15257 15258 },{}],102:[function(_dereq_,module,exports){ 15259 /** 15260 * Copyright 2013-2014 Facebook, Inc. 15261 * 15262 * Licensed under the Apache License, Version 2.0 (the "License"); 15263 * you may not use this file except in compliance with the License. 15264 * You may obtain a copy of the License at 15265 * 15266 * http://www.apache.org/licenses/LICENSE-2.0 15267 * 15268 * Unless required by applicable law or agreed to in writing, software 15269 * distributed under the License is distributed on an "AS IS" BASIS, 15270 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15271 * See the License for the specific language governing permissions and 15272 * limitations under the License. 15273 * 15274 * @providesModule getActiveElement 15275 * @typechecks 15276 */ 15277 15278 /** 15279 * Same as document.activeElement but wraps in a try-catch block. In IE it is 15280 * not safe to call document.activeElement if there is nothing focused. 15281 * 15282 * The activeElement will be null only if the document body is not yet defined. 15283 */ 15284 function getActiveElement() /*?DOMElement*/ { 15285 try { 15286 return document.activeElement || document.body; 15287 } catch (e) { 15288 return document.body; 15289 } 15290 } 15291 15292 module.exports = getActiveElement; 15293 15294 },{}],103:[function(_dereq_,module,exports){ 15295 /** 15296 * Copyright 2013-2014 Facebook, Inc. 15297 * 15298 * Licensed under the Apache License, Version 2.0 (the "License"); 15299 * you may not use this file except in compliance with the License. 15300 * You may obtain a copy of the License at 15301 * 15302 * http://www.apache.org/licenses/LICENSE-2.0 15303 * 15304 * Unless required by applicable law or agreed to in writing, software 15305 * distributed under the License is distributed on an "AS IS" BASIS, 15306 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15307 * See the License for the specific language governing permissions and 15308 * limitations under the License. 15309 * 15310 * @providesModule getEventKey 15311 * @typechecks static-only 15312 */ 15313 15314 "use strict"; 15315 15316 /** 15317 * Normalization of deprecated HTML5 "key" values 15318 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 15319 */ 15320 var normalizeKey = { 15321 'Esc': 'Escape', 15322 'Spacebar': ' ', 15323 'Left': 'ArrowLeft', 15324 'Up': 'ArrowUp', 15325 'Right': 'ArrowRight', 15326 'Down': 'ArrowDown', 15327 'Del': 'Delete', 15328 'Win': 'OS', 15329 'Menu': 'ContextMenu', 15330 'Apps': 'ContextMenu', 15331 'Scroll': 'ScrollLock', 15332 'MozPrintableKey': 'Unidentified' 15333 }; 15334 15335 /** 15336 * Translation from legacy "which/keyCode" to HTML5 "key" 15337 * Only special keys supported, all others depend on keyboard layout or browser 15338 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names 15339 */ 15340 var translateToKey = { 15341 8: 'Backspace', 15342 9: 'Tab', 15343 12: 'Clear', 15344 13: 'Enter', 15345 16: 'Shift', 15346 17: 'Control', 15347 18: 'Alt', 15348 19: 'Pause', 15349 20: 'CapsLock', 15350 27: 'Escape', 15351 32: ' ', 15352 33: 'PageUp', 15353 34: 'PageDown', 15354 35: 'End', 15355 36: 'Home', 15356 37: 'ArrowLeft', 15357 38: 'ArrowUp', 15358 39: 'ArrowRight', 15359 40: 'ArrowDown', 15360 45: 'Insert', 15361 46: 'Delete', 15362 112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6', 15363 118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12', 15364 144: 'NumLock', 15365 145: 'ScrollLock', 15366 224: 'Meta' 15367 }; 15368 15369 /** 15370 * @param {object} nativeEvent Native browser event. 15371 * @return {string} Normalized `key` property. 15372 */ 15373 function getEventKey(nativeEvent) { 15374 return 'key' in nativeEvent ? 15375 normalizeKey[nativeEvent.key] || nativeEvent.key : 15376 translateToKey[nativeEvent.which || nativeEvent.keyCode] || 'Unidentified'; 15377 } 15378 15379 module.exports = getEventKey; 15380 15381 },{}],104:[function(_dereq_,module,exports){ 15382 /** 15383 * Copyright 2013-2014 Facebook, Inc. 15384 * 15385 * Licensed under the Apache License, Version 2.0 (the "License"); 15386 * you may not use this file except in compliance with the License. 15387 * You may obtain a copy of the License at 15388 * 15389 * http://www.apache.org/licenses/LICENSE-2.0 15390 * 15391 * Unless required by applicable law or agreed to in writing, software 15392 * distributed under the License is distributed on an "AS IS" BASIS, 15393 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15394 * See the License for the specific language governing permissions and 15395 * limitations under the License. 15396 * 15397 * @providesModule getEventTarget 15398 * @typechecks static-only 15399 */ 15400 15401 "use strict"; 15402 15403 /** 15404 * Gets the target node from a native browser event by accounting for 15405 * inconsistencies in browser DOM APIs. 15406 * 15407 * @param {object} nativeEvent Native browser event. 15408 * @return {DOMEventTarget} Target node. 15409 */ 15410 function getEventTarget(nativeEvent) { 15411 var target = nativeEvent.target || nativeEvent.srcElement || window; 15412 // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 15413 // @see http://www.quirksmode.org/js/events_properties.html 15414 return target.nodeType === 3 ? target.parentNode : target; 15415 } 15416 15417 module.exports = getEventTarget; 15418 15419 },{}],105:[function(_dereq_,module,exports){ 15420 /** 15421 * Copyright 2013-2014 Facebook, Inc. 15422 * 15423 * Licensed under the Apache License, Version 2.0 (the "License"); 15424 * you may not use this file except in compliance with the License. 15425 * You may obtain a copy of the License at 15426 * 15427 * http://www.apache.org/licenses/LICENSE-2.0 15428 * 15429 * Unless required by applicable law or agreed to in writing, software 15430 * distributed under the License is distributed on an "AS IS" BASIS, 15431 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15432 * See the License for the specific language governing permissions and 15433 * limitations under the License. 15434 * 15435 * @providesModule getMarkupWrap 15436 */ 15437 15438 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 15439 15440 var invariant = _dereq_("./invariant"); 15441 15442 /** 15443 * Dummy container used to detect which wraps are necessary. 15444 */ 15445 var dummyNode = 15446 ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 15447 15448 /** 15449 * Some browsers cannot use `innerHTML` to render certain elements standalone, 15450 * so we wrap them, render the wrapped nodes, then extract the desired node. 15451 * 15452 * In IE8, certain elements cannot render alone, so wrap all elements ('*'). 15453 */ 15454 var shouldWrap = { 15455 // Force wrapping for SVG elements because if they get created inside a <div>, 15456 // they will be initialized in the wrong namespace (and will not display). 15457 'circle': true, 15458 'defs': true, 15459 'g': true, 15460 'line': true, 15461 'linearGradient': true, 15462 'path': true, 15463 'polygon': true, 15464 'polyline': true, 15465 'radialGradient': true, 15466 'rect': true, 15467 'stop': true, 15468 'text': true 15469 }; 15470 15471 var selectWrap = [1, '<select multiple="true">', '</select>']; 15472 var tableWrap = [1, '<table>', '</table>']; 15473 var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>']; 15474 15475 var svgWrap = [1, '<svg>', '</svg>']; 15476 15477 var markupWrap = { 15478 '*': [1, '?<div>', '</div>'], 15479 15480 'area': [1, '<map>', '</map>'], 15481 'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'], 15482 'legend': [1, '<fieldset>', '</fieldset>'], 15483 'param': [1, '<object>', '</object>'], 15484 'tr': [2, '<table><tbody>', '</tbody></table>'], 15485 15486 'optgroup': selectWrap, 15487 'option': selectWrap, 15488 15489 'caption': tableWrap, 15490 'colgroup': tableWrap, 15491 'tbody': tableWrap, 15492 'tfoot': tableWrap, 15493 'thead': tableWrap, 15494 15495 'td': trWrap, 15496 'th': trWrap, 15497 15498 'circle': svgWrap, 15499 'defs': svgWrap, 15500 'g': svgWrap, 15501 'line': svgWrap, 15502 'linearGradient': svgWrap, 15503 'path': svgWrap, 15504 'polygon': svgWrap, 15505 'polyline': svgWrap, 15506 'radialGradient': svgWrap, 15507 'rect': svgWrap, 15508 'stop': svgWrap, 15509 'text': svgWrap 15510 }; 15511 15512 /** 15513 * Gets the markup wrap configuration for the supplied `nodeName`. 15514 * 15515 * NOTE: This lazily detects which wraps are necessary for the current browser. 15516 * 15517 * @param {string} nodeName Lowercase `nodeName`. 15518 * @return {?array} Markup wrap configuration, if applicable. 15519 */ 15520 function getMarkupWrap(nodeName) { 15521 ("production" !== "development" ? invariant(!!dummyNode, 'Markup wrapping node not initialized') : invariant(!!dummyNode)); 15522 if (!markupWrap.hasOwnProperty(nodeName)) { 15523 nodeName = '*'; 15524 } 15525 if (!shouldWrap.hasOwnProperty(nodeName)) { 15526 if (nodeName === '*') { 15527 dummyNode.innerHTML = '<link />'; 15528 } else { 15529 dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>'; 15530 } 15531 shouldWrap[nodeName] = !dummyNode.firstChild; 15532 } 15533 return shouldWrap[nodeName] ? markupWrap[nodeName] : null; 15534 } 15535 15536 15537 module.exports = getMarkupWrap; 15538 15539 },{"./ExecutionEnvironment":20,"./invariant":112}],106:[function(_dereq_,module,exports){ 15540 /** 15541 * Copyright 2013-2014 Facebook, Inc. 15542 * 15543 * Licensed under the Apache License, Version 2.0 (the "License"); 15544 * you may not use this file except in compliance with the License. 15545 * You may obtain a copy of the License at 15546 * 15547 * http://www.apache.org/licenses/LICENSE-2.0 15548 * 15549 * Unless required by applicable law or agreed to in writing, software 15550 * distributed under the License is distributed on an "AS IS" BASIS, 15551 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15552 * See the License for the specific language governing permissions and 15553 * limitations under the License. 15554 * 15555 * @providesModule getNodeForCharacterOffset 15556 */ 15557 15558 "use strict"; 15559 15560 /** 15561 * Given any node return the first leaf node without children. 15562 * 15563 * @param {DOMElement|DOMTextNode} node 15564 * @return {DOMElement|DOMTextNode} 15565 */ 15566 function getLeafNode(node) { 15567 while (node && node.firstChild) { 15568 node = node.firstChild; 15569 } 15570 return node; 15571 } 15572 15573 /** 15574 * Get the next sibling within a container. This will walk up the 15575 * DOM if a node's siblings have been exhausted. 15576 * 15577 * @param {DOMElement|DOMTextNode} node 15578 * @return {?DOMElement|DOMTextNode} 15579 */ 15580 function getSiblingNode(node) { 15581 while (node) { 15582 if (node.nextSibling) { 15583 return node.nextSibling; 15584 } 15585 node = node.parentNode; 15586 } 15587 } 15588 15589 /** 15590 * Get object describing the nodes which contain characters at offset. 15591 * 15592 * @param {DOMElement|DOMTextNode} root 15593 * @param {number} offset 15594 * @return {?object} 15595 */ 15596 function getNodeForCharacterOffset(root, offset) { 15597 var node = getLeafNode(root); 15598 var nodeStart = 0; 15599 var nodeEnd = 0; 15600 15601 while (node) { 15602 if (node.nodeType == 3) { 15603 nodeEnd = nodeStart + node.textContent.length; 15604 15605 if (nodeStart <= offset && nodeEnd >= offset) { 15606 return { 15607 node: node, 15608 offset: offset - nodeStart 15609 }; 15610 } 15611 15612 nodeStart = nodeEnd; 15613 } 15614 15615 node = getLeafNode(getSiblingNode(node)); 15616 } 15617 } 15618 15619 module.exports = getNodeForCharacterOffset; 15620 15621 },{}],107:[function(_dereq_,module,exports){ 15622 /** 15623 * Copyright 2013-2014 Facebook, Inc. 15624 * 15625 * Licensed under the Apache License, Version 2.0 (the "License"); 15626 * you may not use this file except in compliance with the License. 15627 * You may obtain a copy of the License at 15628 * 15629 * http://www.apache.org/licenses/LICENSE-2.0 15630 * 15631 * Unless required by applicable law or agreed to in writing, software 15632 * distributed under the License is distributed on an "AS IS" BASIS, 15633 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15634 * See the License for the specific language governing permissions and 15635 * limitations under the License. 15636 * 15637 * @providesModule getReactRootElementInContainer 15638 */ 15639 15640 "use strict"; 15641 15642 var DOC_NODE_TYPE = 9; 15643 15644 /** 15645 * @param {DOMElement|DOMDocument} container DOM element that may contain 15646 * a React component 15647 * @return {?*} DOM element that may have the reactRoot ID, or null. 15648 */ 15649 function getReactRootElementInContainer(container) { 15650 if (!container) { 15651 return null; 15652 } 15653 15654 if (container.nodeType === DOC_NODE_TYPE) { 15655 return container.documentElement; 15656 } else { 15657 return container.firstChild; 15658 } 15659 } 15660 15661 module.exports = getReactRootElementInContainer; 15662 15663 },{}],108:[function(_dereq_,module,exports){ 15664 /** 15665 * Copyright 2013-2014 Facebook, Inc. 15666 * 15667 * Licensed under the Apache License, Version 2.0 (the "License"); 15668 * you may not use this file except in compliance with the License. 15669 * You may obtain a copy of the License at 15670 * 15671 * http://www.apache.org/licenses/LICENSE-2.0 15672 * 15673 * Unless required by applicable law or agreed to in writing, software 15674 * distributed under the License is distributed on an "AS IS" BASIS, 15675 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15676 * See the License for the specific language governing permissions and 15677 * limitations under the License. 15678 * 15679 * @providesModule getTextContentAccessor 15680 */ 15681 15682 "use strict"; 15683 15684 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 15685 15686 var contentKey = null; 15687 15688 /** 15689 * Gets the key used to access text content on a DOM node. 15690 * 15691 * @return {?string} Key used to access text content. 15692 * @internal 15693 */ 15694 function getTextContentAccessor() { 15695 if (!contentKey && ExecutionEnvironment.canUseDOM) { 15696 // Prefer textContent to innerText because many browsers support both but 15697 // SVG <text> elements don't support innerText even when <div> does. 15698 contentKey = 'textContent' in document.createElement('div') ? 15699 'textContent' : 15700 'innerText'; 15701 } 15702 return contentKey; 15703 } 15704 15705 module.exports = getTextContentAccessor; 15706 15707 },{"./ExecutionEnvironment":20}],109:[function(_dereq_,module,exports){ 15708 /** 15709 * Copyright 2013-2014 Facebook, Inc. 15710 * 15711 * Licensed under the Apache License, Version 2.0 (the "License"); 15712 * you may not use this file except in compliance with the License. 15713 * You may obtain a copy of the License at 15714 * 15715 * http://www.apache.org/licenses/LICENSE-2.0 15716 * 15717 * Unless required by applicable law or agreed to in writing, software 15718 * distributed under the License is distributed on an "AS IS" BASIS, 15719 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15720 * See the License for the specific language governing permissions and 15721 * limitations under the License. 15722 * 15723 * @providesModule getUnboundedScrollPosition 15724 * @typechecks 15725 */ 15726 15727 "use strict"; 15728 15729 /** 15730 * Gets the scroll position of the supplied element or window. 15731 * 15732 * The return values are unbounded, unlike `getScrollPosition`. This means they 15733 * may be negative or exceed the element boundaries (which is possible using 15734 * inertial scrolling). 15735 * 15736 * @param {DOMWindow|DOMElement} scrollable 15737 * @return {object} Map with `x` and `y` keys. 15738 */ 15739 function getUnboundedScrollPosition(scrollable) { 15740 if (scrollable === window) { 15741 return { 15742 x: window.pageXOffset || document.documentElement.scrollLeft, 15743 y: window.pageYOffset || document.documentElement.scrollTop 15744 }; 15745 } 15746 return { 15747 x: scrollable.scrollLeft, 15748 y: scrollable.scrollTop 15749 }; 15750 } 15751 15752 module.exports = getUnboundedScrollPosition; 15753 15754 },{}],110:[function(_dereq_,module,exports){ 15755 /** 15756 * Copyright 2013-2014 Facebook, Inc. 15757 * 15758 * Licensed under the Apache License, Version 2.0 (the "License"); 15759 * you may not use this file except in compliance with the License. 15760 * You may obtain a copy of the License at 15761 * 15762 * http://www.apache.org/licenses/LICENSE-2.0 15763 * 15764 * Unless required by applicable law or agreed to in writing, software 15765 * distributed under the License is distributed on an "AS IS" BASIS, 15766 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15767 * See the License for the specific language governing permissions and 15768 * limitations under the License. 15769 * 15770 * @providesModule hyphenate 15771 * @typechecks 15772 */ 15773 15774 var _uppercasePattern = /([A-Z])/g; 15775 15776 /** 15777 * Hyphenates a camelcased string, for example: 15778 * 15779 * > hyphenate('backgroundColor') 15780 * < "background-color" 15781 * 15782 * @param {string} string 15783 * @return {string} 15784 */ 15785 function hyphenate(string) { 15786 return string.replace(_uppercasePattern, '-$1').toLowerCase(); 15787 } 15788 15789 module.exports = hyphenate; 15790 15791 },{}],111:[function(_dereq_,module,exports){ 15792 /** 15793 * Copyright 2013-2014 Facebook, Inc. 15794 * 15795 * Licensed under the Apache License, Version 2.0 (the "License"); 15796 * you may not use this file except in compliance with the License. 15797 * You may obtain a copy of the License at 15798 * 15799 * http://www.apache.org/licenses/LICENSE-2.0 15800 * 15801 * Unless required by applicable law or agreed to in writing, software 15802 * distributed under the License is distributed on an "AS IS" BASIS, 15803 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15804 * See the License for the specific language governing permissions and 15805 * limitations under the License. 15806 * 15807 * @providesModule instantiateReactComponent 15808 * @typechecks static-only 15809 */ 15810 15811 "use strict"; 15812 15813 var warning = _dereq_("./warning"); 15814 15815 /** 15816 * Validate a `componentDescriptor`. This should be exposed publicly in a follow 15817 * up diff. 15818 * 15819 * @param {object} descriptor 15820 * @return {boolean} Returns true if this is a valid descriptor of a Component. 15821 */ 15822 function isValidComponentDescriptor(descriptor) { 15823 return ( 15824 typeof descriptor.constructor === 'function' && 15825 typeof descriptor.constructor.prototype.construct === 'function' && 15826 typeof descriptor.constructor.prototype.mountComponent === 'function' && 15827 typeof descriptor.constructor.prototype.receiveComponent === 'function' 15828 ); 15829 } 15830 15831 /** 15832 * Given a `componentDescriptor` create an instance that will actually be 15833 * mounted. Currently it just extracts an existing clone from composite 15834 * components but this is an implementation detail which will change. 15835 * 15836 * @param {object} descriptor 15837 * @return {object} A new instance of componentDescriptor's constructor. 15838 * @protected 15839 */ 15840 function instantiateReactComponent(descriptor) { 15841 if ("production" !== "development") { 15842 ("production" !== "development" ? warning( 15843 isValidComponentDescriptor(descriptor), 15844 'Only React Components are valid for mounting.' 15845 ) : null); 15846 // We use the clone of a composite component instead of the original 15847 // instance. This allows us to warn you if you're are accessing the wrong 15848 // instance. 15849 var instance = descriptor.__realComponentInstance || descriptor; 15850 instance._descriptor = descriptor; 15851 return instance; 15852 } 15853 // In prod we don't clone, we simply use the same instance for unaffected 15854 // behavior. We have to keep the descriptor around for comparison later on. 15855 // This should ideally be accepted in the constructor of the instance but 15856 // since that is currently overloaded, we just manually attach it here. 15857 descriptor._descriptor = descriptor; 15858 return descriptor; 15859 } 15860 15861 module.exports = instantiateReactComponent; 15862 15863 },{"./warning":134}],112:[function(_dereq_,module,exports){ 15864 /** 15865 * Copyright 2013-2014 Facebook, Inc. 15866 * 15867 * Licensed under the Apache License, Version 2.0 (the "License"); 15868 * you may not use this file except in compliance with the License. 15869 * You may obtain a copy of the License at 15870 * 15871 * http://www.apache.org/licenses/LICENSE-2.0 15872 * 15873 * Unless required by applicable law or agreed to in writing, software 15874 * distributed under the License is distributed on an "AS IS" BASIS, 15875 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15876 * See the License for the specific language governing permissions and 15877 * limitations under the License. 15878 * 15879 * @providesModule invariant 15880 */ 15881 15882 "use strict"; 15883 15884 /** 15885 * Use invariant() to assert state which your program assumes to be true. 15886 * 15887 * Provide sprintf-style format (only %s is supported) and arguments 15888 * to provide information about what broke and what you were 15889 * expecting. 15890 * 15891 * The invariant message will be stripped in production, but the invariant 15892 * will remain to ensure logic does not differ in production. 15893 */ 15894 15895 var invariant = function(condition) { 15896 if (!condition) { 15897 var error = new Error( 15898 'Minified exception occured; use the non-minified dev environment for ' + 15899 'the full error message and additional helpful warnings.' 15900 ); 15901 error.framesToPop = 1; 15902 throw error; 15903 } 15904 }; 15905 15906 if ("production" !== "development") { 15907 invariant = function(condition, format, a, b, c, d, e, f) { 15908 if (format === undefined) { 15909 throw new Error('invariant requires an error message argument'); 15910 } 15911 15912 if (!condition) { 15913 var args = [a, b, c, d, e, f]; 15914 var argIndex = 0; 15915 var error = new Error( 15916 'Invariant Violation: ' + 15917 format.replace(/%s/g, function() { return args[argIndex++]; }) 15918 ); 15919 error.framesToPop = 1; // we don't care about invariant's own frame 15920 throw error; 15921 } 15922 }; 15923 } 15924 15925 module.exports = invariant; 15926 15927 },{}],113:[function(_dereq_,module,exports){ 15928 /** 15929 * Copyright 2013-2014 Facebook, Inc. 15930 * 15931 * Licensed under the Apache License, Version 2.0 (the "License"); 15932 * you may not use this file except in compliance with the License. 15933 * You may obtain a copy of the License at 15934 * 15935 * http://www.apache.org/licenses/LICENSE-2.0 15936 * 15937 * Unless required by applicable law or agreed to in writing, software 15938 * distributed under the License is distributed on an "AS IS" BASIS, 15939 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15940 * See the License for the specific language governing permissions and 15941 * limitations under the License. 15942 * 15943 * @providesModule isEventSupported 15944 */ 15945 15946 "use strict"; 15947 15948 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 15949 15950 var useHasFeature; 15951 if (ExecutionEnvironment.canUseDOM) { 15952 useHasFeature = 15953 document.implementation && 15954 document.implementation.hasFeature && 15955 // always returns true in newer browsers as per the standard. 15956 // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature 15957 document.implementation.hasFeature('', '') !== true; 15958 } 15959 15960 /** 15961 * Checks if an event is supported in the current execution environment. 15962 * 15963 * NOTE: This will not work correctly for non-generic events such as `change`, 15964 * `reset`, `load`, `error`, and `select`. 15965 * 15966 * Borrows from Modernizr. 15967 * 15968 * @param {string} eventNameSuffix Event name, e.g. "click". 15969 * @param {?boolean} capture Check if the capture phase is supported. 15970 * @return {boolean} True if the event is supported. 15971 * @internal 15972 * @license Modernizr 3.0.0pre (Custom Build) | MIT 15973 */ 15974 function isEventSupported(eventNameSuffix, capture) { 15975 if (!ExecutionEnvironment.canUseDOM || 15976 capture && !('addEventListener' in document)) { 15977 return false; 15978 } 15979 15980 var eventName = 'on' + eventNameSuffix; 15981 var isSupported = eventName in document; 15982 15983 if (!isSupported) { 15984 var element = document.createElement('div'); 15985 element.setAttribute(eventName, 'return;'); 15986 isSupported = typeof element[eventName] === 'function'; 15987 } 15988 15989 if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') { 15990 // This is the only way to test support for the `wheel` event in IE9+. 15991 isSupported = document.implementation.hasFeature('Events.wheel', '3.0'); 15992 } 15993 15994 return isSupported; 15995 } 15996 15997 module.exports = isEventSupported; 15998 15999 },{"./ExecutionEnvironment":20}],114:[function(_dereq_,module,exports){ 16000 /** 16001 * Copyright 2013-2014 Facebook, Inc. 16002 * 16003 * Licensed under the Apache License, Version 2.0 (the "License"); 16004 * you may not use this file except in compliance with the License. 16005 * You may obtain a copy of the License at 16006 * 16007 * http://www.apache.org/licenses/LICENSE-2.0 16008 * 16009 * Unless required by applicable law or agreed to in writing, software 16010 * distributed under the License is distributed on an "AS IS" BASIS, 16011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16012 * See the License for the specific language governing permissions and 16013 * limitations under the License. 16014 * 16015 * @providesModule isNode 16016 * @typechecks 16017 */ 16018 16019 /** 16020 * @param {*} object The object to check. 16021 * @return {boolean} Whether or not the object is a DOM node. 16022 */ 16023 function isNode(object) { 16024 return !!(object && ( 16025 typeof Node === 'function' ? object instanceof Node : 16026 typeof object === 'object' && 16027 typeof object.nodeType === 'number' && 16028 typeof object.nodeName === 'string' 16029 )); 16030 } 16031 16032 module.exports = isNode; 16033 16034 },{}],115:[function(_dereq_,module,exports){ 16035 /** 16036 * Copyright 2013-2014 Facebook, Inc. 16037 * 16038 * Licensed under the Apache License, Version 2.0 (the "License"); 16039 * you may not use this file except in compliance with the License. 16040 * You may obtain a copy of the License at 16041 * 16042 * http://www.apache.org/licenses/LICENSE-2.0 16043 * 16044 * Unless required by applicable law or agreed to in writing, software 16045 * distributed under the License is distributed on an "AS IS" BASIS, 16046 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16047 * See the License for the specific language governing permissions and 16048 * limitations under the License. 16049 * 16050 * @providesModule isTextInputElement 16051 */ 16052 16053 "use strict"; 16054 16055 /** 16056 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 16057 */ 16058 var supportedInputTypes = { 16059 'color': true, 16060 'date': true, 16061 'datetime': true, 16062 'datetime-local': true, 16063 'email': true, 16064 'month': true, 16065 'number': true, 16066 'password': true, 16067 'range': true, 16068 'search': true, 16069 'tel': true, 16070 'text': true, 16071 'time': true, 16072 'url': true, 16073 'week': true 16074 }; 16075 16076 function isTextInputElement(elem) { 16077 return elem && ( 16078 (elem.nodeName === 'INPUT' && supportedInputTypes[elem.type]) || 16079 elem.nodeName === 'TEXTAREA' 16080 ); 16081 } 16082 16083 module.exports = isTextInputElement; 16084 16085 },{}],116:[function(_dereq_,module,exports){ 16086 /** 16087 * Copyright 2013-2014 Facebook, Inc. 16088 * 16089 * Licensed under the Apache License, Version 2.0 (the "License"); 16090 * you may not use this file except in compliance with the License. 16091 * You may obtain a copy of the License at 16092 * 16093 * http://www.apache.org/licenses/LICENSE-2.0 16094 * 16095 * Unless required by applicable law or agreed to in writing, software 16096 * distributed under the License is distributed on an "AS IS" BASIS, 16097 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16098 * See the License for the specific language governing permissions and 16099 * limitations under the License. 16100 * 16101 * @providesModule isTextNode 16102 * @typechecks 16103 */ 16104 16105 var isNode = _dereq_("./isNode"); 16106 16107 /** 16108 * @param {*} object The object to check. 16109 * @return {boolean} Whether or not the object is a DOM text node. 16110 */ 16111 function isTextNode(object) { 16112 return isNode(object) && object.nodeType == 3; 16113 } 16114 16115 module.exports = isTextNode; 16116 16117 },{"./isNode":114}],117:[function(_dereq_,module,exports){ 16118 /** 16119 * Copyright 2013-2014 Facebook, Inc. 16120 * 16121 * Licensed under the Apache License, Version 2.0 (the "License"); 16122 * you may not use this file except in compliance with the License. 16123 * You may obtain a copy of the License at 16124 * 16125 * http://www.apache.org/licenses/LICENSE-2.0 16126 * 16127 * Unless required by applicable law or agreed to in writing, software 16128 * distributed under the License is distributed on an "AS IS" BASIS, 16129 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16130 * See the License for the specific language governing permissions and 16131 * limitations under the License. 16132 * 16133 * @providesModule joinClasses 16134 * @typechecks static-only 16135 */ 16136 16137 "use strict"; 16138 16139 /** 16140 * Combines multiple className strings into one. 16141 * http://jsperf.com/joinclasses-args-vs-array 16142 * 16143 * @param {...?string} classes 16144 * @return {string} 16145 */ 16146 function joinClasses(className/*, ... */) { 16147 if (!className) { 16148 className = ''; 16149 } 16150 var nextClass; 16151 var argLength = arguments.length; 16152 if (argLength > 1) { 16153 for (var ii = 1; ii < argLength; ii++) { 16154 nextClass = arguments[ii]; 16155 nextClass && (className += ' ' + nextClass); 16156 } 16157 } 16158 return className; 16159 } 16160 16161 module.exports = joinClasses; 16162 16163 },{}],118:[function(_dereq_,module,exports){ 16164 /** 16165 * Copyright 2013-2014 Facebook, Inc. 16166 * 16167 * Licensed under the Apache License, Version 2.0 (the "License"); 16168 * you may not use this file except in compliance with the License. 16169 * You may obtain a copy of the License at 16170 * 16171 * http://www.apache.org/licenses/LICENSE-2.0 16172 * 16173 * Unless required by applicable law or agreed to in writing, software 16174 * distributed under the License is distributed on an "AS IS" BASIS, 16175 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16176 * See the License for the specific language governing permissions and 16177 * limitations under the License. 16178 * 16179 * @providesModule keyMirror 16180 * @typechecks static-only 16181 */ 16182 16183 "use strict"; 16184 16185 var invariant = _dereq_("./invariant"); 16186 16187 /** 16188 * Constructs an enumeration with keys equal to their value. 16189 * 16190 * For example: 16191 * 16192 * var COLORS = keyMirror({blue: null, red: null}); 16193 * var myColor = COLORS.blue; 16194 * var isColorValid = !!COLORS[myColor]; 16195 * 16196 * The last line could not be performed if the values of the generated enum were 16197 * not equal to their keys. 16198 * 16199 * Input: {key1: val1, key2: val2} 16200 * Output: {key1: key1, key2: key2} 16201 * 16202 * @param {object} obj 16203 * @return {object} 16204 */ 16205 var keyMirror = function(obj) { 16206 var ret = {}; 16207 var key; 16208 ("production" !== "development" ? invariant( 16209 obj instanceof Object && !Array.isArray(obj), 16210 'keyMirror(...): Argument must be an object.' 16211 ) : invariant(obj instanceof Object && !Array.isArray(obj))); 16212 for (key in obj) { 16213 if (!obj.hasOwnProperty(key)) { 16214 continue; 16215 } 16216 ret[key] = key; 16217 } 16218 return ret; 16219 }; 16220 16221 module.exports = keyMirror; 16222 16223 },{"./invariant":112}],119:[function(_dereq_,module,exports){ 16224 /** 16225 * Copyright 2013-2014 Facebook, Inc. 16226 * 16227 * Licensed under the Apache License, Version 2.0 (the "License"); 16228 * you may not use this file except in compliance with the License. 16229 * You may obtain a copy of the License at 16230 * 16231 * http://www.apache.org/licenses/LICENSE-2.0 16232 * 16233 * Unless required by applicable law or agreed to in writing, software 16234 * distributed under the License is distributed on an "AS IS" BASIS, 16235 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16236 * See the License for the specific language governing permissions and 16237 * limitations under the License. 16238 * 16239 * @providesModule keyOf 16240 */ 16241 16242 /** 16243 * Allows extraction of a minified key. Let's the build system minify keys 16244 * without loosing the ability to dynamically use key strings as values 16245 * themselves. Pass in an object with a single key/val pair and it will return 16246 * you the string key of that single record. Suppose you want to grab the 16247 * value for a key 'className' inside of an object. Key/val minification may 16248 * have aliased that key to be 'xa12'. keyOf({className: null}) will return 16249 * 'xa12' in that case. Resolve keys you want to use once at startup time, then 16250 * reuse those resolutions. 16251 */ 16252 var keyOf = function(oneKeyObj) { 16253 var key; 16254 for (key in oneKeyObj) { 16255 if (!oneKeyObj.hasOwnProperty(key)) { 16256 continue; 16257 } 16258 return key; 16259 } 16260 return null; 16261 }; 16262 16263 16264 module.exports = keyOf; 16265 16266 },{}],120:[function(_dereq_,module,exports){ 16267 /** 16268 * Copyright 2013-2014 Facebook, Inc. 16269 * 16270 * Licensed under the Apache License, Version 2.0 (the "License"); 16271 * you may not use this file except in compliance with the License. 16272 * You may obtain a copy of the License at 16273 * 16274 * http://www.apache.org/licenses/LICENSE-2.0 16275 * 16276 * Unless required by applicable law or agreed to in writing, software 16277 * distributed under the License is distributed on an "AS IS" BASIS, 16278 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16279 * See the License for the specific language governing permissions and 16280 * limitations under the License. 16281 * 16282 * @providesModule memoizeStringOnly 16283 * @typechecks static-only 16284 */ 16285 16286 "use strict"; 16287 16288 /** 16289 * Memoizes the return value of a function that accepts one string argument. 16290 * 16291 * @param {function} callback 16292 * @return {function} 16293 */ 16294 function memoizeStringOnly(callback) { 16295 var cache = {}; 16296 return function(string) { 16297 if (cache.hasOwnProperty(string)) { 16298 return cache[string]; 16299 } else { 16300 return cache[string] = callback.call(this, string); 16301 } 16302 }; 16303 } 16304 16305 module.exports = memoizeStringOnly; 16306 16307 },{}],121:[function(_dereq_,module,exports){ 16308 /** 16309 * Copyright 2013-2014 Facebook, Inc. 16310 * 16311 * Licensed under the Apache License, Version 2.0 (the "License"); 16312 * you may not use this file except in compliance with the License. 16313 * You may obtain a copy of the License at 16314 * 16315 * http://www.apache.org/licenses/LICENSE-2.0 16316 * 16317 * Unless required by applicable law or agreed to in writing, software 16318 * distributed under the License is distributed on an "AS IS" BASIS, 16319 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16320 * See the License for the specific language governing permissions and 16321 * limitations under the License. 16322 * 16323 * @providesModule merge 16324 */ 16325 16326 "use strict"; 16327 16328 var mergeInto = _dereq_("./mergeInto"); 16329 16330 /** 16331 * Shallow merges two structures into a return value, without mutating either. 16332 * 16333 * @param {?object} one Optional object with properties to merge from. 16334 * @param {?object} two Optional object with properties to merge from. 16335 * @return {object} The shallow extension of one by two. 16336 */ 16337 var merge = function(one, two) { 16338 var result = {}; 16339 mergeInto(result, one); 16340 mergeInto(result, two); 16341 return result; 16342 }; 16343 16344 module.exports = merge; 16345 16346 },{"./mergeInto":123}],122:[function(_dereq_,module,exports){ 16347 /** 16348 * Copyright 2013-2014 Facebook, Inc. 16349 * 16350 * Licensed under the Apache License, Version 2.0 (the "License"); 16351 * you may not use this file except in compliance with the License. 16352 * You may obtain a copy of the License at 16353 * 16354 * http://www.apache.org/licenses/LICENSE-2.0 16355 * 16356 * Unless required by applicable law or agreed to in writing, software 16357 * distributed under the License is distributed on an "AS IS" BASIS, 16358 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16359 * See the License for the specific language governing permissions and 16360 * limitations under the License. 16361 * 16362 * @providesModule mergeHelpers 16363 * 16364 * requiresPolyfills: Array.isArray 16365 */ 16366 16367 "use strict"; 16368 16369 var invariant = _dereq_("./invariant"); 16370 var keyMirror = _dereq_("./keyMirror"); 16371 16372 /** 16373 * Maximum number of levels to traverse. Will catch circular structures. 16374 * @const 16375 */ 16376 var MAX_MERGE_DEPTH = 36; 16377 16378 /** 16379 * We won't worry about edge cases like new String('x') or new Boolean(true). 16380 * Functions are considered terminals, and arrays are not. 16381 * @param {*} o The item/object/value to test. 16382 * @return {boolean} true iff the argument is a terminal. 16383 */ 16384 var isTerminal = function(o) { 16385 return typeof o !== 'object' || o === null; 16386 }; 16387 16388 var mergeHelpers = { 16389 16390 MAX_MERGE_DEPTH: MAX_MERGE_DEPTH, 16391 16392 isTerminal: isTerminal, 16393 16394 /** 16395 * Converts null/undefined values into empty object. 16396 * 16397 * @param {?Object=} arg Argument to be normalized (nullable optional) 16398 * @return {!Object} 16399 */ 16400 normalizeMergeArg: function(arg) { 16401 return arg === undefined || arg === null ? {} : arg; 16402 }, 16403 16404 /** 16405 * If merging Arrays, a merge strategy *must* be supplied. If not, it is 16406 * likely the caller's fault. If this function is ever called with anything 16407 * but `one` and `two` being `Array`s, it is the fault of the merge utilities. 16408 * 16409 * @param {*} one Array to merge into. 16410 * @param {*} two Array to merge from. 16411 */ 16412 checkMergeArrayArgs: function(one, two) { 16413 ("production" !== "development" ? invariant( 16414 Array.isArray(one) && Array.isArray(two), 16415 'Tried to merge arrays, instead got %s and %s.', 16416 one, 16417 two 16418 ) : invariant(Array.isArray(one) && Array.isArray(two))); 16419 }, 16420 16421 /** 16422 * @param {*} one Object to merge into. 16423 * @param {*} two Object to merge from. 16424 */ 16425 checkMergeObjectArgs: function(one, two) { 16426 mergeHelpers.checkMergeObjectArg(one); 16427 mergeHelpers.checkMergeObjectArg(two); 16428 }, 16429 16430 /** 16431 * @param {*} arg 16432 */ 16433 checkMergeObjectArg: function(arg) { 16434 ("production" !== "development" ? invariant( 16435 !isTerminal(arg) && !Array.isArray(arg), 16436 'Tried to merge an object, instead got %s.', 16437 arg 16438 ) : invariant(!isTerminal(arg) && !Array.isArray(arg))); 16439 }, 16440 16441 /** 16442 * Checks that a merge was not given a circular object or an object that had 16443 * too great of depth. 16444 * 16445 * @param {number} Level of recursion to validate against maximum. 16446 */ 16447 checkMergeLevel: function(level) { 16448 ("production" !== "development" ? invariant( 16449 level < MAX_MERGE_DEPTH, 16450 'Maximum deep merge depth exceeded. You may be attempting to merge ' + 16451 'circular structures in an unsupported way.' 16452 ) : invariant(level < MAX_MERGE_DEPTH)); 16453 }, 16454 16455 /** 16456 * Checks that the supplied merge strategy is valid. 16457 * 16458 * @param {string} Array merge strategy. 16459 */ 16460 checkArrayStrategy: function(strategy) { 16461 ("production" !== "development" ? invariant( 16462 strategy === undefined || strategy in mergeHelpers.ArrayStrategies, 16463 'You must provide an array strategy to deep merge functions to ' + 16464 'instruct the deep merge how to resolve merging two arrays.' 16465 ) : invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies)); 16466 }, 16467 16468 /** 16469 * Set of possible behaviors of merge algorithms when encountering two Arrays 16470 * that must be merged together. 16471 * - `clobber`: The left `Array` is ignored. 16472 * - `indexByIndex`: The result is achieved by recursively deep merging at 16473 * each index. (not yet supported.) 16474 */ 16475 ArrayStrategies: keyMirror({ 16476 Clobber: true, 16477 IndexByIndex: true 16478 }) 16479 16480 }; 16481 16482 module.exports = mergeHelpers; 16483 16484 },{"./invariant":112,"./keyMirror":118}],123:[function(_dereq_,module,exports){ 16485 /** 16486 * Copyright 2013-2014 Facebook, Inc. 16487 * 16488 * Licensed under the Apache License, Version 2.0 (the "License"); 16489 * you may not use this file except in compliance with the License. 16490 * You may obtain a copy of the License at 16491 * 16492 * http://www.apache.org/licenses/LICENSE-2.0 16493 * 16494 * Unless required by applicable law or agreed to in writing, software 16495 * distributed under the License is distributed on an "AS IS" BASIS, 16496 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16497 * See the License for the specific language governing permissions and 16498 * limitations under the License. 16499 * 16500 * @providesModule mergeInto 16501 * @typechecks static-only 16502 */ 16503 16504 "use strict"; 16505 16506 var mergeHelpers = _dereq_("./mergeHelpers"); 16507 16508 var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg; 16509 16510 /** 16511 * Shallow merges two structures by mutating the first parameter. 16512 * 16513 * @param {object} one Object to be merged into. 16514 * @param {?object} two Optional object with properties to merge from. 16515 */ 16516 function mergeInto(one, two) { 16517 checkMergeObjectArg(one); 16518 if (two != null) { 16519 checkMergeObjectArg(two); 16520 for (var key in two) { 16521 if (!two.hasOwnProperty(key)) { 16522 continue; 16523 } 16524 one[key] = two[key]; 16525 } 16526 } 16527 } 16528 16529 module.exports = mergeInto; 16530 16531 },{"./mergeHelpers":122}],124:[function(_dereq_,module,exports){ 16532 /** 16533 * Copyright 2013-2014 Facebook, Inc. 16534 * 16535 * Licensed under the Apache License, Version 2.0 (the "License"); 16536 * you may not use this file except in compliance with the License. 16537 * You may obtain a copy of the License at 16538 * 16539 * http://www.apache.org/licenses/LICENSE-2.0 16540 * 16541 * Unless required by applicable law or agreed to in writing, software 16542 * distributed under the License is distributed on an "AS IS" BASIS, 16543 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16544 * See the License for the specific language governing permissions and 16545 * limitations under the License. 16546 * 16547 * @providesModule mixInto 16548 */ 16549 16550 "use strict"; 16551 16552 /** 16553 * Simply copies properties to the prototype. 16554 */ 16555 var mixInto = function(constructor, methodBag) { 16556 var methodName; 16557 for (methodName in methodBag) { 16558 if (!methodBag.hasOwnProperty(methodName)) { 16559 continue; 16560 } 16561 constructor.prototype[methodName] = methodBag[methodName]; 16562 } 16563 }; 16564 16565 module.exports = mixInto; 16566 16567 },{}],125:[function(_dereq_,module,exports){ 16568 /** 16569 * Copyright 2014 Facebook, Inc. 16570 * 16571 * Licensed under the Apache License, Version 2.0 (the "License"); 16572 * you may not use this file except in compliance with the License. 16573 * You may obtain a copy of the License at 16574 * 16575 * http://www.apache.org/licenses/LICENSE-2.0 16576 * 16577 * Unless required by applicable law or agreed to in writing, software 16578 * distributed under the License is distributed on an "AS IS" BASIS, 16579 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16580 * See the License for the specific language governing permissions and 16581 * limitations under the License. 16582 * 16583 * @providesModule monitorCodeUse 16584 */ 16585 16586 "use strict"; 16587 16588 var invariant = _dereq_("./invariant"); 16589 16590 /** 16591 * Provides open-source compatible instrumentation for monitoring certain API 16592 * uses before we're ready to issue a warning or refactor. It accepts an event 16593 * name which may only contain the characters [a-z0-9_] and an optional data 16594 * object with further information. 16595 */ 16596 16597 function monitorCodeUse(eventName, data) { 16598 ("production" !== "development" ? invariant( 16599 eventName && !/[^a-z0-9_]/.test(eventName), 16600 'You must provide an eventName using only the characters [a-z0-9_]' 16601 ) : invariant(eventName && !/[^a-z0-9_]/.test(eventName))); 16602 } 16603 16604 module.exports = monitorCodeUse; 16605 16606 },{"./invariant":112}],126:[function(_dereq_,module,exports){ 16607 /** 16608 * Copyright 2013-2014 Facebook, Inc. 16609 * 16610 * Licensed under the Apache License, Version 2.0 (the "License"); 16611 * you may not use this file except in compliance with the License. 16612 * You may obtain a copy of the License at 16613 * 16614 * http://www.apache.org/licenses/LICENSE-2.0 16615 * 16616 * Unless required by applicable law or agreed to in writing, software 16617 * distributed under the License is distributed on an "AS IS" BASIS, 16618 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16619 * See the License for the specific language governing permissions and 16620 * limitations under the License. 16621 * 16622 * @providesModule objMap 16623 */ 16624 16625 "use strict"; 16626 16627 /** 16628 * For each key/value pair, invokes callback func and constructs a resulting 16629 * object which contains, for every key in obj, values that are the result of 16630 * of invoking the function: 16631 * 16632 * func(value, key, iteration) 16633 * 16634 * @param {?object} obj Object to map keys over 16635 * @param {function} func Invoked for each key/val pair. 16636 * @param {?*} context 16637 * @return {?object} Result of mapping or null if obj is falsey 16638 */ 16639 function objMap(obj, func, context) { 16640 if (!obj) { 16641 return null; 16642 } 16643 var i = 0; 16644 var ret = {}; 16645 for (var key in obj) { 16646 if (obj.hasOwnProperty(key)) { 16647 ret[key] = func.call(context, obj[key], key, i++); 16648 } 16649 } 16650 return ret; 16651 } 16652 16653 module.exports = objMap; 16654 16655 },{}],127:[function(_dereq_,module,exports){ 16656 /** 16657 * Copyright 2013-2014 Facebook, Inc. 16658 * 16659 * Licensed under the Apache License, Version 2.0 (the "License"); 16660 * you may not use this file except in compliance with the License. 16661 * You may obtain a copy of the License at 16662 * 16663 * http://www.apache.org/licenses/LICENSE-2.0 16664 * 16665 * Unless required by applicable law or agreed to in writing, software 16666 * distributed under the License is distributed on an "AS IS" BASIS, 16667 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16668 * See the License for the specific language governing permissions and 16669 * limitations under the License. 16670 * 16671 * @providesModule objMapKeyVal 16672 */ 16673 16674 "use strict"; 16675 16676 /** 16677 * Behaves the same as `objMap` but invokes func with the key first, and value 16678 * second. Use `objMap` unless you need this special case. 16679 * Invokes func as: 16680 * 16681 * func(key, value, iteration) 16682 * 16683 * @param {?object} obj Object to map keys over 16684 * @param {!function} func Invoked for each key/val pair. 16685 * @param {?*} context 16686 * @return {?object} Result of mapping or null if obj is falsey 16687 */ 16688 function objMapKeyVal(obj, func, context) { 16689 if (!obj) { 16690 return null; 16691 } 16692 var i = 0; 16693 var ret = {}; 16694 for (var key in obj) { 16695 if (obj.hasOwnProperty(key)) { 16696 ret[key] = func.call(context, key, obj[key], i++); 16697 } 16698 } 16699 return ret; 16700 } 16701 16702 module.exports = objMapKeyVal; 16703 16704 },{}],128:[function(_dereq_,module,exports){ 16705 /** 16706 * Copyright 2013-2014 Facebook, Inc. 16707 * 16708 * Licensed under the Apache License, Version 2.0 (the "License"); 16709 * you may not use this file except in compliance with the License. 16710 * You may obtain a copy of the License at 16711 * 16712 * http://www.apache.org/licenses/LICENSE-2.0 16713 * 16714 * Unless required by applicable law or agreed to in writing, software 16715 * distributed under the License is distributed on an "AS IS" BASIS, 16716 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16717 * See the License for the specific language governing permissions and 16718 * limitations under the License. 16719 * 16720 * @providesModule onlyChild 16721 */ 16722 "use strict"; 16723 16724 var ReactComponent = _dereq_("./ReactComponent"); 16725 16726 var invariant = _dereq_("./invariant"); 16727 16728 /** 16729 * Returns the first child in a collection of children and verifies that there 16730 * is only one child in the collection. The current implementation of this 16731 * function assumes that a single child gets passed without a wrapper, but the 16732 * purpose of this helper function is to abstract away the particular structure 16733 * of children. 16734 * 16735 * @param {?object} children Child collection structure. 16736 * @return {ReactComponent} The first and only `ReactComponent` contained in the 16737 * structure. 16738 */ 16739 function onlyChild(children) { 16740 ("production" !== "development" ? invariant( 16741 ReactComponent.isValidComponent(children), 16742 'onlyChild must be passed a children with exactly one child.' 16743 ) : invariant(ReactComponent.isValidComponent(children))); 16744 return children; 16745 } 16746 16747 module.exports = onlyChild; 16748 16749 },{"./ReactComponent":27,"./invariant":112}],129:[function(_dereq_,module,exports){ 16750 /** 16751 * Copyright 2013-2014 Facebook, Inc. 16752 * 16753 * Licensed under the Apache License, Version 2.0 (the "License"); 16754 * you may not use this file except in compliance with the License. 16755 * You may obtain a copy of the License at 16756 * 16757 * http://www.apache.org/licenses/LICENSE-2.0 16758 * 16759 * Unless required by applicable law or agreed to in writing, software 16760 * distributed under the License is distributed on an "AS IS" BASIS, 16761 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16762 * See the License for the specific language governing permissions and 16763 * limitations under the License. 16764 * 16765 * @providesModule performanceNow 16766 * @typechecks static-only 16767 */ 16768 16769 "use strict"; 16770 16771 var ExecutionEnvironment = _dereq_("./ExecutionEnvironment"); 16772 16773 /** 16774 * Detect if we can use window.performance.now() and gracefully 16775 * fallback to Date.now() if it doesn't exist. 16776 * We need to support Firefox < 15 for now due to Facebook's webdriver 16777 * infrastructure. 16778 */ 16779 var performance = null; 16780 16781 if (ExecutionEnvironment.canUseDOM) { 16782 performance = window.performance || window.webkitPerformance; 16783 } 16784 16785 if (!performance || !performance.now) { 16786 performance = Date; 16787 } 16788 16789 var performanceNow = performance.now.bind(performance); 16790 16791 module.exports = performanceNow; 16792 16793 },{"./ExecutionEnvironment":20}],130:[function(_dereq_,module,exports){ 16794 /** 16795 * Copyright 2013-2014 Facebook, Inc. 16796 * 16797 * Licensed under the Apache License, Version 2.0 (the "License"); 16798 * you may not use this file except in compliance with the License. 16799 * You may obtain a copy of the License at 16800 * 16801 * http://www.apache.org/licenses/LICENSE-2.0 16802 * 16803 * Unless required by applicable law or agreed to in writing, software 16804 * distributed under the License is distributed on an "AS IS" BASIS, 16805 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16806 * See the License for the specific language governing permissions and 16807 * limitations under the License. 16808 * 16809 * @providesModule shallowEqual 16810 */ 16811 16812 "use strict"; 16813 16814 /** 16815 * Performs equality by iterating through keys on an object and returning 16816 * false when any key has values which are not strictly equal between 16817 * objA and objB. Returns true when the values of all keys are strictly equal. 16818 * 16819 * @return {boolean} 16820 */ 16821 function shallowEqual(objA, objB) { 16822 if (objA === objB) { 16823 return true; 16824 } 16825 var key; 16826 // Test for A's keys different from B. 16827 for (key in objA) { 16828 if (objA.hasOwnProperty(key) && 16829 (!objB.hasOwnProperty(key) || objA[key] !== objB[key])) { 16830 return false; 16831 } 16832 } 16833 // Test for B'a keys missing from A. 16834 for (key in objB) { 16835 if (objB.hasOwnProperty(key) && !objA.hasOwnProperty(key)) { 16836 return false; 16837 } 16838 } 16839 return true; 16840 } 16841 16842 module.exports = shallowEqual; 16843 16844 },{}],131:[function(_dereq_,module,exports){ 16845 /** 16846 * Copyright 2013-2014 Facebook, Inc. 16847 * 16848 * Licensed under the Apache License, Version 2.0 (the "License"); 16849 * you may not use this file except in compliance with the License. 16850 * You may obtain a copy of the License at 16851 * 16852 * http://www.apache.org/licenses/LICENSE-2.0 16853 * 16854 * Unless required by applicable law or agreed to in writing, software 16855 * distributed under the License is distributed on an "AS IS" BASIS, 16856 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16857 * See the License for the specific language governing permissions and 16858 * limitations under the License. 16859 * 16860 * @providesModule shouldUpdateReactComponent 16861 * @typechecks static-only 16862 */ 16863 16864 "use strict"; 16865 16866 /** 16867 * Given a `prevComponentInstance` and `nextComponent`, determines if 16868 * `prevComponentInstance` should be updated as opposed to being destroyed or 16869 * replaced by a new instance. The second argument is a descriptor. Future 16870 * versions of the reconciler should only compare descriptors to other 16871 * descriptors. 16872 * 16873 * @param {?object} prevComponentInstance 16874 * @param {?object} nextDescriptor 16875 * @return {boolean} True if `prevComponentInstance` should be updated. 16876 * @protected 16877 */ 16878 function shouldUpdateReactComponent(prevComponentInstance, nextDescriptor) { 16879 // TODO: Remove warning after a release. 16880 if (prevComponentInstance && nextDescriptor && 16881 prevComponentInstance.constructor === nextDescriptor.constructor && ( 16882 (prevComponentInstance.props && prevComponentInstance.props.key) === 16883 (nextDescriptor.props && nextDescriptor.props.key) 16884 )) { 16885 if (prevComponentInstance._owner === nextDescriptor._owner) { 16886 return true; 16887 } else { 16888 if ("production" !== "development") { 16889 if (prevComponentInstance.state) { 16890 console.warn( 16891 'A recent change to React has been found to impact your code. ' + 16892 'A mounted component will now be unmounted and replaced by a ' + 16893 'component (of the same class) if their owners are different. ' + 16894 'Previously, ownership was not considered when updating.', 16895 prevComponentInstance, 16896 nextDescriptor 16897 ); 16898 } 16899 } 16900 } 16901 } 16902 return false; 16903 } 16904 16905 module.exports = shouldUpdateReactComponent; 16906 16907 },{}],132:[function(_dereq_,module,exports){ 16908 /** 16909 * Copyright 2014 Facebook, Inc. 16910 * 16911 * Licensed under the Apache License, Version 2.0 (the "License"); 16912 * you may not use this file except in compliance with the License. 16913 * You may obtain a copy of the License at 16914 * 16915 * http://www.apache.org/licenses/LICENSE-2.0 16916 * 16917 * Unless required by applicable law or agreed to in writing, software 16918 * distributed under the License is distributed on an "AS IS" BASIS, 16919 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16920 * See the License for the specific language governing permissions and 16921 * limitations under the License. 16922 * 16923 * @providesModule toArray 16924 * @typechecks 16925 */ 16926 16927 var invariant = _dereq_("./invariant"); 16928 16929 /** 16930 * Convert array-like objects to arrays. 16931 * 16932 * This API assumes the caller knows the contents of the data type. For less 16933 * well defined inputs use createArrayFrom. 16934 * 16935 * @param {object|function} obj 16936 * @return {array} 16937 */ 16938 function toArray(obj) { 16939 var length = obj.length; 16940 16941 // Some browse builtin objects can report typeof 'function' (e.g. NodeList in 16942 // old versions of Safari). 16943 ("production" !== "development" ? invariant( 16944 !Array.isArray(obj) && 16945 (typeof obj === 'object' || typeof obj === 'function'), 16946 'toArray: Array-like object expected' 16947 ) : invariant(!Array.isArray(obj) && 16948 (typeof obj === 'object' || typeof obj === 'function'))); 16949 16950 ("production" !== "development" ? invariant( 16951 typeof length === 'number', 16952 'toArray: Object needs a length property' 16953 ) : invariant(typeof length === 'number')); 16954 16955 ("production" !== "development" ? invariant( 16956 length === 0 || 16957 (length - 1) in obj, 16958 'toArray: Object should have keys for indices' 16959 ) : invariant(length === 0 || 16960 (length - 1) in obj)); 16961 16962 // Old IE doesn't give collections access to hasOwnProperty. Assume inputs 16963 // without method will throw during the slice call and skip straight to the 16964 // fallback. 16965 if (obj.hasOwnProperty) { 16966 try { 16967 return Array.prototype.slice.call(obj); 16968 } catch (e) { 16969 // IE < 9 does not support Array#slice on collections objects 16970 } 16971 } 16972 16973 // Fall back to copying key by key. This assumes all keys have a value, 16974 // so will not preserve sparsely populated inputs. 16975 var ret = Array(length); 16976 for (var ii = 0; ii < length; ii++) { 16977 ret[ii] = obj[ii]; 16978 } 16979 return ret; 16980 } 16981 16982 module.exports = toArray; 16983 16984 },{"./invariant":112}],133:[function(_dereq_,module,exports){ 16985 /** 16986 * Copyright 2013-2014 Facebook, Inc. 16987 * 16988 * Licensed under the Apache License, Version 2.0 (the "License"); 16989 * you may not use this file except in compliance with the License. 16990 * You may obtain a copy of the License at 16991 * 16992 * http://www.apache.org/licenses/LICENSE-2.0 16993 * 16994 * Unless required by applicable law or agreed to in writing, software 16995 * distributed under the License is distributed on an "AS IS" BASIS, 16996 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16997 * See the License for the specific language governing permissions and 16998 * limitations under the License. 16999 * 17000 * @providesModule traverseAllChildren 17001 */ 17002 17003 "use strict"; 17004 17005 var ReactInstanceHandles = _dereq_("./ReactInstanceHandles"); 17006 var ReactTextComponent = _dereq_("./ReactTextComponent"); 17007 17008 var invariant = _dereq_("./invariant"); 17009 17010 var SEPARATOR = ReactInstanceHandles.SEPARATOR; 17011 var SUBSEPARATOR = ':'; 17012 17013 /** 17014 * TODO: Test that: 17015 * 1. `mapChildren` transforms strings and numbers into `ReactTextComponent`. 17016 * 2. it('should fail when supplied duplicate key', function() { 17017 * 3. That a single child and an array with one item have the same key pattern. 17018 * }); 17019 */ 17020 17021 var userProvidedKeyEscaperLookup = { 17022 '=': '=0', 17023 '.': '=1', 17024 ':': '=2' 17025 }; 17026 17027 var userProvidedKeyEscapeRegex = /[=.:]/g; 17028 17029 function userProvidedKeyEscaper(match) { 17030 return userProvidedKeyEscaperLookup[match]; 17031 } 17032 17033 /** 17034 * Generate a key string that identifies a component within a set. 17035 * 17036 * @param {*} component A component that could contain a manual key. 17037 * @param {number} index Index that is used if a manual key is not provided. 17038 * @return {string} 17039 */ 17040 function getComponentKey(component, index) { 17041 if (component && component.props && component.props.key != null) { 17042 // Explicit key 17043 return wrapUserProvidedKey(component.props.key); 17044 } 17045 // Implicit key determined by the index in the set 17046 return index.toString(36); 17047 } 17048 17049 /** 17050 * Escape a component key so that it is safe to use in a reactid. 17051 * 17052 * @param {*} key Component key to be escaped. 17053 * @return {string} An escaped string. 17054 */ 17055 function escapeUserProvidedKey(text) { 17056 return ('' + text).replace( 17057 userProvidedKeyEscapeRegex, 17058 userProvidedKeyEscaper 17059 ); 17060 } 17061 17062 /** 17063 * Wrap a `key` value explicitly provided by the user to distinguish it from 17064 * implicitly-generated keys generated by a component's index in its parent. 17065 * 17066 * @param {string} key Value of a user-provided `key` attribute 17067 * @return {string} 17068 */ 17069 function wrapUserProvidedKey(key) { 17070 return '$' + escapeUserProvidedKey(key); 17071 } 17072 17073 /** 17074 * @param {?*} children Children tree container. 17075 * @param {!string} nameSoFar Name of the key path so far. 17076 * @param {!number} indexSoFar Number of children encountered until this point. 17077 * @param {!function} callback Callback to invoke with each child found. 17078 * @param {?*} traverseContext Used to pass information throughout the traversal 17079 * process. 17080 * @return {!number} The number of children in this subtree. 17081 */ 17082 var traverseAllChildrenImpl = 17083 function(children, nameSoFar, indexSoFar, callback, traverseContext) { 17084 var subtreeCount = 0; // Count of children found in the current subtree. 17085 if (Array.isArray(children)) { 17086 for (var i = 0; i < children.length; i++) { 17087 var child = children[i]; 17088 var nextName = ( 17089 nameSoFar + 17090 (nameSoFar ? SUBSEPARATOR : SEPARATOR) + 17091 getComponentKey(child, i) 17092 ); 17093 var nextIndex = indexSoFar + subtreeCount; 17094 subtreeCount += traverseAllChildrenImpl( 17095 child, 17096 nextName, 17097 nextIndex, 17098 callback, 17099 traverseContext 17100 ); 17101 } 17102 } else { 17103 var type = typeof children; 17104 var isOnlyChild = nameSoFar === ''; 17105 // If it's the only child, treat the name as if it was wrapped in an array 17106 // so that it's consistent if the number of children grows 17107 var storageName = 17108 isOnlyChild ? SEPARATOR + getComponentKey(children, 0) : nameSoFar; 17109 if (children == null || type === 'boolean') { 17110 // All of the above are perceived as null. 17111 callback(traverseContext, null, storageName, indexSoFar); 17112 subtreeCount = 1; 17113 } else if (children.type && children.type.prototype && 17114 children.type.prototype.mountComponentIntoNode) { 17115 callback(traverseContext, children, storageName, indexSoFar); 17116 subtreeCount = 1; 17117 } else { 17118 if (type === 'object') { 17119 ("production" !== "development" ? invariant( 17120 !children || children.nodeType !== 1, 17121 'traverseAllChildren(...): Encountered an invalid child; DOM ' + 17122 'elements are not valid children of React components.' 17123 ) : invariant(!children || children.nodeType !== 1)); 17124 for (var key in children) { 17125 if (children.hasOwnProperty(key)) { 17126 subtreeCount += traverseAllChildrenImpl( 17127 children[key], 17128 ( 17129 nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) + 17130 wrapUserProvidedKey(key) + SUBSEPARATOR + 17131 getComponentKey(children[key], 0) 17132 ), 17133 indexSoFar + subtreeCount, 17134 callback, 17135 traverseContext 17136 ); 17137 } 17138 } 17139 } else if (type === 'string') { 17140 var normalizedText = new ReactTextComponent(children); 17141 callback(traverseContext, normalizedText, storageName, indexSoFar); 17142 subtreeCount += 1; 17143 } else if (type === 'number') { 17144 var normalizedNumber = new ReactTextComponent('' + children); 17145 callback(traverseContext, normalizedNumber, storageName, indexSoFar); 17146 subtreeCount += 1; 17147 } 17148 } 17149 } 17150 return subtreeCount; 17151 }; 17152 17153 /** 17154 * Traverses children that are typically specified as `props.children`, but 17155 * might also be specified through attributes: 17156 * 17157 * - `traverseAllChildren(this.props.children, ...)` 17158 * - `traverseAllChildren(this.props.leftPanelChildren, ...)` 17159 * 17160 * The `traverseContext` is an optional argument that is passed through the 17161 * entire traversal. It can be used to store accumulations or anything else that 17162 * the callback might find relevant. 17163 * 17164 * @param {?*} children Children tree object. 17165 * @param {!function} callback To invoke upon traversing each child. 17166 * @param {?*} traverseContext Context for traversal. 17167 */ 17168 function traverseAllChildren(children, callback, traverseContext) { 17169 if (children !== null && children !== undefined) { 17170 traverseAllChildrenImpl(children, '', 0, callback, traverseContext); 17171 } 17172 } 17173 17174 module.exports = traverseAllChildren; 17175 17176 },{"./ReactInstanceHandles":53,"./ReactTextComponent":70,"./invariant":112}],134:[function(_dereq_,module,exports){ 17177 /** 17178 * Copyright 2014 Facebook, Inc. 17179 * 17180 * Licensed under the Apache License, Version 2.0 (the "License"); 17181 * you may not use this file except in compliance with the License. 17182 * You may obtain a copy of the License at 17183 * 17184 * http://www.apache.org/licenses/LICENSE-2.0 17185 * 17186 * Unless required by applicable law or agreed to in writing, software 17187 * distributed under the License is distributed on an "AS IS" BASIS, 17188 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17189 * See the License for the specific language governing permissions and 17190 * limitations under the License. 17191 * 17192 * @providesModule warning 17193 */ 17194 17195 "use strict"; 17196 17197 var emptyFunction = _dereq_("./emptyFunction"); 17198 17199 /** 17200 * Similar to invariant but only logs a warning if the condition is not met. 17201 * This can be used to log issues in development environments in critical 17202 * paths. Removing the logging code for production environments will keep the 17203 * same logic and follow the same code paths. 17204 */ 17205 17206 var warning = emptyFunction; 17207 17208 if ("production" !== "development") { 17209 warning = function(condition, format ) {var args=Array.prototype.slice.call(arguments,2); 17210 if (format === undefined) { 17211 throw new Error( 17212 '`warning(condition, format, ...args)` requires a warning ' + 17213 'message argument' 17214 ); 17215 } 17216 17217 if (!condition) { 17218 var argIndex = 0; 17219 console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];})); 17220 } 17221 }; 17222 } 17223 17224 module.exports = warning; 17225 17226 },{"./emptyFunction":96}]},{},[24]) 17227 (24) 17228 });