1 | var textDiff = require('./textDiff');
|
2 |
|
3 | exports.add = addDocumentListeners;
|
4 | exports.inputSupportsSelection = inputSupportsSelection;
|
5 |
|
6 |
|
7 |
|
8 | function inputSupportsSelection(input) {
|
9 | var type = input.type;
|
10 | return (
|
11 | type === 'text' ||
|
12 | type === 'textarea' ||
|
13 | type === 'search' ||
|
14 | type === 'url' ||
|
15 | type === 'tel' ||
|
16 | type === 'password'
|
17 | );
|
18 | }
|
19 | function inputIsNumberValue(input) {
|
20 | var type = input.type;
|
21 | return (type === 'number' || (type === 'range' && !input.multiple));
|
22 | }
|
23 | var inputValue = function(input) {
|
24 | return inputIsNumberValue(input) ? input.valueAsNumber : input.value;
|
25 | };
|
26 |
|
27 | function addDocumentListeners(doc) {
|
28 | doc.addEventListener('input', documentInput, true);
|
29 | doc.addEventListener('change', documentChange, true);
|
30 |
|
31 |
|
32 | if (parseFloat(window.navigator.appVersion.split('MSIE ')[1]) <= 9) {
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | doc.addEventListener('selectionchange', function(e){
|
38 | if (document.activeElement) {
|
39 | documentInput({target: document.activeElement});
|
40 | }
|
41 | }, true);
|
42 | }
|
43 |
|
44 |
|
45 |
|
46 | var input = document.createElement('input');
|
47 | input.type = 'number';
|
48 | input.value = '7';
|
49 | if (input.valueAsNumber !== input.valueAsNumber) {
|
50 | var oldInputValue = inputValue;
|
51 | inputValue = function(input) {
|
52 | if (input.type === 'number') {
|
53 | return inputIsNumberValue(input) ? parseFloat(input.value) : input.value;
|
54 | } else {
|
55 | return oldInputValue.apply(this, arguments);
|
56 | }
|
57 | };
|
58 | }
|
59 | }
|
60 |
|
61 | function documentInput(e) {
|
62 | var target = e.target;
|
63 |
|
64 | if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
65 | setInputValue(e, target);
|
66 | }
|
67 | }
|
68 |
|
69 | function documentChange(e) {
|
70 | var target = e.target;
|
71 |
|
72 | if (target.tagName === 'INPUT') {
|
73 | setBoundProperty(target, 'checked');
|
74 | setInputValue(e, target);
|
75 |
|
76 | } else if (target.tagName === 'SELECT') {
|
77 | setOptionBindings(target);
|
78 |
|
79 | } else if (target.tagName === 'TEXTAREA') {
|
80 | setInputValue(e, target);
|
81 | }
|
82 | }
|
83 |
|
84 | function setBoundProperty(node, property) {
|
85 | var binding = node.$bindAttributes && node.$bindAttributes[property];
|
86 | if (!binding || binding.isUnbound()) return;
|
87 |
|
88 | var value = node[property];
|
89 | binding.template.expression.set(binding.context, value);
|
90 | }
|
91 |
|
92 | function setInputValue(e, target) {
|
93 | var binding = target.$bindAttributes && target.$bindAttributes.value;
|
94 | if (!binding || binding.isUnbound()) return;
|
95 |
|
96 | if (inputSupportsSelection(target)) {
|
97 | var pass = {$event: e};
|
98 | textDiffBinding(binding, target.value, pass);
|
99 | } else {
|
100 | var value = inputValue(target);
|
101 | binding.template.expression.set(binding.context, value);
|
102 | }
|
103 | }
|
104 |
|
105 | function textDiffBinding(binding, value, pass) {
|
106 | var expression = binding.template.expression;
|
107 | var segments = expression.pathSegments(binding.context);
|
108 | if (segments) {
|
109 | var model = binding.context.controller.model.pass(pass);
|
110 | textDiff.onTextInput(model, segments, value);
|
111 | } else if (expression.set) {
|
112 | expression.set(binding.context, value);
|
113 | }
|
114 | }
|
115 |
|
116 | function setOptionBindings(parent) {
|
117 | for (var node = parent.firstChild; node; node = node.nextSibling) {
|
118 | if (node.tagName === 'OPTION') {
|
119 | setBoundProperty(node, 'selected');
|
120 | } else if (node.hasChildNodes()) {
|
121 | setOptionBindings(node);
|
122 | }
|
123 | }
|
124 | }
|