@tko/binding.core 4.0.0-alpha8.4 → 4.0.0-beta1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attr.js +36 -0
- package/dist/attr.js.map +7 -0
- package/dist/checked.js +94 -0
- package/dist/checked.js.map +7 -0
- package/dist/click.js +5 -0
- package/dist/click.js.map +7 -0
- package/dist/css.js +28 -0
- package/dist/css.js.map +7 -0
- package/dist/descendantsComplete.js +14 -0
- package/dist/descendantsComplete.js.map +7 -0
- package/dist/enableDisable.js +21 -0
- package/dist/enableDisable.js.map +7 -0
- package/dist/event.js +75 -0
- package/dist/event.js.map +7 -0
- package/dist/hasfocus.js +48 -0
- package/dist/hasfocus.js.map +7 -0
- package/dist/html.js +15 -0
- package/dist/html.js.map +7 -0
- package/dist/index.cjs +3956 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +7 -0
- package/dist/index.mjs +50 -0
- package/dist/index.mjs.map +7 -0
- package/dist/let.js +12 -0
- package/dist/let.js.map +7 -0
- package/dist/options.js +130 -0
- package/dist/options.js.map +7 -0
- package/dist/selectedOptions.js +41 -0
- package/dist/selectedOptions.js.map +7 -0
- package/dist/style.js +30 -0
- package/dist/style.js.map +7 -0
- package/dist/submit.js +26 -0
- package/dist/submit.js.map +7 -0
- package/dist/test-helper.js +14 -0
- package/dist/test-helper.js.map +7 -0
- package/dist/text.js +13 -0
- package/dist/text.js.map +7 -0
- package/dist/textInput.js +151 -0
- package/dist/textInput.js.map +7 -0
- package/dist/uniqueName.js +13 -0
- package/dist/uniqueName.js.map +7 -0
- package/dist/using.js +12 -0
- package/dist/using.js.map +7 -0
- package/dist/value.js +103 -0
- package/dist/value.js.map +7 -0
- package/dist/visible.js +20 -0
- package/dist/visible.js.map +7 -0
- package/package.json +18 -28
- package/dist/binding.core.es6.js +0 -1044
- package/dist/binding.core.es6.js.map +0 -1
- package/dist/binding.core.js +0 -1143
- package/dist/binding.core.js.map +0 -1
package/dist/binding.core.js
DELETED
|
@@ -1,1143 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* TKO Core bindings 🥊 @tko/binding.core@4.0.0-alpha8.4
|
|
3
|
-
* (c) The Knockout.js Team - https://tko.io
|
|
4
|
-
* License: MIT (http://www.opensource.org/licenses/mit-license.php)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { setElementName, objectForEach, registerEventHandler, arrayIndexOf, addOrRemoveItem, throttle, debounce, createSymbolOrString, toggleDomNodeCssClass, stringTrim, triggerEvent, setHtml, tagNameLower, arrayFilter, arrayMap, setTextContent, setOptionNodeSelectionState, ensureSelectElementIsRenderedCorrectly, selectExtensions, arrayForEach, options, domData, ieVersion, safeSetTimeout, stringStartsWith } from '@tko/utils';
|
|
8
|
-
import { unwrap, dependencyDetection, isWriteableObservable } from '@tko/observable';
|
|
9
|
-
import { computed, pureComputed } from '@tko/computed';
|
|
10
|
-
import { BindingHandler, applyBindingsToDescendants, setDomNodeChildrenFromArrayMapping, applyBindingAccessorsToNode } from '@tko/bind';
|
|
11
|
-
|
|
12
|
-
var attr = {
|
|
13
|
-
update: function (element, valueAccessor, allBindings) {
|
|
14
|
-
var value = unwrap(valueAccessor()) || {};
|
|
15
|
-
objectForEach(value, function (attrName, attrValue) {
|
|
16
|
-
attrValue = unwrap(attrValue);
|
|
17
|
-
// Find the namespace of this attribute, if any.
|
|
18
|
-
var prefixLen = attrName.indexOf(':');
|
|
19
|
-
var namespace = prefixLen > 0 && element.lookupNamespaceURI(attrName.substr(0, prefixLen));
|
|
20
|
-
// To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
|
|
21
|
-
// when someProp is a "no value"-like value (strictly null, false, or undefined)
|
|
22
|
-
// (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
|
|
23
|
-
var toRemove = attrValue === false || attrValue === null || attrValue === undefined;
|
|
24
|
-
if (toRemove) {
|
|
25
|
-
if (namespace) {
|
|
26
|
-
element.removeAttributeNS(namespace, attrName);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
element.removeAttribute(attrName);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
attrValue = attrValue.toString();
|
|
34
|
-
if (namespace) {
|
|
35
|
-
element.setAttributeNS(namespace, attrName, attrValue);
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
element.setAttribute(attrName, attrValue);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// Treat "name" specially - although you can think of it as an attribute, it also needs
|
|
42
|
-
// special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
|
|
43
|
-
// Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
|
|
44
|
-
// entirely, and there's no strong reason to allow for such casing in HTML.
|
|
45
|
-
if (attrName === 'name') {
|
|
46
|
-
setElementName(element, toRemove ? '' : attrValue);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
var checked = {
|
|
53
|
-
after: ['value', 'attr'],
|
|
54
|
-
init: function (element, valueAccessor, allBindings) {
|
|
55
|
-
var checkedValue = pureComputed(function () {
|
|
56
|
-
// Treat "value" like "checkedValue" when it is included with "checked" binding
|
|
57
|
-
if (allBindings.has('checkedValue')) {
|
|
58
|
-
return unwrap(allBindings.get('checkedValue'));
|
|
59
|
-
}
|
|
60
|
-
else if (useElementValue) {
|
|
61
|
-
if (allBindings.has('value')) {
|
|
62
|
-
return unwrap(allBindings.get('value'));
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
return element.value;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
function updateModel() {
|
|
70
|
-
// This updates the model value from the view value.
|
|
71
|
-
// It runs in response to DOM events (click) and changes in checkedValue.
|
|
72
|
-
var isChecked = element.checked, elemValue = checkedValue();
|
|
73
|
-
// When we're first setting up this computed, don't change any model state.
|
|
74
|
-
if (dependencyDetection.isInitial()) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
// We can ignore unchecked radio buttons, because some other radio
|
|
78
|
-
// button will be checked, and that one can take care of updating state.
|
|
79
|
-
// button will be checked, and that one can take care of updating state
|
|
80
|
-
if (!isChecked && (isRadio || dependencyDetection.getDependenciesCount())) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
var modelValue = dependencyDetection.ignore(valueAccessor);
|
|
84
|
-
if (valueIsArray) {
|
|
85
|
-
var writableValue = rawValueIsNonArrayObservable ? modelValue.peek() : modelValue, saveOldValue = oldElemValue;
|
|
86
|
-
oldElemValue = elemValue;
|
|
87
|
-
if (saveOldValue !== elemValue) {
|
|
88
|
-
// When we're responding to the checkedValue changing, and the element is
|
|
89
|
-
// currently checked, replace the old elem value with the new elem value
|
|
90
|
-
// in the model array.
|
|
91
|
-
if (isChecked) {
|
|
92
|
-
addOrRemoveItem(writableValue, elemValue, true);
|
|
93
|
-
addOrRemoveItem(writableValue, saveOldValue, false);
|
|
94
|
-
}
|
|
95
|
-
oldElemValue = elemValue;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// When we're responding to the user having checked/unchecked a checkbox,
|
|
99
|
-
// add/remove the element value to the model array.
|
|
100
|
-
addOrRemoveItem(writableValue, elemValue, isChecked);
|
|
101
|
-
}
|
|
102
|
-
if (rawValueIsNonArrayObservable && isWriteableObservable(modelValue)) {
|
|
103
|
-
modelValue(writableValue);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
if (isCheckbox) {
|
|
108
|
-
if (elemValue === undefined) {
|
|
109
|
-
elemValue = isChecked;
|
|
110
|
-
}
|
|
111
|
-
else if (!isChecked) {
|
|
112
|
-
elemValue = undefined;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
valueAccessor(elemValue, { onlyIfChanged: true });
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function updateView() {
|
|
119
|
-
// This updates the view value from the model value.
|
|
120
|
-
// It runs in response to changes in the bound (checked) value.
|
|
121
|
-
var modelValue = modelValue = unwrap(valueAccessor());
|
|
122
|
-
var elemValue = checkedValue();
|
|
123
|
-
if (valueIsArray) {
|
|
124
|
-
// When a checkbox is bound to an array, being checked represents its value being present in that array
|
|
125
|
-
element.checked = arrayIndexOf(modelValue, elemValue) >= 0;
|
|
126
|
-
oldElemValue = elemValue;
|
|
127
|
-
}
|
|
128
|
-
else if (isCheckbox && elemValue === undefined) {
|
|
129
|
-
// When a checkbox is bound to any other value (not an array) and "checkedValue" is not defined,
|
|
130
|
-
// being checked represents the value being trueish
|
|
131
|
-
element.checked = !!modelValue;
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
// Otherwise, being checked means that the checkbox or radio button's value corresponds to the model value
|
|
135
|
-
element.checked = (checkedValue() === modelValue);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
var isCheckbox = element.type == 'checkbox', isRadio = element.type == 'radio';
|
|
139
|
-
// Only bind to check boxes and radio buttons
|
|
140
|
-
if (!isCheckbox && !isRadio) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
var rawValue = valueAccessor(), valueIsArray = isCheckbox && (unwrap(rawValue) instanceof Array), rawValueIsNonArrayObservable = !(valueIsArray && rawValue.push && rawValue.splice), useElementValue = isRadio || valueIsArray, oldElemValue = valueIsArray ? checkedValue() : undefined;
|
|
144
|
-
// Set up two computeds to update the binding:
|
|
145
|
-
// The first responds to changes in the checkedValue value and to element clicks
|
|
146
|
-
computed(updateModel, null, { disposeWhenNodeIsRemoved: element });
|
|
147
|
-
registerEventHandler(element, 'click', updateModel);
|
|
148
|
-
// The second responds to changes in the model value (the one associated with the checked binding)
|
|
149
|
-
computed(updateView, null, { disposeWhenNodeIsRemoved: element });
|
|
150
|
-
rawValue = undefined;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
var checkedValue = {
|
|
154
|
-
update: function (element, valueAccessor) {
|
|
155
|
-
element.value = unwrap(valueAccessor());
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
/*! *****************************************************************************
|
|
160
|
-
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
161
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
162
|
-
this file except in compliance with the License. You may obtain a copy of the
|
|
163
|
-
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
164
|
-
|
|
165
|
-
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
166
|
-
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
|
167
|
-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
168
|
-
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
169
|
-
|
|
170
|
-
See the Apache Version 2.0 License for specific language governing permissions
|
|
171
|
-
and limitations under the License.
|
|
172
|
-
***************************************************************************** */
|
|
173
|
-
/* global Reflect, Promise */
|
|
174
|
-
|
|
175
|
-
var extendStatics = Object.setPrototypeOf ||
|
|
176
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
177
|
-
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
178
|
-
|
|
179
|
-
function __extends(d, b) {
|
|
180
|
-
extendStatics(d, b);
|
|
181
|
-
function __() { this.constructor = d; }
|
|
182
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function __values(o) {
|
|
186
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
|
187
|
-
if (m) return m.call(o);
|
|
188
|
-
return {
|
|
189
|
-
next: function () {
|
|
190
|
-
if (o && i >= o.length) o = void 0;
|
|
191
|
-
return { value: o && o[i++], done: !o };
|
|
192
|
-
}
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function __read(o, n) {
|
|
197
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
198
|
-
if (!m) return o;
|
|
199
|
-
var i = m.call(o), r, ar = [], e;
|
|
200
|
-
try {
|
|
201
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
202
|
-
}
|
|
203
|
-
catch (error) { e = { error: error }; }
|
|
204
|
-
finally {
|
|
205
|
-
try {
|
|
206
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
207
|
-
}
|
|
208
|
-
finally { if (e) throw e.error; }
|
|
209
|
-
}
|
|
210
|
-
return ar;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function __spread() {
|
|
214
|
-
for (var ar = [], i = 0; i < arguments.length; i++)
|
|
215
|
-
ar = ar.concat(__read(arguments[i]));
|
|
216
|
-
return ar;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// For certain common events (currently just 'click'), allow a simplified data-binding syntax
|
|
220
|
-
// e.g. click:handler instead of the usual full-length event:{click:handler}
|
|
221
|
-
function makeEventHandlerShortcut(eventName) {
|
|
222
|
-
return {
|
|
223
|
-
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
224
|
-
var newValueAccessor = function () {
|
|
225
|
-
var result = {};
|
|
226
|
-
result[eventName] = valueAccessor();
|
|
227
|
-
return result;
|
|
228
|
-
};
|
|
229
|
-
eventHandler.init.call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
function makeDescriptor(handlerOrObject) {
|
|
234
|
-
return typeof handlerOrObject === 'function' ? { handler: handlerOrObject } : handlerOrObject || {};
|
|
235
|
-
}
|
|
236
|
-
var eventHandler = {
|
|
237
|
-
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
238
|
-
var eventsToHandle = valueAccessor() || {};
|
|
239
|
-
objectForEach(eventsToHandle, function (eventName, descriptor) {
|
|
240
|
-
var _a = makeDescriptor(descriptor), passive = _a.passive, capture = _a.capture, once = _a.once, debounce$$1 = _a.debounce, throttle$$1 = _a.throttle;
|
|
241
|
-
var eventOptions = (capture || passive || once) && { capture: capture, passive: passive, once: once };
|
|
242
|
-
var eventHandlerFn = function (event) {
|
|
243
|
-
var more = [];
|
|
244
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
245
|
-
more[_i - 1] = arguments[_i];
|
|
246
|
-
}
|
|
247
|
-
var handlerReturnValue;
|
|
248
|
-
var _a = makeDescriptor(valueAccessor()[eventName]), handler = _a.handler, passive = _a.passive, bubble = _a.bubble;
|
|
249
|
-
try {
|
|
250
|
-
// Take all the event args, and prefix with the viewmodel
|
|
251
|
-
if (handler) {
|
|
252
|
-
var possiblyUpdatedViewModel = bindingContext.$data;
|
|
253
|
-
var argsForHandler = __spread([possiblyUpdatedViewModel, event], more);
|
|
254
|
-
handlerReturnValue = handler.apply(possiblyUpdatedViewModel, argsForHandler);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
finally {
|
|
258
|
-
if (handlerReturnValue !== true) {
|
|
259
|
-
// Normally we want to prevent default action. Developer can override this be explicitly returning true.
|
|
260
|
-
// preventDefault will throw an error if the event is passive.
|
|
261
|
-
if (event.preventDefault) {
|
|
262
|
-
if (!passive) {
|
|
263
|
-
event.preventDefault();
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
event.returnValue = false;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
var bubbleMark = allBindings.get(eventName + 'Bubble') !== false;
|
|
272
|
-
if (bubble === false || !bubbleMark) {
|
|
273
|
-
event.cancelBubble = true;
|
|
274
|
-
if (event.stopPropagation) {
|
|
275
|
-
event.stopPropagation();
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
if (debounce$$1) {
|
|
280
|
-
eventHandlerFn = debounce(eventHandlerFn, debounce$$1);
|
|
281
|
-
}
|
|
282
|
-
if (throttle$$1) {
|
|
283
|
-
eventHandlerFn = throttle(eventHandlerFn, throttle$$1);
|
|
284
|
-
}
|
|
285
|
-
registerEventHandler(element, eventName, eventHandlerFn, eventOptions || false);
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
var onHandler = {
|
|
290
|
-
init: eventHandler.init,
|
|
291
|
-
preprocess: function (value, key, addBinding) {
|
|
292
|
-
addBinding(key.replace('on.', ''), '=>' + value);
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
// 'click' is just a shorthand for the usual full-length event:{click:handler}
|
|
297
|
-
var click = makeEventHandlerShortcut('click');
|
|
298
|
-
|
|
299
|
-
var css = {
|
|
300
|
-
aliases: ['class'],
|
|
301
|
-
update: function (element, valueAccessor) {
|
|
302
|
-
var value = unwrap(valueAccessor());
|
|
303
|
-
if (value !== null && typeof value === 'object') {
|
|
304
|
-
objectForEach(value, function (className, shouldHaveClass) {
|
|
305
|
-
shouldHaveClass = unwrap(shouldHaveClass);
|
|
306
|
-
toggleDomNodeCssClass(element, className, shouldHaveClass);
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
value = stringTrim(String(value || '')); // Make sure we don't try to store or set a non-string value
|
|
311
|
-
toggleDomNodeCssClass(element, element[css.classesWrittenByBindingKey], false);
|
|
312
|
-
element[css.classesWrittenByBindingKey] = value;
|
|
313
|
-
toggleDomNodeCssClass(element, value, true);
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
classesWrittenByBindingKey: createSymbolOrString('__ko__cssValue')
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
var DescendantsCompleteHandler = /** @class */ (function (_super) {
|
|
320
|
-
__extends(DescendantsCompleteHandler, _super);
|
|
321
|
-
function DescendantsCompleteHandler() {
|
|
322
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
323
|
-
}
|
|
324
|
-
DescendantsCompleteHandler.prototype.onDescendantsComplete = function () {
|
|
325
|
-
if (typeof this.value === 'function') {
|
|
326
|
-
this.value(this.$element);
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
Object.defineProperty(DescendantsCompleteHandler, "allowVirtualElements", {
|
|
330
|
-
get: function () { return true; },
|
|
331
|
-
enumerable: true,
|
|
332
|
-
configurable: true
|
|
333
|
-
});
|
|
334
|
-
return DescendantsCompleteHandler;
|
|
335
|
-
}(BindingHandler));
|
|
336
|
-
|
|
337
|
-
var enable = {
|
|
338
|
-
update: function (element, valueAccessor) {
|
|
339
|
-
var value = unwrap(valueAccessor());
|
|
340
|
-
if (value && element.disabled) {
|
|
341
|
-
element.removeAttribute('disabled');
|
|
342
|
-
}
|
|
343
|
-
else if ((!value) && (!element.disabled)) {
|
|
344
|
-
element.disabled = true;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
|
-
var disable = {
|
|
349
|
-
update: function (element, valueAccessor) {
|
|
350
|
-
enable.update(element, function () { return !unwrap(valueAccessor()); });
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
var hasfocusUpdatingProperty = createSymbolOrString('__ko_hasfocusUpdating');
|
|
355
|
-
var hasfocusLastValue = createSymbolOrString('__ko_hasfocusLastValue');
|
|
356
|
-
var hasfocus = {
|
|
357
|
-
init: function (element, valueAccessor /*, allBindings */) {
|
|
358
|
-
var handleElementFocusChange = function (isFocused) {
|
|
359
|
-
// Where possible, ignore which event was raised and determine focus state using activeElement,
|
|
360
|
-
// as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
|
|
361
|
-
// However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
|
|
362
|
-
// prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
|
|
363
|
-
// from calling 'blur()' on the element when it loses focus.
|
|
364
|
-
// Discussion at https://github.com/SteveSanderson/knockout/pull/352
|
|
365
|
-
element[hasfocusUpdatingProperty] = true;
|
|
366
|
-
var ownerDoc = element.ownerDocument;
|
|
367
|
-
if ('activeElement' in ownerDoc) {
|
|
368
|
-
var active;
|
|
369
|
-
try {
|
|
370
|
-
active = ownerDoc.activeElement;
|
|
371
|
-
}
|
|
372
|
-
catch (e) {
|
|
373
|
-
// IE9 throws if you access activeElement during page load (see issue #703)
|
|
374
|
-
active = ownerDoc.body;
|
|
375
|
-
}
|
|
376
|
-
isFocused = (active === element);
|
|
377
|
-
}
|
|
378
|
-
// var modelValue = valueAccessor();
|
|
379
|
-
valueAccessor(isFocused, { onlyIfChanged: true });
|
|
380
|
-
// cache the latest value, so we can avoid unnecessarily calling focus/blur in the update function
|
|
381
|
-
element[hasfocusLastValue] = isFocused;
|
|
382
|
-
element[hasfocusUpdatingProperty] = false;
|
|
383
|
-
};
|
|
384
|
-
var handleElementFocusIn = handleElementFocusChange.bind(null, true);
|
|
385
|
-
var handleElementFocusOut = handleElementFocusChange.bind(null, false);
|
|
386
|
-
registerEventHandler(element, 'focus', handleElementFocusIn);
|
|
387
|
-
registerEventHandler(element, 'focusin', handleElementFocusIn); // For IE
|
|
388
|
-
registerEventHandler(element, 'blur', handleElementFocusOut);
|
|
389
|
-
registerEventHandler(element, 'focusout', handleElementFocusOut); // For IE
|
|
390
|
-
},
|
|
391
|
-
update: function (element, valueAccessor) {
|
|
392
|
-
var value = !!unwrap(valueAccessor());
|
|
393
|
-
if (!element[hasfocusUpdatingProperty] && element[hasfocusLastValue] !== value) {
|
|
394
|
-
value ? element.focus() : element.blur();
|
|
395
|
-
// In IE, the blur method doesn't always cause the element to lose focus (for example, if the window is not in focus).
|
|
396
|
-
// Setting focus to the body element does seem to be reliable in IE, but should only be used if we know that the current
|
|
397
|
-
// element was focused already.
|
|
398
|
-
if (!value && element[hasfocusLastValue]) {
|
|
399
|
-
element.ownerDocument.body.focus();
|
|
400
|
-
}
|
|
401
|
-
// For IE, which doesn't reliably fire "focus" or "blur" events synchronously
|
|
402
|
-
dependencyDetection.ignore(triggerEvent, null, [element, value ? 'focusin' : 'focusout']);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
var html = {
|
|
408
|
-
init: function () {
|
|
409
|
-
// Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
|
|
410
|
-
return {
|
|
411
|
-
'controlsDescendantBindings': true
|
|
412
|
-
};
|
|
413
|
-
},
|
|
414
|
-
//
|
|
415
|
-
// Modify internal, per ko.punches and :
|
|
416
|
-
// http://stackoverflow.com/a/15348139
|
|
417
|
-
update: function (element, valueAccessor) {
|
|
418
|
-
setHtml(element, valueAccessor());
|
|
419
|
-
},
|
|
420
|
-
allowVirtualElements: true
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
var $let = {
|
|
424
|
-
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
425
|
-
// Make a modified binding context, with extra properties, and apply it to descendant elements
|
|
426
|
-
var innerContext = bindingContext['extend'](valueAccessor);
|
|
427
|
-
applyBindingsToDescendants(innerContext, element);
|
|
428
|
-
return { 'controlsDescendantBindings': true };
|
|
429
|
-
},
|
|
430
|
-
allowVirtualElements: true
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
var captionPlaceholder = {};
|
|
434
|
-
var options$1 = {
|
|
435
|
-
init: function (element) {
|
|
436
|
-
if (tagNameLower(element) !== 'select') {
|
|
437
|
-
throw new Error('options binding applies only to SELECT elements');
|
|
438
|
-
}
|
|
439
|
-
// Remove all existing <option>s.
|
|
440
|
-
while (element.length > 0) {
|
|
441
|
-
element.remove(0);
|
|
442
|
-
}
|
|
443
|
-
// Ensures that the binding processor doesn't try to bind the options
|
|
444
|
-
return { 'controlsDescendantBindings': true };
|
|
445
|
-
},
|
|
446
|
-
update: function (element, valueAccessor, allBindings) {
|
|
447
|
-
function selectedOptions() {
|
|
448
|
-
return arrayFilter(element.options, function (node) { return node.selected; });
|
|
449
|
-
}
|
|
450
|
-
var selectWasPreviouslyEmpty = element.length == 0, multiple = element.multiple, previousScrollTop = (!selectWasPreviouslyEmpty && multiple) ? element.scrollTop : null, unwrappedArray = unwrap(valueAccessor()), valueAllowUnset = allBindings.get('valueAllowUnset') && allBindings['has']('value'), includeDestroyed = allBindings.get('optionsIncludeDestroyed'), arrayToDomNodeChildrenOptions = {}, captionValue, filteredArray, previousSelectedValues = [];
|
|
451
|
-
if (!valueAllowUnset) {
|
|
452
|
-
if (multiple) {
|
|
453
|
-
previousSelectedValues = arrayMap(selectedOptions(), selectExtensions.readValue);
|
|
454
|
-
}
|
|
455
|
-
else if (element.selectedIndex >= 0) {
|
|
456
|
-
previousSelectedValues.push(selectExtensions.readValue(element.options[element.selectedIndex]));
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
if (unwrappedArray) {
|
|
460
|
-
if (typeof unwrappedArray.length === 'undefined') // Coerce single value into array
|
|
461
|
-
{
|
|
462
|
-
unwrappedArray = [unwrappedArray];
|
|
463
|
-
}
|
|
464
|
-
// Filter out any entries marked as destroyed
|
|
465
|
-
filteredArray = arrayFilter(unwrappedArray, function (item) {
|
|
466
|
-
return includeDestroyed || item === undefined || item === null || !unwrap(item['_destroy']);
|
|
467
|
-
});
|
|
468
|
-
// If caption is included, add it to the array
|
|
469
|
-
if (allBindings['has']('optionsCaption')) {
|
|
470
|
-
captionValue = unwrap(allBindings.get('optionsCaption'));
|
|
471
|
-
// If caption value is null or undefined, don't show a caption
|
|
472
|
-
if (captionValue !== null && captionValue !== undefined) {
|
|
473
|
-
filteredArray.unshift(captionPlaceholder);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
function applyToObject(object, predicate, defaultValue) {
|
|
478
|
-
var predicateType = typeof predicate;
|
|
479
|
-
if (predicateType == 'function') // Given a function; run it against the data value
|
|
480
|
-
{
|
|
481
|
-
return predicate(object);
|
|
482
|
-
}
|
|
483
|
-
else if (predicateType == 'string') // Given a string; treat it as a property name on the data value
|
|
484
|
-
{
|
|
485
|
-
return object[predicate];
|
|
486
|
-
}
|
|
487
|
-
else // Given no optionsText arg; use the data value itself
|
|
488
|
-
{
|
|
489
|
-
return defaultValue;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
// The following functions can run at two different times:
|
|
493
|
-
// The first is when the whole array is being updated directly from this binding handler.
|
|
494
|
-
// The second is when an observable value for a specific array entry is updated.
|
|
495
|
-
// oldOptions will be empty in the first case, but will be filled with the previously generated option in the second.
|
|
496
|
-
var itemUpdate = false;
|
|
497
|
-
function optionForArrayItem(arrayEntry, index, oldOptions) {
|
|
498
|
-
if (oldOptions.length) {
|
|
499
|
-
previousSelectedValues = !valueAllowUnset && oldOptions[0].selected ? [selectExtensions.readValue(oldOptions[0])] : [];
|
|
500
|
-
itemUpdate = true;
|
|
501
|
-
}
|
|
502
|
-
var option = element.ownerDocument.createElement('option');
|
|
503
|
-
if (arrayEntry === captionPlaceholder) {
|
|
504
|
-
setTextContent(option, allBindings.get('optionsCaption'));
|
|
505
|
-
selectExtensions.writeValue(option, undefined);
|
|
506
|
-
}
|
|
507
|
-
else {
|
|
508
|
-
// Apply a value to the option element
|
|
509
|
-
var optionValue = applyToObject(arrayEntry, allBindings.get('optionsValue'), arrayEntry);
|
|
510
|
-
selectExtensions.writeValue(option, unwrap(optionValue));
|
|
511
|
-
// Apply some text to the option element
|
|
512
|
-
var optionText = applyToObject(arrayEntry, allBindings.get('optionsText'), optionValue);
|
|
513
|
-
setTextContent(option, optionText);
|
|
514
|
-
}
|
|
515
|
-
return [option];
|
|
516
|
-
}
|
|
517
|
-
// By using a beforeRemove callback, we delay the removal until after new items are added. This fixes a selection
|
|
518
|
-
// problem in IE<=8 and Firefox. See https://github.com/knockout/knockout/issues/1208
|
|
519
|
-
arrayToDomNodeChildrenOptions['beforeRemove'] =
|
|
520
|
-
function (option) {
|
|
521
|
-
element.removeChild(option);
|
|
522
|
-
};
|
|
523
|
-
function setSelectionCallback(arrayEntry, newOptions) {
|
|
524
|
-
if (itemUpdate && valueAllowUnset) {
|
|
525
|
-
// The model value is authoritative, so make sure its value is the one selected
|
|
526
|
-
// There is no need to use dependencyDetection.ignore since setDomNodeChildrenFromArrayMapping does so already.
|
|
527
|
-
selectExtensions.writeValue(element, unwrap(allBindings.get('value')), true /* allowUnset */);
|
|
528
|
-
}
|
|
529
|
-
else if (previousSelectedValues.length) {
|
|
530
|
-
// IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
|
|
531
|
-
// That's why we first added them without selection. Now it's time to set the selection.
|
|
532
|
-
var isSelected = arrayIndexOf(previousSelectedValues, selectExtensions.readValue(newOptions[0])) >= 0;
|
|
533
|
-
setOptionNodeSelectionState(newOptions[0], isSelected);
|
|
534
|
-
// If this option was changed from being selected during a single-item update, notify the change
|
|
535
|
-
if (itemUpdate && !isSelected) {
|
|
536
|
-
dependencyDetection.ignore(triggerEvent, null, [element, 'change']);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
var callback = setSelectionCallback;
|
|
541
|
-
if (allBindings['has']('optionsAfterRender') && typeof allBindings.get('optionsAfterRender') === 'function') {
|
|
542
|
-
callback = function (arrayEntry, newOptions) {
|
|
543
|
-
setSelectionCallback(arrayEntry, newOptions);
|
|
544
|
-
dependencyDetection.ignore(allBindings.get('optionsAfterRender'), null, [newOptions[0], arrayEntry !== captionPlaceholder ? arrayEntry : undefined]);
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
setDomNodeChildrenFromArrayMapping(element, filteredArray, optionForArrayItem, arrayToDomNodeChildrenOptions, callback);
|
|
548
|
-
dependencyDetection.ignore(function () {
|
|
549
|
-
if (valueAllowUnset) {
|
|
550
|
-
// The model value is authoritative, so make sure its value is the one selected
|
|
551
|
-
selectExtensions.writeValue(element, unwrap(allBindings.get('value')), true /* allowUnset */);
|
|
552
|
-
}
|
|
553
|
-
else {
|
|
554
|
-
// Determine if the selection has changed as a result of updating the options list
|
|
555
|
-
var selectionChanged;
|
|
556
|
-
if (multiple) {
|
|
557
|
-
// For a multiple-select box, compare the new selection count to the previous one
|
|
558
|
-
// But if nothing was selected before, the selection can't have changed
|
|
559
|
-
selectionChanged = previousSelectedValues.length && selectedOptions().length < previousSelectedValues.length;
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
// For a single-select box, compare the current value to the previous value
|
|
563
|
-
// But if nothing was selected before or nothing is selected now, just look for a change in selection
|
|
564
|
-
selectionChanged = (previousSelectedValues.length && element.selectedIndex >= 0)
|
|
565
|
-
? (selectExtensions.readValue(element.options[element.selectedIndex]) !== previousSelectedValues[0])
|
|
566
|
-
: (previousSelectedValues.length || element.selectedIndex >= 0);
|
|
567
|
-
}
|
|
568
|
-
// Ensure consistency between model value and selected option.
|
|
569
|
-
// If the dropdown was changed so that selection is no longer the same,
|
|
570
|
-
// notify the value or selectedOptions binding.
|
|
571
|
-
if (selectionChanged) {
|
|
572
|
-
triggerEvent(element, 'change');
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
});
|
|
576
|
-
// Workaround for IE bug
|
|
577
|
-
ensureSelectElementIsRenderedCorrectly(element);
|
|
578
|
-
if (previousScrollTop && Math.abs(previousScrollTop - element.scrollTop) > 20) {
|
|
579
|
-
element.scrollTop = previousScrollTop;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
};
|
|
583
|
-
|
|
584
|
-
var selectedOptions = {
|
|
585
|
-
after: ['options', 'foreach'],
|
|
586
|
-
init: function (element, valueAccessor, allBindings) {
|
|
587
|
-
registerEventHandler(element, 'change', function () {
|
|
588
|
-
var value = valueAccessor(), valueToWrite = [];
|
|
589
|
-
arrayForEach(element.getElementsByTagName('option'), function (node) {
|
|
590
|
-
if (node.selected) {
|
|
591
|
-
valueToWrite.push(selectExtensions.readValue(node));
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
valueAccessor(valueToWrite);
|
|
595
|
-
});
|
|
596
|
-
},
|
|
597
|
-
update: function (element, valueAccessor) {
|
|
598
|
-
if (tagNameLower(element) != 'select') {
|
|
599
|
-
throw new Error('values binding applies only to SELECT elements');
|
|
600
|
-
}
|
|
601
|
-
var newValue = unwrap(valueAccessor()), previousScrollTop = element.scrollTop;
|
|
602
|
-
if (newValue && typeof newValue.length === 'number') {
|
|
603
|
-
arrayForEach(element.getElementsByTagName('option'), function (node) {
|
|
604
|
-
var isSelected = arrayIndexOf(newValue, selectExtensions.readValue(node)) >= 0;
|
|
605
|
-
if (node.selected != isSelected) { // This check prevents flashing of the select element in IE
|
|
606
|
-
setOptionNodeSelectionState(node, isSelected);
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
element.scrollTop = previousScrollTop;
|
|
611
|
-
}
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
var jQueryInstance = options.jQueryInstance;
|
|
615
|
-
var style = {
|
|
616
|
-
update: function (element, valueAccessor) {
|
|
617
|
-
var value = unwrap(valueAccessor() || {});
|
|
618
|
-
objectForEach(value, function (styleName, styleValue) {
|
|
619
|
-
styleValue = unwrap(styleValue);
|
|
620
|
-
if (styleValue === null || styleValue === undefined || styleValue === false) {
|
|
621
|
-
// Empty string removes the value, whereas null/undefined have no effect
|
|
622
|
-
styleValue = '';
|
|
623
|
-
}
|
|
624
|
-
if (jQueryInstance) {
|
|
625
|
-
jQueryInstance(element).css(styleName, styleValue);
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
styleName = styleName.replace(/-(\w)/g, function (all, letter) { return letter.toUpperCase(); });
|
|
629
|
-
var previousStyle = element.style[styleName];
|
|
630
|
-
element.style[styleName] = styleValue;
|
|
631
|
-
if (styleValue !== previousStyle && element.style[styleName] === previousStyle && !isNaN(styleValue)) {
|
|
632
|
-
element.style[styleName] = styleValue + 'px';
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
};
|
|
638
|
-
|
|
639
|
-
var submit = {
|
|
640
|
-
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
641
|
-
if (typeof valueAccessor() !== 'function') {
|
|
642
|
-
throw new Error('The value for a submit binding must be a function');
|
|
643
|
-
}
|
|
644
|
-
registerEventHandler(element, 'submit', function (event) {
|
|
645
|
-
var handlerReturnValue;
|
|
646
|
-
var value = valueAccessor();
|
|
647
|
-
try {
|
|
648
|
-
handlerReturnValue = value.call(bindingContext['$data'], element);
|
|
649
|
-
}
|
|
650
|
-
finally {
|
|
651
|
-
if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
|
|
652
|
-
if (event.preventDefault) {
|
|
653
|
-
event.preventDefault();
|
|
654
|
-
}
|
|
655
|
-
else {
|
|
656
|
-
event.returnValue = false;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
var text = {
|
|
665
|
-
init: function () {
|
|
666
|
-
// Prevent binding on the dynamically-injected text node (as developers are unlikely to expect that, and it has security implications).
|
|
667
|
-
// It should also make things faster, as we no longer have to consider whether the text node might be bindable.
|
|
668
|
-
return { controlsDescendantBindings: true };
|
|
669
|
-
},
|
|
670
|
-
update: function (element, valueAccessor) {
|
|
671
|
-
setTextContent(element, valueAccessor());
|
|
672
|
-
},
|
|
673
|
-
allowVirtualElements: true
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
var operaVersion, safariVersion, firefoxVersion;
|
|
677
|
-
/**
|
|
678
|
-
* TextInput binding handler for modern browsers (legacy below).
|
|
679
|
-
* @extends BindingHandler
|
|
680
|
-
*/
|
|
681
|
-
var TextInput = /** @class */ (function (_super) {
|
|
682
|
-
__extends(TextInput, _super);
|
|
683
|
-
function TextInput() {
|
|
684
|
-
var e_1, _a, e_2, _b;
|
|
685
|
-
var args = [];
|
|
686
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
687
|
-
args[_i] = arguments[_i];
|
|
688
|
-
}
|
|
689
|
-
var _this = _super.apply(this, __spread(args)) || this;
|
|
690
|
-
_this.previousElementValue = _this.$element.value;
|
|
691
|
-
if (options.debug && _this.constructor._forceUpdateOn) {
|
|
692
|
-
// Provide a way for tests to specify exactly which events are bound
|
|
693
|
-
arrayForEach(_this.constructor._forceUpdateOn, function (eventName) {
|
|
694
|
-
if (eventName.slice(0, 5) === 'after') {
|
|
695
|
-
_this.addEventListener(eventName.slice(5), 'deferUpdateModel');
|
|
696
|
-
}
|
|
697
|
-
else {
|
|
698
|
-
_this.addEventListener(eventName, 'updateModel');
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
|
-
}
|
|
702
|
-
try {
|
|
703
|
-
for (var _c = __values(_this.eventsIndicatingSyncValueChange()), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
704
|
-
var eventName = _d.value;
|
|
705
|
-
_this.addEventListener(eventName, 'updateModel');
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
709
|
-
finally {
|
|
710
|
-
try {
|
|
711
|
-
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
|
|
712
|
-
}
|
|
713
|
-
finally { if (e_1) throw e_1.error; }
|
|
714
|
-
}
|
|
715
|
-
try {
|
|
716
|
-
for (var _e = __values(_this.eventsIndicatingDeferValueChange()), _f = _e.next(); !_f.done; _f = _e.next()) {
|
|
717
|
-
var eventName = _f.value;
|
|
718
|
-
_this.addEventListener(eventName, 'deferUpdateModel');
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
722
|
-
finally {
|
|
723
|
-
try {
|
|
724
|
-
if (_f && !_f.done && (_b = _e["return"])) _b.call(_e);
|
|
725
|
-
}
|
|
726
|
-
finally { if (e_2) throw e_2.error; }
|
|
727
|
-
}
|
|
728
|
-
_this.computed('updateView');
|
|
729
|
-
return _this;
|
|
730
|
-
}
|
|
731
|
-
Object.defineProperty(TextInput.prototype, "aliases", {
|
|
732
|
-
get: function () { return 'textinput'; },
|
|
733
|
-
enumerable: true,
|
|
734
|
-
configurable: true
|
|
735
|
-
});
|
|
736
|
-
TextInput.prototype.eventsIndicatingSyncValueChange = function () {
|
|
737
|
-
// input: Default, modern handler
|
|
738
|
-
// change: Catch programmatic updates of the value that fire this event.
|
|
739
|
-
// blur: To deal with browsers that don't notify any kind of event for some changes (IE, Safari, etc.)
|
|
740
|
-
return ['input', 'change', 'blur'];
|
|
741
|
-
};
|
|
742
|
-
TextInput.prototype.eventsIndicatingDeferValueChange = function () {
|
|
743
|
-
return [];
|
|
744
|
-
};
|
|
745
|
-
TextInput.prototype.updateModel = function (event) {
|
|
746
|
-
var element = this.$element;
|
|
747
|
-
clearTimeout(this.timeoutHandle);
|
|
748
|
-
this.elementValueBeforeEvent = this.timeoutHandle = undefined;
|
|
749
|
-
var elementValue = element.value;
|
|
750
|
-
if (this.previousElementValue !== elementValue) {
|
|
751
|
-
// Provide a way for tests to know exactly which event was processed
|
|
752
|
-
if (options.debug && event) {
|
|
753
|
-
element._ko_textInputProcessedEvent = event.type;
|
|
754
|
-
}
|
|
755
|
-
this.previousElementValue = elementValue;
|
|
756
|
-
this.value = elementValue;
|
|
757
|
-
}
|
|
758
|
-
};
|
|
759
|
-
TextInput.prototype.deferUpdateModel = function (event) {
|
|
760
|
-
var element = this.$element;
|
|
761
|
-
if (!this.timeoutHandle) {
|
|
762
|
-
// The elementValueBeforeEvent variable is set *only* during the brief gap between an
|
|
763
|
-
// event firing and the updateModel function running. This allows us to ignore model
|
|
764
|
-
// updates that are from the previous state of the element, usually due to techniques
|
|
765
|
-
// such as rateLimit. Such updates, if not ignored, can cause keystrokes to be lost.
|
|
766
|
-
this.elementValueBeforeEvent = element.value;
|
|
767
|
-
var handler = options.debug ? this.updateModel.bind(this, { type: event.type }) : this.updateModel;
|
|
768
|
-
this.timeoutHandle = safeSetTimeout(handler, 4);
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
TextInput.prototype.updateView = function () {
|
|
772
|
-
var modelValue = unwrap(this.value);
|
|
773
|
-
if (modelValue === null || modelValue === undefined) {
|
|
774
|
-
modelValue = '';
|
|
775
|
-
}
|
|
776
|
-
if (this.elementValueBeforeEvent !== undefined
|
|
777
|
-
&& modelValue === this.elementValueBeforeEvent) {
|
|
778
|
-
setTimeout(this.updateView.bind(this), 4);
|
|
779
|
-
}
|
|
780
|
-
else if (this.$element.value !== modelValue) {
|
|
781
|
-
// Update the element only if the element and model are different. On some browsers, updating the value
|
|
782
|
-
// will move the cursor to the end of the input, which would be bad while the user is typing.
|
|
783
|
-
this.previousElementValue = modelValue; // Make sure we ignore events (propertychange) that result from updating the value
|
|
784
|
-
this.$element.value = modelValue;
|
|
785
|
-
this.previousElementValue = this.$element.value; // In case the browser changes the value (see #2281)
|
|
786
|
-
}
|
|
787
|
-
};
|
|
788
|
-
return TextInput;
|
|
789
|
-
}(BindingHandler));
|
|
790
|
-
/**
|
|
791
|
-
* Legacy Input Classes, below
|
|
792
|
-
*/
|
|
793
|
-
var TextInputIE = /** @class */ (function (_super) {
|
|
794
|
-
__extends(TextInputIE, _super);
|
|
795
|
-
function TextInputIE() {
|
|
796
|
-
var args = [];
|
|
797
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
798
|
-
args[_i] = arguments[_i];
|
|
799
|
-
}
|
|
800
|
-
var _this = _super.apply(this, __spread(args)) || this;
|
|
801
|
-
if (ieVersion < 11) {
|
|
802
|
-
// Internet Explorer <= 8 doesn't support the 'input' event, but does include 'propertychange' that fires whenever
|
|
803
|
-
// any property of an element changes. Unlike 'input', it also fires if a property is changed from JavaScript code,
|
|
804
|
-
// but that's an acceptable compromise for this binding. IE 9 and 10 support 'input', but since they don't always
|
|
805
|
-
// fire it when using autocomplete, we'll use 'propertychange' for them also.
|
|
806
|
-
_this.addEventListener('propertychange', function (event) {
|
|
807
|
-
return event.propertyName === 'value' && _this.updateModel(event);
|
|
808
|
-
});
|
|
809
|
-
}
|
|
810
|
-
if (ieVersion >= 8 && ieVersion < 10) {
|
|
811
|
-
_this.watchForSelectionChangeEvent();
|
|
812
|
-
_this.addEventListener('dragend', 'deferUpdateModel');
|
|
813
|
-
}
|
|
814
|
-
return _this;
|
|
815
|
-
}
|
|
816
|
-
TextInputIE.prototype.eventsIndicatingSyncValueChange = function () {
|
|
817
|
-
// keypress: All versions (including 11) of Internet Explorer have a bug that they don't generate an input or propertychange event when ESC is pressed
|
|
818
|
-
return __spread(_super.prototype.eventsIndicatingValueChange.call(this), ['keypress']);
|
|
819
|
-
};
|
|
820
|
-
// IE 8 and 9 have bugs that prevent the normal events from firing when the value changes.
|
|
821
|
-
// But it does fire the 'selectionchange' event on many of those, presumably because the
|
|
822
|
-
// cursor is moving and that counts as the selection changing. The 'selectionchange' event is
|
|
823
|
-
// fired at the document level only and doesn't directly indicate which element changed. We
|
|
824
|
-
// set up just one event handler for the document and use 'activeElement' to determine which
|
|
825
|
-
// element was changed.
|
|
826
|
-
TextInputIE.prototype.selectionChangeHandler = function (event) {
|
|
827
|
-
var target = this.activeElement;
|
|
828
|
-
var handler = target && domData.get(target, selectionChangeHandlerName);
|
|
829
|
-
if (handler) {
|
|
830
|
-
handler(event);
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
TextInputIE.prototype.watchForSelectionChangeEvent = function (element, ieUpdateModel) {
|
|
834
|
-
var ownerDoc = element.ownerDocument;
|
|
835
|
-
if (!domData.get(ownerDoc, selectionChangeRegisteredName)) {
|
|
836
|
-
domData.set(ownerDoc, selectionChangeRegisteredName, true);
|
|
837
|
-
registerEventHandler(ownerDoc, 'selectionchange', this.selectionChangeHandler.bind(ownerDoc));
|
|
838
|
-
}
|
|
839
|
-
domData.set(element, selectionChangeHandlerName, handler);
|
|
840
|
-
};
|
|
841
|
-
return TextInputIE;
|
|
842
|
-
}(TextInput));
|
|
843
|
-
// IE 8 and 9 have bugs that prevent the normal events from firing when the value changes.
|
|
844
|
-
// But it does fire the 'selectionchange' event on many of those, presumably because the
|
|
845
|
-
// cursor is moving and that counts as the selection changing. The 'selectionchange' event is
|
|
846
|
-
// fired at the document level only and doesn't directly indicate which element changed. We
|
|
847
|
-
// set up just one event handler for the document and use 'activeElement' to determine which
|
|
848
|
-
// element was changed.
|
|
849
|
-
var TextInputIE9 = /** @class */ (function (_super) {
|
|
850
|
-
__extends(TextInputIE9, _super);
|
|
851
|
-
function TextInputIE9() {
|
|
852
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
853
|
-
}
|
|
854
|
-
TextInputIE9.prototype.updateModel = function () {
|
|
855
|
-
var args = [];
|
|
856
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
857
|
-
args[_i] = arguments[_i];
|
|
858
|
-
}
|
|
859
|
-
// IE9 will mess up the DOM if you handle events synchronously which results in DOM changes (such as other bindings);
|
|
860
|
-
// so we'll make sure all updates are asynchronous
|
|
861
|
-
this.deferUpdateModel.apply(this, __spread(args));
|
|
862
|
-
};
|
|
863
|
-
return TextInputIE9;
|
|
864
|
-
}(TextInputIE));
|
|
865
|
-
var TextInputIE8 = /** @class */ (function (_super) {
|
|
866
|
-
__extends(TextInputIE8, _super);
|
|
867
|
-
function TextInputIE8() {
|
|
868
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
869
|
-
}
|
|
870
|
-
TextInputIE8.prototype.eventsIndicatingValueChange = function () {
|
|
871
|
-
// IE 8 has a bug where it fails to fire 'propertychange' on the first update following a value change from
|
|
872
|
-
// JavaScript code. It also doesn't fire if you clear the entire value. To fix this, we bind to the following
|
|
873
|
-
// events too.
|
|
874
|
-
// keypress: All versions (including 11) of Internet Explorer have a bug that they don't generate an input or propertychange event when ESC is pressed
|
|
875
|
-
// keyup: A single keystoke
|
|
876
|
-
// keydown: First character when a key is held down
|
|
877
|
-
return __spread(_super.prototype.eventsIndicatingValueChange.call(this), ['keyup', 'keydown']);
|
|
878
|
-
};
|
|
879
|
-
return TextInputIE8;
|
|
880
|
-
}(TextInputIE));
|
|
881
|
-
// Safari <5 doesn't fire the 'input' event for <textarea> elements (it does fire 'textInput'
|
|
882
|
-
// but only when typing). So we'll just catch as much as we can with keydown, cut, and paste.
|
|
883
|
-
var TextInputLegacySafari = /** @class */ (function (_super) {
|
|
884
|
-
__extends(TextInputLegacySafari, _super);
|
|
885
|
-
function TextInputLegacySafari() {
|
|
886
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
887
|
-
}
|
|
888
|
-
TextInputLegacySafari.prototype.eventsIndicatingDeferValueChange = function () {
|
|
889
|
-
return ['keydown', 'paste', 'cut'];
|
|
890
|
-
};
|
|
891
|
-
return TextInputLegacySafari;
|
|
892
|
-
}(TextInput));
|
|
893
|
-
var TextInputLegacyOpera = /** @class */ (function (_super) {
|
|
894
|
-
__extends(TextInputLegacyOpera, _super);
|
|
895
|
-
function TextInputLegacyOpera() {
|
|
896
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
897
|
-
}
|
|
898
|
-
TextInputLegacyOpera.prototype.eventsIndicatingDeferValueChange = function () {
|
|
899
|
-
// Opera 10 doesn't always fire the 'input' event for cut, paste, undo & drop operations.
|
|
900
|
-
// We can try to catch some of those using 'keydown'.
|
|
901
|
-
return ['keydown'];
|
|
902
|
-
};
|
|
903
|
-
return TextInputLegacyOpera;
|
|
904
|
-
}(TextInput));
|
|
905
|
-
var TextInputLegacyFirefox = /** @class */ (function (_super) {
|
|
906
|
-
__extends(TextInputLegacyFirefox, _super);
|
|
907
|
-
function TextInputLegacyFirefox() {
|
|
908
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
909
|
-
}
|
|
910
|
-
TextInputLegacyFirefox.prototype.eventsIndicatingValueChange = function () {
|
|
911
|
-
return __spread(_super.prototype.eventsIndicatingSyncValueChange.call(this), [
|
|
912
|
-
// Firefox <= 3.6 doesn't fire the 'input' event when text is filled in through autocomplete
|
|
913
|
-
'DOMAutoComplete',
|
|
914
|
-
// Firefox <=3.5 doesn't fire the 'input' event when text is dropped into the input.
|
|
915
|
-
'dragdrop',
|
|
916
|
-
'drop' // 3.5
|
|
917
|
-
]);
|
|
918
|
-
};
|
|
919
|
-
return TextInputLegacyFirefox;
|
|
920
|
-
}(TextInput));
|
|
921
|
-
var w = options.global; // window / global
|
|
922
|
-
if (w.navigator) {
|
|
923
|
-
var parseVersion_1 = function (matches) { return matches && parseFloat(matches[1]); };
|
|
924
|
-
var userAgent = w.navigator.userAgent;
|
|
925
|
-
var isChrome = userAgent.match(/Chrome\/([^ ]+)/);
|
|
926
|
-
// Detect various browser versions because some old versions don't fully support the 'input' event
|
|
927
|
-
operaVersion = w.opera && w.opera.version && parseInt(w.opera.version());
|
|
928
|
-
safariVersion = parseVersion_1(userAgent.match(/Version\/([^ ]+) Safari/));
|
|
929
|
-
firefoxVersion = parseVersion_1(userAgent.match(/Firefox\/([^ ]*)/));
|
|
930
|
-
}
|
|
931
|
-
var textInput = ieVersion === 8 ? TextInputIE8
|
|
932
|
-
: ieVersion === 9 ? TextInputIE9
|
|
933
|
-
: ieVersion ? TextInputIE
|
|
934
|
-
: safariVersion && safariVersion < 5 ? TextInputLegacySafari
|
|
935
|
-
: operaVersion < 11 ? TextInputLegacyOpera
|
|
936
|
-
: firefoxVersion && firefoxVersion < 4 ? TextInputLegacyFirefox
|
|
937
|
-
: TextInput;
|
|
938
|
-
|
|
939
|
-
var uniqueName = {
|
|
940
|
-
init: function (element, valueAccessor) {
|
|
941
|
-
if (valueAccessor()) {
|
|
942
|
-
var name = 'ko_unique_' + (++uniqueName.currentIndex);
|
|
943
|
-
setElementName(element, name);
|
|
944
|
-
}
|
|
945
|
-
},
|
|
946
|
-
currentIndex: 0
|
|
947
|
-
};
|
|
948
|
-
|
|
949
|
-
var value = /** @class */ (function (_super) {
|
|
950
|
-
__extends(value, _super);
|
|
951
|
-
function value() {
|
|
952
|
-
var args = [];
|
|
953
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
954
|
-
args[_i] = arguments[_i];
|
|
955
|
-
}
|
|
956
|
-
var _this = _super.apply(this, __spread(args)) || this;
|
|
957
|
-
// If the value binding is placed on a radio/checkbox, then just pass through to checkedValue and quit
|
|
958
|
-
if (_this.isCheckboxOrRadio) {
|
|
959
|
-
applyBindingAccessorsToNode(_this.$element, { checkedValue: _this.valueAccessor });
|
|
960
|
-
return _this;
|
|
961
|
-
}
|
|
962
|
-
_this.propertyChangedFired = false;
|
|
963
|
-
_this.elementValueBeforeEvent = null;
|
|
964
|
-
if (_this.ieAutoCompleteHackNeeded) {
|
|
965
|
-
_this.addEventListener('propertyChange', function () { return _this.propertyChangedFired = true; });
|
|
966
|
-
_this.addEventListener('focus', function () { return _this.propertyChangedFired = false; });
|
|
967
|
-
_this.addEventListener('blur', function () { return _this.propertyChangeFired &&
|
|
968
|
-
_this.valueUpdateHandler(); });
|
|
969
|
-
}
|
|
970
|
-
arrayForEach(_this.eventsToCatch, function (eventName) { return _this.registerEvent(eventName); });
|
|
971
|
-
if (_this.isInput && _this.$element.type === 'file') {
|
|
972
|
-
_this.updateFromModel = _this.updateFromModelForFile;
|
|
973
|
-
}
|
|
974
|
-
else {
|
|
975
|
-
_this.updateFromModel = _this.updateFromModelForValue;
|
|
976
|
-
}
|
|
977
|
-
_this.computed('updateFromModel');
|
|
978
|
-
return _this;
|
|
979
|
-
}
|
|
980
|
-
Object.defineProperty(value, "after", {
|
|
981
|
-
get: function () { return ['options', 'foreach', 'template']; },
|
|
982
|
-
enumerable: true,
|
|
983
|
-
configurable: true
|
|
984
|
-
});
|
|
985
|
-
Object.defineProperty(value.prototype, "eventsToCatch", {
|
|
986
|
-
get: function () {
|
|
987
|
-
var requestedEventsToCatch = this.allBindings.get('valueUpdate');
|
|
988
|
-
var requestedEventsArray = typeof requestedEventsToCatch === 'string' ?
|
|
989
|
-
[requestedEventsToCatch] : requestedEventsToCatch || [];
|
|
990
|
-
return __spread(new Set(__spread(['change'], requestedEventsArray)));
|
|
991
|
-
},
|
|
992
|
-
enumerable: true,
|
|
993
|
-
configurable: true
|
|
994
|
-
});
|
|
995
|
-
Object.defineProperty(value.prototype, "isInput", {
|
|
996
|
-
get: function () {
|
|
997
|
-
return tagNameLower(this.$element) === 'input';
|
|
998
|
-
},
|
|
999
|
-
enumerable: true,
|
|
1000
|
-
configurable: true
|
|
1001
|
-
});
|
|
1002
|
-
Object.defineProperty(value.prototype, "isCheckboxOrRadio", {
|
|
1003
|
-
get: function () {
|
|
1004
|
-
var e = this.$element;
|
|
1005
|
-
return this.isInput && (e.type == 'checkbox' || e.type == 'radio');
|
|
1006
|
-
},
|
|
1007
|
-
enumerable: true,
|
|
1008
|
-
configurable: true
|
|
1009
|
-
});
|
|
1010
|
-
Object.defineProperty(value.prototype, "ieAutoCompleteHackNeeded", {
|
|
1011
|
-
// Workaround for https://github.com/SteveSanderson/knockout/issues/122
|
|
1012
|
-
// IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
|
|
1013
|
-
get: function () {
|
|
1014
|
-
return ieVersion && isInputElement &&
|
|
1015
|
-
this.$element.type == 'text' && this.$element.autocomplete != 'off' &&
|
|
1016
|
-
(!this.$element.form || this.$element.form.autocomplete != 'off');
|
|
1017
|
-
},
|
|
1018
|
-
enumerable: true,
|
|
1019
|
-
configurable: true
|
|
1020
|
-
});
|
|
1021
|
-
value.prototype.valueUpdateHandler = function () {
|
|
1022
|
-
this.elementValueBeforeEvent = null;
|
|
1023
|
-
this.propertyChangedFired = false;
|
|
1024
|
-
this.value = selectExtensions.readValue(this.$element);
|
|
1025
|
-
};
|
|
1026
|
-
value.prototype.registerEvent = function (eventName) {
|
|
1027
|
-
var _this = this;
|
|
1028
|
-
// The syntax "after<eventname>" means "run the handler asynchronously after the event"
|
|
1029
|
-
// This is useful, for example, to catch "keydown" events after the browser has updated the control
|
|
1030
|
-
// (otherwise, selectExtensions.readValue(this) will receive the control's value *before* the key event)
|
|
1031
|
-
var handler = this.valueUpdateHandler.bind(this);
|
|
1032
|
-
if (stringStartsWith(eventName, 'after')) {
|
|
1033
|
-
handler = function () {
|
|
1034
|
-
// The elementValueBeforeEvent variable is non-null *only* during the brief gap between
|
|
1035
|
-
// a keyX event firing and the valueUpdateHandler running, which is scheduled to happen
|
|
1036
|
-
// at the earliest asynchronous opportunity. We store this temporary information so that
|
|
1037
|
-
// if, between keyX and valueUpdateHandler, the underlying model value changes separately,
|
|
1038
|
-
// we can overwrite that model value change with the value the user just typed. Otherwise,
|
|
1039
|
-
// techniques like rateLimit can trigger model changes at critical moments that will
|
|
1040
|
-
// override the user's inputs, causing keystrokes to be lost.
|
|
1041
|
-
_this.elementValueBeforeEvent = selectExtensions.readValue(_this.$element);
|
|
1042
|
-
safeSetTimeout(_this.valueUpdateHandler.bind(_this), 0);
|
|
1043
|
-
};
|
|
1044
|
-
eventName = eventName.substring(5 /* 'after'.length */);
|
|
1045
|
-
}
|
|
1046
|
-
this.addEventListener(eventName, handler);
|
|
1047
|
-
};
|
|
1048
|
-
value.prototype.updateFromModelForFile = function () {
|
|
1049
|
-
// For file input elements, can only write the empty string
|
|
1050
|
-
var newValue = unwrap(this.value);
|
|
1051
|
-
if (newValue === null || newValue === undefined || newValue === '') {
|
|
1052
|
-
this.$element.value = '';
|
|
1053
|
-
}
|
|
1054
|
-
else {
|
|
1055
|
-
dependencyDetection.ignore(this.valueUpdateHandler, this); // reset the model to match the element
|
|
1056
|
-
}
|
|
1057
|
-
};
|
|
1058
|
-
value.prototype.updateFromModelForValue = function () {
|
|
1059
|
-
var element = this.$element;
|
|
1060
|
-
var newValue = unwrap(this.value);
|
|
1061
|
-
var elementValue = selectExtensions.readValue(element);
|
|
1062
|
-
if (this.elementValueBeforeEvent !== null && newValue === this.elementValueBeforeEvent) {
|
|
1063
|
-
safeSetTimeout(this.updateFromModel.bind(this), 0);
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
if (newValue === elementValue && elementValue !== undefined) {
|
|
1067
|
-
return;
|
|
1068
|
-
}
|
|
1069
|
-
if (tagNameLower(element) === 'select') {
|
|
1070
|
-
var allowUnset = this.allBindings.get('valueAllowUnset');
|
|
1071
|
-
selectExtensions.writeValue(element, newValue, allowUnset);
|
|
1072
|
-
if (!allowUnset && newValue !== selectExtensions.readValue(element)) {
|
|
1073
|
-
// If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
|
|
1074
|
-
// because you're not allowed to have a model value that disagrees with a visible UI selection.
|
|
1075
|
-
dependencyDetection.ignore(this.valueUpdateHandler, this);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
else {
|
|
1079
|
-
selectExtensions.writeValue(element, newValue);
|
|
1080
|
-
}
|
|
1081
|
-
};
|
|
1082
|
-
return value;
|
|
1083
|
-
}(BindingHandler));
|
|
1084
|
-
|
|
1085
|
-
var visible = {
|
|
1086
|
-
update: function (element, valueAccessor) {
|
|
1087
|
-
var value = unwrap(valueAccessor());
|
|
1088
|
-
var isCurrentlyVisible = !(element.style.display === 'none');
|
|
1089
|
-
if (value && !isCurrentlyVisible) {
|
|
1090
|
-
element.style.display = '';
|
|
1091
|
-
}
|
|
1092
|
-
else if (!value && isCurrentlyVisible) {
|
|
1093
|
-
element.style.display = 'none';
|
|
1094
|
-
}
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
var hidden = {
|
|
1098
|
-
update: function (element, valueAccessor) {
|
|
1099
|
-
visible.update.call(this, element, function () { return !unwrap(valueAccessor()); });
|
|
1100
|
-
}
|
|
1101
|
-
};
|
|
1102
|
-
|
|
1103
|
-
var using = {
|
|
1104
|
-
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
1105
|
-
var innerContext = bindingContext.createChildContext(valueAccessor);
|
|
1106
|
-
applyBindingsToDescendants(innerContext, element);
|
|
1107
|
-
return { controlsDescendantBindings: true };
|
|
1108
|
-
},
|
|
1109
|
-
allowVirtualElements: true
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
var bindings = {
|
|
1113
|
-
attr: attr,
|
|
1114
|
-
checked: checked,
|
|
1115
|
-
checkedValue: checkedValue,
|
|
1116
|
-
click: click,
|
|
1117
|
-
css: css,
|
|
1118
|
-
'class': css,
|
|
1119
|
-
descendantsComplete: DescendantsCompleteHandler,
|
|
1120
|
-
enable: enable,
|
|
1121
|
-
'event': eventHandler,
|
|
1122
|
-
disable: disable,
|
|
1123
|
-
hasfocus: hasfocus,
|
|
1124
|
-
hasFocus: hasfocus,
|
|
1125
|
-
hidden: hidden,
|
|
1126
|
-
html: html,
|
|
1127
|
-
'let': $let,
|
|
1128
|
-
on: onHandler,
|
|
1129
|
-
options: options$1,
|
|
1130
|
-
selectedOptions: selectedOptions,
|
|
1131
|
-
style: style,
|
|
1132
|
-
submit: submit,
|
|
1133
|
-
text: text,
|
|
1134
|
-
textInput: textInput,
|
|
1135
|
-
textinput: textInput,
|
|
1136
|
-
uniqueName: uniqueName,
|
|
1137
|
-
using: using,
|
|
1138
|
-
value: value,
|
|
1139
|
-
visible: visible
|
|
1140
|
-
};
|
|
1141
|
-
|
|
1142
|
-
export { bindings };
|
|
1143
|
-
//# sourceMappingURL=binding.core.js.map
|