snappymail/dev/External/ko.js

716 lines
18 KiB
JavaScript
Raw Normal View History

2020-08-14 04:58:41 +08:00
import { SaveSettingsStep } from 'Common/Enums';
const
$ = jQuery,
ko = window.ko,
2020-08-13 19:16:08 +08:00
Translator = () => require('Common/Translator'),
isFunction = v => typeof v === 'function';
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.editor = {
init: (element, fValueAccessor) => {
let editor = null;
2015-04-17 01:55:13 +08:00
2019-07-05 03:19:24 +08:00
const fValue = fValueAccessor(),
HtmlEditor = require('Common/HtmlEditor').default,
fUpdateEditorValue = () => fValue && fValue.__editor && fValue.__editor.setHtmlOrPlain(fValue()),
fUpdateKoValue = () => fValue && fValue.__editor && fValue(fValue.__editor.getDataWithHtmlMark()),
fOnReady = () => {
fValue.__editor = editor;
2016-06-30 08:02:45 +08:00
fUpdateEditorValue();
};
2015-04-07 03:32:19 +08:00
2019-07-05 03:19:24 +08:00
if (ko.isObservable(fValue) && HtmlEditor) {
editor = new HtmlEditor(element, fUpdateKoValue, fOnReady, fUpdateKoValue);
2015-04-17 01:55:13 +08:00
2016-06-30 08:02:45 +08:00
fValue.__fetchEditorValue = fUpdateKoValue;
2015-04-07 03:32:19 +08:00
2016-06-30 08:02:45 +08:00
fValue.subscribe(fUpdateEditorValue);
2015-04-17 01:55:13 +08:00
// ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
// });
2015-04-07 03:32:19 +08:00
}
2016-06-30 08:02:45 +08:00
}
};
2015-04-07 03:32:19 +08:00
ko.bindingHandlers.visibleAnimated = {
init: (element, fValueAccessor) => element.hidden = !ko.unwrap(fValueAccessor()),
update: (element, fValueAccessor) => element.hidden = !ko.unwrap(fValueAccessor())
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.tooltip = {
init: (element, fValueAccessor) => {
2020-08-13 19:16:08 +08:00
const fValue = fValueAccessor(),
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals');
2020-08-13 19:16:08 +08:00
if (!Globals.bMobileDevice || 'on' === element.dataset.tooltipMobile) {
const sValue = !ko.isObservable(fValue) && isFunction(fValue) ? fValue() : ko.unwrap(fValue);
2014-08-20 23:03:12 +08:00
2020-08-13 19:16:08 +08:00
if ('off' === element.dataset.tooltipI18n) {
element.title = sValue;
} else {
2020-08-13 19:16:08 +08:00
element.title = Translator().i18n(sValue);
Translator().trigger.subscribe(() =>
element.title = Translator().i18n(sValue)
);
Globals.dropdownVisibility.subscribe(() =>
element.title = Translator().i18n(sValue)
);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
}
},
update: (element, fValueAccessor) => {
2020-08-13 19:16:08 +08:00
const fValue = fValueAccessor(),
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals');
2020-08-13 19:16:08 +08:00
if (!Globals.bMobileDevice || 'on' === element.dataset.tooltipMobile) {
const sValue = !ko.isObservable(fValue) && isFunction(fValue) ? fValue() : ko.unwrap(fValue);
2019-07-05 03:19:24 +08:00
if (sValue) {
2020-08-13 19:16:08 +08:00
element.title = 'off' === element.dataset.tooltipI18n ? sValue : Translator().i18n(sValue);
2019-07-05 03:19:24 +08:00
} else {
2020-08-13 19:16:08 +08:00
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 = {
init: element => {
document.addEventListener('click', () => element.removeAttribute('data-rainloopErrorTip'));
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeAttribute('data-rainloopErrorTip'));
2016-06-30 08:02:45 +08:00
},
update: (element, fValueAccessor) => {
2020-08-13 19:16:08 +08:00
const fValue = fValueAccessor(),
value = !ko.isObservable(fValue) && isFunction(fValue) ? fValue() : ko.unwrap(fValue);
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
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.registrateBootstrapDropdown = {
init: (element) => {
const Globals = require('Common/Globals');
2019-07-05 03:19:24 +08:00
if (Globals && Globals.data.aBootstrapDropdowns) {
Globals.data.aBootstrapDropdowns.push($(element));
element.addEventListener('click', () => require('Common/Utils').detectDropdownVisibility());
}
2016-06-30 08:02:45 +08:00
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.openDropdownTrigger = {
update: (element, fValueAccessor) => {
2019-07-05 03:19:24 +08:00
if (ko.unwrap(fValueAccessor())) {
const $el = $(element), t = $el.find('.dropdown-toggle');
2019-07-05 03:19:24 +08:00
if (!$el.hasClass('open')) {
t.dropdown('toggle');
2016-06-30 08:02:45 +08:00
}
2014-10-04 19:58:01 +08:00
t.focus();
2016-06-30 08:02:45 +08:00
require('Common/Utils').detectDropdownVisibility();
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 = {
init: element => $(element)
.closest('.dropdown')
.on('click', '.e-item', () => {
$(element).dropdown('toggle');
})
2016-06-30 08:02:45 +08:00
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.popover = {
init: (element, fValueAccessor) => {
console.log('TODO: $(element).popover removed', element, fValueAccessor);
2020-08-08 20:39:51 +08:00
/*
$(element).popover(ko.unwrap(fValueAccessor()));
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).popover('destroy');
2016-06-30 08:02:45 +08:00
});
2020-08-08 20:39:51 +08:00
*/
2016-06-30 08:02:45 +08:00
}
};
2014-10-04 19:58:01 +08:00
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.onEnter = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
$(element).on('keypress.koOnEnter', (event) => {
if (event && 13 === parseInt(event.keyCode, 10)) {
$(element).trigger('change');
fValueAccessor().call(viewModel);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
});
2014-08-20 23:03:12 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).off('keypress.koOnEnter');
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 = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
$(element).on('keyup.koOnSpace', (event) => {
if (event && 32 === parseInt(event.keyCode, 10)) {
fValueAccessor().call(viewModel, event);
2016-06-30 08:02:45 +08:00
}
});
2014-08-25 15:10:51 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).off('keyup.koOnSpace');
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.onEsc = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
2016-08-22 05:30:34 +08:00
$(element).on('keyup.koOnEsc', (event) => {
if (event && 27 === parseInt(event.keyCode, 10)) {
$(element).trigger('change');
fValueAccessor().call(viewModel);
2015-02-15 08:30:21 +08:00
}
2016-06-30 08:02:45 +08:00
});
2015-02-15 08:30:21 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
2016-08-22 05:30:34 +08:00
$(element).off('keyup.koOnEsc');
2016-06-30 08:02:45 +08:00
});
}
};
2015-03-07 08:32:06 +08:00
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.modal = {
init: (element, fValueAccessor) => {
const Globals = require('Common/Globals');
2016-06-30 08:02:45 +08:00
$(element)
.toggleClass('fade', !Globals.bMobileDevice)
.modal({
'keyboard': false,
'show': ko.unwrap(fValueAccessor())
})
2019-07-05 03:19:24 +08:00
.find('.close')
.on('click.koModal', () => {
fValueAccessor()(false);
});
2014-08-20 23:03:12 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element)
2016-06-30 08:02:45 +08:00
.off('shown.koModal')
.find('.close')
.off('click.koModal');
});
},
update: (element, fValueAccessor) => {
const Globals = require('Common/Globals');
2014-08-20 23:03:12 +08:00
$(element).modal(ko.unwrap(fValueAccessor()) ? 'show' : 'hide');
2014-08-20 23:03:12 +08:00
if (Globals.$htmlCL.contains('rl-anim')) {
Globals.$htmlCL.add('rl-modal-animation');
setTimeout(() => Globals.$htmlCL.remove('rl-modal-animation'), 500);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
}
};
let ttn = (element, fValueAccessor) => require('Common/Momentor').timeToNode(element, ko.unwrap(fValueAccessor()));
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.moment = {
init: ttn,
update: ttn
2016-06-30 08:02:45 +08:00
};
ko.bindingHandlers.i18nInit = {
init: element => Translator().i18nToNodes(element)
2016-06-30 08:02:45 +08:00
};
ko.bindingHandlers.i18nUpdate = {
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
ko.unwrap(fValueAccessor());
Translator().i18nToNodes(element);
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.link = {
update: (element, fValueAccessor) => element.setAttribute('href', ko.unwrap(fValueAccessor()))
2016-06-30 08:02:45 +08:00
};
ko.bindingHandlers.title = {
update: (element, fValueAccessor) => element.setAttribute('title', ko.unwrap(fValueAccessor()))
2016-06-30 08:02:45 +08:00
};
ko.bindingHandlers.initDom = {
init: (element, fValueAccessor) => fValueAccessor()(element)
2016-06-30 08:02:45 +08:00
};
ko.bindingHandlers.draggable = {
init: (element, fValueAccessor, fAllBindingsAccessor) => {
2019-07-05 03:19:24 +08:00
const Globals = require('Common/Globals'),
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils');
2014-10-04 19:58:01 +08:00
2019-07-05 03:19:24 +08:00
if (!Globals.bMobileDevice) {
const triggerZone = 50,
scrollSpeed = 3,
2016-06-30 08:02:45 +08:00
fAllValueFunc = fAllBindingsAccessor(),
selector = fAllValueFunc ? fAllValueFunc.droppableSelector : '',
droppable = selector ? document.querySelector(selector) : null,
conf = {
2016-06-30 08:02:45 +08:00
distance: 20,
handle: '.dragHandle',
2019-07-05 03:19:24 +08:00
cursorAt: { top: 22, left: 3 },
2016-06-30 08:02:45 +08:00
refreshPositions: true,
2016-09-10 06:38:16 +08:00
scroll: true,
drag: null,
stop: null,
helper: null
2016-06-30 08:02:45 +08:00
};
let bcr;
if (droppable) {
conf.drag = event => {
if (droppable.scrollTopMax) {
clearInterval(droppable.timerScroll);
if (droppable.scrollTop
&& bcr.top < event.clientY
&& bcr.top + triggerZone > event.clientY)
{
droppable.timerScroll = setInterval(() => droppable.scrollTop -= scrollSpeed, 10);
}
else if (droppable.scrollTop < droppable.scrollTopMax
&& bcr.bottom > event.clientY
&& bcr.bottom - triggerZone < event.clientY)
{
droppable.timerScroll = setInterval(() => droppable.scrollTop += scrollSpeed, 10);
}
else {
clearInterval(droppable.timerScroll);
2016-06-30 08:02:45 +08:00
}
}
2014-08-20 23:03:12 +08:00
};
conf.stop = () => clearInterval(droppable.timerScroll);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
conf.helper = event => fValueAccessor()(event && event.target ? ko.dataFor(event.target) : null);
2016-06-30 08:02:45 +08:00
2019-07-05 03:19:24 +08:00
$(element)
.draggable(conf)
.on('mousedown.koDraggable', () => {
Utils.removeInFocus();
bcr = droppable ? droppable.getBoundingClientRect() : null;
2019-07-05 03:19:24 +08:00
});
2016-06-30 08:02:45 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () =>
$(element)
2016-06-30 08:02:45 +08:00
.off('mousedown.koDraggable')
.draggable('destroy')
);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.droppable = {
init: (element, fValueAccessor, fAllBindingsAccessor) => {
const Globals = require('Common/Globals');
2019-07-05 03:19:24 +08:00
if (!Globals.bMobileDevice) {
const fValueFunc = fValueAccessor(),
2016-06-30 08:02:45 +08:00
fAllValueFunc = fAllBindingsAccessor(),
fOverCallback = fAllValueFunc && fAllValueFunc.droppableOver ? fAllValueFunc.droppableOver : null,
fOutCallback = fAllValueFunc && fAllValueFunc.droppableOut ? fAllValueFunc.droppableOut : null,
conf = {
2016-06-30 08:02:45 +08:00
tolerance: 'pointer',
2016-09-10 06:38:16 +08:00
hoverClass: 'droppableHover',
drop: null,
over: null,
out: null
2016-06-30 08:02:45 +08:00
};
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (fValueFunc) {
conf.drop = (event, ui) => {
fValueFunc(event, ui);
2016-06-30 08:02:45 +08:00
};
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (fOverCallback) {
conf.over = (event, ui) => {
fOverCallback(event, ui);
2014-08-20 23:03:12 +08:00
};
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (fOutCallback) {
conf.out = (event, ui) => {
fOutCallback(event, ui);
2016-06-30 08:02:45 +08:00
};
}
2014-08-20 23:03:12 +08:00
$(element).droppable(conf);
2014-10-04 19:58:01 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).droppable('destroy');
2016-06-30 08:02:45 +08:00
});
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.saveTrigger = {
init: (element) => {
const $el = $(element);
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
$el.data(
'save-trigger-type',
$el.is('input[type=text],input[type=email],input[type=password],select,textarea') ? 'input' : 'custom'
);
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if ('custom' === $el.data('save-trigger-type')) {
$el
.append(
'&nbsp;&nbsp;' +
'<i class="icon-spinner animated"></i>' +
'<i class="icon-remove error"></i>' +
'<i class="icon-ok success"></i>'
)
.addClass('settings-saved-trigger');
} else {
$el.addClass('settings-saved-trigger-input');
2016-06-30 08:02:45 +08:00
}
},
update: (element, fValueAccessor) => {
2019-07-05 03:19:24 +08:00
const value = ko.unwrap(fValueAccessor()),
$el = $(element);
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if ('custom' === $el.data('save-trigger-type')) {
switch (value.toString()) {
2016-06-30 08:02:45 +08:00
case '1':
$el
2019-07-05 03:19:24 +08:00
.find('.animated,.error')
.hide()
.removeClass('visible')
2016-06-30 08:02:45 +08:00
.end()
2019-07-05 03:19:24 +08:00
.find('.success')
.show()
.addClass('visible');
2016-06-30 08:02:45 +08:00
break;
case '0':
$el
2019-07-05 03:19:24 +08:00
.find('.animated,.success')
.hide()
.removeClass('visible')
2016-06-30 08:02:45 +08:00
.end()
2019-07-05 03:19:24 +08:00
.find('.error')
.show()
.addClass('visible');
2016-06-30 08:02:45 +08:00
break;
case '-2':
$el
2019-07-05 03:19:24 +08:00
.find('.error,.success')
.hide()
.removeClass('visible')
2016-06-30 08:02:45 +08:00
.end()
2019-07-05 03:19:24 +08:00
.find('.animated')
.show()
.addClass('visible');
2016-06-30 08:02:45 +08:00
break;
default:
$el
2019-07-05 03:19:24 +08:00
.find('.animated')
.hide()
2016-06-30 08:02:45 +08:00
.end()
2019-07-05 03:19:24 +08:00
.find('.error,.success')
.removeClass('visible');
2016-06-30 08:02:45 +08:00
break;
2014-08-20 23:03:12 +08:00
}
2019-07-05 03:19:24 +08:00
} else {
switch (value.toString()) {
2016-06-30 08:02:45 +08:00
case '1':
$el.addClass('success').removeClass('error');
2016-06-30 08:02:45 +08:00
break;
case '0':
$el.addClass('error').removeClass('success');
2016-06-30 08:02:45 +08:00
break;
case '-2':
break;
default:
$el.removeClass('error success');
2016-06-30 08:02:45 +08:00
break;
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.emailsTags = {
init: (element, fValueAccessor, fAllBindingsAccessor) => {
const EmailModel = require('Model/Email').default,
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
fAllBindings = fAllBindingsAccessor(),
inputDelimiters = [',', ';', '\n'];
2016-06-30 08:02:45 +08:00
$el.inputosaurus({
parseOnBlur: true,
allowDragAndDrop: true,
focusCallback: value => {
if (fValue && fValue.focused) {
fValue.focused(!!value);
}
},
2017-09-28 01:58:15 +08:00
inputDelimiters: inputDelimiters,
autoCompleteSource: fAllBindings.autoCompleteSource || null,
splitHook: value => {
const v = value.trim();
2020-07-21 03:39:00 +08:00
if (v && inputDelimiters.includes(v.substr(-1))) {
2017-09-28 01:58:15 +08:00
return EmailModel.splitEmailLine(value);
}
2017-09-28 01:58:15 +08:00
return null;
},
parseHook: input =>
input.map(inputValue => {
const values = EmailModel.parseEmailLine(inputValue);
return values.length ? values : inputValue;
}).flat(Infinity).map(
item => (item.toLine ? [item.toLine(false), item] : [item, null])
2019-07-05 03:19:24 +08:00
),
change: event => {
$el.data('EmailsTagsValue', event.target.value);
fValue(event.target.value);
}
2016-06-30 08:02:45 +08:00
});
2015-02-16 05:55:59 +08:00
2019-07-05 03:19:24 +08:00
if (fValue && fValue.focused && fValue.focused.subscribe) {
fValue.focused.subscribe((value) => {
$el.inputosaurus(value ? 'focus' : 'blur');
2016-06-30 08:02:45 +08:00
});
}
},
update: (element, fValueAccessor) => {
2019-07-05 03:19:24 +08:00
const $oEl = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
value = ko.unwrap(fValue);
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if ($oEl.data('EmailsTagsValue') !== value) {
$oEl.val(value);
$oEl.data('EmailsTagsValue', value);
2016-06-30 08:02:45 +08:00
$oEl.inputosaurus('refresh');
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.command = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
const command = fValueAccessor();
2019-07-05 03:19:24 +08:00
if (!command || !command.isCommand) {
throw new Error('Value should be a command');
}
2019-07-05 03:19:24 +08:00
if (!command.enabled) {
command.enabled = ko.observable(true);
}
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (!command.canExecute) {
const __realCanExecute = command.__realCanExecute;
if (isFunction(__realCanExecute)) {
command.canExecute = ko.computed(() => command.enabled() && __realCanExecute.call(viewModel, viewModel));
2019-07-05 03:19:24 +08:00
} else {
command.canExecute = ko.computed(() => command.enabled() && !!__realCanExecute);
}
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
element.classList.add('command');
ko.bindingHandlers[element.tagName.match(/FORM/i) ? 'submit' : 'click'].init(
2019-07-05 03:19:24 +08:00
element,
fValueAccessor,
fAllBindingsAccessor,
viewModel,
bindingContext
);
2016-06-30 08:02:45 +08:00
},
update: (element, fValueAccessor) => {
const cl = element.classList,
command = fValueAccessor();
2014-08-20 23:03:12 +08:00
let result = command.enabled();
2014-08-20 23:03:12 +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) {
result = command.canExecute();
cl.toggle('command-can-not-be-execute', !result);
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +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
if (element.tagName.match(/INPUT|TEXTAREA|BUTTON/i)) {
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
ko.extenders.posInterer = (target, defaultVal) => {
2019-07-05 03:19:24 +08:00
const Utils = require('Common/Utils'),
result = ko.computed({
read: target,
write: (newValue) => {
let val = Utils.pInt(newValue.toString(), defaultVal);
2019-07-05 03:19:24 +08:00
if (0 >= val) {
val = defaultVal;
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (val === target() && '' + val !== '' + newValue) {
target(val + 1);
2014-08-22 23:08:56 +08:00
}
2014-08-20 23:03:12 +08:00
target(val);
2016-06-30 08:02:45 +08:00
}
});
2014-08-20 23:03:12 +08:00
result(target());
return result;
2016-06-30 08:02:45 +08:00
};
ko.extenders.limitedList = (target, limitedList) => {
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);
if (Array.isArray(list) && list.length) {
if (list.includes(newValue)) {
2019-07-05 03:19:24 +08:00
target(newValue);
} 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('');
}
}
2019-07-05 03:19:24 +08:00
})
.extend({ notify: 'always' });
result(target());
2019-07-05 03:19:24 +08:00
if (!result.valueHasMutated) {
result.valueHasMutated = () => target.valueHasMutated();
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
return result;
2016-06-30 08:02:45 +08:00
};
2014-08-20 23:03:12 +08:00
ko.extenders.reversible = (target) => {
let value = target();
2014-08-20 23:03:12 +08:00
target.commit = () => value = target();
2014-08-20 23:03:12 +08:00
target.reverse = () => target(value);
target.commitedValue = () => value;
return target;
2016-06-30 08:02:45 +08:00
};
ko.extenders.toggleSubscribe = (target, options) => {
target.subscribe(options[1], options[0], 'beforeChange');
target.subscribe(options[2], options[0]);
return target;
2016-06-30 08:02:45 +08:00
};
ko.extenders.toggleSubscribeProperty = (target, options) => {
const prop = options[1];
2019-07-05 03:19:24 +08:00
if (prop) {
target.subscribe(
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
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
return target;
2016-06-30 08:02:45 +08:00
};
ko.extenders.falseTimeout = (target, option) => {
target.iFalseTimeoutTimeout = 0;
target.subscribe(value => {
2019-07-05 03:19:24 +08:00
if (value) {
clearTimeout(target.iFalseTimeoutTimeout);
target.iFalseTimeoutTimeout = setTimeout(() => {
target(false);
target.iFalseTimeoutTimeout = 0;
}, parseInt(option, 10) || 0);
2016-06-30 08:02:45 +08:00
}
});
return target;
2016-06-30 08:02:45 +08:00
};
ko.extenders.specialThrottle = (target, option) => {
target.iSpecialThrottleTimeoutValue = require('Common/Utils').pInt(option);
2019-07-05 03:19:24 +08:00
if (0 < target.iSpecialThrottleTimeoutValue) {
target.iSpecialThrottleTimeout = 0;
2019-07-05 03:19:24 +08:00
target.valueForRead = ko.observable(!!target()).extend({ throttle: 10 });
2015-03-31 08:12:05 +08:00
2016-06-30 08:02:45 +08:00
return ko.computed({
read: target.valueForRead,
write: (bValue) => {
2019-07-05 03:19:24 +08:00
if (bValue) {
target.valueForRead(bValue);
2020-08-19 22:23:15 +08:00
} else if (target.valueForRead()) {
clearTimeout(target.iSpecialThrottleTimeout);
target.iSpecialThrottleTimeout = setTimeout(() => {
target.valueForRead(false);
target.iSpecialThrottleTimeout = 0;
}, target.iSpecialThrottleTimeoutValue);
2019-07-05 03:19:24 +08:00
} else {
2020-08-19 22:23:15 +08:00
target.valueForRead(bValue);
2015-03-31 08:12:05 +08:00
}
2016-06-30 08:02:45 +08:00
}
});
}
2015-03-31 08:12:05 +08:00
return target;
2016-06-30 08:02:45 +08:00
};
2015-03-31 08:12:05 +08:00
ko.extenders.idleTrigger = (target) => {
target.trigger = ko.observable(SaveSettingsStep.Idle);
return target;
2016-07-16 03:54:37 +08:00
};
2016-06-30 08:02:45 +08:00
// functions
2014-10-04 19:58:01 +08:00
ko.observable.fn.idleTrigger = function() {
2019-07-05 03:19:24 +08:00
return this.extend({ 'idleTrigger': true });
2016-07-16 05:29:42 +08:00
};
ko.observable.fn.validateEmail = function() {
2016-06-30 08:02:45 +08:00
this.hasError = ko.observable(false);
2014-08-20 23:03:12 +08:00
this.subscribe(value => this.hasError(value && !/^[^@\s]+@[^@\s]+$/.test(value)));
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
this.valueHasMutated();
return this;
};
2014-08-20 23:03:12 +08:00
ko.observable.fn.validateSimpleEmail = function() {
2016-06-30 08:02:45 +08:00
this.hasError = ko.observable(false);
2014-08-20 23:03:12 +08:00
this.subscribe(value => this.hasError(value && !/^.+@.+$/.test(value)));
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
this.valueHasMutated();
return this;
};
2014-08-20 23:03:12 +08:00
ko.observable.fn.deleteAccessHelper = function() {
2019-07-05 03:19:24 +08:00
this.extend({ falseTimeout: 3000 }).extend({ toggleSubscribeProperty: [this, 'deleteAccess'] });
2016-06-30 08:02:45 +08:00
return this;
};
2014-08-25 15:10:51 +08:00
2017-03-01 02:44:13 +08:00
export default ko;