2020-08-12 06:25:36 +08:00
|
|
|
const
|
2020-08-27 21:45:47 +08:00
|
|
|
doc = document,
|
2020-08-12 06:25:36 +08:00
|
|
|
ko = window.ko,
|
2020-08-13 19:16:08 +08:00
|
|
|
Translator = () => require('Common/Translator'),
|
2020-09-17 06:02:35 +08:00
|
|
|
Globals = () => require('Common/Globals'),
|
2020-09-30 18:31:34 +08:00
|
|
|
isFunction = v => typeof v === 'function',
|
|
|
|
koValue = value => !ko.isObservable(value) && isFunction(value) ? value() : ko.unwrap(value);
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.tooltip = {
|
2016-08-17 06:01:20 +08:00
|
|
|
init: (element, fValueAccessor) => {
|
2020-09-30 18:31:34 +08:00
|
|
|
const Global = Globals();
|
|
|
|
const sValue = koValue(fValueAccessor());
|
2016-06-30 08:02:45 +08:00
|
|
|
|
2020-09-30 18:31:34 +08:00
|
|
|
if ('off' === element.dataset.tooltipI18n) {
|
|
|
|
element.title = sValue;
|
|
|
|
} else {
|
|
|
|
element.title = Translator().i18n(sValue);
|
|
|
|
Translator().trigger.subscribe(() =>
|
|
|
|
element.title = Translator().i18n(sValue)
|
|
|
|
);
|
|
|
|
Global.dropdownVisibility.subscribe(() =>
|
|
|
|
element.title = Translator().i18n(sValue)
|
|
|
|
);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
},
|
2016-08-17 06:01:20 +08:00
|
|
|
update: (element, fValueAccessor) => {
|
2020-09-30 18:31:34 +08:00
|
|
|
const sValue = koValue(fValueAccessor());
|
|
|
|
if (sValue) {
|
|
|
|
element.title = 'off' === element.dataset.tooltipI18n ? sValue : Translator().i18n(sValue);
|
|
|
|
} else {
|
|
|
|
element.title = '';
|
2014-08-20 23:03:12 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.tooltipErrorTip = {
|
2020-08-15 02:35:39 +08:00
|
|
|
init: element => {
|
2020-08-27 21:45:47 +08:00
|
|
|
doc.addEventListener('click', () => element.removeAttribute('data-rainloopErrorTip'));
|
2016-06-30 08:02:45 +08:00
|
|
|
},
|
2016-08-17 06:01:20 +08:00
|
|
|
update: (element, fValueAccessor) => {
|
2020-09-30 18:31:34 +08:00
|
|
|
const value = koValue(fValueAccessor());
|
2020-08-13 19:16:08 +08:00
|
|
|
if (value) {
|
2020-08-14 04:58:41 +08:00
|
|
|
setTimeout(() => element.setAttribute('data-rainloopErrorTip', value), 100);
|
2020-08-13 19:16:08 +08:00
|
|
|
} else {
|
|
|
|
element.removeAttribute('data-rainloopErrorTip');
|
2014-08-20 23:03:12 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-10-26 21:34:59 +08:00
|
|
|
ko.bindingHandlers.registerBootstrapDropdown = {
|
2020-08-30 16:30:50 +08:00
|
|
|
init: element => {
|
2020-10-26 21:34:59 +08:00
|
|
|
rl.Dropdowns.register(element);
|
2020-08-30 16:30:50 +08:00
|
|
|
element.ddBtn = new BSN.Dropdown(element.querySelector('[data-toggle="dropdown"]'));
|
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
2015-04-25 21:50:10 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.openDropdownTrigger = {
|
2016-08-17 06:01:20 +08:00
|
|
|
update: (element, fValueAccessor) => {
|
2019-07-05 03:19:24 +08:00
|
|
|
if (ko.unwrap(fValueAccessor())) {
|
2020-08-30 16:30:50 +08:00
|
|
|
const el = element.ddBtn;
|
2020-10-09 21:00:26 +08:00
|
|
|
el.open || el.toggle();
|
2020-08-30 16:30:50 +08:00
|
|
|
// el.focus();
|
2016-06-30 08:02:45 +08:00
|
|
|
|
2020-08-24 17:14:35 +08:00
|
|
|
rl.Dropdowns.detectVisibility();
|
2016-06-30 08:02:45 +08:00
|
|
|
fValueAccessor()(false);
|
2014-08-20 23:03:12 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.dropdownCloser = {
|
2020-08-30 16:30:50 +08:00
|
|
|
init: element => element.closest('.dropdown').addEventListener('click', event =>
|
2020-10-09 21:00:26 +08:00
|
|
|
event.target.closestWithin('.e-item', element) && element.ddBtn.toggle()
|
2020-08-30 16:30:50 +08:00
|
|
|
)
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
2015-04-25 21:50:10 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.onEnter = {
|
2016-08-17 06:01:20 +08:00
|
|
|
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
|
2020-09-18 03:18:39 +08:00
|
|
|
let fn = event => {
|
|
|
|
if ('Enter' == event.key) {
|
|
|
|
element.dispatchEvent(new Event('change'));
|
2016-08-17 06:01:20 +08:00
|
|
|
fValueAccessor().call(viewModel);
|
2014-08-20 23:03:12 +08:00
|
|
|
}
|
2020-09-18 03:18:39 +08:00
|
|
|
};
|
|
|
|
element.addEventListener('keydown', fn);
|
|
|
|
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keydown', fn));
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.onSpace = {
|
2016-08-17 06:01:20 +08:00
|
|
|
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
|
2020-09-18 03:18:39 +08:00
|
|
|
let fn = event => {
|
|
|
|
if (' ' == event.key) {
|
2016-08-17 06:01:20 +08:00
|
|
|
fValueAccessor().call(viewModel, event);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2020-09-18 03:18:39 +08:00
|
|
|
};
|
|
|
|
element.addEventListener('keyup', fn);
|
|
|
|
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2015-02-15 08:30:21 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.bindingHandlers.modal = {
|
2016-08-17 06:01:20 +08:00
|
|
|
init: (element, fValueAccessor) => {
|
2020-09-30 18:31:34 +08:00
|
|
|
const close = element.querySelector('.close'),
|
|
|
|
click = () => fValueAccessor()(false);
|
2020-08-30 16:30:50 +08:00
|
|
|
close && close.addEventListener('click.koModal', click);
|
|
|
|
|
|
|
|
ko.utils.domNodeDisposal.addDisposeCallback(element, () =>
|
|
|
|
close.removeEventListener('click.koModal', click)
|
|
|
|
);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ko.bindingHandlers.i18nInit = {
|
2020-08-15 02:35:39 +08:00
|
|
|
init: element => Translator().i18nToNodes(element)
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
ko.bindingHandlers.i18nUpdate = {
|
2016-08-17 06:01:20 +08:00
|
|
|
update: (element, fValueAccessor) => {
|
2016-06-30 08:02:45 +08:00
|
|
|
ko.unwrap(fValueAccessor());
|
2020-08-15 02:35:39 +08:00
|
|
|
Translator().i18nToNodes(element);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ko.bindingHandlers.title = {
|
2020-08-27 21:45:47 +08:00
|
|
|
update: (element, fValueAccessor) => element.title = ko.unwrap(fValueAccessor())
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
ko.bindingHandlers.command = {
|
2016-08-17 06:01:20 +08:00
|
|
|
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
|
2020-08-15 02:35:39 +08:00
|
|
|
const command = fValueAccessor();
|
2016-09-03 07:19:37 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
if (!command || !command.isCommand) {
|
2016-09-03 07:19:37 +08:00
|
|
|
throw new Error('Value should be a command');
|
|
|
|
}
|
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
if (!command.enabled) {
|
2016-09-03 07:19:37 +08:00
|
|
|
command.enabled = ko.observable(true);
|
|
|
|
}
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
if (!command.canExecute) {
|
2016-09-03 07:19:37 +08:00
|
|
|
const __realCanExecute = command.__realCanExecute;
|
2020-07-23 22:06:16 +08:00
|
|
|
if (isFunction(__realCanExecute)) {
|
2016-09-03 07:19:37 +08:00
|
|
|
command.canExecute = ko.computed(() => command.enabled() && __realCanExecute.call(viewModel, viewModel));
|
2019-07-05 03:19:24 +08:00
|
|
|
} else {
|
2016-09-03 07:19:37 +08:00
|
|
|
command.canExecute = ko.computed(() => command.enabled() && !!__realCanExecute);
|
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
element.classList.add('command');
|
2020-09-15 15:29:25 +08:00
|
|
|
ko.bindingHandlers['FORM'==element.nodeName ? 'submit' : 'click'].init(
|
2019-07-05 03:19:24 +08:00
|
|
|
element,
|
|
|
|
fValueAccessor,
|
|
|
|
fAllBindingsAccessor,
|
|
|
|
viewModel,
|
|
|
|
bindingContext
|
|
|
|
);
|
2016-06-30 08:02:45 +08:00
|
|
|
},
|
2016-08-17 06:01:20 +08:00
|
|
|
update: (element, fValueAccessor) => {
|
2020-08-15 02:35:39 +08:00
|
|
|
const cl = element.classList,
|
2016-08-17 06:01:20 +08:00
|
|
|
command = fValueAccessor();
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
let result = command.enabled();
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
cl.toggle('command-not-enabled', !result);
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
if (result) {
|
2016-08-17 06:01:20 +08:00
|
|
|
result = command.canExecute();
|
2020-08-15 02:35:39 +08:00
|
|
|
cl.toggle('command-can-not-be-execute', !result);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
['command-disabled','disable','disabled'].forEach(s=>cl.toggle(s, !result));
|
|
|
|
cl.toggle('no-disabled', !!result);
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-09-15 15:29:25 +08:00
|
|
|
if (element.nodeName.match(/INPUT|TEXTAREA|BUTTON/)) {
|
2020-08-15 02:35:39 +08:00
|
|
|
element.disabled = !result;
|
2014-08-20 23:03:12 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-06-30 08:02:45 +08:00
|
|
|
// extenders
|
2014-10-04 19:58:01 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
ko.extenders.limitedList = (target, limitedList) => {
|
2020-07-20 20:33:33 +08:00
|
|
|
const result = ko
|
2019-07-05 03:19:24 +08:00
|
|
|
.computed({
|
|
|
|
read: target,
|
|
|
|
write: (newValue) => {
|
|
|
|
const currentValue = ko.unwrap(target),
|
|
|
|
list = ko.unwrap(limitedList);
|
|
|
|
|
2020-09-04 23:07:35 +08:00
|
|
|
if (Array.isNotEmpty(list)) {
|
2020-07-20 20:33:33 +08:00
|
|
|
if (list.includes(newValue)) {
|
2019-07-05 03:19:24 +08:00
|
|
|
target(newValue);
|
2020-07-20 20:33:33 +08:00
|
|
|
} else if (list.includes(currentValue, list)) {
|
2019-07-05 03:19:24 +08:00
|
|
|
target(currentValue + ' ');
|
|
|
|
target(currentValue);
|
|
|
|
} else {
|
|
|
|
target(list[0] + ' ');
|
|
|
|
target(list[0]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
target('');
|
2015-01-26 07:09:22 +08:00
|
|
|
}
|
|
|
|
}
|
2019-07-05 03:19:24 +08:00
|
|
|
})
|
|
|
|
.extend({ notify: 'always' });
|
2015-01-26 07:09:22 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
result(target());
|
2015-01-26 07:09:22 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
if (!result.valueHasMutated) {
|
2020-08-15 02:35:39 +08:00
|
|
|
result.valueHasMutated = () => target.valueHasMutated();
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
return result;
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
ko.extenders.reversible = (target) => {
|
|
|
|
let value = target();
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
target.commit = () => value = target();
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
target.reverse = () => target(value);
|
2014-12-18 04:53:46 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
target.commitedValue = () => value;
|
|
|
|
return target;
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
2014-12-18 04:53:46 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
ko.extenders.toggleSubscribeProperty = (target, options) => {
|
|
|
|
const prop = options[1];
|
2019-07-05 03:19:24 +08:00
|
|
|
if (prop) {
|
|
|
|
target.subscribe(
|
2020-08-15 02:35:39 +08:00
|
|
|
prev => prev && prev[prop] && prev[prop](false),
|
2019-07-05 03:19:24 +08:00
|
|
|
options[0],
|
|
|
|
'beforeChange'
|
|
|
|
);
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2020-08-15 02:35:39 +08:00
|
|
|
target.subscribe(next => next && next[prop] && next[prop](true), options[0]);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
return target;
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
ko.extenders.falseTimeout = (target, option) => {
|
|
|
|
target.iFalseTimeoutTimeout = 0;
|
2020-08-15 02:35:39 +08:00
|
|
|
target.subscribe(value => {
|
2019-07-05 03:19:24 +08:00
|
|
|
if (value) {
|
2020-08-12 06:25:36 +08:00
|
|
|
clearTimeout(target.iFalseTimeoutTimeout);
|
2020-07-23 02:28:25 +08:00
|
|
|
target.iFalseTimeoutTimeout = setTimeout(() => {
|
2016-08-17 06:01:20 +08:00
|
|
|
target(false);
|
|
|
|
target.iFalseTimeoutTimeout = 0;
|
2020-08-15 02:35:39 +08:00
|
|
|
}, parseInt(option, 10) || 0);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
return target;
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// functions
|
2014-10-04 19:58:01 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
ko.observable.fn.deleteAccessHelper = function() {
|
2020-10-27 18:09:24 +08:00
|
|
|
return this.extend({ falseTimeout: 3000, toggleSubscribeProperty: [this, 'deleteAccess'] });
|
2016-06-30 08:02:45 +08:00
|
|
|
};
|
2014-08-25 15:10:51 +08:00
|
|
|
|
2020-10-26 19:54:03 +08:00
|
|
|
ko.addObservablesTo = (target, observables) => {
|
|
|
|
Object.entries(observables).forEach(([key, value]) => target[key] = ko.observable(value) );
|
|
|
|
/*
|
|
|
|
Object.entries(observables).forEach(([key, value]) =>
|
|
|
|
target[key] = Array.isArray(value) ? ko.observableArray(value) : ko.observable(value)
|
|
|
|
);
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
|
|
|
|
ko.addComputablesTo = (target, computables) =>
|
|
|
|
Object.entries(computables).forEach(([key, fn]) => target[key] = ko.computed(fn));
|
|
|
|
|
|
|
|
ko.addSubscribablesTo = (target, subscribables) =>
|
|
|
|
Object.entries(subscribables).forEach(([key, fn]) => target[key].subscribe(fn));
|
|
|
|
|
2017-03-01 02:44:13 +08:00
|
|
|
export default ko;
|