snappymail/dev/External/ko.js

1237 lines
27 KiB
JavaScript
Raw Normal View History

2014-08-20 23:03:12 +08:00
import window from 'window';
import _ from '_';
import $ from '$';
import Opentip from 'Opentip';
import Pikaday from 'pikaday';
import {SaveSettingsStep, Magics} from 'Common/Enums';
const
2016-06-30 08:02:45 +08:00
ko = window.ko,
$win = $(window),
fDisposalTooltipHelper = (element) => {
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
if (element && element.__opentip)
2016-06-30 08:02:45 +08:00
{
element.__opentip.deactivate();
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.updateWidth = {
init: (element, fValueAccessor) => {
const
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
fInit = () => {
fValue($el.width());
window.setTimeout(() => {
fValue($el.width());
}, Magics.Time500ms);
2016-06-30 08:02:45 +08:00
};
2016-04-29 04:32:54 +08:00
$win.on('resize', fInit);
2016-06-30 08:02:45 +08:00
fInit();
2016-04-29 04:32:54 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$win.off('resize', fInit);
2016-06-30 08:02:45 +08:00
});
}
};
2016-04-29 04:32:54 +08:00
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.editor = {
init: (element, fValueAccessor) => {
2015-04-07 03:32:19 +08:00
let editor = null;
2015-04-17 01:55:13 +08:00
const
fValue = fValueAccessor(),
HtmlEditor = require('Common/HtmlEditor').default,
fUpdateEditorValue = () => {
2016-06-30 08:02:45 +08:00
if (fValue && fValue.__editor)
{
fValue.__editor.setHtmlOrPlain(fValue());
}
},
fUpdateKoValue = () => {
2016-06-30 08:02:45 +08:00
if (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
2016-06-30 08:02:45 +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
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.json = {
init: (element, fValueAccessor) => {
$(element).text(window.JSON.stringify(ko.unwrap(fValueAccessor())));
2016-06-30 08:02:45 +08:00
},
update: (element, fValueAccessor) => {
$(element).text(window.JSON.stringify(ko.unwrap(fValueAccessor())));
2016-06-30 08:02:45 +08:00
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.scrollerShadows = {
init: (element) => {
const
limit = 8,
$el = $(element),
cont = $el.find('[data-scroller-shadows-content]')[0] || null,
fFunc = _.throttle(() => {
$el
.toggleClass('scroller-shadow-top', limit < cont.scrollTop)
.toggleClass('scroller-shadow-bottom', cont.scrollTop + limit < cont.scrollHeight - cont.clientHeight);
2016-06-30 08:02:45 +08:00
}, 100);
if (cont)
2016-06-30 08:02:45 +08:00
{
$(cont).on('scroll resize', fFunc);
2016-06-30 08:02:45 +08:00
$win.on('resize', fFunc);
2016-06-24 05:57:35 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(cont, () => {
$(cont).off();
2016-06-30 08:02:45 +08:00
$win.off('resize', fFunc);
});
2016-06-24 05:57:35 +08:00
}
2016-06-30 08:02:45 +08:00
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.pikaday = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext) => {
ko.bindingHandlers.textInput.init(element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext);
2015-04-14 02:45:09 +08:00
2016-06-30 08:02:45 +08:00
if (Pikaday)
{
element.__pikaday = new Pikaday({
field: element
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
ko.bindingHandlers.visibleAnimated = {
init: (element, fValueAccessor) => {
const $el = $(element);
2016-09-03 07:51:17 +08:00
$el.addClass('rl-animated-inited');
if (ko.unwrap(fValueAccessor())) {
$el.show();
} else {
$el.hide();
}
},
update: (element, fValueAccessor) => {
const $el = $(element);
if (ko.unwrap(fValueAccessor())) {
$el.addClass('rl-animated-hidden').show();
_.delay(() => {
$el.removeClass('rl-animated-hidden');
}, 10);
} else {
$el.hide().removeClass('rl-animated-hidden');
}
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.tooltip = {
init: (element, fValueAccessor) => {
2014-08-20 23:03:12 +08:00
const
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
isMobile = 'on' === ($el.data('tooltip-mobile') || 'off'),
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals');
if (!Globals.bMobileDevice || isMobile)
2016-06-30 08:02:45 +08:00
{
const sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
2014-08-20 23:03:12 +08:00
element.__opentip = new Opentip(element, {
2016-06-30 08:02:45 +08:00
'style': 'rainloopTip',
'element': element,
'tipJoint': $el.data('tooltip-join') || 'bottom'
2014-08-20 23:03:12 +08:00
});
Globals.dropdownVisibility.subscribe((v) => {
if (v) {
element.__opentip.hide();
}
2014-08-20 23:03:12 +08:00
});
2014-10-04 19:58:01 +08:00
2016-06-30 08:02:45 +08:00
if ('' === sValue)
2014-08-20 23:03:12 +08:00
{
element.__opentip.hide();
element.__opentip.deactivate();
element.__opentip.setContent('');
2016-06-30 08:02:45 +08:00
}
else
{
element.__opentip.activate();
2014-08-20 23:03:12 +08:00
}
if ('on' === ($el.data('tooltip-i18n') || 'on'))
2014-10-04 19:58:01 +08:00
{
const Translator = require('Common/Translator');
2015-03-21 06:22:06 +08:00
element.__opentip.setContent(Translator.i18n(sValue));
2016-06-30 08:02:45 +08:00
Translator.trigger.subscribe(() => {
element.__opentip.setContent(Translator.i18n(sValue));
2015-03-16 05:58:50 +08:00
});
Globals.dropdownVisibility.subscribe(() => {
if (element && element.__opentip)
2016-06-30 08:02:45 +08:00
{
element.__opentip.setContent(Translator.i18n(sValue));
2016-06-30 08:02:45 +08:00
}
});
2014-10-04 19:58:01 +08:00
}
2016-06-30 08:02:45 +08:00
else
2014-08-20 23:03:12 +08:00
{
element.__opentip.setContent(sValue);
2016-06-30 08:02:45 +08:00
}
}
},
update: (element, fValueAccessor) => {
2014-08-20 23:03:12 +08:00
const
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
isMobile = 'on' === ($el.data('tooltip-mobile') || 'off'),
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals');
if ((!Globals.bMobileDevice || isMobile) && element.__opentip)
2016-06-30 08:02:45 +08:00
{
const sValue = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue);
2016-06-30 08:02:45 +08:00
if (sValue)
{
element.__opentip.setContent('on' === ($el.data('tooltip-i18n') || 'on') ?
require('Common/Translator').i18n(sValue) : sValue);
element.__opentip.activate();
2016-06-30 08:02:45 +08:00
}
else
{
element.__opentip.hide();
element.__opentip.deactivate();
element.__opentip.setContent('');
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: function(element) {
2014-08-20 23:03:12 +08:00
const $el = $(element);
2014-10-04 19:58:01 +08:00
element.__opentip = new Opentip(element, {
style: 'rainloopErrorTip',
hideOn: 'mouseout click',
element: element,
tipJoint: $el.data('tooltip-join') || 'top'
2016-06-30 08:02:45 +08:00
});
2014-08-20 23:03:12 +08:00
element.__opentip.deactivate();
2016-06-30 08:02:45 +08:00
$(window.document).on('click', () => {
if (element && element.__opentip)
2014-08-20 23:03:12 +08:00
{
element.__opentip.hide();
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
});
fDisposalTooltipHelper(element);
2016-06-30 08:02:45 +08:00
},
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
const
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
value = !ko.isObservable(fValue) && _.isFunction(fValue) ? fValue() : ko.unwrap(fValue),
openTips = element.__opentip;
2016-06-30 08:02:45 +08:00
if (openTips)
2016-06-30 08:02:45 +08:00
{
if ('' === value)
2014-08-20 23:03:12 +08:00
{
openTips.hide();
openTips.deactivate();
openTips.setContent('');
2014-08-20 23:03:12 +08:00
}
else
{
_.delay(() => {
if ($el.is(':visible'))
2016-06-30 08:02:45 +08:00
{
openTips.setContent(value);
openTips.activate();
openTips.show();
2016-06-30 08:02:45 +08:00
}
else
{
openTips.hide();
openTips.deactivate();
openTips.setContent('');
2016-06-30 08:02:45 +08:00
}
}, Magics.Time100ms);
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');
2016-06-30 08:02:45 +08:00
if (Globals && Globals.data.aBootstrapDropdowns)
{
Globals.data.aBootstrapDropdowns.push($(element));
2014-08-20 23:03:12 +08:00
$(element).click(() => {
2016-06-30 08:02:45 +08:00
require('Common/Utils').detectDropdownVisibility();
});
// ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
// });
}
2016-06-30 08:02:45 +08:00
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.openDropdownTrigger = {
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
if (ko.unwrap(fValueAccessor()))
{
const $el = $(element);
if (!$el.hasClass('open'))
2016-06-30 08:02:45 +08:00
{
$el.find('.dropdown-toggle').dropdown('toggle');
2016-06-30 08:02:45 +08:00
}
2014-10-04 19:58:01 +08:00
$el.find('.dropdown-toggle').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: function(element, fValueAccessor) {
$(element).popover(ko.unwrap(fValueAccessor()));
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).popover('destroy');
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.csstext = {};
ko.bindingHandlers.csstext.init = ko.bindingHandlers.csstext.update = (element, fValueAccessor) => {
if (element && element.styleSheet && 'undefined' !== typeof element.styleSheet.cssText)
2016-06-30 08:02:45 +08:00
{
element.styleSheet.cssText = ko.unwrap(fValueAccessor());
2016-06-30 08:02:45 +08:00
}
else
{
$(element).text(ko.unwrap(fValueAccessor()));
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.resizecrop = {
init: (element) => {
$(element).addClass('resizecrop').resizecrop({
2016-06-30 08:02:45 +08:00
'width': '100',
'height': '100',
'wrapperCSS': {
'border-radius': '10px'
}
});
},
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
fValueAccessor()();
$(element).resizecrop({
2016-06-30 08:02:45 +08:00
'width': '100',
'height': '100'
});
}
};
2014-08-20 23:03:12 +08:00
2016-08-22 05:30:34 +08:00
ko.bindingHandlers.onKeyDown = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
$(element).on('keydown.koOnKeyDown', (event) => {
if (event)
{
return fValueAccessor().call(viewModel, event);
}
return true;
});
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).off('keydown.koOnKeyDown');
});
}
};
2016-06-30 08:02:45 +08:00
ko.bindingHandlers.onEnter = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
$(element).on('keypress.koOnEnter', (event) => {
if (event && 13 === window.parseInt(event.keyCode, 10))
2014-08-20 23:03:12 +08:00
{
$(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 === window.parseInt(event.keyCode, 10))
2016-06-30 08:02:45 +08:00
{
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.onTab = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
$(element).on('keydown.koOnTab', (event) => {
if (event && 9 === window.parseInt(event.keyCode, 10))
2016-06-30 08:02:45 +08:00
{
return fValueAccessor().call(viewModel, !!event.shiftKey);
2016-06-30 08:02:45 +08:00
}
2016-07-01 06:50:11 +08:00
return true;
2016-06-30 08:02:45 +08:00
});
2015-02-15 08:30:21 +08:00
ko.utils.domNodeDisposal.addDisposeCallback(element, () => {
$(element).off('keydown.koOnTab');
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 === window.parseInt(event.keyCode, 10))
2015-02-15 08:30:21 +08:00
{
$(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.clickOnTrue = {
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
if (ko.unwrap(fValueAccessor()))
{
$(element).click();
2015-03-07 08:32:06 +08:00
}
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) => {
2014-08-20 23:03:12 +08:00
const
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals'),
Utils = require('Common/Utils');
$(element)
.toggleClass('fade', !Globals.bMobileDevice)
.modal({
'keyboard': false,
'show': ko.unwrap(fValueAccessor())
})
.on('shown.koModal', Utils.windowResizeCallback)
.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) => {
2014-08-20 23:03:12 +08:00
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
2016-06-30 08:02:45 +08:00
if (Globals.$html.hasClass('rl-anim'))
{
Globals.$html.addClass('rl-modal-animation');
_.delay(() => {
2016-06-30 08:02:45 +08:00
Globals.$html.removeClass('rl-modal-animation');
}, Magics.Time500ms);
2014-08-20 23:03:12 +08:00
}
2015-01-09 07:31:31 +08:00
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.moment = {
init: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
require('Common/Momentor').momentToNode(
$(element).addClass('moment').data('moment-time', ko.unwrap(fValueAccessor()))
2016-06-30 08:02:45 +08:00
);
},
update: (element, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
require('Common/Momentor').momentToNode(
$(element).data('moment-time', ko.unwrap(fValueAccessor()))
2016-06-30 08:02:45 +08:00
);
}
};
ko.bindingHandlers.i18nInit = {
init: (element) => {
require('Common/Translator').i18nToNodes(element);
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.translatorInit = {
init: (element) => {
require('Common/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());
require('Common/Translator').i18nToNodes(element);
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.link = {
update: function(element, fValueAccessor) {
$(element).attr('href', ko.unwrap(fValueAccessor()));
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.title = {
update: function(element, fValueAccessor) {
$(element).attr('title', ko.unwrap(fValueAccessor()));
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.textF = {
init: function(element, fValueAccessor) {
$(element).text(ko.unwrap(fValueAccessor()));
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.initDom = {
init: function(element, fValueAccessor) {
fValueAccessor()(element);
2016-06-30 08:02:45 +08:00
}
};
ko.bindingHandlers.initFixedTrigger = {
init: (element, fValueAccessor) => {
const
values = ko.unwrap(fValueAccessor()),
$el = $(element),
top = values[1] || 0;
let $container = $(values[0] || null);
$container = $container[0] ? $container : null;
if ($container)
2016-06-30 08:02:45 +08:00
{
$win.resize(() => {
const offset = $container.offset();
if (offset && offset.top)
2014-08-20 23:03:12 +08:00
{
$el.css('top', offset.top + top);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
});
}
}
};
ko.bindingHandlers.initResizeTrigger = {
init: (element, fValueAccessor) => {
const values = ko.unwrap(fValueAccessor());
$(element).css({
'height': values[1],
'min-height': values[1]
2016-06-30 08:02:45 +08:00
});
},
update: (oElement, fValueAccessor) => {
2016-06-30 08:02:45 +08:00
const
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils'),
Globals = require('Common/Globals'),
values = ko.unwrap(fValueAccessor());
2014-08-20 23:03:12 +08:00
let
value = Utils.pInt(values[1]),
size = 0,
offset = $(oElement).offset().top;
if (0 < offset)
2016-06-30 08:02:45 +08:00
{
offset += Utils.pInt(values[2]);
size = Globals.$win.height() - offset;
2016-06-30 08:02:45 +08:00
if (value < size)
2016-06-30 08:02:45 +08:00
{
value = size;
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
$(oElement).css({
'height': value,
'min-height': value
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.appendDom = {
update: (element, fValueAccessor) => {
$(element).hide().empty().append(ko.unwrap(fValueAccessor())).show();
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.draggable = {
init: (element, fValueAccessor, fAllBindingsAccessor) => {
2016-06-30 08:02:45 +08:00
const
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals'),
Utils = require('Common/Utils');
2014-10-04 19:58:01 +08:00
2016-06-30 08:02:45 +08:00
if (!Globals.bMobileDevice)
{
const
triggerZone = 100,
scrollSpeed = 3,
2016-06-30 08:02:45 +08:00
fAllValueFunc = fAllBindingsAccessor(),
droppableSelector = fAllValueFunc && fAllValueFunc.droppableSelector ? fAllValueFunc.droppableSelector : '',
conf = {
2016-06-30 08:02:45 +08:00
distance: 20,
handle: '.dragHandle',
cursorAt: {top: 22, left: 3},
refreshPositions: true,
scroll: true
};
2014-10-04 19:58:01 +08:00
if (droppableSelector)
2014-08-20 23:03:12 +08:00
{
conf.drag = (event) => {
2014-08-20 23:03:12 +08:00
$(droppableSelector).each(function() {
const
$this = $(this), // eslint-disable-line no-invalid-this
offset = $this.offset(),
bottomPos = offset.top + $this.height();
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
window.clearInterval($this.data('timerScroll'));
$this.data('timerScroll', false);
2014-08-20 23:03:12 +08:00
if (event.pageX >= offset.left && event.pageX <= offset.left + $this.width())
2016-06-30 08:02:45 +08:00
{
if (event.pageY >= bottomPos - triggerZone && event.pageY <= bottomPos)
2014-08-20 23:03:12 +08:00
{
const moveUp = () => {
$this.scrollTop($this.scrollTop() + scrollSpeed);
2016-06-30 08:02:45 +08:00
Utils.windowResize();
};
$this.data('timerScroll', window.setInterval(moveUp, 10));
moveUp();
2014-08-20 23:03:12 +08:00
}
if (event.pageY >= offset.top && event.pageY <= offset.top + triggerZone)
2016-06-30 08:02:45 +08:00
{
const moveDown = () => {
$this.scrollTop($this.scrollTop() - scrollSpeed);
2016-06-30 08:02:45 +08:00
Utils.windowResize();
};
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
$this.data('timerScroll', window.setInterval(moveDown, 10));
moveDown();
}
}
});
2014-08-20 23:03:12 +08:00
};
conf.stop = () => {
$(droppableSelector).each(function() {
const $this = $(this); // eslint-disable-line no-invalid-this
window.clearInterval($this.data('timerScroll'));
$this.data('timerScroll', false);
2016-06-30 08:02:45 +08:00
});
};
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
$(element).draggable(conf).on('mousedown.koDraggable', () => {
2016-06-30 08:02:45 +08:00
Utils.removeInFocus();
});
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');
2016-06-30 08:02:45 +08:00
if (!Globals.bMobileDevice)
{
const
2016-06-30 08:02:45 +08:00
fValueFunc = fValueAccessor(),
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',
hoverClass: 'droppableHover'
};
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
if (fValueFunc)
2014-08-20 23:03:12 +08:00
{
conf.drop = (event, ui) => {
fValueFunc(event, ui);
2016-06-30 08:02:45 +08:00
};
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
if (fOverCallback)
2014-08-20 23:03:12 +08:00
{
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
2016-06-30 08:02:45 +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.nano = {
init: (element) => {
2016-06-09 02:07:16 +08:00
const
2016-06-30 08:02:45 +08:00
Globals = require('Common/Globals'),
Settings = require('Storage/Settings');
2016-06-09 02:07:16 +08:00
2016-06-30 08:02:45 +08:00
if (!Globals.bDisableNanoScroll && !Settings.appSettingsGet('useNativeScrollbars'))
{
$(element)
2016-06-30 08:02:45 +08:00
.addClass('nano')
.nanoScroller({
iOSNativeScrolling: false,
preventPageScrolling: true
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) => {
2014-08-20 23:03:12 +08:00
const $el = $(element);
2014-08-20 23:03:12 +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
if ('custom' === $el.data('save-trigger-type'))
2016-06-30 08:02:45 +08:00
{
$el.append(
2016-06-30 08:02:45 +08:00
'&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) => {
const
value = ko.unwrap(fValueAccessor()),
$el = $(element);
2014-08-20 23:03:12 +08:00
if ('custom' === $el.data('save-trigger-type'))
2016-06-30 08:02:45 +08:00
{
switch (value.toString())
2014-08-20 23:03:12 +08:00
{
2016-06-30 08:02:45 +08:00
case '1':
$el
2016-06-30 08:02:45 +08:00
.find('.animated,.error').hide().removeClass('visible')
.end()
.find('.success').show().addClass('visible');
break;
case '0':
$el
2016-06-30 08:02:45 +08:00
.find('.animated,.success').hide().removeClass('visible')
.end()
.find('.error').show().addClass('visible');
break;
case '-2':
$el
2016-06-30 08:02:45 +08:00
.find('.error,.success').hide().removeClass('visible')
.end()
.find('.animated').show().addClass('visible');
break;
default:
$el
2016-06-30 08:02:45 +08:00
.find('.animated').hide()
.end()
.find('.error,.success').removeClass('visible');
break;
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
}
else
{
switch (value.toString())
2014-08-20 23:03:12 +08:00
{
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) => {
2014-08-25 15:10:51 +08:00
const
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils'),
2016-07-07 05:03:30 +08:00
EmailModel = require('Model/Email').default,
2016-06-30 08:02:45 +08:00
$el = $(element),
2016-06-30 08:02:45 +08:00
fValue = fValueAccessor(),
fAllBindings = fAllBindingsAccessor(),
fAutoCompleteSource = fAllBindings.autoCompleteSource || null,
fFocusCallback = (value) => {
2016-06-30 08:02:45 +08:00
if (fValue && fValue.focused)
{
fValue.focused(!!value);
2014-08-20 23:03:12 +08:00
}
2016-06-30 08:02:45 +08:00
};
$el.inputosaurus({
parseOnBlur: true,
allowDragAndDrop: true,
focusCallback: fFocusCallback,
inputDelimiters: [',', ';', '\n'],
autoCompleteSource: fAutoCompleteSource,
// elementHook: (el, item) => {
// if (el && item)
// {
// el.addClass('pgp');
// }
// },
parseHook: (input) => _.map(input, (inputValue) => {
const value = Utils.trim(inputValue);
if ('' !== value)
{
const email = new EmailModel();
email.mailsoParse(value);
return [email.toLine(false), email];
}
return [value, null];
2015-06-05 02:02:31 +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
2016-06-30 08:02:45 +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) => {
2014-08-20 23:03:12 +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
if ($oEl.data('EmailsTagsValue') !== value)
2016-06-30 08:02:45 +08:00
{
$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
jqElement = $(element),
command = fValueAccessor();
if (!command || !command.isCommand)
{
throw new Error('Value should be a command');
}
if (!command.enabled)
{
command.enabled = ko.observable(true);
}
2014-08-20 23:03:12 +08:00
if (!command.canExecute)
2016-06-30 08:02:45 +08:00
{
const __realCanExecute = command.__realCanExecute;
if (_.isFunction(__realCanExecute))
{
command.canExecute = ko.computed(() => command.enabled() && __realCanExecute.call(viewModel, viewModel));
}
else
{
command.canExecute = ko.computed(() => command.enabled() && !!__realCanExecute);
}
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
jqElement.addClass('command');
ko.bindingHandlers[jqElement.is('form') ? 'submit' : 'click']
.init(element, fValueAccessor, fAllBindingsAccessor, viewModel, bindingContext);
2016-06-30 08:02:45 +08:00
},
update: (element, fValueAccessor) => {
const
jqElement = $(element),
command = fValueAccessor();
2014-08-20 23:03:12 +08:00
let result = command.enabled();
2014-08-20 23:03:12 +08:00
jqElement.toggleClass('command-not-enabled', !result);
2014-08-20 23:03:12 +08:00
if (result)
2016-06-30 08:02:45 +08:00
{
result = command.canExecute();
jqElement.toggleClass('command-can-not-be-execute', !result);
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
jqElement.toggleClass('command-disabled disable disabled', !result).toggleClass('no-disabled', !!result);
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
if (jqElement.is('input') || jqElement.is('button'))
{
jqElement.prop('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.trimmer = (target) => {
const
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils'),
result = ko.computed({
read: target,
write: (newValue) => {
target(Utils.trim(newValue.toString()));
}
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
};
2014-08-20 23:03:12 +08:00
ko.extenders.posInterer = (target, defaultVal) => {
const
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils'),
result = ko.computed({
read: target,
write: (newValue) => {
let val = Utils.pInt(newValue.toString(), defaultVal);
if (0 >= val)
2016-06-30 08:02:45 +08:00
{
val = defaultVal;
2016-06-30 08:02:45 +08:00
}
2014-08-20 23:03:12 +08:00
if (val === target() && '' + val !== '' + newValue)
2016-06-30 08:02:45 +08:00
{
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
2016-06-30 08:02:45 +08:00
Utils = require('Common/Utils'),
result = ko.computed({
read: target,
write: (newValue) => {
2016-06-30 08:02:45 +08:00
const
currentValue = ko.unwrap(target),
list = ko.unwrap(limitedList);
if (Utils.isNonEmptyArray(list))
2016-06-30 08:02:45 +08:00
{
if (-1 < Utils.inArray(newValue, list))
{
target(newValue);
2016-06-30 08:02:45 +08:00
}
else if (-1 < Utils.inArray(currentValue, list))
2016-06-30 08:02:45 +08:00
{
target(currentValue + ' ');
target(currentValue);
}
else
{
target(list[0] + ' ');
target(list[0]);
}
}
2016-06-30 08:02:45 +08:00
else
{
target('');
2016-06-30 08:02:45 +08:00
}
}
}).extend({notify: 'always'});
result(target());
if (!result.valueHasMutated)
2014-08-20 23:03:12 +08:00
{
result.valueHasMutated = () => {
target.valueHasMutated();
2014-08-20 23:03:12 +08:00
};
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) => {
2014-08-20 23:03:12 +08:00
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);
2016-06-30 08:02:45 +08:00
};
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) => {
2016-06-30 08:02:45 +08:00
const prop = options[1];
if (prop)
2014-08-20 23:03:12 +08:00
{
target.subscribe((prev) => {
if (prev && prev[prop])
2014-08-20 23:03:12 +08:00
{
prev[prop](false);
2014-08-20 23:03:12 +08:00
}
}, options[0], 'beforeChange');
2014-08-20 23:03:12 +08:00
target.subscribe((next) => {
if (next && next[prop])
2016-06-30 08:02:45 +08:00
{
next[prop](true);
2016-06-30 08:02:45 +08:00
}
}, 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) => {
if (value)
2015-03-31 08:12:05 +08:00
{
window.clearTimeout(target.iFalseTimeoutTimeout);
target.iFalseTimeoutTimeout = window.setTimeout(() => {
target(false);
target.iFalseTimeoutTimeout = 0;
}, require('Common/Utils').pInt(option));
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);
if (0 < target.iSpecialThrottleTimeoutValue)
2016-06-30 08:02:45 +08:00
{
target.iSpecialThrottleTimeout = 0;
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) => {
2015-03-31 08:12:05 +08:00
2016-06-30 08:02:45 +08:00
if (bValue)
{
target.valueForRead(bValue);
2016-06-30 08:02:45 +08:00
}
else
{
if (target.valueForRead())
2015-03-31 08:12:05 +08:00
{
window.clearTimeout(target.iSpecialThrottleTimeout);
target.iSpecialThrottleTimeout = window.setTimeout(() => {
target.valueForRead(false);
target.iSpecialThrottleTimeout = 0;
}, target.iSpecialThrottleTimeoutValue);
2015-03-31 08:12:05 +08:00
}
else
{
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() {
2016-07-16 05:29:42 +08:00
return this.extend({'idleTrigger': true});
};
ko.observable.fn.validateNone = function() {
2016-06-30 08:02:45 +08:00
this.hasError = ko.observable(false);
return this;
};
2014-08-20 23:03:12 +08:00
ko.observable.fn.validateEmail = function() {
2014-08-25 15:10:51 +08:00
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() {
2014-08-22 23:08:56 +08:00
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() {
2016-08-24 06:17:50 +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
ko.observable.fn.validateFunc = function(fFunc) {
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
this.hasFuncError = ko.observable(false);
2014-08-20 23:03:12 +08:00
if (_.isFunction(fFunc))
2016-06-30 08:02:45 +08:00
{
this.subscribe((value) => {
this.hasFuncError(!fFunc(value));
});
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
this.valueHasMutated();
}
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
return this;
};
2014-08-20 23:03:12 +08:00
2016-06-30 08:02:45 +08:00
module.exports = ko;