1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | 'use strict';
|
10 |
|
11 | var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
12 |
|
13 | function isCheckable(elem) {
|
14 | var type = elem.type;
|
15 | var nodeName = elem.nodeName;
|
16 | return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
|
17 | }
|
18 |
|
19 | function getTracker(inst) {
|
20 | return inst._wrapperState.valueTracker;
|
21 | }
|
22 |
|
23 | function attachTracker(inst, tracker) {
|
24 | inst._wrapperState.valueTracker = tracker;
|
25 | }
|
26 |
|
27 | function detachTracker(inst) {
|
28 | inst._wrapperState.valueTracker = null;
|
29 | }
|
30 |
|
31 | function getValueFromNode(node) {
|
32 | var value;
|
33 | if (node) {
|
34 | value = isCheckable(node) ? '' + node.checked : node.value;
|
35 | }
|
36 | return value;
|
37 | }
|
38 |
|
39 | var inputValueTracking = {
|
40 |
|
41 | _getTrackerFromNode: function (node) {
|
42 | return getTracker(ReactDOMComponentTree.getInstanceFromNode(node));
|
43 | },
|
44 |
|
45 |
|
46 | track: function (inst) {
|
47 | if (getTracker(inst)) {
|
48 | return;
|
49 | }
|
50 |
|
51 | var node = ReactDOMComponentTree.getNodeFromInstance(inst);
|
52 | var valueField = isCheckable(node) ? 'checked' : 'value';
|
53 | var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
|
54 |
|
55 | var currentValue = '' + node[valueField];
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | if (node.hasOwnProperty(valueField) || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
|
62 | return;
|
63 | }
|
64 |
|
65 | Object.defineProperty(node, valueField, {
|
66 | enumerable: descriptor.enumerable,
|
67 | configurable: true,
|
68 | get: function () {
|
69 | return descriptor.get.call(this);
|
70 | },
|
71 | set: function (value) {
|
72 | currentValue = '' + value;
|
73 | descriptor.set.call(this, value);
|
74 | }
|
75 | });
|
76 |
|
77 | attachTracker(inst, {
|
78 | getValue: function () {
|
79 | return currentValue;
|
80 | },
|
81 | setValue: function (value) {
|
82 | currentValue = '' + value;
|
83 | },
|
84 | stopTracking: function () {
|
85 | detachTracker(inst);
|
86 | delete node[valueField];
|
87 | }
|
88 | });
|
89 | },
|
90 |
|
91 | updateValueIfChanged: function (inst) {
|
92 | if (!inst) {
|
93 | return false;
|
94 | }
|
95 | var tracker = getTracker(inst);
|
96 |
|
97 | if (!tracker) {
|
98 | inputValueTracking.track(inst);
|
99 | return true;
|
100 | }
|
101 |
|
102 | var lastValue = tracker.getValue();
|
103 | var nextValue = getValueFromNode(ReactDOMComponentTree.getNodeFromInstance(inst));
|
104 |
|
105 | if (nextValue !== lastValue) {
|
106 | tracker.setValue(nextValue);
|
107 | return true;
|
108 | }
|
109 |
|
110 | return false;
|
111 | },
|
112 | stopTracking: function (inst) {
|
113 | var tracker = getTracker(inst);
|
114 | if (tracker) {
|
115 | tracker.stopTracking();
|
116 | }
|
117 | }
|
118 | };
|
119 |
|
120 | module.exports = inputValueTracking; |
\ | No newline at end of file |