mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 04:59:21 +03:00
Added: addEventsListener() and addEventsListeners()
This commit is contained in:
parent
c270f0ad9a
commit
5990addfef
14 changed files with 484 additions and 464 deletions
392
dev/External/User/ko.js
vendored
392
dev/External/User/ko.js
vendored
|
|
@ -2,7 +2,7 @@ import 'External/ko';
|
|||
import ko from 'ko';
|
||||
import { HtmlEditor } from 'Common/Html';
|
||||
import { timeToNode } from 'Common/Translator';
|
||||
import { elementById } from 'Common/Globals';
|
||||
import { elementById, addEventsListeners } from 'Common/Globals';
|
||||
import { isArray } from 'Common/Utils';
|
||||
import { EmailAddressesComponent } from 'Component/EmailAddresses';
|
||||
import { ThemeStore } from 'Stores/Theme';
|
||||
|
|
@ -29,226 +29,236 @@ const rlContentType = 'snappymail/action',
|
|||
id: 0,
|
||||
stop: () => clearTimeout(dragTimer.id),
|
||||
start: fn => dragTimer.id = setTimeout(fn, 500)
|
||||
};
|
||||
},
|
||||
|
||||
ttn = (element, fValueAccessor) => timeToNode(element, ko.unwrap(fValueAccessor()));
|
||||
|
||||
let dragImage,
|
||||
dragData;
|
||||
|
||||
ko.bindingHandlers.editor = {
|
||||
init: (element, fValueAccessor) => {
|
||||
let editor = null;
|
||||
Object.assign(ko.bindingHandlers, {
|
||||
|
||||
const fValue = fValueAccessor(),
|
||||
fUpdateEditorValue = () => fValue && fValue.__editor && fValue.__editor.setHtmlOrPlain(fValue()),
|
||||
fUpdateKoValue = () => fValue && fValue.__editor && fValue(fValue.__editor.getDataWithHtmlMark()),
|
||||
fOnReady = () => {
|
||||
fValue.__editor = editor;
|
||||
fUpdateEditorValue();
|
||||
};
|
||||
editor: {
|
||||
init: (element, fValueAccessor) => {
|
||||
let editor = null;
|
||||
|
||||
if (ko.isObservable(fValue) && HtmlEditor) {
|
||||
editor = new HtmlEditor(element, fUpdateKoValue, fOnReady, fUpdateKoValue);
|
||||
const fValue = fValueAccessor(),
|
||||
fUpdateEditorValue = () => fValue && fValue.__editor && fValue.__editor.setHtmlOrPlain(fValue()),
|
||||
fUpdateKoValue = () => fValue && fValue.__editor && fValue(fValue.__editor.getDataWithHtmlMark()),
|
||||
fOnReady = () => {
|
||||
fValue.__editor = editor;
|
||||
fUpdateEditorValue();
|
||||
};
|
||||
|
||||
fValue.__fetchEditorValue = fUpdateKoValue;
|
||||
if (ko.isObservable(fValue) && HtmlEditor) {
|
||||
editor = new HtmlEditor(element, fUpdateKoValue, fOnReady, fUpdateKoValue);
|
||||
|
||||
fValue.subscribe(fUpdateEditorValue);
|
||||
fValue.__fetchEditorValue = fUpdateKoValue;
|
||||
|
||||
// ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
|
||||
// });
|
||||
}
|
||||
}
|
||||
};
|
||||
fValue.subscribe(fUpdateEditorValue);
|
||||
|
||||
let ttn = (element, fValueAccessor) => timeToNode(element, ko.unwrap(fValueAccessor()));
|
||||
ko.bindingHandlers.moment = {
|
||||
init: ttn,
|
||||
update: ttn
|
||||
};
|
||||
|
||||
ko.bindingHandlers.emailsTags = {
|
||||
init: (element, fValueAccessor, fAllBindings) => {
|
||||
const fValue = fValueAccessor();
|
||||
|
||||
element.addresses = new EmailAddressesComponent(element, {
|
||||
focusCallback: value => fValue.focused && fValue.focused(!!value),
|
||||
autoCompleteSource: fAllBindings.get('autoCompleteSource'),
|
||||
onChange: value => fValue(value)
|
||||
});
|
||||
|
||||
if (fValue.focused && fValue.focused.subscribe) {
|
||||
fValue.focused.subscribe(value =>
|
||||
element.addresses[value ? 'focus' : 'blur']()
|
||||
);
|
||||
// ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
|
||||
// });
|
||||
}
|
||||
}
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
element.addresses.value = ko.unwrap(fValueAccessor());
|
||||
}
|
||||
};
|
||||
|
||||
// Start dragging selected messages
|
||||
ko.bindingHandlers.dragmessages = {
|
||||
init: (element, fValueAccessor) => {
|
||||
element.addEventListener("dragstart", e => {
|
||||
let data = fValueAccessor()(e);
|
||||
dragImage || (dragImage = elementById('messagesDragImage'));
|
||||
if (data && dragImage && !ThemeStore.isMobile()) {
|
||||
dragImage.querySelector('.text').textContent = data.uids.length;
|
||||
let img = dragImage.querySelector('i');
|
||||
img.classList.toggle('icon-copy', e.ctrlKey);
|
||||
img.classList.toggle('icon-mail', !e.ctrlKey);
|
||||
moment: {
|
||||
init: ttn,
|
||||
update: ttn
|
||||
},
|
||||
|
||||
// Else Chrome doesn't show it
|
||||
dragImage.style.left = e.clientX + 'px';
|
||||
dragImage.style.top = e.clientY + 'px';
|
||||
dragImage.style.right = 'auto';
|
||||
emailsTags: {
|
||||
init: (element, fValueAccessor, fAllBindings) => {
|
||||
const fValue = fValueAccessor();
|
||||
|
||||
setDragAction(e, 'messages', e.ctrlKey ? 'copy' : 'move', data, dragImage);
|
||||
element.addresses = new EmailAddressesComponent(element, {
|
||||
focusCallback: value => fValue.focused && fValue.focused(!!value),
|
||||
autoCompleteSource: fAllBindings.get('autoCompleteSource'),
|
||||
onChange: value => fValue(value)
|
||||
});
|
||||
|
||||
// Remove the Chrome visibility
|
||||
dragImage.style.cssText = '';
|
||||
} else {
|
||||
e.preventDefault();
|
||||
if (fValue.focused && fValue.focused.subscribe) {
|
||||
fValue.focused.subscribe(value =>
|
||||
element.addresses[value ? 'focus' : 'blur']()
|
||||
);
|
||||
}
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
element.addresses.value = ko.unwrap(fValueAccessor());
|
||||
}
|
||||
},
|
||||
|
||||
}, false);
|
||||
element.addEventListener("dragend", () => dragData = null);
|
||||
element.setAttribute('draggable', true);
|
||||
}
|
||||
};
|
||||
// Start dragging selected messages
|
||||
dragmessages: {
|
||||
init: (element, fValueAccessor) => {
|
||||
element.addEventListener("dragstart", e => {
|
||||
let data = fValueAccessor()(e);
|
||||
dragImage || (dragImage = elementById('messagesDragImage'));
|
||||
if (data && dragImage && !ThemeStore.isMobile()) {
|
||||
dragImage.querySelector('.text').textContent = data.uids.length;
|
||||
let img = dragImage.querySelector('i');
|
||||
img.classList.toggle('icon-copy', e.ctrlKey);
|
||||
img.classList.toggle('icon-mail', !e.ctrlKey);
|
||||
|
||||
// Drop selected messages on folder
|
||||
ko.bindingHandlers.dropmessages = {
|
||||
init: (element, fValueAccessor) => {
|
||||
const folder = fValueAccessor(),
|
||||
// folder = ko.dataFor(element),
|
||||
fnStop = e => {
|
||||
e.preventDefault();
|
||||
element.classList.remove('droppableHover');
|
||||
dragTimer.stop();
|
||||
},
|
||||
fnHover = e => {
|
||||
if ('messages' === getDragAction(e)) {
|
||||
fnStop(e);
|
||||
element.classList.add('droppableHover');
|
||||
if (folder && folder.collapsed()) {
|
||||
dragTimer.start(() => {
|
||||
folder.collapsed(false);
|
||||
setExpandedFolder(folder.fullName, true);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
};
|
||||
element.addEventListener("dragenter", fnHover);
|
||||
element.addEventListener("dragover", fnHover);
|
||||
element.addEventListener("dragleave", fnStop);
|
||||
element.addEventListener("drop", e => {
|
||||
fnStop(e);
|
||||
if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) {
|
||||
let data = dragData.data;
|
||||
if (folder && data && data.folder && isArray(data.uids)) {
|
||||
moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
// Else Chrome doesn't show it
|
||||
dragImage.style.left = e.clientX + 'px';
|
||||
dragImage.style.top = e.clientY + 'px';
|
||||
dragImage.style.right = 'auto';
|
||||
|
||||
ko.bindingHandlers.sortableItem = {
|
||||
init: (element, fValueAccessor) => {
|
||||
let options = ko.unwrap(fValueAccessor()) || {},
|
||||
parent = element.parentNode,
|
||||
fnHover = e => {
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
setDragAction(e, 'messages', e.ctrlKey ? 'copy' : 'move', data, dragImage);
|
||||
|
||||
// Remove the Chrome visibility
|
||||
dragImage.style.cssText = '';
|
||||
} else {
|
||||
e.preventDefault();
|
||||
let node = (e.target.closest ? e.target : e.target.parentNode).closest('[draggable]');
|
||||
if (node && node !== dragData.data && parent.contains(node)) {
|
||||
let rect = node.getBoundingClientRect();
|
||||
if (rect.top + (rect.height / 2) <= e.clientY) {
|
||||
if (node.nextElementSibling !== dragData.data) {
|
||||
node.after(dragData.data);
|
||||
}
|
||||
} else if (node.previousElementSibling !== dragData.data) {
|
||||
node.before(dragData.data);
|
||||
}
|
||||
|
||||
}, false);
|
||||
element.addEventListener("dragend", () => dragData = null);
|
||||
element.setAttribute('draggable', true);
|
||||
}
|
||||
},
|
||||
|
||||
// Drop selected messages on folder
|
||||
dropmessages: {
|
||||
init: (element, fValueAccessor) => {
|
||||
const folder = fValueAccessor(),
|
||||
// folder = ko.dataFor(element),
|
||||
fnStop = e => {
|
||||
e.preventDefault();
|
||||
element.classList.remove('droppableHover');
|
||||
dragTimer.stop();
|
||||
},
|
||||
fnHover = e => {
|
||||
if ('messages' === getDragAction(e)) {
|
||||
fnStop(e);
|
||||
element.classList.add('droppableHover');
|
||||
if (folder && folder.collapsed()) {
|
||||
dragTimer.start(() => {
|
||||
folder.collapsed(false);
|
||||
setExpandedFolder(folder.fullName, true);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
};
|
||||
addEventsListeners(element, {
|
||||
dragenter: fnHover,
|
||||
dragover: fnHover,
|
||||
dragleave: fnStop,
|
||||
drop: e => {
|
||||
fnStop(e);
|
||||
if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) {
|
||||
let data = dragData.data;
|
||||
if (folder && data && data.folder && isArray(data.uids)) {
|
||||
moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
element.addEventListener("dragstart", e => {
|
||||
dragData = {
|
||||
action: 'sortable',
|
||||
element: element
|
||||
};
|
||||
setDragAction(e, 'sortable', 'move', element, element);
|
||||
element.style.opacity = 0.25;
|
||||
});
|
||||
element.addEventListener("dragend", e => {
|
||||
element.style.opacity = null;
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
dragData.data.style.cssText = '';
|
||||
let row = parent.rows[options.list.indexOf(ko.dataFor(element))];
|
||||
if (row != dragData.data) {
|
||||
row.before(dragData.data);
|
||||
}
|
||||
dragData = null;
|
||||
}
|
||||
});
|
||||
if (!parent.sortable) {
|
||||
parent.sortable = true;
|
||||
parent.addEventListener("dragenter", fnHover);
|
||||
parent.addEventListener("dragover", fnHover);
|
||||
parent.addEventListener("drop", e => {
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
e.preventDefault();
|
||||
let data = ko.dataFor(dragData.data),
|
||||
from = options.list.indexOf(data),
|
||||
to = [...parent.children].indexOf(dragData.data);
|
||||
if (from != to) {
|
||||
let arr = options.list();
|
||||
arr.splice(to, 0, ...arr.splice(from, 1));
|
||||
options.list(arr);
|
||||
}
|
||||
dragData = null;
|
||||
options.afterMove && options.afterMove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
ko.bindingHandlers.initDom = {
|
||||
init: (element, fValueAccessor) => fValueAccessor()(element)
|
||||
};
|
||||
|
||||
ko.bindingHandlers.onEsc = {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if ('Escape' == event.key) {
|
||||
element.dispatchEvent(new Event('change'));
|
||||
fValueAccessor().call(viewModel);
|
||||
sortableItem: {
|
||||
init: (element, fValueAccessor) => {
|
||||
let options = ko.unwrap(fValueAccessor()) || {},
|
||||
parent = element.parentNode,
|
||||
fnHover = e => {
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
e.preventDefault();
|
||||
let node = (e.target.closest ? e.target : e.target.parentNode).closest('[draggable]');
|
||||
if (node && node !== dragData.data && parent.contains(node)) {
|
||||
let rect = node.getBoundingClientRect();
|
||||
if (rect.top + (rect.height / 2) <= e.clientY) {
|
||||
if (node.nextElementSibling !== dragData.data) {
|
||||
node.after(dragData.data);
|
||||
}
|
||||
} else if (node.previousElementSibling !== dragData.data) {
|
||||
node.before(dragData.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
addEventsListeners(element, {
|
||||
dragstart: e => {
|
||||
dragData = {
|
||||
action: 'sortable',
|
||||
element: element
|
||||
};
|
||||
setDragAction(e, 'sortable', 'move', element, element);
|
||||
element.style.opacity = 0.25;
|
||||
},
|
||||
dragend: e => {
|
||||
element.style.opacity = null;
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
dragData.data.style.cssText = '';
|
||||
let row = parent.rows[options.list.indexOf(ko.dataFor(element))];
|
||||
if (row != dragData.data) {
|
||||
row.before(dragData.data);
|
||||
}
|
||||
dragData = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!parent.sortable) {
|
||||
parent.sortable = true;
|
||||
addEventsListeners(parent, {
|
||||
dragenter: fnHover,
|
||||
dragover: fnHover,
|
||||
drop: e => {
|
||||
if ('sortable' === getDragAction(e)) {
|
||||
e.preventDefault();
|
||||
let data = ko.dataFor(dragData.data),
|
||||
from = options.list.indexOf(data),
|
||||
to = [...parent.children].indexOf(dragData.data);
|
||||
if (from != to) {
|
||||
let arr = options.list();
|
||||
arr.splice(to, 0, ...arr.splice(from, 1));
|
||||
options.list(arr);
|
||||
}
|
||||
dragData = null;
|
||||
options.afterMove && options.afterMove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
element.addEventListener('keyup', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
ko.bindingHandlers.registerBootstrapDropdown = {
|
||||
init: element => {
|
||||
rl.Dropdowns.register(element);
|
||||
element.ddBtn = new BSN.Dropdown(element.querySelector('.dropdown-toggle'));
|
||||
}
|
||||
};
|
||||
initDom: {
|
||||
init: (element, fValueAccessor) => fValueAccessor()(element)
|
||||
},
|
||||
|
||||
ko.bindingHandlers.openDropdownTrigger = {
|
||||
update: (element, fValueAccessor) => {
|
||||
if (ko.unwrap(fValueAccessor())) {
|
||||
const el = element.ddBtn;
|
||||
el.open || el.toggle();
|
||||
// el.focus();
|
||||
onEsc: {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if ('Escape' == event.key) {
|
||||
element.dispatchEvent(new Event('change'));
|
||||
fValueAccessor().call(viewModel);
|
||||
}
|
||||
};
|
||||
element.addEventListener('keyup', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
|
||||
}
|
||||
},
|
||||
|
||||
rl.Dropdowns.detectVisibility();
|
||||
fValueAccessor()(false);
|
||||
registerBootstrapDropdown: {
|
||||
init: element => {
|
||||
rl.Dropdowns.register(element);
|
||||
element.ddBtn = new BSN.Dropdown(element.querySelector('.dropdown-toggle'));
|
||||
}
|
||||
},
|
||||
|
||||
openDropdownTrigger: {
|
||||
update: (element, fValueAccessor) => {
|
||||
if (ko.unwrap(fValueAccessor())) {
|
||||
const el = element.ddBtn;
|
||||
el.open || el.toggle();
|
||||
// el.focus();
|
||||
|
||||
rl.Dropdowns.detectVisibility();
|
||||
fValueAccessor()(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
|||
202
dev/External/ko.js
vendored
202
dev/External/ko.js
vendored
|
|
@ -5,6 +5,10 @@ import { SaveSettingsStep } from 'Common/Enums';
|
|||
import { arrayLength, isFunction, forEachObjectEntry } from 'Common/Utils';
|
||||
|
||||
export const
|
||||
errorTip = (element, value) => value
|
||||
? setTimeout(() => element.setAttribute('data-rainloopErrorTip', value), 100)
|
||||
: element.removeAttribute('data-rainloopErrorTip'),
|
||||
|
||||
/**
|
||||
* The value of the pureComputed observable shouldn’t vary based on the
|
||||
* number of evaluations or other “hidden” information. Its value should be
|
||||
|
|
@ -35,118 +39,116 @@ export const
|
|||
return data;
|
||||
};
|
||||
|
||||
ko.bindingHandlers.tooltipErrorTip = {
|
||||
init: (element, fValueAccessor) => {
|
||||
doc.addEventListener('click', () => {
|
||||
let value = fValueAccessor();
|
||||
ko.isObservable(value) && !ko.isComputed(value) && value('');
|
||||
element.removeAttribute('data-rainloopErrorTip');
|
||||
});
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
let value = ko.unwrap(fValueAccessor());
|
||||
value = isFunction(value) ? value() : value;
|
||||
if (value) {
|
||||
setTimeout(() => element.setAttribute('data-rainloopErrorTip', value), 100);
|
||||
} else {
|
||||
element.removeAttribute('data-rainloopErrorTip');
|
||||
Object.assign(ko.bindingHandlers, {
|
||||
tooltipErrorTip: {
|
||||
init: (element, fValueAccessor) => {
|
||||
doc.addEventListener('click', () => {
|
||||
let value = fValueAccessor();
|
||||
ko.isObservable(value) && !ko.isComputed(value) && value('');
|
||||
errorTip(element);
|
||||
});
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
let value = ko.unwrap(fValueAccessor());
|
||||
value = isFunction(value) ? value() : value;
|
||||
errorTip(element, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
ko.bindingHandlers.onEnter = {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if ('Enter' == event.key) {
|
||||
element.dispatchEvent(new Event('change'));
|
||||
fValueAccessor().call(viewModel);
|
||||
onEnter: {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if ('Enter' == event.key) {
|
||||
element.dispatchEvent(new Event('change'));
|
||||
fValueAccessor().call(viewModel);
|
||||
}
|
||||
};
|
||||
element.addEventListener('keydown', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keydown', fn));
|
||||
}
|
||||
},
|
||||
|
||||
onSpace: {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if (' ' == event.key) {
|
||||
fValueAccessor().call(viewModel, event);
|
||||
}
|
||||
};
|
||||
element.addEventListener('keyup', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
|
||||
}
|
||||
},
|
||||
|
||||
i18nInit: {
|
||||
init: element => i18nToNodes(element)
|
||||
},
|
||||
|
||||
i18nUpdate: {
|
||||
update: (element, fValueAccessor) => {
|
||||
ko.unwrap(fValueAccessor());
|
||||
i18nToNodes(element);
|
||||
}
|
||||
},
|
||||
|
||||
title: {
|
||||
update: (element, fValueAccessor) => element.title = ko.unwrap(fValueAccessor())
|
||||
},
|
||||
|
||||
command: {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel, bindingContext) => {
|
||||
const command = fValueAccessor();
|
||||
|
||||
if (!command || !command.enabled || !command.canExecute) {
|
||||
throw new Error('Value should be a command');
|
||||
}
|
||||
};
|
||||
element.addEventListener('keydown', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keydown', fn));
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.onSpace = {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel) => {
|
||||
let fn = event => {
|
||||
if (' ' == event.key) {
|
||||
fValueAccessor().call(viewModel, event);
|
||||
ko.bindingHandlers['FORM'==element.nodeName ? 'submit' : 'click'].init(
|
||||
element,
|
||||
fValueAccessor,
|
||||
fAllBindings,
|
||||
viewModel,
|
||||
bindingContext
|
||||
);
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
const cl = element.classList,
|
||||
command = fValueAccessor();
|
||||
|
||||
let disabled = !command.enabled();
|
||||
|
||||
disabled = disabled || !command.canExecute();
|
||||
cl.toggle('disabled', disabled);
|
||||
|
||||
if (element.matches('INPUT,TEXTAREA,BUTTON')) {
|
||||
element.disabled = disabled;
|
||||
}
|
||||
};
|
||||
element.addEventListener('keyup', fn);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.i18nInit = {
|
||||
init: element => i18nToNodes(element)
|
||||
};
|
||||
|
||||
ko.bindingHandlers.i18nUpdate = {
|
||||
update: (element, fValueAccessor) => {
|
||||
ko.unwrap(fValueAccessor());
|
||||
i18nToNodes(element);
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.title = {
|
||||
update: (element, fValueAccessor) => element.title = ko.unwrap(fValueAccessor())
|
||||
};
|
||||
|
||||
ko.bindingHandlers.command = {
|
||||
init: (element, fValueAccessor, fAllBindings, viewModel, bindingContext) => {
|
||||
const command = fValueAccessor();
|
||||
|
||||
if (!command || !command.enabled || !command.canExecute) {
|
||||
throw new Error('Value should be a command');
|
||||
}
|
||||
|
||||
ko.bindingHandlers['FORM'==element.nodeName ? 'submit' : 'click'].init(
|
||||
element,
|
||||
fValueAccessor,
|
||||
fAllBindings,
|
||||
viewModel,
|
||||
bindingContext
|
||||
);
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
const cl = element.classList,
|
||||
command = fValueAccessor();
|
||||
|
||||
let disabled = !command.enabled();
|
||||
|
||||
disabled = disabled || !command.canExecute();
|
||||
cl.toggle('disabled', disabled);
|
||||
|
||||
if (element.matches('INPUT,TEXTAREA,BUTTON')) {
|
||||
element.disabled = disabled;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingHandlers.saveTrigger = {
|
||||
init: (element) => {
|
||||
let icon = element;
|
||||
if (element.matches('input,select,textarea')) {
|
||||
element.classList.add('settings-saved-trigger-input');
|
||||
element.after(element.saveTriggerIcon = icon = createElement('span'));
|
||||
}
|
||||
icon.classList.add('settings-save-trigger');
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
const value = parseInt(ko.unwrap(fValueAccessor()),10);
|
||||
let cl = (element.saveTriggerIcon || element).classList;
|
||||
if (element.saveTriggerIcon) {
|
||||
cl.toggle('saving', value === SaveSettingsStep.Animate);
|
||||
saveTrigger: {
|
||||
init: (element) => {
|
||||
let icon = element;
|
||||
if (element.matches('input,select,textarea')) {
|
||||
element.classList.add('settings-saved-trigger-input');
|
||||
element.after(element.saveTriggerIcon = icon = createElement('span'));
|
||||
}
|
||||
icon.classList.add('settings-save-trigger');
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
const value = parseInt(ko.unwrap(fValueAccessor()),10);
|
||||
let cl = (element.saveTriggerIcon || element).classList;
|
||||
if (element.saveTriggerIcon) {
|
||||
cl.toggle('saving', value === SaveSettingsStep.Animate);
|
||||
cl.toggle('success', value === SaveSettingsStep.TrueResult);
|
||||
cl.toggle('error', value === SaveSettingsStep.FalseResult);
|
||||
}
|
||||
cl = element.classList;
|
||||
cl.toggle('success', value === SaveSettingsStep.TrueResult);
|
||||
cl.toggle('error', value === SaveSettingsStep.FalseResult);
|
||||
}
|
||||
cl = element.classList;
|
||||
cl.toggle('success', value === SaveSettingsStep.TrueResult);
|
||||
cl.toggle('error', value === SaveSettingsStep.FalseResult);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// extenders
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue