trackValue.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. 'use strict';
  2. require('../utils/dataTransfer/Clipboard.js');
  3. var getWindow = require('../utils/misc/getWindow.js');
  4. var UI = require('./UI.js');
  5. const TrackChanges = Symbol('Track programmatic changes for React workaround');
  6. // When the input event happens in the browser, React executes all event handlers
  7. // and if they change state of a controlled value, nothing happens.
  8. // But when we trigger the event handlers in test environment with React@17,
  9. // the changes are rolled back before the state update is applied.
  10. // This results in a reset cursor.
  11. // There might be a better way to work around if we figure out
  12. // why the batched update is executed differently in our test environment.
  13. function isReact17Element(element) {
  14. return Object.getOwnPropertyNames(element).some((k)=>k.startsWith('__react')) && getWindow.getWindow(element).REACT_VERSION === 17;
  15. }
  16. function startTrackValue(element) {
  17. if (!isReact17Element(element)) {
  18. return;
  19. }
  20. element[TrackChanges] = {
  21. previousValue: String(element.value),
  22. tracked: []
  23. };
  24. }
  25. function trackOrSetValue(element, v) {
  26. var _element_TrackChanges_tracked, _element_TrackChanges;
  27. (_element_TrackChanges = element[TrackChanges]) === null || _element_TrackChanges === undefined ? undefined : (_element_TrackChanges_tracked = _element_TrackChanges.tracked) === null || _element_TrackChanges_tracked === undefined ? undefined : _element_TrackChanges_tracked.push(v);
  28. if (!element[TrackChanges]) {
  29. UI.setUIValueClean(element);
  30. UI.setUISelection(element, {
  31. focusOffset: v.length
  32. });
  33. }
  34. }
  35. function commitValueAfterInput(element, cursorOffset) {
  36. var _changes_tracked;
  37. const changes = element[TrackChanges];
  38. element[TrackChanges] = undefined;
  39. if (!(changes === null || changes === undefined ? undefined : (_changes_tracked = changes.tracked) === null || _changes_tracked === undefined ? undefined : _changes_tracked.length)) {
  40. return;
  41. }
  42. const isJustReactStateUpdate = changes.tracked.length === 2 && changes.tracked[0] === changes.previousValue && changes.tracked[1] === element.value;
  43. if (!isJustReactStateUpdate) {
  44. UI.setUIValueClean(element);
  45. }
  46. if (UI.hasUISelection(element)) {
  47. UI.setUISelection(element, {
  48. focusOffset: isJustReactStateUpdate ? cursorOffset : element.value.length
  49. });
  50. }
  51. }
  52. exports.commitValueAfterInput = commitValueAfterInput;
  53. exports.startTrackValue = startTrackValue;
  54. exports.trackOrSetValue = trackOrSetValue;