github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/react/react-with-addons.js (about) 1 /** 2 * React (with addons) v0.8.0 3 */ 4 !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.React=e():"undefined"!=typeof global?global.React=e():"undefined"!=typeof self&&(self.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(require,module,exports){ 5 /** 6 * Copyright 2013 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 $ 21 * @typechecks 22 */ 23 24 var ge = require("./ge"); 25 var ex = require("./ex"); 26 27 /** 28 * Find a node by ID. 29 * 30 * If your application code depends on the existence of the element, use $, 31 * which will throw if the element doesn't exist. 32 * 33 * If you're not sure whether or not the element exists, use ge instead, and 34 * manually check for the element's existence in your application code. 35 * 36 * @param {string|DOMDocument|DOMElement|DOMTextNode|Comment} id 37 * @return {DOMDocument|DOMElement|DOMTextNode|Comment} 38 */ 39 function $(id) { 40 var element = ge(id); 41 if (!element) { 42 throw new Error(ex( 43 'Tried to get element with id of "%s" but it is not present on the page.', 44 id 45 )); 46 } 47 return element; 48 } 49 50 module.exports = $; 51 52 },{"./ex":96,"./ge":100}],2:[function(require,module,exports){ 53 /** 54 * Copyright 2013 Facebook, Inc. 55 * 56 * Licensed under the Apache License, Version 2.0 (the "License"); 57 * you may not use this file except in compliance with the License. 58 * You may obtain a copy of the License at 59 * 60 * http://www.apache.org/licenses/LICENSE-2.0 61 * 62 * Unless required by applicable law or agreed to in writing, software 63 * distributed under the License is distributed on an "AS IS" BASIS, 64 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 65 * See the License for the specific language governing permissions and 66 * limitations under the License. 67 * 68 * @providesModule CSSCore 69 * @typechecks 70 */ 71 72 var invariant = require("./invariant"); 73 74 /** 75 * The CSSCore module specifies the API (and implements most of the methods) 76 * that should be used when dealing with the display of elements (via their 77 * CSS classes and visibility on screeni. It is an API focused on mutating the 78 * display and not reading it as no logical state should be encoded in the 79 * display of elements. 80 */ 81 82 /** 83 * Tests whether the element has the class specified. 84 * 85 * Note: This function is not exported in CSSCore because CSS classNames should 86 * not store any logical information about the element. Use DataStore to store 87 * information on an element. 88 * 89 * @param {DOMElement} element the element to set the class on 90 * @param {string} className the CSS className 91 * @returns {boolean} true if the element has the class, false if not 92 */ 93 function hasClass(element, className) { 94 if (element.classList) { 95 return !!className && element.classList.contains(className); 96 } 97 return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1; 98 } 99 100 var CSSCore = { 101 102 /** 103 * Adds the class passed in to the element if it doesn't already have it. 104 * 105 * @param {DOMElement} element the element to set the class on 106 * @param {string} className the CSS className 107 * @return {DOMElement} the element passed in 108 */ 109 addClass: function(element, className) { 110 ("production" !== "development" ? invariant( 111 !/\s/.test(className), 112 'CSSCore.addClass takes only a single class name. "%s" contains ' + 113 'multiple classes.', className 114 ) : invariant(!/\s/.test(className))); 115 116 if (className) { 117 if (element.classList) { 118 element.classList.add(className); 119 } else if (!hasClass(element, className)) { 120 element.className = element.className + ' ' + className; 121 } 122 } 123 return element; 124 }, 125 126 /** 127 * Removes the class passed in from the element 128 * 129 * @param {DOMElement} element the element to set the class on 130 * @param {string} className the CSS className 131 * @return {DOMElement} the element passed in 132 */ 133 removeClass: function(element, className) { 134 ("production" !== "development" ? invariant( 135 !/\s/.test(className), 136 'CSSCore.removeClass takes only a single class name. "%s" contains ' + 137 'multiple classes.', className 138 ) : invariant(!/\s/.test(className))); 139 140 if (className) { 141 if (element.classList) { 142 element.classList.remove(className); 143 } else if (hasClass(element, className)) { 144 element.className = element.className 145 .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1') 146 .replace(/\s+/g, ' ') // multiple spaces to one 147 .replace(/^\s*|\s*$/g, ''); // trim the ends 148 } 149 } 150 return element; 151 }, 152 153 /** 154 * Helper to add or remove a class from an element based on a condition. 155 * 156 * @param {DOMElement} element the element to set the class on 157 * @param {string} className the CSS className 158 * @param {*} bool condition to whether to add or remove the class 159 * @return {DOMElement} the element passed in 160 */ 161 conditionClass: function(element, className, bool) { 162 return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className); 163 } 164 }; 165 166 module.exports = CSSCore; 167 168 },{"./invariant":109}],3:[function(require,module,exports){ 169 /** 170 * Copyright 2013 Facebook, Inc. 171 * 172 * Licensed under the Apache License, Version 2.0 (the "License"); 173 * you may not use this file except in compliance with the License. 174 * You may obtain a copy of the License at 175 * 176 * http://www.apache.org/licenses/LICENSE-2.0 177 * 178 * Unless required by applicable law or agreed to in writing, software 179 * distributed under the License is distributed on an "AS IS" BASIS, 180 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 181 * See the License for the specific language governing permissions and 182 * limitations under the License. 183 * 184 * @providesModule CSSProperty 185 */ 186 187 "use strict"; 188 189 /** 190 * CSS properties which accept numbers but are not in units of "px". 191 */ 192 var isUnitlessNumber = { 193 fillOpacity: true, 194 fontWeight: true, 195 lineHeight: true, 196 opacity: true, 197 orphans: true, 198 zIndex: true, 199 zoom: true 200 }; 201 202 /** 203 * Most style properties can be unset by doing .style[prop] = '' but IE8 204 * doesn't like doing that with shorthand properties so for the properties that 205 * IE8 breaks on, which are listed here, we instead unset each of the 206 * individual properties. See http://bugs.jquery.com/ticket/12385. 207 * The 4-value 'clock' properties like margin, padding, border-width seem to 208 * behave without any problems. Curiously, list-style works too without any 209 * special prodding. 210 */ 211 var shorthandPropertyExpansions = { 212 background: { 213 backgroundImage: true, 214 backgroundPosition: true, 215 backgroundRepeat: true, 216 backgroundColor: true 217 }, 218 border: { 219 borderWidth: true, 220 borderStyle: true, 221 borderColor: true 222 }, 223 borderBottom: { 224 borderBottomWidth: true, 225 borderBottomStyle: true, 226 borderBottomColor: true 227 }, 228 borderLeft: { 229 borderLeftWidth: true, 230 borderLeftStyle: true, 231 borderLeftColor: true 232 }, 233 borderRight: { 234 borderRightWidth: true, 235 borderRightStyle: true, 236 borderRightColor: true 237 }, 238 borderTop: { 239 borderTopWidth: true, 240 borderTopStyle: true, 241 borderTopColor: true 242 }, 243 font: { 244 fontStyle: true, 245 fontVariant: true, 246 fontWeight: true, 247 fontSize: true, 248 lineHeight: true, 249 fontFamily: true 250 } 251 }; 252 253 var CSSProperty = { 254 isUnitlessNumber: isUnitlessNumber, 255 shorthandPropertyExpansions: shorthandPropertyExpansions 256 }; 257 258 module.exports = CSSProperty; 259 260 },{}],4:[function(require,module,exports){ 261 /** 262 * Copyright 2013 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 CSSPropertyOperations 277 * @typechecks static-only 278 */ 279 280 "use strict"; 281 282 var CSSProperty = require("./CSSProperty"); 283 284 var dangerousStyleValue = require("./dangerousStyleValue"); 285 var escapeTextForBrowser = require("./escapeTextForBrowser"); 286 var hyphenate = require("./hyphenate"); 287 var memoizeStringOnly = require("./memoizeStringOnly"); 288 289 var processStyleName = memoizeStringOnly(function(styleName) { 290 return escapeTextForBrowser(hyphenate(styleName)); 291 }); 292 293 /** 294 * Operations for dealing with CSS properties. 295 */ 296 var CSSPropertyOperations = { 297 298 /** 299 * Serializes a mapping of style properties for use as inline styles: 300 * 301 * > createMarkupForStyles({width: '200px', height: 0}) 302 * "width:200px;height:0;" 303 * 304 * Undefined values are ignored so that declarative programming is easier. 305 * 306 * @param {object} styles 307 * @return {?string} 308 */ 309 createMarkupForStyles: function(styles) { 310 var serialized = ''; 311 for (var styleName in styles) { 312 if (!styles.hasOwnProperty(styleName)) { 313 continue; 314 } 315 var styleValue = styles[styleName]; 316 if (styleValue != null) { 317 serialized += processStyleName(styleName) + ':'; 318 serialized += dangerousStyleValue(styleName, styleValue) + ';'; 319 } 320 } 321 return serialized || null; 322 }, 323 324 /** 325 * Sets the value for multiple styles on a node. If a value is specified as 326 * '' (empty string), the corresponding style property will be unset. 327 * 328 * @param {DOMElement} node 329 * @param {object} styles 330 */ 331 setValueForStyles: function(node, styles) { 332 var style = node.style; 333 for (var styleName in styles) { 334 if (!styles.hasOwnProperty(styleName)) { 335 continue; 336 } 337 var styleValue = dangerousStyleValue(styleName, styles[styleName]); 338 if (styleValue) { 339 style[styleName] = styleValue; 340 } else { 341 var expansion = CSSProperty.shorthandPropertyExpansions[styleName]; 342 if (expansion) { 343 // Shorthand property that IE8 won't like unsetting, so unset each 344 // component to placate it 345 for (var individualStyleName in expansion) { 346 style[individualStyleName] = ''; 347 } 348 } else { 349 style[styleName] = ''; 350 } 351 } 352 } 353 } 354 355 }; 356 357 module.exports = CSSPropertyOperations; 358 359 },{"./CSSProperty":3,"./dangerousStyleValue":93,"./escapeTextForBrowser":95,"./hyphenate":108,"./memoizeStringOnly":117}],5:[function(require,module,exports){ 360 /** 361 * Copyright 2013 Facebook, Inc. 362 * 363 * Licensed under the Apache License, Version 2.0 (the "License"); 364 * you may not use this file except in compliance with the License. 365 * You may obtain a copy of the License at 366 * 367 * http://www.apache.org/licenses/LICENSE-2.0 368 * 369 * Unless required by applicable law or agreed to in writing, software 370 * distributed under the License is distributed on an "AS IS" BASIS, 371 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 372 * See the License for the specific language governing permissions and 373 * limitations under the License. 374 * 375 * @providesModule CallbackRegistry 376 * @typechecks static-only 377 */ 378 379 "use strict"; 380 381 var listenerBank = {}; 382 383 /** 384 * Stores "listeners" by `registrationName`/`id`. There should be at most one 385 * "listener" per `registrationName`/`id` in the `listenerBank`. 386 * 387 * Access listeners via `listenerBank[registrationName][id]`. 388 * 389 * @class CallbackRegistry 390 * @internal 391 */ 392 var CallbackRegistry = { 393 394 /** 395 * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. 396 * 397 * @param {string} id ID of the DOM element. 398 * @param {string} registrationName Name of listener (e.g. `onClick`). 399 * @param {?function} listener The callback to store. 400 */ 401 putListener: function(id, registrationName, listener) { 402 var bankForRegistrationName = 403 listenerBank[registrationName] || (listenerBank[registrationName] = {}); 404 bankForRegistrationName[id] = listener; 405 }, 406 407 /** 408 * @param {string} id ID of the DOM element. 409 * @param {string} registrationName Name of listener (e.g. `onClick`). 410 * @return {?function} The stored callback. 411 */ 412 getListener: function(id, registrationName) { 413 var bankForRegistrationName = listenerBank[registrationName]; 414 return bankForRegistrationName && bankForRegistrationName[id]; 415 }, 416 417 /** 418 * Deletes a listener from the registration bank. 419 * 420 * @param {string} id ID of the DOM element. 421 * @param {string} registrationName Name of listener (e.g. `onClick`). 422 */ 423 deleteListener: function(id, registrationName) { 424 var bankForRegistrationName = listenerBank[registrationName]; 425 if (bankForRegistrationName) { 426 delete bankForRegistrationName[id]; 427 } 428 }, 429 430 /** 431 * Deletes all listeners for the DOM element with the supplied ID. 432 * 433 * @param {string} id ID of the DOM element. 434 */ 435 deleteAllListeners: function(id) { 436 for (var registrationName in listenerBank) { 437 delete listenerBank[registrationName][id]; 438 } 439 }, 440 441 /** 442 * This is needed for tests only. Do not use! 443 */ 444 __purge: function() { 445 listenerBank = {}; 446 } 447 448 }; 449 450 module.exports = CallbackRegistry; 451 452 },{}],6:[function(require,module,exports){ 453 /** 454 * Copyright 2013 Facebook, Inc. 455 * 456 * Licensed under the Apache License, Version 2.0 (the "License"); 457 * you may not use this file except in compliance with the License. 458 * You may obtain a copy of the License at 459 * 460 * http://www.apache.org/licenses/LICENSE-2.0 461 * 462 * Unless required by applicable law or agreed to in writing, software 463 * distributed under the License is distributed on an "AS IS" BASIS, 464 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 465 * See the License for the specific language governing permissions and 466 * limitations under the License. 467 * 468 * @providesModule ChangeEventPlugin 469 */ 470 471 "use strict"; 472 473 var EventConstants = require("./EventConstants"); 474 var EventPluginHub = require("./EventPluginHub"); 475 var EventPropagators = require("./EventPropagators"); 476 var ExecutionEnvironment = require("./ExecutionEnvironment"); 477 var SyntheticEvent = require("./SyntheticEvent"); 478 479 var isEventSupported = require("./isEventSupported"); 480 var isTextInputElement = require("./isTextInputElement"); 481 var keyOf = require("./keyOf"); 482 483 var topLevelTypes = EventConstants.topLevelTypes; 484 485 var eventTypes = { 486 change: { 487 phasedRegistrationNames: { 488 bubbled: keyOf({onChange: null}), 489 captured: keyOf({onChangeCapture: null}) 490 } 491 } 492 }; 493 494 /** 495 * For IE shims 496 */ 497 var activeElement = null; 498 var activeElementID = null; 499 var activeElementValue = null; 500 var activeElementValueProp = null; 501 502 /** 503 * SECTION: handle `change` event 504 */ 505 function shouldUseChangeEvent(elem) { 506 return ( 507 elem.nodeName === 'SELECT' || 508 (elem.nodeName === 'INPUT' && elem.type === 'file') 509 ); 510 } 511 512 var doesChangeEventBubble = false; 513 if (ExecutionEnvironment.canUseDOM) { 514 // See `handleChange` comment below 515 doesChangeEventBubble = isEventSupported('change') && ( 516 !('documentMode' in document) || document.documentMode > 8 517 ); 518 } 519 520 function manualDispatchChangeEvent(nativeEvent) { 521 var event = SyntheticEvent.getPooled( 522 eventTypes.change, 523 activeElementID, 524 nativeEvent 525 ); 526 EventPropagators.accumulateTwoPhaseDispatches(event); 527 528 // If change bubbled, we'd just bind to it like all the other events 529 // and have it go through ReactEventTopLevelCallback. Since it doesn't, we 530 // manually listen for the change event and so we have to enqueue and 531 // process the abstract event manually. 532 EventPluginHub.enqueueEvents(event); 533 EventPluginHub.processEventQueue(); 534 } 535 536 function startWatchingForChangeEventIE8(target, targetID) { 537 activeElement = target; 538 activeElementID = targetID; 539 activeElement.attachEvent('onchange', manualDispatchChangeEvent); 540 } 541 542 function stopWatchingForChangeEventIE8() { 543 if (!activeElement) { 544 return; 545 } 546 activeElement.detachEvent('onchange', manualDispatchChangeEvent); 547 activeElement = null; 548 activeElementID = null; 549 } 550 551 function getTargetIDForChangeEvent( 552 topLevelType, 553 topLevelTarget, 554 topLevelTargetID) { 555 if (topLevelType === topLevelTypes.topChange) { 556 return topLevelTargetID; 557 } 558 } 559 function handleEventsForChangeEventIE8( 560 topLevelType, 561 topLevelTarget, 562 topLevelTargetID) { 563 if (topLevelType === topLevelTypes.topFocus) { 564 // stopWatching() should be a noop here but we call it just in case we 565 // missed a blur event somehow. 566 stopWatchingForChangeEventIE8(); 567 startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID); 568 } else if (topLevelType === topLevelTypes.topBlur) { 569 stopWatchingForChangeEventIE8(); 570 } 571 } 572 573 574 /** 575 * SECTION: handle `input` event 576 */ 577 var isInputEventSupported = false; 578 if (ExecutionEnvironment.canUseDOM) { 579 // IE9 claims to support the input event but fails to trigger it when 580 // deleting text, so we ignore its input events 581 isInputEventSupported = isEventSupported('input') && ( 582 !('documentMode' in document) || document.documentMode > 9 583 ); 584 } 585 586 /** 587 * (For old IE.) Replacement getter/setter for the `value` property that gets 588 * set on the active element. 589 */ 590 var newValueProp = { 591 get: function() { 592 return activeElementValueProp.get.call(this); 593 }, 594 set: function(val) { 595 // Cast to a string so we can do equality checks. 596 activeElementValue = '' + val; 597 activeElementValueProp.set.call(this, val); 598 } 599 }; 600 601 /** 602 * (For old IE.) Starts tracking propertychange events on the passed-in element 603 * and override the value property so that we can distinguish user events from 604 * value changes in JS. 605 */ 606 function startWatchingForValueChange(target, targetID) { 607 activeElement = target; 608 activeElementID = targetID; 609 activeElementValue = target.value; 610 activeElementValueProp = Object.getOwnPropertyDescriptor( 611 target.constructor.prototype, 612 'value' 613 ); 614 615 Object.defineProperty(activeElement, 'value', newValueProp); 616 activeElement.attachEvent('onpropertychange', handlePropertyChange); 617 } 618 619 /** 620 * (For old IE.) Removes the event listeners from the currently-tracked element, 621 * if any exists. 622 */ 623 function stopWatchingForValueChange() { 624 if (!activeElement) { 625 return; 626 } 627 628 // delete restores the original property definition 629 delete activeElement.value; 630 activeElement.detachEvent('onpropertychange', handlePropertyChange); 631 632 activeElement = null; 633 activeElementID = null; 634 activeElementValue = null; 635 activeElementValueProp = null; 636 } 637 638 /** 639 * (For old IE.) Handles a propertychange event, sending a `change` event if 640 * the value of the active element has changed. 641 */ 642 function handlePropertyChange(nativeEvent) { 643 if (nativeEvent.propertyName !== 'value') { 644 return; 645 } 646 var value = nativeEvent.srcElement.value; 647 if (value === activeElementValue) { 648 return; 649 } 650 activeElementValue = value; 651 652 manualDispatchChangeEvent(nativeEvent); 653 } 654 655 /** 656 * If a `change` event should be fired, returns the target's ID. 657 */ 658 function getTargetIDForInputEvent( 659 topLevelType, 660 topLevelTarget, 661 topLevelTargetID) { 662 if (topLevelType === topLevelTypes.topInput) { 663 // In modern browsers (i.e., not IE8 or IE9), the input event is exactly 664 // what we want so fall through here and trigger an abstract event 665 return topLevelTargetID; 666 } 667 } 668 669 // For IE8 and IE9. 670 function handleEventsForInputEventIE( 671 topLevelType, 672 topLevelTarget, 673 topLevelTargetID) { 674 if (topLevelType === topLevelTypes.topFocus) { 675 // In IE8, we can capture almost all .value changes by adding a 676 // propertychange handler and looking for events with propertyName 677 // equal to 'value' 678 // In IE9, propertychange fires for most input events but is buggy and 679 // doesn't fire when text is deleted, but conveniently, selectionchange 680 // appears to fire in all of the remaining cases so we catch those and 681 // forward the event if the value has changed 682 // In either case, we don't want to call the event handler if the value 683 // is changed from JS so we redefine a setter for `.value` that updates 684 // our activeElementValue variable, allowing us to ignore those changes 685 // 686 // stopWatching() should be a noop here but we call it just in case we 687 // missed a blur event somehow. 688 stopWatchingForValueChange(); 689 startWatchingForValueChange(topLevelTarget, topLevelTargetID); 690 } else if (topLevelType === topLevelTypes.topBlur) { 691 stopWatchingForValueChange(); 692 } 693 } 694 695 // For IE8 and IE9. 696 function getTargetIDForInputEventIE( 697 topLevelType, 698 topLevelTarget, 699 topLevelTargetID) { 700 if (topLevelType === topLevelTypes.topSelectionChange || 701 topLevelType === topLevelTypes.topKeyUp || 702 topLevelType === topLevelTypes.topKeyDown) { 703 // On the selectionchange event, the target is just document which isn't 704 // helpful for us so just check activeElement instead. 705 // 706 // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire 707 // propertychange on the first input event after setting `value` from a 708 // script and fires only keydown, keypress, keyup. Catching keyup usually 709 // gets it and catching keydown lets us fire an event for the first 710 // keystroke if user does a key repeat (it'll be a little delayed: right 711 // before the second keystroke). Other input methods (e.g., paste) seem to 712 // fire selectionchange normally. 713 if (activeElement && activeElement.value !== activeElementValue) { 714 activeElementValue = activeElement.value; 715 return activeElementID; 716 } 717 } 718 } 719 720 721 /** 722 * SECTION: handle `click` event 723 */ 724 function shouldUseClickEvent(elem) { 725 // Use the `click` event to detect changes to checkbox and radio inputs. 726 // This approach works across all browsers, whereas `change` does not fire 727 // until `blur` in IE8. 728 return ( 729 elem.nodeName === 'INPUT' && 730 (elem.type === 'checkbox' || elem.type === 'radio') 731 ); 732 } 733 734 function getTargetIDForClickEvent( 735 topLevelType, 736 topLevelTarget, 737 topLevelTargetID) { 738 if (topLevelType === topLevelTypes.topClick) { 739 return topLevelTargetID; 740 } 741 } 742 743 /** 744 * This plugin creates an `onChange` event that normalizes change events 745 * across form elements. This event fires at a time when it's possible to 746 * change the element's value without seeing a flicker. 747 * 748 * Supported elements are: 749 * - input (see `isTextInputElement`) 750 * - textarea 751 * - select 752 */ 753 var ChangeEventPlugin = { 754 755 eventTypes: eventTypes, 756 757 /** 758 * @param {string} topLevelType Record from `EventConstants`. 759 * @param {DOMEventTarget} topLevelTarget The listening component root node. 760 * @param {string} topLevelTargetID ID of `topLevelTarget`. 761 * @param {object} nativeEvent Native browser event. 762 * @return {*} An accumulation of synthetic events. 763 * @see {EventPluginHub.extractEvents} 764 */ 765 extractEvents: function( 766 topLevelType, 767 topLevelTarget, 768 topLevelTargetID, 769 nativeEvent) { 770 771 var getTargetIDFunc, handleEventFunc; 772 if (shouldUseChangeEvent(topLevelTarget)) { 773 if (doesChangeEventBubble) { 774 getTargetIDFunc = getTargetIDForChangeEvent; 775 } else { 776 handleEventFunc = handleEventsForChangeEventIE8; 777 } 778 } else if (isTextInputElement(topLevelTarget)) { 779 if (isInputEventSupported) { 780 getTargetIDFunc = getTargetIDForInputEvent; 781 } else { 782 getTargetIDFunc = getTargetIDForInputEventIE; 783 handleEventFunc = handleEventsForInputEventIE; 784 } 785 } else if (shouldUseClickEvent(topLevelTarget)) { 786 getTargetIDFunc = getTargetIDForClickEvent; 787 } 788 789 if (getTargetIDFunc) { 790 var targetID = getTargetIDFunc( 791 topLevelType, 792 topLevelTarget, 793 topLevelTargetID 794 ); 795 if (targetID) { 796 var event = SyntheticEvent.getPooled( 797 eventTypes.change, 798 targetID, 799 nativeEvent 800 ); 801 EventPropagators.accumulateTwoPhaseDispatches(event); 802 return event; 803 } 804 } 805 806 if (handleEventFunc) { 807 handleEventFunc( 808 topLevelType, 809 topLevelTarget, 810 topLevelTargetID 811 ); 812 } 813 } 814 815 }; 816 817 module.exports = ChangeEventPlugin; 818 819 },{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./SyntheticEvent":76,"./isEventSupported":110,"./isTextInputElement":112,"./keyOf":116}],7:[function(require,module,exports){ 820 /** 821 * Copyright 2013 Facebook, Inc. 822 * 823 * Licensed under the Apache License, Version 2.0 (the "License"); 824 * you may not use this file except in compliance with the License. 825 * You may obtain a copy of the License at 826 * 827 * http://www.apache.org/licenses/LICENSE-2.0 828 * 829 * Unless required by applicable law or agreed to in writing, software 830 * distributed under the License is distributed on an "AS IS" BASIS, 831 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 832 * See the License for the specific language governing permissions and 833 * limitations under the License. 834 * 835 * @providesModule CompositionEventPlugin 836 * @typechecks static-only 837 */ 838 839 "use strict"; 840 841 var EventConstants = require("./EventConstants"); 842 var EventPropagators = require("./EventPropagators"); 843 var ExecutionEnvironment = require("./ExecutionEnvironment"); 844 var ReactInputSelection = require("./ReactInputSelection"); 845 var SyntheticCompositionEvent = require("./SyntheticCompositionEvent"); 846 847 var getTextContentAccessor = require("./getTextContentAccessor"); 848 var keyOf = require("./keyOf"); 849 850 var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space 851 var START_KEYCODE = 229; 852 853 var useCompositionEvent = ExecutionEnvironment.canUseDOM && 854 'CompositionEvent' in window; 855 var topLevelTypes = EventConstants.topLevelTypes; 856 var currentComposition = null; 857 858 // Events and their corresponding property names. 859 var eventTypes = { 860 compositionEnd: { 861 phasedRegistrationNames: { 862 bubbled: keyOf({onCompositionEnd: null}), 863 captured: keyOf({onCompositionEndCapture: null}) 864 } 865 }, 866 compositionStart: { 867 phasedRegistrationNames: { 868 bubbled: keyOf({onCompositionStart: null}), 869 captured: keyOf({onCompositionStartCapture: null}) 870 } 871 }, 872 compositionUpdate: { 873 phasedRegistrationNames: { 874 bubbled: keyOf({onCompositionUpdate: null}), 875 captured: keyOf({onCompositionUpdateCapture: null}) 876 } 877 } 878 }; 879 880 /** 881 * Translate native top level events into event types. 882 * 883 * @param {string} topLevelType 884 * @return {object} 885 */ 886 function getCompositionEventType(topLevelType) { 887 switch (topLevelType) { 888 case topLevelTypes.topCompositionStart: 889 return eventTypes.compositionStart; 890 case topLevelTypes.topCompositionEnd: 891 return eventTypes.compositionEnd; 892 case topLevelTypes.topCompositionUpdate: 893 return eventTypes.compositionUpdate; 894 } 895 } 896 897 /** 898 * Does our fallback best-guess model think this event signifies that 899 * composition has begun? 900 * 901 * @param {string} topLevelType 902 * @param {object} nativeEvent 903 * @return {boolean} 904 */ 905 function isFallbackStart(topLevelType, nativeEvent) { 906 return ( 907 topLevelType === topLevelTypes.topKeyDown && 908 nativeEvent.keyCode === START_KEYCODE 909 ); 910 } 911 912 /** 913 * Does our fallback mode think that this event is the end of composition? 914 * 915 * @param {string} topLevelType 916 * @param {object} nativeEvent 917 * @return {boolean} 918 */ 919 function isFallbackEnd(topLevelType, nativeEvent) { 920 switch (topLevelType) { 921 case topLevelTypes.topKeyUp: 922 // Command keys insert or clear IME input. 923 return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); 924 case topLevelTypes.topKeyDown: 925 // Expect IME keyCode on each keydown. If we get any other 926 // code we must have exited earlier. 927 return (nativeEvent.keyCode !== START_KEYCODE); 928 case topLevelTypes.topKeyPress: 929 case topLevelTypes.topMouseDown: 930 case topLevelTypes.topBlur: 931 // Events are not possible without cancelling IME. 932 return true; 933 default: 934 return false; 935 } 936 } 937 938 /** 939 * Helper class stores information about selection and document state 940 * so we can figure out what changed at a later date. 941 * 942 * @param {DOMEventTarget} root 943 */ 944 function FallbackCompositionState(root) { 945 this.root = root; 946 this.startSelection = ReactInputSelection.getSelection(root); 947 this.startValue = this.getText(); 948 } 949 950 /** 951 * Get current text of input. 952 * 953 * @return {string} 954 */ 955 FallbackCompositionState.prototype.getText = function() { 956 return this.root.value || this.root[getTextContentAccessor()]; 957 }; 958 959 /** 960 * Text that has changed since the start of composition. 961 * 962 * @return {string} 963 */ 964 FallbackCompositionState.prototype.getData = function() { 965 var endValue = this.getText(); 966 var prefixLength = this.startSelection.start; 967 var suffixLength = this.startValue.length - this.startSelection.end; 968 969 return endValue.substr( 970 prefixLength, 971 endValue.length - suffixLength - prefixLength 972 ); 973 }; 974 975 /** 976 * This plugin creates `onCompositionStart`, `onCompositionUpdate` and 977 * `onCompositionEnd` events on inputs, textareas and contentEditable 978 * nodes. 979 */ 980 var CompositionEventPlugin = { 981 982 eventTypes: eventTypes, 983 984 /** 985 * @param {string} topLevelType Record from `EventConstants`. 986 * @param {DOMEventTarget} topLevelTarget The listening component root node. 987 * @param {string} topLevelTargetID ID of `topLevelTarget`. 988 * @param {object} nativeEvent Native browser event. 989 * @return {*} An accumulation of synthetic events. 990 * @see {EventPluginHub.extractEvents} 991 */ 992 extractEvents: function( 993 topLevelType, 994 topLevelTarget, 995 topLevelTargetID, 996 nativeEvent) { 997 998 var eventType; 999 var data; 1000 1001 if (useCompositionEvent) { 1002 eventType = getCompositionEventType(topLevelType); 1003 } else if (!currentComposition) { 1004 if (isFallbackStart(topLevelType, nativeEvent)) { 1005 eventType = eventTypes.start; 1006 currentComposition = new FallbackCompositionState(topLevelTarget); 1007 } 1008 } else if (isFallbackEnd(topLevelType, nativeEvent)) { 1009 eventType = eventTypes.compositionEnd; 1010 data = currentComposition.getData(); 1011 currentComposition = null; 1012 } 1013 1014 if (eventType) { 1015 var event = SyntheticCompositionEvent.getPooled( 1016 eventType, 1017 topLevelTargetID, 1018 nativeEvent 1019 ); 1020 if (data) { 1021 // Inject data generated from fallback path into the synthetic event. 1022 // This matches the property of native CompositionEventInterface. 1023 event.data = data; 1024 } 1025 EventPropagators.accumulateTwoPhaseDispatches(event); 1026 return event; 1027 } 1028 } 1029 }; 1030 1031 module.exports = CompositionEventPlugin; 1032 1033 },{"./EventConstants":15,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":50,"./SyntheticCompositionEvent":75,"./getTextContentAccessor":106,"./keyOf":116}],8:[function(require,module,exports){ 1034 /** 1035 * Copyright 2013 Facebook, Inc. 1036 * 1037 * Licensed under the Apache License, Version 2.0 (the "License"); 1038 * you may not use this file except in compliance with the License. 1039 * You may obtain a copy of the License at 1040 * 1041 * http://www.apache.org/licenses/LICENSE-2.0 1042 * 1043 * Unless required by applicable law or agreed to in writing, software 1044 * distributed under the License is distributed on an "AS IS" BASIS, 1045 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1046 * See the License for the specific language governing permissions and 1047 * limitations under the License. 1048 * 1049 * @providesModule DOMChildrenOperations 1050 * @typechecks static-only 1051 */ 1052 1053 "use strict"; 1054 1055 var Danger = require("./Danger"); 1056 var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); 1057 1058 var getTextContentAccessor = require("./getTextContentAccessor"); 1059 1060 /** 1061 * The DOM property to use when setting text content. 1062 * 1063 * @type {string} 1064 * @private 1065 */ 1066 var textContentAccessor = getTextContentAccessor() || 'NA'; 1067 1068 /** 1069 * Inserts `childNode` as a child of `parentNode` at the `index`. 1070 * 1071 * @param {DOMElement} parentNode Parent node in which to insert. 1072 * @param {DOMElement} childNode Child node to insert. 1073 * @param {number} index Index at which to insert the child. 1074 * @internal 1075 */ 1076 function insertChildAt(parentNode, childNode, index) { 1077 var childNodes = parentNode.childNodes; 1078 if (childNodes[index] === childNode) { 1079 return; 1080 } 1081 // If `childNode` is already a child of `parentNode`, remove it so that 1082 // computing `childNodes[index]` takes into account the removal. 1083 if (childNode.parentNode === parentNode) { 1084 parentNode.removeChild(childNode); 1085 } 1086 if (index >= childNodes.length) { 1087 parentNode.appendChild(childNode); 1088 } else { 1089 parentNode.insertBefore(childNode, childNodes[index]); 1090 } 1091 } 1092 1093 /** 1094 * Operations for updating with DOM children. 1095 */ 1096 var DOMChildrenOperations = { 1097 1098 dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, 1099 1100 /** 1101 * Updates a component's children by processing a series of updates. The 1102 * update configurations are each expected to have a `parentNode` property. 1103 * 1104 * @param {array<object>} updates List of update configurations. 1105 * @param {array<string>} markupList List of markup strings. 1106 * @internal 1107 */ 1108 processUpdates: function(updates, markupList) { 1109 var update; 1110 // Mapping from parent IDs to initial child orderings. 1111 var initialChildren = null; 1112 // List of children that will be moved or removed. 1113 var updatedChildren = null; 1114 1115 for (var i = 0; update = updates[i]; i++) { 1116 if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || 1117 update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { 1118 var updatedIndex = update.fromIndex; 1119 var updatedChild = update.parentNode.childNodes[updatedIndex]; 1120 var parentID = update.parentID; 1121 1122 initialChildren = initialChildren || {}; 1123 initialChildren[parentID] = initialChildren[parentID] || []; 1124 initialChildren[parentID][updatedIndex] = updatedChild; 1125 1126 updatedChildren = updatedChildren || []; 1127 updatedChildren.push(updatedChild); 1128 } 1129 } 1130 1131 var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); 1132 1133 // Remove updated children first so that `toIndex` is consistent. 1134 if (updatedChildren) { 1135 for (var j = 0; j < updatedChildren.length; j++) { 1136 updatedChildren[j].parentNode.removeChild(updatedChildren[j]); 1137 } 1138 } 1139 1140 for (var k = 0; update = updates[k]; k++) { 1141 switch (update.type) { 1142 case ReactMultiChildUpdateTypes.INSERT_MARKUP: 1143 insertChildAt( 1144 update.parentNode, 1145 renderedMarkup[update.markupIndex], 1146 update.toIndex 1147 ); 1148 break; 1149 case ReactMultiChildUpdateTypes.MOVE_EXISTING: 1150 insertChildAt( 1151 update.parentNode, 1152 initialChildren[update.parentID][update.fromIndex], 1153 update.toIndex 1154 ); 1155 break; 1156 case ReactMultiChildUpdateTypes.TEXT_CONTENT: 1157 update.parentNode[textContentAccessor] = update.textContent; 1158 break; 1159 case ReactMultiChildUpdateTypes.REMOVE_NODE: 1160 // Already removed by the for-loop above. 1161 break; 1162 } 1163 } 1164 } 1165 1166 }; 1167 1168 module.exports = DOMChildrenOperations; 1169 1170 },{"./Danger":11,"./ReactMultiChildUpdateTypes":57,"./getTextContentAccessor":106}],9:[function(require,module,exports){ 1171 /** 1172 * Copyright 2013 Facebook, Inc. 1173 * 1174 * Licensed under the Apache License, Version 2.0 (the "License"); 1175 * you may not use this file except in compliance with the License. 1176 * You may obtain a copy of the License at 1177 * 1178 * http://www.apache.org/licenses/LICENSE-2.0 1179 * 1180 * Unless required by applicable law or agreed to in writing, software 1181 * distributed under the License is distributed on an "AS IS" BASIS, 1182 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1183 * See the License for the specific language governing permissions and 1184 * limitations under the License. 1185 * 1186 * @providesModule DOMProperty 1187 * @typechecks static-only 1188 */ 1189 1190 /*jslint bitwise: true */ 1191 1192 "use strict"; 1193 1194 var invariant = require("./invariant"); 1195 1196 var DOMPropertyInjection = { 1197 /** 1198 * Mapping from normalized, camelcased property names to a configuration that 1199 * specifies how the associated DOM property should be accessed or rendered. 1200 */ 1201 MUST_USE_ATTRIBUTE: 0x1, 1202 MUST_USE_PROPERTY: 0x2, 1203 HAS_SIDE_EFFECTS: 0x4, 1204 HAS_BOOLEAN_VALUE: 0x8, 1205 HAS_POSITIVE_NUMERIC_VALUE: 0x10, 1206 1207 /** 1208 * Inject some specialized knowledge about the DOM. This takes a config object 1209 * with the following properties: 1210 * 1211 * isCustomAttribute: function that given an attribute name will return true 1212 * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* 1213 * attributes where it's impossible to enumerate all of the possible 1214 * attribute names, 1215 * 1216 * Properties: object mapping DOM property name to one of the 1217 * DOMPropertyInjection constants or null. If your attribute isn't in here, 1218 * it won't get written to the DOM. 1219 * 1220 * DOMAttributeNames: object mapping React attribute name to the DOM 1221 * attribute name. Attribute names not specified use the **lowercase** 1222 * normalized name. 1223 * 1224 * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. 1225 * Property names not specified use the normalized name. 1226 * 1227 * DOMMutationMethods: Properties that require special mutation methods. If 1228 * `value` is undefined, the mutation method should unset the property. 1229 * 1230 * @param {object} domPropertyConfig the config as described above. 1231 */ 1232 injectDOMPropertyConfig: function(domPropertyConfig) { 1233 var Properties = domPropertyConfig.Properties || {}; 1234 var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; 1235 var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; 1236 var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; 1237 1238 if (domPropertyConfig.isCustomAttribute) { 1239 DOMProperty._isCustomAttributeFunctions.push( 1240 domPropertyConfig.isCustomAttribute 1241 ); 1242 } 1243 1244 for (var propName in Properties) { 1245 ("production" !== "development" ? invariant( 1246 !DOMProperty.isStandardName[propName], 1247 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + 1248 '\'%s\' which has already been injected. You may be accidentally ' + 1249 'injecting the same DOM property config twice, or you may be ' + 1250 'injecting two configs that have conflicting property names.', 1251 propName 1252 ) : invariant(!DOMProperty.isStandardName[propName])); 1253 1254 DOMProperty.isStandardName[propName] = true; 1255 1256 var lowerCased = propName.toLowerCase(); 1257 DOMProperty.getPossibleStandardName[lowerCased] = propName; 1258 1259 var attributeName = DOMAttributeNames[propName]; 1260 if (attributeName) { 1261 DOMProperty.getPossibleStandardName[attributeName] = propName; 1262 } 1263 1264 DOMProperty.getAttributeName[propName] = attributeName || lowerCased; 1265 1266 DOMProperty.getPropertyName[propName] = 1267 DOMPropertyNames[propName] || propName; 1268 1269 var mutationMethod = DOMMutationMethods[propName]; 1270 if (mutationMethod) { 1271 DOMProperty.getMutationMethod[propName] = mutationMethod; 1272 } 1273 1274 var propConfig = Properties[propName]; 1275 DOMProperty.mustUseAttribute[propName] = 1276 propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; 1277 DOMProperty.mustUseProperty[propName] = 1278 propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; 1279 DOMProperty.hasSideEffects[propName] = 1280 propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; 1281 DOMProperty.hasBooleanValue[propName] = 1282 propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; 1283 DOMProperty.hasPositiveNumericValue[propName] = 1284 propConfig & DOMPropertyInjection.HAS_POSITIVE_NUMERIC_VALUE; 1285 1286 ("production" !== "development" ? invariant( 1287 !DOMProperty.mustUseAttribute[propName] || 1288 !DOMProperty.mustUseProperty[propName], 1289 'DOMProperty: Cannot require using both attribute and property: %s', 1290 propName 1291 ) : invariant(!DOMProperty.mustUseAttribute[propName] || 1292 !DOMProperty.mustUseProperty[propName])); 1293 ("production" !== "development" ? invariant( 1294 DOMProperty.mustUseProperty[propName] || 1295 !DOMProperty.hasSideEffects[propName], 1296 'DOMProperty: Properties that have side effects must use property: %s', 1297 propName 1298 ) : invariant(DOMProperty.mustUseProperty[propName] || 1299 !DOMProperty.hasSideEffects[propName])); 1300 ("production" !== "development" ? invariant( 1301 !DOMProperty.hasBooleanValue[propName] || 1302 !DOMProperty.hasPositiveNumericValue[propName], 1303 'DOMProperty: Cannot have both boolean and positive numeric value: %s', 1304 propName 1305 ) : invariant(!DOMProperty.hasBooleanValue[propName] || 1306 !DOMProperty.hasPositiveNumericValue[propName])); 1307 } 1308 } 1309 }; 1310 var defaultValueCache = {}; 1311 1312 /** 1313 * DOMProperty exports lookup objects that can be used like functions: 1314 * 1315 * > DOMProperty.isValid['id'] 1316 * true 1317 * > DOMProperty.isValid['foobar'] 1318 * undefined 1319 * 1320 * Although this may be confusing, it performs better in general. 1321 * 1322 * @see http://jsperf.com/key-exists 1323 * @see http://jsperf.com/key-missing 1324 */ 1325 var DOMProperty = { 1326 1327 /** 1328 * Checks whether a property name is a standard property. 1329 * @type {Object} 1330 */ 1331 isStandardName: {}, 1332 1333 /** 1334 * Mapping from lowercase property names to the properly cased version, used 1335 * to warn in the case of missing properties. 1336 * @type {Object} 1337 */ 1338 getPossibleStandardName: {}, 1339 1340 /** 1341 * Mapping from normalized names to attribute names that differ. Attribute 1342 * names are used when rendering markup or with `*Attribute()`. 1343 * @type {Object} 1344 */ 1345 getAttributeName: {}, 1346 1347 /** 1348 * Mapping from normalized names to properties on DOM node instances. 1349 * (This includes properties that mutate due to external factors.) 1350 * @type {Object} 1351 */ 1352 getPropertyName: {}, 1353 1354 /** 1355 * Mapping from normalized names to mutation methods. This will only exist if 1356 * mutation cannot be set simply by the property or `setAttribute()`. 1357 * @type {Object} 1358 */ 1359 getMutationMethod: {}, 1360 1361 /** 1362 * Whether the property must be accessed and mutated as an object property. 1363 * @type {Object} 1364 */ 1365 mustUseAttribute: {}, 1366 1367 /** 1368 * Whether the property must be accessed and mutated using `*Attribute()`. 1369 * (This includes anything that fails `<propName> in <element>`.) 1370 * @type {Object} 1371 */ 1372 mustUseProperty: {}, 1373 1374 /** 1375 * Whether or not setting a value causes side effects such as triggering 1376 * resources to be loaded or text selection changes. We must ensure that 1377 * the value is only set if it has changed. 1378 * @type {Object} 1379 */ 1380 hasSideEffects: {}, 1381 1382 /** 1383 * Whether the property should be removed when set to a falsey value. 1384 * @type {Object} 1385 */ 1386 hasBooleanValue: {}, 1387 1388 /** 1389 * Whether the property must be positive numeric or parse as a positive 1390 * numeric and should be removed when set to a falsey value. 1391 * @type {Object} 1392 */ 1393 hasPositiveNumericValue: {}, 1394 1395 /** 1396 * All of the isCustomAttribute() functions that have been injected. 1397 */ 1398 _isCustomAttributeFunctions: [], 1399 1400 /** 1401 * Checks whether a property name is a custom attribute. 1402 * @method 1403 */ 1404 isCustomAttribute: function(attributeName) { 1405 return DOMProperty._isCustomAttributeFunctions.some( 1406 function(isCustomAttributeFn) { 1407 return isCustomAttributeFn.call(null, attributeName); 1408 } 1409 ); 1410 }, 1411 1412 /** 1413 * Returns the default property value for a DOM property (i.e., not an 1414 * attribute). Most default values are '' or false, but not all. Worse yet, 1415 * some (in particular, `type`) vary depending on the type of element. 1416 * 1417 * TODO: Is it better to grab all the possible properties when creating an 1418 * element to avoid having to create the same element twice? 1419 */ 1420 getDefaultValueForProperty: function(nodeName, prop) { 1421 var nodeDefaults = defaultValueCache[nodeName]; 1422 var testElement; 1423 if (!nodeDefaults) { 1424 defaultValueCache[nodeName] = nodeDefaults = {}; 1425 } 1426 if (!(prop in nodeDefaults)) { 1427 testElement = document.createElement(nodeName); 1428 nodeDefaults[prop] = testElement[prop]; 1429 } 1430 return nodeDefaults[prop]; 1431 }, 1432 1433 injection: DOMPropertyInjection 1434 }; 1435 1436 module.exports = DOMProperty; 1437 1438 },{"./invariant":109}],10:[function(require,module,exports){ 1439 /** 1440 * Copyright 2013 Facebook, Inc. 1441 * 1442 * Licensed under the Apache License, Version 2.0 (the "License"); 1443 * you may not use this file except in compliance with the License. 1444 * You may obtain a copy of the License at 1445 * 1446 * http://www.apache.org/licenses/LICENSE-2.0 1447 * 1448 * Unless required by applicable law or agreed to in writing, software 1449 * distributed under the License is distributed on an "AS IS" BASIS, 1450 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1451 * See the License for the specific language governing permissions and 1452 * limitations under the License. 1453 * 1454 * @providesModule DOMPropertyOperations 1455 * @typechecks static-only 1456 */ 1457 1458 "use strict"; 1459 1460 var DOMProperty = require("./DOMProperty"); 1461 1462 var escapeTextForBrowser = require("./escapeTextForBrowser"); 1463 var memoizeStringOnly = require("./memoizeStringOnly"); 1464 1465 function shouldIgnoreValue(name, value) { 1466 return value == null || 1467 DOMProperty.hasBooleanValue[name] && !value || 1468 DOMProperty.hasPositiveNumericValue[name] && (isNaN(value) || value < 1); 1469 } 1470 1471 var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { 1472 return escapeTextForBrowser(name) + '="'; 1473 }); 1474 1475 if ("production" !== "development") { 1476 var reactProps = { 1477 __owner__: true, 1478 children: true, 1479 dangerouslySetInnerHTML: true, 1480 key: true, 1481 ref: true 1482 }; 1483 var warnedProperties = {}; 1484 1485 var warnUnknownProperty = function(name) { 1486 if (reactProps[name] || warnedProperties[name]) { 1487 return; 1488 } 1489 1490 warnedProperties[name] = true; 1491 var lowerCasedName = name.toLowerCase(); 1492 1493 // data-* attributes should be lowercase; suggest the lowercase version 1494 var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? 1495 lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName]; 1496 1497 // For now, only warn when we have a suggested correction. This prevents 1498 // logging too much when using transferPropsTo. 1499 if (standardName != null) { 1500 console.warn( 1501 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' 1502 ); 1503 } 1504 1505 }; 1506 } 1507 1508 /** 1509 * Operations for dealing with DOM properties. 1510 */ 1511 var DOMPropertyOperations = { 1512 1513 /** 1514 * Creates markup for a property. 1515 * 1516 * @param {string} name 1517 * @param {*} value 1518 * @return {?string} Markup string, or null if the property was invalid. 1519 */ 1520 createMarkupForProperty: function(name, value) { 1521 if (DOMProperty.isStandardName[name]) { 1522 if (shouldIgnoreValue(name, value)) { 1523 return ''; 1524 } 1525 var attributeName = DOMProperty.getAttributeName[name]; 1526 return processAttributeNameAndPrefix(attributeName) + 1527 escapeTextForBrowser(value) + '"'; 1528 } else if (DOMProperty.isCustomAttribute(name)) { 1529 if (value == null) { 1530 return ''; 1531 } 1532 return processAttributeNameAndPrefix(name) + 1533 escapeTextForBrowser(value) + '"'; 1534 } else if ("production" !== "development") { 1535 warnUnknownProperty(name); 1536 } 1537 return null; 1538 }, 1539 1540 /** 1541 * Sets the value for a property on a node. 1542 * 1543 * @param {DOMElement} node 1544 * @param {string} name 1545 * @param {*} value 1546 */ 1547 setValueForProperty: function(node, name, value) { 1548 if (DOMProperty.isStandardName[name]) { 1549 var mutationMethod = DOMProperty.getMutationMethod[name]; 1550 if (mutationMethod) { 1551 mutationMethod(node, value); 1552 } else if (shouldIgnoreValue(name, value)) { 1553 this.deleteValueForProperty(node, name); 1554 } else if (DOMProperty.mustUseAttribute[name]) { 1555 node.setAttribute(DOMProperty.getAttributeName[name], '' + value); 1556 } else { 1557 var propName = DOMProperty.getPropertyName[name]; 1558 if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { 1559 node[propName] = value; 1560 } 1561 } 1562 } else if (DOMProperty.isCustomAttribute(name)) { 1563 if (value == null) { 1564 node.removeAttribute(DOMProperty.getAttributeName[name]); 1565 } else { 1566 node.setAttribute(name, '' + value); 1567 } 1568 } else if ("production" !== "development") { 1569 warnUnknownProperty(name); 1570 } 1571 }, 1572 1573 /** 1574 * Deletes the value for a property on a node. 1575 * 1576 * @param {DOMElement} node 1577 * @param {string} name 1578 */ 1579 deleteValueForProperty: function(node, name) { 1580 if (DOMProperty.isStandardName[name]) { 1581 var mutationMethod = DOMProperty.getMutationMethod[name]; 1582 if (mutationMethod) { 1583 mutationMethod(node, undefined); 1584 } else if (DOMProperty.mustUseAttribute[name]) { 1585 node.removeAttribute(DOMProperty.getAttributeName[name]); 1586 } else { 1587 var propName = DOMProperty.getPropertyName[name]; 1588 var defaultValue = DOMProperty.getDefaultValueForProperty( 1589 node.nodeName, 1590 name 1591 ); 1592 if (!DOMProperty.hasSideEffects[name] || 1593 node[propName] !== defaultValue) { 1594 node[propName] = defaultValue; 1595 } 1596 } 1597 } else if (DOMProperty.isCustomAttribute(name)) { 1598 node.removeAttribute(name); 1599 } else if ("production" !== "development") { 1600 warnUnknownProperty(name); 1601 } 1602 } 1603 1604 }; 1605 1606 module.exports = DOMPropertyOperations; 1607 1608 },{"./DOMProperty":9,"./escapeTextForBrowser":95,"./memoizeStringOnly":117}],11:[function(require,module,exports){ 1609 /** 1610 * Copyright 2013 Facebook, Inc. 1611 * 1612 * Licensed under the Apache License, Version 2.0 (the "License"); 1613 * you may not use this file except in compliance with the License. 1614 * You may obtain a copy of the License at 1615 * 1616 * http://www.apache.org/licenses/LICENSE-2.0 1617 * 1618 * Unless required by applicable law or agreed to in writing, software 1619 * distributed under the License is distributed on an "AS IS" BASIS, 1620 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1621 * See the License for the specific language governing permissions and 1622 * limitations under the License. 1623 * 1624 * @providesModule Danger 1625 * @typechecks static-only 1626 */ 1627 1628 /*jslint evil: true, sub: true */ 1629 1630 "use strict"; 1631 1632 var ExecutionEnvironment = require("./ExecutionEnvironment"); 1633 1634 var createNodesFromMarkup = require("./createNodesFromMarkup"); 1635 var emptyFunction = require("./emptyFunction"); 1636 var getMarkupWrap = require("./getMarkupWrap"); 1637 var invariant = require("./invariant"); 1638 var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup"); 1639 1640 var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; 1641 var RESULT_INDEX_ATTR = 'data-danger-index'; 1642 1643 /** 1644 * Extracts the `nodeName` from a string of markup. 1645 * 1646 * NOTE: Extracting the `nodeName` does not require a regular expression match 1647 * because we make assumptions about React-generated markup (i.e. there are no 1648 * spaces surrounding the opening tag and there is at least one attribute). 1649 * 1650 * @param {string} markup String of markup. 1651 * @return {string} Node name of the supplied markup. 1652 * @see http://jsperf.com/extract-nodename 1653 */ 1654 function getNodeName(markup) { 1655 return markup.substring(1, markup.indexOf(' ')); 1656 } 1657 1658 var Danger = { 1659 1660 /** 1661 * Renders markup into an array of nodes. The markup is expected to render 1662 * into a list of root nodes. Also, the length of `resultList` and 1663 * `markupList` should be the same. 1664 * 1665 * @param {array<string>} markupList List of markup strings to render. 1666 * @return {array<DOMElement>} List of rendered nodes. 1667 * @internal 1668 */ 1669 dangerouslyRenderMarkup: function(markupList) { 1670 ("production" !== "development" ? invariant( 1671 ExecutionEnvironment.canUseDOM, 1672 'dangerouslyRenderMarkup(...): Cannot render markup in a Worker ' + 1673 'thread. This is likely a bug in the framework. Please report ' + 1674 'immediately.' 1675 ) : invariant(ExecutionEnvironment.canUseDOM)); 1676 var nodeName; 1677 var markupByNodeName = {}; 1678 // Group markup by `nodeName` if a wrap is necessary, else by '*'. 1679 for (var i = 0; i < markupList.length; i++) { 1680 ("production" !== "development" ? invariant( 1681 markupList[i], 1682 'dangerouslyRenderMarkup(...): Missing markup.' 1683 ) : invariant(markupList[i])); 1684 nodeName = getNodeName(markupList[i]); 1685 nodeName = getMarkupWrap(nodeName) ? nodeName : '*'; 1686 markupByNodeName[nodeName] = markupByNodeName[nodeName] || []; 1687 markupByNodeName[nodeName][i] = markupList[i]; 1688 } 1689 var resultList = []; 1690 var resultListAssignmentCount = 0; 1691 for (nodeName in markupByNodeName) { 1692 if (!markupByNodeName.hasOwnProperty(nodeName)) { 1693 continue; 1694 } 1695 var markupListByNodeName = markupByNodeName[nodeName]; 1696 1697 // This for-in loop skips the holes of the sparse array. The order of 1698 // iteration should follow the order of assignment, which happens to match 1699 // numerical index order, but we don't rely on that. 1700 for (var resultIndex in markupListByNodeName) { 1701 if (markupListByNodeName.hasOwnProperty(resultIndex)) { 1702 var markup = markupListByNodeName[resultIndex]; 1703 1704 // Push the requested markup with an additional RESULT_INDEX_ATTR 1705 // attribute. If the markup does not start with a < character, it 1706 // will be discarded below (with an appropriate console.error). 1707 markupListByNodeName[resultIndex] = markup.replace( 1708 OPEN_TAG_NAME_EXP, 1709 // This index will be parsed back out below. 1710 '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ' 1711 ); 1712 } 1713 } 1714 1715 // Render each group of markup with similar wrapping `nodeName`. 1716 var renderNodes = createNodesFromMarkup( 1717 markupListByNodeName.join(''), 1718 emptyFunction // Do nothing special with <script> tags. 1719 ); 1720 1721 for (i = 0; i < renderNodes.length; ++i) { 1722 var renderNode = renderNodes[i]; 1723 if (renderNode.hasAttribute && 1724 renderNode.hasAttribute(RESULT_INDEX_ATTR)) { 1725 1726 resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR); 1727 renderNode.removeAttribute(RESULT_INDEX_ATTR); 1728 1729 ("production" !== "development" ? invariant( 1730 !resultList.hasOwnProperty(resultIndex), 1731 'Danger: Assigning to an already-occupied result index.' 1732 ) : invariant(!resultList.hasOwnProperty(resultIndex))); 1733 1734 resultList[resultIndex] = renderNode; 1735 1736 // This should match resultList.length and markupList.length when 1737 // we're done. 1738 resultListAssignmentCount += 1; 1739 1740 } else if ("production" !== "development") { 1741 console.error( 1742 "Danger: Discarding unexpected node:", 1743 renderNode 1744 ); 1745 } 1746 } 1747 } 1748 1749 // Although resultList was populated out of order, it should now be a dense 1750 // array. 1751 ("production" !== "development" ? invariant( 1752 resultListAssignmentCount === resultList.length, 1753 'Danger: Did not assign to every index of resultList.' 1754 ) : invariant(resultListAssignmentCount === resultList.length)); 1755 1756 ("production" !== "development" ? invariant( 1757 resultList.length === markupList.length, 1758 'Danger: Expected markup to render %s nodes, but rendered %s.', 1759 markupList.length, 1760 resultList.length 1761 ) : invariant(resultList.length === markupList.length)); 1762 1763 return resultList; 1764 }, 1765 1766 /** 1767 * Replaces a node with a string of markup at its current position within its 1768 * parent. The markup must render into a single root node. 1769 * 1770 * @param {DOMElement} oldChild Child node to replace. 1771 * @param {string} markup Markup to render in place of the child node. 1772 * @internal 1773 */ 1774 dangerouslyReplaceNodeWithMarkup: function(oldChild, markup) { 1775 ("production" !== "development" ? invariant( 1776 ExecutionEnvironment.canUseDOM, 1777 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + 1778 'worker thread. This is likely a bug in the framework. Please report ' + 1779 'immediately.' 1780 ) : invariant(ExecutionEnvironment.canUseDOM)); 1781 ("production" !== "development" ? invariant(markup, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(markup)); 1782 // createNodesFromMarkup() won't work if the markup is rooted by <html> 1783 // since it has special semantic meaning. So we use an alternatie strategy. 1784 if (oldChild.tagName.toLowerCase() === 'html') { 1785 mutateHTMLNodeWithMarkup(oldChild, markup); 1786 return; 1787 } 1788 var newChild = createNodesFromMarkup(markup, emptyFunction)[0]; 1789 oldChild.parentNode.replaceChild(newChild, oldChild); 1790 } 1791 1792 }; 1793 1794 module.exports = Danger; 1795 1796 },{"./ExecutionEnvironment":21,"./createNodesFromMarkup":90,"./emptyFunction":94,"./getMarkupWrap":103,"./invariant":109,"./mutateHTMLNodeWithMarkup":122}],12:[function(require,module,exports){ 1797 /** 1798 * Copyright 2013 Facebook, Inc. 1799 * 1800 * Licensed under the Apache License, Version 2.0 (the "License"); 1801 * you may not use this file except in compliance with the License. 1802 * You may obtain a copy of the License at 1803 * 1804 * http://www.apache.org/licenses/LICENSE-2.0 1805 * 1806 * Unless required by applicable law or agreed to in writing, software 1807 * distributed under the License is distributed on an "AS IS" BASIS, 1808 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1809 * See the License for the specific language governing permissions and 1810 * limitations under the License. 1811 * 1812 * @providesModule DefaultDOMPropertyConfig 1813 */ 1814 1815 /*jslint bitwise: true*/ 1816 1817 "use strict"; 1818 1819 var DOMProperty = require("./DOMProperty"); 1820 1821 var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE; 1822 var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY; 1823 var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE; 1824 var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS; 1825 var HAS_POSITIVE_NUMERIC_VALUE = 1826 DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE; 1827 1828 var DefaultDOMPropertyConfig = { 1829 isCustomAttribute: RegExp.prototype.test.bind( 1830 /^(data|aria)-[a-z_][a-z\d_.\-]*$/ 1831 ), 1832 Properties: { 1833 /** 1834 * Standard Properties 1835 */ 1836 accept: null, 1837 accessKey: null, 1838 action: null, 1839 allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1840 allowTransparency: MUST_USE_ATTRIBUTE, 1841 alt: null, 1842 async: HAS_BOOLEAN_VALUE, 1843 autoComplete: null, 1844 autoFocus: HAS_BOOLEAN_VALUE, 1845 autoPlay: HAS_BOOLEAN_VALUE, 1846 cellPadding: null, 1847 cellSpacing: null, 1848 charSet: MUST_USE_ATTRIBUTE, 1849 checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1850 className: MUST_USE_PROPERTY, 1851 cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1852 colSpan: null, 1853 content: null, 1854 contentEditable: null, 1855 contextMenu: MUST_USE_ATTRIBUTE, 1856 controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1857 data: null, // For `<object />` acts as `src`. 1858 dateTime: MUST_USE_ATTRIBUTE, 1859 defer: HAS_BOOLEAN_VALUE, 1860 dir: null, 1861 disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1862 draggable: null, 1863 encType: null, 1864 form: MUST_USE_ATTRIBUTE, 1865 frameBorder: MUST_USE_ATTRIBUTE, 1866 height: MUST_USE_ATTRIBUTE, 1867 hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, 1868 href: null, 1869 htmlFor: null, 1870 httpEquiv: null, 1871 icon: null, 1872 id: MUST_USE_PROPERTY, 1873 label: null, 1874 lang: null, 1875 list: null, 1876 loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1877 max: null, 1878 maxLength: MUST_USE_ATTRIBUTE, 1879 method: null, 1880 min: null, 1881 multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1882 name: null, 1883 pattern: null, 1884 placeholder: null, 1885 poster: null, 1886 preload: null, 1887 radioGroup: null, 1888 readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1889 rel: null, 1890 required: HAS_BOOLEAN_VALUE, 1891 role: MUST_USE_ATTRIBUTE, 1892 rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1893 rowSpan: null, 1894 scrollLeft: MUST_USE_PROPERTY, 1895 scrollTop: MUST_USE_PROPERTY, 1896 selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, 1897 size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE, 1898 spellCheck: null, 1899 src: null, 1900 step: null, 1901 style: null, 1902 tabIndex: null, 1903 target: null, 1904 title: null, 1905 type: null, 1906 value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS, 1907 width: MUST_USE_ATTRIBUTE, 1908 wmode: MUST_USE_ATTRIBUTE, 1909 1910 /** 1911 * Non-standard Properties 1912 */ 1913 autoCapitalize: null, // Supported in Mobile Safari for keyboard hints 1914 autoCorrect: null, // Supported in Mobile Safari for keyboard hints 1915 1916 /** 1917 * SVG Properties 1918 */ 1919 cx: MUST_USE_ATTRIBUTE, 1920 cy: MUST_USE_ATTRIBUTE, 1921 d: MUST_USE_ATTRIBUTE, 1922 fill: MUST_USE_ATTRIBUTE, 1923 fx: MUST_USE_ATTRIBUTE, 1924 fy: MUST_USE_ATTRIBUTE, 1925 gradientTransform: MUST_USE_ATTRIBUTE, 1926 gradientUnits: MUST_USE_ATTRIBUTE, 1927 offset: MUST_USE_ATTRIBUTE, 1928 points: MUST_USE_ATTRIBUTE, 1929 r: MUST_USE_ATTRIBUTE, 1930 rx: MUST_USE_ATTRIBUTE, 1931 ry: MUST_USE_ATTRIBUTE, 1932 spreadMethod: MUST_USE_ATTRIBUTE, 1933 stopColor: MUST_USE_ATTRIBUTE, 1934 stopOpacity: MUST_USE_ATTRIBUTE, 1935 stroke: MUST_USE_ATTRIBUTE, 1936 strokeLinecap: MUST_USE_ATTRIBUTE, 1937 strokeWidth: MUST_USE_ATTRIBUTE, 1938 transform: MUST_USE_ATTRIBUTE, 1939 version: MUST_USE_ATTRIBUTE, 1940 viewBox: MUST_USE_ATTRIBUTE, 1941 x1: MUST_USE_ATTRIBUTE, 1942 x2: MUST_USE_ATTRIBUTE, 1943 x: MUST_USE_ATTRIBUTE, 1944 y1: MUST_USE_ATTRIBUTE, 1945 y2: MUST_USE_ATTRIBUTE, 1946 y: MUST_USE_ATTRIBUTE 1947 }, 1948 DOMAttributeNames: { 1949 className: 'class', 1950 gradientTransform: 'gradientTransform', 1951 gradientUnits: 'gradientUnits', 1952 htmlFor: 'for', 1953 spreadMethod: 'spreadMethod', 1954 stopColor: 'stop-color', 1955 stopOpacity: 'stop-opacity', 1956 strokeLinecap: 'stroke-linecap', 1957 strokeWidth: 'stroke-width', 1958 viewBox: 'viewBox' 1959 }, 1960 DOMPropertyNames: { 1961 autoCapitalize: 'autocapitalize', 1962 autoComplete: 'autocomplete', 1963 autoCorrect: 'autocorrect', 1964 autoFocus: 'autofocus', 1965 autoPlay: 'autoplay', 1966 encType: 'enctype', 1967 radioGroup: 'radiogroup', 1968 spellCheck: 'spellcheck' 1969 }, 1970 DOMMutationMethods: { 1971 /** 1972 * Setting `className` to null may cause it to be set to the string "null". 1973 * 1974 * @param {DOMElement} node 1975 * @param {*} value 1976 */ 1977 className: function(node, value) { 1978 node.className = value || ''; 1979 } 1980 } 1981 }; 1982 1983 module.exports = DefaultDOMPropertyConfig; 1984 1985 },{"./DOMProperty":9}],13:[function(require,module,exports){ 1986 /** 1987 * Copyright 2013 Facebook, Inc. 1988 * 1989 * Licensed under the Apache License, Version 2.0 (the "License"); 1990 * you may not use this file except in compliance with the License. 1991 * You may obtain a copy of the License at 1992 * 1993 * http://www.apache.org/licenses/LICENSE-2.0 1994 * 1995 * Unless required by applicable law or agreed to in writing, software 1996 * distributed under the License is distributed on an "AS IS" BASIS, 1997 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1998 * See the License for the specific language governing permissions and 1999 * limitations under the License. 2000 * 2001 * @providesModule DefaultEventPluginOrder 2002 */ 2003 2004 "use strict"; 2005 2006 var keyOf = require("./keyOf"); 2007 2008 /** 2009 * Module that is injectable into `EventPluginHub`, that specifies a 2010 * deterministic ordering of `EventPlugin`s. A convenient way to reason about 2011 * plugins, without having to package every one of them. This is better than 2012 * having plugins be ordered in the same order that they are injected because 2013 * that ordering would be influenced by the packaging order. 2014 * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that 2015 * preventing default on events is convenient in `SimpleEventPlugin` handlers. 2016 */ 2017 var DefaultEventPluginOrder = [ 2018 keyOf({ResponderEventPlugin: null}), 2019 keyOf({SimpleEventPlugin: null}), 2020 keyOf({TapEventPlugin: null}), 2021 keyOf({EnterLeaveEventPlugin: null}), 2022 keyOf({ChangeEventPlugin: null}), 2023 keyOf({SelectEventPlugin: null}), 2024 keyOf({CompositionEventPlugin: null}), 2025 keyOf({AnalyticsEventPlugin: null}), 2026 keyOf({MobileSafariClickEventPlugin: null}) 2027 ]; 2028 2029 module.exports = DefaultEventPluginOrder; 2030 2031 },{"./keyOf":116}],14:[function(require,module,exports){ 2032 /** 2033 * Copyright 2013 Facebook, Inc. 2034 * 2035 * Licensed under the Apache License, Version 2.0 (the "License"); 2036 * you may not use this file except in compliance with the License. 2037 * You may obtain a copy of the License at 2038 * 2039 * http://www.apache.org/licenses/LICENSE-2.0 2040 * 2041 * Unless required by applicable law or agreed to in writing, software 2042 * distributed under the License is distributed on an "AS IS" BASIS, 2043 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2044 * See the License for the specific language governing permissions and 2045 * limitations under the License. 2046 * 2047 * @providesModule EnterLeaveEventPlugin 2048 * @typechecks static-only 2049 */ 2050 2051 "use strict"; 2052 2053 var EventConstants = require("./EventConstants"); 2054 var EventPropagators = require("./EventPropagators"); 2055 var SyntheticMouseEvent = require("./SyntheticMouseEvent"); 2056 2057 var ReactMount = require("./ReactMount"); 2058 var keyOf = require("./keyOf"); 2059 2060 var topLevelTypes = EventConstants.topLevelTypes; 2061 var getFirstReactDOM = ReactMount.getFirstReactDOM; 2062 2063 var eventTypes = { 2064 mouseEnter: {registrationName: keyOf({onMouseEnter: null})}, 2065 mouseLeave: {registrationName: keyOf({onMouseLeave: null})} 2066 }; 2067 2068 var extractedEvents = [null, null]; 2069 2070 var EnterLeaveEventPlugin = { 2071 2072 eventTypes: eventTypes, 2073 2074 /** 2075 * For almost every interaction we care about, there will be both a top-level 2076 * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that 2077 * we do not extract duplicate events. However, moving the mouse into the 2078 * browser from outside will not fire a `mouseout` event. In this case, we use 2079 * the `mouseover` top-level event. 2080 * 2081 * @param {string} topLevelType Record from `EventConstants`. 2082 * @param {DOMEventTarget} topLevelTarget The listening component root node. 2083 * @param {string} topLevelTargetID ID of `topLevelTarget`. 2084 * @param {object} nativeEvent Native browser event. 2085 * @return {*} An accumulation of synthetic events. 2086 * @see {EventPluginHub.extractEvents} 2087 */ 2088 extractEvents: function( 2089 topLevelType, 2090 topLevelTarget, 2091 topLevelTargetID, 2092 nativeEvent) { 2093 if (topLevelType === topLevelTypes.topMouseOver && 2094 (nativeEvent.relatedTarget || nativeEvent.fromElement)) { 2095 return null; 2096 } 2097 if (topLevelType !== topLevelTypes.topMouseOut && 2098 topLevelType !== topLevelTypes.topMouseOver) { 2099 // Must not be a mouse in or mouse out - ignoring. 2100 return null; 2101 } 2102 2103 var from, to; 2104 if (topLevelType === topLevelTypes.topMouseOut) { 2105 from = topLevelTarget; 2106 to = 2107 getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) || 2108 window; 2109 } else { 2110 from = window; 2111 to = topLevelTarget; 2112 } 2113 2114 if (from === to) { 2115 // Nothing pertains to our managed components. 2116 return null; 2117 } 2118 2119 var fromID = from ? ReactMount.getID(from) : ''; 2120 var toID = to ? ReactMount.getID(to) : ''; 2121 2122 var leave = SyntheticMouseEvent.getPooled( 2123 eventTypes.mouseLeave, 2124 fromID, 2125 nativeEvent 2126 ); 2127 var enter = SyntheticMouseEvent.getPooled( 2128 eventTypes.mouseEnter, 2129 toID, 2130 nativeEvent 2131 ); 2132 2133 EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID); 2134 2135 extractedEvents[0] = leave; 2136 extractedEvents[1] = enter; 2137 2138 return extractedEvents; 2139 } 2140 2141 }; 2142 2143 module.exports = EnterLeaveEventPlugin; 2144 2145 },{"./EventConstants":15,"./EventPropagators":20,"./ReactMount":54,"./SyntheticMouseEvent":79,"./keyOf":116}],15:[function(require,module,exports){ 2146 /** 2147 * Copyright 2013 Facebook, Inc. 2148 * 2149 * Licensed under the Apache License, Version 2.0 (the "License"); 2150 * you may not use this file except in compliance with the License. 2151 * You may obtain a copy of the License at 2152 * 2153 * http://www.apache.org/licenses/LICENSE-2.0 2154 * 2155 * Unless required by applicable law or agreed to in writing, software 2156 * distributed under the License is distributed on an "AS IS" BASIS, 2157 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2158 * See the License for the specific language governing permissions and 2159 * limitations under the License. 2160 * 2161 * @providesModule EventConstants 2162 */ 2163 2164 "use strict"; 2165 2166 var keyMirror = require("./keyMirror"); 2167 2168 var PropagationPhases = keyMirror({bubbled: null, captured: null}); 2169 2170 /** 2171 * Types of raw signals from the browser caught at the top level. 2172 */ 2173 var topLevelTypes = keyMirror({ 2174 topBlur: null, 2175 topChange: null, 2176 topClick: null, 2177 topCompositionEnd: null, 2178 topCompositionStart: null, 2179 topCompositionUpdate: null, 2180 topContextMenu: null, 2181 topCopy: null, 2182 topCut: null, 2183 topDoubleClick: null, 2184 topDrag: null, 2185 topDragEnd: null, 2186 topDragEnter: null, 2187 topDragExit: null, 2188 topDragLeave: null, 2189 topDragOver: null, 2190 topDragStart: null, 2191 topDrop: null, 2192 topFocus: null, 2193 topInput: null, 2194 topKeyDown: null, 2195 topKeyPress: null, 2196 topKeyUp: null, 2197 topMouseDown: null, 2198 topMouseMove: null, 2199 topMouseOut: null, 2200 topMouseOver: null, 2201 topMouseUp: null, 2202 topPaste: null, 2203 topScroll: null, 2204 topSelectionChange: null, 2205 topSubmit: null, 2206 topTouchCancel: null, 2207 topTouchEnd: null, 2208 topTouchMove: null, 2209 topTouchStart: null, 2210 topWheel: null 2211 }); 2212 2213 var EventConstants = { 2214 topLevelTypes: topLevelTypes, 2215 PropagationPhases: PropagationPhases 2216 }; 2217 2218 module.exports = EventConstants; 2219 2220 },{"./keyMirror":115}],16:[function(require,module,exports){ 2221 /** 2222 * Copyright 2013 Facebook, Inc. 2223 * 2224 * Licensed under the Apache License, Version 2.0 (the "License"); 2225 * you may not use this file except in compliance with the License. 2226 * You may obtain a copy of the License at 2227 * 2228 * http://www.apache.org/licenses/LICENSE-2.0 2229 * 2230 * Unless required by applicable law or agreed to in writing, software 2231 * distributed under the License is distributed on an "AS IS" BASIS, 2232 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2233 * See the License for the specific language governing permissions and 2234 * limitations under the License. 2235 * 2236 * @providesModule EventListener 2237 */ 2238 2239 /** 2240 * Upstream version of event listener. Does not take into account specific 2241 * nature of platform. 2242 */ 2243 var EventListener = { 2244 /** 2245 * Listens to bubbled events on a DOM node. 2246 * 2247 * @param {Element} el DOM element to register listener on. 2248 * @param {string} handlerBaseName 'click'/'mouseover' 2249 * @param {Function!} cb Callback function 2250 */ 2251 listen: function(el, handlerBaseName, cb) { 2252 if (el.addEventListener) { 2253 el.addEventListener(handlerBaseName, cb, false); 2254 } else if (el.attachEvent) { 2255 el.attachEvent('on' + handlerBaseName, cb); 2256 } 2257 }, 2258 2259 /** 2260 * Listens to captured events on a DOM node. 2261 * 2262 * @see `EventListener.listen` for params. 2263 * @throws Exception if addEventListener is not supported. 2264 */ 2265 capture: function(el, handlerBaseName, cb) { 2266 if (!el.addEventListener) { 2267 if ("production" !== "development") { 2268 console.error( 2269 'You are attempting to use addEventListener ' + 2270 'in a browser that does not support it.' + 2271 'This likely means that you will not receive events that ' + 2272 'your application relies on (such as scroll).'); 2273 } 2274 return; 2275 } else { 2276 el.addEventListener(handlerBaseName, cb, true); 2277 } 2278 } 2279 }; 2280 2281 module.exports = EventListener; 2282 2283 },{}],17:[function(require,module,exports){ 2284 /** 2285 * Copyright 2013 Facebook, Inc. 2286 * 2287 * Licensed under the Apache License, Version 2.0 (the "License"); 2288 * you may not use this file except in compliance with the License. 2289 * You may obtain a copy of the License at 2290 * 2291 * http://www.apache.org/licenses/LICENSE-2.0 2292 * 2293 * Unless required by applicable law or agreed to in writing, software 2294 * distributed under the License is distributed on an "AS IS" BASIS, 2295 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2296 * See the License for the specific language governing permissions and 2297 * limitations under the License. 2298 * 2299 * @providesModule EventPluginHub 2300 */ 2301 2302 "use strict"; 2303 2304 var CallbackRegistry = require("./CallbackRegistry"); 2305 var EventPluginRegistry = require("./EventPluginRegistry"); 2306 var EventPluginUtils = require("./EventPluginUtils"); 2307 var EventPropagators = require("./EventPropagators"); 2308 var ExecutionEnvironment = require("./ExecutionEnvironment"); 2309 2310 var accumulate = require("./accumulate"); 2311 var forEachAccumulated = require("./forEachAccumulated"); 2312 var invariant = require("./invariant"); 2313 2314 /** 2315 * Internal queue of events that have accumulated their dispatches and are 2316 * waiting to have their dispatches executed. 2317 */ 2318 var eventQueue = null; 2319 2320 /** 2321 * Dispatches an event and releases it back into the pool, unless persistent. 2322 * 2323 * @param {?object} event Synthetic event to be dispatched. 2324 * @private 2325 */ 2326 var executeDispatchesAndRelease = function(event) { 2327 if (event) { 2328 var executeDispatch = EventPluginUtils.executeDispatch; 2329 // Plugins can provide custom behavior when dispatching events. 2330 var PluginModule = EventPluginRegistry.getPluginModuleForEvent(event); 2331 if (PluginModule && PluginModule.executeDispatch) { 2332 executeDispatch = PluginModule.executeDispatch; 2333 } 2334 EventPluginUtils.executeDispatchesInOrder(event, executeDispatch); 2335 2336 if (!event.isPersistent()) { 2337 event.constructor.release(event); 2338 } 2339 } 2340 }; 2341 2342 /** 2343 * This is a unified interface for event plugins to be installed and configured. 2344 * 2345 * Event plugins can implement the following properties: 2346 * 2347 * `extractEvents` {function(string, DOMEventTarget, string, object): *} 2348 * Required. When a top-level event is fired, this method is expected to 2349 * extract synthetic events that will in turn be queued and dispatched. 2350 * 2351 * `eventTypes` {object} 2352 * Optional, plugins that fire events must publish a mapping of registration 2353 * names that are used to register listeners. Values of this mapping must 2354 * be objects that contain `registrationName` or `phasedRegistrationNames`. 2355 * 2356 * `executeDispatch` {function(object, function, string)} 2357 * Optional, allows plugins to override how an event gets dispatched. By 2358 * default, the listener is simply invoked. 2359 * 2360 * Each plugin that is injected into `EventsPluginHub` is immediately operable. 2361 * 2362 * @public 2363 */ 2364 var EventPluginHub = { 2365 2366 /** 2367 * Methods for injecting dependencies. 2368 */ 2369 injection: { 2370 2371 /** 2372 * @param {object} InjectedInstanceHandle 2373 * @public 2374 */ 2375 injectInstanceHandle: EventPropagators.injection.injectInstanceHandle, 2376 2377 /** 2378 * @param {array} InjectedEventPluginOrder 2379 * @public 2380 */ 2381 injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder, 2382 2383 /** 2384 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 2385 */ 2386 injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName 2387 2388 }, 2389 2390 registrationNames: EventPluginRegistry.registrationNames, 2391 2392 putListener: CallbackRegistry.putListener, 2393 2394 getListener: CallbackRegistry.getListener, 2395 2396 deleteListener: CallbackRegistry.deleteListener, 2397 2398 deleteAllListeners: CallbackRegistry.deleteAllListeners, 2399 2400 /** 2401 * Allows registered plugins an opportunity to extract events from top-level 2402 * native browser events. 2403 * 2404 * @param {string} topLevelType Record from `EventConstants`. 2405 * @param {DOMEventTarget} topLevelTarget The listening component root node. 2406 * @param {string} topLevelTargetID ID of `topLevelTarget`. 2407 * @param {object} nativeEvent Native browser event. 2408 * @return {*} An accumulation of synthetic events. 2409 * @internal 2410 */ 2411 extractEvents: function( 2412 topLevelType, 2413 topLevelTarget, 2414 topLevelTargetID, 2415 nativeEvent) { 2416 var events; 2417 var plugins = EventPluginRegistry.plugins; 2418 for (var i = 0, l = plugins.length; i < l; i++) { 2419 // Not every plugin in the ordering may be loaded at runtime. 2420 var possiblePlugin = plugins[i]; 2421 if (possiblePlugin) { 2422 var extractedEvents = possiblePlugin.extractEvents( 2423 topLevelType, 2424 topLevelTarget, 2425 topLevelTargetID, 2426 nativeEvent 2427 ); 2428 if (extractedEvents) { 2429 events = accumulate(events, extractedEvents); 2430 } 2431 } 2432 } 2433 return events; 2434 }, 2435 2436 /** 2437 * Enqueues a synthetic event that should be dispatched when 2438 * `processEventQueue` is invoked. 2439 * 2440 * @param {*} events An accumulation of synthetic events. 2441 * @internal 2442 */ 2443 enqueueEvents: function(events) { 2444 if (events) { 2445 eventQueue = accumulate(eventQueue, events); 2446 } 2447 }, 2448 2449 /** 2450 * Dispatches all synthetic events on the event queue. 2451 * 2452 * @internal 2453 */ 2454 processEventQueue: function() { 2455 // Set `eventQueue` to null before processing it so that we can tell if more 2456 // events get enqueued while processing. 2457 var processingEventQueue = eventQueue; 2458 eventQueue = null; 2459 forEachAccumulated(processingEventQueue, executeDispatchesAndRelease); 2460 ("production" !== "development" ? invariant( 2461 !eventQueue, 2462 'processEventQueue(): Additional events were enqueued while processing ' + 2463 'an event queue. Support for this has not yet been implemented.' 2464 ) : invariant(!eventQueue)); 2465 } 2466 2467 }; 2468 2469 if (ExecutionEnvironment.canUseDOM) { 2470 window.EventPluginHub = EventPluginHub; 2471 } 2472 2473 module.exports = EventPluginHub; 2474 2475 },{"./CallbackRegistry":5,"./EventPluginRegistry":18,"./EventPluginUtils":19,"./EventPropagators":20,"./ExecutionEnvironment":21,"./accumulate":85,"./forEachAccumulated":99,"./invariant":109}],18:[function(require,module,exports){ 2476 /** 2477 * Copyright 2013 Facebook, Inc. 2478 * 2479 * Licensed under the Apache License, Version 2.0 (the "License"); 2480 * you may not use this file except in compliance with the License. 2481 * You may obtain a copy of the License at 2482 * 2483 * http://www.apache.org/licenses/LICENSE-2.0 2484 * 2485 * Unless required by applicable law or agreed to in writing, software 2486 * distributed under the License is distributed on an "AS IS" BASIS, 2487 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2488 * See the License for the specific language governing permissions and 2489 * limitations under the License. 2490 * 2491 * @providesModule EventPluginRegistry 2492 * @typechecks static-only 2493 */ 2494 2495 "use strict"; 2496 2497 var invariant = require("./invariant"); 2498 2499 /** 2500 * Injectable ordering of event plugins. 2501 */ 2502 var EventPluginOrder = null; 2503 2504 /** 2505 * Injectable mapping from names to event plugin modules. 2506 */ 2507 var namesToPlugins = {}; 2508 2509 /** 2510 * Recomputes the plugin list using the injected plugins and plugin ordering. 2511 * 2512 * @private 2513 */ 2514 function recomputePluginOrdering() { 2515 if (!EventPluginOrder) { 2516 // Wait until an `EventPluginOrder` is injected. 2517 return; 2518 } 2519 for (var pluginName in namesToPlugins) { 2520 var PluginModule = namesToPlugins[pluginName]; 2521 var pluginIndex = EventPluginOrder.indexOf(pluginName); 2522 ("production" !== "development" ? invariant( 2523 pluginIndex > -1, 2524 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 2525 'the plugin ordering, `%s`.', 2526 pluginName 2527 ) : invariant(pluginIndex > -1)); 2528 if (EventPluginRegistry.plugins[pluginIndex]) { 2529 continue; 2530 } 2531 ("production" !== "development" ? invariant( 2532 PluginModule.extractEvents, 2533 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 2534 'method, but `%s` does not.', 2535 pluginName 2536 ) : invariant(PluginModule.extractEvents)); 2537 EventPluginRegistry.plugins[pluginIndex] = PluginModule; 2538 var publishedEvents = PluginModule.eventTypes; 2539 for (var eventName in publishedEvents) { 2540 ("production" !== "development" ? invariant( 2541 publishEventForPlugin(publishedEvents[eventName], PluginModule), 2542 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', 2543 eventName, 2544 pluginName 2545 ) : invariant(publishEventForPlugin(publishedEvents[eventName], PluginModule))); 2546 } 2547 } 2548 } 2549 2550 /** 2551 * Publishes an event so that it can be dispatched by the supplied plugin. 2552 * 2553 * @param {object} dispatchConfig Dispatch configuration for the event. 2554 * @param {object} PluginModule Plugin publishing the event. 2555 * @return {boolean} True if the event was successfully published. 2556 * @private 2557 */ 2558 function publishEventForPlugin(dispatchConfig, PluginModule) { 2559 var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; 2560 if (phasedRegistrationNames) { 2561 for (var phaseName in phasedRegistrationNames) { 2562 if (phasedRegistrationNames.hasOwnProperty(phaseName)) { 2563 var phasedRegistrationName = phasedRegistrationNames[phaseName]; 2564 publishRegistrationName(phasedRegistrationName, PluginModule); 2565 } 2566 } 2567 return true; 2568 } else if (dispatchConfig.registrationName) { 2569 publishRegistrationName(dispatchConfig.registrationName, PluginModule); 2570 return true; 2571 } 2572 return false; 2573 } 2574 2575 /** 2576 * Publishes a registration name that is used to identify dispatched events and 2577 * can be used with `EventPluginHub.putListener` to register listeners. 2578 * 2579 * @param {string} registrationName Registration name to add. 2580 * @param {object} PluginModule Plugin publishing the event. 2581 * @private 2582 */ 2583 function publishRegistrationName(registrationName, PluginModule) { 2584 ("production" !== "development" ? invariant( 2585 !EventPluginRegistry.registrationNames[registrationName], 2586 'EventPluginHub: More than one plugin attempted to publish the same ' + 2587 'registration name, `%s`.', 2588 registrationName 2589 ) : invariant(!EventPluginRegistry.registrationNames[registrationName])); 2590 EventPluginRegistry.registrationNames[registrationName] = PluginModule; 2591 } 2592 2593 /** 2594 * Registers plugins so that they can extract and dispatch events. 2595 * 2596 * @see {EventPluginHub} 2597 */ 2598 var EventPluginRegistry = { 2599 2600 /** 2601 * Ordered list of injected plugins. 2602 */ 2603 plugins: [], 2604 2605 /** 2606 * Mapping from registration names to plugin modules. 2607 */ 2608 registrationNames: {}, 2609 2610 /** 2611 * Injects an ordering of plugins (by plugin name). This allows the ordering 2612 * to be decoupled from injection of the actual plugins so that ordering is 2613 * always deterministic regardless of packaging, on-the-fly injection, etc. 2614 * 2615 * @param {array} InjectedEventPluginOrder 2616 * @internal 2617 * @see {EventPluginHub.injection.injectEventPluginOrder} 2618 */ 2619 injectEventPluginOrder: function(InjectedEventPluginOrder) { 2620 ("production" !== "development" ? invariant( 2621 !EventPluginOrder, 2622 'EventPluginRegistry: Cannot inject event plugin ordering more than once.' 2623 ) : invariant(!EventPluginOrder)); 2624 // Clone the ordering so it cannot be dynamically mutated. 2625 EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder); 2626 recomputePluginOrdering(); 2627 }, 2628 2629 /** 2630 * Injects plugins to be used by `EventPluginHub`. The plugin names must be 2631 * in the ordering injected by `injectEventPluginOrder`. 2632 * 2633 * Plugins can be injected as part of page initialization or on-the-fly. 2634 * 2635 * @param {object} injectedNamesToPlugins Map from names to plugin modules. 2636 * @internal 2637 * @see {EventPluginHub.injection.injectEventPluginsByName} 2638 */ 2639 injectEventPluginsByName: function(injectedNamesToPlugins) { 2640 var isOrderingDirty = false; 2641 for (var pluginName in injectedNamesToPlugins) { 2642 if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { 2643 continue; 2644 } 2645 var PluginModule = injectedNamesToPlugins[pluginName]; 2646 if (namesToPlugins[pluginName] !== PluginModule) { 2647 ("production" !== "development" ? invariant( 2648 !namesToPlugins[pluginName], 2649 'EventPluginRegistry: Cannot inject two different event plugins ' + 2650 'using the same name, `%s`.', 2651 pluginName 2652 ) : invariant(!namesToPlugins[pluginName])); 2653 namesToPlugins[pluginName] = PluginModule; 2654 isOrderingDirty = true; 2655 } 2656 } 2657 if (isOrderingDirty) { 2658 recomputePluginOrdering(); 2659 } 2660 }, 2661 2662 /** 2663 * Looks up the plugin for the supplied event. 2664 * 2665 * @param {object} event A synthetic event. 2666 * @return {?object} The plugin that created the supplied event. 2667 * @internal 2668 */ 2669 getPluginModuleForEvent: function(event) { 2670 var dispatchConfig = event.dispatchConfig; 2671 if (dispatchConfig.registrationName) { 2672 return EventPluginRegistry.registrationNames[ 2673 dispatchConfig.registrationName 2674 ] || null; 2675 } 2676 for (var phase in dispatchConfig.phasedRegistrationNames) { 2677 if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) { 2678 continue; 2679 } 2680 var PluginModule = EventPluginRegistry.registrationNames[ 2681 dispatchConfig.phasedRegistrationNames[phase] 2682 ]; 2683 if (PluginModule) { 2684 return PluginModule; 2685 } 2686 } 2687 return null; 2688 }, 2689 2690 /** 2691 * Exposed for unit testing. 2692 * @private 2693 */ 2694 _resetEventPlugins: function() { 2695 EventPluginOrder = null; 2696 for (var pluginName in namesToPlugins) { 2697 if (namesToPlugins.hasOwnProperty(pluginName)) { 2698 delete namesToPlugins[pluginName]; 2699 } 2700 } 2701 EventPluginRegistry.plugins.length = 0; 2702 var registrationNames = EventPluginRegistry.registrationNames; 2703 for (var registrationName in registrationNames) { 2704 if (registrationNames.hasOwnProperty(registrationName)) { 2705 delete registrationNames[registrationName]; 2706 } 2707 } 2708 } 2709 2710 }; 2711 2712 module.exports = EventPluginRegistry; 2713 2714 },{"./invariant":109}],19:[function(require,module,exports){ 2715 /** 2716 * Copyright 2013 Facebook, Inc. 2717 * 2718 * Licensed under the Apache License, Version 2.0 (the "License"); 2719 * you may not use this file except in compliance with the License. 2720 * You may obtain a copy of the License at 2721 * 2722 * http://www.apache.org/licenses/LICENSE-2.0 2723 * 2724 * Unless required by applicable law or agreed to in writing, software 2725 * distributed under the License is distributed on an "AS IS" BASIS, 2726 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2727 * See the License for the specific language governing permissions and 2728 * limitations under the License. 2729 * 2730 * @providesModule EventPluginUtils 2731 */ 2732 2733 "use strict"; 2734 2735 var EventConstants = require("./EventConstants"); 2736 2737 var invariant = require("./invariant"); 2738 2739 var topLevelTypes = EventConstants.topLevelTypes; 2740 2741 function isEndish(topLevelType) { 2742 return topLevelType === topLevelTypes.topMouseUp || 2743 topLevelType === topLevelTypes.topTouchEnd || 2744 topLevelType === topLevelTypes.topTouchCancel; 2745 } 2746 2747 function isMoveish(topLevelType) { 2748 return topLevelType === topLevelTypes.topMouseMove || 2749 topLevelType === topLevelTypes.topTouchMove; 2750 } 2751 function isStartish(topLevelType) { 2752 return topLevelType === topLevelTypes.topMouseDown || 2753 topLevelType === topLevelTypes.topTouchStart; 2754 } 2755 2756 var validateEventDispatches; 2757 if ("production" !== "development") { 2758 validateEventDispatches = function(event) { 2759 var dispatchListeners = event._dispatchListeners; 2760 var dispatchIDs = event._dispatchIDs; 2761 2762 var listenersIsArr = Array.isArray(dispatchListeners); 2763 var idsIsArr = Array.isArray(dispatchIDs); 2764 var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0; 2765 var listenersLen = listenersIsArr ? 2766 dispatchListeners.length : 2767 dispatchListeners ? 1 : 0; 2768 2769 ("production" !== "development" ? invariant( 2770 idsIsArr === listenersIsArr && IDsLen === listenersLen, 2771 'EventPluginUtils: Invalid `event`.' 2772 ) : invariant(idsIsArr === listenersIsArr && IDsLen === listenersLen)); 2773 }; 2774 } 2775 2776 /** 2777 * Invokes `cb(event, listener, id)`. Avoids using call if no scope is 2778 * provided. The `(listener,id)` pair effectively forms the "dispatch" but are 2779 * kept separate to conserve memory. 2780 */ 2781 function forEachEventDispatch(event, cb) { 2782 var dispatchListeners = event._dispatchListeners; 2783 var dispatchIDs = event._dispatchIDs; 2784 if ("production" !== "development") { 2785 validateEventDispatches(event); 2786 } 2787 if (Array.isArray(dispatchListeners)) { 2788 for (var i = 0; i < dispatchListeners.length; i++) { 2789 if (event.isPropagationStopped()) { 2790 break; 2791 } 2792 // Listeners and IDs are two parallel arrays that are always in sync. 2793 cb(event, dispatchListeners[i], dispatchIDs[i]); 2794 } 2795 } else if (dispatchListeners) { 2796 cb(event, dispatchListeners, dispatchIDs); 2797 } 2798 } 2799 2800 /** 2801 * Default implementation of PluginModule.executeDispatch(). 2802 * @param {SyntheticEvent} SyntheticEvent to handle 2803 * @param {function} Application-level callback 2804 * @param {string} domID DOM id to pass to the callback. 2805 */ 2806 function executeDispatch(event, listener, domID) { 2807 listener(event, domID); 2808 } 2809 2810 /** 2811 * Standard/simple iteration through an event's collected dispatches. 2812 */ 2813 function executeDispatchesInOrder(event, executeDispatch) { 2814 forEachEventDispatch(event, executeDispatch); 2815 event._dispatchListeners = null; 2816 event._dispatchIDs = null; 2817 } 2818 2819 /** 2820 * Standard/simple iteration through an event's collected dispatches, but stops 2821 * at the first dispatch execution returning true, and returns that id. 2822 * 2823 * @return id of the first dispatch execution who's listener returns true, or 2824 * null if no listener returned true. 2825 */ 2826 function executeDispatchesInOrderStopAtTrue(event) { 2827 var dispatchListeners = event._dispatchListeners; 2828 var dispatchIDs = event._dispatchIDs; 2829 if ("production" !== "development") { 2830 validateEventDispatches(event); 2831 } 2832 if (Array.isArray(dispatchListeners)) { 2833 for (var i = 0; i < dispatchListeners.length; i++) { 2834 if (event.isPropagationStopped()) { 2835 break; 2836 } 2837 // Listeners and IDs are two parallel arrays that are always in sync. 2838 if (dispatchListeners[i](event, dispatchIDs[i])) { 2839 return dispatchIDs[i]; 2840 } 2841 } 2842 } else if (dispatchListeners) { 2843 if (dispatchListeners(event, dispatchIDs)) { 2844 return dispatchIDs; 2845 } 2846 } 2847 return null; 2848 } 2849 2850 /** 2851 * Execution of a "direct" dispatch - there must be at most one dispatch 2852 * accumulated on the event or it is considered an error. It doesn't really make 2853 * sense for an event with multiple dispatches (bubbled) to keep track of the 2854 * return values at each dispatch execution, but it does tend to make sense when 2855 * dealing with "direct" dispatches. 2856 * 2857 * @return The return value of executing the single dispatch. 2858 */ 2859 function executeDirectDispatch(event) { 2860 if ("production" !== "development") { 2861 validateEventDispatches(event); 2862 } 2863 var dispatchListener = event._dispatchListeners; 2864 var dispatchID = event._dispatchIDs; 2865 ("production" !== "development" ? invariant( 2866 !Array.isArray(dispatchListener), 2867 'executeDirectDispatch(...): Invalid `event`.' 2868 ) : invariant(!Array.isArray(dispatchListener))); 2869 var res = dispatchListener ? 2870 dispatchListener(event, dispatchID) : 2871 null; 2872 event._dispatchListeners = null; 2873 event._dispatchIDs = null; 2874 return res; 2875 } 2876 2877 /** 2878 * @param {SyntheticEvent} event 2879 * @return {bool} True iff number of dispatches accumulated is greater than 0. 2880 */ 2881 function hasDispatches(event) { 2882 return !!event._dispatchListeners; 2883 } 2884 2885 /** 2886 * General utilities that are useful in creating custom Event Plugins. 2887 */ 2888 var EventPluginUtils = { 2889 isEndish: isEndish, 2890 isMoveish: isMoveish, 2891 isStartish: isStartish, 2892 executeDispatchesInOrder: executeDispatchesInOrder, 2893 executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, 2894 executeDirectDispatch: executeDirectDispatch, 2895 hasDispatches: hasDispatches, 2896 executeDispatch: executeDispatch 2897 }; 2898 2899 module.exports = EventPluginUtils; 2900 2901 },{"./EventConstants":15,"./invariant":109}],20:[function(require,module,exports){ 2902 /** 2903 * Copyright 2013 Facebook, Inc. 2904 * 2905 * Licensed under the Apache License, Version 2.0 (the "License"); 2906 * you may not use this file except in compliance with the License. 2907 * You may obtain a copy of the License at 2908 * 2909 * http://www.apache.org/licenses/LICENSE-2.0 2910 * 2911 * Unless required by applicable law or agreed to in writing, software 2912 * distributed under the License is distributed on an "AS IS" BASIS, 2913 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2914 * See the License for the specific language governing permissions and 2915 * limitations under the License. 2916 * 2917 * @providesModule EventPropagators 2918 */ 2919 2920 "use strict"; 2921 2922 var CallbackRegistry = require("./CallbackRegistry"); 2923 var EventConstants = require("./EventConstants"); 2924 2925 var accumulate = require("./accumulate"); 2926 var forEachAccumulated = require("./forEachAccumulated"); 2927 var getListener = CallbackRegistry.getListener; 2928 var PropagationPhases = EventConstants.PropagationPhases; 2929 2930 /** 2931 * Injected dependencies: 2932 */ 2933 2934 /** 2935 * - `InstanceHandle`: [required] Module that performs logical traversals of DOM 2936 * hierarchy given ids of the logical DOM elements involved. 2937 */ 2938 var injection = { 2939 InstanceHandle: null, 2940 injectInstanceHandle: function(InjectedInstanceHandle) { 2941 injection.InstanceHandle = InjectedInstanceHandle; 2942 if ("production" !== "development") { 2943 injection.validate(); 2944 } 2945 }, 2946 validate: function() { 2947 var invalid = !injection.InstanceHandle|| 2948 !injection.InstanceHandle.traverseTwoPhase || 2949 !injection.InstanceHandle.traverseEnterLeave; 2950 if (invalid) { 2951 throw new Error('InstanceHandle not injected before use!'); 2952 } 2953 } 2954 }; 2955 2956 /** 2957 * Some event types have a notion of different registration names for different 2958 * "phases" of propagation. This finds listeners by a given phase. 2959 */ 2960 function listenerAtPhase(id, event, propagationPhase) { 2961 var registrationName = 2962 event.dispatchConfig.phasedRegistrationNames[propagationPhase]; 2963 return getListener(id, registrationName); 2964 } 2965 2966 /** 2967 * Tags a `SyntheticEvent` with dispatched listeners. Creating this function 2968 * here, allows us to not have to bind or create functions for each event. 2969 * Mutating the event's members allows us to not have to create a wrapping 2970 * "dispatch" object that pairs the event with the listener. 2971 */ 2972 function accumulateDirectionalDispatches(domID, upwards, event) { 2973 if ("production" !== "development") { 2974 if (!domID) { 2975 throw new Error('Dispatching id must not be null'); 2976 } 2977 injection.validate(); 2978 } 2979 var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; 2980 var listener = listenerAtPhase(domID, event, phase); 2981 if (listener) { 2982 event._dispatchListeners = accumulate(event._dispatchListeners, listener); 2983 event._dispatchIDs = accumulate(event._dispatchIDs, domID); 2984 } 2985 } 2986 2987 /** 2988 * Collect dispatches (must be entirely collected before dispatching - see unit 2989 * tests). Lazily allocate the array to conserve memory. We must loop through 2990 * each event and perform the traversal for each one. We can not perform a 2991 * single traversal for the entire collection of events because each event may 2992 * have a different target. 2993 */ 2994 function accumulateTwoPhaseDispatchesSingle(event) { 2995 if (event && event.dispatchConfig.phasedRegistrationNames) { 2996 injection.InstanceHandle.traverseTwoPhase( 2997 event.dispatchMarker, 2998 accumulateDirectionalDispatches, 2999 event 3000 ); 3001 } 3002 } 3003 3004 3005 /** 3006 * Accumulates without regard to direction, does not look for phased 3007 * registration names. Same as `accumulateDirectDispatchesSingle` but without 3008 * requiring that the `dispatchMarker` be the same as the dispatched ID. 3009 */ 3010 function accumulateDispatches(id, ignoredDirection, event) { 3011 if (event && event.dispatchConfig.registrationName) { 3012 var registrationName = event.dispatchConfig.registrationName; 3013 var listener = getListener(id, registrationName); 3014 if (listener) { 3015 event._dispatchListeners = accumulate(event._dispatchListeners, listener); 3016 event._dispatchIDs = accumulate(event._dispatchIDs, id); 3017 } 3018 } 3019 } 3020 3021 /** 3022 * Accumulates dispatches on an `SyntheticEvent`, but only for the 3023 * `dispatchMarker`. 3024 * @param {SyntheticEvent} event 3025 */ 3026 function accumulateDirectDispatchesSingle(event) { 3027 if (event && event.dispatchConfig.registrationName) { 3028 accumulateDispatches(event.dispatchMarker, null, event); 3029 } 3030 } 3031 3032 function accumulateTwoPhaseDispatches(events) { 3033 if ("production" !== "development") { 3034 injection.validate(); 3035 } 3036 forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); 3037 } 3038 3039 function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) { 3040 if ("production" !== "development") { 3041 injection.validate(); 3042 } 3043 injection.InstanceHandle.traverseEnterLeave( 3044 fromID, 3045 toID, 3046 accumulateDispatches, 3047 leave, 3048 enter 3049 ); 3050 } 3051 3052 3053 function accumulateDirectDispatches(events) { 3054 if ("production" !== "development") { 3055 injection.validate(); 3056 } 3057 forEachAccumulated(events, accumulateDirectDispatchesSingle); 3058 } 3059 3060 3061 3062 /** 3063 * A small set of propagation patterns, each of which will accept a small amount 3064 * of information, and generate a set of "dispatch ready event objects" - which 3065 * are sets of events that have already been annotated with a set of dispatched 3066 * listener functions/ids. The API is designed this way to discourage these 3067 * propagation strategies from actually executing the dispatches, since we 3068 * always want to collect the entire set of dispatches before executing event a 3069 * single one. 3070 * 3071 * @constructor EventPropagators 3072 */ 3073 var EventPropagators = { 3074 accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, 3075 accumulateDirectDispatches: accumulateDirectDispatches, 3076 accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches, 3077 injection: injection 3078 }; 3079 3080 module.exports = EventPropagators; 3081 3082 },{"./CallbackRegistry":5,"./EventConstants":15,"./accumulate":85,"./forEachAccumulated":99}],21:[function(require,module,exports){ 3083 /** 3084 * Copyright 2013 Facebook, Inc. 3085 * 3086 * Licensed under the Apache License, Version 2.0 (the "License"); 3087 * you may not use this file except in compliance with the License. 3088 * You may obtain a copy of the License at 3089 * 3090 * http://www.apache.org/licenses/LICENSE-2.0 3091 * 3092 * Unless required by applicable law or agreed to in writing, software 3093 * distributed under the License is distributed on an "AS IS" BASIS, 3094 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3095 * See the License for the specific language governing permissions and 3096 * limitations under the License. 3097 * 3098 * @providesModule ExecutionEnvironment 3099 */ 3100 3101 /*jslint evil: true */ 3102 3103 "use strict"; 3104 3105 var canUseDOM = typeof window !== 'undefined'; 3106 3107 /** 3108 * Simple, lightweight module assisting with the detection and context of 3109 * Worker. Helps avoid circular dependencies and allows code to reason about 3110 * whether or not they are in a Worker, even if they never include the main 3111 * `ReactWorker` dependency. 3112 */ 3113 var ExecutionEnvironment = { 3114 3115 canUseDOM: canUseDOM, 3116 3117 canUseWorkers: typeof Worker !== 'undefined', 3118 3119 isInWorker: !canUseDOM // For now, this is true - might change in the future. 3120 3121 }; 3122 3123 module.exports = ExecutionEnvironment; 3124 3125 },{}],22:[function(require,module,exports){ 3126 /** 3127 * Copyright 2013 Facebook, Inc. 3128 * 3129 * Licensed under the Apache License, Version 2.0 (the "License"); 3130 * you may not use this file except in compliance with the License. 3131 * You may obtain a copy of the License at 3132 * 3133 * http://www.apache.org/licenses/LICENSE-2.0 3134 * 3135 * Unless required by applicable law or agreed to in writing, software 3136 * distributed under the License is distributed on an "AS IS" BASIS, 3137 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3138 * See the License for the specific language governing permissions and 3139 * limitations under the License. 3140 * 3141 * @providesModule LinkedStateMixin 3142 * @typechecks static-only 3143 */ 3144 3145 "use strict"; 3146 3147 var ReactLink = require("./ReactLink"); 3148 var ReactStateSetters = require("./ReactStateSetters"); 3149 3150 /** 3151 * A simple mixin around ReactLink.forState(). 3152 */ 3153 var LinkedStateMixin = { 3154 /** 3155 * Create a ReactLink that's linked to part of this component's state. The 3156 * ReactLink will have the current value of this.state[key] and will call 3157 * setState() when a change is requested. 3158 * 3159 * @param {string} key state key to update. Note: you may want to use keyOf() 3160 * if you're using Google Closure Compiler advanced mode. 3161 * @return {ReactLink} ReactLink instance linking to the state. 3162 */ 3163 linkState: function(key) { 3164 return new ReactLink( 3165 this.state[key], 3166 ReactStateSetters.createStateKeySetter(this, key) 3167 ); 3168 } 3169 }; 3170 3171 module.exports = LinkedStateMixin; 3172 3173 },{"./ReactLink":52,"./ReactStateSetters":64}],23:[function(require,module,exports){ 3174 /** 3175 * Copyright 2013 Facebook, Inc. 3176 * 3177 * Licensed under the Apache License, Version 2.0 (the "License"); 3178 * you may not use this file except in compliance with the License. 3179 * You may obtain a copy of the License at 3180 * 3181 * http://www.apache.org/licenses/LICENSE-2.0 3182 * 3183 * Unless required by applicable law or agreed to in writing, software 3184 * distributed under the License is distributed on an "AS IS" BASIS, 3185 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3186 * See the License for the specific language governing permissions and 3187 * limitations under the License. 3188 * 3189 * @providesModule LinkedValueMixin 3190 * @typechecks static-only 3191 */ 3192 3193 "use strict"; 3194 3195 var invariant = require("./invariant"); 3196 3197 /** 3198 * Provide a linked `value` attribute for controlled forms. You should not use 3199 * this outside of the ReactDOM controlled form components. 3200 */ 3201 var LinkedValueMixin = { 3202 _assertLink: function() { 3203 ("production" !== "development" ? invariant( 3204 this.props.value == null && this.props.onChange == null, 3205 'Cannot provide a valueLink and a value or onChange event. If you ' + 3206 'want to use value or onChange, you probably don\'t want to use ' + 3207 'valueLink' 3208 ) : invariant(this.props.value == null && this.props.onChange == null)); 3209 }, 3210 3211 /** 3212 * @return {*} current value of the input either from value prop or link. 3213 */ 3214 getValue: function() { 3215 if (this.props.valueLink) { 3216 this._assertLink(); 3217 return this.props.valueLink.value; 3218 } 3219 return this.props.value; 3220 }, 3221 3222 /** 3223 * @return {function} change callback either from onChange prop or link. 3224 */ 3225 getOnChange: function() { 3226 if (this.props.valueLink) { 3227 this._assertLink(); 3228 return this._handleLinkedValueChange; 3229 } 3230 return this.props.onChange; 3231 }, 3232 3233 /** 3234 * @param {SyntheticEvent} e change event to handle 3235 */ 3236 _handleLinkedValueChange: function(e) { 3237 this.props.valueLink.requestChange(e.target.value); 3238 } 3239 }; 3240 3241 module.exports = LinkedValueMixin; 3242 3243 },{"./invariant":109}],24:[function(require,module,exports){ 3244 /** 3245 * Copyright 2013 Facebook, Inc. 3246 * 3247 * Licensed under the Apache License, Version 2.0 (the "License"); 3248 * you may not use this file except in compliance with the License. 3249 * You may obtain a copy of the License at 3250 * 3251 * http://www.apache.org/licenses/LICENSE-2.0 3252 * 3253 * Unless required by applicable law or agreed to in writing, software 3254 * distributed under the License is distributed on an "AS IS" BASIS, 3255 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3256 * See the License for the specific language governing permissions and 3257 * limitations under the License. 3258 * 3259 * @providesModule MobileSafariClickEventPlugin 3260 * @typechecks static-only 3261 */ 3262 3263 "use strict"; 3264 3265 var EventConstants = require("./EventConstants"); 3266 3267 var emptyFunction = require("./emptyFunction"); 3268 3269 var topLevelTypes = EventConstants.topLevelTypes; 3270 3271 /** 3272 * Mobile Safari does not fire properly bubble click events on non-interactive 3273 * elements, which means delegated click listeners do not fire. The workaround 3274 * for this bug involves attaching an empty click listener on the target node. 3275 * 3276 * This particular plugin works around the bug by attaching an empty click 3277 * listener on `touchstart` (which does fire on every element). 3278 */ 3279 var MobileSafariClickEventPlugin = { 3280 3281 eventTypes: null, 3282 3283 /** 3284 * @param {string} topLevelType Record from `EventConstants`. 3285 * @param {DOMEventTarget} topLevelTarget The listening component root node. 3286 * @param {string} topLevelTargetID ID of `topLevelTarget`. 3287 * @param {object} nativeEvent Native browser event. 3288 * @return {*} An accumulation of synthetic events. 3289 * @see {EventPluginHub.extractEvents} 3290 */ 3291 extractEvents: function( 3292 topLevelType, 3293 topLevelTarget, 3294 topLevelTargetID, 3295 nativeEvent) { 3296 if (topLevelType === topLevelTypes.topTouchStart) { 3297 var target = nativeEvent.target; 3298 if (target && !target.onclick) { 3299 target.onclick = emptyFunction; 3300 } 3301 } 3302 } 3303 3304 }; 3305 3306 module.exports = MobileSafariClickEventPlugin; 3307 3308 },{"./EventConstants":15,"./emptyFunction":94}],25:[function(require,module,exports){ 3309 /** 3310 * Copyright 2013 Facebook, Inc. 3311 * 3312 * Licensed under the Apache License, Version 2.0 (the "License"); 3313 * you may not use this file except in compliance with the License. 3314 * You may obtain a copy of the License at 3315 * 3316 * http://www.apache.org/licenses/LICENSE-2.0 3317 * 3318 * Unless required by applicable law or agreed to in writing, software 3319 * distributed under the License is distributed on an "AS IS" BASIS, 3320 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3321 * See the License for the specific language governing permissions and 3322 * limitations under the License. 3323 * 3324 * @providesModule PooledClass 3325 */ 3326 3327 "use strict"; 3328 3329 /** 3330 * Static poolers. Several custom versions for each potential number of 3331 * arguments. A completely generic pooler is easy to implement, but would 3332 * require accessing the `arguments` object. In each of these, `this` refers to 3333 * the Class itself, not an instance. If any others are needed, simply add them 3334 * here, or in their own files. 3335 */ 3336 var oneArgumentPooler = function(copyFieldsFrom) { 3337 var Klass = this; 3338 if (Klass.instancePool.length) { 3339 var instance = Klass.instancePool.pop(); 3340 Klass.call(instance, copyFieldsFrom); 3341 return instance; 3342 } else { 3343 return new Klass(copyFieldsFrom); 3344 } 3345 }; 3346 3347 var twoArgumentPooler = function(a1, a2) { 3348 var Klass = this; 3349 if (Klass.instancePool.length) { 3350 var instance = Klass.instancePool.pop(); 3351 Klass.call(instance, a1, a2); 3352 return instance; 3353 } else { 3354 return new Klass(a1, a2); 3355 } 3356 }; 3357 3358 var threeArgumentPooler = function(a1, a2, a3) { 3359 var Klass = this; 3360 if (Klass.instancePool.length) { 3361 var instance = Klass.instancePool.pop(); 3362 Klass.call(instance, a1, a2, a3); 3363 return instance; 3364 } else { 3365 return new Klass(a1, a2, a3); 3366 } 3367 }; 3368 3369 var fiveArgumentPooler = function(a1, a2, a3, a4, a5) { 3370 var Klass = this; 3371 if (Klass.instancePool.length) { 3372 var instance = Klass.instancePool.pop(); 3373 Klass.call(instance, a1, a2, a3, a4, a5); 3374 return instance; 3375 } else { 3376 return new Klass(a1, a2, a3, a4, a5); 3377 } 3378 }; 3379 3380 var standardReleaser = function(instance) { 3381 var Klass = this; 3382 if (instance.destructor) { 3383 instance.destructor(); 3384 } 3385 if (Klass.instancePool.length < Klass.poolSize) { 3386 Klass.instancePool.push(instance); 3387 } 3388 }; 3389 3390 var DEFAULT_POOL_SIZE = 10; 3391 var DEFAULT_POOLER = oneArgumentPooler; 3392 3393 /** 3394 * Augments `CopyConstructor` to be a poolable class, augmenting only the class 3395 * itself (statically) not adding any prototypical fields. Any CopyConstructor 3396 * you give this may have a `poolSize` property, and will look for a 3397 * prototypical `destructor` on instances (optional). 3398 * 3399 * @param {Function} CopyConstructor Constructor that can be used to reset. 3400 * @param {Function} pooler Customizable pooler. 3401 */ 3402 var addPoolingTo = function(CopyConstructor, pooler) { 3403 var NewKlass = CopyConstructor; 3404 NewKlass.instancePool = []; 3405 NewKlass.getPooled = pooler || DEFAULT_POOLER; 3406 if (!NewKlass.poolSize) { 3407 NewKlass.poolSize = DEFAULT_POOL_SIZE; 3408 } 3409 NewKlass.release = standardReleaser; 3410 return NewKlass; 3411 }; 3412 3413 var PooledClass = { 3414 addPoolingTo: addPoolingTo, 3415 oneArgumentPooler: oneArgumentPooler, 3416 twoArgumentPooler: twoArgumentPooler, 3417 threeArgumentPooler: threeArgumentPooler, 3418 fiveArgumentPooler: fiveArgumentPooler 3419 }; 3420 3421 module.exports = PooledClass; 3422 3423 },{}],26:[function(require,module,exports){ 3424 /** 3425 * Copyright 2013 Facebook, Inc. 3426 * 3427 * Licensed under the Apache License, Version 2.0 (the "License"); 3428 * you may not use this file except in compliance with the License. 3429 * You may obtain a copy of the License at 3430 * 3431 * http://www.apache.org/licenses/LICENSE-2.0 3432 * 3433 * Unless required by applicable law or agreed to in writing, software 3434 * distributed under the License is distributed on an "AS IS" BASIS, 3435 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3436 * See the License for the specific language governing permissions and 3437 * limitations under the License. 3438 * 3439 * @providesModule React 3440 */ 3441 3442 "use strict"; 3443 3444 var ReactComponent = require("./ReactComponent"); 3445 var ReactCompositeComponent = require("./ReactCompositeComponent"); 3446 var ReactCurrentOwner = require("./ReactCurrentOwner"); 3447 var ReactDOM = require("./ReactDOM"); 3448 var ReactDOMComponent = require("./ReactDOMComponent"); 3449 var ReactDefaultInjection = require("./ReactDefaultInjection"); 3450 var ReactInstanceHandles = require("./ReactInstanceHandles"); 3451 var ReactMount = require("./ReactMount"); 3452 var ReactMultiChild = require("./ReactMultiChild"); 3453 var ReactPerf = require("./ReactPerf"); 3454 var ReactPropTypes = require("./ReactPropTypes"); 3455 var ReactServerRendering = require("./ReactServerRendering"); 3456 var ReactTextComponent = require("./ReactTextComponent"); 3457 3458 ReactDefaultInjection.inject(); 3459 3460 var React = { 3461 DOM: ReactDOM, 3462 PropTypes: ReactPropTypes, 3463 initializeTouchEvents: function(shouldUseTouch) { 3464 ReactMount.useTouchEvents = shouldUseTouch; 3465 }, 3466 createClass: ReactCompositeComponent.createClass, 3467 constructAndRenderComponent: ReactMount.constructAndRenderComponent, 3468 constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, 3469 renderComponent: ReactPerf.measure( 3470 'React', 3471 'renderComponent', 3472 ReactMount.renderComponent 3473 ), 3474 renderComponentToString: ReactServerRendering.renderComponentToString, 3475 unmountComponentAtNode: ReactMount.unmountComponentAtNode, 3476 unmountAndReleaseReactRootNode: ReactMount.unmountAndReleaseReactRootNode, 3477 isValidClass: ReactCompositeComponent.isValidClass, 3478 isValidComponent: ReactComponent.isValidComponent, 3479 __internals: { 3480 Component: ReactComponent, 3481 CurrentOwner: ReactCurrentOwner, 3482 DOMComponent: ReactDOMComponent, 3483 InstanceHandles: ReactInstanceHandles, 3484 Mount: ReactMount, 3485 MultiChild: ReactMultiChild, 3486 TextComponent: ReactTextComponent 3487 } 3488 }; 3489 3490 // Version exists only in the open-source version of React, not in Facebook's 3491 // internal version. 3492 React.version = '0.8.0'; 3493 3494 module.exports = React; 3495 3496 },{"./ReactComponent":28,"./ReactCompositeComponent":31,"./ReactCurrentOwner":32,"./ReactDOM":33,"./ReactDOMComponent":35,"./ReactDefaultInjection":44,"./ReactInstanceHandles":51,"./ReactMount":54,"./ReactMultiChild":56,"./ReactPerf":59,"./ReactPropTypes":61,"./ReactServerRendering":63,"./ReactTextComponent":65}],27:[function(require,module,exports){ 3497 /** 3498 * Copyright 2013 Facebook, Inc. 3499 * 3500 * Licensed under the Apache License, Version 2.0 (the "License"); 3501 * you may not use this file except in compliance with the License. 3502 * You may obtain a copy of the License at 3503 * 3504 * http://www.apache.org/licenses/LICENSE-2.0 3505 * 3506 * Unless required by applicable law or agreed to in writing, software 3507 * distributed under the License is distributed on an "AS IS" BASIS, 3508 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3509 * See the License for the specific language governing permissions and 3510 * limitations under the License. 3511 * 3512 * @providesModule ReactChildren 3513 */ 3514 3515 "use strict"; 3516 3517 var PooledClass = require("./PooledClass"); 3518 3519 var invariant = require("./invariant"); 3520 var traverseAllChildren = require("./traverseAllChildren"); 3521 3522 var twoArgumentPooler = PooledClass.twoArgumentPooler; 3523 var threeArgumentPooler = PooledClass.threeArgumentPooler; 3524 3525 /** 3526 * PooledClass representing the bookkeeping associated with performing a child 3527 * traversal. Allows avoiding binding callbacks. 3528 * 3529 * @constructor ForEachBookKeeping 3530 * @param {!function} forEachFunction Function to perform traversal with. 3531 * @param {?*} forEachContext Context to perform context with. 3532 */ 3533 function ForEachBookKeeping(forEachFunction, forEachContext) { 3534 this.forEachFunction = forEachFunction; 3535 this.forEachContext = forEachContext; 3536 } 3537 PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); 3538 3539 function forEachSingleChild(traverseContext, child, name, i) { 3540 var forEachBookKeeping = traverseContext; 3541 forEachBookKeeping.forEachFunction.call( 3542 forEachBookKeeping.forEachContext, child, i); 3543 } 3544 3545 /** 3546 * Iterates through children that are typically specified as `props.children`. 3547 * 3548 * The provided forEachFunc(child, index) will be called for each 3549 * leaf child. 3550 * 3551 * @param {array} children 3552 * @param {function(*, int)} forEachFunc. 3553 * @param {*} forEachContext Context for forEachContext. 3554 */ 3555 function forEachChildren(children, forEachFunc, forEachContext) { 3556 if (children == null) { 3557 return children; 3558 } 3559 3560 var traverseContext = 3561 ForEachBookKeeping.getPooled(forEachFunc, forEachContext); 3562 traverseAllChildren(children, forEachSingleChild, traverseContext); 3563 ForEachBookKeeping.release(traverseContext); 3564 } 3565 3566 /** 3567 * PooledClass representing the bookkeeping associated with performing a child 3568 * mapping. Allows avoiding binding callbacks. 3569 * 3570 * @constructor MapBookKeeping 3571 * @param {!*} mapResult Object containing the ordered map of results. 3572 * @param {!function} mapFunction Function to perform mapping with. 3573 * @param {?*} mapContext Context to perform mapping with. 3574 */ 3575 function MapBookKeeping(mapResult, mapFunction, mapContext) { 3576 this.mapResult = mapResult; 3577 this.mapFunction = mapFunction; 3578 this.mapContext = mapContext; 3579 } 3580 PooledClass.addPoolingTo(MapBookKeeping, threeArgumentPooler); 3581 3582 function mapSingleChildIntoContext(traverseContext, child, name, i) { 3583 var mapBookKeeping = traverseContext; 3584 var mapResult = mapBookKeeping.mapResult; 3585 var mappedChild = 3586 mapBookKeeping.mapFunction.call(mapBookKeeping.mapContext, child, i); 3587 // We found a component instance 3588 ("production" !== "development" ? invariant( 3589 !mapResult.hasOwnProperty(name), 3590 'ReactChildren.map(...): Encountered two children with the same key, ' + 3591 '`%s`. Children keys must be unique.', 3592 name 3593 ) : invariant(!mapResult.hasOwnProperty(name))); 3594 mapResult[name] = mappedChild; 3595 } 3596 3597 /** 3598 * Maps children that are typically specified as `props.children`. 3599 * 3600 * The provided mapFunction(child, key, index) will be called for each 3601 * leaf child. 3602 * 3603 * TODO: This may likely break any calls to `ReactChildren.map` that were 3604 * previously relying on the fact that we guarded against null children. 3605 * 3606 * @param {array} children 3607 * @param {function(*, int)} mapFunction. 3608 * @param {*} mapContext Context for mapFunction. 3609 * @return {array} mirrored array with mapped children. 3610 */ 3611 function mapChildren(children, func, context) { 3612 if (children == null) { 3613 return children; 3614 } 3615 3616 var mapResult = {}; 3617 var traverseContext = MapBookKeeping.getPooled(mapResult, func, context); 3618 traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); 3619 MapBookKeeping.release(traverseContext); 3620 return mapResult; 3621 } 3622 3623 var ReactChildren = { 3624 forEach: forEachChildren, 3625 map: mapChildren 3626 }; 3627 3628 module.exports = ReactChildren; 3629 3630 },{"./PooledClass":25,"./invariant":109,"./traverseAllChildren":127}],28:[function(require,module,exports){ 3631 /** 3632 * Copyright 2013 Facebook, Inc. 3633 * 3634 * Licensed under the Apache License, Version 2.0 (the "License"); 3635 * you may not use this file except in compliance with the License. 3636 * You may obtain a copy of the License at 3637 * 3638 * http://www.apache.org/licenses/LICENSE-2.0 3639 * 3640 * Unless required by applicable law or agreed to in writing, software 3641 * distributed under the License is distributed on an "AS IS" BASIS, 3642 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 3643 * See the License for the specific language governing permissions and 3644 * limitations under the License. 3645 * 3646 * @providesModule ReactComponent 3647 */ 3648 3649 "use strict"; 3650 3651 var ReactComponentEnvironment = require("./ReactComponentEnvironment"); 3652 var ReactCurrentOwner = require("./ReactCurrentOwner"); 3653 var ReactOwner = require("./ReactOwner"); 3654 var ReactUpdates = require("./ReactUpdates"); 3655 3656 var invariant = require("./invariant"); 3657 var keyMirror = require("./keyMirror"); 3658 var merge = require("./merge"); 3659 3660 /** 3661 * Every React component is in one of these life cycles. 3662 */ 3663 var ComponentLifeCycle = keyMirror({ 3664 /** 3665 * Mounted components have a DOM node representation and are capable of 3666 * receiving new props. 3667 */ 3668 MOUNTED: null, 3669 /** 3670 * Unmounted components are inactive and cannot receive new props. 3671 */ 3672 UNMOUNTED: null 3673 }); 3674 3675 /** 3676 * Warn if there's no key explicitly set on dynamic arrays of children. 3677 * This allows us to keep track of children between updates. 3678 */ 3679 3680 var ownerHasWarned = {}; 3681 3682 /** 3683 * Warn if the component doesn't have an explicit key assigned to it. 3684 * This component is in an array. The array could grow and shrink or be 3685 * reordered. All children, that hasn't already been validated, are required to 3686 * have a "key" property assigned to it. 3687 * 3688 * @internal 3689 * @param {ReactComponent} component Component that requires a key. 3690 */ 3691 function validateExplicitKey(component) { 3692 if (component.__keyValidated__ || component.props.key != null) { 3693 return; 3694 } 3695 component.__keyValidated__ = true; 3696 3697 // We can't provide friendly warnings for top level components. 3698 if (!ReactCurrentOwner.current) { 3699 return; 3700 } 3701 3702 // Name of the component whose render method tried to pass children. 3703 var currentName = ReactCurrentOwner.current.constructor.displayName; 3704 if (ownerHasWarned.hasOwnProperty(currentName)) { 3705 return; 3706 } 3707 ownerHasWarned[currentName] = true; 3708 3709 var message = 'Each child in an array should have a unique "key" prop. ' + 3710 'Check the render method of ' + currentName + '.'; 3711 if (!component.isOwnedBy(ReactCurrentOwner.current)) { 3712 // Name of the component that originally created this child. 3713 var childOwnerName = 3714 component.props.__owner__ && 3715 component.props.__owner__.constructor.displayName; 3716 3717 // Usually the current owner is the offender, but if it accepts 3718 // children as a property, it may be the creator of the child that's 3719 // responsible for assigning it a key. 3720 message += ' It was passed a child from ' + childOwnerName + '.'; 3721 } 3722 3723 console.warn(message); 3724 } 3725 3726 /** 3727 * Ensure that every component either is passed in a static location or, if 3728 * if it's passed in an array, has an explicit key property defined. 3729 * 3730 * @internal 3731 * @param {*} component Statically passed child of any type. 3732 * @return {boolean} 3733 */ 3734 function validateChildKeys(component) { 3735 if (Array.isArray(component)) { 3736 for (var i = 0; i < component.length; i++) { 3737 var child = component[i]; 3738 if (ReactComponent.isValidComponent(child)) { 3739 validateExplicitKey(child); 3740 } 3741 } 3742 } else if (ReactComponent.isValidComponent(component)) { 3743 // This component was passed in a valid location. 3744 component.__keyValidated__ = true; 3745 } 3746 } 3747 3748 /** 3749 * Components are the basic units of composition in React. 3750 * 3751 * Every component accepts a set of keyed input parameters known as "props" that 3752 * are initialized by the constructor. Once a component is mounted, the props 3753 * can be mutated using `setProps` or `replaceProps`. 3754 * 3755 * Every component is capable of the following operations: 3756 * 3757 * `mountComponent` 3758 * Initializes the component, renders markup, and registers event listeners. 3759 * 3760 * `receiveComponent` 3761 * Updates the rendered DOM nodes to match the given component. 3762 * 3763 * `unmountComponent` 3764 * Releases any resources allocated by this component. 3765 * 3766 * Components can also be "owned" by other components. Being owned by another 3767 * component means being constructed by that component. This is different from 3768 * being the child of a component, which means having a DOM representation that 3769 * is a child of the DOM representation of that component. 3770 * 3771 * @class ReactComponent 3772 */ 3773 var ReactComponent = { 3774 3775 /** 3776 * @param {?object} object 3777 * @return {boolean} True if `object` is a valid component. 3778 * @final 3779 */ 3780 isValidComponent: function(object) { 3781 return !!( 3782 object && 3783 typeof object.mountComponentIntoNode === 'function' && 3784 typeof object.receiveComponent === 'function' 3785 ); 3786 }, 3787 3788 /** 3789 * Generate a key string that identifies a component within a set. 3790 * 3791 * @param {*} component A component that could contain a manual key. 3792 * @param {number} index Index that is used if a manual key is not provided. 3793 * @return {string} 3794 * @internal 3795 */ 3796 getKey: function(component, index) { 3797 if (component && component.props && component.props.key != null) { 3798 // Explicit key 3799 return '{' + component.props.key + '}'; 3800 } 3801 // Implicit key determined by the index in the set 3802 return '[' + index + ']'; 3803 }, 3804 3805 /** 3806 * @internal 3807 */ 3808 LifeCycle: ComponentLifeCycle, 3809 3810 /** 3811 * Injected module that provides ability to mutate individual properties. 3812 * Injected into the base class because many different subclasses need access 3813 * to this. 3814 * 3815 * @internal 3816 */ 3817 DOMIDOperations: ReactComponentEnvironment.DOMIDOperations, 3818 3819 /** 3820 * Optionally injectable environment dependent cleanup hook. (server vs. 3821 * browser etc). Example: A browser system caches DOM nodes based on component 3822 * ID and must remove that cache entry when this instance is unmounted. 3823 * 3824 * @private 3825 */ 3826 unmountIDFromEnvironment: ReactComponentEnvironment.unmountIDFromEnvironment, 3827 3828 /** 3829 * The "image" of a component tree, is the platform specific (typically 3830 * serialized) data that represents a tree of lower level UI building blocks. 3831 * On the web, this "image" is HTML markup which describes a construction of 3832 * low level `div` and `span` nodes. Other platforms may have different 3833 * encoding of this "image". This must be injected. 3834 * 3835 * @private 3836 */ 3837 mountImageIntoNode: ReactComponentEnvironment.mountImageIntoNode, 3838 3839 /** 3840 * React references `ReactReconcileTransaction` using this property in order 3841 * to allow dependency injection. 3842 * 3843 * @internal 3844 */ 3845 ReactReconcileTransaction: 3846 ReactComponentEnvironment.ReactReconcileTransaction, 3847 3848 /** 3849 * Base functionality for every ReactComponent constructor. Mixed into the 3850 * `ReactComponent` prototype, but exposed statically for easy access. 3851 * 3852 * @lends {ReactComponent.prototype} 3853 */ 3854 Mixin: merge(ReactComponentEnvironment.Mixin, { 3855 3856 /** 3857 * Checks whether or not this component is mounted. 3858 * 3859 * @return {boolean} True if mounted, false otherwise. 3860 * @final 3861 * @protected 3862 */ 3863 isMounted: function() { 3864 return this._lifeCycleState === ComponentLifeCycle.MOUNTED; 3865 }, 3866 3867 /** 3868 * Sets a subset of the props. 3869 * 3870 * @param {object} partialProps Subset of the next props. 3871 * @param {?function} callback Called after props are updated. 3872 * @final 3873 * @public 3874 */ 3875 setProps: function(partialProps, callback) { 3876 // Merge with `_pendingProps` if it exists, otherwise with existing props. 3877 this.replaceProps( 3878 merge(this._pendingProps || this.props, partialProps), 3879 callback 3880 ); 3881 }, 3882 3883 /** 3884 * Replaces all of the props. 3885 * 3886 * @param {object} props New props. 3887 * @param {?function} callback Called after props are updated. 3888 * @final 3889 * @public 3890 */ 3891 replaceProps: function(props, callback) { 3892 ("production" !== "development" ? invariant( 3893 !this.props.__owner__, 3894 'replaceProps(...): You called `setProps` or `replaceProps` on a ' + 3895 'component with an owner. This is an anti-pattern since props will ' + 3896 'get reactively updated when rendered. Instead, change the owner\'s ' + 3897 '`render` method to pass the correct value as props to the component ' + 3898 'where it is created.' 3899 ) : invariant(!this.props.__owner__)); 3900 ("production" !== "development" ? invariant( 3901 this.isMounted(), 3902 'replaceProps(...): Can only update a mounted component.' 3903 ) : invariant(this.isMounted())); 3904 this._pendingProps = props; 3905 ReactUpdates.enqueueUpdate(this, callback); 3906 }, 3907 3908 /** 3909 * Base constructor for all React component. 3910 * 3911 * Subclasses that override this method should make sure to invoke 3912 * `ReactComponent.Mixin.construct.call(this, ...)`. 3913 * 3914 * @param {?object} initialProps 3915 * @param {*} children 3916 * @internal 3917 */ 3918 construct: function(initialProps, children) { 3919 this.props = initialProps || {}; 3920 // Record the component responsible for creating this component. 3921 this.props.__owner__ = ReactCurrentOwner.current; 3922 // All components start unmounted. 3923 this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; 3924 3925 this._pendingProps = null; 3926 this._pendingCallbacks = null; 3927 3928 // Children can be more than one argument 3929 var childrenLength = arguments.length - 1; 3930 if (childrenLength === 1) { 3931 if ("production" !== "development") { 3932 validateChildKeys(children); 3933 } 3934 this.props.children = children; 3935 } else if (childrenLength > 1) { 3936 var childArray = Array(childrenLength); 3937 for (var i = 0; i < childrenLength; i++) { 3938 if ("production" !== "development") { 3939 validateChildKeys(arguments[i + 1]); 3940 } 3941 childArray[i] = arguments[i + 1]; 3942 } 3943 this.props.children = childArray; 3944 } 3945 }, 3946 3947 /** 3948 * Initializes the component, renders markup, and registers event listeners. 3949 * 3950 * NOTE: This does not insert any nodes into the DOM. 3951 * 3952 * Subclasses that override this method should make sure to invoke 3953 * `ReactComponent.Mixin.mountComponent.call(this, ...)`. 3954 * 3955 * @param {string} rootID DOM ID of the root node. 3956 * @param {ReactReconcileTransaction} transaction 3957 * @param {number} mountDepth number of components in the owner hierarchy. 3958 * @return {?string} Rendered markup to be inserted into the DOM. 3959 * @internal 3960 */ 3961 mountComponent: function(rootID, transaction, mountDepth) { 3962 ("production" !== "development" ? invariant( 3963 !this.isMounted(), 3964 'mountComponent(%s, ...): Can only mount an unmounted component.', 3965 rootID 3966 ) : invariant(!this.isMounted())); 3967 var props = this.props; 3968 if (props.ref != null) { 3969 ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__); 3970 } 3971 this._rootNodeID = rootID; 3972 this._lifeCycleState = ComponentLifeCycle.MOUNTED; 3973 this._mountDepth = mountDepth; 3974 // Effectively: return ''; 3975 }, 3976 3977 /** 3978 * Releases any resources allocated by `mountComponent`. 3979 * 3980 * NOTE: This does not remove any nodes from the DOM. 3981 * 3982 * Subclasses that override this method should make sure to invoke 3983 * `ReactComponent.Mixin.unmountComponent.call(this)`. 3984 * 3985 * @internal 3986 */ 3987 unmountComponent: function() { 3988 ("production" !== "development" ? invariant( 3989 this.isMounted(), 3990 'unmountComponent(): Can only unmount a mounted component.' 3991 ) : invariant(this.isMounted())); 3992 var props = this.props; 3993 if (props.ref != null) { 3994 ReactOwner.removeComponentAsRefFrom(this, props.ref, props.__owner__); 3995 } 3996 ReactComponent.unmountIDFromEnvironment(this._rootNodeID); 3997 this._rootNodeID = null; 3998 this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; 3999 }, 4000 4001 /** 4002 * Given a new instance of this component, updates the rendered DOM nodes 4003 * as if that instance was rendered instead. 4004 * 4005 * Subclasses that override this method should make sure to invoke 4006 * `ReactComponent.Mixin.receiveComponent.call(this, ...)`. 4007 * 4008 * @param {object} nextComponent Next set of properties. 4009 * @param {ReactReconcileTransaction} transaction 4010 * @internal 4011 */ 4012 receiveComponent: function(nextComponent, transaction) { 4013 ("production" !== "development" ? invariant( 4014 this.isMounted(), 4015 'receiveComponent(...): Can only update a mounted component.' 4016 ) : invariant(this.isMounted())); 4017 this._pendingProps = nextComponent.props; 4018 this._performUpdateIfNecessary(transaction); 4019 }, 4020 4021 /** 4022 * Call `_performUpdateIfNecessary` within a new transaction. 4023 * 4024 * @param {ReactReconcileTransaction} transaction 4025 * @internal 4026 */ 4027 performUpdateIfNecessary: function() { 4028 var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); 4029 transaction.perform(this._performUpdateIfNecessary, this, transaction); 4030 ReactComponent.ReactReconcileTransaction.release(transaction); 4031 }, 4032 4033 /** 4034 * If `_pendingProps` is set, update the component. 4035 * 4036 * @param {ReactReconcileTransaction} transaction 4037 * @internal 4038 */ 4039 _performUpdateIfNecessary: function(transaction) { 4040 if (this._pendingProps == null) { 4041 return; 4042 } 4043 var prevProps = this.props; 4044 this.props = this._pendingProps; 4045 this._pendingProps = null; 4046 this.updateComponent(transaction, prevProps); 4047 }, 4048 4049 /** 4050 * Updates the component's currently mounted representation. 4051 * 4052 * @param {ReactReconcileTransaction} transaction 4053 * @param {object} prevProps 4054 * @internal 4055 */ 4056 updateComponent: function(transaction, prevProps) { 4057 var props = this.props; 4058 // If either the owner or a `ref` has changed, make sure the newest owner 4059 // has stored a reference to `this`, and the previous owner (if different) 4060 // has forgotten the reference to `this`. 4061 if (props.__owner__ !== prevProps.__owner__ || 4062 props.ref !== prevProps.ref) { 4063 if (prevProps.ref != null) { 4064 ReactOwner.removeComponentAsRefFrom( 4065 this, prevProps.ref, prevProps.__owner__ 4066 ); 4067 } 4068 // Correct, even if the owner is the same, and only the ref has changed. 4069 if (props.ref != null) { 4070 ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__); 4071 } 4072 } 4073 }, 4074 4075 /** 4076 * Mounts this component and inserts it into the DOM. 4077 * 4078 * @param {string} rootID DOM ID of the root node. 4079 * @param {DOMElement} container DOM element to mount into. 4080 * @param {boolean} shouldReuseMarkup If true, do not insert markup 4081 * @final 4082 * @internal 4083 * @see {ReactMount.renderComponent} 4084 */ 4085 mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { 4086 var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); 4087 transaction.perform( 4088 this._mountComponentIntoNode, 4089 this, 4090 rootID, 4091 container, 4092 transaction, 4093 shouldReuseMarkup 4094 ); 4095 ReactComponent.ReactReconcileTransaction.release(transaction); 4096 }, 4097 4098 /** 4099 * @param {string} rootID DOM ID of the root node. 4100 * @param {DOMElement} container DOM element to mount into. 4101 * @param {ReactReconcileTransaction} transaction 4102 * @param {boolean} shouldReuseMarkup If true, do not insert markup 4103 * @final 4104 * @private 4105 */ 4106 _mountComponentIntoNode: function( 4107 rootID, 4108 container, 4109 transaction, 4110 shouldReuseMarkup) { 4111 var markup = this.mountComponent(rootID, transaction, 0); 4112 ReactComponent.mountImageIntoNode(markup, container, shouldReuseMarkup); 4113 }, 4114 4115 /** 4116 * Checks if this component is owned by the supplied `owner` component. 4117 * 4118 * @param {ReactComponent} owner Component to check. 4119 * @return {boolean} True if `owners` owns this component. 4120 * @final 4121 * @internal 4122 */ 4123 isOwnedBy: function(owner) { 4124 return this.props.__owner__ === owner; 4125 }, 4126 4127 /** 4128 * Gets another component, that shares the same owner as this one, by ref. 4129 * 4130 * @param {string} ref of a sibling Component. 4131 * @return {?ReactComponent} the actual sibling Component. 4132 * @final 4133 * @internal 4134 */ 4135 getSiblingByRef: function(ref) { 4136 var owner = this.props.__owner__; 4137 if (!owner || !owner.refs) { 4138 return null; 4139 } 4140 return owner.refs[ref]; 4141 } 4142 }) 4143 }; 4144 4145 module.exports = ReactComponent; 4146 4147 },{"./ReactComponentEnvironment":30,"./ReactCurrentOwner":32,"./ReactOwner":58,"./ReactUpdates":70,"./invariant":109,"./keyMirror":115,"./merge":118}],29:[function(require,module,exports){ 4148 /** 4149 * Copyright 2013 Facebook, Inc. 4150 * 4151 * Licensed under the Apache License, Version 2.0 (the "License"); 4152 * you may not use this file except in compliance with the License. 4153 * You may obtain a copy of the License at 4154 * 4155 * http://www.apache.org/licenses/LICENSE-2.0 4156 * 4157 * Unless required by applicable law or agreed to in writing, software 4158 * distributed under the License is distributed on an "AS IS" BASIS, 4159 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4160 * See the License for the specific language governing permissions and 4161 * limitations under the License. 4162 * 4163 * @providesModule ReactComponentBrowserEnvironment 4164 */ 4165 4166 /*jslint evil: true */ 4167 4168 "use strict"; 4169 4170 var ReactDOMIDOperations = require("./ReactDOMIDOperations"); 4171 var ReactMarkupChecksum = require("./ReactMarkupChecksum"); 4172 var ReactMount = require("./ReactMount"); 4173 var ReactReconcileTransaction = require("./ReactReconcileTransaction"); 4174 4175 var getReactRootElementInContainer = require("./getReactRootElementInContainer"); 4176 var invariant = require("./invariant"); 4177 var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup"); 4178 4179 4180 var ELEMENT_NODE_TYPE = 1; 4181 var DOC_NODE_TYPE = 9; 4182 4183 4184 /** 4185 * Abstracts away all functionality of `ReactComponent` requires knowledge of 4186 * the browser context. 4187 */ 4188 var ReactComponentBrowserEnvironment = { 4189 /** 4190 * Mixed into every component instance. 4191 */ 4192 Mixin: { 4193 /** 4194 * Returns the DOM node rendered by this component. 4195 * 4196 * @return {DOMElement} The root node of this component. 4197 * @final 4198 * @protected 4199 */ 4200 getDOMNode: function() { 4201 ("production" !== "development" ? invariant( 4202 this.isMounted(), 4203 'getDOMNode(): A component must be mounted to have a DOM node.' 4204 ) : invariant(this.isMounted())); 4205 return ReactMount.getNode(this._rootNodeID); 4206 } 4207 }, 4208 4209 ReactReconcileTransaction: ReactReconcileTransaction, 4210 4211 DOMIDOperations: ReactDOMIDOperations, 4212 4213 /** 4214 * If a particular environment requires that some resources be cleaned up, 4215 * specify this in the injected Mixin. In the DOM, we would likely want to 4216 * purge any cached node ID lookups. 4217 * 4218 * @private 4219 */ 4220 unmountIDFromEnvironment: function(rootNodeID) { 4221 ReactMount.purgeID(rootNodeID); 4222 }, 4223 4224 /** 4225 * @param {string} markup Markup string to place into the DOM Element. 4226 * @param {DOMElement} container DOM Element to insert markup into. 4227 * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the 4228 * container if possible. 4229 */ 4230 mountImageIntoNode: function(markup, container, shouldReuseMarkup) { 4231 ("production" !== "development" ? invariant( 4232 container && ( 4233 container.nodeType === ELEMENT_NODE_TYPE || 4234 container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender 4235 ), 4236 'mountComponentIntoNode(...): Target container is not valid.' 4237 ) : invariant(container && ( 4238 container.nodeType === ELEMENT_NODE_TYPE || 4239 container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender 4240 ))); 4241 if (shouldReuseMarkup) { 4242 if (ReactMarkupChecksum.canReuseMarkup( 4243 markup, 4244 getReactRootElementInContainer(container))) { 4245 return; 4246 } else { 4247 if ("production" !== "development") { 4248 console.warn( 4249 'React attempted to use reuse markup in a container but the ' + 4250 'checksum was invalid. This generally means that you are using ' + 4251 'server rendering and the markup generated on the server was ' + 4252 'not what the client was expecting. React injected new markup ' + 4253 'to compensate which works but you have lost many of the ' + 4254 'benefits of server rendering. Instead, figure out why the ' + 4255 'markup being generated is different on the client or server.' 4256 ); 4257 } 4258 } 4259 } 4260 4261 // You can't naively set the innerHTML of the entire document. You need 4262 // to mutate documentElement which requires doing some crazy tricks. See 4263 // mutateHTMLNodeWithMarkup() 4264 if (container.nodeType === DOC_NODE_TYPE) { 4265 mutateHTMLNodeWithMarkup(container.documentElement, markup); 4266 return; 4267 } 4268 4269 // Asynchronously inject markup by ensuring that the container is not in 4270 // the document when settings its `innerHTML`. 4271 var parent = container.parentNode; 4272 if (parent) { 4273 var next = container.nextSibling; 4274 parent.removeChild(container); 4275 container.innerHTML = markup; 4276 if (next) { 4277 parent.insertBefore(container, next); 4278 } else { 4279 parent.appendChild(container); 4280 } 4281 } else { 4282 container.innerHTML = markup; 4283 } 4284 } 4285 }; 4286 4287 module.exports = ReactComponentBrowserEnvironment; 4288 4289 },{"./ReactDOMIDOperations":37,"./ReactMarkupChecksum":53,"./ReactMount":54,"./ReactReconcileTransaction":62,"./getReactRootElementInContainer":105,"./invariant":109,"./mutateHTMLNodeWithMarkup":122}],30:[function(require,module,exports){ 4290 /** 4291 * Copyright 2013 Facebook, Inc. 4292 * 4293 * Licensed under the Apache License, Version 2.0 (the "License"); 4294 * you may not use this file except in compliance with the License. 4295 * You may obtain a copy of the License at 4296 * 4297 * http://www.apache.org/licenses/LICENSE-2.0 4298 * 4299 * Unless required by applicable law or agreed to in writing, software 4300 * distributed under the License is distributed on an "AS IS" BASIS, 4301 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4302 * See the License for the specific language governing permissions and 4303 * limitations under the License. 4304 * 4305 * @providesModule ReactComponentEnvironment 4306 */ 4307 4308 var ReactComponentBrowserEnvironment = 4309 require("./ReactComponentBrowserEnvironment"); 4310 4311 var ReactComponentEnvironment = ReactComponentBrowserEnvironment; 4312 4313 module.exports = ReactComponentEnvironment; 4314 4315 },{"./ReactComponentBrowserEnvironment":29}],31:[function(require,module,exports){ 4316 /** 4317 * Copyright 2013 Facebook, Inc. 4318 * 4319 * Licensed under the Apache License, Version 2.0 (the "License"); 4320 * you may not use this file except in compliance with the License. 4321 * You may obtain a copy of the License at 4322 * 4323 * http://www.apache.org/licenses/LICENSE-2.0 4324 * 4325 * Unless required by applicable law or agreed to in writing, software 4326 * distributed under the License is distributed on an "AS IS" BASIS, 4327 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4328 * See the License for the specific language governing permissions and 4329 * limitations under the License. 4330 * 4331 * @providesModule ReactCompositeComponent 4332 */ 4333 4334 "use strict"; 4335 4336 var ReactComponent = require("./ReactComponent"); 4337 var ReactCurrentOwner = require("./ReactCurrentOwner"); 4338 var ReactErrorUtils = require("./ReactErrorUtils"); 4339 var ReactOwner = require("./ReactOwner"); 4340 var ReactPerf = require("./ReactPerf"); 4341 var ReactPropTransferer = require("./ReactPropTransferer"); 4342 var ReactUpdates = require("./ReactUpdates"); 4343 4344 var invariant = require("./invariant"); 4345 var keyMirror = require("./keyMirror"); 4346 var merge = require("./merge"); 4347 var mixInto = require("./mixInto"); 4348 var objMap = require("./objMap"); 4349 4350 /** 4351 * Policies that describe methods in `ReactCompositeComponentInterface`. 4352 */ 4353 var SpecPolicy = keyMirror({ 4354 /** 4355 * These methods may be defined only once by the class specification or mixin. 4356 */ 4357 DEFINE_ONCE: null, 4358 /** 4359 * These methods may be defined by both the class specification and mixins. 4360 * Subsequent definitions will be chained. These methods must return void. 4361 */ 4362 DEFINE_MANY: null, 4363 /** 4364 * These methods are overriding the base ReactCompositeComponent class. 4365 */ 4366 OVERRIDE_BASE: null, 4367 /** 4368 * These methods are similar to DEFINE_MANY, except we assume they return 4369 * objects. We try to merge the keys of the return values of all the mixed in 4370 * functions. If there is a key conflict we throw. 4371 */ 4372 DEFINE_MANY_MERGED: null 4373 }); 4374 4375 /** 4376 * Composite components are higher-level components that compose other composite 4377 * or native components. 4378 * 4379 * To create a new type of `ReactCompositeComponent`, pass a specification of 4380 * your new class to `React.createClass`. The only requirement of your class 4381 * specification is that you implement a `render` method. 4382 * 4383 * var MyComponent = React.createClass({ 4384 * render: function() { 4385 * return <div>Hello World</div>; 4386 * } 4387 * }); 4388 * 4389 * The class specification supports a specific protocol of methods that have 4390 * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for 4391 * more the comprehensive protocol. Any other properties and methods in the 4392 * class specification will available on the prototype. 4393 * 4394 * @interface ReactCompositeComponentInterface 4395 * @internal 4396 */ 4397 var ReactCompositeComponentInterface = { 4398 4399 /** 4400 * An array of Mixin objects to include when defining your component. 4401 * 4402 * @type {array} 4403 * @optional 4404 */ 4405 mixins: SpecPolicy.DEFINE_MANY, 4406 4407 /** 4408 * Definition of prop types for this component. 4409 * 4410 * @type {object} 4411 * @optional 4412 */ 4413 propTypes: SpecPolicy.DEFINE_ONCE, 4414 4415 4416 4417 // ==== Definition methods ==== 4418 4419 /** 4420 * Invoked when the component is mounted. Values in the mapping will be set on 4421 * `this.props` if that prop is not specified (i.e. using an `in` check). 4422 * 4423 * This method is invoked before `getInitialState` and therefore cannot rely 4424 * on `this.state` or use `this.setState`. 4425 * 4426 * @return {object} 4427 * @optional 4428 */ 4429 getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED, 4430 4431 /** 4432 * Invoked once before the component is mounted. The return value will be used 4433 * as the initial value of `this.state`. 4434 * 4435 * getInitialState: function() { 4436 * return { 4437 * isOn: false, 4438 * fooBaz: new BazFoo() 4439 * } 4440 * } 4441 * 4442 * @return {object} 4443 * @optional 4444 */ 4445 getInitialState: SpecPolicy.DEFINE_MANY_MERGED, 4446 4447 /** 4448 * Uses props from `this.props` and state from `this.state` to render the 4449 * structure of the component. 4450 * 4451 * No guarantees are made about when or how often this method is invoked, so 4452 * it must not have side effects. 4453 * 4454 * render: function() { 4455 * var name = this.props.name; 4456 * return <div>Hello, {name}!</div>; 4457 * } 4458 * 4459 * @return {ReactComponent} 4460 * @nosideeffects 4461 * @required 4462 */ 4463 render: SpecPolicy.DEFINE_ONCE, 4464 4465 4466 4467 // ==== Delegate methods ==== 4468 4469 /** 4470 * Invoked when the component is initially created and about to be mounted. 4471 * This may have side effects, but any external subscriptions or data created 4472 * by this method must be cleaned up in `componentWillUnmount`. 4473 * 4474 * @optional 4475 */ 4476 componentWillMount: SpecPolicy.DEFINE_MANY, 4477 4478 /** 4479 * Invoked when the component has been mounted and has a DOM representation. 4480 * However, there is no guarantee that the DOM node is in the document. 4481 * 4482 * Use this as an opportunity to operate on the DOM when the component has 4483 * been mounted (initialized and rendered) for the first time. 4484 * 4485 * @param {DOMElement} rootNode DOM element representing the component. 4486 * @optional 4487 */ 4488 componentDidMount: SpecPolicy.DEFINE_MANY, 4489 4490 /** 4491 * Invoked before the component receives new props. 4492 * 4493 * Use this as an opportunity to react to a prop transition by updating the 4494 * state using `this.setState`. Current props are accessed via `this.props`. 4495 * 4496 * componentWillReceiveProps: function(nextProps) { 4497 * this.setState({ 4498 * likesIncreasing: nextProps.likeCount > this.props.likeCount 4499 * }); 4500 * } 4501 * 4502 * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop 4503 * transition may cause a state change, but the opposite is not true. If you 4504 * need it, you are probably looking for `componentWillUpdate`. 4505 * 4506 * @param {object} nextProps 4507 * @optional 4508 */ 4509 componentWillReceiveProps: SpecPolicy.DEFINE_MANY, 4510 4511 /** 4512 * Invoked while deciding if the component should be updated as a result of 4513 * receiving new props and state. 4514 * 4515 * Use this as an opportunity to `return false` when you're certain that the 4516 * transition to the new props and state will not require a component update. 4517 * 4518 * shouldComponentUpdate: function(nextProps, nextState) { 4519 * return !equal(nextProps, this.props) || !equal(nextState, this.state); 4520 * } 4521 * 4522 * @param {object} nextProps 4523 * @param {?object} nextState 4524 * @return {boolean} True if the component should update. 4525 * @optional 4526 */ 4527 shouldComponentUpdate: SpecPolicy.DEFINE_ONCE, 4528 4529 /** 4530 * Invoked when the component is about to update due to a transition from 4531 * `this.props` and `this.state` to `nextProps` and `nextState`. 4532 * 4533 * Use this as an opportunity to perform preparation before an update occurs. 4534 * 4535 * NOTE: You **cannot** use `this.setState()` in this method. 4536 * 4537 * @param {object} nextProps 4538 * @param {?object} nextState 4539 * @param {ReactReconcileTransaction} transaction 4540 * @optional 4541 */ 4542 componentWillUpdate: SpecPolicy.DEFINE_MANY, 4543 4544 /** 4545 * Invoked when the component's DOM representation has been updated. 4546 * 4547 * Use this as an opportunity to operate on the DOM when the component has 4548 * been updated. 4549 * 4550 * @param {object} prevProps 4551 * @param {?object} prevState 4552 * @param {DOMElement} rootNode DOM element representing the component. 4553 * @optional 4554 */ 4555 componentDidUpdate: SpecPolicy.DEFINE_MANY, 4556 4557 /** 4558 * Invoked when the component is about to be removed from its parent and have 4559 * its DOM representation destroyed. 4560 * 4561 * Use this as an opportunity to deallocate any external resources. 4562 * 4563 * NOTE: There is no `componentDidUnmount` since your component will have been 4564 * destroyed by that point. 4565 * 4566 * @optional 4567 */ 4568 componentWillUnmount: SpecPolicy.DEFINE_MANY, 4569 4570 4571 4572 // ==== Advanced methods ==== 4573 4574 /** 4575 * Updates the component's currently mounted DOM representation. 4576 * 4577 * By default, this implements React's rendering and reconciliation algorithm. 4578 * Sophisticated clients may wish to override this. 4579 * 4580 * @param {ReactReconcileTransaction} transaction 4581 * @internal 4582 * @overridable 4583 */ 4584 updateComponent: SpecPolicy.OVERRIDE_BASE 4585 4586 }; 4587 4588 /** 4589 * Mapping from class specification keys to special processing functions. 4590 * 4591 * Although these are declared in the specification when defining classes 4592 * using `React.createClass`, they will not be on the component's prototype. 4593 */ 4594 var RESERVED_SPEC_KEYS = { 4595 displayName: function(Constructor, displayName) { 4596 Constructor.displayName = displayName; 4597 }, 4598 mixins: function(Constructor, mixins) { 4599 if (mixins) { 4600 for (var i = 0; i < mixins.length; i++) { 4601 mixSpecIntoComponent(Constructor, mixins[i]); 4602 } 4603 } 4604 }, 4605 propTypes: function(Constructor, propTypes) { 4606 Constructor.propTypes = propTypes; 4607 } 4608 }; 4609 4610 function validateMethodOverride(proto, name) { 4611 var specPolicy = ReactCompositeComponentInterface[name]; 4612 4613 // Disallow overriding of base class methods unless explicitly allowed. 4614 if (ReactCompositeComponentMixin.hasOwnProperty(name)) { 4615 ("production" !== "development" ? invariant( 4616 specPolicy === SpecPolicy.OVERRIDE_BASE, 4617 'ReactCompositeComponentInterface: You are attempting to override ' + 4618 '`%s` from your class specification. Ensure that your method names ' + 4619 'do not overlap with React methods.', 4620 name 4621 ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE)); 4622 } 4623 4624 // Disallow defining methods more than once unless explicitly allowed. 4625 if (proto.hasOwnProperty(name)) { 4626 ("production" !== "development" ? invariant( 4627 specPolicy === SpecPolicy.DEFINE_MANY || 4628 specPolicy === SpecPolicy.DEFINE_MANY_MERGED, 4629 'ReactCompositeComponentInterface: You are attempting to define ' + 4630 '`%s` on your component more than once. This conflict may be due ' + 4631 'to a mixin.', 4632 name 4633 ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY || 4634 specPolicy === SpecPolicy.DEFINE_MANY_MERGED)); 4635 } 4636 } 4637 4638 4639 function validateLifeCycleOnReplaceState(instance) { 4640 var compositeLifeCycleState = instance._compositeLifeCycleState; 4641 ("production" !== "development" ? invariant( 4642 instance.isMounted() || 4643 compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 4644 'replaceState(...): Can only update a mounted or mounting component.' 4645 ) : invariant(instance.isMounted() || 4646 compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); 4647 ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE, 4648 'replaceState(...): Cannot update during an existing state transition ' + 4649 '(such as within `render`). This could potentially cause an infinite ' + 4650 'loop so it is forbidden.' 4651 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE)); 4652 ("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 4653 'replaceState(...): Cannot update while unmounting component. This ' + 4654 'usually means you called setState() on an unmounted component.' 4655 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); 4656 } 4657 4658 /** 4659 * Custom version of `mixInto` which handles policy validation and reserved 4660 * specification keys when building `ReactCompositeComponent` classses. 4661 */ 4662 function mixSpecIntoComponent(Constructor, spec) { 4663 var proto = Constructor.prototype; 4664 for (var name in spec) { 4665 var property = spec[name]; 4666 if (!spec.hasOwnProperty(name) || !property) { 4667 continue; 4668 } 4669 validateMethodOverride(proto, name); 4670 4671 if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { 4672 RESERVED_SPEC_KEYS[name](Constructor, property); 4673 } else { 4674 // Setup methods on prototype: 4675 // The following member methods should not be automatically bound: 4676 // 1. Expected ReactCompositeComponent methods (in the "interface"). 4677 // 2. Overridden methods (that were mixed in). 4678 var isCompositeComponentMethod = name in ReactCompositeComponentInterface; 4679 var isInherited = name in proto; 4680 var markedDontBind = property.__reactDontBind; 4681 var isFunction = typeof property === 'function'; 4682 var shouldAutoBind = 4683 isFunction && 4684 !isCompositeComponentMethod && 4685 !isInherited && 4686 !markedDontBind; 4687 4688 if (shouldAutoBind) { 4689 if (!proto.__reactAutoBindMap) { 4690 proto.__reactAutoBindMap = {}; 4691 } 4692 proto.__reactAutoBindMap[name] = property; 4693 proto[name] = property; 4694 } else { 4695 if (isInherited) { 4696 // For methods which are defined more than once, call the existing 4697 // methods before calling the new property. 4698 if (ReactCompositeComponentInterface[name] === 4699 SpecPolicy.DEFINE_MANY_MERGED) { 4700 proto[name] = createMergedResultFunction(proto[name], property); 4701 } else { 4702 proto[name] = createChainedFunction(proto[name], property); 4703 } 4704 } else { 4705 proto[name] = property; 4706 } 4707 } 4708 } 4709 } 4710 } 4711 4712 /** 4713 * Merge two objects, but throw if both contain the same key. 4714 * 4715 * @param {object} one The first object, which is mutated. 4716 * @param {object} two The second object 4717 * @return {object} one after it has been mutated to contain everything in two. 4718 */ 4719 function mergeObjectsWithNoDuplicateKeys(one, two) { 4720 ("production" !== "development" ? invariant( 4721 one && two && typeof one === 'object' && typeof two === 'object', 4722 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects' 4723 ) : invariant(one && two && typeof one === 'object' && typeof two === 'object')); 4724 4725 objMap(two, function(value, key) { 4726 ("production" !== "development" ? invariant( 4727 one[key] === undefined, 4728 'mergeObjectsWithNoDuplicateKeys(): ' + 4729 'Tried to merge two objects with the same key: %s', 4730 key 4731 ) : invariant(one[key] === undefined)); 4732 one[key] = value; 4733 }); 4734 return one; 4735 } 4736 4737 /** 4738 * Creates a function that invokes two functions and merges their return values. 4739 * 4740 * @param {function} one Function to invoke first. 4741 * @param {function} two Function to invoke second. 4742 * @return {function} Function that invokes the two argument functions. 4743 * @private 4744 */ 4745 function createMergedResultFunction(one, two) { 4746 return function mergedResult() { 4747 return mergeObjectsWithNoDuplicateKeys( 4748 one.apply(this, arguments), 4749 two.apply(this, arguments) 4750 ); 4751 }; 4752 } 4753 4754 /** 4755 * Creates a function that invokes two functions and ignores their return vales. 4756 * 4757 * @param {function} one Function to invoke first. 4758 * @param {function} two Function to invoke second. 4759 * @return {function} Function that invokes the two argument functions. 4760 * @private 4761 */ 4762 function createChainedFunction(one, two) { 4763 return function chainedFunction() { 4764 one.apply(this, arguments); 4765 two.apply(this, arguments); 4766 }; 4767 } 4768 4769 /** 4770 * `ReactCompositeComponent` maintains an auxiliary life cycle state in 4771 * `this._compositeLifeCycleState` (which can be null). 4772 * 4773 * This is different from the life cycle state maintained by `ReactComponent` in 4774 * `this._lifeCycleState`. The following diagram shows how the states overlap in 4775 * time. There are times when the CompositeLifeCycle is null - at those times it 4776 * is only meaningful to look at ComponentLifeCycle alone. 4777 * 4778 * Top Row: ReactComponent.ComponentLifeCycle 4779 * Low Row: ReactComponent.CompositeLifeCycle 4780 * 4781 * +-------+------------------------------------------------------+--------+ 4782 * | UN | MOUNTED | UN | 4783 * |MOUNTED| | MOUNTED| 4784 * +-------+------------------------------------------------------+--------+ 4785 * | ^--------+ +------+ +------+ +------+ +--------^ | 4786 * | | | | | | | | | | | | 4787 * | 0--|MOUNTING|-0-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 | 4788 * | | | |PROPS | | PROPS| | STATE| |MOUNTING| | 4789 * | | | | | | | | | | | | 4790 * | | | | | | | | | | | | 4791 * | +--------+ +------+ +------+ +------+ +--------+ | 4792 * | | | | 4793 * +-------+------------------------------------------------------+--------+ 4794 */ 4795 var CompositeLifeCycle = keyMirror({ 4796 /** 4797 * Components in the process of being mounted respond to state changes 4798 * differently. 4799 */ 4800 MOUNTING: null, 4801 /** 4802 * Components in the process of being unmounted are guarded against state 4803 * changes. 4804 */ 4805 UNMOUNTING: null, 4806 /** 4807 * Components that are mounted and receiving new props respond to state 4808 * changes differently. 4809 */ 4810 RECEIVING_PROPS: null, 4811 /** 4812 * Components that are mounted and receiving new state are guarded against 4813 * additional state changes. 4814 */ 4815 RECEIVING_STATE: null 4816 }); 4817 4818 /** 4819 * @lends {ReactCompositeComponent.prototype} 4820 */ 4821 var ReactCompositeComponentMixin = { 4822 4823 /** 4824 * Base constructor for all composite component. 4825 * 4826 * @param {?object} initialProps 4827 * @param {*} children 4828 * @final 4829 * @internal 4830 */ 4831 construct: function(initialProps, children) { 4832 // Children can be either an array or more than one argument 4833 ReactComponent.Mixin.construct.apply(this, arguments); 4834 this.state = null; 4835 this._pendingState = null; 4836 this._compositeLifeCycleState = null; 4837 }, 4838 4839 /** 4840 * Checks whether or not this composite component is mounted. 4841 * @return {boolean} True if mounted, false otherwise. 4842 * @protected 4843 * @final 4844 */ 4845 isMounted: function() { 4846 return ReactComponent.Mixin.isMounted.call(this) && 4847 this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING; 4848 }, 4849 4850 /** 4851 * Initializes the component, renders markup, and registers event listeners. 4852 * 4853 * @param {string} rootID DOM ID of the root node. 4854 * @param {ReactReconcileTransaction} transaction 4855 * @param {number} mountDepth number of components in the owner hierarchy 4856 * @return {?string} Rendered markup to be inserted into the DOM. 4857 * @final 4858 * @internal 4859 */ 4860 mountComponent: ReactPerf.measure( 4861 'ReactCompositeComponent', 4862 'mountComponent', 4863 function(rootID, transaction, mountDepth) { 4864 ReactComponent.Mixin.mountComponent.call( 4865 this, 4866 rootID, 4867 transaction, 4868 mountDepth 4869 ); 4870 this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; 4871 4872 this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null; 4873 this._processProps(this.props); 4874 4875 if (this.__reactAutoBindMap) { 4876 this._bindAutoBindMethods(); 4877 } 4878 4879 this.state = this.getInitialState ? this.getInitialState() : null; 4880 this._pendingState = null; 4881 this._pendingForceUpdate = false; 4882 4883 if (this.componentWillMount) { 4884 this.componentWillMount(); 4885 // When mounting, calls to `setState` by `componentWillMount` will set 4886 // `this._pendingState` without triggering a re-render. 4887 if (this._pendingState) { 4888 this.state = this._pendingState; 4889 this._pendingState = null; 4890 } 4891 } 4892 4893 this._renderedComponent = this._renderValidatedComponent(); 4894 4895 // Done with mounting, `setState` will now trigger UI changes. 4896 this._compositeLifeCycleState = null; 4897 var markup = this._renderedComponent.mountComponent( 4898 rootID, 4899 transaction, 4900 mountDepth + 1 4901 ); 4902 if (this.componentDidMount) { 4903 transaction.getReactMountReady().enqueue(this, this.componentDidMount); 4904 } 4905 return markup; 4906 } 4907 ), 4908 4909 /** 4910 * Releases any resources allocated by `mountComponent`. 4911 * 4912 * @final 4913 * @internal 4914 */ 4915 unmountComponent: function() { 4916 this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING; 4917 if (this.componentWillUnmount) { 4918 this.componentWillUnmount(); 4919 } 4920 this._compositeLifeCycleState = null; 4921 4922 this._defaultProps = null; 4923 4924 ReactComponent.Mixin.unmountComponent.call(this); 4925 this._renderedComponent.unmountComponent(); 4926 this._renderedComponent = null; 4927 4928 if (this.refs) { 4929 this.refs = null; 4930 } 4931 4932 // Some existing components rely on this.props even after they've been 4933 // destroyed (in event handlers). 4934 // TODO: this.props = null; 4935 // TODO: this.state = null; 4936 }, 4937 4938 /** 4939 * Sets a subset of the state. Always use this or `replaceState` to mutate 4940 * state. You should treat `this.state` as immutable. 4941 * 4942 * There is no guarantee that `this.state` will be immediately updated, so 4943 * accessing `this.state` after calling this method may return the old value. 4944 * 4945 * There is no guarantee that calls to `setState` will run synchronously, 4946 * as they may eventually be batched together. You can provide an optional 4947 * callback that will be executed when the call to setState is actually 4948 * completed. 4949 * 4950 * @param {object} partialState Next partial state to be merged with state. 4951 * @param {?function} callback Called after state is updated. 4952 * @final 4953 * @protected 4954 */ 4955 setState: function(partialState, callback) { 4956 // Merge with `_pendingState` if it exists, otherwise with existing state. 4957 this.replaceState( 4958 merge(this._pendingState || this.state, partialState), 4959 callback 4960 ); 4961 }, 4962 4963 /** 4964 * Replaces all of the state. Always use this or `setState` to mutate state. 4965 * You should treat `this.state` as immutable. 4966 * 4967 * There is no guarantee that `this.state` will be immediately updated, so 4968 * accessing `this.state` after calling this method may return the old value. 4969 * 4970 * @param {object} completeState Next state. 4971 * @param {?function} callback Called after state is updated. 4972 * @final 4973 * @protected 4974 */ 4975 replaceState: function(completeState, callback) { 4976 validateLifeCycleOnReplaceState(this); 4977 this._pendingState = completeState; 4978 ReactUpdates.enqueueUpdate(this, callback); 4979 }, 4980 4981 /** 4982 * Processes props by setting default values for unspecified props and 4983 * asserting that the props are valid. 4984 * 4985 * @param {object} props 4986 * @private 4987 */ 4988 _processProps: function(props) { 4989 var propName; 4990 var defaultProps = this._defaultProps; 4991 for (propName in defaultProps) { 4992 if (!(propName in props)) { 4993 props[propName] = defaultProps[propName]; 4994 } 4995 } 4996 var propTypes = this.constructor.propTypes; 4997 if (propTypes) { 4998 var componentName = this.constructor.displayName; 4999 for (propName in propTypes) { 5000 var checkProp = propTypes[propName]; 5001 if (checkProp) { 5002 checkProp(props, propName, componentName); 5003 } 5004 } 5005 } 5006 }, 5007 5008 performUpdateIfNecessary: function() { 5009 var compositeLifeCycleState = this._compositeLifeCycleState; 5010 // Do not trigger a state transition if we are in the middle of mounting or 5011 // receiving props because both of those will already be doing this. 5012 if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING || 5013 compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) { 5014 return; 5015 } 5016 ReactComponent.Mixin.performUpdateIfNecessary.call(this); 5017 }, 5018 5019 /** 5020 * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is 5021 * set, update the component. 5022 * 5023 * @param {ReactReconcileTransaction} transaction 5024 * @internal 5025 */ 5026 _performUpdateIfNecessary: function(transaction) { 5027 if (this._pendingProps == null && 5028 this._pendingState == null && 5029 !this._pendingForceUpdate) { 5030 return; 5031 } 5032 5033 var nextProps = this.props; 5034 if (this._pendingProps != null) { 5035 nextProps = this._pendingProps; 5036 this._processProps(nextProps); 5037 this._pendingProps = null; 5038 5039 this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS; 5040 if (this.componentWillReceiveProps) { 5041 this.componentWillReceiveProps(nextProps, transaction); 5042 } 5043 } 5044 5045 this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE; 5046 5047 var nextState = this._pendingState || this.state; 5048 this._pendingState = null; 5049 5050 if (this._pendingForceUpdate || 5051 !this.shouldComponentUpdate || 5052 this.shouldComponentUpdate(nextProps, nextState)) { 5053 this._pendingForceUpdate = false; 5054 // Will set `this.props` and `this.state`. 5055 this._performComponentUpdate(nextProps, nextState, transaction); 5056 } else { 5057 // If it's determined that a component should not update, we still want 5058 // to set props and state. 5059 this.props = nextProps; 5060 this.state = nextState; 5061 } 5062 5063 this._compositeLifeCycleState = null; 5064 }, 5065 5066 /** 5067 * Merges new props and state, notifies delegate methods of update and 5068 * performs update. 5069 * 5070 * @param {object} nextProps Next object to set as properties. 5071 * @param {?object} nextState Next object to set as state. 5072 * @param {ReactReconcileTransaction} transaction 5073 * @private 5074 */ 5075 _performComponentUpdate: function(nextProps, nextState, transaction) { 5076 var prevProps = this.props; 5077 var prevState = this.state; 5078 5079 if (this.componentWillUpdate) { 5080 this.componentWillUpdate(nextProps, nextState, transaction); 5081 } 5082 5083 this.props = nextProps; 5084 this.state = nextState; 5085 5086 this.updateComponent(transaction, prevProps, prevState); 5087 5088 if (this.componentDidUpdate) { 5089 transaction.getReactMountReady().enqueue( 5090 this, 5091 this.componentDidUpdate.bind(this, prevProps, prevState) 5092 ); 5093 } 5094 }, 5095 5096 /** 5097 * Updates the component's currently mounted DOM representation. 5098 * 5099 * By default, this implements React's rendering and reconciliation algorithm. 5100 * Sophisticated clients may wish to override this. 5101 * 5102 * @param {ReactReconcileTransaction} transaction 5103 * @param {object} prevProps 5104 * @param {?object} prevState 5105 * @internal 5106 * @overridable 5107 */ 5108 updateComponent: ReactPerf.measure( 5109 'ReactCompositeComponent', 5110 'updateComponent', 5111 function(transaction, prevProps, prevState) { 5112 ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps); 5113 var currentComponent = this._renderedComponent; 5114 var nextComponent = this._renderValidatedComponent(); 5115 if (currentComponent.constructor === nextComponent.constructor) { 5116 currentComponent.receiveComponent(nextComponent, transaction); 5117 } else { 5118 // These two IDs are actually the same! But nothing should rely on that. 5119 var thisID = this._rootNodeID; 5120 var currentComponentID = currentComponent._rootNodeID; 5121 currentComponent.unmountComponent(); 5122 this._renderedComponent = nextComponent; 5123 var nextMarkup = nextComponent.mountComponent( 5124 thisID, 5125 transaction, 5126 this._mountDepth + 1 5127 ); 5128 ReactComponent.DOMIDOperations.dangerouslyReplaceNodeWithMarkupByID( 5129 currentComponentID, 5130 nextMarkup 5131 ); 5132 } 5133 } 5134 ), 5135 5136 /** 5137 * Forces an update. This should only be invoked when it is known with 5138 * certainty that we are **not** in a DOM transaction. 5139 * 5140 * You may want to call this when you know that some deeper aspect of the 5141 * component's state has changed but `setState` was not called. 5142 * 5143 * This will not invoke `shouldUpdateComponent`, but it will invoke 5144 * `componentWillUpdate` and `componentDidUpdate`. 5145 * 5146 * @param {?function} callback Called after update is complete. 5147 * @final 5148 * @protected 5149 */ 5150 forceUpdate: function(callback) { 5151 var compositeLifeCycleState = this._compositeLifeCycleState; 5152 ("production" !== "development" ? invariant( 5153 this.isMounted() || 5154 compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 5155 'forceUpdate(...): Can only force an update on mounted or mounting ' + 5156 'components.' 5157 ) : invariant(this.isMounted() || 5158 compositeLifeCycleState === CompositeLifeCycle.MOUNTING)); 5159 ("production" !== "development" ? invariant( 5160 compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && 5161 compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 5162 'forceUpdate(...): Cannot force an update while unmounting component ' + 5163 'or during an existing state transition (such as within `render`).' 5164 ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && 5165 compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING)); 5166 this._pendingForceUpdate = true; 5167 ReactUpdates.enqueueUpdate(this, callback); 5168 }, 5169 5170 /** 5171 * @private 5172 */ 5173 _renderValidatedComponent: function() { 5174 var renderedComponent; 5175 ReactCurrentOwner.current = this; 5176 try { 5177 renderedComponent = this.render(); 5178 } catch (error) { 5179 // IE8 requires `catch` in order to use `finally`. 5180 throw error; 5181 } finally { 5182 ReactCurrentOwner.current = null; 5183 } 5184 ("production" !== "development" ? invariant( 5185 ReactComponent.isValidComponent(renderedComponent), 5186 '%s.render(): A valid ReactComponent must be returned. You may have ' + 5187 'returned null, undefined, an array, or some other invalid object.', 5188 this.constructor.displayName || 'ReactCompositeComponent' 5189 ) : invariant(ReactComponent.isValidComponent(renderedComponent))); 5190 return renderedComponent; 5191 }, 5192 5193 /** 5194 * @private 5195 */ 5196 _bindAutoBindMethods: function() { 5197 for (var autoBindKey in this.__reactAutoBindMap) { 5198 if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) { 5199 continue; 5200 } 5201 var method = this.__reactAutoBindMap[autoBindKey]; 5202 this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard( 5203 method, 5204 this.constructor.displayName + '.' + autoBindKey 5205 )); 5206 } 5207 }, 5208 5209 /** 5210 * Binds a method to the component. 5211 * 5212 * @param {function} method Method to be bound. 5213 * @private 5214 */ 5215 _bindAutoBindMethod: function(method) { 5216 var component = this; 5217 var boundMethod = function() { 5218 return method.apply(component, arguments); 5219 }; 5220 if ("production" !== "development") { 5221 boundMethod.__reactBoundContext = component; 5222 boundMethod.__reactBoundMethod = method; 5223 boundMethod.__reactBoundArguments = null; 5224 var componentName = component.constructor.displayName; 5225 var _bind = boundMethod.bind; 5226 boundMethod.bind = function(newThis) { 5227 // User is trying to bind() an autobound method; we effectively will 5228 // ignore the value of "this" that the user is trying to use, so 5229 // let's warn. 5230 if (newThis !== component && newThis !== null) { 5231 console.warn( 5232 'bind(): React component methods may only be bound to the ' + 5233 'component instance. See ' + componentName 5234 ); 5235 } else if (arguments.length === 1) { 5236 console.warn( 5237 'bind(): You are binding a component method to the component. ' + 5238 'React does this for you automatically in a high-performance ' + 5239 'way, so you can safely remove this call. See ' + componentName 5240 ); 5241 return boundMethod; 5242 } 5243 var reboundMethod = _bind.apply(boundMethod, arguments); 5244 reboundMethod.__reactBoundContext = component; 5245 reboundMethod.__reactBoundMethod = method; 5246 reboundMethod.__reactBoundArguments = 5247 Array.prototype.slice.call(arguments, 1); 5248 return reboundMethod; 5249 }; 5250 } 5251 return boundMethod; 5252 } 5253 }; 5254 5255 var ReactCompositeComponentBase = function() {}; 5256 mixInto(ReactCompositeComponentBase, ReactComponent.Mixin); 5257 mixInto(ReactCompositeComponentBase, ReactOwner.Mixin); 5258 mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin); 5259 mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin); 5260 5261 /** 5262 * Module for creating composite components. 5263 * 5264 * @class ReactCompositeComponent 5265 * @extends ReactComponent 5266 * @extends ReactOwner 5267 * @extends ReactPropTransferer 5268 */ 5269 var ReactCompositeComponent = { 5270 5271 LifeCycle: CompositeLifeCycle, 5272 5273 Base: ReactCompositeComponentBase, 5274 5275 /** 5276 * Creates a composite component class given a class specification. 5277 * 5278 * @param {object} spec Class specification (which must define `render`). 5279 * @return {function} Component constructor function. 5280 * @public 5281 */ 5282 createClass: function(spec) { 5283 var Constructor = function() {}; 5284 Constructor.prototype = new ReactCompositeComponentBase(); 5285 Constructor.prototype.constructor = Constructor; 5286 mixSpecIntoComponent(Constructor, spec); 5287 5288 ("production" !== "development" ? invariant( 5289 Constructor.prototype.render, 5290 'createClass(...): Class specification must implement a `render` method.' 5291 ) : invariant(Constructor.prototype.render)); 5292 5293 if ("production" !== "development") { 5294 if (Constructor.prototype.componentShouldUpdate) { 5295 console.warn( 5296 (spec.displayName || 'A component') + ' has a method called ' + 5297 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 5298 'The name is phrased as a question because the function is ' + 5299 'expected to return a value.' 5300 ); 5301 } 5302 } 5303 5304 // Reduce time spent doing lookups by setting these on the prototype. 5305 for (var methodName in ReactCompositeComponentInterface) { 5306 if (!Constructor.prototype[methodName]) { 5307 Constructor.prototype[methodName] = null; 5308 } 5309 } 5310 5311 var ConvenienceConstructor = function(props, children) { 5312 var instance = new Constructor(); 5313 instance.construct.apply(instance, arguments); 5314 return instance; 5315 }; 5316 ConvenienceConstructor.componentConstructor = Constructor; 5317 ConvenienceConstructor.originalSpec = spec; 5318 return ConvenienceConstructor; 5319 }, 5320 5321 /** 5322 * Checks if a value is a valid component constructor. 5323 * 5324 * @param {*} 5325 * @return {boolean} 5326 * @public 5327 */ 5328 isValidClass: function(componentClass) { 5329 return componentClass instanceof Function && 5330 'componentConstructor' in componentClass && 5331 componentClass.componentConstructor instanceof Function; 5332 } 5333 }; 5334 5335 module.exports = ReactCompositeComponent; 5336 5337 },{"./ReactComponent":28,"./ReactCurrentOwner":32,"./ReactErrorUtils":46,"./ReactOwner":58,"./ReactPerf":59,"./ReactPropTransferer":60,"./ReactUpdates":70,"./invariant":109,"./keyMirror":115,"./merge":118,"./mixInto":121,"./objMap":123}],32:[function(require,module,exports){ 5338 /** 5339 * Copyright 2013 Facebook, Inc. 5340 * 5341 * Licensed under the Apache License, Version 2.0 (the "License"); 5342 * you may not use this file except in compliance with the License. 5343 * You may obtain a copy of the License at 5344 * 5345 * http://www.apache.org/licenses/LICENSE-2.0 5346 * 5347 * Unless required by applicable law or agreed to in writing, software 5348 * distributed under the License is distributed on an "AS IS" BASIS, 5349 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5350 * See the License for the specific language governing permissions and 5351 * limitations under the License. 5352 * 5353 * @providesModule ReactCurrentOwner 5354 */ 5355 5356 "use strict"; 5357 5358 /** 5359 * Keeps track of the current owner. 5360 * 5361 * The current owner is the component who should own any components that are 5362 * currently being constructed. 5363 * 5364 * The depth indicate how many composite components are above this render level. 5365 */ 5366 var ReactCurrentOwner = { 5367 5368 /** 5369 * @internal 5370 * @type {ReactComponent} 5371 */ 5372 current: null 5373 5374 }; 5375 5376 module.exports = ReactCurrentOwner; 5377 5378 },{}],33:[function(require,module,exports){ 5379 /** 5380 * Copyright 2013 Facebook, Inc. 5381 * 5382 * Licensed under the Apache License, Version 2.0 (the "License"); 5383 * you may not use this file except in compliance with the License. 5384 * You may obtain a copy of the License at 5385 * 5386 * http://www.apache.org/licenses/LICENSE-2.0 5387 * 5388 * Unless required by applicable law or agreed to in writing, software 5389 * distributed under the License is distributed on an "AS IS" BASIS, 5390 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5391 * See the License for the specific language governing permissions and 5392 * limitations under the License. 5393 * 5394 * @providesModule ReactDOM 5395 * @typechecks static-only 5396 */ 5397 5398 "use strict"; 5399 5400 var ReactDOMComponent = require("./ReactDOMComponent"); 5401 5402 var mergeInto = require("./mergeInto"); 5403 var objMapKeyVal = require("./objMapKeyVal"); 5404 5405 /** 5406 * Creates a new React class that is idempotent and capable of containing other 5407 * React components. It accepts event listeners and DOM properties that are 5408 * valid according to `DOMProperty`. 5409 * 5410 * - Event listeners: `onClick`, `onMouseDown`, etc. 5411 * - DOM properties: `className`, `name`, `title`, etc. 5412 * 5413 * The `style` property functions differently from the DOM API. It accepts an 5414 * object mapping of style properties to values. 5415 * 5416 * @param {string} tag Tag name (e.g. `div`). 5417 * @param {boolean} omitClose True if the close tag should be omitted. 5418 * @private 5419 */ 5420 function createDOMComponentClass(tag, omitClose) { 5421 var Constructor = function() {}; 5422 Constructor.prototype = new ReactDOMComponent(tag, omitClose); 5423 Constructor.prototype.constructor = Constructor; 5424 Constructor.displayName = tag; 5425 5426 var ConvenienceConstructor = function(props, children) { 5427 var instance = new Constructor(); 5428 instance.construct.apply(instance, arguments); 5429 return instance; 5430 }; 5431 ConvenienceConstructor.componentConstructor = Constructor; 5432 return ConvenienceConstructor; 5433 } 5434 5435 /** 5436 * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes. 5437 * This is also accessible via `React.DOM`. 5438 * 5439 * @public 5440 */ 5441 var ReactDOM = objMapKeyVal({ 5442 a: false, 5443 abbr: false, 5444 address: false, 5445 area: false, 5446 article: false, 5447 aside: false, 5448 audio: false, 5449 b: false, 5450 base: false, 5451 bdi: false, 5452 bdo: false, 5453 big: false, 5454 blockquote: false, 5455 body: false, 5456 br: true, 5457 button: false, 5458 canvas: false, 5459 caption: false, 5460 cite: false, 5461 code: false, 5462 col: true, 5463 colgroup: false, 5464 data: false, 5465 datalist: false, 5466 dd: false, 5467 del: false, 5468 details: false, 5469 dfn: false, 5470 div: false, 5471 dl: false, 5472 dt: false, 5473 em: false, 5474 embed: true, 5475 fieldset: false, 5476 figcaption: false, 5477 figure: false, 5478 footer: false, 5479 form: false, // NOTE: Injected, see `ReactDOMForm`. 5480 h1: false, 5481 h2: false, 5482 h3: false, 5483 h4: false, 5484 h5: false, 5485 h6: false, 5486 head: false, 5487 header: false, 5488 hr: true, 5489 html: false, 5490 i: false, 5491 iframe: false, 5492 img: true, 5493 input: true, 5494 ins: false, 5495 kbd: false, 5496 keygen: true, 5497 label: false, 5498 legend: false, 5499 li: false, 5500 link: false, 5501 main: false, 5502 map: false, 5503 mark: false, 5504 menu: false, 5505 menuitem: false, // NOTE: Close tag should be omitted, but causes problems. 5506 meta: true, 5507 meter: false, 5508 nav: false, 5509 noscript: false, 5510 object: false, 5511 ol: false, 5512 optgroup: false, 5513 option: false, 5514 output: false, 5515 p: false, 5516 param: true, 5517 pre: false, 5518 progress: false, 5519 q: false, 5520 rp: false, 5521 rt: false, 5522 ruby: false, 5523 s: false, 5524 samp: false, 5525 script: false, 5526 section: false, 5527 select: false, 5528 small: false, 5529 source: false, 5530 span: false, 5531 strong: false, 5532 style: false, 5533 sub: false, 5534 summary: false, 5535 sup: false, 5536 table: false, 5537 tbody: false, 5538 td: false, 5539 textarea: false, // NOTE: Injected, see `ReactDOMTextarea`. 5540 tfoot: false, 5541 th: false, 5542 thead: false, 5543 time: false, 5544 title: false, 5545 tr: false, 5546 track: true, 5547 u: false, 5548 ul: false, 5549 'var': false, 5550 video: false, 5551 wbr: false, 5552 5553 // SVG 5554 circle: false, 5555 g: false, 5556 line: false, 5557 path: false, 5558 polyline: false, 5559 rect: false, 5560 svg: false, 5561 text: false 5562 }, createDOMComponentClass); 5563 5564 var injection = { 5565 injectComponentClasses: function(componentClasses) { 5566 mergeInto(ReactDOM, componentClasses); 5567 } 5568 }; 5569 5570 ReactDOM.injection = injection; 5571 5572 module.exports = ReactDOM; 5573 5574 },{"./ReactDOMComponent":35,"./mergeInto":120,"./objMapKeyVal":124}],34:[function(require,module,exports){ 5575 /** 5576 * Copyright 2013 Facebook, Inc. 5577 * 5578 * Licensed under the Apache License, Version 2.0 (the "License"); 5579 * you may not use this file except in compliance with the License. 5580 * You may obtain a copy of the License at 5581 * 5582 * http://www.apache.org/licenses/LICENSE-2.0 5583 * 5584 * Unless required by applicable law or agreed to in writing, software 5585 * distributed under the License is distributed on an "AS IS" BASIS, 5586 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5587 * See the License for the specific language governing permissions and 5588 * limitations under the License. 5589 * 5590 * @providesModule ReactDOMButton 5591 */ 5592 5593 "use strict"; 5594 5595 var ReactCompositeComponent = require("./ReactCompositeComponent"); 5596 var ReactDOM = require("./ReactDOM"); 5597 5598 var keyMirror = require("./keyMirror"); 5599 5600 // Store a reference to the <button> `ReactDOMComponent`. 5601 var button = ReactDOM.button; 5602 5603 var mouseListenerNames = keyMirror({ 5604 onClick: true, 5605 onDoubleClick: true, 5606 onMouseDown: true, 5607 onMouseMove: true, 5608 onMouseUp: true, 5609 onClickCapture: true, 5610 onDoubleClickCapture: true, 5611 onMouseDownCapture: true, 5612 onMouseMoveCapture: true, 5613 onMouseUpCapture: true 5614 }); 5615 5616 /** 5617 * Implements a <button> native component that does not receive mouse events 5618 * when `disabled` is set. 5619 */ 5620 var ReactDOMButton = ReactCompositeComponent.createClass({ 5621 5622 render: function() { 5623 var props = {}; 5624 5625 // Copy the props; except the mouse listeners if we're disabled 5626 for (var key in this.props) { 5627 if (this.props.hasOwnProperty(key) && 5628 (!this.props.disabled || !mouseListenerNames[key])) { 5629 props[key] = this.props[key]; 5630 } 5631 } 5632 5633 return button(props, this.props.children); 5634 } 5635 5636 }); 5637 5638 module.exports = ReactDOMButton; 5639 5640 },{"./ReactCompositeComponent":31,"./ReactDOM":33,"./keyMirror":115}],35:[function(require,module,exports){ 5641 /** 5642 * Copyright 2013 Facebook, Inc. 5643 * 5644 * Licensed under the Apache License, Version 2.0 (the "License"); 5645 * you may not use this file except in compliance with the License. 5646 * You may obtain a copy of the License at 5647 * 5648 * http://www.apache.org/licenses/LICENSE-2.0 5649 * 5650 * Unless required by applicable law or agreed to in writing, software 5651 * distributed under the License is distributed on an "AS IS" BASIS, 5652 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 5653 * See the License for the specific language governing permissions and 5654 * limitations under the License. 5655 * 5656 * @providesModule ReactDOMComponent 5657 * @typechecks static-only 5658 */ 5659 5660 "use strict"; 5661 5662 var CSSPropertyOperations = require("./CSSPropertyOperations"); 5663 var DOMProperty = require("./DOMProperty"); 5664 var DOMPropertyOperations = require("./DOMPropertyOperations"); 5665 var ReactComponent = require("./ReactComponent"); 5666 var ReactEventEmitter = require("./ReactEventEmitter"); 5667 var ReactMultiChild = require("./ReactMultiChild"); 5668 var ReactMount = require("./ReactMount"); 5669 var ReactPerf = require("./ReactPerf"); 5670 5671 var escapeTextForBrowser = require("./escapeTextForBrowser"); 5672 var invariant = require("./invariant"); 5673 var keyOf = require("./keyOf"); 5674 var merge = require("./merge"); 5675 var mixInto = require("./mixInto"); 5676 5677 var putListener = ReactEventEmitter.putListener; 5678 var deleteListener = ReactEventEmitter.deleteListener; 5679 var registrationNames = ReactEventEmitter.registrationNames; 5680 5681 // For quickly matching children type, to test if can be treated as content. 5682 var CONTENT_TYPES = {'string': true, 'number': true}; 5683 5684 var STYLE = keyOf({style: null}); 5685 5686 /** 5687 * @param {?object} props 5688 */ 5689 function assertValidProps(props) { 5690 if (!props) { 5691 return; 5692 } 5693 // Note the use of `==` which checks for null or undefined. 5694 ("production" !== "development" ? invariant( 5695 props.children == null || props.dangerouslySetInnerHTML == null, 5696 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' 5697 ) : invariant(props.children == null || props.dangerouslySetInnerHTML == null)); 5698 ("production" !== "development" ? invariant( 5699 props.style == null || typeof props.style === 'object', 5700 'The `style` prop expects a mapping from style properties to values, ' + 5701 'not a string.' 5702 ) : invariant(props.style == null || typeof props.style === 'object')); 5703 } 5704 5705 /** 5706 * @constructor ReactDOMComponent 5707 * @extends ReactComponent 5708 * @extends ReactMultiChild 5709 */ 5710 function ReactDOMComponent(tag, omitClose) { 5711 this._tagOpen = '<' + tag; 5712 this._tagClose = omitClose ? '' : '</' + tag + '>'; 5713 this.tagName = tag.toUpperCase(); 5714 } 5715 5716 ReactDOMComponent.Mixin = { 5717 5718 /** 5719 * Generates root tag markup then recurses. This method has side effects and 5720 * is not idempotent. 5721 * 5722 * @internal 5723 * @param {string} rootID The root DOM ID for this node. 5724 * @param {ReactReconcileTransaction} transaction 5725 * @param {number} mountDepth number of components in the owner hierarchy 5726 * @return {string} The computed markup. 5727 */ 5728 mountComponent: ReactPerf.measure( 5729 'ReactDOMComponent', 5730 'mountComponent', 5731 function(rootID, transaction, mountDepth) { 5732 ReactComponent.Mixin.mountComponent.call( 5733 this, 5734 rootID, 5735 transaction, 5736 mountDepth 5737 ); 5738 assertValidProps(this.props); 5739 return ( 5740 this._createOpenTagMarkup() + 5741 this._createContentMarkup(transaction) + 5742 this._tagClose 5743 ); 5744 } 5745 ), 5746 5747 /** 5748 * Creates markup for the open tag and all attributes. 5749 * 5750 * This method has side effects because events get registered. 5751 * 5752 * Iterating over object properties is faster than iterating over arrays. 5753 * @see http://jsperf.com/obj-vs-arr-iteration 5754 * 5755 * @private 5756 * @return {string} Markup of opening tag. 5757 */ 5758 _createOpenTagMarkup: function() { 5759 var props = this.props; 5760 var ret = this._tagOpen; 5761 5762 for (var propKey in props) { 5763 if (!props.hasOwnProperty(propKey)) { 5764 continue; 5765 } 5766 var propValue = props[propKey]; 5767 if (propValue == null) { 5768 continue; 5769 } 5770 if (registrationNames[propKey]) { 5771 putListener(this._rootNodeID, propKey, propValue); 5772 } else { 5773 if (propKey === STYLE) { 5774 if (propValue) { 5775 propValue = props.style = merge(props.style); 5776 } 5777 propValue = CSSPropertyOperations.createMarkupForStyles(propValue); 5778 } 5779 var markup = 5780 DOMPropertyOperations.createMarkupForProperty(propKey, propValue); 5781 if (markup) { 5782 ret += ' ' + markup; 5783 } 5784 } 5785 } 5786 5787 var escapedID = escapeTextForBrowser(this._rootNodeID); 5788 return ret + ' ' + ReactMount.ATTR_NAME + '="' + escapedID + '">'; 5789 }, 5790 5791 /** 5792 * Creates markup for the content between the tags. 5793 * 5794 * @private 5795 * @param {ReactReconcileTransaction} transaction 5796 * @return {string} Content markup. 5797 */ 5798 _createContentMarkup: function(transaction) { 5799 // Intentional use of != to avoid catching zero/false. 5800 var innerHTML = this.props.dangerouslySetInnerHTML; 5801 if (innerHTML != null) { 5802 if (innerHTML.__html != null) { 5803 return innerHTML.__html; 5804 } 5805 } else { 5806 var contentToUse = 5807 CONTENT_TYPES[typeof this.props.children] ? this.props.children : null; 5808 var childrenToUse = contentToUse != null ? null : this.props.children; 5809 if (contentToUse != null) { 5810 return escapeTextForBrowser(contentToUse); 5811 } else if (childrenToUse != null) { 5812 var mountImages = this.mountChildren( 5813 childrenToUse, 5814 transaction 5815 ); 5816 return mountImages.join(''); 5817 } 5818 } 5819 return ''; 5820 }, 5821 5822 receiveComponent: function(nextComponent, transaction) { 5823 assertValidProps(nextComponent.props); 5824 ReactComponent.Mixin.receiveComponent.call( 5825 this, 5826 nextComponent, 5827 transaction 5828 ); 5829 }, 5830 5831 /** 5832 * Updates a native DOM component after it has already been allocated and 5833 * attached to the DOM. Reconciles the root DOM node, then recurses. 5834 * 5835 * @param {ReactReconcileTransaction} transaction 5836 * @param {object} prevProps 5837 * @internal 5838 * @overridable 5839 */ 5840 updateComponent: ReactPerf.measure( 5841 'ReactDOMComponent', 5842 'updateComponent', 5843 function(transaction, prevProps) { 5844 ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps); 5845 this._updateDOMProperties(prevProps); 5846 this._updateDOMChildren(prevProps, transaction); 5847 } 5848 ), 5849 5850 /** 5851 * Reconciles the properties by detecting differences in property values and 5852 * updating the DOM as necessary. This function is probably the single most 5853 * critical path for performance optimization. 5854 * 5855 * TODO: Benchmark whether checking for changed values in memory actually 5856 * improves performance (especially statically positioned elements). 5857 * TODO: Benchmark the effects of putting this at the top since 99% of props 5858 * do not change for a given reconciliation. 5859 * TODO: Benchmark areas that can be improved with caching. 5860 * 5861 * @private 5862 * @param {object} lastProps 5863 */ 5864 _updateDOMProperties: function(lastProps) { 5865 var nextProps = this.props; 5866 var propKey; 5867 var styleName; 5868 var styleUpdates; 5869 for (propKey in lastProps) { 5870 if (nextProps.hasOwnProperty(propKey) || 5871 !lastProps.hasOwnProperty(propKey)) { 5872 continue; 5873 } 5874 if (propKey === STYLE) { 5875 var lastStyle = lastProps[propKey]; 5876 for (styleName in lastStyle) { 5877 if (lastStyle.hasOwnProperty(styleName)) { 5878 styleUpdates = styleUpdates || {}; 5879 styleUpdates[styleName] = ''; 5880 } 5881 } 5882 } else if (registrationNames[propKey]) { 5883 deleteListener(this._rootNodeID, propKey); 5884 } else if ( 5885 DOMProperty.isStandardName[propKey] || 5886 DOMProperty.isCustomAttribute(propKey)) { 5887 ReactComponent.DOMIDOperations.deletePropertyByID( 5888 this._rootNodeID, 5889 propKey 5890 ); 5891 } 5892 } 5893 for (propKey in nextProps) { 5894 var nextProp = nextProps[propKey]; 5895 var lastProp = lastProps[propKey]; 5896 if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) { 5897 continue; 5898 } 5899 if (propKey === STYLE) { 5900 if (nextProp) { 5901 nextProp = nextProps.style = merge(nextProp); 5902 } 5903 if (lastProp) { 5904 // Unset styles on `lastProp` but not on `nextProp`. 5905 for (styleName in lastProp) { 5906 if (lastProp.hasOwnProperty(styleName) && 5907 !nextProp.hasOwnProperty(styleName)) { 5908 styleUpdates = styleUpdates || {}; 5909 styleUpdates[styleName] = ''; 5910 } 5911 } 5912 // Update styles that changed since `lastProp`. 5913 for (styleName in nextProp) { 5914 if (nextProp.hasOwnProperty(styleName) && 5915 lastProp[styleName] !== nextProp[styleName]) { 5916 styleUpdates = styleUpdates || {}; 5917 styleUpdates[styleName] = nextProp[styleName]; 5918 } 5919 } 5920 } else { 5921 // Relies on `updateStylesByID` not mutating `styleUpdates`. 5922 styleUpdates = nextProp; 5923 } 5924 } else if (registrationNames[propKey]) { 5925 putListener(this._rootNodeID, propKey, nextProp); 5926 } else if ( 5927 DOMProperty.isStandardName[propKey] || 5928 DOMProperty.isCustomAttribute(propKey)) { 5929 ReactComponent.DOMIDOperations.updatePropertyByID( 5930 this._rootNodeID, 5931 propKey, 5932 nextProp 5933 ); 5934 } 5935 } 5936 if (styleUpdates) { 5937 ReactComponent.DOMIDOperations.updateStylesByID( 5938 this._rootNodeID, 5939 styleUpdates 5940 ); 5941 } 5942 }, 5943 5944 /** 5945 * Reconciles the children with the various properties that affect the 5946 * children content. 5947 * 5948 * @param {object} lastProps 5949 * @param {ReactReconcileTransaction} transaction 5950 */ 5951 _updateDOMChildren: function(lastProps, transaction) { 5952 var nextProps = this.props; 5953 5954 var lastContent = 5955 CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null; 5956 var nextContent = 5957 CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null; 5958 5959 var lastHtml = 5960 lastProps.dangerouslySetInnerHTML && 5961 lastProps.dangerouslySetInnerHTML.__html; 5962 var nextHtml = 5963 nextProps.dangerouslySetInnerHTML && 5964 nextProps.dangerouslySetInnerHTML.__html; 5965 5966 // Note the use of `!=` which checks for null or undefined. 5967 var lastChildren = lastContent != null ? null : lastProps.children; 5968 var nextChildren = nextContent != null ? null : nextProps.children; 5969 5970 // If we're switching from children to content/html or vice versa, remove 5971 // the old content 5972 var lastHasContentOrHtml = lastContent != null || lastHtml != null; 5973 var nextHasContentOrHtml = nextContent != null || nextHtml != null; 5974 if (lastChildren != null && nextChildren == null) { 5975 this.updateChildren(null, transaction); 5976 } else if (lastHasContentOrHtml && !nextHasContentOrHtml) { 5977 this.updateTextContent(''); 5978 } 5979 5980 if (nextContent != null) { 5981 if (lastContent !== nextContent) { 5982 this.updateTextContent('' + nextContent); 5983 } 5984 } else if (nextHtml != null) { 5985 if (lastHtml !== nextHtml) { 5986 ReactComponent.DOMIDOperations.updateInnerHTMLByID( 5987 this._rootNodeID, 5988 nextHtml 5989 ); 5990 } 5991 } else if (nextChildren != null) { 5992 this.updateChildren(nextChildren, transaction); 5993 } 5994 }, 5995 5996 /** 5997 * Destroys all event registrations for this instance. Does not remove from 5998 * the DOM. That must be done by the parent. 5999 * 6000 * @internal 6001 */ 6002 unmountComponent: function() { 6003 ReactEventEmitter.deleteAllListeners(this._rootNodeID); 6004 ReactComponent.Mixin.unmountComponent.call(this); 6005 this.unmountChildren(); 6006 } 6007 6008 }; 6009 6010 mixInto(ReactDOMComponent, ReactComponent.Mixin); 6011 mixInto(ReactDOMComponent, ReactDOMComponent.Mixin); 6012 mixInto(ReactDOMComponent, ReactMultiChild.Mixin); 6013 6014 module.exports = ReactDOMComponent; 6015 6016 },{"./CSSPropertyOperations":4,"./DOMProperty":9,"./DOMPropertyOperations":10,"./ReactComponent":28,"./ReactEventEmitter":47,"./ReactMount":54,"./ReactMultiChild":56,"./ReactPerf":59,"./escapeTextForBrowser":95,"./invariant":109,"./keyOf":116,"./merge":118,"./mixInto":121}],36:[function(require,module,exports){ 6017 /** 6018 * Copyright 2013 Facebook, Inc. 6019 * 6020 * Licensed under the Apache License, Version 2.0 (the "License"); 6021 * you may not use this file except in compliance with the License. 6022 * You may obtain a copy of the License at 6023 * 6024 * http://www.apache.org/licenses/LICENSE-2.0 6025 * 6026 * Unless required by applicable law or agreed to in writing, software 6027 * distributed under the License is distributed on an "AS IS" BASIS, 6028 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6029 * See the License for the specific language governing permissions and 6030 * limitations under the License. 6031 * 6032 * @providesModule ReactDOMForm 6033 */ 6034 6035 "use strict"; 6036 6037 var ReactCompositeComponent = require("./ReactCompositeComponent"); 6038 var ReactDOM = require("./ReactDOM"); 6039 var ReactEventEmitter = require("./ReactEventEmitter"); 6040 var EventConstants = require("./EventConstants"); 6041 6042 // Store a reference to the <form> `ReactDOMComponent`. 6043 var form = ReactDOM.form; 6044 6045 /** 6046 * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need 6047 * to capture it on the <form> element itself. There are lots of hacks we could 6048 * do to accomplish this, but the most reliable is to make <form> a 6049 * composite component and use `componentDidMount` to attach the event handlers. 6050 */ 6051 var ReactDOMForm = ReactCompositeComponent.createClass({ 6052 render: function() { 6053 // TODO: Instead of using `ReactDOM` directly, we should use JSX. However, 6054 // `jshint` fails to parse JSX so in order for linting to work in the open 6055 // source repo, we need to just use `ReactDOM.form`. 6056 return this.transferPropsTo(form(null, this.props.children)); 6057 }, 6058 6059 componentDidMount: function(node) { 6060 ReactEventEmitter.trapBubbledEvent( 6061 EventConstants.topLevelTypes.topSubmit, 6062 'submit', 6063 node 6064 ); 6065 } 6066 }); 6067 6068 module.exports = ReactDOMForm; 6069 6070 },{"./EventConstants":15,"./ReactCompositeComponent":31,"./ReactDOM":33,"./ReactEventEmitter":47}],37:[function(require,module,exports){ 6071 /** 6072 * Copyright 2013 Facebook, Inc. 6073 * 6074 * Licensed under the Apache License, Version 2.0 (the "License"); 6075 * you may not use this file except in compliance with the License. 6076 * You may obtain a copy of the License at 6077 * 6078 * http://www.apache.org/licenses/LICENSE-2.0 6079 * 6080 * Unless required by applicable law or agreed to in writing, software 6081 * distributed under the License is distributed on an "AS IS" BASIS, 6082 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6083 * See the License for the specific language governing permissions and 6084 * limitations under the License. 6085 * 6086 * @providesModule ReactDOMIDOperations 6087 * @typechecks static-only 6088 */ 6089 6090 /*jslint evil: true */ 6091 6092 "use strict"; 6093 6094 var CSSPropertyOperations = require("./CSSPropertyOperations"); 6095 var DOMChildrenOperations = require("./DOMChildrenOperations"); 6096 var DOMPropertyOperations = require("./DOMPropertyOperations"); 6097 var ReactMount = require("./ReactMount"); 6098 6099 var getTextContentAccessor = require("./getTextContentAccessor"); 6100 var invariant = require("./invariant"); 6101 6102 /** 6103 * Errors for properties that should not be updated with `updatePropertyById()`. 6104 * 6105 * @type {object} 6106 * @private 6107 */ 6108 var INVALID_PROPERTY_ERRORS = { 6109 dangerouslySetInnerHTML: 6110 '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.', 6111 style: '`style` must be set using `updateStylesByID()`.' 6112 }; 6113 6114 /** 6115 * The DOM property to use when setting text content. 6116 * 6117 * @type {string} 6118 * @private 6119 */ 6120 var textContentAccessor = getTextContentAccessor() || 'NA'; 6121 6122 var LEADING_SPACE = /^ /; 6123 6124 /** 6125 * Operations used to process updates to DOM nodes. This is made injectable via 6126 * `ReactComponent.DOMIDOperations`. 6127 */ 6128 var ReactDOMIDOperations = { 6129 6130 /** 6131 * Updates a DOM node with new property values. This should only be used to 6132 * update DOM properties in `DOMProperty`. 6133 * 6134 * @param {string} id ID of the node to update. 6135 * @param {string} name A valid property name, see `DOMProperty`. 6136 * @param {*} value New value of the property. 6137 * @internal 6138 */ 6139 updatePropertyByID: function(id, name, value) { 6140 var node = ReactMount.getNode(id); 6141 ("production" !== "development" ? invariant( 6142 !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 6143 'updatePropertyByID(...): %s', 6144 INVALID_PROPERTY_ERRORS[name] 6145 ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); 6146 6147 // If we're updating to null or undefined, we should remove the property 6148 // from the DOM node instead of inadvertantly setting to a string. This 6149 // brings us in line with the same behavior we have on initial render. 6150 if (value != null) { 6151 DOMPropertyOperations.setValueForProperty(node, name, value); 6152 } else { 6153 DOMPropertyOperations.deleteValueForProperty(node, name); 6154 } 6155 }, 6156 6157 /** 6158 * Updates a DOM node to remove a property. This should only be used to remove 6159 * DOM properties in `DOMProperty`. 6160 * 6161 * @param {string} id ID of the node to update. 6162 * @param {string} name A property name to remove, see `DOMProperty`. 6163 * @internal 6164 */ 6165 deletePropertyByID: function(id, name, value) { 6166 var node = ReactMount.getNode(id); 6167 ("production" !== "development" ? invariant( 6168 !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 6169 'updatePropertyByID(...): %s', 6170 INVALID_PROPERTY_ERRORS[name] 6171 ) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name))); 6172 DOMPropertyOperations.deleteValueForProperty(node, name, value); 6173 }, 6174 6175 /** 6176 * Updates a DOM node with new style values. If a value is specified as '', 6177 * the corresponding style property will be unset. 6178 * 6179 * @param {string} id ID of the node to update. 6180 * @param {object} styles Mapping from styles to values. 6181 * @internal 6182 */ 6183 updateStylesByID: function(id, styles) { 6184 var node = ReactMount.getNode(id); 6185 CSSPropertyOperations.setValueForStyles(node, styles); 6186 }, 6187 6188 /** 6189 * Updates a DOM node's innerHTML. 6190 * 6191 * @param {string} id ID of the node to update. 6192 * @param {string} html An HTML string. 6193 * @internal 6194 */ 6195 updateInnerHTMLByID: function(id, html) { 6196 var node = ReactMount.getNode(id); 6197 // HACK: IE8- normalize whitespace in innerHTML, removing leading spaces. 6198 // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html 6199 node.innerHTML = html.replace(LEADING_SPACE, ' '); 6200 }, 6201 6202 /** 6203 * Updates a DOM node's text content set by `props.content`. 6204 * 6205 * @param {string} id ID of the node to update. 6206 * @param {string} content Text content. 6207 * @internal 6208 */ 6209 updateTextContentByID: function(id, content) { 6210 var node = ReactMount.getNode(id); 6211 node[textContentAccessor] = content; 6212 }, 6213 6214 /** 6215 * Replaces a DOM node that exists in the document with markup. 6216 * 6217 * @param {string} id ID of child to be replaced. 6218 * @param {string} markup Dangerous markup to inject in place of child. 6219 * @internal 6220 * @see {Danger.dangerouslyReplaceNodeWithMarkup} 6221 */ 6222 dangerouslyReplaceNodeWithMarkupByID: function(id, markup) { 6223 var node = ReactMount.getNode(id); 6224 DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); 6225 }, 6226 6227 /** 6228 * Updates a component's children by processing a series of updates. 6229 * 6230 * @param {array<object>} updates List of update configurations. 6231 * @param {array<string>} markup List of markup strings. 6232 * @internal 6233 */ 6234 dangerouslyProcessChildrenUpdates: function(updates, markup) { 6235 for (var i = 0; i < updates.length; i++) { 6236 updates[i].parentNode = ReactMount.getNode(updates[i].parentID); 6237 } 6238 DOMChildrenOperations.processUpdates(updates, markup); 6239 } 6240 6241 }; 6242 6243 module.exports = ReactDOMIDOperations; 6244 6245 },{"./CSSPropertyOperations":4,"./DOMChildrenOperations":8,"./DOMPropertyOperations":10,"./ReactMount":54,"./getTextContentAccessor":106,"./invariant":109}],38:[function(require,module,exports){ 6246 /** 6247 * Copyright 2013 Facebook, Inc. 6248 * 6249 * Licensed under the Apache License, Version 2.0 (the "License"); 6250 * you may not use this file except in compliance with the License. 6251 * You may obtain a copy of the License at 6252 * 6253 * http://www.apache.org/licenses/LICENSE-2.0 6254 * 6255 * Unless required by applicable law or agreed to in writing, software 6256 * distributed under the License is distributed on an "AS IS" BASIS, 6257 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6258 * See the License for the specific language governing permissions and 6259 * limitations under the License. 6260 * 6261 * @providesModule ReactDOMInput 6262 */ 6263 6264 "use strict"; 6265 6266 var DOMPropertyOperations = require("./DOMPropertyOperations"); 6267 var LinkedValueMixin = require("./LinkedValueMixin"); 6268 var ReactCompositeComponent = require("./ReactCompositeComponent"); 6269 var ReactDOM = require("./ReactDOM"); 6270 var ReactMount = require("./ReactMount"); 6271 6272 var invariant = require("./invariant"); 6273 var merge = require("./merge"); 6274 6275 // Store a reference to the <input> `ReactDOMComponent`. 6276 var input = ReactDOM.input; 6277 6278 var instancesByReactID = {}; 6279 6280 /** 6281 * Implements an <input> native component that allows setting these optional 6282 * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. 6283 * 6284 * If `checked` or `value` are not supplied (or null/undefined), user actions 6285 * that affect the checked state or value will trigger updates to the element. 6286 * 6287 * If they are supplied (and not null/undefined), the rendered element will not 6288 * trigger updates to the element. Instead, the props must change in order for 6289 * the rendered element to be updated. 6290 * 6291 * The rendered element will be initialized as unchecked (or `defaultChecked`) 6292 * with an empty value (or `defaultValue`). 6293 * 6294 * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html 6295 */ 6296 var ReactDOMInput = ReactCompositeComponent.createClass({ 6297 mixins: [LinkedValueMixin], 6298 6299 getInitialState: function() { 6300 var defaultValue = this.props.defaultValue; 6301 return { 6302 checked: this.props.defaultChecked || false, 6303 value: defaultValue != null ? defaultValue : null 6304 }; 6305 }, 6306 6307 shouldComponentUpdate: function() { 6308 // Defer any updates to this component during the `onChange` handler. 6309 return !this._isChanging; 6310 }, 6311 6312 render: function() { 6313 // Clone `this.props` so we don't mutate the input. 6314 var props = merge(this.props); 6315 6316 props.defaultChecked = null; 6317 props.defaultValue = null; 6318 props.checked = 6319 this.props.checked != null ? this.props.checked : this.state.checked; 6320 6321 var value = this.getValue(); 6322 props.value = value != null ? value : this.state.value; 6323 6324 props.onChange = this._handleChange; 6325 6326 return input(props, this.props.children); 6327 }, 6328 6329 componentDidMount: function(rootNode) { 6330 var id = ReactMount.getID(rootNode); 6331 instancesByReactID[id] = this; 6332 }, 6333 6334 componentWillUnmount: function() { 6335 var rootNode = this.getDOMNode(); 6336 var id = ReactMount.getID(rootNode); 6337 delete instancesByReactID[id]; 6338 }, 6339 6340 componentDidUpdate: function(prevProps, prevState, rootNode) { 6341 if (this.props.checked != null) { 6342 DOMPropertyOperations.setValueForProperty( 6343 rootNode, 6344 'checked', 6345 this.props.checked || false 6346 ); 6347 } 6348 6349 var value = this.getValue(); 6350 if (value != null) { 6351 // Cast `value` to a string to ensure the value is set correctly. While 6352 // browsers typically do this as necessary, jsdom doesn't. 6353 DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value); 6354 } 6355 }, 6356 6357 _handleChange: function(event) { 6358 var returnValue; 6359 var onChange = this.getOnChange(); 6360 if (onChange) { 6361 this._isChanging = true; 6362 returnValue = onChange(event); 6363 this._isChanging = false; 6364 } 6365 this.setState({ 6366 checked: event.target.checked, 6367 value: event.target.value 6368 }); 6369 6370 var name = this.props.name; 6371 if (this.props.type === 'radio' && name != null) { 6372 var rootNode = this.getDOMNode(); 6373 // If `rootNode.form` was non-null, then we could try `form.elements`, 6374 // but that sometimes behaves strangely in IE8. We could also try using 6375 // `form.getElementsByName`, but that will only return direct children 6376 // and won't include inputs that use the HTML5 `form=` attribute. Since 6377 // the input might not even be in a form, let's just use the global 6378 // `getElementsByName` to ensure we don't miss anything. 6379 var group = document.getElementsByName(name); 6380 for (var i = 0, groupLen = group.length; i < groupLen; i++) { 6381 var otherNode = group[i]; 6382 if (otherNode === rootNode || 6383 otherNode.nodeName !== 'INPUT' || otherNode.type !== 'radio' || 6384 otherNode.form !== rootNode.form) { 6385 continue; 6386 } 6387 var otherID = ReactMount.getID(otherNode); 6388 ("production" !== "development" ? invariant( 6389 otherID, 6390 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 6391 'same `name` is not supported.' 6392 ) : invariant(otherID)); 6393 var otherInstance = instancesByReactID[otherID]; 6394 ("production" !== "development" ? invariant( 6395 otherInstance, 6396 'ReactDOMInput: Unknown radio button ID %s.', 6397 otherID 6398 ) : invariant(otherInstance)); 6399 // In some cases, this will actually change the `checked` state value. 6400 // In other cases, there's no change but this forces a reconcile upon 6401 // which componentDidUpdate will reset the DOM property to whatever it 6402 // should be. 6403 otherInstance.setState({ 6404 checked: false 6405 }); 6406 } 6407 } 6408 6409 return returnValue; 6410 } 6411 6412 }); 6413 6414 module.exports = ReactDOMInput; 6415 6416 },{"./DOMPropertyOperations":10,"./LinkedValueMixin":23,"./ReactCompositeComponent":31,"./ReactDOM":33,"./ReactMount":54,"./invariant":109,"./merge":118}],39:[function(require,module,exports){ 6417 /** 6418 * Copyright 2013 Facebook, Inc. 6419 * 6420 * Licensed under the Apache License, Version 2.0 (the "License"); 6421 * you may not use this file except in compliance with the License. 6422 * You may obtain a copy of the License at 6423 * 6424 * http://www.apache.org/licenses/LICENSE-2.0 6425 * 6426 * Unless required by applicable law or agreed to in writing, software 6427 * distributed under the License is distributed on an "AS IS" BASIS, 6428 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6429 * See the License for the specific language governing permissions and 6430 * limitations under the License. 6431 * 6432 * @providesModule ReactDOMOption 6433 */ 6434 6435 "use strict"; 6436 6437 var ReactCompositeComponent = require("./ReactCompositeComponent"); 6438 var ReactDOM = require("./ReactDOM"); 6439 6440 // Store a reference to the <option> `ReactDOMComponent`. 6441 var option = ReactDOM.option; 6442 6443 /** 6444 * Implements an <option> native component that warns when `selected` is set. 6445 */ 6446 var ReactDOMOption = ReactCompositeComponent.createClass({ 6447 6448 componentWillMount: function() { 6449 // TODO (yungsters): Remove support for `selected` in <option>. 6450 if (this.props.selected != null) { 6451 if ("production" !== "development") { 6452 console.warn( 6453 'Use the `defaultValue` or `value` props on <select> instead of ' + 6454 'setting `selected` on <option>.' 6455 ); 6456 } 6457 } 6458 }, 6459 6460 render: function() { 6461 return option(this.props, this.props.children); 6462 } 6463 6464 }); 6465 6466 module.exports = ReactDOMOption; 6467 6468 },{"./ReactCompositeComponent":31,"./ReactDOM":33}],40:[function(require,module,exports){ 6469 /** 6470 * Copyright 2013 Facebook, Inc. 6471 * 6472 * Licensed under the Apache License, Version 2.0 (the "License"); 6473 * you may not use this file except in compliance with the License. 6474 * You may obtain a copy of the License at 6475 * 6476 * http://www.apache.org/licenses/LICENSE-2.0 6477 * 6478 * Unless required by applicable law or agreed to in writing, software 6479 * distributed under the License is distributed on an "AS IS" BASIS, 6480 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6481 * See the License for the specific language governing permissions and 6482 * limitations under the License. 6483 * 6484 * @providesModule ReactDOMSelect 6485 */ 6486 6487 "use strict"; 6488 6489 var LinkedValueMixin = require("./LinkedValueMixin"); 6490 var ReactCompositeComponent = require("./ReactCompositeComponent"); 6491 var ReactDOM = require("./ReactDOM"); 6492 6493 var invariant = require("./invariant"); 6494 var merge = require("./merge"); 6495 6496 // Store a reference to the <select> `ReactDOMComponent`. 6497 var select = ReactDOM.select; 6498 6499 /** 6500 * Validation function for `value` and `defaultValue`. 6501 * @private 6502 */ 6503 function selectValueType(props, propName, componentName) { 6504 if (props[propName] == null) { 6505 return; 6506 } 6507 if (props.multiple) { 6508 ("production" !== "development" ? invariant( 6509 Array.isArray(props[propName]), 6510 'The `%s` prop supplied to <select> must be an array if `multiple` is ' + 6511 'true.', 6512 propName 6513 ) : invariant(Array.isArray(props[propName]))); 6514 } else { 6515 ("production" !== "development" ? invariant( 6516 !Array.isArray(props[propName]), 6517 'The `%s` prop supplied to <select> must be a scalar value if ' + 6518 '`multiple` is false.', 6519 propName 6520 ) : invariant(!Array.isArray(props[propName]))); 6521 } 6522 } 6523 6524 /** 6525 * If `value` is supplied, updates <option> elements on mount and update. 6526 * @private 6527 */ 6528 function updateOptions() { 6529 /*jshint validthis:true */ 6530 var propValue = this.getValue(); 6531 var value = propValue != null ? propValue : this.state.value; 6532 var options = this.getDOMNode().options; 6533 var selectedValue = '' + value; 6534 6535 for (var i = 0, l = options.length; i < l; i++) { 6536 var selected = this.props.multiple ? 6537 selectedValue.indexOf(options[i].value) >= 0 : 6538 selected = options[i].value === selectedValue; 6539 6540 if (selected !== options[i].selected) { 6541 options[i].selected = selected; 6542 } 6543 } 6544 } 6545 6546 /** 6547 * Implements a <select> native component that allows optionally setting the 6548 * props `value` and `defaultValue`. If `multiple` is false, the prop must be a 6549 * string. If `multiple` is true, the prop must be an array of strings. 6550 * 6551 * If `value` is not supplied (or null/undefined), user actions that change the 6552 * selected option will trigger updates to the rendered options. 6553 * 6554 * If it is supplied (and not null/undefined), the rendered options will not 6555 * update in response to user actions. Instead, the `value` prop must change in 6556 * order for the rendered options to update. 6557 * 6558 * If `defaultValue` is provided, any options with the supplied values will be 6559 * selected. 6560 */ 6561 var ReactDOMSelect = ReactCompositeComponent.createClass({ 6562 mixins: [LinkedValueMixin], 6563 6564 propTypes: { 6565 defaultValue: selectValueType, 6566 value: selectValueType 6567 }, 6568 6569 getInitialState: function() { 6570 return {value: this.props.defaultValue || (this.props.multiple ? [] : '')}; 6571 }, 6572 6573 componentWillReceiveProps: function(nextProps) { 6574 if (!this.props.multiple && nextProps.multiple) { 6575 this.setState({value: [this.state.value]}); 6576 } else if (this.props.multiple && !nextProps.multiple) { 6577 this.setState({value: this.state.value[0]}); 6578 } 6579 }, 6580 6581 shouldComponentUpdate: function() { 6582 // Defer any updates to this component during the `onChange` handler. 6583 return !this._isChanging; 6584 }, 6585 6586 render: function() { 6587 // Clone `this.props` so we don't mutate the input. 6588 var props = merge(this.props); 6589 6590 props.onChange = this._handleChange; 6591 props.value = null; 6592 6593 return select(props, this.props.children); 6594 }, 6595 6596 componentDidMount: updateOptions, 6597 6598 componentDidUpdate: updateOptions, 6599 6600 _handleChange: function(event) { 6601 var returnValue; 6602 var onChange = this.getOnChange(); 6603 if (onChange) { 6604 this._isChanging = true; 6605 returnValue = onChange(event); 6606 this._isChanging = false; 6607 } 6608 6609 var selectedValue; 6610 if (this.props.multiple) { 6611 selectedValue = []; 6612 var options = event.target.options; 6613 for (var i = 0, l = options.length; i < l; i++) { 6614 if (options[i].selected) { 6615 selectedValue.push(options[i].value); 6616 } 6617 } 6618 } else { 6619 selectedValue = event.target.value; 6620 } 6621 6622 this.setState({value: selectedValue}); 6623 return returnValue; 6624 } 6625 6626 }); 6627 6628 module.exports = ReactDOMSelect; 6629 6630 },{"./LinkedValueMixin":23,"./ReactCompositeComponent":31,"./ReactDOM":33,"./invariant":109,"./merge":118}],41:[function(require,module,exports){ 6631 /** 6632 * Copyright 2013 Facebook, Inc. 6633 * 6634 * Licensed under the Apache License, Version 2.0 (the "License"); 6635 * you may not use this file except in compliance with the License. 6636 * You may obtain a copy of the License at 6637 * 6638 * http://www.apache.org/licenses/LICENSE-2.0 6639 * 6640 * Unless required by applicable law or agreed to in writing, software 6641 * distributed under the License is distributed on an "AS IS" BASIS, 6642 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6643 * See the License for the specific language governing permissions and 6644 * limitations under the License. 6645 * 6646 * @providesModule ReactDOMSelection 6647 */ 6648 6649 "use strict"; 6650 6651 var getNodeForCharacterOffset = require("./getNodeForCharacterOffset"); 6652 var getTextContentAccessor = require("./getTextContentAccessor"); 6653 6654 /** 6655 * Get the appropriate anchor and focus node/offset pairs for IE. 6656 * 6657 * The catch here is that IE's selection API doesn't provide information 6658 * about whether the selection is forward or backward, so we have to 6659 * behave as though it's always forward. 6660 * 6661 * IE text differs from modern selection in that it behaves as though 6662 * block elements end with a new line. This means character offsets will 6663 * differ between the two APIs. 6664 * 6665 * @param {DOMElement} node 6666 * @return {object} 6667 */ 6668 function getIEOffsets(node) { 6669 var selection = document.selection; 6670 var selectedRange = selection.createRange(); 6671 var selectedLength = selectedRange.text.length; 6672 6673 // Duplicate selection so we can move range without breaking user selection. 6674 var fromStart = selectedRange.duplicate(); 6675 fromStart.moveToElementText(node); 6676 fromStart.setEndPoint('EndToStart', selectedRange); 6677 6678 var startOffset = fromStart.text.length; 6679 var endOffset = startOffset + selectedLength; 6680 6681 return { 6682 start: startOffset, 6683 end: endOffset 6684 }; 6685 } 6686 6687 /** 6688 * @param {DOMElement} node 6689 * @return {?object} 6690 */ 6691 function getModernOffsets(node) { 6692 var selection = window.getSelection(); 6693 6694 if (selection.rangeCount === 0) { 6695 return null; 6696 } 6697 6698 var anchorNode = selection.anchorNode; 6699 var anchorOffset = selection.anchorOffset; 6700 var focusNode = selection.focusNode; 6701 var focusOffset = selection.focusOffset; 6702 6703 var currentRange = selection.getRangeAt(0); 6704 var rangeLength = currentRange.toString().length; 6705 6706 var tempRange = currentRange.cloneRange(); 6707 tempRange.selectNodeContents(node); 6708 tempRange.setEnd(currentRange.startContainer, currentRange.startOffset); 6709 6710 var start = tempRange.toString().length; 6711 var end = start + rangeLength; 6712 6713 // Detect whether the selection is backward. 6714 var detectionRange = document.createRange(); 6715 detectionRange.setStart(anchorNode, anchorOffset); 6716 detectionRange.setEnd(focusNode, focusOffset); 6717 var isBackward = detectionRange.collapsed; 6718 detectionRange.detach(); 6719 6720 return { 6721 start: isBackward ? end : start, 6722 end: isBackward ? start : end 6723 }; 6724 } 6725 6726 /** 6727 * @param {DOMElement|DOMTextNode} node 6728 * @param {object} offsets 6729 */ 6730 function setIEOffsets(node, offsets) { 6731 var range = document.selection.createRange().duplicate(); 6732 var start, end; 6733 6734 if (typeof offsets.end === 'undefined') { 6735 start = offsets.start; 6736 end = start; 6737 } else if (offsets.start > offsets.end) { 6738 start = offsets.end; 6739 end = offsets.start; 6740 } else { 6741 start = offsets.start; 6742 end = offsets.end; 6743 } 6744 6745 range.moveToElementText(node); 6746 range.moveStart('character', start); 6747 range.setEndPoint('EndToStart', range); 6748 range.moveEnd('character', end - start); 6749 range.select(); 6750 } 6751 6752 /** 6753 * In modern non-IE browsers, we can support both forward and backward 6754 * selections. 6755 * 6756 * Note: IE10+ supports the Selection object, but it does not support 6757 * the `extend` method, which means that even in modern IE, it's not possible 6758 * to programatically create a backward selection. Thus, for all IE 6759 * versions, we use the old IE API to create our selections. 6760 * 6761 * @param {DOMElement|DOMTextNode} node 6762 * @param {object} offsets 6763 */ 6764 function setModernOffsets(node, offsets) { 6765 var selection = window.getSelection(); 6766 6767 var length = node[getTextContentAccessor()].length; 6768 var start = Math.min(offsets.start, length); 6769 var end = typeof offsets.end === 'undefined' ? 6770 start : Math.min(offsets.end, length); 6771 6772 // IE 11 uses modern selection, but doesn't support the extend method. 6773 // Flip backward selections, so we can set with a single range. 6774 if (!selection.extend && start > end) { 6775 var temp = end; 6776 end = start; 6777 start = temp; 6778 } 6779 6780 var startMarker = getNodeForCharacterOffset(node, start); 6781 var endMarker = getNodeForCharacterOffset(node, end); 6782 6783 if (startMarker && endMarker) { 6784 var range = document.createRange(); 6785 range.setStart(startMarker.node, startMarker.offset); 6786 selection.removeAllRanges(); 6787 6788 if (start > end) { 6789 selection.addRange(range); 6790 selection.extend(endMarker.node, endMarker.offset); 6791 } else { 6792 range.setEnd(endMarker.node, endMarker.offset); 6793 selection.addRange(range); 6794 } 6795 6796 range.detach(); 6797 } 6798 } 6799 6800 var ReactDOMSelection = { 6801 /** 6802 * @param {DOMElement} node 6803 */ 6804 getOffsets: function(node) { 6805 var getOffsets = document.selection ? getIEOffsets : getModernOffsets; 6806 return getOffsets(node); 6807 }, 6808 6809 /** 6810 * @param {DOMElement|DOMTextNode} node 6811 * @param {object} offsets 6812 */ 6813 setOffsets: function(node, offsets) { 6814 var setOffsets = document.selection ? setIEOffsets : setModernOffsets; 6815 setOffsets(node, offsets); 6816 } 6817 }; 6818 6819 module.exports = ReactDOMSelection; 6820 6821 },{"./getNodeForCharacterOffset":104,"./getTextContentAccessor":106}],42:[function(require,module,exports){ 6822 /** 6823 * Copyright 2013 Facebook, Inc. 6824 * 6825 * Licensed under the Apache License, Version 2.0 (the "License"); 6826 * you may not use this file except in compliance with the License. 6827 * You may obtain a copy of the License at 6828 * 6829 * http://www.apache.org/licenses/LICENSE-2.0 6830 * 6831 * Unless required by applicable law or agreed to in writing, software 6832 * distributed under the License is distributed on an "AS IS" BASIS, 6833 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6834 * See the License for the specific language governing permissions and 6835 * limitations under the License. 6836 * 6837 * @providesModule ReactDOMTextarea 6838 */ 6839 6840 "use strict"; 6841 6842 var DOMPropertyOperations = require("./DOMPropertyOperations"); 6843 var LinkedValueMixin = require("./LinkedValueMixin"); 6844 var ReactCompositeComponent = require("./ReactCompositeComponent"); 6845 var ReactDOM = require("./ReactDOM"); 6846 6847 var invariant = require("./invariant"); 6848 var merge = require("./merge"); 6849 6850 // Store a reference to the <textarea> `ReactDOMComponent`. 6851 var textarea = ReactDOM.textarea; 6852 6853 /** 6854 * Implements a <textarea> native component that allows setting `value`, and 6855 * `defaultValue`. This differs from the traditional DOM API because value is 6856 * usually set as PCDATA children. 6857 * 6858 * If `value` is not supplied (or null/undefined), user actions that affect the 6859 * value will trigger updates to the element. 6860 * 6861 * If `value` is supplied (and not null/undefined), the rendered element will 6862 * not trigger updates to the element. Instead, the `value` prop must change in 6863 * order for the rendered element to be updated. 6864 * 6865 * The rendered element will be initialized with an empty value, the prop 6866 * `defaultValue` if specified, or the children content (deprecated). 6867 */ 6868 var ReactDOMTextarea = ReactCompositeComponent.createClass({ 6869 mixins: [LinkedValueMixin], 6870 6871 getInitialState: function() { 6872 var defaultValue = this.props.defaultValue; 6873 // TODO (yungsters): Remove support for children content in <textarea>. 6874 var children = this.props.children; 6875 if (children != null) { 6876 if ("production" !== "development") { 6877 console.warn( 6878 'Use the `defaultValue` or `value` props instead of setting ' + 6879 'children on <textarea>.' 6880 ); 6881 } 6882 ("production" !== "development" ? invariant( 6883 defaultValue == null, 6884 'If you supply `defaultValue` on a <textarea>, do not pass children.' 6885 ) : invariant(defaultValue == null)); 6886 if (Array.isArray(children)) { 6887 ("production" !== "development" ? invariant( 6888 children.length <= 1, 6889 '<textarea> can only have at most one child.' 6890 ) : invariant(children.length <= 1)); 6891 children = children[0]; 6892 } 6893 6894 defaultValue = '' + children; 6895 } 6896 if (defaultValue == null) { 6897 defaultValue = ''; 6898 } 6899 var value = this.getValue(); 6900 return { 6901 // We save the initial value so that `ReactDOMComponent` doesn't update 6902 // `textContent` (unnecessary since we update value). 6903 // The initial value can be a boolean or object so that's why it's 6904 // forced to be a string. 6905 initialValue: '' + (value != null ? value : defaultValue), 6906 value: defaultValue 6907 }; 6908 }, 6909 6910 shouldComponentUpdate: function() { 6911 // Defer any updates to this component during the `onChange` handler. 6912 return !this._isChanging; 6913 }, 6914 6915 render: function() { 6916 // Clone `this.props` so we don't mutate the input. 6917 var props = merge(this.props); 6918 var value = this.getValue(); 6919 6920 ("production" !== "development" ? invariant( 6921 props.dangerouslySetInnerHTML == null, 6922 '`dangerouslySetInnerHTML` does not make sense on <textarea>.' 6923 ) : invariant(props.dangerouslySetInnerHTML == null)); 6924 6925 props.defaultValue = null; 6926 props.value = value != null ? value : this.state.value; 6927 props.onChange = this._handleChange; 6928 6929 // Always set children to the same thing. In IE9, the selection range will 6930 // get reset if `textContent` is mutated. 6931 return textarea(props, this.state.initialValue); 6932 }, 6933 6934 componentDidUpdate: function(prevProps, prevState, rootNode) { 6935 var value = this.getValue(); 6936 if (value != null) { 6937 // Cast `value` to a string to ensure the value is set correctly. While 6938 // browsers typically do this as necessary, jsdom doesn't. 6939 DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value); 6940 } 6941 }, 6942 6943 _handleChange: function(event) { 6944 var returnValue; 6945 var onChange = this.getOnChange(); 6946 if (onChange) { 6947 this._isChanging = true; 6948 returnValue = onChange(event); 6949 this._isChanging = false; 6950 } 6951 this.setState({value: event.target.value}); 6952 return returnValue; 6953 } 6954 6955 }); 6956 6957 module.exports = ReactDOMTextarea; 6958 6959 },{"./DOMPropertyOperations":10,"./LinkedValueMixin":23,"./ReactCompositeComponent":31,"./ReactDOM":33,"./invariant":109,"./merge":118}],43:[function(require,module,exports){ 6960 /** 6961 * Copyright 2013 Facebook, Inc. 6962 * 6963 * Licensed under the Apache License, Version 2.0 (the "License"); 6964 * you may not use this file except in compliance with the License. 6965 * You may obtain a copy of the License at 6966 * 6967 * http://www.apache.org/licenses/LICENSE-2.0 6968 * 6969 * Unless required by applicable law or agreed to in writing, software 6970 * distributed under the License is distributed on an "AS IS" BASIS, 6971 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 6972 * See the License for the specific language governing permissions and 6973 * limitations under the License. 6974 * 6975 * @providesModule ReactDefaultBatchingStrategy 6976 */ 6977 6978 "use strict"; 6979 6980 var ReactUpdates = require("./ReactUpdates"); 6981 var Transaction = require("./Transaction"); 6982 6983 var emptyFunction = require("./emptyFunction"); 6984 var mixInto = require("./mixInto"); 6985 6986 var RESET_BATCHED_UPDATES = { 6987 initialize: emptyFunction, 6988 close: function() { 6989 ReactDefaultBatchingStrategy.isBatchingUpdates = false; 6990 } 6991 }; 6992 6993 var FLUSH_BATCHED_UPDATES = { 6994 initialize: emptyFunction, 6995 close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates) 6996 }; 6997 6998 var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES]; 6999 7000 function ReactDefaultBatchingStrategyTransaction() { 7001 this.reinitializeTransaction(); 7002 } 7003 7004 mixInto(ReactDefaultBatchingStrategyTransaction, Transaction.Mixin); 7005 mixInto(ReactDefaultBatchingStrategyTransaction, { 7006 getTransactionWrappers: function() { 7007 return TRANSACTION_WRAPPERS; 7008 } 7009 }); 7010 7011 var transaction = new ReactDefaultBatchingStrategyTransaction(); 7012 7013 var ReactDefaultBatchingStrategy = { 7014 isBatchingUpdates: false, 7015 7016 /** 7017 * Call the provided function in a context within which calls to `setState` 7018 * and friends are batched such that components aren't updated unnecessarily. 7019 */ 7020 batchedUpdates: function(callback, param) { 7021 var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates; 7022 7023 ReactDefaultBatchingStrategy.isBatchingUpdates = true; 7024 7025 // The code is written this way to avoid extra allocations 7026 if (alreadyBatchingUpdates) { 7027 callback(param); 7028 } else { 7029 transaction.perform(callback, null, param); 7030 } 7031 } 7032 }; 7033 7034 module.exports = ReactDefaultBatchingStrategy; 7035 7036 },{"./ReactUpdates":70,"./Transaction":83,"./emptyFunction":94,"./mixInto":121}],44:[function(require,module,exports){ 7037 /** 7038 * Copyright 2013 Facebook, Inc. 7039 * 7040 * Licensed under the Apache License, Version 2.0 (the "License"); 7041 * you may not use this file except in compliance with the License. 7042 * You may obtain a copy of the License at 7043 * 7044 * http://www.apache.org/licenses/LICENSE-2.0 7045 * 7046 * Unless required by applicable law or agreed to in writing, software 7047 * distributed under the License is distributed on an "AS IS" BASIS, 7048 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7049 * See the License for the specific language governing permissions and 7050 * limitations under the License. 7051 * 7052 * @providesModule ReactDefaultInjection 7053 */ 7054 7055 "use strict"; 7056 7057 var ReactDOM = require("./ReactDOM"); 7058 var ReactDOMButton = require("./ReactDOMButton"); 7059 var ReactDOMForm = require("./ReactDOMForm"); 7060 var ReactDOMInput = require("./ReactDOMInput"); 7061 var ReactDOMOption = require("./ReactDOMOption"); 7062 var ReactDOMSelect = require("./ReactDOMSelect"); 7063 var ReactDOMTextarea = require("./ReactDOMTextarea"); 7064 var ReactEventEmitter = require("./ReactEventEmitter"); 7065 var ReactEventTopLevelCallback = require("./ReactEventTopLevelCallback"); 7066 var ReactPerf = require("./ReactPerf"); 7067 7068 var DefaultDOMPropertyConfig = require("./DefaultDOMPropertyConfig"); 7069 var DOMProperty = require("./DOMProperty"); 7070 7071 var ChangeEventPlugin = require("./ChangeEventPlugin"); 7072 var CompositionEventPlugin = require("./CompositionEventPlugin"); 7073 var DefaultEventPluginOrder = require("./DefaultEventPluginOrder"); 7074 var EnterLeaveEventPlugin = require("./EnterLeaveEventPlugin"); 7075 var EventPluginHub = require("./EventPluginHub"); 7076 var MobileSafariClickEventPlugin = require("./MobileSafariClickEventPlugin"); 7077 var ReactInstanceHandles = require("./ReactInstanceHandles"); 7078 var SelectEventPlugin = require("./SelectEventPlugin"); 7079 var SimpleEventPlugin = require("./SimpleEventPlugin"); 7080 7081 var ReactDefaultBatchingStrategy = require("./ReactDefaultBatchingStrategy"); 7082 var ReactUpdates = require("./ReactUpdates"); 7083 7084 function inject() { 7085 ReactEventEmitter.TopLevelCallbackCreator = ReactEventTopLevelCallback; 7086 /** 7087 * Inject module for resolving DOM hierarchy and plugin ordering. 7088 */ 7089 EventPluginHub.injection.injectEventPluginOrder(DefaultEventPluginOrder); 7090 EventPluginHub.injection.injectInstanceHandle(ReactInstanceHandles); 7091 7092 /** 7093 * Some important event plugins included by default (without having to require 7094 * them). 7095 */ 7096 EventPluginHub.injection.injectEventPluginsByName({ 7097 SimpleEventPlugin: SimpleEventPlugin, 7098 EnterLeaveEventPlugin: EnterLeaveEventPlugin, 7099 ChangeEventPlugin: ChangeEventPlugin, 7100 CompositionEventPlugin: CompositionEventPlugin, 7101 MobileSafariClickEventPlugin: MobileSafariClickEventPlugin, 7102 SelectEventPlugin: SelectEventPlugin 7103 }); 7104 7105 ReactDOM.injection.injectComponentClasses({ 7106 button: ReactDOMButton, 7107 form: ReactDOMForm, 7108 input: ReactDOMInput, 7109 option: ReactDOMOption, 7110 select: ReactDOMSelect, 7111 textarea: ReactDOMTextarea 7112 }); 7113 7114 DOMProperty.injection.injectDOMPropertyConfig(DefaultDOMPropertyConfig); 7115 7116 if ("production" !== "development") { 7117 ReactPerf.injection.injectMeasure(require("./ReactDefaultPerf").measure); 7118 } 7119 7120 ReactUpdates.injection.injectBatchingStrategy( 7121 ReactDefaultBatchingStrategy 7122 ); 7123 } 7124 7125 module.exports = { 7126 inject: inject 7127 }; 7128 7129 },{"./ChangeEventPlugin":6,"./CompositionEventPlugin":7,"./DOMProperty":9,"./DefaultDOMPropertyConfig":12,"./DefaultEventPluginOrder":13,"./EnterLeaveEventPlugin":14,"./EventPluginHub":17,"./MobileSafariClickEventPlugin":24,"./ReactDOM":33,"./ReactDOMButton":34,"./ReactDOMForm":36,"./ReactDOMInput":38,"./ReactDOMOption":39,"./ReactDOMSelect":40,"./ReactDOMTextarea":42,"./ReactDefaultBatchingStrategy":43,"./ReactDefaultPerf":45,"./ReactEventEmitter":47,"./ReactEventTopLevelCallback":49,"./ReactInstanceHandles":51,"./ReactPerf":59,"./ReactUpdates":70,"./SelectEventPlugin":72,"./SimpleEventPlugin":73}],45:[function(require,module,exports){ 7130 /** 7131 * Copyright 2013 Facebook, Inc. 7132 * 7133 * Licensed under the Apache License, Version 2.0 (the "License"); 7134 * you may not use this file except in compliance with the License. 7135 * You may obtain a copy of the License at 7136 * 7137 * http://www.apache.org/licenses/LICENSE-2.0 7138 * 7139 * Unless required by applicable law or agreed to in writing, software 7140 * distributed under the License is distributed on an "AS IS" BASIS, 7141 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7142 * See the License for the specific language governing permissions and 7143 * limitations under the License. 7144 * 7145 * @providesModule ReactDefaultPerf 7146 * @typechecks static-only 7147 */ 7148 7149 "use strict"; 7150 7151 var performanceNow = require("./performanceNow"); 7152 7153 var ReactDefaultPerf = {}; 7154 7155 if ("production" !== "development") { 7156 ReactDefaultPerf = { 7157 /** 7158 * Gets the stored information for a given object's function. 7159 * 7160 * @param {string} objName 7161 * @param {string} fnName 7162 * @return {?object} 7163 */ 7164 getInfo: function(objName, fnName) { 7165 if (!this.info[objName] || !this.info[objName][fnName]) { 7166 return null; 7167 } 7168 return this.info[objName][fnName]; 7169 }, 7170 7171 /** 7172 * Gets the logs pertaining to a given object's function. 7173 * 7174 * @param {string} objName 7175 * @param {string} fnName 7176 * @return {?array<object>} 7177 */ 7178 getLogs: function(objName, fnName) { 7179 if (!this.getInfo(objName, fnName)) { 7180 return null; 7181 } 7182 return this.logs.filter(function(log) { 7183 return log.objName === objName && log.fnName === fnName; 7184 }); 7185 }, 7186 7187 /** 7188 * Runs through the logs and builds an array of arrays, where each array 7189 * walks through the mounting/updating of each component underneath. 7190 * 7191 * @param {string} rootID The reactID of the root node, e.g. '.r[2cpyq]' 7192 * @return {array<array>} 7193 */ 7194 getRawRenderHistory: function(rootID) { 7195 var history = []; 7196 /** 7197 * Since logs are added after the method returns, the logs are in a sense 7198 * upside-down: the inner-most elements from mounting/updating are logged 7199 * first, and the last addition to the log is the top renderComponent. 7200 * Therefore, we flip the logs upside down for ease of processing, and 7201 * reverse the history array at the end so the earliest event has index 0. 7202 */ 7203 var logs = this.logs.filter(function(log) { 7204 return log.reactID.indexOf(rootID) === 0; 7205 }).reverse(); 7206 7207 var subHistory = []; 7208 logs.forEach(function(log, i) { 7209 if (i && log.reactID === rootID && logs[i - 1].reactID !== rootID) { 7210 subHistory.length && history.push(subHistory); 7211 subHistory = []; 7212 } 7213 subHistory.push(log); 7214 }); 7215 if (subHistory.length) { 7216 history.push(subHistory); 7217 } 7218 return history.reverse(); 7219 }, 7220 7221 /** 7222 * Runs through the logs and builds an array of strings, where each string 7223 * is a multiline formatted way of walking through the mounting/updating 7224 * underneath. 7225 * 7226 * @param {string} rootID The reactID of the root node, e.g. '.r[2cpyq]' 7227 * @return {array<string>} 7228 */ 7229 getRenderHistory: function(rootID) { 7230 var history = this.getRawRenderHistory(rootID); 7231 7232 return history.map(function(subHistory) { 7233 var headerString = ( 7234 'log# Component (execution time) [bloat from logging]\n' + 7235 '================================================================\n' 7236 ); 7237 return headerString + subHistory.map(function(log) { 7238 // Add two spaces for every layer in the reactID. 7239 var indents = '\t' + Array(log.reactID.split('.[').length).join(' '); 7240 var delta = _microTime(log.timing.delta); 7241 var bloat = _microTime(log.timing.timeToLog); 7242 7243 return log.index + indents + log.name + ' (' + delta + 'ms)' + 7244 ' [' + bloat + 'ms]'; 7245 }).join('\n'); 7246 }); 7247 }, 7248 7249 /** 7250 * Print the render history from `getRenderHistory` using console.log. 7251 * This is currently the best way to display perf data from 7252 * any React component; working on that. 7253 * 7254 * @param {string} rootID The reactID of the root node, e.g. '.r[2cpyq]' 7255 * @param {number} index 7256 */ 7257 printRenderHistory: function(rootID, index) { 7258 var history = this.getRenderHistory(rootID); 7259 if (!history[index]) { 7260 console.warn( 7261 'Index', index, 'isn\'t available! ' + 7262 'The render history is', history.length, 'long.' 7263 ); 7264 return; 7265 } 7266 console.log( 7267 'Loading render history #' + (index + 1) + 7268 ' of ' + history.length + ':\n' + history[index] 7269 ); 7270 }, 7271 7272 /** 7273 * Prints the heatmap legend to console, showing how the colors correspond 7274 * with render times. This relies on console.log styles. 7275 */ 7276 printHeatmapLegend: function() { 7277 if (!this.options.heatmap.enabled) { 7278 return; 7279 } 7280 var max = this.info.React 7281 && this.info.React.renderComponent 7282 && this.info.React.renderComponent.max; 7283 if (max) { 7284 var logStr = 'Heatmap: '; 7285 for (var ii = 0; ii <= 10 * max; ii += max) { 7286 logStr += '%c ' + (Math.round(ii) / 10) + 'ms '; 7287 } 7288 console.log( 7289 logStr, 7290 'background-color: hsla(100, 100%, 50%, 0.6);', 7291 'background-color: hsla( 90, 100%, 50%, 0.6);', 7292 'background-color: hsla( 80, 100%, 50%, 0.6);', 7293 'background-color: hsla( 70, 100%, 50%, 0.6);', 7294 'background-color: hsla( 60, 100%, 50%, 0.6);', 7295 'background-color: hsla( 50, 100%, 50%, 0.6);', 7296 'background-color: hsla( 40, 100%, 50%, 0.6);', 7297 'background-color: hsla( 30, 100%, 50%, 0.6);', 7298 'background-color: hsla( 20, 100%, 50%, 0.6);', 7299 'background-color: hsla( 10, 100%, 50%, 0.6);', 7300 'background-color: hsla( 0, 100%, 50%, 0.6);' 7301 ); 7302 } 7303 }, 7304 7305 /** 7306 * Measure a given function with logging information, and calls a callback 7307 * if there is one. 7308 * 7309 * @param {string} objName 7310 * @param {string} fnName 7311 * @param {function} func 7312 * @return {function} 7313 */ 7314 measure: function(objName, fnName, func) { 7315 var info = _getNewInfo(objName, fnName); 7316 7317 var fnArgs = _getFnArguments(func); 7318 7319 return function() { 7320 var timeBeforeFn = performanceNow(); 7321 var fnReturn = func.apply(this, arguments); 7322 var timeAfterFn = performanceNow(); 7323 7324 /** 7325 * Hold onto arguments in a readable way: args[1] -> args.component. 7326 * args is also passed to the callback, so if you want to save an 7327 * argument in the log, do so in the callback. 7328 */ 7329 var args = {}; 7330 for (var i = 0; i < arguments.length; i++) { 7331 args[fnArgs[i]] = arguments[i]; 7332 } 7333 7334 var log = { 7335 index: ReactDefaultPerf.logs.length, 7336 fnName: fnName, 7337 objName: objName, 7338 timing: { 7339 before: timeBeforeFn, 7340 after: timeAfterFn, 7341 delta: timeAfterFn - timeBeforeFn 7342 } 7343 }; 7344 7345 ReactDefaultPerf.logs.push(log); 7346 7347 /** 7348 * The callback gets: 7349 * - this (the component) 7350 * - the original method's arguments 7351 * - what the method returned 7352 * - the log object, and 7353 * - the wrapped method's info object. 7354 */ 7355 var callback = _getCallback(objName, fnName); 7356 callback && callback(this, args, fnReturn, log, info); 7357 7358 log.timing.timeToLog = performanceNow() - timeAfterFn; 7359 7360 return fnReturn; 7361 }; 7362 }, 7363 7364 /** 7365 * Holds information on wrapped objects/methods. 7366 * For instance, ReactDefaultPerf.info.React.renderComponent 7367 */ 7368 info: {}, 7369 7370 /** 7371 * Holds all of the logs. Filter this to pull desired information. 7372 */ 7373 logs: [], 7374 7375 /** 7376 * Toggle settings for ReactDefaultPerf 7377 */ 7378 options: { 7379 /** 7380 * The heatmap sets the background color of the React containers 7381 * according to how much total time has been spent rendering them. 7382 * The most temporally expensive component is set as pure red, 7383 * and the others are colored from green to red as a fraction 7384 * of that max component time. 7385 */ 7386 heatmap: { 7387 enabled: true 7388 } 7389 } 7390 }; 7391 7392 /** 7393 * Gets a info area for a given object's function, adding a new one if 7394 * necessary. 7395 * 7396 * @param {string} objName 7397 * @param {string} fnName 7398 * @return {object} 7399 */ 7400 var _getNewInfo = function(objName, fnName) { 7401 var info = ReactDefaultPerf.getInfo(objName, fnName); 7402 if (info) { 7403 return info; 7404 } 7405 ReactDefaultPerf.info[objName] = ReactDefaultPerf.info[objName] || {}; 7406 7407 return ReactDefaultPerf.info[objName][fnName] = { 7408 getLogs: function() { 7409 return ReactDefaultPerf.getLogs(objName, fnName); 7410 } 7411 }; 7412 }; 7413 7414 /** 7415 * Gets a list of the argument names from a function's definition. 7416 * This is useful for storing arguments by their names within wrapFn(). 7417 * 7418 * @param {function} fn 7419 * @return {array<string>} 7420 */ 7421 var _getFnArguments = function(fn) { 7422 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; 7423 var fnStr = fn.toString().replace(STRIP_COMMENTS, ''); 7424 fnStr = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')); 7425 return fnStr.match(/([^\s,]+)/g); 7426 }; 7427 7428 /** 7429 * Store common callbacks within ReactDefaultPerf. 7430 * 7431 * @param {string} objName 7432 * @param {string} fnName 7433 * @return {?function} 7434 */ 7435 var _getCallback = function(objName, fnName) { 7436 switch (objName + '.' + fnName) { 7437 case 'React.renderComponent': 7438 return _renderComponentCallback; 7439 case 'ReactDOMComponent.mountComponent': 7440 case 'ReactDOMComponent.updateComponent': 7441 return _nativeComponentCallback; 7442 case 'ReactCompositeComponent.mountComponent': 7443 case 'ReactCompositeComponent.updateComponent': 7444 return _compositeComponentCallback; 7445 default: 7446 return null; 7447 } 7448 }; 7449 7450 /** 7451 * Callback function for React.renderComponent 7452 * 7453 * @param {object} component 7454 * @param {object} args 7455 * @param {?object} fnReturn 7456 * @param {object} log 7457 * @param {object} info 7458 */ 7459 var _renderComponentCallback = 7460 function(component, args, fnReturn, log, info) { 7461 log.name = args.nextComponent.constructor.displayName || '[unknown]'; 7462 log.reactID = fnReturn._rootNodeID || null; 7463 7464 if (ReactDefaultPerf.options.heatmap.enabled) { 7465 var container = args.container; 7466 if (!container.loggedByReactDefaultPerf) { 7467 container.loggedByReactDefaultPerf = true; 7468 info.components = info.components || []; 7469 info.components.push(container); 7470 } 7471 7472 container.count = container.count || 0; 7473 container.count += log.timing.delta; 7474 info.max = info.max || 0; 7475 if (container.count > info.max) { 7476 info.max = container.count; 7477 info.components.forEach(function(component) { 7478 _setHue(component, 100 - 100 * component.count / info.max); 7479 }); 7480 } else { 7481 _setHue(container, 100 - 100 * container.count / info.max); 7482 } 7483 } 7484 }; 7485 7486 /** 7487 * Callback function for ReactDOMComponent 7488 * 7489 * @param {object} component 7490 * @param {object} args 7491 * @param {?object} fnReturn 7492 * @param {object} log 7493 * @param {object} info 7494 */ 7495 var _nativeComponentCallback = 7496 function(component, args, fnReturn, log, info) { 7497 log.name = component.tagName || '[unknown]'; 7498 log.reactID = component._rootNodeID; 7499 }; 7500 7501 /** 7502 * Callback function for ReactCompositeComponent 7503 * 7504 * @param {object} component 7505 * @param {object} args 7506 * @param {?object} fnReturn 7507 * @param {object} log 7508 * @param {object} info 7509 */ 7510 var _compositeComponentCallback = 7511 function(component, args, fnReturn, log, info) { 7512 log.name = component.constructor.displayName || '[unknown]'; 7513 log.reactID = component._rootNodeID; 7514 }; 7515 7516 /** 7517 * Using the hsl() background-color attribute, colors an element. 7518 * 7519 * @param {DOMElement} el 7520 * @param {number} hue [0 for red, 120 for green, 240 for blue] 7521 */ 7522 var _setHue = function(el, hue) { 7523 el.style.backgroundColor = 'hsla(' + hue + ', 100%, 50%, 0.6)'; 7524 }; 7525 7526 /** 7527 * Round to the thousandth place. 7528 * @param {number} time 7529 * @return {number} 7530 */ 7531 var _microTime = function(time) { 7532 return Math.round(time * 1000) / 1000; 7533 }; 7534 } 7535 7536 module.exports = ReactDefaultPerf; 7537 7538 },{"./performanceNow":125}],46:[function(require,module,exports){ 7539 /** 7540 * Copyright 2013 Facebook, Inc. 7541 * 7542 * Licensed under the Apache License, Version 2.0 (the "License"); 7543 * you may not use this file except in compliance with the License. 7544 * You may obtain a copy of the License at 7545 * 7546 * http://www.apache.org/licenses/LICENSE-2.0 7547 * 7548 * Unless required by applicable law or agreed to in writing, software 7549 * distributed under the License is distributed on an "AS IS" BASIS, 7550 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7551 * See the License for the specific language governing permissions and 7552 * limitations under the License. 7553 * 7554 * @providesModule ReactErrorUtils 7555 * @typechecks 7556 */ 7557 7558 var ReactErrorUtils = { 7559 /** 7560 * Creates a guarded version of a function. This is supposed to make debugging 7561 * of event handlers easier. This implementation provides only basic error 7562 * logging and re-throws the error. 7563 * 7564 * @param {function} func Function to be executed 7565 * @param {string} name The name of the guard 7566 * @return {function} 7567 */ 7568 guard: function(func, name) { 7569 if ("production" !== "development") { 7570 return function guarded() { 7571 try { 7572 return func.apply(this, arguments); 7573 } catch(ex) { 7574 console.error(name + ': ' + ex.message); 7575 throw ex; 7576 } 7577 }; 7578 } else { 7579 return func; 7580 } 7581 } 7582 }; 7583 7584 module.exports = ReactErrorUtils; 7585 7586 },{}],47:[function(require,module,exports){ 7587 /** 7588 * Copyright 2013 Facebook, Inc. 7589 * 7590 * Licensed under the Apache License, Version 2.0 (the "License"); 7591 * you may not use this file except in compliance with the License. 7592 * You may obtain a copy of the License at 7593 * 7594 * http://www.apache.org/licenses/LICENSE-2.0 7595 * 7596 * Unless required by applicable law or agreed to in writing, software 7597 * distributed under the License is distributed on an "AS IS" BASIS, 7598 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7599 * See the License for the specific language governing permissions and 7600 * limitations under the License. 7601 * 7602 * @providesModule ReactEventEmitter 7603 * @typechecks static-only 7604 */ 7605 7606 "use strict"; 7607 7608 var EventConstants = require("./EventConstants"); 7609 var EventListener = require("./EventListener"); 7610 var EventPluginHub = require("./EventPluginHub"); 7611 var ExecutionEnvironment = require("./ExecutionEnvironment"); 7612 var ReactEventEmitterMixin = require("./ReactEventEmitterMixin"); 7613 var ViewportMetrics = require("./ViewportMetrics"); 7614 7615 var invariant = require("./invariant"); 7616 var isEventSupported = require("./isEventSupported"); 7617 var merge = require("./merge"); 7618 7619 /** 7620 * Summary of `ReactEventEmitter` event handling: 7621 * 7622 * - Top-level delegation is used to trap native browser events. We normalize 7623 * and de-duplicate events to account for browser quirks. 7624 * 7625 * - Forward these native events (with the associated top-level type used to 7626 * trap it) to `EventPluginHub`, which in turn will ask plugins if they want 7627 * to extract any synthetic events. 7628 * 7629 * - The `EventPluginHub` will then process each event by annotating them with 7630 * "dispatches", a sequence of listeners and IDs that care about that event. 7631 * 7632 * - The `EventPluginHub` then dispatches the events. 7633 * 7634 * Overview of React and the event system: 7635 * 7636 * . 7637 * +------------+ . 7638 * | DOM | . 7639 * +------------+ . +-----------+ 7640 * + . +--------+|SimpleEvent| 7641 * | . | |Plugin | 7642 * +-----|------+ . v +-----------+ 7643 * | | | . +--------------+ +------------+ 7644 * | +-----------.--->|EventPluginHub| | Event | 7645 * | | . | | +-----------+ | Propagators| 7646 * | ReactEvent | . | | |TapEvent | |------------| 7647 * | Emitter | . | |<---+|Plugin | |other plugin| 7648 * | | . | | +-----------+ | utilities | 7649 * | +-----------.---------+ | +------------+ 7650 * | | | . +----|---------+ 7651 * +-----|------+ . | ^ +-----------+ 7652 * | . | | |Enter/Leave| 7653 * + . | +-------+|Plugin | 7654 * +-------------+ . v +-----------+ 7655 * | application | . +----------+ 7656 * |-------------| . | callback | 7657 * | | . | registry | 7658 * | | . +----------+ 7659 * +-------------+ . 7660 * . 7661 * React Core . General Purpose Event Plugin System 7662 */ 7663 7664 /** 7665 * Traps top-level events by using event bubbling. 7666 * 7667 * @param {string} topLevelType Record from `EventConstants`. 7668 * @param {string} handlerBaseName Event name (e.g. "click"). 7669 * @param {DOMEventTarget} element Element on which to attach listener. 7670 * @internal 7671 */ 7672 function trapBubbledEvent(topLevelType, handlerBaseName, element) { 7673 EventListener.listen( 7674 element, 7675 handlerBaseName, 7676 ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback( 7677 topLevelType 7678 ) 7679 ); 7680 } 7681 7682 /** 7683 * Traps a top-level event by using event capturing. 7684 * 7685 * @param {string} topLevelType Record from `EventConstants`. 7686 * @param {string} handlerBaseName Event name (e.g. "click"). 7687 * @param {DOMEventTarget} element Element on which to attach listener. 7688 * @internal 7689 */ 7690 function trapCapturedEvent(topLevelType, handlerBaseName, element) { 7691 EventListener.capture( 7692 element, 7693 handlerBaseName, 7694 ReactEventEmitter.TopLevelCallbackCreator.createTopLevelCallback( 7695 topLevelType 7696 ) 7697 ); 7698 } 7699 7700 /** 7701 * Listens to window scroll and resize events. We cache scroll values so that 7702 * application code can access them without triggering reflows. 7703 * 7704 * NOTE: Scroll events do not bubble. 7705 * 7706 * @private 7707 * @see http://www.quirksmode.org/dom/events/scroll.html 7708 */ 7709 function registerScrollValueMonitoring() { 7710 var refresh = ViewportMetrics.refreshScrollValues; 7711 EventListener.listen(window, 'scroll', refresh); 7712 EventListener.listen(window, 'resize', refresh); 7713 } 7714 7715 /** 7716 * `ReactEventEmitter` is used to attach top-level event listeners. For example: 7717 * 7718 * ReactEventEmitter.putListener('myID', 'onClick', myFunction); 7719 * 7720 * This would allocate a "registration" of `('onClick', myFunction)` on 'myID'. 7721 * 7722 * @internal 7723 */ 7724 var ReactEventEmitter = merge(ReactEventEmitterMixin, { 7725 7726 /** 7727 * React references `ReactEventTopLevelCallback` using this property in order 7728 * to allow dependency injection. 7729 */ 7730 TopLevelCallbackCreator: null, 7731 7732 /** 7733 * Ensures that top-level event delegation listeners are installed. 7734 * 7735 * There are issues with listening to both touch events and mouse events on 7736 * the top-level, so we make the caller choose which one to listen to. (If 7737 * there's a touch top-level listeners, anchors don't receive clicks for some 7738 * reason, and only in some cases). 7739 * 7740 * @param {boolean} touchNotMouse Listen to touch events instead of mouse. 7741 * @param {DOMDocument} contentDocument DOM document to listen on 7742 */ 7743 ensureListening: function(touchNotMouse, contentDocument) { 7744 ("production" !== "development" ? invariant( 7745 ExecutionEnvironment.canUseDOM, 7746 'ensureListening(...): Cannot toggle event listening in a Worker ' + 7747 'thread. This is likely a bug in the framework. Please report ' + 7748 'immediately.' 7749 ) : invariant(ExecutionEnvironment.canUseDOM)); 7750 ("production" !== "development" ? invariant( 7751 ReactEventEmitter.TopLevelCallbackCreator, 7752 'ensureListening(...): Cannot be called without a top level callback ' + 7753 'creator being injected.' 7754 ) : invariant(ReactEventEmitter.TopLevelCallbackCreator)); 7755 // Call out to base implementation. 7756 ReactEventEmitterMixin.ensureListening.call( 7757 ReactEventEmitter, 7758 { 7759 touchNotMouse: touchNotMouse, 7760 contentDocument: contentDocument 7761 } 7762 ); 7763 }, 7764 7765 /** 7766 * Sets whether or not any created callbacks should be enabled. 7767 * 7768 * @param {boolean} enabled True if callbacks should be enabled. 7769 */ 7770 setEnabled: function(enabled) { 7771 ("production" !== "development" ? invariant( 7772 ExecutionEnvironment.canUseDOM, 7773 'setEnabled(...): Cannot toggle event listening in a Worker thread. ' + 7774 'This is likely a bug in the framework. Please report immediately.' 7775 ) : invariant(ExecutionEnvironment.canUseDOM)); 7776 if (ReactEventEmitter.TopLevelCallbackCreator) { 7777 ReactEventEmitter.TopLevelCallbackCreator.setEnabled(enabled); 7778 } 7779 }, 7780 7781 /** 7782 * @return {boolean} True if callbacks are enabled. 7783 */ 7784 isEnabled: function() { 7785 return !!( 7786 ReactEventEmitter.TopLevelCallbackCreator && 7787 ReactEventEmitter.TopLevelCallbackCreator.isEnabled() 7788 ); 7789 }, 7790 7791 /** 7792 * We listen for bubbled touch events on the document object. 7793 * 7794 * Firefox v8.01 (and possibly others) exhibited strange behavior when 7795 * mounting `onmousemove` events at some node that was not the document 7796 * element. The symptoms were that if your mouse is not moving over something 7797 * contained within that mount point (for example on the background) the 7798 * top-level listeners for `onmousemove` won't be called. However, if you 7799 * register the `mousemove` on the document object, then it will of course 7800 * catch all `mousemove`s. This along with iOS quirks, justifies restricting 7801 * top-level listeners to the document object only, at least for these 7802 * movement types of events and possibly all events. 7803 * 7804 * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html 7805 * 7806 * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but 7807 * they bubble to document. 7808 * 7809 * @param {boolean} touchNotMouse Listen to touch events instead of mouse. 7810 * @param {DOMDocument} contentDocument Document which owns the container 7811 * @private 7812 * @see http://www.quirksmode.org/dom/events/keys.html. 7813 */ 7814 listenAtTopLevel: function(touchNotMouse, contentDocument) { 7815 ("production" !== "development" ? invariant( 7816 !contentDocument._isListening, 7817 'listenAtTopLevel(...): Cannot setup top-level listener more than once.' 7818 ) : invariant(!contentDocument._isListening)); 7819 var topLevelTypes = EventConstants.topLevelTypes; 7820 var mountAt = contentDocument; 7821 7822 registerScrollValueMonitoring(); 7823 trapBubbledEvent(topLevelTypes.topMouseOver, 'mouseover', mountAt); 7824 trapBubbledEvent(topLevelTypes.topMouseDown, 'mousedown', mountAt); 7825 trapBubbledEvent(topLevelTypes.topMouseUp, 'mouseup', mountAt); 7826 trapBubbledEvent(topLevelTypes.topMouseMove, 'mousemove', mountAt); 7827 trapBubbledEvent(topLevelTypes.topMouseOut, 'mouseout', mountAt); 7828 trapBubbledEvent(topLevelTypes.topClick, 'click', mountAt); 7829 trapBubbledEvent(topLevelTypes.topDoubleClick, 'dblclick', mountAt); 7830 trapBubbledEvent(topLevelTypes.topContextMenu, 'contextmenu', mountAt); 7831 if (touchNotMouse) { 7832 trapBubbledEvent(topLevelTypes.topTouchStart, 'touchstart', mountAt); 7833 trapBubbledEvent(topLevelTypes.topTouchEnd, 'touchend', mountAt); 7834 trapBubbledEvent(topLevelTypes.topTouchMove, 'touchmove', mountAt); 7835 trapBubbledEvent(topLevelTypes.topTouchCancel, 'touchcancel', mountAt); 7836 } 7837 trapBubbledEvent(topLevelTypes.topKeyUp, 'keyup', mountAt); 7838 trapBubbledEvent(topLevelTypes.topKeyPress, 'keypress', mountAt); 7839 trapBubbledEvent(topLevelTypes.topKeyDown, 'keydown', mountAt); 7840 trapBubbledEvent(topLevelTypes.topInput, 'input', mountAt); 7841 trapBubbledEvent(topLevelTypes.topChange, 'change', mountAt); 7842 trapBubbledEvent( 7843 topLevelTypes.topSelectionChange, 7844 'selectionchange', 7845 mountAt 7846 ); 7847 7848 trapBubbledEvent( 7849 topLevelTypes.topCompositionEnd, 7850 'compositionend', 7851 mountAt 7852 ); 7853 trapBubbledEvent( 7854 topLevelTypes.topCompositionStart, 7855 'compositionstart', 7856 mountAt 7857 ); 7858 trapBubbledEvent( 7859 topLevelTypes.topCompositionUpdate, 7860 'compositionupdate', 7861 mountAt 7862 ); 7863 7864 if (isEventSupported('drag')) { 7865 trapBubbledEvent(topLevelTypes.topDrag, 'drag', mountAt); 7866 trapBubbledEvent(topLevelTypes.topDragEnd, 'dragend', mountAt); 7867 trapBubbledEvent(topLevelTypes.topDragEnter, 'dragenter', mountAt); 7868 trapBubbledEvent(topLevelTypes.topDragExit, 'dragexit', mountAt); 7869 trapBubbledEvent(topLevelTypes.topDragLeave, 'dragleave', mountAt); 7870 trapBubbledEvent(topLevelTypes.topDragOver, 'dragover', mountAt); 7871 trapBubbledEvent(topLevelTypes.topDragStart, 'dragstart', mountAt); 7872 trapBubbledEvent(topLevelTypes.topDrop, 'drop', mountAt); 7873 } 7874 7875 if (isEventSupported('wheel')) { 7876 trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt); 7877 } else if (isEventSupported('mousewheel')) { 7878 trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt); 7879 } else { 7880 // Firefox needs to capture a different mouse scroll event. 7881 // @see http://www.quirksmode.org/dom/events/tests/scroll.html 7882 trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt); 7883 } 7884 7885 // IE<9 does not support capturing so just trap the bubbled event there. 7886 if (isEventSupported('scroll', true)) { 7887 trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt); 7888 } else { 7889 trapBubbledEvent(topLevelTypes.topScroll, 'scroll', window); 7890 } 7891 7892 if (isEventSupported('focus', true)) { 7893 trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt); 7894 trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt); 7895 } else if (isEventSupported('focusin')) { 7896 // IE has `focusin` and `focusout` events which bubble. 7897 // @see 7898 // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html 7899 trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt); 7900 trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt); 7901 } 7902 7903 if (isEventSupported('copy')) { 7904 trapBubbledEvent(topLevelTypes.topCopy, 'copy', mountAt); 7905 trapBubbledEvent(topLevelTypes.topCut, 'cut', mountAt); 7906 trapBubbledEvent(topLevelTypes.topPaste, 'paste', mountAt); 7907 } 7908 }, 7909 7910 registrationNames: EventPluginHub.registrationNames, 7911 7912 putListener: EventPluginHub.putListener, 7913 7914 getListener: EventPluginHub.getListener, 7915 7916 deleteListener: EventPluginHub.deleteListener, 7917 7918 deleteAllListeners: EventPluginHub.deleteAllListeners, 7919 7920 trapBubbledEvent: trapBubbledEvent, 7921 7922 trapCapturedEvent: trapCapturedEvent 7923 7924 }); 7925 7926 7927 module.exports = ReactEventEmitter; 7928 7929 },{"./EventConstants":15,"./EventListener":16,"./EventPluginHub":17,"./ExecutionEnvironment":21,"./ReactEventEmitterMixin":48,"./ViewportMetrics":84,"./invariant":109,"./isEventSupported":110,"./merge":118}],48:[function(require,module,exports){ 7930 /** 7931 * Copyright 2013 Facebook, Inc. 7932 * 7933 * Licensed under the Apache License, Version 2.0 (the "License"); 7934 * you may not use this file except in compliance with the License. 7935 * You may obtain a copy of the License at 7936 * 7937 * http://www.apache.org/licenses/LICENSE-2.0 7938 * 7939 * Unless required by applicable law or agreed to in writing, software 7940 * distributed under the License is distributed on an "AS IS" BASIS, 7941 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 7942 * See the License for the specific language governing permissions and 7943 * limitations under the License. 7944 * 7945 * @providesModule ReactEventEmitterMixin 7946 */ 7947 7948 "use strict"; 7949 7950 var EventPluginHub = require("./EventPluginHub"); 7951 var ReactUpdates = require("./ReactUpdates"); 7952 7953 function runEventQueueInBatch(events) { 7954 EventPluginHub.enqueueEvents(events); 7955 EventPluginHub.processEventQueue(); 7956 } 7957 7958 var ReactEventEmitterMixin = { 7959 /** 7960 * Whether or not `ensureListening` has been invoked. 7961 * @type {boolean} 7962 * @private 7963 */ 7964 _isListening: false, 7965 7966 /** 7967 * Function, must be implemented. Listens to events on the top level of the 7968 * application. 7969 * 7970 * @abstract 7971 * 7972 * listenAtTopLevel: null, 7973 */ 7974 7975 /** 7976 * Ensures that top-level event delegation listeners are installed. 7977 * 7978 * There are issues with listening to both touch events and mouse events on 7979 * the top-level, so we make the caller choose which one to listen to. (If 7980 * there's a touch top-level listeners, anchors don't receive clicks for some 7981 * reason, and only in some cases). 7982 * 7983 * @param {*} config Configuration passed through to `listenAtTopLevel`. 7984 */ 7985 ensureListening: function(config) { 7986 if (!config.contentDocument._reactIsListening) { 7987 this.listenAtTopLevel(config.touchNotMouse, config.contentDocument); 7988 config.contentDocument._reactIsListening = true; 7989 } 7990 }, 7991 7992 /** 7993 * Streams a fired top-level event to `EventPluginHub` where plugins have the 7994 * opportunity to create `ReactEvent`s to be dispatched. 7995 * 7996 * @param {string} topLevelType Record from `EventConstants`. 7997 * @param {object} topLevelTarget The listening component root node. 7998 * @param {string} topLevelTargetID ID of `topLevelTarget`. 7999 * @param {object} nativeEvent Native environment event. 8000 */ 8001 handleTopLevel: function( 8002 topLevelType, 8003 topLevelTarget, 8004 topLevelTargetID, 8005 nativeEvent) { 8006 var events = EventPluginHub.extractEvents( 8007 topLevelType, 8008 topLevelTarget, 8009 topLevelTargetID, 8010 nativeEvent 8011 ); 8012 8013 // Event queue being processed in the same cycle allows `preventDefault`. 8014 ReactUpdates.batchedUpdates(runEventQueueInBatch, events); 8015 } 8016 }; 8017 8018 module.exports = ReactEventEmitterMixin; 8019 8020 },{"./EventPluginHub":17,"./ReactUpdates":70}],49:[function(require,module,exports){ 8021 /** 8022 * Copyright 2013 Facebook, Inc. 8023 * 8024 * Licensed under the Apache License, Version 2.0 (the "License"); 8025 * you may not use this file except in compliance with the License. 8026 * You may obtain a copy of the License at 8027 * 8028 * http://www.apache.org/licenses/LICENSE-2.0 8029 * 8030 * Unless required by applicable law or agreed to in writing, software 8031 * distributed under the License is distributed on an "AS IS" BASIS, 8032 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8033 * See the License for the specific language governing permissions and 8034 * limitations under the License. 8035 * 8036 * @providesModule ReactEventTopLevelCallback 8037 * @typechecks static-only 8038 */ 8039 8040 "use strict"; 8041 8042 var ReactEventEmitter = require("./ReactEventEmitter"); 8043 var ReactMount = require("./ReactMount"); 8044 8045 var getEventTarget = require("./getEventTarget"); 8046 8047 /** 8048 * @type {boolean} 8049 * @private 8050 */ 8051 var _topLevelListenersEnabled = true; 8052 8053 /** 8054 * Top-level callback creator used to implement event handling using delegation. 8055 * This is used via dependency injection. 8056 */ 8057 var ReactEventTopLevelCallback = { 8058 8059 /** 8060 * Sets whether or not any created callbacks should be enabled. 8061 * 8062 * @param {boolean} enabled True if callbacks should be enabled. 8063 */ 8064 setEnabled: function(enabled) { 8065 _topLevelListenersEnabled = !!enabled; 8066 }, 8067 8068 /** 8069 * @return {boolean} True if callbacks are enabled. 8070 */ 8071 isEnabled: function() { 8072 return _topLevelListenersEnabled; 8073 }, 8074 8075 /** 8076 * Creates a callback for the supplied `topLevelType` that could be added as 8077 * a listener to the document. The callback computes a `topLevelTarget` which 8078 * should be the root node of a mounted React component where the listener 8079 * is attached. 8080 * 8081 * @param {string} topLevelType Record from `EventConstants`. 8082 * @return {function} Callback for handling top-level events. 8083 */ 8084 createTopLevelCallback: function(topLevelType) { 8085 return function(nativeEvent) { 8086 if (!_topLevelListenersEnabled) { 8087 return; 8088 } 8089 // TODO: Remove when synthetic events are ready, this is for IE<9. 8090 if (nativeEvent.srcElement && 8091 nativeEvent.srcElement !== nativeEvent.target) { 8092 nativeEvent.target = nativeEvent.srcElement; 8093 } 8094 var topLevelTarget = ReactMount.getFirstReactDOM( 8095 getEventTarget(nativeEvent) 8096 ) || window; 8097 var topLevelTargetID = ReactMount.getID(topLevelTarget) || ''; 8098 ReactEventEmitter.handleTopLevel( 8099 topLevelType, 8100 topLevelTarget, 8101 topLevelTargetID, 8102 nativeEvent 8103 ); 8104 }; 8105 } 8106 8107 }; 8108 8109 module.exports = ReactEventTopLevelCallback; 8110 8111 },{"./ReactEventEmitter":47,"./ReactMount":54,"./getEventTarget":102}],50:[function(require,module,exports){ 8112 /** 8113 * Copyright 2013 Facebook, Inc. 8114 * 8115 * Licensed under the Apache License, Version 2.0 (the "License"); 8116 * you may not use this file except in compliance with the License. 8117 * You may obtain a copy of the License at 8118 * 8119 * http://www.apache.org/licenses/LICENSE-2.0 8120 * 8121 * Unless required by applicable law or agreed to in writing, software 8122 * distributed under the License is distributed on an "AS IS" BASIS, 8123 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8124 * See the License for the specific language governing permissions and 8125 * limitations under the License. 8126 * 8127 * @providesModule ReactInputSelection 8128 */ 8129 8130 "use strict"; 8131 8132 var ReactDOMSelection = require("./ReactDOMSelection"); 8133 8134 var containsNode = require("./containsNode"); 8135 var getActiveElement = require("./getActiveElement"); 8136 8137 function isInDocument(node) { 8138 return containsNode(document.documentElement, node); 8139 } 8140 8141 /** 8142 * @ReactInputSelection: React input selection module. Based on Selection.js, 8143 * but modified to be suitable for react and has a couple of bug fixes (doesn't 8144 * assume buttons have range selections allowed). 8145 * Input selection module for React. 8146 */ 8147 var ReactInputSelection = { 8148 8149 hasSelectionCapabilities: function(elem) { 8150 return elem && ( 8151 (elem.nodeName === 'INPUT' && elem.type === 'text') || 8152 elem.nodeName === 'TEXTAREA' || 8153 elem.contentEditable === 'true' 8154 ); 8155 }, 8156 8157 getSelectionInformation: function() { 8158 var focusedElem = getActiveElement(); 8159 return { 8160 focusedElem: focusedElem, 8161 selectionRange: 8162 ReactInputSelection.hasSelectionCapabilities(focusedElem) ? 8163 ReactInputSelection.getSelection(focusedElem) : 8164 null 8165 }; 8166 }, 8167 8168 /** 8169 * @restoreSelection: If any selection information was potentially lost, 8170 * restore it. This is useful when performing operations that could remove dom 8171 * nodes and place them back in, resulting in focus being lost. 8172 */ 8173 restoreSelection: function(priorSelectionInformation) { 8174 var curFocusedElem = getActiveElement(); 8175 var priorFocusedElem = priorSelectionInformation.focusedElem; 8176 var priorSelectionRange = priorSelectionInformation.selectionRange; 8177 if (curFocusedElem !== priorFocusedElem && 8178 isInDocument(priorFocusedElem)) { 8179 if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) { 8180 ReactInputSelection.setSelection( 8181 priorFocusedElem, 8182 priorSelectionRange 8183 ); 8184 } 8185 priorFocusedElem.focus(); 8186 } 8187 }, 8188 8189 /** 8190 * @getSelection: Gets the selection bounds of a focused textarea, input or 8191 * contentEditable node. 8192 * -@input: Look up selection bounds of this input 8193 * -@return {start: selectionStart, end: selectionEnd} 8194 */ 8195 getSelection: function(input) { 8196 var selection; 8197 8198 if ('selectionStart' in input) { 8199 // Modern browser with input or textarea. 8200 selection = { 8201 start: input.selectionStart, 8202 end: input.selectionEnd 8203 }; 8204 } else if (document.selection && input.nodeName === 'INPUT') { 8205 // IE8 input. 8206 var range = document.selection.createRange(); 8207 // There can only be one selection per document in IE, so it must 8208 // be in our element. 8209 if (range.parentElement() === input) { 8210 selection = { 8211 start: -range.moveStart('character', -input.value.length), 8212 end: -range.moveEnd('character', -input.value.length) 8213 }; 8214 } 8215 } else { 8216 // Content editable or old IE textarea. 8217 selection = ReactDOMSelection.getOffsets(input); 8218 } 8219 8220 return selection || {start: 0, end: 0}; 8221 }, 8222 8223 /** 8224 * @setSelection: Sets the selection bounds of a textarea or input and focuses 8225 * the input. 8226 * -@input Set selection bounds of this input or textarea 8227 * -@offsets Object of same form that is returned from get* 8228 */ 8229 setSelection: function(input, offsets) { 8230 var start = offsets.start; 8231 var end = offsets.end; 8232 if (typeof end === 'undefined') { 8233 end = start; 8234 } 8235 8236 if ('selectionStart' in input) { 8237 input.selectionStart = start; 8238 input.selectionEnd = Math.min(end, input.value.length); 8239 } else if (document.selection && input.nodeName === 'INPUT') { 8240 var range = input.createTextRange(); 8241 range.collapse(true); 8242 range.moveStart('character', start); 8243 range.moveEnd('character', end - start); 8244 range.select(); 8245 } else { 8246 ReactDOMSelection.setOffsets(input, offsets); 8247 } 8248 } 8249 }; 8250 8251 module.exports = ReactInputSelection; 8252 8253 },{"./ReactDOMSelection":41,"./containsNode":87,"./getActiveElement":101}],51:[function(require,module,exports){ 8254 /** 8255 * Copyright 2013 Facebook, Inc. 8256 * 8257 * Licensed under the Apache License, Version 2.0 (the "License"); 8258 * you may not use this file except in compliance with the License. 8259 * You may obtain a copy of the License at 8260 * 8261 * http://www.apache.org/licenses/LICENSE-2.0 8262 * 8263 * Unless required by applicable law or agreed to in writing, software 8264 * distributed under the License is distributed on an "AS IS" BASIS, 8265 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8266 * See the License for the specific language governing permissions and 8267 * limitations under the License. 8268 * 8269 * @providesModule ReactInstanceHandles 8270 * @typechecks static-only 8271 */ 8272 8273 "use strict"; 8274 8275 var invariant = require("./invariant"); 8276 8277 var SEPARATOR = '.'; 8278 var SEPARATOR_LENGTH = SEPARATOR.length; 8279 8280 /** 8281 * Maximum depth of traversals before we consider the possibility of a bad ID. 8282 */ 8283 var MAX_TREE_DEPTH = 100; 8284 8285 /** 8286 * Size of the reactRoot ID space. We generate random numbers for React root 8287 * IDs and if there's a collision the events and DOM update system will 8288 * get confused. If we assume 100 React components per page, and a user 8289 * loads 1 page per minute 24/7 for 50 years, with a mount point space of 8290 * 9,999,999 the likelihood of never having a collision is 99.997%. 8291 */ 8292 var GLOBAL_MOUNT_POINT_MAX = 9999999; 8293 8294 /** 8295 * Creates a DOM ID prefix to use when mounting React components. 8296 * 8297 * @param {number} index A unique integer 8298 * @return {string} React root ID. 8299 * @internal 8300 */ 8301 function getReactRootIDString(index) { 8302 return SEPARATOR + 'r[' + index.toString(36) + ']'; 8303 } 8304 8305 /** 8306 * Checks if a character in the supplied ID is a separator or the end. 8307 * 8308 * @param {string} id A React DOM ID. 8309 * @param {number} index Index of the character to check. 8310 * @return {boolean} True if the character is a separator or end of the ID. 8311 * @private 8312 */ 8313 function isBoundary(id, index) { 8314 return id.charAt(index) === SEPARATOR || index === id.length; 8315 } 8316 8317 /** 8318 * Checks if the supplied string is a valid React DOM ID. 8319 * 8320 * @param {string} id A React DOM ID, maybe. 8321 * @return {boolean} True if the string is a valid React DOM ID. 8322 * @private 8323 */ 8324 function isValidID(id) { 8325 return id === '' || ( 8326 id.charAt(0) === SEPARATOR && id.charAt(id.length - 1) !== SEPARATOR 8327 ); 8328 } 8329 8330 /** 8331 * Checks if the first ID is an ancestor of or equal to the second ID. 8332 * 8333 * @param {string} ancestorID 8334 * @param {string} descendantID 8335 * @return {boolean} True if `ancestorID` is an ancestor of `descendantID`. 8336 * @internal 8337 */ 8338 function isAncestorIDOf(ancestorID, descendantID) { 8339 return ( 8340 descendantID.indexOf(ancestorID) === 0 && 8341 isBoundary(descendantID, ancestorID.length) 8342 ); 8343 } 8344 8345 /** 8346 * Gets the parent ID of the supplied React DOM ID, `id`. 8347 * 8348 * @param {string} id ID of a component. 8349 * @return {string} ID of the parent, or an empty string. 8350 * @private 8351 */ 8352 function getParentID(id) { 8353 return id ? id.substr(0, id.lastIndexOf(SEPARATOR)) : ''; 8354 } 8355 8356 /** 8357 * Gets the next DOM ID on the tree path from the supplied `ancestorID` to the 8358 * supplied `destinationID`. If they are equal, the ID is returned. 8359 * 8360 * @param {string} ancestorID ID of an ancestor node of `destinationID`. 8361 * @param {string} destinationID ID of the destination node. 8362 * @return {string} Next ID on the path from `ancestorID` to `destinationID`. 8363 * @private 8364 */ 8365 function getNextDescendantID(ancestorID, destinationID) { 8366 ("production" !== "development" ? invariant( 8367 isValidID(ancestorID) && isValidID(destinationID), 8368 'getNextDescendantID(%s, %s): Received an invalid React DOM ID.', 8369 ancestorID, 8370 destinationID 8371 ) : invariant(isValidID(ancestorID) && isValidID(destinationID))); 8372 ("production" !== "development" ? invariant( 8373 isAncestorIDOf(ancestorID, destinationID), 8374 'getNextDescendantID(...): React has made an invalid assumption about ' + 8375 'the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.', 8376 ancestorID, 8377 destinationID 8378 ) : invariant(isAncestorIDOf(ancestorID, destinationID))); 8379 if (ancestorID === destinationID) { 8380 return ancestorID; 8381 } 8382 // Skip over the ancestor and the immediate separator. Traverse until we hit 8383 // another separator or we reach the end of `destinationID`. 8384 var start = ancestorID.length + SEPARATOR_LENGTH; 8385 for (var i = start; i < destinationID.length; i++) { 8386 if (isBoundary(destinationID, i)) { 8387 break; 8388 } 8389 } 8390 return destinationID.substr(0, i); 8391 } 8392 8393 /** 8394 * Gets the nearest common ancestor ID of two IDs. 8395 * 8396 * Using this ID scheme, the nearest common ancestor ID is the longest common 8397 * prefix of the two IDs that immediately preceded a "marker" in both strings. 8398 * 8399 * @param {string} oneID 8400 * @param {string} twoID 8401 * @return {string} Nearest common ancestor ID, or the empty string if none. 8402 * @private 8403 */ 8404 function getFirstCommonAncestorID(oneID, twoID) { 8405 var minLength = Math.min(oneID.length, twoID.length); 8406 if (minLength === 0) { 8407 return ''; 8408 } 8409 var lastCommonMarkerIndex = 0; 8410 // Use `<=` to traverse until the "EOL" of the shorter string. 8411 for (var i = 0; i <= minLength; i++) { 8412 if (isBoundary(oneID, i) && isBoundary(twoID, i)) { 8413 lastCommonMarkerIndex = i; 8414 } else if (oneID.charAt(i) !== twoID.charAt(i)) { 8415 break; 8416 } 8417 } 8418 var longestCommonID = oneID.substr(0, lastCommonMarkerIndex); 8419 ("production" !== "development" ? invariant( 8420 isValidID(longestCommonID), 8421 'getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s', 8422 oneID, 8423 twoID, 8424 longestCommonID 8425 ) : invariant(isValidID(longestCommonID))); 8426 return longestCommonID; 8427 } 8428 8429 /** 8430 * Traverses the parent path between two IDs (either up or down). The IDs must 8431 * not be the same, and there must exist a parent path between them. 8432 * 8433 * @param {?string} start ID at which to start traversal. 8434 * @param {?string} stop ID at which to end traversal. 8435 * @param {function} cb Callback to invoke each ID with. 8436 * @param {?boolean} skipFirst Whether or not to skip the first node. 8437 * @param {?boolean} skipLast Whether or not to skip the last node. 8438 * @private 8439 */ 8440 function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) { 8441 start = start || ''; 8442 stop = stop || ''; 8443 ("production" !== "development" ? invariant( 8444 start !== stop, 8445 'traverseParentPath(...): Cannot traverse from and to the same ID, `%s`.', 8446 start 8447 ) : invariant(start !== stop)); 8448 var traverseUp = isAncestorIDOf(stop, start); 8449 ("production" !== "development" ? invariant( 8450 traverseUp || isAncestorIDOf(start, stop), 8451 'traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do ' + 8452 'not have a parent path.', 8453 start, 8454 stop 8455 ) : invariant(traverseUp || isAncestorIDOf(start, stop))); 8456 // Traverse from `start` to `stop` one depth at a time. 8457 var depth = 0; 8458 var traverse = traverseUp ? getParentID : getNextDescendantID; 8459 for (var id = start; /* until break */; id = traverse(id, stop)) { 8460 if ((!skipFirst || id !== start) && (!skipLast || id !== stop)) { 8461 cb(id, traverseUp, arg); 8462 } 8463 if (id === stop) { 8464 // Only break //after// visiting `stop`. 8465 break; 8466 } 8467 ("production" !== "development" ? invariant( 8468 depth++ < MAX_TREE_DEPTH, 8469 'traverseParentPath(%s, %s, ...): Detected an infinite loop while ' + 8470 'traversing the React DOM ID tree. This may be due to malformed IDs: %s', 8471 start, stop 8472 ) : invariant(depth++ < MAX_TREE_DEPTH)); 8473 } 8474 } 8475 8476 /** 8477 * Manages the IDs assigned to DOM representations of React components. This 8478 * uses a specific scheme in order to traverse the DOM efficiently (e.g. in 8479 * order to simulate events). 8480 * 8481 * @internal 8482 */ 8483 var ReactInstanceHandles = { 8484 8485 createReactRootID: function() { 8486 return getReactRootIDString( 8487 Math.ceil(Math.random() * GLOBAL_MOUNT_POINT_MAX) 8488 ); 8489 }, 8490 8491 /** 8492 * Constructs a React ID by joining a root ID with a name. 8493 * 8494 * @param {string} rootID Root ID of a parent component. 8495 * @param {string} name A component's name (as flattened children). 8496 * @return {string} A React ID. 8497 * @internal 8498 */ 8499 createReactID: function(rootID, name) { 8500 return rootID + SEPARATOR + name; 8501 }, 8502 8503 /** 8504 * Gets the DOM ID of the React component that is the root of the tree that 8505 * contains the React component with the supplied DOM ID. 8506 * 8507 * @param {string} id DOM ID of a React component. 8508 * @return {?string} DOM ID of the React component that is the root. 8509 * @internal 8510 */ 8511 getReactRootIDFromNodeID: function(id) { 8512 var regexResult = /\.r\[[^\]]+\]/.exec(id); 8513 return regexResult && regexResult[0]; 8514 }, 8515 8516 /** 8517 * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that 8518 * should would receive a `mouseEnter` or `mouseLeave` event. 8519 * 8520 * NOTE: Does not invoke the callback on the nearest common ancestor because 8521 * nothing "entered" or "left" that element. 8522 * 8523 * @param {string} leaveID ID being left. 8524 * @param {string} enterID ID being entered. 8525 * @param {function} cb Callback to invoke on each entered/left ID. 8526 * @param {*} upArg Argument to invoke the callback with on left IDs. 8527 * @param {*} downArg Argument to invoke the callback with on entered IDs. 8528 * @internal 8529 */ 8530 traverseEnterLeave: function(leaveID, enterID, cb, upArg, downArg) { 8531 var ancestorID = getFirstCommonAncestorID(leaveID, enterID); 8532 if (ancestorID !== leaveID) { 8533 traverseParentPath(leaveID, ancestorID, cb, upArg, false, true); 8534 } 8535 if (ancestorID !== enterID) { 8536 traverseParentPath(ancestorID, enterID, cb, downArg, true, false); 8537 } 8538 }, 8539 8540 /** 8541 * Simulates the traversal of a two-phase, capture/bubble event dispatch. 8542 * 8543 * NOTE: This traversal happens on IDs without touching the DOM. 8544 * 8545 * @param {string} targetID ID of the target node. 8546 * @param {function} cb Callback to invoke. 8547 * @param {*} arg Argument to invoke the callback with. 8548 * @internal 8549 */ 8550 traverseTwoPhase: function(targetID, cb, arg) { 8551 if (targetID) { 8552 traverseParentPath('', targetID, cb, arg, true, false); 8553 traverseParentPath(targetID, '', cb, arg, false, true); 8554 } 8555 }, 8556 8557 /** 8558 * Exposed for unit testing. 8559 * @private 8560 */ 8561 _getFirstCommonAncestorID: getFirstCommonAncestorID, 8562 8563 /** 8564 * Exposed for unit testing. 8565 * @private 8566 */ 8567 _getNextDescendantID: getNextDescendantID, 8568 8569 isAncestorIDOf: isAncestorIDOf, 8570 8571 SEPARATOR: SEPARATOR 8572 8573 }; 8574 8575 module.exports = ReactInstanceHandles; 8576 8577 },{"./invariant":109}],52:[function(require,module,exports){ 8578 /** 8579 * Copyright 2013 Facebook, Inc. 8580 * 8581 * Licensed under the Apache License, Version 2.0 (the "License"); 8582 * you may not use this file except in compliance with the License. 8583 * You may obtain a copy of the License at 8584 * 8585 * http://www.apache.org/licenses/LICENSE-2.0 8586 * 8587 * Unless required by applicable law or agreed to in writing, software 8588 * distributed under the License is distributed on an "AS IS" BASIS, 8589 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8590 * See the License for the specific language governing permissions and 8591 * limitations under the License. 8592 * 8593 * @providesModule ReactLink 8594 * @typechecks static-only 8595 */ 8596 8597 "use strict"; 8598 8599 /** 8600 * ReactLink encapsulates a common pattern in which a component wants to modify 8601 * a prop received from its parent. ReactLink allows the parent to pass down a 8602 * value coupled with a callback that, when invoked, expresses an intent to 8603 * modify that value. For example: 8604 * 8605 * React.createClass({ 8606 * getInitialState: function() { 8607 * return {value: ''}; 8608 * }, 8609 * render: function() { 8610 * var valueLink = new ReactLink(this.state.value, this._handleValueChange); 8611 * return <input valueLink={valueLink} />; 8612 * }, 8613 * this._handleValueChange: function(newValue) { 8614 * this.setState({value: newValue}); 8615 * } 8616 * }); 8617 * 8618 * We have provided some sugary mixins to make the creation and 8619 * consumption of ReactLink easier; see LinkedValueMixin and LinkedStateMixin. 8620 */ 8621 8622 /** 8623 * @param {*} value current value of the link 8624 * @param {function} requestChange callback to request a change 8625 */ 8626 function ReactLink(value, requestChange) { 8627 this.value = value; 8628 this.requestChange = requestChange; 8629 } 8630 8631 module.exports = ReactLink; 8632 8633 },{}],53:[function(require,module,exports){ 8634 /** 8635 * Copyright 2013 Facebook, Inc. 8636 * 8637 * Licensed under the Apache License, Version 2.0 (the "License"); 8638 * you may not use this file except in compliance with the License. 8639 * You may obtain a copy of the License at 8640 * 8641 * http://www.apache.org/licenses/LICENSE-2.0 8642 * 8643 * Unless required by applicable law or agreed to in writing, software 8644 * distributed under the License is distributed on an "AS IS" BASIS, 8645 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8646 * See the License for the specific language governing permissions and 8647 * limitations under the License. 8648 * 8649 * @providesModule ReactMarkupChecksum 8650 */ 8651 8652 "use strict"; 8653 8654 var adler32 = require("./adler32"); 8655 8656 var ReactMarkupChecksum = { 8657 CHECKSUM_ATTR_NAME: 'data-react-checksum', 8658 8659 /** 8660 * @param {string} markup Markup string 8661 * @return {string} Markup string with checksum attribute attached 8662 */ 8663 addChecksumToMarkup: function(markup) { 8664 var checksum = adler32(markup); 8665 return markup.replace( 8666 '>', 8667 ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '">' 8668 ); 8669 }, 8670 8671 /** 8672 * @param {string} markup to use 8673 * @param {DOMElement} element root React element 8674 * @returns {boolean} whether or not the markup is the same 8675 */ 8676 canReuseMarkup: function(markup, element) { 8677 var existingChecksum = element.getAttribute( 8678 ReactMarkupChecksum.CHECKSUM_ATTR_NAME 8679 ); 8680 existingChecksum = existingChecksum && parseInt(existingChecksum, 10); 8681 var markupChecksum = adler32(markup); 8682 return markupChecksum === existingChecksum; 8683 } 8684 }; 8685 8686 module.exports = ReactMarkupChecksum; 8687 8688 },{"./adler32":86}],54:[function(require,module,exports){ 8689 /** 8690 * Copyright 2013 Facebook, Inc. 8691 * 8692 * Licensed under the Apache License, Version 2.0 (the "License"); 8693 * you may not use this file except in compliance with the License. 8694 * You may obtain a copy of the License at 8695 * 8696 * http://www.apache.org/licenses/LICENSE-2.0 8697 * 8698 * Unless required by applicable law or agreed to in writing, software 8699 * distributed under the License is distributed on an "AS IS" BASIS, 8700 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8701 * See the License for the specific language governing permissions and 8702 * limitations under the License. 8703 * 8704 * @providesModule ReactMount 8705 */ 8706 8707 "use strict"; 8708 8709 var ReactEventEmitter = require("./ReactEventEmitter"); 8710 var ReactInstanceHandles = require("./ReactInstanceHandles"); 8711 8712 var $ = require("./$"); 8713 var containsNode = require("./containsNode"); 8714 var getReactRootElementInContainer = require("./getReactRootElementInContainer"); 8715 var invariant = require("./invariant"); 8716 8717 var SEPARATOR = ReactInstanceHandles.SEPARATOR; 8718 8719 var ATTR_NAME = 'data-reactid'; 8720 var nodeCache = {}; 8721 8722 var ELEMENT_NODE_TYPE = 1; 8723 var DOC_NODE_TYPE = 9; 8724 8725 /** Mapping from reactRootID to React component instance. */ 8726 var instancesByReactRootID = {}; 8727 8728 /** Mapping from reactRootID to `container` nodes. */ 8729 var containersByReactRootID = {}; 8730 8731 if ("production" !== "development") { 8732 /** __DEV__-only mapping from reactRootID to root elements. */ 8733 var rootElementsByReactRootID = {}; 8734 } 8735 8736 /** 8737 * @param {DOMElement} container DOM element that may contain a React component. 8738 * @return {?string} A "reactRoot" ID, if a React component is rendered. 8739 */ 8740 function getReactRootID(container) { 8741 var rootElement = getReactRootElementInContainer(container); 8742 return rootElement && ReactMount.getID(rootElement); 8743 } 8744 8745 /** 8746 * Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form 8747 * element can return its control whose name or ID equals ATTR_NAME. All 8748 * DOM nodes support `getAttributeNode` but this can also get called on 8749 * other objects so just return '' if we're given something other than a 8750 * DOM node (such as window). 8751 * 8752 * @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node. 8753 * @return {string} ID of the supplied `domNode`. 8754 */ 8755 function getID(node) { 8756 var id = internalGetID(node); 8757 if (id) { 8758 if (nodeCache.hasOwnProperty(id)) { 8759 var cached = nodeCache[id]; 8760 if (cached !== node) { 8761 ("production" !== "development" ? invariant( 8762 !isValid(cached, id), 8763 'ReactMount: Two valid but unequal nodes with the same `%s`: %s', 8764 ATTR_NAME, id 8765 ) : invariant(!isValid(cached, id))); 8766 8767 nodeCache[id] = node; 8768 } 8769 } else { 8770 nodeCache[id] = node; 8771 } 8772 } 8773 8774 return id; 8775 } 8776 8777 function internalGetID(node) { 8778 // If node is something like a window, document, or text node, none of 8779 // which support attributes or a .getAttribute method, gracefully return 8780 // the empty string, as if the attribute were missing. 8781 return node && node.getAttribute && node.getAttribute(ATTR_NAME) || ''; 8782 } 8783 8784 /** 8785 * Sets the React-specific ID of the given node. 8786 * 8787 * @param {DOMElement} node The DOM node whose ID will be set. 8788 * @param {string} id The value of the ID attribute. 8789 */ 8790 function setID(node, id) { 8791 var oldID = internalGetID(node); 8792 if (oldID !== id) { 8793 delete nodeCache[oldID]; 8794 } 8795 node.setAttribute(ATTR_NAME, id); 8796 nodeCache[id] = node; 8797 } 8798 8799 /** 8800 * Finds the node with the supplied React-generated DOM ID. 8801 * 8802 * @param {string} id A React-generated DOM ID. 8803 * @return {DOMElement} DOM node with the suppled `id`. 8804 * @internal 8805 */ 8806 function getNode(id) { 8807 if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) { 8808 nodeCache[id] = ReactMount.findReactNodeByID(id); 8809 } 8810 return nodeCache[id]; 8811 } 8812 8813 /** 8814 * A node is "valid" if it is contained by a currently mounted container. 8815 * 8816 * This means that the node does not have to be contained by a document in 8817 * order to be considered valid. 8818 * 8819 * @param {?DOMElement} node The candidate DOM node. 8820 * @param {string} id The expected ID of the node. 8821 * @return {boolean} Whether the node is contained by a mounted container. 8822 */ 8823 function isValid(node, id) { 8824 if (node) { 8825 ("production" !== "development" ? invariant( 8826 internalGetID(node) === id, 8827 'ReactMount: Unexpected modification of `%s`', 8828 ATTR_NAME 8829 ) : invariant(internalGetID(node) === id)); 8830 8831 var container = ReactMount.findReactContainerForID(id); 8832 if (container && containsNode(container, node)) { 8833 return true; 8834 } 8835 } 8836 8837 return false; 8838 } 8839 8840 /** 8841 * Causes the cache to forget about one React-specific ID. 8842 * 8843 * @param {string} id The ID to forget. 8844 */ 8845 function purgeID(id) { 8846 delete nodeCache[id]; 8847 } 8848 8849 /** 8850 * Mounting is the process of initializing a React component by creatings its 8851 * representative DOM elements and inserting them into a supplied `container`. 8852 * Any prior content inside `container` is destroyed in the process. 8853 * 8854 * ReactMount.renderComponent(component, $('container')); 8855 * 8856 * <div id="container"> <-- Supplied `container`. 8857 * <div data-reactid=".r[3]"> <-- Rendered reactRoot of React 8858 * // ... component. 8859 * </div> 8860 * </div> 8861 * 8862 * Inside of `container`, the first element rendered is the "reactRoot". 8863 */ 8864 var ReactMount = { 8865 /** 8866 * Safety guard to prevent accidentally rendering over the entire HTML tree. 8867 */ 8868 allowFullPageRender: false, 8869 8870 /** Time spent generating markup. */ 8871 totalInstantiationTime: 0, 8872 8873 /** Time spent inserting markup into the DOM. */ 8874 totalInjectionTime: 0, 8875 8876 /** Whether support for touch events should be initialized. */ 8877 useTouchEvents: false, 8878 8879 /** Exposed for debugging purposes **/ 8880 _instancesByReactRootID: instancesByReactRootID, 8881 8882 /** 8883 * This is a hook provided to support rendering React components while 8884 * ensuring that the apparent scroll position of its `container` does not 8885 * change. 8886 * 8887 * @param {DOMElement} container The `container` being rendered into. 8888 * @param {function} renderCallback This must be called once to do the render. 8889 */ 8890 scrollMonitor: function(container, renderCallback) { 8891 renderCallback(); 8892 }, 8893 8894 /** 8895 * Ensures that the top-level event delegation listener is set up. This will 8896 * be invoked some time before the first time any React component is rendered. 8897 * @param {DOMElement} container container we're rendering into 8898 * 8899 * @private 8900 */ 8901 prepareEnvironmentForDOM: function(container) { 8902 ("production" !== "development" ? invariant( 8903 container && ( 8904 container.nodeType === ELEMENT_NODE_TYPE || 8905 container.nodeType === DOC_NODE_TYPE 8906 ), 8907 'prepareEnvironmentForDOM(...): Target container is not a DOM element.' 8908 ) : invariant(container && ( 8909 container.nodeType === ELEMENT_NODE_TYPE || 8910 container.nodeType === DOC_NODE_TYPE 8911 ))); 8912 var doc = container.nodeType === ELEMENT_NODE_TYPE ? 8913 container.ownerDocument : 8914 container; 8915 ReactEventEmitter.ensureListening(ReactMount.useTouchEvents, doc); 8916 }, 8917 8918 /** 8919 * Take a component that's already mounted into the DOM and replace its props 8920 * @param {ReactComponent} prevComponent component instance already in the DOM 8921 * @param {ReactComponent} nextComponent component instance to render 8922 * @param {DOMElement} container container to render into 8923 * @param {?function} callback function triggered on completion 8924 */ 8925 _updateRootComponent: function( 8926 prevComponent, 8927 nextComponent, 8928 container, 8929 callback) { 8930 var nextProps = nextComponent.props; 8931 ReactMount.scrollMonitor(container, function() { 8932 prevComponent.replaceProps(nextProps, callback); 8933 }); 8934 8935 if ("production" !== "development") { 8936 // Record the root element in case it later gets transplanted. 8937 rootElementsByReactRootID[getReactRootID(container)] = 8938 getReactRootElementInContainer(container); 8939 } 8940 8941 return prevComponent; 8942 }, 8943 8944 /** 8945 * Register a component into the instance map and start the events system. 8946 * @param {ReactComponent} nextComponent component instance to render 8947 * @param {DOMElement} container container to render into 8948 * @return {string} reactRoot ID prefix 8949 */ 8950 _registerComponent: function(nextComponent, container) { 8951 ReactMount.prepareEnvironmentForDOM(container); 8952 8953 var reactRootID = ReactMount.registerContainer(container); 8954 instancesByReactRootID[reactRootID] = nextComponent; 8955 return reactRootID; 8956 }, 8957 8958 /** 8959 * Render a new component into the DOM. 8960 * @param {ReactComponent} nextComponent component instance to render 8961 * @param {DOMElement} container container to render into 8962 * @param {boolean} shouldReuseMarkup if we should skip the markup insertion 8963 * @return {ReactComponent} nextComponent 8964 */ 8965 _renderNewRootComponent: function( 8966 nextComponent, 8967 container, 8968 shouldReuseMarkup) { 8969 var reactRootID = ReactMount._registerComponent(nextComponent, container); 8970 nextComponent.mountComponentIntoNode( 8971 reactRootID, 8972 container, 8973 shouldReuseMarkup 8974 ); 8975 8976 if ("production" !== "development") { 8977 // Record the root element in case it later gets transplanted. 8978 rootElementsByReactRootID[reactRootID] = 8979 getReactRootElementInContainer(container); 8980 } 8981 8982 return nextComponent; 8983 }, 8984 8985 /** 8986 * Renders a React component into the DOM in the supplied `container`. 8987 * 8988 * If the React component was previously rendered into `container`, this will 8989 * perform an update on it and only mutate the DOM as necessary to reflect the 8990 * latest React component. 8991 * 8992 * @param {ReactComponent} nextComponent Component instance to render. 8993 * @param {DOMElement} container DOM element to render into. 8994 * @param {?function} callback function triggered on completion 8995 * @return {ReactComponent} Component instance rendered in `container`. 8996 */ 8997 renderComponent: function(nextComponent, container, callback) { 8998 var registeredComponent = instancesByReactRootID[getReactRootID(container)]; 8999 9000 if (registeredComponent) { 9001 if (registeredComponent.constructor === nextComponent.constructor) { 9002 return ReactMount._updateRootComponent( 9003 registeredComponent, 9004 nextComponent, 9005 container, 9006 callback 9007 ); 9008 } else { 9009 ReactMount.unmountComponentAtNode(container); 9010 } 9011 } 9012 9013 var reactRootElement = getReactRootElementInContainer(container); 9014 var containerHasReactMarkup = 9015 reactRootElement && ReactMount.isRenderedByReact(reactRootElement); 9016 9017 var shouldReuseMarkup = containerHasReactMarkup && !registeredComponent; 9018 9019 var component = ReactMount._renderNewRootComponent( 9020 nextComponent, 9021 container, 9022 shouldReuseMarkup 9023 ); 9024 callback && callback(); 9025 return component; 9026 }, 9027 9028 /** 9029 * Constructs a component instance of `constructor` with `initialProps` and 9030 * renders it into the supplied `container`. 9031 * 9032 * @param {function} constructor React component constructor. 9033 * @param {?object} props Initial props of the component instance. 9034 * @param {DOMElement} container DOM element to render into. 9035 * @return {ReactComponent} Component instance rendered in `container`. 9036 */ 9037 constructAndRenderComponent: function(constructor, props, container) { 9038 return ReactMount.renderComponent(constructor(props), container); 9039 }, 9040 9041 /** 9042 * Constructs a component instance of `constructor` with `initialProps` and 9043 * renders it into a container node identified by supplied `id`. 9044 * 9045 * @param {function} componentConstructor React component constructor 9046 * @param {?object} props Initial props of the component instance. 9047 * @param {string} id ID of the DOM element to render into. 9048 * @return {ReactComponent} Component instance rendered in the container node. 9049 */ 9050 constructAndRenderComponentByID: function(constructor, props, id) { 9051 return ReactMount.constructAndRenderComponent(constructor, props, $(id)); 9052 }, 9053 9054 /** 9055 * Registers a container node into which React components will be rendered. 9056 * This also creates the "reatRoot" ID that will be assigned to the element 9057 * rendered within. 9058 * 9059 * @param {DOMElement} container DOM element to register as a container. 9060 * @return {string} The "reactRoot" ID of elements rendered within. 9061 */ 9062 registerContainer: function(container) { 9063 var reactRootID = getReactRootID(container); 9064 if (reactRootID) { 9065 // If one exists, make sure it is a valid "reactRoot" ID. 9066 reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID); 9067 } 9068 if (!reactRootID) { 9069 // No valid "reactRoot" ID found, create one. 9070 reactRootID = ReactInstanceHandles.createReactRootID(); 9071 } 9072 containersByReactRootID[reactRootID] = container; 9073 return reactRootID; 9074 }, 9075 9076 /** 9077 * Unmounts and destroys the React component rendered in the `container`. 9078 * 9079 * @param {DOMElement} container DOM element containing a React component. 9080 * @return {boolean} True if a component was found in and unmounted from 9081 * `container` 9082 */ 9083 unmountComponentAtNode: function(container) { 9084 var reactRootID = getReactRootID(container); 9085 var component = instancesByReactRootID[reactRootID]; 9086 if (!component) { 9087 return false; 9088 } 9089 ReactMount.unmountComponentFromNode(component, container); 9090 delete instancesByReactRootID[reactRootID]; 9091 delete containersByReactRootID[reactRootID]; 9092 if ("production" !== "development") { 9093 delete rootElementsByReactRootID[reactRootID]; 9094 } 9095 return true; 9096 }, 9097 9098 /** 9099 * @deprecated 9100 */ 9101 unmountAndReleaseReactRootNode: function() { 9102 if ("production" !== "development") { 9103 console.warn( 9104 'unmountAndReleaseReactRootNode() has been renamed to ' + 9105 'unmountComponentAtNode() and will be removed in the next ' + 9106 'version of React.' 9107 ); 9108 } 9109 return ReactMount.unmountComponentAtNode.apply(this, arguments); 9110 }, 9111 9112 /** 9113 * Unmounts a component and removes it from the DOM. 9114 * 9115 * @param {ReactComponent} instance React component instance. 9116 * @param {DOMElement} container DOM element to unmount from. 9117 * @final 9118 * @internal 9119 * @see {ReactMount.unmountComponentAtNode} 9120 */ 9121 unmountComponentFromNode: function(instance, container) { 9122 instance.unmountComponent(); 9123 9124 if (container.nodeType === DOC_NODE_TYPE) { 9125 container = container.documentElement; 9126 } 9127 9128 // http://jsperf.com/emptying-a-node 9129 while (container.lastChild) { 9130 container.removeChild(container.lastChild); 9131 } 9132 }, 9133 9134 /** 9135 * Finds the container DOM element that contains React component to which the 9136 * supplied DOM `id` belongs. 9137 * 9138 * @param {string} id The ID of an element rendered by a React component. 9139 * @return {?DOMElement} DOM element that contains the `id`. 9140 */ 9141 findReactContainerForID: function(id) { 9142 var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(id); 9143 var container = containersByReactRootID[reactRootID]; 9144 9145 if ("production" !== "development") { 9146 var rootElement = rootElementsByReactRootID[reactRootID]; 9147 if (rootElement && rootElement.parentNode !== container) { 9148 ("production" !== "development" ? invariant( 9149 // Call internalGetID here because getID calls isValid which calls 9150 // findReactContainerForID (this function). 9151 internalGetID(rootElement) === reactRootID, 9152 'ReactMount: Root element ID differed from reactRootID.' 9153 ) : invariant(// Call internalGetID here because getID calls isValid which calls 9154 // findReactContainerForID (this function). 9155 internalGetID(rootElement) === reactRootID)); 9156 9157 var containerChild = container.firstChild; 9158 if (containerChild && 9159 reactRootID === internalGetID(containerChild)) { 9160 // If the container has a new child with the same ID as the old 9161 // root element, then rootElementsByReactRootID[reactRootID] is 9162 // just stale and needs to be updated. The case that deserves a 9163 // warning is when the container is empty. 9164 rootElementsByReactRootID[reactRootID] = containerChild; 9165 } else { 9166 console.warn( 9167 'ReactMount: Root element has been removed from its original ' + 9168 'container. New container:', rootElement.parentNode 9169 ); 9170 } 9171 } 9172 } 9173 9174 return container; 9175 }, 9176 9177 /** 9178 * Finds an element rendered by React with the supplied ID. 9179 * 9180 * @param {string} id ID of a DOM node in the React component. 9181 * @return {DOMElement} Root DOM node of the React component. 9182 */ 9183 findReactNodeByID: function(id) { 9184 var reactRoot = ReactMount.findReactContainerForID(id); 9185 return ReactMount.findComponentRoot(reactRoot, id); 9186 }, 9187 9188 /** 9189 * True if the supplied `node` is rendered by React. 9190 * 9191 * @param {*} node DOM Element to check. 9192 * @return {boolean} True if the DOM Element appears to be rendered by React. 9193 * @internal 9194 */ 9195 isRenderedByReact: function(node) { 9196 if (node.nodeType !== 1) { 9197 // Not a DOMElement, therefore not a React component 9198 return false; 9199 } 9200 var id = ReactMount.getID(node); 9201 return id ? id.charAt(0) === SEPARATOR : false; 9202 }, 9203 9204 /** 9205 * Traverses up the ancestors of the supplied node to find a node that is a 9206 * DOM representation of a React component. 9207 * 9208 * @param {*} node 9209 * @return {?DOMEventTarget} 9210 * @internal 9211 */ 9212 getFirstReactDOM: function(node) { 9213 var current = node; 9214 while (current && current.parentNode !== current) { 9215 if (ReactMount.isRenderedByReact(current)) { 9216 return current; 9217 } 9218 current = current.parentNode; 9219 } 9220 return null; 9221 }, 9222 9223 /** 9224 * Finds a node with the supplied `id` inside of the supplied `ancestorNode`. 9225 * Exploits the ID naming scheme to perform the search quickly. 9226 * 9227 * @param {DOMEventTarget} ancestorNode Search from this root. 9228 * @pararm {string} id ID of the DOM representation of the component. 9229 * @return {DOMEventTarget} DOM node with the supplied `id`. 9230 * @internal 9231 */ 9232 findComponentRoot: function(ancestorNode, id) { 9233 var firstChildren = [ancestorNode.firstChild]; 9234 var childIndex = 0; 9235 9236 while (childIndex < firstChildren.length) { 9237 var child = firstChildren[childIndex++]; 9238 while (child) { 9239 var childID = ReactMount.getID(child); 9240 if (childID) { 9241 if (id === childID) { 9242 return child; 9243 } else if (ReactInstanceHandles.isAncestorIDOf(childID, id)) { 9244 // If we find a child whose ID is an ancestor of the given ID, 9245 // then we can be sure that we only want to search the subtree 9246 // rooted at this child, so we can throw out the rest of the 9247 // search state. 9248 firstChildren.length = childIndex = 0; 9249 firstChildren.push(child.firstChild); 9250 break; 9251 } else { 9252 // TODO This should not be necessary if the ID hierarchy is 9253 // correct, but is occasionally necessary if the DOM has been 9254 // modified in unexpected ways. 9255 firstChildren.push(child.firstChild); 9256 } 9257 } else { 9258 // If this child had no ID, then there's a chance that it was 9259 // injected automatically by the browser, as when a `<table>` 9260 // element sprouts an extra `<tbody>` child as a side effect of 9261 // `.innerHTML` parsing. Optimistically continue down this 9262 // branch, but not before examining the other siblings. 9263 firstChildren.push(child.firstChild); 9264 } 9265 child = child.nextSibling; 9266 } 9267 } 9268 9269 if ("production" !== "development") { 9270 console.error( 9271 'Error while invoking `findComponentRoot` with the following ' + 9272 'ancestor node:', 9273 ancestorNode 9274 ); 9275 } 9276 ("production" !== "development" ? invariant( 9277 false, 9278 'findComponentRoot(..., %s): Unable to find element. This probably ' + 9279 'means the DOM was unexpectedly mutated (e.g. by the browser).', 9280 id, 9281 ReactMount.getID(ancestorNode) 9282 ) : invariant(false)); 9283 }, 9284 9285 9286 /** 9287 * React ID utilities. 9288 */ 9289 9290 ATTR_NAME: ATTR_NAME, 9291 9292 getReactRootID: getReactRootID, 9293 9294 getID: getID, 9295 9296 setID: setID, 9297 9298 getNode: getNode, 9299 9300 purgeID: purgeID, 9301 9302 injection: {} 9303 }; 9304 9305 module.exports = ReactMount; 9306 9307 },{"./$":1,"./ReactEventEmitter":47,"./ReactInstanceHandles":51,"./containsNode":87,"./getReactRootElementInContainer":105,"./invariant":109}],55:[function(require,module,exports){ 9308 /** 9309 * Copyright 2013 Facebook, Inc. 9310 * 9311 * Licensed under the Apache License, Version 2.0 (the "License"); 9312 * you may not use this file except in compliance with the License. 9313 * You may obtain a copy of the License at 9314 * 9315 * http://www.apache.org/licenses/LICENSE-2.0 9316 * 9317 * Unless required by applicable law or agreed to in writing, software 9318 * distributed under the License is distributed on an "AS IS" BASIS, 9319 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9320 * See the License for the specific language governing permissions and 9321 * limitations under the License. 9322 * 9323 * @providesModule ReactMountReady 9324 */ 9325 9326 "use strict"; 9327 9328 var PooledClass = require("./PooledClass"); 9329 9330 var mixInto = require("./mixInto"); 9331 9332 /** 9333 * A specialized pseudo-event module to help keep track of components waiting to 9334 * be notified when their DOM representations are available for use. 9335 * 9336 * This implements `PooledClass`, so you should never need to instantiate this. 9337 * Instead, use `ReactMountReady.getPooled()`. 9338 * 9339 * @param {?array<function>} initialCollection 9340 * @class ReactMountReady 9341 * @implements PooledClass 9342 * @internal 9343 */ 9344 function ReactMountReady(initialCollection) { 9345 this._queue = initialCollection || null; 9346 } 9347 9348 mixInto(ReactMountReady, { 9349 9350 /** 9351 * Enqueues a callback to be invoked when `notifyAll` is invoked. This is used 9352 * to enqueue calls to `componentDidMount` and `componentDidUpdate`. 9353 * 9354 * @param {ReactComponent} component Component being rendered. 9355 * @param {function(DOMElement)} callback Invoked when `notifyAll` is invoked. 9356 * @internal 9357 */ 9358 enqueue: function(component, callback) { 9359 this._queue = this._queue || []; 9360 this._queue.push({component: component, callback: callback}); 9361 }, 9362 9363 /** 9364 * Invokes all enqueued callbacks and clears the queue. This is invoked after 9365 * the DOM representation of a component has been created or updated. 9366 * 9367 * @internal 9368 */ 9369 notifyAll: function() { 9370 var queue = this._queue; 9371 if (queue) { 9372 this._queue = null; 9373 for (var i = 0, l = queue.length; i < l; i++) { 9374 var component = queue[i].component; 9375 var callback = queue[i].callback; 9376 callback.call(component, component.getDOMNode()); 9377 } 9378 queue.length = 0; 9379 } 9380 }, 9381 9382 /** 9383 * Resets the internal queue. 9384 * 9385 * @internal 9386 */ 9387 reset: function() { 9388 this._queue = null; 9389 }, 9390 9391 /** 9392 * `PooledClass` looks for this. 9393 */ 9394 destructor: function() { 9395 this.reset(); 9396 } 9397 9398 }); 9399 9400 PooledClass.addPoolingTo(ReactMountReady); 9401 9402 module.exports = ReactMountReady; 9403 9404 },{"./PooledClass":25,"./mixInto":121}],56:[function(require,module,exports){ 9405 /** 9406 * Copyright 2013 Facebook, Inc. 9407 * 9408 * Licensed under the Apache License, Version 2.0 (the "License"); 9409 * you may not use this file except in compliance with the License. 9410 * You may obtain a copy of the License at 9411 * 9412 * http://www.apache.org/licenses/LICENSE-2.0 9413 * 9414 * Unless required by applicable law or agreed to in writing, software 9415 * distributed under the License is distributed on an "AS IS" BASIS, 9416 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9417 * See the License for the specific language governing permissions and 9418 * limitations under the License. 9419 * 9420 * @providesModule ReactMultiChild 9421 * @typechecks static-only 9422 */ 9423 9424 "use strict"; 9425 9426 var ReactComponent = require("./ReactComponent"); 9427 var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); 9428 9429 var flattenChildren = require("./flattenChildren"); 9430 9431 /** 9432 * Given a `curChild` and `newChild`, determines if `curChild` should be 9433 * updated as opposed to being destroyed or replaced. 9434 * 9435 * @param {?ReactComponent} curChild 9436 * @param {?ReactComponent} newChild 9437 * @return {boolean} True if `curChild` should be updated with `newChild`. 9438 * @protected 9439 */ 9440 function shouldUpdateChild(curChild, newChild) { 9441 return curChild && newChild && curChild.constructor === newChild.constructor; 9442 } 9443 9444 /** 9445 * Updating children of a component may trigger recursive updates. The depth is 9446 * used to batch recursive updates to render markup more efficiently. 9447 * 9448 * @type {number} 9449 * @private 9450 */ 9451 var updateDepth = 0; 9452 9453 /** 9454 * Queue of update configuration objects. 9455 * 9456 * Each object has a `type` property that is in `ReactMultiChildUpdateTypes`. 9457 * 9458 * @type {array<object>} 9459 * @private 9460 */ 9461 var updateQueue = []; 9462 9463 /** 9464 * Queue of markup to be rendered. 9465 * 9466 * @type {array<string>} 9467 * @private 9468 */ 9469 var markupQueue = []; 9470 9471 /** 9472 * Enqueues markup to be rendered and inserted at a supplied index. 9473 * 9474 * @param {string} parentID ID of the parent component. 9475 * @param {string} markup Markup that renders into an element. 9476 * @param {number} toIndex Destination index. 9477 * @private 9478 */ 9479 function enqueueMarkup(parentID, markup, toIndex) { 9480 // NOTE: Null values reduce hidden classes. 9481 updateQueue.push({ 9482 parentID: parentID, 9483 parentNode: null, 9484 type: ReactMultiChildUpdateTypes.INSERT_MARKUP, 9485 markupIndex: markupQueue.push(markup) - 1, 9486 textContent: null, 9487 fromIndex: null, 9488 toIndex: toIndex 9489 }); 9490 } 9491 9492 /** 9493 * Enqueues moving an existing element to another index. 9494 * 9495 * @param {string} parentID ID of the parent component. 9496 * @param {number} fromIndex Source index of the existing element. 9497 * @param {number} toIndex Destination index of the element. 9498 * @private 9499 */ 9500 function enqueueMove(parentID, fromIndex, toIndex) { 9501 // NOTE: Null values reduce hidden classes. 9502 updateQueue.push({ 9503 parentID: parentID, 9504 parentNode: null, 9505 type: ReactMultiChildUpdateTypes.MOVE_EXISTING, 9506 markupIndex: null, 9507 textContent: null, 9508 fromIndex: fromIndex, 9509 toIndex: toIndex 9510 }); 9511 } 9512 9513 /** 9514 * Enqueues removing an element at an index. 9515 * 9516 * @param {string} parentID ID of the parent component. 9517 * @param {number} fromIndex Index of the element to remove. 9518 * @private 9519 */ 9520 function enqueueRemove(parentID, fromIndex) { 9521 // NOTE: Null values reduce hidden classes. 9522 updateQueue.push({ 9523 parentID: parentID, 9524 parentNode: null, 9525 type: ReactMultiChildUpdateTypes.REMOVE_NODE, 9526 markupIndex: null, 9527 textContent: null, 9528 fromIndex: fromIndex, 9529 toIndex: null 9530 }); 9531 } 9532 9533 /** 9534 * Enqueues setting the text content. 9535 * 9536 * @param {string} parentID ID of the parent component. 9537 * @param {string} textContent Text content to set. 9538 * @private 9539 */ 9540 function enqueueTextContent(parentID, textContent) { 9541 // NOTE: Null values reduce hidden classes. 9542 updateQueue.push({ 9543 parentID: parentID, 9544 parentNode: null, 9545 type: ReactMultiChildUpdateTypes.TEXT_CONTENT, 9546 markupIndex: null, 9547 textContent: textContent, 9548 fromIndex: null, 9549 toIndex: null 9550 }); 9551 } 9552 9553 /** 9554 * Processes any enqueued updates. 9555 * 9556 * @private 9557 */ 9558 function processQueue() { 9559 if (updateQueue.length) { 9560 ReactComponent.DOMIDOperations.dangerouslyProcessChildrenUpdates( 9561 updateQueue, 9562 markupQueue 9563 ); 9564 clearQueue(); 9565 } 9566 } 9567 9568 /** 9569 * Clears any enqueued updates. 9570 * 9571 * @private 9572 */ 9573 function clearQueue() { 9574 updateQueue.length = 0; 9575 markupQueue.length = 0; 9576 } 9577 9578 /** 9579 * ReactMultiChild are capable of reconciling multiple children. 9580 * 9581 * @class ReactMultiChild 9582 * @internal 9583 */ 9584 var ReactMultiChild = { 9585 9586 /** 9587 * Provides common functionality for components that must reconcile multiple 9588 * children. This is used by `ReactDOMComponent` to mount, update, and 9589 * unmount child components. 9590 * 9591 * @lends {ReactMultiChild.prototype} 9592 */ 9593 Mixin: { 9594 9595 /** 9596 * Generates a "mount image" for each of the supplied children. In the case 9597 * of `ReactDOMComponent`, a mount image is a string of markup. 9598 * 9599 * @param {?object} nestedChildren Nested child maps. 9600 * @return {array} An array of mounted representations. 9601 * @internal 9602 */ 9603 mountChildren: function(nestedChildren, transaction) { 9604 var children = flattenChildren(nestedChildren); 9605 var mountImages = []; 9606 var index = 0; 9607 this._renderedChildren = children; 9608 for (var name in children) { 9609 var child = children[name]; 9610 if (children.hasOwnProperty(name) && child) { 9611 // Inlined for performance, see `ReactInstanceHandles.createReactID`. 9612 var rootID = this._rootNodeID + '.' + name; 9613 var mountImage = child.mountComponent( 9614 rootID, 9615 transaction, 9616 this._mountDepth + 1 9617 ); 9618 child._mountImage = mountImage; 9619 child._mountIndex = index; 9620 mountImages.push(mountImage); 9621 index++; 9622 } 9623 } 9624 return mountImages; 9625 }, 9626 9627 /** 9628 * Replaces any rendered children with a text content string. 9629 * 9630 * @param {string} nextContent String of content. 9631 * @internal 9632 */ 9633 updateTextContent: function(nextContent) { 9634 updateDepth++; 9635 try { 9636 var prevChildren = this._renderedChildren; 9637 // Remove any rendered children. 9638 for (var name in prevChildren) { 9639 if (prevChildren.hasOwnProperty(name) && 9640 prevChildren[name]) { 9641 this._unmountChildByName(prevChildren[name], name); 9642 } 9643 } 9644 // Set new text content. 9645 this.setTextContent(nextContent); 9646 } catch (error) { 9647 updateDepth--; 9648 updateDepth || clearQueue(); 9649 throw error; 9650 } 9651 updateDepth--; 9652 updateDepth || processQueue(); 9653 }, 9654 9655 /** 9656 * Updates the rendered children with new children. 9657 * 9658 * @param {?object} nextNestedChildren Nested child maps. 9659 * @param {ReactReconcileTransaction} transaction 9660 * @internal 9661 */ 9662 updateChildren: function(nextNestedChildren, transaction) { 9663 updateDepth++; 9664 try { 9665 this._updateChildren(nextNestedChildren, transaction); 9666 } catch (error) { 9667 updateDepth--; 9668 updateDepth || clearQueue(); 9669 throw error; 9670 } 9671 updateDepth--; 9672 updateDepth || processQueue(); 9673 }, 9674 9675 /** 9676 * Improve performance by isolating this hot code path from the try/catch 9677 * block in `updateChildren`. 9678 * 9679 * @param {?object} nextNestedChildren Nested child maps. 9680 * @param {ReactReconcileTransaction} transaction 9681 * @final 9682 * @protected 9683 */ 9684 _updateChildren: function(nextNestedChildren, transaction) { 9685 var nextChildren = flattenChildren(nextNestedChildren); 9686 var prevChildren = this._renderedChildren; 9687 if (!nextChildren && !prevChildren) { 9688 return; 9689 } 9690 var name; 9691 // `nextIndex` will increment for each child in `nextChildren`, but 9692 // `lastIndex` will be the last index visited in `prevChildren`. 9693 var lastIndex = 0; 9694 var nextIndex = 0; 9695 for (name in nextChildren) { 9696 if (!nextChildren.hasOwnProperty(name)) { 9697 continue; 9698 } 9699 var prevChild = prevChildren && prevChildren[name]; 9700 var nextChild = nextChildren[name]; 9701 if (shouldUpdateChild(prevChild, nextChild)) { 9702 this.moveChild(prevChild, nextIndex, lastIndex); 9703 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 9704 prevChild.receiveComponent(nextChild, transaction); 9705 prevChild._mountIndex = nextIndex; 9706 } else { 9707 if (prevChild) { 9708 // Update `lastIndex` before `_mountIndex` gets unset by unmounting. 9709 lastIndex = Math.max(prevChild._mountIndex, lastIndex); 9710 this._unmountChildByName(prevChild, name); 9711 } 9712 if (nextChild) { 9713 this._mountChildByNameAtIndex( 9714 nextChild, name, nextIndex, transaction 9715 ); 9716 } 9717 } 9718 if (nextChild) { 9719 nextIndex++; 9720 } 9721 } 9722 // Remove children that are no longer present. 9723 for (name in prevChildren) { 9724 if (prevChildren.hasOwnProperty(name) && 9725 prevChildren[name] && 9726 !(nextChildren && nextChildren[name])) { 9727 this._unmountChildByName(prevChildren[name], name); 9728 } 9729 } 9730 }, 9731 9732 /** 9733 * Unmounts all rendered children. This should be used to clean up children 9734 * when this component is unmounted. 9735 * 9736 * @internal 9737 */ 9738 unmountChildren: function() { 9739 var renderedChildren = this._renderedChildren; 9740 for (var name in renderedChildren) { 9741 var renderedChild = renderedChildren[name]; 9742 if (renderedChild && renderedChild.unmountComponent) { 9743 renderedChild.unmountComponent(); 9744 } 9745 } 9746 this._renderedChildren = null; 9747 }, 9748 9749 /** 9750 * Moves a child component to the supplied index. 9751 * 9752 * @param {ReactComponent} child Component to move. 9753 * @param {number} toIndex Destination index of the element. 9754 * @param {number} lastIndex Last index visited of the siblings of `child`. 9755 * @protected 9756 */ 9757 moveChild: function(child, toIndex, lastIndex) { 9758 // If the index of `child` is less than `lastIndex`, then it needs to 9759 // be moved. Otherwise, we do not need to move it because a child will be 9760 // inserted or moved before `child`. 9761 if (child._mountIndex < lastIndex) { 9762 enqueueMove(this._rootNodeID, child._mountIndex, toIndex); 9763 } 9764 }, 9765 9766 /** 9767 * Creates a child component. 9768 * 9769 * @param {ReactComponent} child Component to create. 9770 * @protected 9771 */ 9772 createChild: function(child) { 9773 enqueueMarkup(this._rootNodeID, child._mountImage, child._mountIndex); 9774 }, 9775 9776 /** 9777 * Removes a child component. 9778 * 9779 * @param {ReactComponent} child Child to remove. 9780 * @protected 9781 */ 9782 removeChild: function(child) { 9783 enqueueRemove(this._rootNodeID, child._mountIndex); 9784 }, 9785 9786 /** 9787 * Sets this text content string. 9788 * 9789 * @param {string} textContent Text content to set. 9790 * @protected 9791 */ 9792 setTextContent: function(textContent) { 9793 enqueueTextContent(this._rootNodeID, textContent); 9794 }, 9795 9796 /** 9797 * Mounts a child with the supplied name. 9798 * 9799 * NOTE: This is part of `updateChildren` and is here for readability. 9800 * 9801 * @param {ReactComponent} child Component to mount. 9802 * @param {string} name Name of the child. 9803 * @param {number} index Index at which to insert the child. 9804 * @param {ReactReconcileTransaction} transaction 9805 * @private 9806 */ 9807 _mountChildByNameAtIndex: function(child, name, index, transaction) { 9808 // Inlined for performance, see `ReactInstanceHandles.createReactID`. 9809 var rootID = this._rootNodeID + '.' + name; 9810 var mountImage = child.mountComponent( 9811 rootID, 9812 transaction, 9813 this._mountDepth + 1 9814 ); 9815 child._mountImage = mountImage; 9816 child._mountIndex = index; 9817 this.createChild(child); 9818 this._renderedChildren = this._renderedChildren || {}; 9819 this._renderedChildren[name] = child; 9820 }, 9821 9822 /** 9823 * Unmounts a rendered child by name. 9824 * 9825 * NOTE: This is part of `updateChildren` and is here for readability. 9826 * 9827 * @param {ReactComponent} child Component to unmount. 9828 * @param {string} name Name of the child in `this._renderedChildren`. 9829 * @private 9830 */ 9831 _unmountChildByName: function(child, name) { 9832 if (ReactComponent.isValidComponent(child)) { 9833 this.removeChild(child); 9834 child._mountImage = null; 9835 child._mountIndex = null; 9836 child.unmountComponent(); 9837 delete this._renderedChildren[name]; 9838 } 9839 } 9840 9841 } 9842 9843 }; 9844 9845 module.exports = ReactMultiChild; 9846 9847 },{"./ReactComponent":28,"./ReactMultiChildUpdateTypes":57,"./flattenChildren":98}],57:[function(require,module,exports){ 9848 /** 9849 * Copyright 2013 Facebook, Inc. 9850 * 9851 * Licensed under the Apache License, Version 2.0 (the "License"); 9852 * you may not use this file except in compliance with the License. 9853 * You may obtain a copy of the License at 9854 * 9855 * http://www.apache.org/licenses/LICENSE-2.0 9856 * 9857 * Unless required by applicable law or agreed to in writing, software 9858 * distributed under the License is distributed on an "AS IS" BASIS, 9859 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9860 * See the License for the specific language governing permissions and 9861 * limitations under the License. 9862 * 9863 * @providesModule ReactMultiChildUpdateTypes 9864 */ 9865 9866 var keyMirror = require("./keyMirror"); 9867 9868 /** 9869 * When a component's children are updated, a series of update configuration 9870 * objects are created in order to batch and serialize the required changes. 9871 * 9872 * Enumerates all the possible types of update configurations. 9873 * 9874 * @internal 9875 */ 9876 var ReactMultiChildUpdateTypes = keyMirror({ 9877 INSERT_MARKUP: null, 9878 MOVE_EXISTING: null, 9879 REMOVE_NODE: null, 9880 TEXT_CONTENT: null 9881 }); 9882 9883 module.exports = ReactMultiChildUpdateTypes; 9884 9885 },{"./keyMirror":115}],58:[function(require,module,exports){ 9886 /** 9887 * Copyright 2013 Facebook, Inc. 9888 * 9889 * Licensed under the Apache License, Version 2.0 (the "License"); 9890 * you may not use this file except in compliance with the License. 9891 * You may obtain a copy of the License at 9892 * 9893 * http://www.apache.org/licenses/LICENSE-2.0 9894 * 9895 * Unless required by applicable law or agreed to in writing, software 9896 * distributed under the License is distributed on an "AS IS" BASIS, 9897 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9898 * See the License for the specific language governing permissions and 9899 * limitations under the License. 9900 * 9901 * @providesModule ReactOwner 9902 */ 9903 9904 "use strict"; 9905 9906 var invariant = require("./invariant"); 9907 9908 /** 9909 * ReactOwners are capable of storing references to owned components. 9910 * 9911 * All components are capable of //being// referenced by owner components, but 9912 * only ReactOwner components are capable of //referencing// owned components. 9913 * The named reference is known as a "ref". 9914 * 9915 * Refs are available when mounted and updated during reconciliation. 9916 * 9917 * var MyComponent = React.createClass({ 9918 * render: function() { 9919 * return ( 9920 * <div onClick={this.handleClick}> 9921 * <CustomComponent ref="custom" /> 9922 * </div> 9923 * ); 9924 * }, 9925 * handleClick: function() { 9926 * this.refs.custom.handleClick(); 9927 * }, 9928 * componentDidMount: function() { 9929 * this.refs.custom.initialize(); 9930 * } 9931 * }); 9932 * 9933 * Refs should rarely be used. When refs are used, they should only be done to 9934 * control data that is not handled by React's data flow. 9935 * 9936 * @class ReactOwner 9937 */ 9938 var ReactOwner = { 9939 9940 /** 9941 * @param {?object} object 9942 * @return {boolean} True if `object` is a valid owner. 9943 * @final 9944 */ 9945 isValidOwner: function(object) { 9946 return !!( 9947 object && 9948 typeof object.attachRef === 'function' && 9949 typeof object.detachRef === 'function' 9950 ); 9951 }, 9952 9953 /** 9954 * Adds a component by ref to an owner component. 9955 * 9956 * @param {ReactComponent} component Component to reference. 9957 * @param {string} ref Name by which to refer to the component. 9958 * @param {ReactOwner} owner Component on which to record the ref. 9959 * @final 9960 * @internal 9961 */ 9962 addComponentAsRefTo: function(component, ref, owner) { 9963 ("production" !== "development" ? invariant( 9964 ReactOwner.isValidOwner(owner), 9965 'addComponentAsRefTo(...): Only a ReactOwner can have refs.' 9966 ) : invariant(ReactOwner.isValidOwner(owner))); 9967 owner.attachRef(ref, component); 9968 }, 9969 9970 /** 9971 * Removes a component by ref from an owner component. 9972 * 9973 * @param {ReactComponent} component Component to dereference. 9974 * @param {string} ref Name of the ref to remove. 9975 * @param {ReactOwner} owner Component on which the ref is recorded. 9976 * @final 9977 * @internal 9978 */ 9979 removeComponentAsRefFrom: function(component, ref, owner) { 9980 ("production" !== "development" ? invariant( 9981 ReactOwner.isValidOwner(owner), 9982 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs.' 9983 ) : invariant(ReactOwner.isValidOwner(owner))); 9984 // Check that `component` is still the current ref because we do not want to 9985 // detach the ref if another component stole it. 9986 if (owner.refs[ref] === component) { 9987 owner.detachRef(ref); 9988 } 9989 }, 9990 9991 /** 9992 * A ReactComponent must mix this in to have refs. 9993 * 9994 * @lends {ReactOwner.prototype} 9995 */ 9996 Mixin: { 9997 9998 /** 9999 * Lazily allocates the refs object and stores `component` as `ref`. 10000 * 10001 * @param {string} ref Reference name. 10002 * @param {component} component Component to store as `ref`. 10003 * @final 10004 * @private 10005 */ 10006 attachRef: function(ref, component) { 10007 ("production" !== "development" ? invariant( 10008 component.isOwnedBy(this), 10009 'attachRef(%s, ...): Only a component\'s owner can store a ref to it.', 10010 ref 10011 ) : invariant(component.isOwnedBy(this))); 10012 var refs = this.refs || (this.refs = {}); 10013 refs[ref] = component; 10014 }, 10015 10016 /** 10017 * Detaches a reference name. 10018 * 10019 * @param {string} ref Name to dereference. 10020 * @final 10021 * @private 10022 */ 10023 detachRef: function(ref) { 10024 delete this.refs[ref]; 10025 } 10026 10027 } 10028 10029 }; 10030 10031 module.exports = ReactOwner; 10032 10033 },{"./invariant":109}],59:[function(require,module,exports){ 10034 /** 10035 * Copyright 2013 Facebook, Inc. 10036 * 10037 * Licensed under the Apache License, Version 2.0 (the "License"); 10038 * you may not use this file except in compliance with the License. 10039 * You may obtain a copy of the License at 10040 * 10041 * http://www.apache.org/licenses/LICENSE-2.0 10042 * 10043 * Unless required by applicable law or agreed to in writing, software 10044 * distributed under the License is distributed on an "AS IS" BASIS, 10045 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10046 * See the License for the specific language governing permissions and 10047 * limitations under the License. 10048 * 10049 * @providesModule ReactPerf 10050 * @typechecks static-only 10051 */ 10052 10053 "use strict"; 10054 10055 var ReactPerf = { 10056 /** 10057 * Boolean to enable/disable measurement. Set to false by default to prevent 10058 * accidental logging and perf loss. 10059 */ 10060 enableMeasure: false, 10061 10062 /** 10063 * Holds onto the measure function in use. By default, don't measure 10064 * anything, but we'll override this if we inject a measure function. 10065 */ 10066 storedMeasure: _noMeasure, 10067 10068 /** 10069 * Use this to wrap methods you want to measure. 10070 * 10071 * @param {string} objName 10072 * @param {string} fnName 10073 * @param {function} func 10074 * @return {function} 10075 */ 10076 measure: function(objName, fnName, func) { 10077 if ("production" !== "development") { 10078 var measuredFunc = null; 10079 return function() { 10080 if (ReactPerf.enableMeasure) { 10081 if (!measuredFunc) { 10082 measuredFunc = ReactPerf.storedMeasure(objName, fnName, func); 10083 } 10084 return measuredFunc.apply(this, arguments); 10085 } 10086 return func.apply(this, arguments); 10087 }; 10088 } 10089 return func; 10090 }, 10091 10092 injection: { 10093 /** 10094 * @param {function} measure 10095 */ 10096 injectMeasure: function(measure) { 10097 ReactPerf.storedMeasure = measure; 10098 } 10099 } 10100 }; 10101 10102 if ("production" !== "development") { 10103 var ExecutionEnvironment = require("./ExecutionEnvironment"); 10104 var url = (ExecutionEnvironment.canUseDOM && window.location.href) || ''; 10105 ReactPerf.enableMeasure = ReactPerf.enableMeasure || 10106 (/[?&]react_perf\b/).test(url); 10107 } 10108 10109 /** 10110 * Simply passes through the measured function, without measuring it. 10111 * 10112 * @param {string} objName 10113 * @param {string} fnName 10114 * @param {function} func 10115 * @return {function} 10116 */ 10117 function _noMeasure(objName, fnName, func) { 10118 return func; 10119 } 10120 10121 module.exports = ReactPerf; 10122 10123 },{"./ExecutionEnvironment":21}],60:[function(require,module,exports){ 10124 /** 10125 * Copyright 2013 Facebook, Inc. 10126 * 10127 * Licensed under the Apache License, Version 2.0 (the "License"); 10128 * you may not use this file except in compliance with the License. 10129 * You may obtain a copy of the License at 10130 * 10131 * http://www.apache.org/licenses/LICENSE-2.0 10132 * 10133 * Unless required by applicable law or agreed to in writing, software 10134 * distributed under the License is distributed on an "AS IS" BASIS, 10135 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10136 * See the License for the specific language governing permissions and 10137 * limitations under the License. 10138 * 10139 * @providesModule ReactPropTransferer 10140 */ 10141 10142 "use strict"; 10143 10144 var emptyFunction = require("./emptyFunction"); 10145 var invariant = require("./invariant"); 10146 var joinClasses = require("./joinClasses"); 10147 var merge = require("./merge"); 10148 10149 /** 10150 * Creates a transfer strategy that will merge prop values using the supplied 10151 * `mergeStrategy`. If a prop was previously unset, this just sets it. 10152 * 10153 * @param {function} mergeStrategy 10154 * @return {function} 10155 */ 10156 function createTransferStrategy(mergeStrategy) { 10157 return function(props, key, value) { 10158 if (!props.hasOwnProperty(key)) { 10159 props[key] = value; 10160 } else { 10161 props[key] = mergeStrategy(props[key], value); 10162 } 10163 }; 10164 } 10165 10166 /** 10167 * Transfer strategies dictate how props are transferred by `transferPropsTo`. 10168 */ 10169 var TransferStrategies = { 10170 /** 10171 * Never transfer `children`. 10172 */ 10173 children: emptyFunction, 10174 /** 10175 * Transfer the `className` prop by merging them. 10176 */ 10177 className: createTransferStrategy(joinClasses), 10178 /** 10179 * Never transfer the `ref` prop. 10180 */ 10181 ref: emptyFunction, 10182 /** 10183 * Transfer the `style` prop (which is an object) by merging them. 10184 */ 10185 style: createTransferStrategy(merge) 10186 }; 10187 10188 /** 10189 * ReactPropTransferer are capable of transferring props to another component 10190 * using a `transferPropsTo` method. 10191 * 10192 * @class ReactPropTransferer 10193 */ 10194 var ReactPropTransferer = { 10195 10196 TransferStrategies: TransferStrategies, 10197 10198 /** 10199 * @lends {ReactPropTransferer.prototype} 10200 */ 10201 Mixin: { 10202 10203 /** 10204 * Transfer props from this component to a target component. 10205 * 10206 * Props that do not have an explicit transfer strategy will be transferred 10207 * only if the target component does not already have the prop set. 10208 * 10209 * This is usually used to pass down props to a returned root component. 10210 * 10211 * @param {ReactComponent} component Component receiving the properties. 10212 * @return {ReactComponent} The supplied `component`. 10213 * @final 10214 * @protected 10215 */ 10216 transferPropsTo: function(component) { 10217 ("production" !== "development" ? invariant( 10218 component.props.__owner__ === this, 10219 '%s: You can\'t call transferPropsTo() on a component that you ' + 10220 'don\'t own, %s. This usually means you are calling ' + 10221 'transferPropsTo() on a component passed in as props or children.', 10222 this.constructor.displayName, 10223 component.constructor.displayName 10224 ) : invariant(component.props.__owner__ === this)); 10225 10226 var props = {}; 10227 for (var thatKey in component.props) { 10228 if (component.props.hasOwnProperty(thatKey)) { 10229 props[thatKey] = component.props[thatKey]; 10230 } 10231 } 10232 for (var thisKey in this.props) { 10233 if (!this.props.hasOwnProperty(thisKey)) { 10234 continue; 10235 } 10236 var transferStrategy = TransferStrategies[thisKey]; 10237 if (transferStrategy) { 10238 transferStrategy(props, thisKey, this.props[thisKey]); 10239 } else if (!props.hasOwnProperty(thisKey)) { 10240 props[thisKey] = this.props[thisKey]; 10241 } 10242 } 10243 component.props = props; 10244 return component; 10245 } 10246 10247 } 10248 10249 }; 10250 10251 module.exports = ReactPropTransferer; 10252 10253 },{"./emptyFunction":94,"./invariant":109,"./joinClasses":114,"./merge":118}],61:[function(require,module,exports){ 10254 /** 10255 * Copyright 2013 Facebook, Inc. 10256 * 10257 * Licensed under the Apache License, Version 2.0 (the "License"); 10258 * you may not use this file except in compliance with the License. 10259 * You may obtain a copy of the License at 10260 * 10261 * http://www.apache.org/licenses/LICENSE-2.0 10262 * 10263 * Unless required by applicable law or agreed to in writing, software 10264 * distributed under the License is distributed on an "AS IS" BASIS, 10265 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10266 * See the License for the specific language governing permissions and 10267 * limitations under the License. 10268 * 10269 * @providesModule ReactPropTypes 10270 */ 10271 10272 "use strict"; 10273 10274 var createObjectFrom = require("./createObjectFrom"); 10275 var invariant = require("./invariant"); 10276 10277 /** 10278 * Collection of methods that allow declaration and validation of props that are 10279 * supplied to React components. Example usage: 10280 * 10281 * var Props = require('ReactPropTypes'); 10282 * var MyArticle = React.createClass({ 10283 * propTypes: { 10284 * // An optional string prop named "description". 10285 * description: Props.string, 10286 * 10287 * // A required enum prop named "category". 10288 * category: Props.oneOf(['News','Photos']).isRequired, 10289 * 10290 * // A prop named "dialog" that requires an instance of Dialog. 10291 * dialog: Props.instanceOf(Dialog).isRequired 10292 * }, 10293 * render: function() { ... } 10294 * }); 10295 * 10296 * A more formal specification of how these methods are used: 10297 * 10298 * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...) 10299 * decl := ReactPropTypes.{type}(.isRequired)? 10300 * 10301 * Each and every declaration produces a function with the same signature. This 10302 * allows the creation of custom validation functions. For example: 10303 * 10304 * var Props = require('ReactPropTypes'); 10305 * var MyLink = React.createClass({ 10306 * propTypes: { 10307 * // An optional string or URI prop named "href". 10308 * href: function(props, propName, componentName) { 10309 * var propValue = props[propName]; 10310 * invariant( 10311 * propValue == null || 10312 * typeof propValue === 'string' || 10313 * propValue instanceof URI, 10314 * 'Invalid `%s` supplied to `%s`, expected string or URI.', 10315 * propName, 10316 * componentName 10317 * ); 10318 * } 10319 * }, 10320 * render: function() { ... } 10321 * }); 10322 * 10323 * @internal 10324 */ 10325 var Props = { 10326 10327 array: createPrimitiveTypeChecker('array'), 10328 bool: createPrimitiveTypeChecker('boolean'), 10329 func: createPrimitiveTypeChecker('function'), 10330 number: createPrimitiveTypeChecker('number'), 10331 object: createPrimitiveTypeChecker('object'), 10332 string: createPrimitiveTypeChecker('string'), 10333 10334 oneOf: createEnumTypeChecker, 10335 10336 instanceOf: createInstanceTypeChecker 10337 10338 }; 10339 10340 var ANONYMOUS = '<<anonymous>>'; 10341 10342 function createPrimitiveTypeChecker(expectedType) { 10343 function validatePrimitiveType(propValue, propName, componentName) { 10344 var propType = typeof propValue; 10345 if (propType === 'object' && Array.isArray(propValue)) { 10346 propType = 'array'; 10347 } 10348 ("production" !== "development" ? invariant( 10349 propType === expectedType, 10350 'Invalid prop `%s` of type `%s` supplied to `%s`, expected `%s`.', 10351 propName, 10352 propType, 10353 componentName, 10354 expectedType 10355 ) : invariant(propType === expectedType)); 10356 } 10357 return createChainableTypeChecker(validatePrimitiveType); 10358 } 10359 10360 function createEnumTypeChecker(expectedValues) { 10361 var expectedEnum = createObjectFrom(expectedValues); 10362 function validateEnumType(propValue, propName, componentName) { 10363 ("production" !== "development" ? invariant( 10364 expectedEnum[propValue], 10365 'Invalid prop `%s` supplied to `%s`, expected one of %s.', 10366 propName, 10367 componentName, 10368 JSON.stringify(Object.keys(expectedEnum)) 10369 ) : invariant(expectedEnum[propValue])); 10370 } 10371 return createChainableTypeChecker(validateEnumType); 10372 } 10373 10374 function createInstanceTypeChecker(expectedClass) { 10375 function validateInstanceType(propValue, propName, componentName) { 10376 ("production" !== "development" ? invariant( 10377 propValue instanceof expectedClass, 10378 'Invalid prop `%s` supplied to `%s`, expected instance of `%s`.', 10379 propName, 10380 componentName, 10381 expectedClass.name || ANONYMOUS 10382 ) : invariant(propValue instanceof expectedClass)); 10383 } 10384 return createChainableTypeChecker(validateInstanceType); 10385 } 10386 10387 function createChainableTypeChecker(validate) { 10388 function createTypeChecker(isRequired) { 10389 function checkType(props, propName, componentName) { 10390 var propValue = props[propName]; 10391 if (propValue != null) { 10392 // Only validate if there is a value to check. 10393 validate(propValue, propName, componentName || ANONYMOUS); 10394 } else { 10395 ("production" !== "development" ? invariant( 10396 !isRequired, 10397 'Required prop `%s` was not specified in `%s`.', 10398 propName, 10399 componentName || ANONYMOUS 10400 ) : invariant(!isRequired)); 10401 } 10402 } 10403 if (!isRequired) { 10404 checkType.isRequired = createTypeChecker(true); 10405 } 10406 return checkType; 10407 } 10408 return createTypeChecker(false); 10409 } 10410 10411 module.exports = Props; 10412 10413 },{"./createObjectFrom":91,"./invariant":109}],62:[function(require,module,exports){ 10414 /** 10415 * Copyright 2013 Facebook, Inc. 10416 * 10417 * Licensed under the Apache License, Version 2.0 (the "License"); 10418 * you may not use this file except in compliance with the License. 10419 * You may obtain a copy of the License at 10420 * 10421 * http://www.apache.org/licenses/LICENSE-2.0 10422 * 10423 * Unless required by applicable law or agreed to in writing, software 10424 * distributed under the License is distributed on an "AS IS" BASIS, 10425 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10426 * See the License for the specific language governing permissions and 10427 * limitations under the License. 10428 * 10429 * @providesModule ReactReconcileTransaction 10430 * @typechecks static-only 10431 */ 10432 10433 "use strict"; 10434 10435 var ExecutionEnvironment = require("./ExecutionEnvironment"); 10436 var PooledClass = require("./PooledClass"); 10437 var ReactEventEmitter = require("./ReactEventEmitter"); 10438 var ReactInputSelection = require("./ReactInputSelection"); 10439 var ReactMountReady = require("./ReactMountReady"); 10440 var Transaction = require("./Transaction"); 10441 10442 var mixInto = require("./mixInto"); 10443 10444 /** 10445 * Ensures that, when possible, the selection range (currently selected text 10446 * input) is not disturbed by performing the transaction. 10447 */ 10448 var SELECTION_RESTORATION = { 10449 /** 10450 * @return {Selection} Selection information. 10451 */ 10452 initialize: ReactInputSelection.getSelectionInformation, 10453 /** 10454 * @param {Selection} sel Selection information returned from `initialize`. 10455 */ 10456 close: ReactInputSelection.restoreSelection 10457 }; 10458 10459 /** 10460 * Suppresses events (blur/focus) that could be inadvertently dispatched due to 10461 * high level DOM manipulations (like temporarily removing a text input from the 10462 * DOM). 10463 */ 10464 var EVENT_SUPPRESSION = { 10465 /** 10466 * @return {boolean} The enabled status of `ReactEventEmitter` before the 10467 * reconciliation. 10468 */ 10469 initialize: function() { 10470 var currentlyEnabled = ReactEventEmitter.isEnabled(); 10471 ReactEventEmitter.setEnabled(false); 10472 return currentlyEnabled; 10473 }, 10474 10475 /** 10476 * @param {boolean} previouslyEnabled Enabled status of `ReactEventEmitter` 10477 * before the reconciliation occured. `close` restores the previous value. 10478 */ 10479 close: function(previouslyEnabled) { 10480 ReactEventEmitter.setEnabled(previouslyEnabled); 10481 } 10482 }; 10483 10484 /** 10485 * Provides a `ReactMountReady` queue for collecting `onDOMReady` callbacks 10486 * during the performing of the transaction. 10487 */ 10488 var ON_DOM_READY_QUEUEING = { 10489 /** 10490 * Initializes the internal `onDOMReady` queue. 10491 */ 10492 initialize: function() { 10493 this.reactMountReady.reset(); 10494 }, 10495 10496 /** 10497 * After DOM is flushed, invoke all registered `onDOMReady` callbacks. 10498 */ 10499 close: function() { 10500 this.reactMountReady.notifyAll(); 10501 } 10502 }; 10503 10504 /** 10505 * Executed within the scope of the `Transaction` instance. Consider these as 10506 * being member methods, but with an implied ordering while being isolated from 10507 * each other. 10508 */ 10509 var TRANSACTION_WRAPPERS = [ 10510 SELECTION_RESTORATION, 10511 EVENT_SUPPRESSION, 10512 ON_DOM_READY_QUEUEING 10513 ]; 10514 10515 /** 10516 * Currently: 10517 * - The order that these are listed in the transaction is critical: 10518 * - Suppresses events. 10519 * - Restores selection range. 10520 * 10521 * Future: 10522 * - Restore document/overflow scroll positions that were unintentionally 10523 * modified via DOM insertions above the top viewport boundary. 10524 * - Implement/integrate with customized constraint based layout system and keep 10525 * track of which dimensions must be remeasured. 10526 * 10527 * @class ReactReconcileTransaction 10528 */ 10529 function ReactReconcileTransaction() { 10530 this.reinitializeTransaction(); 10531 this.reactMountReady = ReactMountReady.getPooled(null); 10532 } 10533 10534 var Mixin = { 10535 /** 10536 * @see Transaction 10537 * @abstract 10538 * @final 10539 * @return {array<object>} List of operation wrap proceedures. 10540 * TODO: convert to array<TransactionWrapper> 10541 */ 10542 getTransactionWrappers: function() { 10543 if (ExecutionEnvironment.canUseDOM) { 10544 return TRANSACTION_WRAPPERS; 10545 } else { 10546 return []; 10547 } 10548 }, 10549 10550 /** 10551 * @return {object} The queue to collect `onDOMReady` callbacks with. 10552 * TODO: convert to ReactMountReady 10553 */ 10554 getReactMountReady: function() { 10555 return this.reactMountReady; 10556 }, 10557 10558 /** 10559 * `PooledClass` looks for this, and will invoke this before allowing this 10560 * instance to be resused. 10561 */ 10562 destructor: function() { 10563 ReactMountReady.release(this.reactMountReady); 10564 this.reactMountReady = null; 10565 } 10566 }; 10567 10568 10569 mixInto(ReactReconcileTransaction, Transaction.Mixin); 10570 mixInto(ReactReconcileTransaction, Mixin); 10571 10572 PooledClass.addPoolingTo(ReactReconcileTransaction); 10573 10574 module.exports = ReactReconcileTransaction; 10575 10576 },{"./ExecutionEnvironment":21,"./PooledClass":25,"./ReactEventEmitter":47,"./ReactInputSelection":50,"./ReactMountReady":55,"./Transaction":83,"./mixInto":121}],63:[function(require,module,exports){ 10577 /** 10578 * Copyright 2013 Facebook, Inc. 10579 * 10580 * Licensed under the Apache License, Version 2.0 (the "License"); 10581 * you may not use this file except in compliance with the License. 10582 * You may obtain a copy of the License at 10583 * 10584 * http://www.apache.org/licenses/LICENSE-2.0 10585 * 10586 * Unless required by applicable law or agreed to in writing, software 10587 * distributed under the License is distributed on an "AS IS" BASIS, 10588 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10589 * See the License for the specific language governing permissions and 10590 * limitations under the License. 10591 * 10592 * @typechecks static-only 10593 * @providesModule ReactServerRendering 10594 */ 10595 "use strict"; 10596 10597 var ReactComponent = require("./ReactComponent"); 10598 var ReactInstanceHandles = require("./ReactInstanceHandles"); 10599 var ReactMarkupChecksum = require("./ReactMarkupChecksum"); 10600 var ReactReconcileTransaction = require("./ReactReconcileTransaction"); 10601 10602 var invariant = require("./invariant"); 10603 10604 /** 10605 * @param {ReactComponent} component 10606 * @param {function} callback 10607 */ 10608 function renderComponentToString(component, callback) { 10609 // We use a callback API to keep the API async in case in the future we ever 10610 // need it, but in reality this is a synchronous operation. 10611 10612 ("production" !== "development" ? invariant( 10613 ReactComponent.isValidComponent(component), 10614 'renderComponentToString(): You must pass a valid ReactComponent.' 10615 ) : invariant(ReactComponent.isValidComponent(component))); 10616 10617 ("production" !== "development" ? invariant( 10618 typeof callback === 'function', 10619 'renderComponentToString(): You must pass a function as a callback.' 10620 ) : invariant(typeof callback === 'function')); 10621 10622 var id = ReactInstanceHandles.createReactRootID(); 10623 var transaction = ReactReconcileTransaction.getPooled(); 10624 transaction.reinitializeTransaction(); 10625 try { 10626 transaction.perform(function() { 10627 var markup = component.mountComponent(id, transaction, 0); 10628 markup = ReactMarkupChecksum.addChecksumToMarkup(markup); 10629 callback(markup); 10630 }, null); 10631 } finally { 10632 ReactReconcileTransaction.release(transaction); 10633 } 10634 } 10635 10636 module.exports = { 10637 renderComponentToString: renderComponentToString 10638 }; 10639 10640 },{"./ReactComponent":28,"./ReactInstanceHandles":51,"./ReactMarkupChecksum":53,"./ReactReconcileTransaction":62,"./invariant":109}],64:[function(require,module,exports){ 10641 /** 10642 * Copyright 2013 Facebook, Inc. 10643 * 10644 * Licensed under the Apache License, Version 2.0 (the "License"); 10645 * you may not use this file except in compliance with the License. 10646 * You may obtain a copy of the License at 10647 * 10648 * http://www.apache.org/licenses/LICENSE-2.0 10649 * 10650 * Unless required by applicable law or agreed to in writing, software 10651 * distributed under the License is distributed on an "AS IS" BASIS, 10652 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10653 * See the License for the specific language governing permissions and 10654 * limitations under the License. 10655 * 10656 * @providesModule ReactStateSetters 10657 */ 10658 10659 "use strict"; 10660 10661 var ReactStateSetters = { 10662 /** 10663 * Returns a function that calls the provided function, and uses the result 10664 * of that to set the component's state. 10665 * 10666 * @param {ReactCompositeComponent} component 10667 * @param {function} funcReturningState Returned callback uses this to 10668 * determine how to update state. 10669 * @return {function} callback that when invoked uses funcReturningState to 10670 * determined the object literal to setState. 10671 */ 10672 createStateSetter: function(component, funcReturningState) { 10673 return function(a, b, c, d, e, f) { 10674 var partialState = funcReturningState.call(component, a, b, c, d, e, f); 10675 if (partialState) { 10676 component.setState(partialState); 10677 } 10678 }; 10679 }, 10680 10681 /** 10682 * Returns a single-argument callback that can be used to update a single 10683 * key in the component's state. 10684 * 10685 * Note: this is memoized function, which makes it inexpensive to call. 10686 * 10687 * @param {ReactCompositeComponent} component 10688 * @param {string} key The key in the state that you should update. 10689 * @return {function} callback of 1 argument which calls setState() with 10690 * the provided keyName and callback argument. 10691 */ 10692 createStateKeySetter: function(component, key) { 10693 // Memoize the setters. 10694 var cache = component.__keySetters || (component.__keySetters = {}); 10695 return cache[key] || (cache[key] = createStateKeySetter(component, key)); 10696 } 10697 }; 10698 10699 function createStateKeySetter(component, key) { 10700 // Partial state is allocated outside of the function closure so it can be 10701 // reused with every call, avoiding memory allocation when this function 10702 // is called. 10703 var partialState = {}; 10704 return function stateKeySetter(value) { 10705 partialState[key] = value; 10706 component.setState(partialState); 10707 }; 10708 } 10709 10710 ReactStateSetters.Mixin = { 10711 /** 10712 * Returns a function that calls the provided function, and uses the result 10713 * of that to set the component's state. 10714 * 10715 * For example, these statements are equivalent: 10716 * 10717 * this.setState({x: 1}); 10718 * this.createStateSetter(function(xValue) { 10719 * return {x: xValue}; 10720 * })(1); 10721 * 10722 * @param {function} funcReturningState Returned callback uses this to 10723 * determine how to update state. 10724 * @return {function} callback that when invoked uses funcReturningState to 10725 * determined the object literal to setState. 10726 */ 10727 createStateSetter: function(funcReturningState) { 10728 return ReactStateSetters.createStateSetter(this, funcReturningState); 10729 }, 10730 10731 /** 10732 * Returns a single-argument callback that can be used to update a single 10733 * key in the component's state. 10734 * 10735 * For example, these statements are equivalent: 10736 * 10737 * this.setState({x: 1}); 10738 * this.createStateKeySetter('x')(1); 10739 * 10740 * Note: this is memoized function, which makes it inexpensive to call. 10741 * 10742 * @param {string} key The key in the state that you should update. 10743 * @return {function} callback of 1 argument which calls setState() with 10744 * the provided keyName and callback argument. 10745 */ 10746 createStateKeySetter: function(key) { 10747 return ReactStateSetters.createStateKeySetter(this, key); 10748 } 10749 }; 10750 10751 module.exports = ReactStateSetters; 10752 10753 },{}],65:[function(require,module,exports){ 10754 /** 10755 * Copyright 2013 Facebook, Inc. 10756 * 10757 * Licensed under the Apache License, Version 2.0 (the "License"); 10758 * you may not use this file except in compliance with the License. 10759 * You may obtain a copy of the License at 10760 * 10761 * http://www.apache.org/licenses/LICENSE-2.0 10762 * 10763 * Unless required by applicable law or agreed to in writing, software 10764 * distributed under the License is distributed on an "AS IS" BASIS, 10765 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10766 * See the License for the specific language governing permissions and 10767 * limitations under the License. 10768 * 10769 * @providesModule ReactTextComponent 10770 * @typechecks static-only 10771 */ 10772 10773 "use strict"; 10774 10775 var ReactComponent = require("./ReactComponent"); 10776 var ReactMount = require("./ReactMount"); 10777 10778 var escapeTextForBrowser = require("./escapeTextForBrowser"); 10779 var mixInto = require("./mixInto"); 10780 10781 /** 10782 * Text nodes violate a couple assumptions that React makes about components: 10783 * 10784 * - When mounting text into the DOM, adjacent text nodes are merged. 10785 * - Text nodes cannot be assigned a React root ID. 10786 * 10787 * This component is used to wrap strings in elements so that they can undergo 10788 * the same reconciliation that is applied to elements. 10789 * 10790 * TODO: Investigate representing React components in the DOM with text nodes. 10791 * 10792 * @class ReactTextComponent 10793 * @extends ReactComponent 10794 * @internal 10795 */ 10796 var ReactTextComponent = function(initialText) { 10797 this.construct({text: initialText}); 10798 }; 10799 10800 mixInto(ReactTextComponent, ReactComponent.Mixin); 10801 mixInto(ReactTextComponent, { 10802 10803 /** 10804 * Creates the markup for this text node. This node is not intended to have 10805 * any features besides containing text content. 10806 * 10807 * @param {string} rootID DOM ID of the root node. 10808 * @param {ReactReconcileTransaction} transaction 10809 * @param {number} mountDepth number of components in the owner hierarchy 10810 * @return {string} Markup for this text node. 10811 * @internal 10812 */ 10813 mountComponent: function(rootID, transaction, mountDepth) { 10814 ReactComponent.Mixin.mountComponent.call( 10815 this, 10816 rootID, 10817 transaction, 10818 mountDepth 10819 ); 10820 return ( 10821 '<span ' + ReactMount.ATTR_NAME + '="' + escapeTextForBrowser(rootID) + '">' + 10822 escapeTextForBrowser(this.props.text) + 10823 '</span>' 10824 ); 10825 }, 10826 10827 /** 10828 * Updates this component by updating the text content. 10829 * 10830 * @param {object} nextComponent Contains the next text content. 10831 * @param {ReactReconcileTransaction} transaction 10832 * @internal 10833 */ 10834 receiveComponent: function(nextComponent, transaction) { 10835 var nextProps = nextComponent.props; 10836 if (nextProps.text !== this.props.text) { 10837 this.props.text = nextProps.text; 10838 ReactComponent.DOMIDOperations.updateTextContentByID( 10839 this._rootNodeID, 10840 nextProps.text 10841 ); 10842 } 10843 } 10844 10845 }); 10846 10847 module.exports = ReactTextComponent; 10848 10849 },{"./ReactComponent":28,"./ReactMount":54,"./escapeTextForBrowser":95,"./mixInto":121}],66:[function(require,module,exports){ 10850 /** 10851 * Copyright 2013 Facebook, Inc. 10852 * 10853 * Licensed under the Apache License, Version 2.0 (the "License"); 10854 * you may not use this file except in compliance with the License. 10855 * You may obtain a copy of the License at 10856 * 10857 * http://www.apache.org/licenses/LICENSE-2.0 10858 * 10859 * Unless required by applicable law or agreed to in writing, software 10860 * distributed under the License is distributed on an "AS IS" BASIS, 10861 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10862 * See the License for the specific language governing permissions and 10863 * limitations under the License. 10864 * 10865 * @providesModule ReactTransitionEvents 10866 */ 10867 10868 "use strict"; 10869 10870 var ExecutionEnvironment = require("./ExecutionEnvironment"); 10871 10872 var EVENT_NAME_MAP = { 10873 transitionend: { 10874 'transition': 'transitionend', 10875 'WebkitTransition': 'webkitTransitionEnd', 10876 'MozTransition': 'mozTransitionEnd', 10877 'OTransition': 'oTransitionEnd', 10878 'msTransition': 'MSTransitionEnd' 10879 }, 10880 10881 animationend: { 10882 'animation': 'animationend', 10883 'WebkitAnimation': 'webkitAnimationEnd', 10884 'MozAnimation': 'mozAnimationEnd', 10885 'OAnimation': 'oAnimationEnd', 10886 'msAnimation': 'MSAnimationEnd' 10887 } 10888 }; 10889 10890 var endEvents = []; 10891 10892 function detectEvents() { 10893 var testEl = document.createElement('div'); 10894 var style = testEl.style; 10895 for (var baseEventName in EVENT_NAME_MAP) { 10896 var baseEvents = EVENT_NAME_MAP[baseEventName]; 10897 for (var styleName in baseEvents) { 10898 if (styleName in style) { 10899 endEvents.push(baseEvents[styleName]); 10900 break; 10901 } 10902 } 10903 } 10904 } 10905 10906 if (ExecutionEnvironment.canUseDOM) { 10907 detectEvents(); 10908 } 10909 10910 // We use the raw {add|remove}EventListener() call because EventListener 10911 // does not know how to remove event listeners and we really should 10912 // clean up. Also, these events are not triggered in older browsers 10913 // so we should be A-OK here. 10914 10915 function addEventListener(node, eventName, eventListener) { 10916 node.addEventListener(eventName, eventListener, false); 10917 } 10918 10919 function removeEventListener(node, eventName, eventListener) { 10920 node.removeEventListener(eventName, eventListener, false); 10921 } 10922 10923 var ReactTransitionEvents = { 10924 addEndEventListener: function(node, eventListener) { 10925 if (endEvents.length === 0) { 10926 // If CSS transitions are not supported, trigger an "end animation" 10927 // event immediately. 10928 window.setTimeout(eventListener, 0); 10929 return; 10930 } 10931 endEvents.forEach(function(endEvent) { 10932 addEventListener(node, endEvent, eventListener); 10933 }); 10934 }, 10935 10936 removeEndEventListener: function(node, eventListener) { 10937 if (endEvents.length === 0) { 10938 return; 10939 } 10940 endEvents.forEach(function(endEvent) { 10941 removeEventListener(node, endEvent, eventListener); 10942 }); 10943 } 10944 }; 10945 10946 module.exports = ReactTransitionEvents; 10947 10948 },{"./ExecutionEnvironment":21}],67:[function(require,module,exports){ 10949 /** 10950 * Copyright 2013 Facebook, Inc. 10951 * 10952 * Licensed under the Apache License, Version 2.0 (the "License"); 10953 * you may not use this file except in compliance with the License. 10954 * You may obtain a copy of the License at 10955 * 10956 * http://www.apache.org/licenses/LICENSE-2.0 10957 * 10958 * Unless required by applicable law or agreed to in writing, software 10959 * distributed under the License is distributed on an "AS IS" BASIS, 10960 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10961 * See the License for the specific language governing permissions and 10962 * limitations under the License. 10963 * 10964 * @providesModule ReactTransitionGroup 10965 */ 10966 10967 "use strict"; 10968 10969 var React = require("./React"); 10970 var ReactTransitionableChild = require("./ReactTransitionableChild"); 10971 var ReactTransitionKeySet = require("./ReactTransitionKeySet"); 10972 10973 var ReactTransitionGroup = React.createClass({ 10974 10975 propTypes: { 10976 transitionName: React.PropTypes.string.isRequired, 10977 transitionEnter: React.PropTypes.bool, 10978 transitionLeave: React.PropTypes.bool, 10979 onTransition: React.PropTypes.func, 10980 component: React.PropTypes.func 10981 }, 10982 10983 getDefaultProps: function() { 10984 return { 10985 transitionEnter: true, 10986 transitionLeave: true, 10987 component: React.DOM.span 10988 }; 10989 }, 10990 10991 componentWillMount: function() { 10992 // _transitionGroupCurrentKeys stores the union of previous *and* next keys. 10993 // If this were a component we'd store it as state, however, since this must 10994 // be a mixin, we need to keep the result of the union of keys in each 10995 // call to animateChildren() which happens in render(), so we can't 10996 // call setState() in there. 10997 this._transitionGroupCurrentKeys = {}; 10998 }, 10999 11000 componentDidUpdate: function() { 11001 if (this.props.onTransition) { 11002 this.props.onTransition(); 11003 } 11004 }, 11005 11006 /** 11007 * Render some children in a transitionable way. 11008 */ 11009 renderTransitionableChildren: function(sourceChildren) { 11010 var children = {}; 11011 var childMapping = ReactTransitionKeySet.getChildMapping(sourceChildren); 11012 11013 var currentKeys = ReactTransitionKeySet.mergeKeySets( 11014 this._transitionGroupCurrentKeys, 11015 ReactTransitionKeySet.getKeySet(sourceChildren) 11016 ); 11017 11018 for (var key in currentKeys) { 11019 // Here is how we keep the nodes in the DOM. ReactTransitionableChild 11020 // knows how to hold onto its child if it changes to undefined. Here, we 11021 // may look up an old key in the new children, and it may switch to 11022 // undefined. React's reconciler will keep the ReactTransitionableChild 11023 // instance alive such that we can animate it. 11024 if (childMapping[key] || this.props.transitionLeave) { 11025 children[key] = ReactTransitionableChild({ 11026 name: this.props.transitionName, 11027 enter: this.props.transitionEnter, 11028 onDoneLeaving: this._handleDoneLeaving.bind(this, key) 11029 }, childMapping[key]); 11030 } 11031 } 11032 11033 this._transitionGroupCurrentKeys = currentKeys; 11034 11035 return children; 11036 }, 11037 11038 _handleDoneLeaving: function(key) { 11039 // When the leave animation finishes, we should blow away the actual DOM 11040 // node. 11041 delete this._transitionGroupCurrentKeys[key]; 11042 this.forceUpdate(); 11043 }, 11044 11045 render: function() { 11046 return this.transferPropsTo( 11047 this.props.component( 11048 { 11049 transitionName: null, 11050 transitionEnter: null, 11051 transitionLeave: null, 11052 component: null 11053 }, 11054 this.renderTransitionableChildren(this.props.children) 11055 ) 11056 ); 11057 } 11058 }); 11059 11060 module.exports = ReactTransitionGroup; 11061 11062 },{"./React":26,"./ReactTransitionKeySet":68,"./ReactTransitionableChild":69}],68:[function(require,module,exports){ 11063 /** 11064 * Copyright 2013 Facebook, Inc. 11065 * 11066 * Licensed under the Apache License, Version 2.0 (the "License"); 11067 * you may not use this file except in compliance with the License. 11068 * You may obtain a copy of the License at 11069 * 11070 * http://www.apache.org/licenses/LICENSE-2.0 11071 * 11072 * Unless required by applicable law or agreed to in writing, software 11073 * distributed under the License is distributed on an "AS IS" BASIS, 11074 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11075 * See the License for the specific language governing permissions and 11076 * limitations under the License. 11077 * 11078 * @typechecks static-only 11079 * @providesModule ReactTransitionKeySet 11080 */ 11081 11082 "use strict"; 11083 11084 var ReactChildren = require("./ReactChildren"); 11085 11086 var MERGE_KEY_SETS_TAIL_SENTINEL = {}; 11087 11088 var ReactTransitionKeySet = { 11089 /** 11090 * Given `this.props.children`, return an object mapping key to child. Just 11091 * simple syntactic sugar around ReactChildren.map(). 11092 * 11093 * @param {*} children `this.props.children` 11094 * @return {object} Mapping of key to child 11095 */ 11096 getChildMapping: function(children) { 11097 return ReactChildren.map(children, function(child) { 11098 return child; 11099 }); 11100 }, 11101 11102 /** 11103 * Simple syntactic sugar to get an object with keys of all of `children`. 11104 * Does not have references to the children themselves. 11105 * 11106 * @param {*} children `this.props.children` 11107 * @return {object} Mapping of key to the value "true" 11108 */ 11109 getKeySet: function(children) { 11110 return ReactChildren.map(children, function() { 11111 return true; 11112 }); 11113 }, 11114 11115 /** 11116 * When you're adding or removing children some may be added or removed in the 11117 * same render pass. We want ot show *both* since we want to simultaneously 11118 * animate elements in and out. This function takes a previous set of keys 11119 * and a new set of keys and merges them with its best guess of the correct 11120 * ordering. In the future we may expose some of the utilities in 11121 * ReactMultiChild to make this easy, but for now React itself does not 11122 * directly have this concept of the union of prevChildren and nextChildren 11123 * so we implement it here. 11124 * 11125 * @param {object} prev prev child keys as returned from 11126 * `ReactTransitionKeySet.getKeySet()`. 11127 * @param {object} next next child keys as returned from 11128 * `ReactTransitionKeySet.getKeySet()`. 11129 * @return {object} a key set that contains all keys in `prev` and all keys 11130 * in `next` in a reasonable order. 11131 */ 11132 mergeKeySets: function(prev, next) { 11133 prev = prev || {}; 11134 next = next || {}; 11135 11136 var keySet = {}; 11137 var prevKeys = Object.keys(prev).concat([MERGE_KEY_SETS_TAIL_SENTINEL]); 11138 var nextKeys = Object.keys(next).concat([MERGE_KEY_SETS_TAIL_SENTINEL]); 11139 var i; 11140 for (i = 0; i < prevKeys.length - 1; i++) { 11141 var prevKey = prevKeys[i]; 11142 if (next[prevKey]) { 11143 continue; 11144 } 11145 11146 // This key is not in the new set. Place it in our 11147 // best guess where it should go. We do this by searching 11148 // for a key after the current one in prevKeys that is 11149 // still in nextKeys, and inserting right before it. 11150 // I know this is O(n^2), but this is not a particularly 11151 // hot code path. 11152 var insertPos = -1; 11153 11154 for (var j = i + 1; j < prevKeys.length; j++) { 11155 insertPos = nextKeys.indexOf(prevKeys[j]); 11156 if (insertPos >= 0) { 11157 break; 11158 } 11159 } 11160 11161 // Insert before insertPos 11162 nextKeys.splice(insertPos, 0, prevKey); 11163 } 11164 11165 for (i = 0; i < nextKeys.length - 1; i++) { 11166 keySet[nextKeys[i]] = true; 11167 } 11168 11169 return keySet; 11170 } 11171 }; 11172 11173 module.exports = ReactTransitionKeySet; 11174 11175 },{"./ReactChildren":27}],69:[function(require,module,exports){ 11176 /** 11177 * Copyright 2013 Facebook, Inc. 11178 * 11179 * Licensed under the Apache License, Version 2.0 (the "License"); 11180 * you may not use this file except in compliance with the License. 11181 * You may obtain a copy of the License at 11182 * 11183 * http://www.apache.org/licenses/LICENSE-2.0 11184 * 11185 * Unless required by applicable law or agreed to in writing, software 11186 * distributed under the License is distributed on an "AS IS" BASIS, 11187 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11188 * See the License for the specific language governing permissions and 11189 * limitations under the License. 11190 * 11191 * @providesModule ReactTransitionableChild 11192 */ 11193 11194 "use strict"; 11195 11196 var React = require("./React"); 11197 var CSSCore = require("./CSSCore"); 11198 var ReactTransitionEvents = require("./ReactTransitionEvents"); 11199 11200 // We don't remove the element from the DOM until we receive an animationend or 11201 // transitionend event. If the user screws up and forgets to add an animation 11202 // their node will be stuck in the DOM forever, so we detect if an animation 11203 // does not start and if it doesn't, we just call the end listener immediately. 11204 var TICK = 17; 11205 var NO_EVENT_TIMEOUT = 5000; 11206 11207 var noEventListener = null; 11208 11209 if ("production" !== "development") { 11210 noEventListener = function() { 11211 console.warn( 11212 'transition(): tried to perform an animation without ' + 11213 'an animationend or transitionend event after timeout (' + 11214 NO_EVENT_TIMEOUT + 'ms). You should either disable this ' + 11215 'transition in JS or add a CSS animation/transition.' 11216 ); 11217 }; 11218 } 11219 11220 /** 11221 * This component is simply responsible for watching when its single child 11222 * changes to undefined and animating the old child out. It does this by 11223 * recording its old child in savedChildren when it detects this event is about 11224 * to occur. 11225 */ 11226 var ReactTransitionableChild = React.createClass({ 11227 /** 11228 * Perform an actual DOM transition. This takes care of a few things: 11229 * - Adding the second CSS class to trigger the transition 11230 * - Listening for the finish event 11231 * - Cleaning up the css (unless noReset is true) 11232 */ 11233 transition: function(animationType, noReset, finishCallback) { 11234 var node = this.getDOMNode(); 11235 var className = this.props.name + '-' + animationType; 11236 var activeClassName = className + '-active'; 11237 var noEventTimeout = null; 11238 11239 var endListener = function() { 11240 if ("production" !== "development") { 11241 clearTimeout(noEventTimeout); 11242 } 11243 11244 // If this gets invoked after the component is unmounted it's OK. 11245 if (!noReset) { 11246 // Usually this means you're about to remove the node if you want to 11247 // leave it in its animated state. 11248 CSSCore.removeClass(node, className); 11249 CSSCore.removeClass(node, activeClassName); 11250 } 11251 11252 ReactTransitionEvents.removeEndEventListener(node, endListener); 11253 11254 // Usually this optional callback is used for informing an owner of 11255 // a leave animation and telling it to remove the child. 11256 finishCallback && finishCallback(); 11257 }; 11258 11259 ReactTransitionEvents.addEndEventListener(node, endListener); 11260 11261 CSSCore.addClass(node, className); 11262 11263 // Need to do this to actually trigger a transition. 11264 this.queueClass(activeClassName); 11265 11266 if ("production" !== "development") { 11267 noEventTimeout = setTimeout(noEventListener, NO_EVENT_TIMEOUT); 11268 } 11269 }, 11270 11271 queueClass: function(className) { 11272 this.classNameQueue.push(className); 11273 11274 if (this.props.runNextTick) { 11275 this.props.runNextTick(this.flushClassNameQueue); 11276 return; 11277 } 11278 11279 if (!this.timeout) { 11280 this.timeout = setTimeout(this.flushClassNameQueue, TICK); 11281 } 11282 }, 11283 11284 flushClassNameQueue: function() { 11285 if (this.isMounted()) { 11286 this.classNameQueue.forEach( 11287 CSSCore.addClass.bind(CSSCore, this.getDOMNode()) 11288 ); 11289 } 11290 this.classNameQueue.length = 0; 11291 this.timeout = null; 11292 }, 11293 11294 componentWillMount: function() { 11295 this.classNameQueue = []; 11296 }, 11297 11298 componentWillUnmount: function() { 11299 if (this.timeout) { 11300 clearTimeout(this.timeout); 11301 } 11302 }, 11303 11304 componentWillReceiveProps: function(nextProps) { 11305 if (!nextProps.children && this.props.children) { 11306 this.savedChildren = this.props.children; 11307 } 11308 }, 11309 11310 componentDidMount: function(node) { 11311 if (this.props.enter) { 11312 this.transition('enter'); 11313 } 11314 }, 11315 11316 componentDidUpdate: function(prevProps, prevState, node) { 11317 if (prevProps.children && !this.props.children) { 11318 this.transition('leave', true, this.props.onDoneLeaving); 11319 } 11320 }, 11321 11322 render: function() { 11323 return this.props.children || this.savedChildren; 11324 } 11325 }); 11326 11327 module.exports = ReactTransitionableChild; 11328 11329 },{"./CSSCore":2,"./React":26,"./ReactTransitionEvents":66}],70:[function(require,module,exports){ 11330 /** 11331 * Copyright 2013 Facebook, Inc. 11332 * 11333 * Licensed under the Apache License, Version 2.0 (the "License"); 11334 * you may not use this file except in compliance with the License. 11335 * You may obtain a copy of the License at 11336 * 11337 * http://www.apache.org/licenses/LICENSE-2.0 11338 * 11339 * Unless required by applicable law or agreed to in writing, software 11340 * distributed under the License is distributed on an "AS IS" BASIS, 11341 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11342 * See the License for the specific language governing permissions and 11343 * limitations under the License. 11344 * 11345 * @providesModule ReactUpdates 11346 */ 11347 11348 "use strict"; 11349 11350 var invariant = require("./invariant"); 11351 11352 var dirtyComponents = []; 11353 11354 var batchingStrategy = null; 11355 11356 function ensureBatchingStrategy() { 11357 ("production" !== "development" ? invariant(batchingStrategy, 'ReactUpdates: must inject a batching strategy') : invariant(batchingStrategy)); 11358 } 11359 11360 function batchedUpdates(callback, param) { 11361 ensureBatchingStrategy(); 11362 batchingStrategy.batchedUpdates(callback, param); 11363 } 11364 11365 /** 11366 * Array comparator for ReactComponents by owner depth 11367 * 11368 * @param {ReactComponent} c1 first component you're comparing 11369 * @param {ReactComponent} c2 second component you're comparing 11370 * @return {number} Return value usable by Array.prototype.sort(). 11371 */ 11372 function mountDepthComparator(c1, c2) { 11373 return c1._mountDepth - c2._mountDepth; 11374 } 11375 11376 function runBatchedUpdates() { 11377 // Since reconciling a component higher in the owner hierarchy usually (not 11378 // always -- see shouldComponentUpdate()) will reconcile children, reconcile 11379 // them before their children by sorting the array. 11380 11381 dirtyComponents.sort(mountDepthComparator); 11382 11383 for (var i = 0; i < dirtyComponents.length; i++) { 11384 // If a component is unmounted before pending changes apply, ignore them 11385 // TODO: Queue unmounts in the same list to avoid this happening at all 11386 var component = dirtyComponents[i]; 11387 if (component.isMounted()) { 11388 // If performUpdateIfNecessary happens to enqueue any new updates, we 11389 // shouldn't execute the callbacks until the next render happens, so 11390 // stash the callbacks first 11391 var callbacks = component._pendingCallbacks; 11392 component._pendingCallbacks = null; 11393 component.performUpdateIfNecessary(); 11394 if (callbacks) { 11395 for (var j = 0; j < callbacks.length; j++) { 11396 callbacks[j].call(component); 11397 } 11398 } 11399 } 11400 } 11401 } 11402 11403 function clearDirtyComponents() { 11404 dirtyComponents.length = 0; 11405 } 11406 11407 function flushBatchedUpdates() { 11408 // Run these in separate functions so the JIT can optimize 11409 try { 11410 runBatchedUpdates(); 11411 } catch (e) { 11412 // IE 8 requires catch to use finally. 11413 throw e; 11414 } finally { 11415 clearDirtyComponents(); 11416 } 11417 } 11418 11419 /** 11420 * Mark a component as needing a rerender, adding an optional callback to a 11421 * list of functions which will be executed once the rerender occurs. 11422 */ 11423 function enqueueUpdate(component, callback) { 11424 ("production" !== "development" ? invariant( 11425 !callback || typeof callback === "function", 11426 'enqueueUpdate(...): You called `setProps`, `replaceProps`, ' + 11427 '`setState`, `replaceState`, or `forceUpdate` with a callback that ' + 11428 'isn\'t callable.' 11429 ) : invariant(!callback || typeof callback === "function")); 11430 ensureBatchingStrategy(); 11431 11432 if (!batchingStrategy.isBatchingUpdates) { 11433 component.performUpdateIfNecessary(); 11434 callback && callback(); 11435 return; 11436 } 11437 11438 dirtyComponents.push(component); 11439 11440 if (callback) { 11441 if (component._pendingCallbacks) { 11442 component._pendingCallbacks.push(callback); 11443 } else { 11444 component._pendingCallbacks = [callback]; 11445 } 11446 } 11447 } 11448 11449 var ReactUpdatesInjection = { 11450 injectBatchingStrategy: function(_batchingStrategy) { 11451 ("production" !== "development" ? invariant( 11452 _batchingStrategy, 11453 'ReactUpdates: must provide a batching strategy' 11454 ) : invariant(_batchingStrategy)); 11455 ("production" !== "development" ? invariant( 11456 typeof _batchingStrategy.batchedUpdates === 'function', 11457 'ReactUpdates: must provide a batchedUpdates() function' 11458 ) : invariant(typeof _batchingStrategy.batchedUpdates === 'function')); 11459 ("production" !== "development" ? invariant( 11460 typeof _batchingStrategy.isBatchingUpdates === 'boolean', 11461 'ReactUpdates: must provide an isBatchingUpdates boolean attribute' 11462 ) : invariant(typeof _batchingStrategy.isBatchingUpdates === 'boolean')); 11463 batchingStrategy = _batchingStrategy; 11464 } 11465 }; 11466 11467 var ReactUpdates = { 11468 batchedUpdates: batchedUpdates, 11469 enqueueUpdate: enqueueUpdate, 11470 flushBatchedUpdates: flushBatchedUpdates, 11471 injection: ReactUpdatesInjection 11472 }; 11473 11474 module.exports = ReactUpdates; 11475 11476 },{"./invariant":109}],71:[function(require,module,exports){ 11477 /** 11478 * Copyright 2013 Facebook, Inc. 11479 * 11480 * Licensed under the Apache License, Version 2.0 (the "License"); 11481 * you may not use this file except in compliance with the License. 11482 * You may obtain a copy of the License at 11483 * 11484 * http://www.apache.org/licenses/LICENSE-2.0 11485 * 11486 * Unless required by applicable law or agreed to in writing, software 11487 * distributed under the License is distributed on an "AS IS" BASIS, 11488 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11489 * See the License for the specific language governing permissions and 11490 * limitations under the License. 11491 * 11492 * @providesModule ReactWithAddons 11493 */ 11494 11495 /** 11496 * This module exists purely in the open source project, and is meant as a way 11497 * to create a separate standalone build of React. This build has "addons", or 11498 * functionality we've built and think might be useful but doesn't have a good 11499 * place to live inside React core. 11500 */ 11501 11502 "use strict"; 11503 11504 var LinkedStateMixin = require("./LinkedStateMixin"); 11505 var React = require("./React"); 11506 var ReactTransitionGroup = require("./ReactTransitionGroup"); 11507 11508 var cx = require("./cx"); 11509 11510 React.addons = { 11511 classSet: cx, 11512 LinkedStateMixin: LinkedStateMixin, 11513 TransitionGroup: ReactTransitionGroup 11514 }; 11515 11516 module.exports = React; 11517 11518 11519 },{"./LinkedStateMixin":22,"./React":26,"./ReactTransitionGroup":67,"./cx":92}],72:[function(require,module,exports){ 11520 /** 11521 * Copyright 2013 Facebook, Inc. 11522 * 11523 * Licensed under the Apache License, Version 2.0 (the "License"); 11524 * you may not use this file except in compliance with the License. 11525 * You may obtain a copy of the License at 11526 * 11527 * http://www.apache.org/licenses/LICENSE-2.0 11528 * 11529 * Unless required by applicable law or agreed to in writing, software 11530 * distributed under the License is distributed on an "AS IS" BASIS, 11531 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11532 * See the License for the specific language governing permissions and 11533 * limitations under the License. 11534 * 11535 * @providesModule SelectEventPlugin 11536 */ 11537 11538 "use strict"; 11539 11540 var EventConstants = require("./EventConstants"); 11541 var EventPluginHub = require("./EventPluginHub"); 11542 var EventPropagators = require("./EventPropagators"); 11543 var ExecutionEnvironment = require("./ExecutionEnvironment"); 11544 var ReactInputSelection = require("./ReactInputSelection"); 11545 var SyntheticEvent = require("./SyntheticEvent"); 11546 11547 var getActiveElement = require("./getActiveElement"); 11548 var isTextInputElement = require("./isTextInputElement"); 11549 var keyOf = require("./keyOf"); 11550 var shallowEqual = require("./shallowEqual"); 11551 11552 var topLevelTypes = EventConstants.topLevelTypes; 11553 11554 var eventTypes = { 11555 select: { 11556 phasedRegistrationNames: { 11557 bubbled: keyOf({onSelect: null}), 11558 captured: keyOf({onSelectCapture: null}) 11559 } 11560 } 11561 }; 11562 11563 var useSelectionChange = false; 11564 11565 if (ExecutionEnvironment.canUseDOM) { 11566 useSelectionChange = 'onselectionchange' in document; 11567 } 11568 11569 var activeElement = null; 11570 var activeElementID = null; 11571 var activeNativeEvent = null; 11572 var lastSelection = null; 11573 var mouseDown = false; 11574 11575 /** 11576 * Get an object which is a unique representation of the current selection. 11577 * 11578 * The return value will not be consistent across nodes or browsers, but 11579 * two identical selections on the same node will return identical objects. 11580 * 11581 * @param {DOMElement} node 11582 * @param {object} 11583 */ 11584 function getSelection(node) { 11585 if ('selectionStart' in node && 11586 ReactInputSelection.hasSelectionCapabilities(node)) { 11587 return { 11588 start: node.selectionStart, 11589 end: node.selectionEnd 11590 }; 11591 } else if (document.selection) { 11592 var range = document.selection.createRange(); 11593 return { 11594 parentElement: range.parentElement(), 11595 text: range.text, 11596 top: range.boundingTop, 11597 left: range.boundingLeft 11598 }; 11599 } else { 11600 var selection = window.getSelection(); 11601 return { 11602 anchorNode: selection.anchorNode, 11603 anchorOffset: selection.anchorOffset, 11604 focusNode: selection.focusNode, 11605 focusOffset: selection.focusOffset 11606 }; 11607 } 11608 } 11609 11610 /** 11611 * Poll selection to see whether it's changed. 11612 * 11613 * @param {object} nativeEvent 11614 * @return {?SyntheticEvent} 11615 */ 11616 function constructSelectEvent(nativeEvent) { 11617 // Ensure we have the right element, and that the user is not dragging a 11618 // selection (this matches native `select` event behavior). 11619 if (mouseDown || activeElement != getActiveElement()) { 11620 return; 11621 } 11622 11623 // Only fire when selection has actually changed. 11624 var currentSelection = getSelection(activeElement); 11625 if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { 11626 lastSelection = currentSelection; 11627 11628 var syntheticEvent = SyntheticEvent.getPooled( 11629 eventTypes.select, 11630 activeElementID, 11631 nativeEvent 11632 ); 11633 11634 syntheticEvent.type = 'select'; 11635 syntheticEvent.target = activeElement; 11636 11637 EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent); 11638 11639 return syntheticEvent; 11640 } 11641 } 11642 11643 /** 11644 * Handle deferred event. And manually dispatch synthetic events. 11645 */ 11646 function dispatchDeferredSelectEvent() { 11647 if (!activeNativeEvent) { 11648 return; 11649 } 11650 11651 var syntheticEvent = constructSelectEvent(activeNativeEvent); 11652 activeNativeEvent = null; 11653 11654 // Enqueue and process the abstract event manually. 11655 if (syntheticEvent) { 11656 EventPluginHub.enqueueEvents(syntheticEvent); 11657 EventPluginHub.processEventQueue(); 11658 } 11659 } 11660 11661 /** 11662 * This plugin creates an `onSelect` event that normalizes select events 11663 * across form elements. 11664 * 11665 * Supported elements are: 11666 * - input (see `isTextInputElement`) 11667 * - textarea 11668 * - contentEditable 11669 * 11670 * This differs from native browser implementations in the following ways: 11671 * - Fires on contentEditable fields as well as inputs. 11672 * - Fires for collapsed selection. 11673 * - Fires after user input. 11674 */ 11675 var SelectEventPlugin = { 11676 11677 eventTypes: eventTypes, 11678 11679 /** 11680 * @param {string} topLevelType Record from `EventConstants`. 11681 * @param {DOMEventTarget} topLevelTarget The listening component root node. 11682 * @param {string} topLevelTargetID ID of `topLevelTarget`. 11683 * @param {object} nativeEvent Native browser event. 11684 * @return {*} An accumulation of synthetic events. 11685 * @see {EventPluginHub.extractEvents} 11686 */ 11687 extractEvents: function( 11688 topLevelType, 11689 topLevelTarget, 11690 topLevelTargetID, 11691 nativeEvent) { 11692 11693 switch (topLevelType) { 11694 // Track the input node that has focus. 11695 case topLevelTypes.topFocus: 11696 if (isTextInputElement(topLevelTarget) || 11697 topLevelTarget.contentEditable === 'true') { 11698 activeElement = topLevelTarget; 11699 activeElementID = topLevelTargetID; 11700 lastSelection = null; 11701 } 11702 break; 11703 case topLevelTypes.topBlur: 11704 activeElement = null; 11705 activeElementID = null; 11706 lastSelection = null; 11707 break; 11708 11709 // Don't fire the event while the user is dragging. This matches the 11710 // semantics of the native select event. 11711 case topLevelTypes.topMouseDown: 11712 mouseDown = true; 11713 break; 11714 case topLevelTypes.topContextMenu: 11715 case topLevelTypes.topMouseUp: 11716 mouseDown = false; 11717 return constructSelectEvent(nativeEvent); 11718 11719 // Chrome and IE fire non-standard event when selection is changed (and 11720 // sometimes when it hasn't). 11721 case topLevelTypes.topSelectionChange: 11722 return constructSelectEvent(nativeEvent); 11723 11724 // Firefox doesn't support selectionchange, so check selection status 11725 // after each key entry. 11726 case topLevelTypes.topKeyDown: 11727 if (!useSelectionChange) { 11728 activeNativeEvent = nativeEvent; 11729 setTimeout(dispatchDeferredSelectEvent, 0); 11730 } 11731 break; 11732 } 11733 } 11734 }; 11735 11736 module.exports = SelectEventPlugin; 11737 11738 },{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":50,"./SyntheticEvent":76,"./getActiveElement":101,"./isTextInputElement":112,"./keyOf":116,"./shallowEqual":126}],73:[function(require,module,exports){ 11739 /** 11740 * Copyright 2013 Facebook, Inc. 11741 * 11742 * Licensed under the Apache License, Version 2.0 (the "License"); 11743 * you may not use this file except in compliance with the License. 11744 * You may obtain a copy of the License at 11745 * 11746 * http://www.apache.org/licenses/LICENSE-2.0 11747 * 11748 * Unless required by applicable law or agreed to in writing, software 11749 * distributed under the License is distributed on an "AS IS" BASIS, 11750 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11751 * See the License for the specific language governing permissions and 11752 * limitations under the License. 11753 * 11754 * @providesModule SimpleEventPlugin 11755 */ 11756 11757 "use strict"; 11758 11759 var EventConstants = require("./EventConstants"); 11760 var EventPropagators = require("./EventPropagators"); 11761 var SyntheticClipboardEvent = require("./SyntheticClipboardEvent"); 11762 var SyntheticEvent = require("./SyntheticEvent"); 11763 var SyntheticFocusEvent = require("./SyntheticFocusEvent"); 11764 var SyntheticKeyboardEvent = require("./SyntheticKeyboardEvent"); 11765 var SyntheticMouseEvent = require("./SyntheticMouseEvent"); 11766 var SyntheticTouchEvent = require("./SyntheticTouchEvent"); 11767 var SyntheticUIEvent = require("./SyntheticUIEvent"); 11768 var SyntheticWheelEvent = require("./SyntheticWheelEvent"); 11769 11770 var invariant = require("./invariant"); 11771 var keyOf = require("./keyOf"); 11772 11773 var topLevelTypes = EventConstants.topLevelTypes; 11774 11775 var eventTypes = { 11776 blur: { 11777 phasedRegistrationNames: { 11778 bubbled: keyOf({onBlur: true}), 11779 captured: keyOf({onBlurCapture: true}) 11780 } 11781 }, 11782 click: { 11783 phasedRegistrationNames: { 11784 bubbled: keyOf({onClick: true}), 11785 captured: keyOf({onClickCapture: true}) 11786 } 11787 }, 11788 contextMenu: { 11789 phasedRegistrationNames: { 11790 bubbled: keyOf({onContextMenu: true}), 11791 captured: keyOf({onContextMenuCapture: true}) 11792 } 11793 }, 11794 copy: { 11795 phasedRegistrationNames: { 11796 bubbled: keyOf({onCopy: true}), 11797 captured: keyOf({onCopyCapture: true}) 11798 } 11799 }, 11800 cut: { 11801 phasedRegistrationNames: { 11802 bubbled: keyOf({onCut: true}), 11803 captured: keyOf({onCutCapture: true}) 11804 } 11805 }, 11806 doubleClick: { 11807 phasedRegistrationNames: { 11808 bubbled: keyOf({onDoubleClick: true}), 11809 captured: keyOf({onDoubleClickCapture: true}) 11810 } 11811 }, 11812 drag: { 11813 phasedRegistrationNames: { 11814 bubbled: keyOf({onDrag: true}), 11815 captured: keyOf({onDragCapture: true}) 11816 } 11817 }, 11818 dragEnd: { 11819 phasedRegistrationNames: { 11820 bubbled: keyOf({onDragEnd: true}), 11821 captured: keyOf({onDragEndCapture: true}) 11822 } 11823 }, 11824 dragEnter: { 11825 phasedRegistrationNames: { 11826 bubbled: keyOf({onDragEnter: true}), 11827 captured: keyOf({onDragEnterCapture: true}) 11828 } 11829 }, 11830 dragExit: { 11831 phasedRegistrationNames: { 11832 bubbled: keyOf({onDragExit: true}), 11833 captured: keyOf({onDragExitCapture: true}) 11834 } 11835 }, 11836 dragLeave: { 11837 phasedRegistrationNames: { 11838 bubbled: keyOf({onDragLeave: true}), 11839 captured: keyOf({onDragLeaveCapture: true}) 11840 } 11841 }, 11842 dragOver: { 11843 phasedRegistrationNames: { 11844 bubbled: keyOf({onDragOver: true}), 11845 captured: keyOf({onDragOverCapture: true}) 11846 } 11847 }, 11848 dragStart: { 11849 phasedRegistrationNames: { 11850 bubbled: keyOf({onDragStart: true}), 11851 captured: keyOf({onDragStartCapture: true}) 11852 } 11853 }, 11854 drop: { 11855 phasedRegistrationNames: { 11856 bubbled: keyOf({onDrop: true}), 11857 captured: keyOf({onDropCapture: true}) 11858 } 11859 }, 11860 focus: { 11861 phasedRegistrationNames: { 11862 bubbled: keyOf({onFocus: true}), 11863 captured: keyOf({onFocusCapture: true}) 11864 } 11865 }, 11866 input: { 11867 phasedRegistrationNames: { 11868 bubbled: keyOf({onInput: true}), 11869 captured: keyOf({onInputCapture: true}) 11870 } 11871 }, 11872 keyDown: { 11873 phasedRegistrationNames: { 11874 bubbled: keyOf({onKeyDown: true}), 11875 captured: keyOf({onKeyDownCapture: true}) 11876 } 11877 }, 11878 keyPress: { 11879 phasedRegistrationNames: { 11880 bubbled: keyOf({onKeyPress: true}), 11881 captured: keyOf({onKeyPressCapture: true}) 11882 } 11883 }, 11884 keyUp: { 11885 phasedRegistrationNames: { 11886 bubbled: keyOf({onKeyUp: true}), 11887 captured: keyOf({onKeyUpCapture: true}) 11888 } 11889 }, 11890 // Note: We do not allow listening to mouseOver events. Instead, use the 11891 // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`. 11892 mouseDown: { 11893 phasedRegistrationNames: { 11894 bubbled: keyOf({onMouseDown: true}), 11895 captured: keyOf({onMouseDownCapture: true}) 11896 } 11897 }, 11898 mouseMove: { 11899 phasedRegistrationNames: { 11900 bubbled: keyOf({onMouseMove: true}), 11901 captured: keyOf({onMouseMoveCapture: true}) 11902 } 11903 }, 11904 mouseUp: { 11905 phasedRegistrationNames: { 11906 bubbled: keyOf({onMouseUp: true}), 11907 captured: keyOf({onMouseUpCapture: true}) 11908 } 11909 }, 11910 paste: { 11911 phasedRegistrationNames: { 11912 bubbled: keyOf({onPaste: true}), 11913 captured: keyOf({onPasteCapture: true}) 11914 } 11915 }, 11916 scroll: { 11917 phasedRegistrationNames: { 11918 bubbled: keyOf({onScroll: true}), 11919 captured: keyOf({onScrollCapture: true}) 11920 } 11921 }, 11922 submit: { 11923 phasedRegistrationNames: { 11924 bubbled: keyOf({onSubmit: true}), 11925 captured: keyOf({onSubmitCapture: true}) 11926 } 11927 }, 11928 touchCancel: { 11929 phasedRegistrationNames: { 11930 bubbled: keyOf({onTouchCancel: true}), 11931 captured: keyOf({onTouchCancelCapture: true}) 11932 } 11933 }, 11934 touchEnd: { 11935 phasedRegistrationNames: { 11936 bubbled: keyOf({onTouchEnd: true}), 11937 captured: keyOf({onTouchEndCapture: true}) 11938 } 11939 }, 11940 touchMove: { 11941 phasedRegistrationNames: { 11942 bubbled: keyOf({onTouchMove: true}), 11943 captured: keyOf({onTouchMoveCapture: true}) 11944 } 11945 }, 11946 touchStart: { 11947 phasedRegistrationNames: { 11948 bubbled: keyOf({onTouchStart: true}), 11949 captured: keyOf({onTouchStartCapture: true}) 11950 } 11951 }, 11952 wheel: { 11953 phasedRegistrationNames: { 11954 bubbled: keyOf({onWheel: true}), 11955 captured: keyOf({onWheelCapture: true}) 11956 } 11957 } 11958 }; 11959 11960 var topLevelEventsToDispatchConfig = { 11961 topBlur: eventTypes.blur, 11962 topClick: eventTypes.click, 11963 topContextMenu: eventTypes.contextMenu, 11964 topCopy: eventTypes.copy, 11965 topCut: eventTypes.cut, 11966 topDoubleClick: eventTypes.doubleClick, 11967 topDrag: eventTypes.drag, 11968 topDragEnd: eventTypes.dragEnd, 11969 topDragEnter: eventTypes.dragEnter, 11970 topDragExit: eventTypes.dragExit, 11971 topDragLeave: eventTypes.dragLeave, 11972 topDragOver: eventTypes.dragOver, 11973 topDragStart: eventTypes.dragStart, 11974 topDrop: eventTypes.drop, 11975 topFocus: eventTypes.focus, 11976 topInput: eventTypes.input, 11977 topKeyDown: eventTypes.keyDown, 11978 topKeyPress: eventTypes.keyPress, 11979 topKeyUp: eventTypes.keyUp, 11980 topMouseDown: eventTypes.mouseDown, 11981 topMouseMove: eventTypes.mouseMove, 11982 topMouseUp: eventTypes.mouseUp, 11983 topPaste: eventTypes.paste, 11984 topScroll: eventTypes.scroll, 11985 topSubmit: eventTypes.submit, 11986 topTouchCancel: eventTypes.touchCancel, 11987 topTouchEnd: eventTypes.touchEnd, 11988 topTouchMove: eventTypes.touchMove, 11989 topTouchStart: eventTypes.touchStart, 11990 topWheel: eventTypes.wheel 11991 }; 11992 11993 var SimpleEventPlugin = { 11994 11995 eventTypes: eventTypes, 11996 11997 /** 11998 * Same as the default implementation, except cancels the event when return 11999 * value is false. 12000 * 12001 * @param {object} Event to be dispatched. 12002 * @param {function} Application-level callback. 12003 * @param {string} domID DOM ID to pass to the callback. 12004 */ 12005 executeDispatch: function(event, listener, domID) { 12006 var returnValue = listener(event, domID); 12007 if (returnValue === false) { 12008 event.stopPropagation(); 12009 event.preventDefault(); 12010 } 12011 }, 12012 12013 /** 12014 * @param {string} topLevelType Record from `EventConstants`. 12015 * @param {DOMEventTarget} topLevelTarget The listening component root node. 12016 * @param {string} topLevelTargetID ID of `topLevelTarget`. 12017 * @param {object} nativeEvent Native browser event. 12018 * @return {*} An accumulation of synthetic events. 12019 * @see {EventPluginHub.extractEvents} 12020 */ 12021 extractEvents: function( 12022 topLevelType, 12023 topLevelTarget, 12024 topLevelTargetID, 12025 nativeEvent) { 12026 var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; 12027 if (!dispatchConfig) { 12028 return null; 12029 } 12030 var EventConstructor; 12031 switch(topLevelType) { 12032 case topLevelTypes.topInput: 12033 case topLevelTypes.topSubmit: 12034 // HTML Events 12035 // @see http://www.w3.org/TR/html5/index.html#events-0 12036 EventConstructor = SyntheticEvent; 12037 break; 12038 case topLevelTypes.topKeyDown: 12039 case topLevelTypes.topKeyPress: 12040 case topLevelTypes.topKeyUp: 12041 EventConstructor = SyntheticKeyboardEvent; 12042 break; 12043 case topLevelTypes.topBlur: 12044 case topLevelTypes.topFocus: 12045 EventConstructor = SyntheticFocusEvent; 12046 break; 12047 case topLevelTypes.topClick: 12048 // Firefox creates a click event on right mouse clicks. This removes the 12049 // unwanted click events. 12050 if (nativeEvent.button === 2) { 12051 return null; 12052 } 12053 /* falls through */ 12054 case topLevelTypes.topContextMenu: 12055 case topLevelTypes.topDoubleClick: 12056 case topLevelTypes.topDrag: 12057 case topLevelTypes.topDragEnd: 12058 case topLevelTypes.topDragEnter: 12059 case topLevelTypes.topDragExit: 12060 case topLevelTypes.topDragLeave: 12061 case topLevelTypes.topDragOver: 12062 case topLevelTypes.topDragStart: 12063 case topLevelTypes.topDrop: 12064 case topLevelTypes.topMouseDown: 12065 case topLevelTypes.topMouseMove: 12066 case topLevelTypes.topMouseUp: 12067 EventConstructor = SyntheticMouseEvent; 12068 break; 12069 case topLevelTypes.topTouchCancel: 12070 case topLevelTypes.topTouchEnd: 12071 case topLevelTypes.topTouchMove: 12072 case topLevelTypes.topTouchStart: 12073 EventConstructor = SyntheticTouchEvent; 12074 break; 12075 case topLevelTypes.topScroll: 12076 EventConstructor = SyntheticUIEvent; 12077 break; 12078 case topLevelTypes.topWheel: 12079 EventConstructor = SyntheticWheelEvent; 12080 break; 12081 case topLevelTypes.topCopy: 12082 case topLevelTypes.topCut: 12083 case topLevelTypes.topPaste: 12084 EventConstructor = SyntheticClipboardEvent; 12085 break; 12086 } 12087 ("production" !== "development" ? invariant( 12088 EventConstructor, 12089 'SimpleEventPlugin: Unhandled event type, `%s`.', 12090 topLevelType 12091 ) : invariant(EventConstructor)); 12092 var event = EventConstructor.getPooled( 12093 dispatchConfig, 12094 topLevelTargetID, 12095 nativeEvent 12096 ); 12097 EventPropagators.accumulateTwoPhaseDispatches(event); 12098 return event; 12099 } 12100 12101 }; 12102 12103 module.exports = SimpleEventPlugin; 12104 12105 },{"./EventConstants":15,"./EventPropagators":20,"./SyntheticClipboardEvent":74,"./SyntheticEvent":76,"./SyntheticFocusEvent":77,"./SyntheticKeyboardEvent":78,"./SyntheticMouseEvent":79,"./SyntheticTouchEvent":80,"./SyntheticUIEvent":81,"./SyntheticWheelEvent":82,"./invariant":109,"./keyOf":116}],74:[function(require,module,exports){ 12106 /** 12107 * Copyright 2013 Facebook, Inc. 12108 * 12109 * Licensed under the Apache License, Version 2.0 (the "License"); 12110 * you may not use this file except in compliance with the License. 12111 * You may obtain a copy of the License at 12112 * 12113 * http://www.apache.org/licenses/LICENSE-2.0 12114 * 12115 * Unless required by applicable law or agreed to in writing, software 12116 * distributed under the License is distributed on an "AS IS" BASIS, 12117 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12118 * See the License for the specific language governing permissions and 12119 * limitations under the License. 12120 * 12121 * @providesModule SyntheticClipboardEvent 12122 * @typechecks static-only 12123 */ 12124 12125 "use strict"; 12126 12127 var SyntheticEvent = require("./SyntheticEvent"); 12128 12129 /** 12130 * @interface Event 12131 * @see http://www.w3.org/TR/clipboard-apis/ 12132 */ 12133 var ClipboardEventInterface = { 12134 clipboardData: null 12135 }; 12136 12137 /** 12138 * @param {object} dispatchConfig Configuration used to dispatch this event. 12139 * @param {string} dispatchMarker Marker identifying the event target. 12140 * @param {object} nativeEvent Native browser event. 12141 * @extends {SyntheticUIEvent} 12142 */ 12143 function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12144 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12145 } 12146 12147 SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface); 12148 12149 module.exports = SyntheticClipboardEvent; 12150 12151 12152 },{"./SyntheticEvent":76}],75:[function(require,module,exports){ 12153 /** 12154 * Copyright 2013 Facebook, Inc. 12155 * 12156 * Licensed under the Apache License, Version 2.0 (the "License"); 12157 * you may not use this file except in compliance with the License. 12158 * You may obtain a copy of the License at 12159 * 12160 * http://www.apache.org/licenses/LICENSE-2.0 12161 * 12162 * Unless required by applicable law or agreed to in writing, software 12163 * distributed under the License is distributed on an "AS IS" BASIS, 12164 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12165 * See the License for the specific language governing permissions and 12166 * limitations under the License. 12167 * 12168 * @providesModule SyntheticCompositionEvent 12169 * @typechecks static-only 12170 */ 12171 12172 "use strict"; 12173 12174 var SyntheticEvent = require("./SyntheticEvent"); 12175 12176 /** 12177 * @interface Event 12178 * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents 12179 */ 12180 var CompositionEventInterface = { 12181 data: null 12182 }; 12183 12184 /** 12185 * @param {object} dispatchConfig Configuration used to dispatch this event. 12186 * @param {string} dispatchMarker Marker identifying the event target. 12187 * @param {object} nativeEvent Native browser event. 12188 * @extends {SyntheticUIEvent} 12189 */ 12190 function SyntheticCompositionEvent( 12191 dispatchConfig, 12192 dispatchMarker, 12193 nativeEvent) { 12194 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12195 } 12196 12197 SyntheticEvent.augmentClass( 12198 SyntheticCompositionEvent, 12199 CompositionEventInterface 12200 ); 12201 12202 module.exports = SyntheticCompositionEvent; 12203 12204 12205 },{"./SyntheticEvent":76}],76:[function(require,module,exports){ 12206 /** 12207 * Copyright 2013 Facebook, Inc. 12208 * 12209 * Licensed under the Apache License, Version 2.0 (the "License"); 12210 * you may not use this file except in compliance with the License. 12211 * You may obtain a copy of the License at 12212 * 12213 * http://www.apache.org/licenses/LICENSE-2.0 12214 * 12215 * Unless required by applicable law or agreed to in writing, software 12216 * distributed under the License is distributed on an "AS IS" BASIS, 12217 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12218 * See the License for the specific language governing permissions and 12219 * limitations under the License. 12220 * 12221 * @providesModule SyntheticEvent 12222 * @typechecks static-only 12223 */ 12224 12225 "use strict"; 12226 12227 var PooledClass = require("./PooledClass"); 12228 12229 var emptyFunction = require("./emptyFunction"); 12230 var getEventTarget = require("./getEventTarget"); 12231 var merge = require("./merge"); 12232 var mergeInto = require("./mergeInto"); 12233 12234 /** 12235 * @interface Event 12236 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12237 */ 12238 var EventInterface = { 12239 type: null, 12240 target: getEventTarget, 12241 currentTarget: null, 12242 eventPhase: null, 12243 bubbles: null, 12244 cancelable: null, 12245 timeStamp: function(event) { 12246 return event.timeStamp || Date.now(); 12247 }, 12248 defaultPrevented: null, 12249 isTrusted: null 12250 }; 12251 12252 /** 12253 * Synthetic events are dispatched by event plugins, typically in response to a 12254 * top-level event delegation handler. 12255 * 12256 * These systems should generally use pooling to reduce the frequency of garbage 12257 * collection. The system should check `isPersistent` to determine whether the 12258 * event should be released into the pool after being dispatched. Users that 12259 * need a persisted event should invoke `persist`. 12260 * 12261 * Synthetic events (and subclasses) implement the DOM Level 3 Events API by 12262 * normalizing browser quirks. Subclasses do not necessarily have to implement a 12263 * DOM interface; custom application-specific events can also subclass this. 12264 * 12265 * @param {object} dispatchConfig Configuration used to dispatch this event. 12266 * @param {string} dispatchMarker Marker identifying the event target. 12267 * @param {object} nativeEvent Native browser event. 12268 */ 12269 function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12270 this.dispatchConfig = dispatchConfig; 12271 this.dispatchMarker = dispatchMarker; 12272 this.nativeEvent = nativeEvent; 12273 12274 var Interface = this.constructor.Interface; 12275 for (var propName in Interface) { 12276 if (!Interface.hasOwnProperty(propName)) { 12277 continue; 12278 } 12279 var normalize = Interface[propName]; 12280 if (normalize) { 12281 this[propName] = normalize(nativeEvent); 12282 } else { 12283 this[propName] = nativeEvent[propName]; 12284 } 12285 } 12286 12287 var defaultPrevented = nativeEvent.defaultPrevented != null ? 12288 nativeEvent.defaultPrevented : 12289 nativeEvent.returnValue === false; 12290 if (defaultPrevented) { 12291 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 12292 } else { 12293 this.isDefaultPrevented = emptyFunction.thatReturnsFalse; 12294 } 12295 this.isPropagationStopped = emptyFunction.thatReturnsFalse; 12296 } 12297 12298 mergeInto(SyntheticEvent.prototype, { 12299 12300 preventDefault: function() { 12301 this.defaultPrevented = true; 12302 var event = this.nativeEvent; 12303 event.preventDefault ? event.preventDefault() : event.returnValue = false; 12304 this.isDefaultPrevented = emptyFunction.thatReturnsTrue; 12305 }, 12306 12307 stopPropagation: function() { 12308 var event = this.nativeEvent; 12309 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; 12310 this.isPropagationStopped = emptyFunction.thatReturnsTrue; 12311 }, 12312 12313 /** 12314 * We release all dispatched `SyntheticEvent`s after each event loop, adding 12315 * them back into the pool. This allows a way to hold onto a reference that 12316 * won't be added back into the pool. 12317 */ 12318 persist: function() { 12319 this.isPersistent = emptyFunction.thatReturnsTrue; 12320 }, 12321 12322 /** 12323 * Checks if this event should be released back into the pool. 12324 * 12325 * @return {boolean} True if this should not be released, false otherwise. 12326 */ 12327 isPersistent: emptyFunction.thatReturnsFalse, 12328 12329 /** 12330 * `PooledClass` looks for `destructor` on each instance it releases. 12331 */ 12332 destructor: function() { 12333 var Interface = this.constructor.Interface; 12334 for (var propName in Interface) { 12335 this[propName] = null; 12336 } 12337 this.dispatchConfig = null; 12338 this.dispatchMarker = null; 12339 this.nativeEvent = null; 12340 } 12341 12342 }); 12343 12344 SyntheticEvent.Interface = EventInterface; 12345 12346 /** 12347 * Helper to reduce boilerplate when creating subclasses. 12348 * 12349 * @param {function} Class 12350 * @param {?object} Interface 12351 */ 12352 SyntheticEvent.augmentClass = function(Class, Interface) { 12353 var Super = this; 12354 12355 var prototype = Object.create(Super.prototype); 12356 mergeInto(prototype, Class.prototype); 12357 Class.prototype = prototype; 12358 Class.prototype.constructor = Class; 12359 12360 Class.Interface = merge(Super.Interface, Interface); 12361 Class.augmentClass = Super.augmentClass; 12362 12363 PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler); 12364 }; 12365 12366 PooledClass.addPoolingTo(SyntheticEvent, PooledClass.threeArgumentPooler); 12367 12368 module.exports = SyntheticEvent; 12369 12370 },{"./PooledClass":25,"./emptyFunction":94,"./getEventTarget":102,"./merge":118,"./mergeInto":120}],77:[function(require,module,exports){ 12371 /** 12372 * Copyright 2013 Facebook, Inc. 12373 * 12374 * Licensed under the Apache License, Version 2.0 (the "License"); 12375 * you may not use this file except in compliance with the License. 12376 * You may obtain a copy of the License at 12377 * 12378 * http://www.apache.org/licenses/LICENSE-2.0 12379 * 12380 * Unless required by applicable law or agreed to in writing, software 12381 * distributed under the License is distributed on an "AS IS" BASIS, 12382 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12383 * See the License for the specific language governing permissions and 12384 * limitations under the License. 12385 * 12386 * @providesModule SyntheticFocusEvent 12387 * @typechecks static-only 12388 */ 12389 12390 "use strict"; 12391 12392 var SyntheticUIEvent = require("./SyntheticUIEvent"); 12393 12394 /** 12395 * @interface FocusEvent 12396 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12397 */ 12398 var FocusEventInterface = { 12399 relatedTarget: null 12400 }; 12401 12402 /** 12403 * @param {object} dispatchConfig Configuration used to dispatch this event. 12404 * @param {string} dispatchMarker Marker identifying the event target. 12405 * @param {object} nativeEvent Native browser event. 12406 * @extends {SyntheticUIEvent} 12407 */ 12408 function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12409 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12410 } 12411 12412 SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface); 12413 12414 module.exports = SyntheticFocusEvent; 12415 12416 },{"./SyntheticUIEvent":81}],78:[function(require,module,exports){ 12417 /** 12418 * Copyright 2013 Facebook, Inc. 12419 * 12420 * Licensed under the Apache License, Version 2.0 (the "License"); 12421 * you may not use this file except in compliance with the License. 12422 * You may obtain a copy of the License at 12423 * 12424 * http://www.apache.org/licenses/LICENSE-2.0 12425 * 12426 * Unless required by applicable law or agreed to in writing, software 12427 * distributed under the License is distributed on an "AS IS" BASIS, 12428 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12429 * See the License for the specific language governing permissions and 12430 * limitations under the License. 12431 * 12432 * @providesModule SyntheticKeyboardEvent 12433 * @typechecks static-only 12434 */ 12435 12436 "use strict"; 12437 12438 var SyntheticUIEvent = require("./SyntheticUIEvent"); 12439 12440 /** 12441 * @interface KeyboardEvent 12442 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12443 */ 12444 var KeyboardEventInterface = { 12445 'char': null, 12446 key: null, 12447 location: null, 12448 ctrlKey: null, 12449 shiftKey: null, 12450 altKey: null, 12451 metaKey: null, 12452 repeat: null, 12453 locale: null, 12454 // Legacy Interface 12455 charCode: null, 12456 keyCode: null, 12457 which: null 12458 }; 12459 12460 /** 12461 * @param {object} dispatchConfig Configuration used to dispatch this event. 12462 * @param {string} dispatchMarker Marker identifying the event target. 12463 * @param {object} nativeEvent Native browser event. 12464 * @extends {SyntheticUIEvent} 12465 */ 12466 function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12467 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12468 } 12469 12470 SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface); 12471 12472 module.exports = SyntheticKeyboardEvent; 12473 12474 },{"./SyntheticUIEvent":81}],79:[function(require,module,exports){ 12475 /** 12476 * Copyright 2013 Facebook, Inc. 12477 * 12478 * Licensed under the Apache License, Version 2.0 (the "License"); 12479 * you may not use this file except in compliance with the License. 12480 * You may obtain a copy of the License at 12481 * 12482 * http://www.apache.org/licenses/LICENSE-2.0 12483 * 12484 * Unless required by applicable law or agreed to in writing, software 12485 * distributed under the License is distributed on an "AS IS" BASIS, 12486 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12487 * See the License for the specific language governing permissions and 12488 * limitations under the License. 12489 * 12490 * @providesModule SyntheticMouseEvent 12491 * @typechecks static-only 12492 */ 12493 12494 "use strict"; 12495 12496 var SyntheticUIEvent = require("./SyntheticUIEvent"); 12497 var ViewportMetrics = require("./ViewportMetrics"); 12498 12499 /** 12500 * @interface MouseEvent 12501 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12502 */ 12503 var MouseEventInterface = { 12504 screenX: null, 12505 screenY: null, 12506 clientX: null, 12507 clientY: null, 12508 ctrlKey: null, 12509 shiftKey: null, 12510 altKey: null, 12511 metaKey: null, 12512 button: function(event) { 12513 // Webkit, Firefox, IE9+ 12514 // which: 1 2 3 12515 // button: 0 1 2 (standard) 12516 var button = event.button; 12517 if ('which' in event) { 12518 return button; 12519 } 12520 // IE<9 12521 // which: undefined 12522 // button: 0 0 0 12523 // button: 1 4 2 (onmouseup) 12524 return button === 2 ? 2 : button === 4 ? 1 : 0; 12525 }, 12526 buttons: null, 12527 relatedTarget: function(event) { 12528 return event.relatedTarget || ( 12529 event.fromElement === event.srcElement ? 12530 event.toElement : 12531 event.fromElement 12532 ); 12533 }, 12534 // "Proprietary" Interface. 12535 pageX: function(event) { 12536 return 'pageX' in event ? 12537 event.pageX : 12538 event.clientX + ViewportMetrics.currentScrollLeft; 12539 }, 12540 pageY: function(event) { 12541 return 'pageY' in event ? 12542 event.pageY : 12543 event.clientY + ViewportMetrics.currentScrollTop; 12544 } 12545 }; 12546 12547 /** 12548 * @param {object} dispatchConfig Configuration used to dispatch this event. 12549 * @param {string} dispatchMarker Marker identifying the event target. 12550 * @param {object} nativeEvent Native browser event. 12551 * @extends {SyntheticUIEvent} 12552 */ 12553 function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12554 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12555 } 12556 12557 SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface); 12558 12559 module.exports = SyntheticMouseEvent; 12560 12561 },{"./SyntheticUIEvent":81,"./ViewportMetrics":84}],80:[function(require,module,exports){ 12562 /** 12563 * Copyright 2013 Facebook, Inc. 12564 * 12565 * Licensed under the Apache License, Version 2.0 (the "License"); 12566 * you may not use this file except in compliance with the License. 12567 * You may obtain a copy of the License at 12568 * 12569 * http://www.apache.org/licenses/LICENSE-2.0 12570 * 12571 * Unless required by applicable law or agreed to in writing, software 12572 * distributed under the License is distributed on an "AS IS" BASIS, 12573 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12574 * See the License for the specific language governing permissions and 12575 * limitations under the License. 12576 * 12577 * @providesModule SyntheticTouchEvent 12578 * @typechecks static-only 12579 */ 12580 12581 "use strict"; 12582 12583 var SyntheticUIEvent = require("./SyntheticUIEvent"); 12584 12585 /** 12586 * @interface TouchEvent 12587 * @see http://www.w3.org/TR/touch-events/ 12588 */ 12589 var TouchEventInterface = { 12590 touches: null, 12591 targetTouches: null, 12592 changedTouches: null, 12593 altKey: null, 12594 metaKey: null, 12595 ctrlKey: null, 12596 shiftKey: null 12597 }; 12598 12599 /** 12600 * @param {object} dispatchConfig Configuration used to dispatch this event. 12601 * @param {string} dispatchMarker Marker identifying the event target. 12602 * @param {object} nativeEvent Native browser event. 12603 * @extends {SyntheticUIEvent} 12604 */ 12605 function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12606 SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12607 } 12608 12609 SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface); 12610 12611 module.exports = SyntheticTouchEvent; 12612 12613 },{"./SyntheticUIEvent":81}],81:[function(require,module,exports){ 12614 /** 12615 * Copyright 2013 Facebook, Inc. 12616 * 12617 * Licensed under the Apache License, Version 2.0 (the "License"); 12618 * you may not use this file except in compliance with the License. 12619 * You may obtain a copy of the License at 12620 * 12621 * http://www.apache.org/licenses/LICENSE-2.0 12622 * 12623 * Unless required by applicable law or agreed to in writing, software 12624 * distributed under the License is distributed on an "AS IS" BASIS, 12625 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12626 * See the License for the specific language governing permissions and 12627 * limitations under the License. 12628 * 12629 * @providesModule SyntheticUIEvent 12630 * @typechecks static-only 12631 */ 12632 12633 "use strict"; 12634 12635 var SyntheticEvent = require("./SyntheticEvent"); 12636 12637 /** 12638 * @interface UIEvent 12639 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12640 */ 12641 var UIEventInterface = { 12642 view: null, 12643 detail: null 12644 }; 12645 12646 /** 12647 * @param {object} dispatchConfig Configuration used to dispatch this event. 12648 * @param {string} dispatchMarker Marker identifying the event target. 12649 * @param {object} nativeEvent Native browser event. 12650 * @extends {SyntheticEvent} 12651 */ 12652 function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12653 SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12654 } 12655 12656 SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface); 12657 12658 module.exports = SyntheticUIEvent; 12659 12660 },{"./SyntheticEvent":76}],82:[function(require,module,exports){ 12661 /** 12662 * Copyright 2013 Facebook, Inc. 12663 * 12664 * Licensed under the Apache License, Version 2.0 (the "License"); 12665 * you may not use this file except in compliance with the License. 12666 * You may obtain a copy of the License at 12667 * 12668 * http://www.apache.org/licenses/LICENSE-2.0 12669 * 12670 * Unless required by applicable law or agreed to in writing, software 12671 * distributed under the License is distributed on an "AS IS" BASIS, 12672 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12673 * See the License for the specific language governing permissions and 12674 * limitations under the License. 12675 * 12676 * @providesModule SyntheticWheelEvent 12677 * @typechecks static-only 12678 */ 12679 12680 "use strict"; 12681 12682 var SyntheticMouseEvent = require("./SyntheticMouseEvent"); 12683 12684 /** 12685 * @interface WheelEvent 12686 * @see http://www.w3.org/TR/DOM-Level-3-Events/ 12687 */ 12688 var WheelEventInterface = { 12689 deltaX: function(event) { 12690 // NOTE: IE<9 does not support x-axis delta. 12691 return ( 12692 'deltaX' in event ? event.deltaX : 12693 // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). 12694 'wheelDeltaX' in event ? -event.wheelDeltaX : 0 12695 ); 12696 }, 12697 deltaY: function(event) { 12698 return ( 12699 // Normalize (up is positive). 12700 'deltaY' in event ? -event.deltaY : 12701 // Fallback to `wheelDeltaY` for Webkit. 12702 'wheelDeltaY' in event ? event.wheelDeltaY : 12703 // Fallback to `wheelDelta` for IE<9. 12704 'wheelDelta' in event ? event.wheelDelta : 0 12705 ); 12706 }, 12707 deltaZ: null, 12708 deltaMode: null 12709 }; 12710 12711 /** 12712 * @param {object} dispatchConfig Configuration used to dispatch this event. 12713 * @param {string} dispatchMarker Marker identifying the event target. 12714 * @param {object} nativeEvent Native browser event. 12715 * @extends {SyntheticMouseEvent} 12716 */ 12717 function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent) { 12718 SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent); 12719 } 12720 12721 SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface); 12722 12723 module.exports = SyntheticWheelEvent; 12724 12725 },{"./SyntheticMouseEvent":79}],83:[function(require,module,exports){ 12726 /** 12727 * Copyright 2013 Facebook, Inc. 12728 * 12729 * Licensed under the Apache License, Version 2.0 (the "License"); 12730 * you may not use this file except in compliance with the License. 12731 * You may obtain a copy of the License at 12732 * 12733 * http://www.apache.org/licenses/LICENSE-2.0 12734 * 12735 * Unless required by applicable law or agreed to in writing, software 12736 * distributed under the License is distributed on an "AS IS" BASIS, 12737 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12738 * See the License for the specific language governing permissions and 12739 * limitations under the License. 12740 * 12741 * @providesModule Transaction 12742 */ 12743 12744 "use strict"; 12745 12746 var invariant = require("./invariant"); 12747 12748 /** 12749 * `Transaction` creates a black box that is able to wrap any method such that 12750 * certain invariants are maintained before and after the method is invoked 12751 * (Even if an exception is thrown while invoking the wrapped method). Whoever 12752 * instantiates a transaction can provide enforcers of the invariants at 12753 * creation time. The `Transaction` class itself will supply one additional 12754 * automatic invariant for you - the invariant that any transaction instance 12755 * should not be ran while it is already being ran. You would typically create a 12756 * single instance of a `Transaction` for reuse multiple times, that potentially 12757 * is used to wrap several different methods. Wrappers are extremely simple - 12758 * they only require implementing two methods. 12759 * 12760 * <pre> 12761 * wrappers (injected at creation time) 12762 * + + 12763 * | | 12764 * +-----------------|--------|--------------+ 12765 * | v | | 12766 * | +---------------+ | | 12767 * | +--| wrapper1 |---|----+ | 12768 * | | +---------------+ v | | 12769 * | | +-------------+ | | 12770 * | | +----| wrapper2 |--------+ | 12771 * | | | +-------------+ | | | 12772 * | | | | | | 12773 * | v v v v | wrapper 12774 * | +---+ +---+ +---------+ +---+ +---+ | invariants 12775 * perform(anyMethod) | | | | | | | | | | | | maintained 12776 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|--------> 12777 * | | | | | | | | | | | | 12778 * | | | | | | | | | | | | 12779 * | | | | | | | | | | | | 12780 * | +---+ +---+ +---------+ +---+ +---+ | 12781 * | initialize close | 12782 * +-----------------------------------------+ 12783 * </pre> 12784 * 12785 * Bonus: 12786 * - Reports timing metrics by method name and wrapper index. 12787 * 12788 * Use cases: 12789 * - Preserving the input selection ranges before/after reconciliation. 12790 * Restoring selection even in the event of an unexpected error. 12791 * - Deactivating events while rearranging the DOM, preventing blurs/focuses, 12792 * while guaranteeing that afterwards, the event system is reactivated. 12793 * - Flushing a queue of collected DOM mutations to the main UI thread after a 12794 * reconciliation takes place in a worker thread. 12795 * - Invoking any collected `componentDidRender` callbacks after rendering new 12796 * content. 12797 * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue 12798 * to preserve the `scrollTop` (an automatic scroll aware DOM). 12799 * - (Future use case): Layout calculations before and after DOM upates. 12800 * 12801 * Transactional plugin API: 12802 * - A module that has an `initialize` method that returns any precomputation. 12803 * - and a `close` method that accepts the precomputation. `close` is invoked 12804 * when the wrapped process is completed, or has failed. 12805 * 12806 * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules 12807 * that implement `initialize` and `close`. 12808 * @return {Transaction} Single transaction for reuse in thread. 12809 * 12810 * @class Transaction 12811 */ 12812 var Mixin = { 12813 /** 12814 * Sets up this instance so that it is prepared for collecting metrics. Does 12815 * so such that this setup method may be used on an instance that is already 12816 * initialized, in a way that does not consume additional memory upon reuse. 12817 * That can be useful if you decide to make your subclass of this mixin a 12818 * "PooledClass". 12819 */ 12820 reinitializeTransaction: function() { 12821 this.transactionWrappers = this.getTransactionWrappers(); 12822 if (!this.wrapperInitData) { 12823 this.wrapperInitData = []; 12824 } else { 12825 this.wrapperInitData.length = 0; 12826 } 12827 if (!this.timingMetrics) { 12828 this.timingMetrics = {}; 12829 } 12830 this.timingMetrics.methodInvocationTime = 0; 12831 if (!this.timingMetrics.wrapperInitTimes) { 12832 this.timingMetrics.wrapperInitTimes = []; 12833 } else { 12834 this.timingMetrics.wrapperInitTimes.length = 0; 12835 } 12836 if (!this.timingMetrics.wrapperCloseTimes) { 12837 this.timingMetrics.wrapperCloseTimes = []; 12838 } else { 12839 this.timingMetrics.wrapperCloseTimes.length = 0; 12840 } 12841 this._isInTransaction = false; 12842 }, 12843 12844 _isInTransaction: false, 12845 12846 /** 12847 * @abstract 12848 * @return {Array<TransactionWrapper>} Array of transaction wrappers. 12849 */ 12850 getTransactionWrappers: null, 12851 12852 isInTransaction: function() { 12853 return !!this._isInTransaction; 12854 }, 12855 12856 /** 12857 * Executes the function within a safety window. Use this for the top level 12858 * methods that result in large amounts of computation/mutations that would 12859 * need to be safety checked. 12860 * 12861 * @param {function} method Member of scope to call. 12862 * @param {Object} scope Scope to invoke from. 12863 * @param {Object?=} args... Arguments to pass to the method (optional). 12864 * Helps prevent need to bind in many cases. 12865 * @return Return value from `method`. 12866 */ 12867 perform: function(method, scope, a, b, c, d, e, f) { 12868 ("production" !== "development" ? invariant( 12869 !this.isInTransaction(), 12870 'Transaction.perform(...): Cannot initialize a transaction when there ' + 12871 'is already an outstanding transaction.' 12872 ) : invariant(!this.isInTransaction())); 12873 var memberStart = Date.now(); 12874 var errorToThrow = null; 12875 var ret; 12876 try { 12877 this.initializeAll(); 12878 ret = method.call(scope, a, b, c, d, e, f); 12879 } catch (error) { 12880 // IE8 requires `catch` in order to use `finally`. 12881 errorToThrow = error; 12882 } finally { 12883 var memberEnd = Date.now(); 12884 this.methodInvocationTime += (memberEnd - memberStart); 12885 try { 12886 this.closeAll(); 12887 } catch (closeError) { 12888 // If `method` throws, prefer to show that stack trace over any thrown 12889 // by invoking `closeAll`. 12890 errorToThrow = errorToThrow || closeError; 12891 } 12892 } 12893 if (errorToThrow) { 12894 throw errorToThrow; 12895 } 12896 return ret; 12897 }, 12898 12899 initializeAll: function() { 12900 this._isInTransaction = true; 12901 var transactionWrappers = this.transactionWrappers; 12902 var wrapperInitTimes = this.timingMetrics.wrapperInitTimes; 12903 var errorToThrow = null; 12904 for (var i = 0; i < transactionWrappers.length; i++) { 12905 var initStart = Date.now(); 12906 var wrapper = transactionWrappers[i]; 12907 try { 12908 this.wrapperInitData[i] = wrapper.initialize ? 12909 wrapper.initialize.call(this) : 12910 null; 12911 } catch (initError) { 12912 // Prefer to show the stack trace of the first error. 12913 errorToThrow = errorToThrow || initError; 12914 this.wrapperInitData[i] = Transaction.OBSERVED_ERROR; 12915 } finally { 12916 var curInitTime = wrapperInitTimes[i]; 12917 var initEnd = Date.now(); 12918 wrapperInitTimes[i] = (curInitTime || 0) + (initEnd - initStart); 12919 } 12920 } 12921 if (errorToThrow) { 12922 throw errorToThrow; 12923 } 12924 }, 12925 12926 /** 12927 * Invokes each of `this.transactionWrappers.close[i]` functions, passing into 12928 * them the respective return values of `this.transactionWrappers.init[i]` 12929 * (`close`rs that correspond to initializers that failed will not be 12930 * invoked). 12931 */ 12932 closeAll: function() { 12933 ("production" !== "development" ? invariant( 12934 this.isInTransaction(), 12935 'Transaction.closeAll(): Cannot close transaction when none are open.' 12936 ) : invariant(this.isInTransaction())); 12937 var transactionWrappers = this.transactionWrappers; 12938 var wrapperCloseTimes = this.timingMetrics.wrapperCloseTimes; 12939 var errorToThrow = null; 12940 for (var i = 0; i < transactionWrappers.length; i++) { 12941 var wrapper = transactionWrappers[i]; 12942 var closeStart = Date.now(); 12943 var initData = this.wrapperInitData[i]; 12944 try { 12945 if (initData !== Transaction.OBSERVED_ERROR) { 12946 wrapper.close && wrapper.close.call(this, initData); 12947 } 12948 } catch (closeError) { 12949 // Prefer to show the stack trace of the first error. 12950 errorToThrow = errorToThrow || closeError; 12951 } finally { 12952 var closeEnd = Date.now(); 12953 var curCloseTime = wrapperCloseTimes[i]; 12954 wrapperCloseTimes[i] = (curCloseTime || 0) + (closeEnd - closeStart); 12955 } 12956 } 12957 this.wrapperInitData.length = 0; 12958 this._isInTransaction = false; 12959 if (errorToThrow) { 12960 throw errorToThrow; 12961 } 12962 } 12963 }; 12964 12965 var Transaction = { 12966 12967 Mixin: Mixin, 12968 12969 /** 12970 * Token to look for to determine if an error occured. 12971 */ 12972 OBSERVED_ERROR: {} 12973 12974 }; 12975 12976 module.exports = Transaction; 12977 12978 },{"./invariant":109}],84:[function(require,module,exports){ 12979 /** 12980 * Copyright 2013 Facebook, Inc. 12981 * 12982 * Licensed under the Apache License, Version 2.0 (the "License"); 12983 * you may not use this file except in compliance with the License. 12984 * You may obtain a copy of the License at 12985 * 12986 * http://www.apache.org/licenses/LICENSE-2.0 12987 * 12988 * Unless required by applicable law or agreed to in writing, software 12989 * distributed under the License is distributed on an "AS IS" BASIS, 12990 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12991 * See the License for the specific language governing permissions and 12992 * limitations under the License. 12993 * 12994 * @providesModule ViewportMetrics 12995 */ 12996 12997 "use strict"; 12998 12999 var getUnboundedScrollPosition = require("./getUnboundedScrollPosition"); 13000 13001 var ViewportMetrics = { 13002 13003 currentScrollLeft: 0, 13004 13005 currentScrollTop: 0, 13006 13007 refreshScrollValues: function() { 13008 var scrollPosition = getUnboundedScrollPosition(window); 13009 ViewportMetrics.currentScrollLeft = scrollPosition.x; 13010 ViewportMetrics.currentScrollTop = scrollPosition.y; 13011 } 13012 13013 }; 13014 13015 module.exports = ViewportMetrics; 13016 13017 },{"./getUnboundedScrollPosition":107}],85:[function(require,module,exports){ 13018 /** 13019 * Copyright 2013 Facebook, Inc. 13020 * 13021 * Licensed under the Apache License, Version 2.0 (the "License"); 13022 * you may not use this file except in compliance with the License. 13023 * You may obtain a copy of the License at 13024 * 13025 * http://www.apache.org/licenses/LICENSE-2.0 13026 * 13027 * Unless required by applicable law or agreed to in writing, software 13028 * distributed under the License is distributed on an "AS IS" BASIS, 13029 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13030 * See the License for the specific language governing permissions and 13031 * limitations under the License. 13032 * 13033 * @providesModule accumulate 13034 */ 13035 13036 "use strict"; 13037 13038 var invariant = require("./invariant"); 13039 13040 /** 13041 * Accumulates items that must not be null or undefined. 13042 * 13043 * This is used to conserve memory by avoiding array allocations. 13044 * 13045 * @return {*|array<*>} An accumulation of items. 13046 */ 13047 function accumulate(current, next) { 13048 ("production" !== "development" ? invariant( 13049 next != null, 13050 'accumulate(...): Accumulated items must be not be null or undefined.' 13051 ) : invariant(next != null)); 13052 if (current == null) { 13053 return next; 13054 } else { 13055 // Both are not empty. Warning: Never call x.concat(y) when you are not 13056 // certain that x is an Array (x could be a string with concat method). 13057 var currentIsArray = Array.isArray(current); 13058 var nextIsArray = Array.isArray(next); 13059 if (currentIsArray) { 13060 return current.concat(next); 13061 } else { 13062 if (nextIsArray) { 13063 return [current].concat(next); 13064 } else { 13065 return [current, next]; 13066 } 13067 } 13068 } 13069 } 13070 13071 module.exports = accumulate; 13072 13073 },{"./invariant":109}],86:[function(require,module,exports){ 13074 /** 13075 * Copyright 2013 Facebook, Inc. 13076 * 13077 * Licensed under the Apache License, Version 2.0 (the "License"); 13078 * you may not use this file except in compliance with the License. 13079 * You may obtain a copy of the License at 13080 * 13081 * http://www.apache.org/licenses/LICENSE-2.0 13082 * 13083 * Unless required by applicable law or agreed to in writing, software 13084 * distributed under the License is distributed on an "AS IS" BASIS, 13085 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13086 * See the License for the specific language governing permissions and 13087 * limitations under the License. 13088 * 13089 * @providesModule adler32 13090 */ 13091 13092 /* jslint bitwise:true */ 13093 13094 "use strict"; 13095 13096 var MOD = 65521; 13097 13098 // This is a clean-room implementation of adler32 designed for detecting 13099 // if markup is not what we expect it to be. It does not need to be 13100 // cryptographically strong, only reasonable good at detecting if markup 13101 // generated on the server is different than that on the client. 13102 function adler32(data) { 13103 var a = 1; 13104 var b = 0; 13105 for (var i = 0; i < data.length; i++) { 13106 a = (a + data.charCodeAt(i)) % MOD; 13107 b = (b + a) % MOD; 13108 } 13109 return a | (b << 16); 13110 } 13111 13112 module.exports = adler32; 13113 13114 },{}],87:[function(require,module,exports){ 13115 /** 13116 * Copyright 2013 Facebook, Inc. 13117 * 13118 * Licensed under the Apache License, Version 2.0 (the "License"); 13119 * you may not use this file except in compliance with the License. 13120 * You may obtain a copy of the License at 13121 * 13122 * http://www.apache.org/licenses/LICENSE-2.0 13123 * 13124 * Unless required by applicable law or agreed to in writing, software 13125 * distributed under the License is distributed on an "AS IS" BASIS, 13126 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13127 * See the License for the specific language governing permissions and 13128 * limitations under the License. 13129 * 13130 * @providesModule containsNode 13131 * @typechecks 13132 */ 13133 13134 var isTextNode = require("./isTextNode"); 13135 13136 /*jslint bitwise:true */ 13137 13138 /** 13139 * Checks if a given DOM node contains or is another DOM node. 13140 * 13141 * @param {?DOMNode} outerNode Outer DOM node. 13142 * @param {?DOMNode} innerNode Inner DOM node. 13143 * @return {boolean} True if `outerNode` contains or is `innerNode`. 13144 */ 13145 function containsNode(outerNode, innerNode) { 13146 if (!outerNode || !innerNode) { 13147 return false; 13148 } else if (outerNode === innerNode) { 13149 return true; 13150 } else if (isTextNode(outerNode)) { 13151 return false; 13152 } else if (isTextNode(innerNode)) { 13153 return containsNode(outerNode, innerNode.parentNode); 13154 } else if (outerNode.contains) { 13155 return outerNode.contains(innerNode); 13156 } else if (outerNode.compareDocumentPosition) { 13157 return !!(outerNode.compareDocumentPosition(innerNode) & 16); 13158 } else { 13159 return false; 13160 } 13161 } 13162 13163 module.exports = containsNode; 13164 13165 },{"./isTextNode":113}],88:[function(require,module,exports){ 13166 /** 13167 * Copyright 2013 Facebook, Inc. 13168 * 13169 * Licensed under the Apache License, Version 2.0 (the "License"); 13170 * you may not use this file except in compliance with the License. 13171 * You may obtain a copy of the License at 13172 * 13173 * http://www.apache.org/licenses/LICENSE-2.0 13174 * 13175 * Unless required by applicable law or agreed to in writing, software 13176 * distributed under the License is distributed on an "AS IS" BASIS, 13177 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13178 * See the License for the specific language governing permissions and 13179 * limitations under the License. 13180 * 13181 * @providesModule copyProperties 13182 */ 13183 13184 /** 13185 * Copy properties from one or more objects (up to 5) into the first object. 13186 * This is a shallow copy. It mutates the first object and also returns it. 13187 * 13188 * NOTE: `arguments` has a very significant performance penalty, which is why 13189 * we don't support unlimited arguments. 13190 */ 13191 function copyProperties(obj, a, b, c, d, e, f) { 13192 obj = obj || {}; 13193 13194 if ("production" !== "development") { 13195 if (f) { 13196 throw new Error('Too many arguments passed to copyProperties'); 13197 } 13198 } 13199 13200 var args = [a, b, c, d, e]; 13201 var ii = 0, v; 13202 while (args[ii]) { 13203 v = args[ii++]; 13204 for (var k in v) { 13205 obj[k] = v[k]; 13206 } 13207 13208 // IE ignores toString in object iteration.. See: 13209 // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html 13210 if (v.hasOwnProperty && v.hasOwnProperty('toString') && 13211 (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { 13212 obj.toString = v.toString; 13213 } 13214 } 13215 13216 return obj; 13217 } 13218 13219 module.exports = copyProperties; 13220 13221 },{}],89:[function(require,module,exports){ 13222 /** 13223 * Copyright 2013 Facebook, Inc. 13224 * 13225 * Licensed under the Apache License, Version 2.0 (the "License"); 13226 * you may not use this file except in compliance with the License. 13227 * You may obtain a copy of the License at 13228 * 13229 * http://www.apache.org/licenses/LICENSE-2.0 13230 * 13231 * Unless required by applicable law or agreed to in writing, software 13232 * distributed under the License is distributed on an "AS IS" BASIS, 13233 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13234 * See the License for the specific language governing permissions and 13235 * limitations under the License. 13236 * 13237 * @providesModule createArrayFrom 13238 * @typechecks 13239 */ 13240 13241 /** 13242 * NOTE: if you are a previous user of this function, it has been considered 13243 * unsafe because it's inconsistent across browsers for some inputs. 13244 * Instead use `Array.isArray()`. 13245 * 13246 * Perform a heuristic test to determine if an object is "array-like". 13247 * 13248 * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" 13249 * Joshu replied: "Mu." 13250 * 13251 * This function determines if its argument has "array nature": it returns 13252 * true if the argument is an actual array, an `arguments' object, or an 13253 * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). 13254 * 13255 * @param {*} obj 13256 * @return {boolean} 13257 */ 13258 function hasArrayNature(obj) { 13259 return ( 13260 // not null/false 13261 !!obj && 13262 // arrays are objects, NodeLists are functions in Safari 13263 (typeof obj == 'object' || typeof obj == 'function') && 13264 // quacks like an array 13265 ('length' in obj) && 13266 // not window 13267 !('setInterval' in obj) && 13268 // no DOM node should be considered an array-like 13269 // a 'select' element has 'length' and 'item' properties on IE8 13270 (typeof obj.nodeType != 'number') && 13271 ( 13272 // a real array 13273 (// HTMLCollection/NodeList 13274 (Array.isArray(obj) || 13275 // arguments 13276 ('callee' in obj) || 'item' in obj)) 13277 ) 13278 ); 13279 } 13280 13281 /** 13282 * Ensure that the argument is an array by wrapping it in an array if it is not. 13283 * Creates a copy of the argument if it is already an array. 13284 * 13285 * This is mostly useful idiomatically: 13286 * 13287 * var createArrayFrom = require('createArrayFrom'); 13288 * 13289 * function takesOneOrMoreThings(things) { 13290 * things = createArrayFrom(things); 13291 * ... 13292 * } 13293 * 13294 * This allows you to treat `things' as an array, but accept scalars in the API. 13295 * 13296 * This is also good for converting certain pseudo-arrays, like `arguments` or 13297 * HTMLCollections, into arrays. 13298 * 13299 * @param {*} obj 13300 * @return {array} 13301 */ 13302 function createArrayFrom(obj) { 13303 if (!hasArrayNature(obj)) { 13304 return [obj]; 13305 } 13306 if (obj.item) { 13307 // IE does not support Array#slice on HTMLCollections 13308 var l = obj.length, ret = new Array(l); 13309 while (l--) { ret[l] = obj[l]; } 13310 return ret; 13311 } 13312 return Array.prototype.slice.call(obj); 13313 } 13314 13315 module.exports = createArrayFrom; 13316 13317 },{}],90:[function(require,module,exports){ 13318 /** 13319 * Copyright 2013 Facebook, Inc. 13320 * 13321 * Licensed under the Apache License, Version 2.0 (the "License"); 13322 * you may not use this file except in compliance with the License. 13323 * You may obtain a copy of the License at 13324 * 13325 * http://www.apache.org/licenses/LICENSE-2.0 13326 * 13327 * Unless required by applicable law or agreed to in writing, software 13328 * distributed under the License is distributed on an "AS IS" BASIS, 13329 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13330 * See the License for the specific language governing permissions and 13331 * limitations under the License. 13332 * 13333 * @providesModule createNodesFromMarkup 13334 * @typechecks 13335 */ 13336 13337 /*jslint evil: true, sub: true */ 13338 13339 var ExecutionEnvironment = require("./ExecutionEnvironment"); 13340 13341 var createArrayFrom = require("./createArrayFrom"); 13342 var getMarkupWrap = require("./getMarkupWrap"); 13343 var invariant = require("./invariant"); 13344 13345 /** 13346 * Dummy container used to render all markup. 13347 */ 13348 var dummyNode = 13349 ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 13350 13351 /** 13352 * Pattern used by `getNodeName`. 13353 */ 13354 var nodeNamePattern = /^\s*<(\w+)/; 13355 13356 /** 13357 * Extracts the `nodeName` of the first element in a string of markup. 13358 * 13359 * @param {string} markup String of markup. 13360 * @return {?string} Node name of the supplied markup. 13361 */ 13362 function getNodeName(markup) { 13363 var nodeNameMatch = markup.match(nodeNamePattern); 13364 return nodeNameMatch && nodeNameMatch[1].toLowerCase(); 13365 } 13366 13367 /** 13368 * Creates an array containing the nodes rendered from the supplied markup. The 13369 * optionally supplied `handleScript` function will be invoked once for each 13370 * <script> element that is rendered. If no `handleScript` function is supplied, 13371 * an exception is thrown if any <script> elements are rendered. 13372 * 13373 * @param {string} markup A string of valid HTML markup. 13374 * @param {?function} handleScript Invoked once for each rendered <script>. 13375 * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes. 13376 */ 13377 function createNodesFromMarkup(markup, handleScript) { 13378 var node = dummyNode; 13379 ("production" !== "development" ? invariant(!!dummyNode, 'createNodesFromMarkup dummy not initialized') : invariant(!!dummyNode)); 13380 var nodeName = getNodeName(markup); 13381 13382 var wrap = nodeName && getMarkupWrap(nodeName); 13383 if (wrap) { 13384 node.innerHTML = wrap[1] + markup + wrap[2]; 13385 13386 var wrapDepth = wrap[0]; 13387 while (wrapDepth--) { 13388 node = node.lastChild; 13389 } 13390 } else { 13391 node.innerHTML = markup; 13392 } 13393 13394 var scripts = node.getElementsByTagName('script'); 13395 if (scripts.length) { 13396 ("production" !== "development" ? invariant( 13397 handleScript, 13398 'createNodesFromMarkup(...): Unexpected <script> element rendered.' 13399 ) : invariant(handleScript)); 13400 createArrayFrom(scripts).forEach(handleScript); 13401 } 13402 13403 var nodes = createArrayFrom(node.childNodes); 13404 while (node.lastChild) { 13405 node.removeChild(node.lastChild); 13406 } 13407 return nodes; 13408 } 13409 13410 module.exports = createNodesFromMarkup; 13411 13412 },{"./ExecutionEnvironment":21,"./createArrayFrom":89,"./getMarkupWrap":103,"./invariant":109}],91:[function(require,module,exports){ 13413 /** 13414 * Copyright 2013 Facebook, Inc. 13415 * 13416 * Licensed under the Apache License, Version 2.0 (the "License"); 13417 * you may not use this file except in compliance with the License. 13418 * You may obtain a copy of the License at 13419 * 13420 * http://www.apache.org/licenses/LICENSE-2.0 13421 * 13422 * Unless required by applicable law or agreed to in writing, software 13423 * distributed under the License is distributed on an "AS IS" BASIS, 13424 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13425 * See the License for the specific language governing permissions and 13426 * limitations under the License. 13427 * 13428 * @providesModule createObjectFrom 13429 */ 13430 13431 /** 13432 * Construct an object from an array of keys 13433 * and optionally specified value or list of values. 13434 * 13435 * >>> createObjectFrom(['a','b','c']); 13436 * {a: true, b: true, c: true} 13437 * 13438 * >>> createObjectFrom(['a','b','c'], false); 13439 * {a: false, b: false, c: false} 13440 * 13441 * >>> createObjectFrom(['a','b','c'], 'monkey'); 13442 * {c:'monkey', b:'monkey' c:'monkey'} 13443 * 13444 * >>> createObjectFrom(['a','b','c'], [1,2,3]); 13445 * {a: 1, b: 2, c: 3} 13446 * 13447 * >>> createObjectFrom(['women', 'men'], [true, false]); 13448 * {women: true, men: false} 13449 * 13450 * @param Array list of keys 13451 * @param mixed optional value or value array. defaults true. 13452 * @returns object 13453 */ 13454 function createObjectFrom(keys, values /* = true */) { 13455 if ("production" !== "development") { 13456 if (!Array.isArray(keys)) { 13457 throw new TypeError('Must pass an array of keys.'); 13458 } 13459 } 13460 13461 var object = {}; 13462 var isArray = Array.isArray(values); 13463 if (typeof values == 'undefined') { 13464 values = true; 13465 } 13466 13467 for (var ii = keys.length; ii--;) { 13468 object[keys[ii]] = isArray ? values[ii] : values; 13469 } 13470 return object; 13471 } 13472 13473 module.exports = createObjectFrom; 13474 13475 },{}],92:[function(require,module,exports){ 13476 /** 13477 * Copyright 2013 Facebook, Inc. 13478 * 13479 * Licensed under the Apache License, Version 2.0 (the "License"); 13480 * you may not use this file except in compliance with the License. 13481 * You may obtain a copy of the License at 13482 * 13483 * http://www.apache.org/licenses/LICENSE-2.0 13484 * 13485 * Unless required by applicable law or agreed to in writing, software 13486 * distributed under the License is distributed on an "AS IS" BASIS, 13487 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13488 * See the License for the specific language governing permissions and 13489 * limitations under the License. 13490 * 13491 * @providesModule cx 13492 */ 13493 13494 /** 13495 * This function is used to mark string literals representing CSS class names 13496 * so that they can be transformed statically. This allows for modularization 13497 * and minification of CSS class names. 13498 * 13499 * In static_upstream, this function is actually implemented, but it should 13500 * eventually be replaced with something more descriptive, and the transform 13501 * that is used in the main stack should be ported for use elsewhere. 13502 * 13503 * @param string|object className to modularize, or an object of key/values. 13504 * In the object case, the values are conditions that 13505 * determine if the className keys should be included. 13506 * @param [string ...] Variable list of classNames in the string case. 13507 * @return string Renderable space-separated CSS className. 13508 */ 13509 function cx(classNames) { 13510 if (typeof classNames == 'object') { 13511 return Object.keys(classNames).map(function(className) { 13512 return classNames[className] ? className : ''; 13513 }).join(' '); 13514 } else { 13515 return Array.prototype.join.call(arguments, ' '); 13516 } 13517 } 13518 13519 module.exports = cx; 13520 13521 },{}],93:[function(require,module,exports){ 13522 /** 13523 * Copyright 2013 Facebook, Inc. 13524 * 13525 * Licensed under the Apache License, Version 2.0 (the "License"); 13526 * you may not use this file except in compliance with the License. 13527 * You may obtain a copy of the License at 13528 * 13529 * http://www.apache.org/licenses/LICENSE-2.0 13530 * 13531 * Unless required by applicable law or agreed to in writing, software 13532 * distributed under the License is distributed on an "AS IS" BASIS, 13533 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13534 * See the License for the specific language governing permissions and 13535 * limitations under the License. 13536 * 13537 * @providesModule dangerousStyleValue 13538 * @typechecks static-only 13539 */ 13540 13541 "use strict"; 13542 13543 var CSSProperty = require("./CSSProperty"); 13544 13545 /** 13546 * Convert a value into the proper css writable value. The `styleName` name 13547 * name should be logical (no hyphens), as specified 13548 * in `CSSProperty.isUnitlessNumber`. 13549 * 13550 * @param {string} styleName CSS property name such as `topMargin`. 13551 * @param {*} value CSS property value such as `10px`. 13552 * @return {string} Normalized style value with dimensions applied. 13553 */ 13554 function dangerousStyleValue(styleName, value) { 13555 // Note that we've removed escapeTextForBrowser() calls here since the 13556 // whole string will be escaped when the attribute is injected into 13557 // the markup. If you provide unsafe user data here they can inject 13558 // arbitrary CSS which may be problematic (I couldn't repro this): 13559 // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet 13560 // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ 13561 // This is not an XSS hole but instead a potential CSS injection issue 13562 // which has lead to a greater discussion about how we're going to 13563 // trust URLs moving forward. See #2115901 13564 13565 var isEmpty = value == null || typeof value === 'boolean' || value === ''; 13566 if (isEmpty) { 13567 return ''; 13568 } 13569 13570 var isNonNumeric = isNaN(value); 13571 if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) { 13572 return '' + value; // cast to string 13573 } 13574 13575 return value + 'px'; 13576 } 13577 13578 module.exports = dangerousStyleValue; 13579 13580 },{"./CSSProperty":3}],94:[function(require,module,exports){ 13581 /** 13582 * Copyright 2013 Facebook, Inc. 13583 * 13584 * Licensed under the Apache License, Version 2.0 (the "License"); 13585 * you may not use this file except in compliance with the License. 13586 * You may obtain a copy of the License at 13587 * 13588 * http://www.apache.org/licenses/LICENSE-2.0 13589 * 13590 * Unless required by applicable law or agreed to in writing, software 13591 * distributed under the License is distributed on an "AS IS" BASIS, 13592 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13593 * See the License for the specific language governing permissions and 13594 * limitations under the License. 13595 * 13596 * @providesModule emptyFunction 13597 */ 13598 13599 var copyProperties = require("./copyProperties"); 13600 13601 function makeEmptyFunction(arg) { 13602 return function() { 13603 return arg; 13604 }; 13605 } 13606 13607 /** 13608 * This function accepts and discards inputs; it has no side effects. This is 13609 * primarily useful idiomatically for overridable function endpoints which 13610 * always need to be callable, since JS lacks a null-call idiom ala Cocoa. 13611 */ 13612 function emptyFunction() {} 13613 13614 copyProperties(emptyFunction, { 13615 thatReturns: makeEmptyFunction, 13616 thatReturnsFalse: makeEmptyFunction(false), 13617 thatReturnsTrue: makeEmptyFunction(true), 13618 thatReturnsNull: makeEmptyFunction(null), 13619 thatReturnsThis: function() { return this; }, 13620 thatReturnsArgument: function(arg) { return arg; } 13621 }); 13622 13623 module.exports = emptyFunction; 13624 13625 },{"./copyProperties":88}],95:[function(require,module,exports){ 13626 /** 13627 * Copyright 2013 Facebook, Inc. 13628 * 13629 * Licensed under the Apache License, Version 2.0 (the "License"); 13630 * you may not use this file except in compliance with the License. 13631 * You may obtain a copy of the License at 13632 * 13633 * http://www.apache.org/licenses/LICENSE-2.0 13634 * 13635 * Unless required by applicable law or agreed to in writing, software 13636 * distributed under the License is distributed on an "AS IS" BASIS, 13637 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13638 * See the License for the specific language governing permissions and 13639 * limitations under the License. 13640 * 13641 * @providesModule escapeTextForBrowser 13642 * @typechecks static-only 13643 */ 13644 13645 "use strict"; 13646 13647 var ESCAPE_LOOKUP = { 13648 "&": "&", 13649 ">": ">", 13650 "<": "<", 13651 "\"": """, 13652 "'": "'", 13653 "/": "/" 13654 }; 13655 13656 var ESCAPE_REGEX = /[&><"'\/]/g; 13657 13658 function escaper(match) { 13659 return ESCAPE_LOOKUP[match]; 13660 } 13661 13662 /** 13663 * Escapes text to prevent scripting attacks. 13664 * 13665 * @param {*} text Text value to escape. 13666 * @return {string} An escaped string. 13667 */ 13668 function escapeTextForBrowser(text) { 13669 return ('' + text).replace(ESCAPE_REGEX, escaper); 13670 } 13671 13672 module.exports = escapeTextForBrowser; 13673 13674 },{}],96:[function(require,module,exports){ 13675 /** 13676 * Copyright 2013 Facebook, Inc. 13677 * 13678 * Licensed under the Apache License, Version 2.0 (the "License"); 13679 * you may not use this file except in compliance with the License. 13680 * You may obtain a copy of the License at 13681 * 13682 * http://www.apache.org/licenses/LICENSE-2.0 13683 * 13684 * Unless required by applicable law or agreed to in writing, software 13685 * distributed under the License is distributed on an "AS IS" BASIS, 13686 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13687 * See the License for the specific language governing permissions and 13688 * limitations under the License. 13689 * 13690 * @providesModule ex 13691 * @typechecks 13692 * @nostacktrace 13693 */ 13694 13695 /** 13696 * This function transforms error message with arguments into plain text error 13697 * message, so that it can be passed to window.onerror without losing anything. 13698 * It can then be transformed back by `erx()` function. 13699 * 13700 * Usage: 13701 * throw new Error(ex('Error %s from %s', errorCode, userID)); 13702 * 13703 * @param {string} errorMessage 13704 */ 13705 13706 var ex = function(errorMessage/*, arg1, arg2, ...*/) { 13707 var args = Array.prototype.slice.call(arguments).map(function(arg) { 13708 return String(arg); 13709 }); 13710 var expectedLength = errorMessage.split('%s').length - 1; 13711 13712 if (expectedLength !== args.length - 1) { 13713 // something wrong with the formatting string 13714 return ex('ex args number mismatch: %s', JSON.stringify(args)); 13715 } 13716 13717 return ex._prefix + JSON.stringify(args) + ex._suffix; 13718 }; 13719 13720 ex._prefix = '<![EX['; 13721 ex._suffix = ']]>'; 13722 13723 module.exports = ex; 13724 13725 },{}],97:[function(require,module,exports){ 13726 /** 13727 * Copyright 2013 Facebook, Inc. 13728 * 13729 * Licensed under the Apache License, Version 2.0 (the "License"); 13730 * you may not use this file except in compliance with the License. 13731 * You may obtain a copy of the License at 13732 * 13733 * http://www.apache.org/licenses/LICENSE-2.0 13734 * 13735 * Unless required by applicable law or agreed to in writing, software 13736 * distributed under the License is distributed on an "AS IS" BASIS, 13737 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13738 * See the License for the specific language governing permissions and 13739 * limitations under the License. 13740 * 13741 * @providesModule filterAttributes 13742 * @typechecks static-only 13743 */ 13744 13745 /*jslint evil: true */ 13746 13747 'use strict'; 13748 13749 /** 13750 * Like filter(), but for a DOM nodes attributes. Returns an array of 13751 * the filter DOMAttribute objects. Does some perf related this like 13752 * caching attributes.length. 13753 * 13754 * @param {DOMElement} node Node whose attributes you want to filter 13755 * @return {array} array of DOM attribute objects. 13756 */ 13757 function filterAttributes(node, func, context) { 13758 var attributes = node.attributes; 13759 var numAttributes = attributes.length; 13760 var accumulator = []; 13761 for (var i = 0; i < numAttributes; i++) { 13762 var attr = attributes.item(i); 13763 if (func.call(context, attr)) { 13764 accumulator.push(attr); 13765 } 13766 } 13767 return accumulator; 13768 } 13769 13770 module.exports = filterAttributes; 13771 13772 },{}],98:[function(require,module,exports){ 13773 /** 13774 * Copyright 2013 Facebook, Inc. 13775 * 13776 * Licensed under the Apache License, Version 2.0 (the "License"); 13777 * you may not use this file except in compliance with the License. 13778 * You may obtain a copy of the License at 13779 * 13780 * http://www.apache.org/licenses/LICENSE-2.0 13781 * 13782 * Unless required by applicable law or agreed to in writing, software 13783 * distributed under the License is distributed on an "AS IS" BASIS, 13784 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13785 * See the License for the specific language governing permissions and 13786 * limitations under the License. 13787 * 13788 * @providesModule flattenChildren 13789 */ 13790 13791 "use strict"; 13792 13793 var invariant = require("./invariant"); 13794 var traverseAllChildren = require("./traverseAllChildren"); 13795 13796 /** 13797 * @param {function} traverseContext Context passed through traversal. 13798 * @param {?ReactComponent} child React child component. 13799 * @param {!string} name String name of key path to child. 13800 */ 13801 function flattenSingleChildIntoContext(traverseContext, child, name) { 13802 // We found a component instance. 13803 var result = traverseContext; 13804 ("production" !== "development" ? invariant( 13805 !result.hasOwnProperty(name), 13806 'flattenChildren(...): Encountered two children with the same key, `%s`. ' + 13807 'Children keys must be unique.', 13808 name 13809 ) : invariant(!result.hasOwnProperty(name))); 13810 result[name] = child; 13811 } 13812 13813 /** 13814 * Flattens children that are typically specified as `props.children`. 13815 * @return {!object} flattened children keyed by name. 13816 */ 13817 function flattenChildren(children) { 13818 if (children == null) { 13819 return children; 13820 } 13821 var result = {}; 13822 traverseAllChildren(children, flattenSingleChildIntoContext, result); 13823 return result; 13824 } 13825 13826 module.exports = flattenChildren; 13827 13828 },{"./invariant":109,"./traverseAllChildren":127}],99:[function(require,module,exports){ 13829 /** 13830 * Copyright 2013 Facebook, Inc. 13831 * 13832 * Licensed under the Apache License, Version 2.0 (the "License"); 13833 * you may not use this file except in compliance with the License. 13834 * You may obtain a copy of the License at 13835 * 13836 * http://www.apache.org/licenses/LICENSE-2.0 13837 * 13838 * Unless required by applicable law or agreed to in writing, software 13839 * distributed under the License is distributed on an "AS IS" BASIS, 13840 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13841 * See the License for the specific language governing permissions and 13842 * limitations under the License. 13843 * 13844 * @providesModule forEachAccumulated 13845 */ 13846 13847 "use strict"; 13848 13849 /** 13850 * @param {array} an "accumulation" of items which is either an Array or 13851 * a single item. Useful when paired with the `accumulate` module. This is a 13852 * simple utility that allows us to reason about a collection of items, but 13853 * handling the case when there is exactly one item (and we do not need to 13854 * allocate an array). 13855 */ 13856 var forEachAccumulated = function(arr, cb, scope) { 13857 if (Array.isArray(arr)) { 13858 arr.forEach(cb, scope); 13859 } else if (arr) { 13860 cb.call(scope, arr); 13861 } 13862 }; 13863 13864 module.exports = forEachAccumulated; 13865 13866 },{}],100:[function(require,module,exports){ 13867 /** 13868 * Copyright 2013 Facebook, Inc. 13869 * 13870 * Licensed under the Apache License, Version 2.0 (the "License"); 13871 * you may not use this file except in compliance with the License. 13872 * You may obtain a copy of the License at 13873 * 13874 * http://www.apache.org/licenses/LICENSE-2.0 13875 * 13876 * Unless required by applicable law or agreed to in writing, software 13877 * distributed under the License is distributed on an "AS IS" BASIS, 13878 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13879 * See the License for the specific language governing permissions and 13880 * limitations under the License. 13881 * 13882 * @providesModule ge 13883 */ 13884 13885 /** 13886 * Find a node by ID. Optionally search a sub-tree outside of the document 13887 * 13888 * Use ge if you're not sure whether or not the element exists. You can test 13889 * for existence yourself in your application code. 13890 * 13891 * If your application code depends on the existence of the element, use $ 13892 * instead, which will throw in DEV if the element doesn't exist. 13893 */ 13894 function ge(arg, root, tag) { 13895 return typeof arg != 'string' ? arg : 13896 !root ? document.getElementById(arg) : 13897 _geFromSubtree(arg, root, tag); 13898 } 13899 13900 function _geFromSubtree(id, root, tag) { 13901 var elem, children, ii; 13902 13903 if (_getNodeID(root) == id) { 13904 return root; 13905 } else if (root.getElementsByTagName) { 13906 // All Elements implement this, which does an iterative DFS, which is 13907 // faster than recursion and doesn't run into stack depth issues. 13908 children = root.getElementsByTagName(tag || '*'); 13909 for (ii = 0; ii < children.length; ii++) { 13910 if (_getNodeID(children[ii]) == id) { 13911 return children[ii]; 13912 } 13913 } 13914 } else { 13915 // DocumentFragment does not implement getElementsByTagName, so 13916 // recurse over its children. Its children must be Elements, so 13917 // each child will use the getElementsByTagName case instead. 13918 children = root.childNodes; 13919 for (ii = 0; ii < children.length; ii++) { 13920 elem = _geFromSubtree(id, children[ii]); 13921 if (elem) { 13922 return elem; 13923 } 13924 } 13925 } 13926 13927 return null; 13928 } 13929 13930 /** 13931 * Return the ID value for a given node. This allows us to avoid issues 13932 * with forms that contain inputs with name="id". 13933 * 13934 * @return string (null if attribute not set) 13935 */ 13936 function _getNodeID(node) { 13937 // #document and #document-fragment do not have getAttributeNode. 13938 var id = node.getAttributeNode && node.getAttributeNode('id'); 13939 return id ? id.value : null; 13940 } 13941 13942 module.exports = ge; 13943 13944 },{}],101:[function(require,module,exports){ 13945 /** 13946 * Copyright 2013 Facebook, Inc. 13947 * 13948 * Licensed under the Apache License, Version 2.0 (the "License"); 13949 * you may not use this file except in compliance with the License. 13950 * You may obtain a copy of the License at 13951 * 13952 * http://www.apache.org/licenses/LICENSE-2.0 13953 * 13954 * Unless required by applicable law or agreed to in writing, software 13955 * distributed under the License is distributed on an "AS IS" BASIS, 13956 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13957 * See the License for the specific language governing permissions and 13958 * limitations under the License. 13959 * 13960 * @providesModule getActiveElement 13961 * @typechecks 13962 */ 13963 13964 /** 13965 * Same as document.activeElement but wraps in a try-catch block. In IE it is 13966 * not safe to call document.activeElement if there is nothing focused. 13967 */ 13968 function getActiveElement() /*?DOMElement*/ { 13969 try { 13970 return document.activeElement; 13971 } catch (e) { 13972 return null; 13973 } 13974 } 13975 13976 module.exports = getActiveElement; 13977 13978 13979 },{}],102:[function(require,module,exports){ 13980 /** 13981 * Copyright 2013 Facebook, Inc. 13982 * 13983 * Licensed under the Apache License, Version 2.0 (the "License"); 13984 * you may not use this file except in compliance with the License. 13985 * You may obtain a copy of the License at 13986 * 13987 * http://www.apache.org/licenses/LICENSE-2.0 13988 * 13989 * Unless required by applicable law or agreed to in writing, software 13990 * distributed under the License is distributed on an "AS IS" BASIS, 13991 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13992 * See the License for the specific language governing permissions and 13993 * limitations under the License. 13994 * 13995 * @providesModule getEventTarget 13996 * @typechecks static-only 13997 */ 13998 13999 "use strict"; 14000 14001 /** 14002 * Gets the target node from a native browser event by accounting for 14003 * inconsistencies in browser DOM APIs. 14004 * 14005 * @param {object} nativeEvent Native browser event. 14006 * @return {DOMEventTarget} Target node. 14007 */ 14008 function getEventTarget(nativeEvent) { 14009 var target = nativeEvent.target || nativeEvent.srcElement || window; 14010 // Safari may fire events on text nodes (Node.TEXT_NODE is 3). 14011 // @see http://www.quirksmode.org/js/events_properties.html 14012 return target.nodeType === 3 ? target.parentNode : target; 14013 } 14014 14015 module.exports = getEventTarget; 14016 14017 },{}],103:[function(require,module,exports){ 14018 /** 14019 * Copyright 2013 Facebook, Inc. 14020 * 14021 * Licensed under the Apache License, Version 2.0 (the "License"); 14022 * you may not use this file except in compliance with the License. 14023 * You may obtain a copy of the License at 14024 * 14025 * http://www.apache.org/licenses/LICENSE-2.0 14026 * 14027 * Unless required by applicable law or agreed to in writing, software 14028 * distributed under the License is distributed on an "AS IS" BASIS, 14029 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14030 * See the License for the specific language governing permissions and 14031 * limitations under the License. 14032 * 14033 * @providesModule getMarkupWrap 14034 */ 14035 14036 var ExecutionEnvironment = require("./ExecutionEnvironment"); 14037 14038 var invariant = require("./invariant"); 14039 14040 /** 14041 * Dummy container used to detect which wraps are necessary. 14042 */ 14043 var dummyNode = 14044 ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; 14045 14046 /** 14047 * Some browsers cannot use `innerHTML` to render certain elements standalone, 14048 * so we wrap them, render the wrapped nodes, then extract the desired node. 14049 * 14050 * In IE8, certain elements cannot render alone, so wrap all elements ('*'). 14051 */ 14052 var shouldWrap = { 14053 // Force wrapping for SVG elements because if they get created inside a <div>, 14054 // they will be initialized in the wrong namespace (and will not display). 14055 'circle': true, 14056 'g': true, 14057 'line': true, 14058 'path': true, 14059 'polyline': true, 14060 'rect': true, 14061 'text': true 14062 }; 14063 14064 var selectWrap = [1, '<select multiple="true">', '</select>']; 14065 var tableWrap = [1, '<table>', '</table>']; 14066 var trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>']; 14067 14068 var svgWrap = [1, '<svg>', '</svg>']; 14069 14070 var markupWrap = { 14071 '*': [1, '?<div>', '</div>'], 14072 14073 'area': [1, '<map>', '</map>'], 14074 'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'], 14075 'legend': [1, '<fieldset>', '</fieldset>'], 14076 'param': [1, '<object>', '</object>'], 14077 'tr': [2, '<table><tbody>', '</tbody></table>'], 14078 14079 'optgroup': selectWrap, 14080 'option': selectWrap, 14081 14082 'caption': tableWrap, 14083 'colgroup': tableWrap, 14084 'tbody': tableWrap, 14085 'tfoot': tableWrap, 14086 'thead': tableWrap, 14087 14088 'td': trWrap, 14089 'th': trWrap, 14090 14091 'circle': svgWrap, 14092 'g': svgWrap, 14093 'line': svgWrap, 14094 'path': svgWrap, 14095 'polyline': svgWrap, 14096 'rect': svgWrap, 14097 'text': svgWrap 14098 }; 14099 14100 /** 14101 * Gets the markup wrap configuration for the supplied `nodeName`. 14102 * 14103 * NOTE: This lazily detects which wraps are necessary for the current browser. 14104 * 14105 * @param {string} nodeName Lowercase `nodeName`. 14106 * @return {?array} Markup wrap configuration, if applicable. 14107 */ 14108 function getMarkupWrap(nodeName) { 14109 ("production" !== "development" ? invariant(!!dummyNode, 'Markup wrapping node not initialized') : invariant(!!dummyNode)); 14110 if (!markupWrap.hasOwnProperty(nodeName)) { 14111 nodeName = '*'; 14112 } 14113 if (!shouldWrap.hasOwnProperty(nodeName)) { 14114 if (nodeName === '*') { 14115 dummyNode.innerHTML = '<link />'; 14116 } else { 14117 dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>'; 14118 } 14119 shouldWrap[nodeName] = !dummyNode.firstChild; 14120 } 14121 return shouldWrap[nodeName] ? markupWrap[nodeName] : null; 14122 } 14123 14124 14125 module.exports = getMarkupWrap; 14126 14127 },{"./ExecutionEnvironment":21,"./invariant":109}],104:[function(require,module,exports){ 14128 /** 14129 * Copyright 2013 Facebook, Inc. 14130 * 14131 * Licensed under the Apache License, Version 2.0 (the "License"); 14132 * you may not use this file except in compliance with the License. 14133 * You may obtain a copy of the License at 14134 * 14135 * http://www.apache.org/licenses/LICENSE-2.0 14136 * 14137 * Unless required by applicable law or agreed to in writing, software 14138 * distributed under the License is distributed on an "AS IS" BASIS, 14139 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14140 * See the License for the specific language governing permissions and 14141 * limitations under the License. 14142 * 14143 * @providesModule getNodeForCharacterOffset 14144 */ 14145 14146 "use strict"; 14147 14148 /** 14149 * Given any node return the first leaf node without children. 14150 * 14151 * @param {DOMElement|DOMTextNode} node 14152 * @return {DOMElement|DOMTextNode} 14153 */ 14154 function getLeafNode(node) { 14155 while (node && node.firstChild) { 14156 node = node.firstChild; 14157 } 14158 return node; 14159 } 14160 14161 /** 14162 * Get the next sibling within a container. This will walk up the 14163 * DOM if a node's siblings have been exhausted. 14164 * 14165 * @param {DOMElement|DOMTextNode} node 14166 * @return {?DOMElement|DOMTextNode} 14167 */ 14168 function getSiblingNode(node) { 14169 while (node) { 14170 if (node.nextSibling) { 14171 return node.nextSibling; 14172 } 14173 node = node.parentNode; 14174 } 14175 } 14176 14177 /** 14178 * Get object describing the nodes which contain characters at offset. 14179 * 14180 * @param {DOMElement|DOMTextNode} root 14181 * @param {number} offset 14182 * @return {?object} 14183 */ 14184 function getNodeForCharacterOffset(root, offset) { 14185 var node = getLeafNode(root); 14186 var nodeStart = 0; 14187 var nodeEnd = 0; 14188 14189 while (node) { 14190 if (node.nodeType == 3) { 14191 nodeEnd = nodeStart + node.textContent.length; 14192 14193 if (nodeStart <= offset && nodeEnd >= offset) { 14194 return { 14195 node: node, 14196 offset: offset - nodeStart 14197 }; 14198 } 14199 14200 nodeStart = nodeEnd; 14201 } 14202 14203 node = getLeafNode(getSiblingNode(node)); 14204 } 14205 } 14206 14207 module.exports = getNodeForCharacterOffset; 14208 14209 },{}],105:[function(require,module,exports){ 14210 /** 14211 * Copyright 2013 Facebook, Inc. 14212 * 14213 * Licensed under the Apache License, Version 2.0 (the "License"); 14214 * you may not use this file except in compliance with the License. 14215 * You may obtain a copy of the License at 14216 * 14217 * http://www.apache.org/licenses/LICENSE-2.0 14218 * 14219 * Unless required by applicable law or agreed to in writing, software 14220 * distributed under the License is distributed on an "AS IS" BASIS, 14221 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14222 * See the License for the specific language governing permissions and 14223 * limitations under the License. 14224 * 14225 * @providesModule getReactRootElementInContainer 14226 */ 14227 14228 "use strict"; 14229 14230 var DOC_NODE_TYPE = 9; 14231 14232 /** 14233 * @param {DOMElement|DOMDocument} container DOM element that may contain 14234 * a React component 14235 * @return {?*} DOM element that may have the reactRoot ID, or null. 14236 */ 14237 function getReactRootElementInContainer(container) { 14238 if (!container) { 14239 return null; 14240 } 14241 14242 if (container.nodeType === DOC_NODE_TYPE) { 14243 return container.documentElement; 14244 } else { 14245 return container.firstChild; 14246 } 14247 } 14248 14249 module.exports = getReactRootElementInContainer; 14250 14251 },{}],106:[function(require,module,exports){ 14252 /** 14253 * Copyright 2013 Facebook, Inc. 14254 * 14255 * Licensed under the Apache License, Version 2.0 (the "License"); 14256 * you may not use this file except in compliance with the License. 14257 * You may obtain a copy of the License at 14258 * 14259 * http://www.apache.org/licenses/LICENSE-2.0 14260 * 14261 * Unless required by applicable law or agreed to in writing, software 14262 * distributed under the License is distributed on an "AS IS" BASIS, 14263 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14264 * See the License for the specific language governing permissions and 14265 * limitations under the License. 14266 * 14267 * @providesModule getTextContentAccessor 14268 */ 14269 14270 "use strict"; 14271 14272 var ExecutionEnvironment = require("./ExecutionEnvironment"); 14273 14274 var contentKey = null; 14275 14276 /** 14277 * Gets the key used to access text content on a DOM node. 14278 * 14279 * @return {?string} Key used to access text content. 14280 * @internal 14281 */ 14282 function getTextContentAccessor() { 14283 if (!contentKey && ExecutionEnvironment.canUseDOM) { 14284 contentKey = 'innerText' in document.createElement('div') ? 14285 'innerText' : 14286 'textContent'; 14287 } 14288 return contentKey; 14289 } 14290 14291 module.exports = getTextContentAccessor; 14292 14293 },{"./ExecutionEnvironment":21}],107:[function(require,module,exports){ 14294 /** 14295 * Copyright 2013 Facebook, Inc. 14296 * 14297 * Licensed under the Apache License, Version 2.0 (the "License"); 14298 * you may not use this file except in compliance with the License. 14299 * You may obtain a copy of the License at 14300 * 14301 * http://www.apache.org/licenses/LICENSE-2.0 14302 * 14303 * Unless required by applicable law or agreed to in writing, software 14304 * distributed under the License is distributed on an "AS IS" BASIS, 14305 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14306 * See the License for the specific language governing permissions and 14307 * limitations under the License. 14308 * 14309 * @providesModule getUnboundedScrollPosition 14310 * @typechecks 14311 */ 14312 14313 "use strict"; 14314 14315 /** 14316 * Gets the scroll position of the supplied element or window. 14317 * 14318 * The return values are unbounded, unlike `getScrollPosition`. This means they 14319 * may be negative or exceed the element boundaries (which is possible using 14320 * inertial scrolling). 14321 * 14322 * @param {DOMWindow|DOMElement} scrollable 14323 * @return {object} Map with `x` and `y` keys. 14324 */ 14325 function getUnboundedScrollPosition(scrollable) { 14326 if (scrollable === window) { 14327 return { 14328 x: document.documentElement.scrollLeft || document.body.scrollLeft, 14329 y: document.documentElement.scrollTop || document.body.scrollTop 14330 }; 14331 } 14332 return { 14333 x: scrollable.scrollLeft, 14334 y: scrollable.scrollTop 14335 }; 14336 } 14337 14338 module.exports = getUnboundedScrollPosition; 14339 14340 },{}],108:[function(require,module,exports){ 14341 /** 14342 * Copyright 2013 Facebook, Inc. 14343 * 14344 * Licensed under the Apache License, Version 2.0 (the "License"); 14345 * you may not use this file except in compliance with the License. 14346 * You may obtain a copy of the License at 14347 * 14348 * http://www.apache.org/licenses/LICENSE-2.0 14349 * 14350 * Unless required by applicable law or agreed to in writing, software 14351 * distributed under the License is distributed on an "AS IS" BASIS, 14352 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14353 * See the License for the specific language governing permissions and 14354 * limitations under the License. 14355 * 14356 * @providesModule hyphenate 14357 * @typechecks 14358 */ 14359 14360 var _uppercasePattern = /([A-Z])/g; 14361 14362 /** 14363 * Hyphenates a camelcased string, for example: 14364 * 14365 * > hyphenate('backgroundColor') 14366 * < "background-color" 14367 * 14368 * @param {string} string 14369 * @return {string} 14370 */ 14371 function hyphenate(string) { 14372 return string.replace(_uppercasePattern, '-$1').toLowerCase(); 14373 } 14374 14375 module.exports = hyphenate; 14376 14377 },{}],109:[function(require,module,exports){ 14378 /** 14379 * Copyright 2013 Facebook, Inc. 14380 * 14381 * Licensed under the Apache License, Version 2.0 (the "License"); 14382 * you may not use this file except in compliance with the License. 14383 * You may obtain a copy of the License at 14384 * 14385 * http://www.apache.org/licenses/LICENSE-2.0 14386 * 14387 * Unless required by applicable law or agreed to in writing, software 14388 * distributed under the License is distributed on an "AS IS" BASIS, 14389 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14390 * See the License for the specific language governing permissions and 14391 * limitations under the License. 14392 * 14393 * @providesModule invariant 14394 */ 14395 14396 /** 14397 * Use invariant() to assert state which your program assumes to be true. 14398 * 14399 * Provide sprintf style format and arguments to provide information about 14400 * what broke and what you were expecting. 14401 * 14402 * The invariant message will be stripped in production, but the invariant 14403 * will remain to ensure logic does not differ in production. 14404 */ 14405 14406 function invariant(condition) { 14407 if (!condition) { 14408 throw new Error('Invariant Violation'); 14409 } 14410 } 14411 14412 module.exports = invariant; 14413 14414 if ("production" !== "development") { 14415 var invariantDev = function(condition, format, a, b, c, d, e, f) { 14416 if (format === undefined) { 14417 throw new Error('invariant requires an error message argument'); 14418 } 14419 14420 if (!condition) { 14421 var args = [a, b, c, d, e, f]; 14422 var argIndex = 0; 14423 throw new Error( 14424 'Invariant Violation: ' + 14425 format.replace(/%s/g, function() { return args[argIndex++]; }) 14426 ); 14427 } 14428 }; 14429 14430 module.exports = invariantDev; 14431 } 14432 14433 },{}],110:[function(require,module,exports){ 14434 /** 14435 * Copyright 2013 Facebook, Inc. 14436 * 14437 * Licensed under the Apache License, Version 2.0 (the "License"); 14438 * you may not use this file except in compliance with the License. 14439 * You may obtain a copy of the License at 14440 * 14441 * http://www.apache.org/licenses/LICENSE-2.0 14442 * 14443 * Unless required by applicable law or agreed to in writing, software 14444 * distributed under the License is distributed on an "AS IS" BASIS, 14445 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14446 * See the License for the specific language governing permissions and 14447 * limitations under the License. 14448 * 14449 * @providesModule isEventSupported 14450 */ 14451 14452 "use strict"; 14453 14454 var ExecutionEnvironment = require("./ExecutionEnvironment"); 14455 14456 var testNode, useHasFeature; 14457 if (ExecutionEnvironment.canUseDOM) { 14458 testNode = document.createElement('div'); 14459 useHasFeature = 14460 document.implementation && 14461 document.implementation.hasFeature && 14462 // `hasFeature` always returns true in Firefox 19+. 14463 document.implementation.hasFeature('', '') !== true; 14464 } 14465 14466 /** 14467 * Checks if an event is supported in the current execution environment. 14468 * 14469 * NOTE: This will not work correctly for non-generic events such as `change`, 14470 * `reset`, `load`, `error`, and `select`. 14471 * 14472 * Borrows from Modernizr. 14473 * 14474 * @param {string} eventNameSuffix Event name, e.g. "click". 14475 * @param {?boolean} capture Check if the capture phase is supported. 14476 * @return {boolean} True if the event is supported. 14477 * @internal 14478 * @license Modernizr 3.0.0pre (Custom Build) | MIT 14479 */ 14480 function isEventSupported(eventNameSuffix, capture) { 14481 if (!testNode || (capture && !testNode.addEventListener)) { 14482 return false; 14483 } 14484 var element = document.createElement('div'); 14485 14486 var eventName = 'on' + eventNameSuffix; 14487 var isSupported = eventName in element; 14488 14489 if (!isSupported) { 14490 element.setAttribute(eventName, 'return;'); 14491 isSupported = typeof element[eventName] === 'function'; 14492 if (typeof element[eventName] !== 'undefined') { 14493 element[eventName] = undefined; 14494 } 14495 element.removeAttribute(eventName); 14496 } 14497 14498 if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') { 14499 // This is the only way to test support for the `wheel` event in IE9+. 14500 isSupported = document.implementation.hasFeature('Events.wheel', '3.0'); 14501 } 14502 14503 element = null; 14504 return isSupported; 14505 } 14506 14507 module.exports = isEventSupported; 14508 14509 },{"./ExecutionEnvironment":21}],111:[function(require,module,exports){ 14510 /** 14511 * Copyright 2013 Facebook, Inc. 14512 * 14513 * Licensed under the Apache License, Version 2.0 (the "License"); 14514 * you may not use this file except in compliance with the License. 14515 * You may obtain a copy of the License at 14516 * 14517 * http://www.apache.org/licenses/LICENSE-2.0 14518 * 14519 * Unless required by applicable law or agreed to in writing, software 14520 * distributed under the License is distributed on an "AS IS" BASIS, 14521 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14522 * See the License for the specific language governing permissions and 14523 * limitations under the License. 14524 * 14525 * @providesModule isNode 14526 * @typechecks 14527 */ 14528 14529 /** 14530 * @param {*} object The object to check. 14531 * @return {boolean} Whether or not the object is a DOM node. 14532 */ 14533 function isNode(object) { 14534 return !!(object && ( 14535 typeof Node !== 'undefined' ? object instanceof Node : 14536 typeof object === 'object' && 14537 typeof object.nodeType === 'number' && 14538 typeof object.nodeName === 'string' 14539 )); 14540 } 14541 14542 module.exports = isNode; 14543 14544 },{}],112:[function(require,module,exports){ 14545 /** 14546 * Copyright 2013 Facebook, Inc. 14547 * 14548 * Licensed under the Apache License, Version 2.0 (the "License"); 14549 * you may not use this file except in compliance with the License. 14550 * You may obtain a copy of the License at 14551 * 14552 * http://www.apache.org/licenses/LICENSE-2.0 14553 * 14554 * Unless required by applicable law or agreed to in writing, software 14555 * distributed under the License is distributed on an "AS IS" BASIS, 14556 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14557 * See the License for the specific language governing permissions and 14558 * limitations under the License. 14559 * 14560 * @providesModule isTextInputElement 14561 */ 14562 14563 "use strict"; 14564 14565 /** 14566 * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 14567 */ 14568 var supportedInputTypes = { 14569 'color': true, 14570 'date': true, 14571 'datetime': true, 14572 'datetime-local': true, 14573 'email': true, 14574 'month': true, 14575 'number': true, 14576 'password': true, 14577 'range': true, 14578 'search': true, 14579 'tel': true, 14580 'text': true, 14581 'time': true, 14582 'url': true, 14583 'week': true 14584 }; 14585 14586 function isTextInputElement(elem) { 14587 return elem && ( 14588 (elem.nodeName === 'INPUT' && supportedInputTypes[elem.type]) || 14589 elem.nodeName === 'TEXTAREA' 14590 ); 14591 } 14592 14593 module.exports = isTextInputElement; 14594 14595 },{}],113:[function(require,module,exports){ 14596 /** 14597 * Copyright 2013 Facebook, Inc. 14598 * 14599 * Licensed under the Apache License, Version 2.0 (the "License"); 14600 * you may not use this file except in compliance with the License. 14601 * You may obtain a copy of the License at 14602 * 14603 * http://www.apache.org/licenses/LICENSE-2.0 14604 * 14605 * Unless required by applicable law or agreed to in writing, software 14606 * distributed under the License is distributed on an "AS IS" BASIS, 14607 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14608 * See the License for the specific language governing permissions and 14609 * limitations under the License. 14610 * 14611 * @providesModule isTextNode 14612 * @typechecks 14613 */ 14614 14615 var isNode = require("./isNode"); 14616 14617 /** 14618 * @param {*} object The object to check. 14619 * @return {boolean} Whether or not the object is a DOM text node. 14620 */ 14621 function isTextNode(object) { 14622 return isNode(object) && object.nodeType == 3; 14623 } 14624 14625 module.exports = isTextNode; 14626 14627 },{"./isNode":111}],114:[function(require,module,exports){ 14628 /** 14629 * Copyright 2013 Facebook, Inc. 14630 * 14631 * Licensed under the Apache License, Version 2.0 (the "License"); 14632 * you may not use this file except in compliance with the License. 14633 * You may obtain a copy of the License at 14634 * 14635 * http://www.apache.org/licenses/LICENSE-2.0 14636 * 14637 * Unless required by applicable law or agreed to in writing, software 14638 * distributed under the License is distributed on an "AS IS" BASIS, 14639 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14640 * See the License for the specific language governing permissions and 14641 * limitations under the License. 14642 * 14643 * @providesModule joinClasses 14644 * @typechecks static-only 14645 */ 14646 14647 "use strict"; 14648 14649 /** 14650 * Combines multiple className strings into one. 14651 * http://jsperf.com/joinclasses-args-vs-array 14652 * 14653 * @param {...?string} classes 14654 * @return {string} 14655 */ 14656 function joinClasses(className/*, ... */) { 14657 if (!className) { 14658 className = ''; 14659 } 14660 var nextClass; 14661 var argLength = arguments.length; 14662 if (argLength > 1) { 14663 for (var ii = 1; ii < argLength; ii++) { 14664 nextClass = arguments[ii]; 14665 nextClass && (className += ' ' + nextClass); 14666 } 14667 } 14668 return className; 14669 } 14670 14671 module.exports = joinClasses; 14672 14673 },{}],115:[function(require,module,exports){ 14674 /** 14675 * Copyright 2013 Facebook, Inc. 14676 * 14677 * Licensed under the Apache License, Version 2.0 (the "License"); 14678 * you may not use this file except in compliance with the License. 14679 * You may obtain a copy of the License at 14680 * 14681 * http://www.apache.org/licenses/LICENSE-2.0 14682 * 14683 * Unless required by applicable law or agreed to in writing, software 14684 * distributed under the License is distributed on an "AS IS" BASIS, 14685 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14686 * See the License for the specific language governing permissions and 14687 * limitations under the License. 14688 * 14689 * @providesModule keyMirror 14690 * @typechecks static-only 14691 */ 14692 14693 "use strict"; 14694 14695 var invariant = require("./invariant"); 14696 14697 /** 14698 * Constructs an enumeration with keys equal to their value. 14699 * 14700 * For example: 14701 * 14702 * var COLORS = keyMirror({blue: null, red: null}); 14703 * var myColor = COLORS.blue; 14704 * var isColorValid = !!COLORS[myColor]; 14705 * 14706 * The last line could not be performed if the values of the generated enum were 14707 * not equal to their keys. 14708 * 14709 * Input: {key1: val1, key2: val2} 14710 * Output: {key1: key1, key2: key2} 14711 * 14712 * @param {object} obj 14713 * @return {object} 14714 */ 14715 var keyMirror = function(obj) { 14716 var ret = {}; 14717 var key; 14718 ("production" !== "development" ? invariant( 14719 obj instanceof Object && !Array.isArray(obj), 14720 'keyMirror(...): Argument must be an object.' 14721 ) : invariant(obj instanceof Object && !Array.isArray(obj))); 14722 for (key in obj) { 14723 if (!obj.hasOwnProperty(key)) { 14724 continue; 14725 } 14726 ret[key] = key; 14727 } 14728 return ret; 14729 }; 14730 14731 module.exports = keyMirror; 14732 14733 },{"./invariant":109}],116:[function(require,module,exports){ 14734 /** 14735 * Copyright 2013 Facebook, Inc. 14736 * 14737 * Licensed under the Apache License, Version 2.0 (the "License"); 14738 * you may not use this file except in compliance with the License. 14739 * You may obtain a copy of the License at 14740 * 14741 * http://www.apache.org/licenses/LICENSE-2.0 14742 * 14743 * Unless required by applicable law or agreed to in writing, software 14744 * distributed under the License is distributed on an "AS IS" BASIS, 14745 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14746 * See the License for the specific language governing permissions and 14747 * limitations under the License. 14748 * 14749 * @providesModule keyOf 14750 */ 14751 14752 /** 14753 * Allows extraction of a minified key. Let's the build system minify keys 14754 * without loosing the ability to dynamically use key strings as values 14755 * themselves. Pass in an object with a single key/val pair and it will return 14756 * you the string key of that single record. Suppose you want to grab the 14757 * value for a key 'className' inside of an object. Key/val minification may 14758 * have aliased that key to be 'xa12'. keyOf({className: null}) will return 14759 * 'xa12' in that case. Resolve keys you want to use once at startup time, then 14760 * reuse those resolutions. 14761 */ 14762 var keyOf = function(oneKeyObj) { 14763 var key; 14764 for (key in oneKeyObj) { 14765 if (!oneKeyObj.hasOwnProperty(key)) { 14766 continue; 14767 } 14768 return key; 14769 } 14770 return null; 14771 }; 14772 14773 14774 module.exports = keyOf; 14775 14776 },{}],117:[function(require,module,exports){ 14777 /** 14778 * Copyright 2013 Facebook, Inc. 14779 * 14780 * Licensed under the Apache License, Version 2.0 (the "License"); 14781 * you may not use this file except in compliance with the License. 14782 * You may obtain a copy of the License at 14783 * 14784 * http://www.apache.org/licenses/LICENSE-2.0 14785 * 14786 * Unless required by applicable law or agreed to in writing, software 14787 * distributed under the License is distributed on an "AS IS" BASIS, 14788 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14789 * See the License for the specific language governing permissions and 14790 * limitations under the License. 14791 * 14792 * @providesModule memoizeStringOnly 14793 * @typechecks static-only 14794 */ 14795 14796 "use strict"; 14797 14798 /** 14799 * Memoizes the return value of a function that accepts one string argument. 14800 * 14801 * @param {function} callback 14802 * @return {function} 14803 */ 14804 function memoizeStringOnly(callback) { 14805 var cache = {}; 14806 return function(string) { 14807 if (cache.hasOwnProperty(string)) { 14808 return cache[string]; 14809 } else { 14810 return cache[string] = callback.call(this, string); 14811 } 14812 }; 14813 } 14814 14815 module.exports = memoizeStringOnly; 14816 14817 },{}],118:[function(require,module,exports){ 14818 /** 14819 * Copyright 2013 Facebook, Inc. 14820 * 14821 * Licensed under the Apache License, Version 2.0 (the "License"); 14822 * you may not use this file except in compliance with the License. 14823 * You may obtain a copy of the License at 14824 * 14825 * http://www.apache.org/licenses/LICENSE-2.0 14826 * 14827 * Unless required by applicable law or agreed to in writing, software 14828 * distributed under the License is distributed on an "AS IS" BASIS, 14829 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14830 * See the License for the specific language governing permissions and 14831 * limitations under the License. 14832 * 14833 * @providesModule merge 14834 */ 14835 14836 "use strict"; 14837 14838 var mergeInto = require("./mergeInto"); 14839 14840 /** 14841 * Shallow merges two structures into a return value, without mutating either. 14842 * 14843 * @param {?object} one Optional object with properties to merge from. 14844 * @param {?object} two Optional object with properties to merge from. 14845 * @return {object} The shallow extension of one by two. 14846 */ 14847 var merge = function(one, two) { 14848 var result = {}; 14849 mergeInto(result, one); 14850 mergeInto(result, two); 14851 return result; 14852 }; 14853 14854 module.exports = merge; 14855 14856 },{"./mergeInto":120}],119:[function(require,module,exports){ 14857 /** 14858 * Copyright 2013 Facebook, Inc. 14859 * 14860 * Licensed under the Apache License, Version 2.0 (the "License"); 14861 * you may not use this file except in compliance with the License. 14862 * You may obtain a copy of the License at 14863 * 14864 * http://www.apache.org/licenses/LICENSE-2.0 14865 * 14866 * Unless required by applicable law or agreed to in writing, software 14867 * distributed under the License is distributed on an "AS IS" BASIS, 14868 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14869 * See the License for the specific language governing permissions and 14870 * limitations under the License. 14871 * 14872 * @providesModule mergeHelpers 14873 * 14874 * requiresPolyfills: Array.isArray 14875 */ 14876 14877 "use strict"; 14878 14879 var invariant = require("./invariant"); 14880 var keyMirror = require("./keyMirror"); 14881 14882 /** 14883 * Maximum number of levels to traverse. Will catch circular structures. 14884 * @const 14885 */ 14886 var MAX_MERGE_DEPTH = 36; 14887 14888 /** 14889 * We won't worry about edge cases like new String('x') or new Boolean(true). 14890 * Functions are considered terminals, and arrays are not. 14891 * @param {*} o The item/object/value to test. 14892 * @return {boolean} true iff the argument is a terminal. 14893 */ 14894 var isTerminal = function(o) { 14895 return typeof o !== 'object' || o === null; 14896 }; 14897 14898 var mergeHelpers = { 14899 14900 MAX_MERGE_DEPTH: MAX_MERGE_DEPTH, 14901 14902 isTerminal: isTerminal, 14903 14904 /** 14905 * Converts null/undefined values into empty object. 14906 * 14907 * @param {?Object=} arg Argument to be normalized (nullable optional) 14908 * @return {!Object} 14909 */ 14910 normalizeMergeArg: function(arg) { 14911 return arg === undefined || arg === null ? {} : arg; 14912 }, 14913 14914 /** 14915 * If merging Arrays, a merge strategy *must* be supplied. If not, it is 14916 * likely the caller's fault. If this function is ever called with anything 14917 * but `one` and `two` being `Array`s, it is the fault of the merge utilities. 14918 * 14919 * @param {*} one Array to merge into. 14920 * @param {*} two Array to merge from. 14921 */ 14922 checkMergeArrayArgs: function(one, two) { 14923 ("production" !== "development" ? invariant( 14924 Array.isArray(one) && Array.isArray(two), 14925 'Critical assumptions about the merge functions have been violated. ' + 14926 'This is the fault of the merge functions themselves, not necessarily ' + 14927 'the callers.' 14928 ) : invariant(Array.isArray(one) && Array.isArray(two))); 14929 }, 14930 14931 /** 14932 * @param {*} one Object to merge into. 14933 * @param {*} two Object to merge from. 14934 */ 14935 checkMergeObjectArgs: function(one, two) { 14936 mergeHelpers.checkMergeObjectArg(one); 14937 mergeHelpers.checkMergeObjectArg(two); 14938 }, 14939 14940 /** 14941 * @param {*} arg 14942 */ 14943 checkMergeObjectArg: function(arg) { 14944 ("production" !== "development" ? invariant( 14945 !isTerminal(arg) && !Array.isArray(arg), 14946 'Critical assumptions about the merge functions have been violated. ' + 14947 'This is the fault of the merge functions themselves, not necessarily ' + 14948 'the callers.' 14949 ) : invariant(!isTerminal(arg) && !Array.isArray(arg))); 14950 }, 14951 14952 /** 14953 * Checks that a merge was not given a circular object or an object that had 14954 * too great of depth. 14955 * 14956 * @param {number} Level of recursion to validate against maximum. 14957 */ 14958 checkMergeLevel: function(level) { 14959 ("production" !== "development" ? invariant( 14960 level < MAX_MERGE_DEPTH, 14961 'Maximum deep merge depth exceeded. You may be attempting to merge ' + 14962 'circular structures in an unsupported way.' 14963 ) : invariant(level < MAX_MERGE_DEPTH)); 14964 }, 14965 14966 /** 14967 * Checks that the supplied merge strategy is valid. 14968 * 14969 * @param {string} Array merge strategy. 14970 */ 14971 checkArrayStrategy: function(strategy) { 14972 ("production" !== "development" ? invariant( 14973 strategy === undefined || strategy in mergeHelpers.ArrayStrategies, 14974 'You must provide an array strategy to deep merge functions to ' + 14975 'instruct the deep merge how to resolve merging two arrays.' 14976 ) : invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies)); 14977 }, 14978 14979 /** 14980 * Set of possible behaviors of merge algorithms when encountering two Arrays 14981 * that must be merged together. 14982 * - `clobber`: The left `Array` is ignored. 14983 * - `indexByIndex`: The result is achieved by recursively deep merging at 14984 * each index. (not yet supported.) 14985 */ 14986 ArrayStrategies: keyMirror({ 14987 Clobber: true, 14988 IndexByIndex: true 14989 }) 14990 14991 }; 14992 14993 module.exports = mergeHelpers; 14994 14995 },{"./invariant":109,"./keyMirror":115}],120:[function(require,module,exports){ 14996 /** 14997 * Copyright 2013 Facebook, Inc. 14998 * 14999 * Licensed under the Apache License, Version 2.0 (the "License"); 15000 * you may not use this file except in compliance with the License. 15001 * You may obtain a copy of the License at 15002 * 15003 * http://www.apache.org/licenses/LICENSE-2.0 15004 * 15005 * Unless required by applicable law or agreed to in writing, software 15006 * distributed under the License is distributed on an "AS IS" BASIS, 15007 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15008 * See the License for the specific language governing permissions and 15009 * limitations under the License. 15010 * 15011 * @providesModule mergeInto 15012 * @typechecks static-only 15013 */ 15014 15015 "use strict"; 15016 15017 var mergeHelpers = require("./mergeHelpers"); 15018 15019 var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg; 15020 15021 /** 15022 * Shallow merges two structures by mutating the first parameter. 15023 * 15024 * @param {object} one Object to be merged into. 15025 * @param {?object} two Optional object with properties to merge from. 15026 */ 15027 function mergeInto(one, two) { 15028 checkMergeObjectArg(one); 15029 if (two != null) { 15030 checkMergeObjectArg(two); 15031 for (var key in two) { 15032 if (!two.hasOwnProperty(key)) { 15033 continue; 15034 } 15035 one[key] = two[key]; 15036 } 15037 } 15038 } 15039 15040 module.exports = mergeInto; 15041 15042 },{"./mergeHelpers":119}],121:[function(require,module,exports){ 15043 /** 15044 * Copyright 2013 Facebook, Inc. 15045 * 15046 * Licensed under the Apache License, Version 2.0 (the "License"); 15047 * you may not use this file except in compliance with the License. 15048 * You may obtain a copy of the License at 15049 * 15050 * http://www.apache.org/licenses/LICENSE-2.0 15051 * 15052 * Unless required by applicable law or agreed to in writing, software 15053 * distributed under the License is distributed on an "AS IS" BASIS, 15054 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15055 * See the License for the specific language governing permissions and 15056 * limitations under the License. 15057 * 15058 * @providesModule mixInto 15059 */ 15060 15061 "use strict"; 15062 15063 /** 15064 * Simply copies properties to the prototype. 15065 */ 15066 var mixInto = function(constructor, methodBag) { 15067 var methodName; 15068 for (methodName in methodBag) { 15069 if (!methodBag.hasOwnProperty(methodName)) { 15070 continue; 15071 } 15072 constructor.prototype[methodName] = methodBag[methodName]; 15073 } 15074 }; 15075 15076 module.exports = mixInto; 15077 15078 },{}],122:[function(require,module,exports){ 15079 /** 15080 * Copyright 2013 Facebook, Inc. 15081 * 15082 * Licensed under the Apache License, Version 2.0 (the "License"); 15083 * you may not use this file except in compliance with the License. 15084 * You may obtain a copy of the License at 15085 * 15086 * http://www.apache.org/licenses/LICENSE-2.0 15087 * 15088 * Unless required by applicable law or agreed to in writing, software 15089 * distributed under the License is distributed on an "AS IS" BASIS, 15090 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15091 * See the License for the specific language governing permissions and 15092 * limitations under the License. 15093 * 15094 * @providesModule mutateHTMLNodeWithMarkup 15095 * @typechecks static-only 15096 */ 15097 15098 /*jslint evil: true */ 15099 15100 'use strict'; 15101 15102 var createNodesFromMarkup = require("./createNodesFromMarkup"); 15103 var filterAttributes = require("./filterAttributes"); 15104 var invariant = require("./invariant"); 15105 15106 /** 15107 * You can't set the innerHTML of a document. Unless you have 15108 * this function. 15109 * 15110 * @param {DOMElement} node with tagName == 'html' 15111 * @param {string} markup markup string including <html>. 15112 */ 15113 function mutateHTMLNodeWithMarkup(node, markup) { 15114 ("production" !== "development" ? invariant( 15115 node.tagName.toLowerCase() === 'html', 15116 'mutateHTMLNodeWithMarkup(): node must have tagName of "html", got %s', 15117 node.tagName 15118 ) : invariant(node.tagName.toLowerCase() === 'html')); 15119 15120 markup = markup.trim(); 15121 ("production" !== "development" ? invariant( 15122 markup.toLowerCase().indexOf('<html') === 0, 15123 'mutateHTMLNodeWithMarkup(): markup must start with <html' 15124 ) : invariant(markup.toLowerCase().indexOf('<html') === 0)); 15125 15126 // First let's extract the various pieces of markup. 15127 var htmlOpenTagEnd = markup.indexOf('>') + 1; 15128 var htmlCloseTagStart = markup.lastIndexOf('<'); 15129 var htmlOpenTag = markup.substring(0, htmlOpenTagEnd); 15130 var innerHTML = markup.substring(htmlOpenTagEnd, htmlCloseTagStart); 15131 15132 // Now for the fun stuff. Pass through both sets of attributes and 15133 // bring them up-to-date. We get the new set by creating a markup 15134 // fragment. 15135 var shouldExtractAttributes = htmlOpenTag.indexOf(' ') > -1; 15136 var attributeHolder = null; 15137 15138 if (shouldExtractAttributes) { 15139 // We extract the attributes by creating a <span> and evaluating 15140 // the node. 15141 attributeHolder = createNodesFromMarkup( 15142 htmlOpenTag.replace('html ', 'span ') + '</span>' 15143 )[0]; 15144 15145 // Add all attributes present in attributeHolder 15146 var attributesToSet = filterAttributes( 15147 attributeHolder, 15148 function(attr) { 15149 return node.getAttributeNS(attr.namespaceURI, attr.name) !== attr.value; 15150 } 15151 ); 15152 attributesToSet.forEach(function(attr) { 15153 node.setAttributeNS(attr.namespaceURI, attr.name, attr.value); 15154 }); 15155 } 15156 15157 // Remove all attributes not present in attributeHolder 15158 var attributesToRemove = filterAttributes( 15159 node, 15160 function(attr) { 15161 // Remove all attributes if attributeHolder is null or if it does not have 15162 // the desired attribute. 15163 return !( 15164 attributeHolder && 15165 attributeHolder.hasAttributeNS(attr.namespaceURI, attr.name) 15166 ); 15167 } 15168 ); 15169 attributesToRemove.forEach(function(attr) { 15170 node.removeAttributeNS(attr.namespaceURI, attr.name); 15171 }); 15172 15173 // Finally, set the inner HTML. No tricks needed. Do this last to 15174 // minimize likelihood of triggering reflows. 15175 node.innerHTML = innerHTML; 15176 } 15177 15178 module.exports = mutateHTMLNodeWithMarkup; 15179 15180 },{"./createNodesFromMarkup":90,"./filterAttributes":97,"./invariant":109}],123:[function(require,module,exports){ 15181 /** 15182 * Copyright 2013 Facebook, Inc. 15183 * 15184 * Licensed under the Apache License, Version 2.0 (the "License"); 15185 * you may not use this file except in compliance with the License. 15186 * You may obtain a copy of the License at 15187 * 15188 * http://www.apache.org/licenses/LICENSE-2.0 15189 * 15190 * Unless required by applicable law or agreed to in writing, software 15191 * distributed under the License is distributed on an "AS IS" BASIS, 15192 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15193 * See the License for the specific language governing permissions and 15194 * limitations under the License. 15195 * 15196 * @providesModule objMap 15197 */ 15198 15199 "use strict"; 15200 15201 /** 15202 * For each key/value pair, invokes callback func and constructs a resulting 15203 * object which contains, for every key in obj, values that are the result of 15204 * of invoking the function: 15205 * 15206 * func(value, key, iteration) 15207 * 15208 * @param {?object} obj Object to map keys over 15209 * @param {function} func Invoked for each key/val pair. 15210 * @param {?*} context 15211 * @return {?object} Result of mapping or null if obj is falsey 15212 */ 15213 function objMap(obj, func, context) { 15214 if (!obj) { 15215 return null; 15216 } 15217 var i = 0; 15218 var ret = {}; 15219 for (var key in obj) { 15220 if (obj.hasOwnProperty(key)) { 15221 ret[key] = func.call(context, obj[key], key, i++); 15222 } 15223 } 15224 return ret; 15225 } 15226 15227 module.exports = objMap; 15228 15229 },{}],124:[function(require,module,exports){ 15230 /** 15231 * Copyright 2013 Facebook, Inc. 15232 * 15233 * Licensed under the Apache License, Version 2.0 (the "License"); 15234 * you may not use this file except in compliance with the License. 15235 * You may obtain a copy of the License at 15236 * 15237 * http://www.apache.org/licenses/LICENSE-2.0 15238 * 15239 * Unless required by applicable law or agreed to in writing, software 15240 * distributed under the License is distributed on an "AS IS" BASIS, 15241 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15242 * See the License for the specific language governing permissions and 15243 * limitations under the License. 15244 * 15245 * @providesModule objMapKeyVal 15246 */ 15247 15248 "use strict"; 15249 15250 /** 15251 * Behaves the same as `objMap` but invokes func with the key first, and value 15252 * second. Use `objMap` unless you need this special case. 15253 * Invokes func as: 15254 * 15255 * func(key, value, iteration) 15256 * 15257 * @param {?object} obj Object to map keys over 15258 * @param {!function} func Invoked for each key/val pair. 15259 * @param {?*} context 15260 * @return {?object} Result of mapping or null if obj is falsey 15261 */ 15262 function objMapKeyVal(obj, func, context) { 15263 if (!obj) { 15264 return null; 15265 } 15266 var i = 0; 15267 var ret = {}; 15268 for (var key in obj) { 15269 if (obj.hasOwnProperty(key)) { 15270 ret[key] = func.call(context, key, obj[key], i++); 15271 } 15272 } 15273 return ret; 15274 } 15275 15276 module.exports = objMapKeyVal; 15277 15278 },{}],125:[function(require,module,exports){ 15279 /** 15280 * Copyright 2013 Facebook, Inc. 15281 * 15282 * Licensed under the Apache License, Version 2.0 (the "License"); 15283 * you may not use this file except in compliance with the License. 15284 * You may obtain a copy of the License at 15285 * 15286 * http://www.apache.org/licenses/LICENSE-2.0 15287 * 15288 * Unless required by applicable law or agreed to in writing, software 15289 * distributed under the License is distributed on an "AS IS" BASIS, 15290 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15291 * See the License for the specific language governing permissions and 15292 * limitations under the License. 15293 * 15294 * @providesModule performanceNow 15295 * @typechecks static-only 15296 */ 15297 15298 "use strict"; 15299 15300 var ExecutionEnvironment = require("./ExecutionEnvironment"); 15301 15302 /** 15303 * Detect if we can use window.performance.now() and gracefully 15304 * fallback to Date.now() if it doesn't exist. 15305 * We need to support Firefox < 15 for now due to Facebook's webdriver 15306 * infrastructure. 15307 */ 15308 var performance = null; 15309 15310 if (ExecutionEnvironment.canUseDOM) { 15311 performance = window.performance || window.webkitPerformance; 15312 } 15313 15314 if (!performance || !performance.now) { 15315 performance = Date; 15316 } 15317 15318 var performanceNow = performance.now.bind(performance); 15319 15320 module.exports = performanceNow; 15321 15322 },{"./ExecutionEnvironment":21}],126:[function(require,module,exports){ 15323 /** 15324 * Copyright 2013 Facebook, Inc. 15325 * 15326 * Licensed under the Apache License, Version 2.0 (the "License"); 15327 * you may not use this file except in compliance with the License. 15328 * You may obtain a copy of the License at 15329 * 15330 * http://www.apache.org/licenses/LICENSE-2.0 15331 * 15332 * Unless required by applicable law or agreed to in writing, software 15333 * distributed under the License is distributed on an "AS IS" BASIS, 15334 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15335 * See the License for the specific language governing permissions and 15336 * limitations under the License. 15337 * 15338 * @providesModule shallowEqual 15339 */ 15340 15341 "use strict"; 15342 15343 /** 15344 * Performs equality by iterating through keys on an object and returning 15345 * false when any key has values which are not strictly equal between 15346 * objA and objB. Returns true when the values of all keys are strictly equal. 15347 * 15348 * @return {boolean} 15349 */ 15350 function shallowEqual(objA, objB) { 15351 if (objA === objB) { 15352 return true; 15353 } 15354 var key; 15355 // Test for A's keys different from B. 15356 for (key in objA) { 15357 if (objA.hasOwnProperty(key) && 15358 (!objB.hasOwnProperty(key) || objA[key] !== objB[key])) { 15359 return false; 15360 } 15361 } 15362 // Test for B'a keys missing from A. 15363 for (key in objB) { 15364 if (objB.hasOwnProperty(key) && !objA.hasOwnProperty(key)) { 15365 return false; 15366 } 15367 } 15368 return true; 15369 } 15370 15371 module.exports = shallowEqual; 15372 15373 },{}],127:[function(require,module,exports){ 15374 /** 15375 * Copyright 2013 Facebook, Inc. 15376 * 15377 * Licensed under the Apache License, Version 2.0 (the "License"); 15378 * you may not use this file except in compliance with the License. 15379 * You may obtain a copy of the License at 15380 * 15381 * http://www.apache.org/licenses/LICENSE-2.0 15382 * 15383 * Unless required by applicable law or agreed to in writing, software 15384 * distributed under the License is distributed on an "AS IS" BASIS, 15385 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15386 * See the License for the specific language governing permissions and 15387 * limitations under the License. 15388 * 15389 * @providesModule traverseAllChildren 15390 */ 15391 15392 "use strict"; 15393 15394 var ReactComponent = require("./ReactComponent"); 15395 var ReactTextComponent = require("./ReactTextComponent"); 15396 15397 var invariant = require("./invariant"); 15398 15399 /** 15400 * TODO: Test that: 15401 * 1. `mapChildren` transforms strings and numbers into `ReactTextComponent`. 15402 * 2. it('should fail when supplied duplicate key', function() { 15403 * 3. That a single child and an array with one item have the same key pattern. 15404 * }); 15405 */ 15406 15407 /** 15408 * @param {?*} children Children tree container. 15409 * @param {!string} nameSoFar Name of the key path so far. 15410 * @param {!number} indexSoFar Number of children encountered until this point. 15411 * @param {!function} callback Callback to invoke with each child found. 15412 * @param {?*} traverseContext Used to pass information throughout the traversal 15413 * process. 15414 * @return {!number} The number of children in this subtree. 15415 */ 15416 var traverseAllChildrenImpl = 15417 function(children, nameSoFar, indexSoFar, callback, traverseContext) { 15418 var subtreeCount = 0; // Count of children found in the current subtree. 15419 if (Array.isArray(children)) { 15420 for (var i = 0; i < children.length; i++) { 15421 var child = children[i]; 15422 var nextName = nameSoFar + ReactComponent.getKey(child, i); 15423 var nextIndex = indexSoFar + subtreeCount; 15424 subtreeCount += traverseAllChildrenImpl( 15425 child, 15426 nextName, 15427 nextIndex, 15428 callback, 15429 traverseContext 15430 ); 15431 } 15432 } else { 15433 var type = typeof children; 15434 var isOnlyChild = nameSoFar === ''; 15435 // If it's the only child, treat the name as if it was wrapped in an array 15436 // so that it's consistent if the number of children grows 15437 var storageName = isOnlyChild ? 15438 ReactComponent.getKey(children, 0): 15439 nameSoFar; 15440 if (children === null || children === undefined || type === 'boolean') { 15441 // All of the above are perceived as null. 15442 callback(traverseContext, null, storageName, indexSoFar); 15443 subtreeCount = 1; 15444 } else if (children.mountComponentIntoNode) { 15445 callback(traverseContext, children, storageName, indexSoFar); 15446 subtreeCount = 1; 15447 } else { 15448 if (type === 'object') { 15449 ("production" !== "development" ? invariant( 15450 !children || children.nodeType !== 1, 15451 'traverseAllChildren(...): Encountered an invalid child; DOM ' + 15452 'elements are not valid children of React components.' 15453 ) : invariant(!children || children.nodeType !== 1)); 15454 for (var key in children) { 15455 if (children.hasOwnProperty(key)) { 15456 subtreeCount += traverseAllChildrenImpl( 15457 children[key], 15458 nameSoFar + '{' + key + '}', 15459 indexSoFar + subtreeCount, 15460 callback, 15461 traverseContext 15462 ); 15463 } 15464 } 15465 } else if (type === 'string') { 15466 var normalizedText = new ReactTextComponent(children); 15467 callback(traverseContext, normalizedText, storageName, indexSoFar); 15468 subtreeCount += 1; 15469 } else if (type === 'number') { 15470 var normalizedNumber = new ReactTextComponent('' + children); 15471 callback(traverseContext, normalizedNumber, storageName, indexSoFar); 15472 subtreeCount += 1; 15473 } 15474 } 15475 } 15476 return subtreeCount; 15477 }; 15478 15479 /** 15480 * Traverses children that are typically specified as `props.children`, but 15481 * might also be specified through attributes: 15482 * 15483 * - `traverseAllChildren(this.props.children, ...)` 15484 * - `traverseAllChildren(this.props.leftPanelChildren, ...)` 15485 * 15486 * The `traverseContext` is an optional argument that is passed through the 15487 * entire traversal. It can be used to store accumulations or anything else that 15488 * the callback might find relevant. 15489 * 15490 * @param {?*} children Children tree object. 15491 * @param {!function} callback To invoke upon traversing each child. 15492 * @param {?*} traverseContext Context for traversal. 15493 */ 15494 function traverseAllChildren(children, callback, traverseContext) { 15495 if (children !== null && children !== undefined) { 15496 traverseAllChildrenImpl(children, '', 0, callback, traverseContext); 15497 } 15498 } 15499 15500 module.exports = traverseAllChildren; 15501 15502 },{"./ReactComponent":28,"./ReactTextComponent":65,"./invariant":109}]},{},[71]) 15503 (71) 15504 }); 15505 ;