iobroker.vis-2
Version:
Next generation graphical user interface for ioBroker.
1,094 lines (1,017 loc) • 146 kB
HTML
<link
rel="stylesheet"
type="text/css"
href="widgets/basic/css/table.css"
/>
<script
type="text/javascript"
src="widgets/basic/js/table.js"
></script>
<script type="text/javascript">
'use strict';
if (vis.editMode) {
// Add words for basic widgets
$.extend(true, systemDictionary, {
// Bars
src: { en: 'Source', de: 'Quelle', ru: 'Адрес' },
refreshInterval: { en: 'Refresh interval(ms)', de: 'Updatezeit(ms)', ru: 'Интервал обновления(ms)' },
is_comma: { en: 'Divider comma', de: 'Komme als Trennung', ru: 'Запятая-разделитель' },
is_tdp: { en: 'Use thousands separator', de: 'Tausender Trennzeichen', ru: 'Use thousands separator' },
digits: { en: 'Digits after comma', de: 'Zeichen nach Komma', ru: 'Знаков после запятой' },
oid: { en: 'Object ID', de: 'Object ID', ru: 'ID Объекта' },
html_prepend: { en: 'Prepend value', de: 'Voranstellen HTML', ru: 'Префикс значения' },
html_append: { en: 'Append to value', de: 'HTML anhängen', ru: 'Суффикс значения' },
html_append_singular: {
en: 'Append to value (Singular)',
de: 'HTML anhängen (Singulär)',
ru: 'Суффикс значения(един.ч.)',
},
html_append_plural: {
en: 'Append to value (Plural)',
de: 'HTML anhängen(Plüral)',
ru: 'Суффикс значения(множ.ч.)',
},
html_prepend_tooltip: {
en: 'Write HTML code here that will be placed before,\x0Ae.g. <b> ',
de: 'HTML Kod, der wird vom dem Wert platziert,\x0Az.B. <b>',
ru: 'HTML код будет помещён перед значением,\x0Aнапример <b>',
},
html_append_tooltip: {
en: 'Write HTML code here that will be placed before,\x0Ae.g. </b>',
de: 'HTML Kod, der wird vom dem Wert platziert,\x0Az.B. </b>',
ru: 'HTML код будет помещён после значения,\x0Aнапример </b>',
},
stretch: { en: 'Stretch', de: 'Strecken', ru: 'Растянуть' },
factor: { en: 'Multiplex factor', de: 'Multiplikation', ru: 'Множитеть' },
class_true: {
en: "Class if quality 'true'",
de: "Klasse bei Qualität 'true'",
ru: "Класс, если качество 'true'",
},
class_false: {
en: "Class if quality 'false'",
de: "Klasse bei Qualität 'false'",
ru: "Класс, если качество 'false'",
},
test_html: { en: 'Text for test', de: 'Testtext', ru: 'Тестовый текст' },
test_html_tooltip: {
en: 'You can specify the test text if value is now empty to visualise settings.\x0AIt is valid only during edit.',
de: 'Man kann noch Testtext setzen um die Einstellungen visuell zu sehen.\x0ADas ist nur während Edit gültig.',
ru: 'Можно задать тестовый текст, что бы видеть настройки визуально.\x0AОн действителен только во время редактирования.',
},
html: { en: 'HTML', de: 'HTML', ru: 'HTML' },
'oid-quality': { en: 'Quality ID', de: 'Qualität ID', ru: 'ID-Качество' },
'oid-quality_tooltip': {
en: 'You can set additionally Quality ID to indicate if the value valid or not.',
de: 'Man kann noch zusätzlich Qualität ID setzetn um zu zeigen ob das Wert aktuell ist.',
ru: 'Можно дополнительно установить ID-Качества, что бы показать актуальное значение или нет.',
},
title: { en: 'Title', de: 'Titel', ru: 'Заголовок' },
title_font: { en: 'Title font name', de: 'Titelschriftname', ru: 'Шрифт заголовка' },
title_color: { en: 'Title color', de: 'Titelfarbe', ru: 'Цвет заголовка' },
title_back: { en: 'Title backg. color', de: 'Titelhintergrund', ru: 'Цвет фона текста' },
title_top: { en: 'Title top padding', de: 'Titel-Oben-Abstand', ru: 'Отступ заголовка сверху' },
title_left: { en: 'Title left padding', de: 'Titel-Links-Abstand', ru: 'Отступ заголовка слева' },
header_height: { en: 'Header height', de: 'Kopfhöhe', ru: 'Высота заголовока' },
header_color: { en: 'Header color', de: 'Kopffarbe', ru: 'Цвет фона заголовка' },
refreshOnWakeUp: {
en: 'Refresh on wake up',
de: 'Update bei Aufwachen',
ru: 'Обновлять при выходе из сна',
},
refreshOnViewChange: {
en: 'Refresh on view change',
de: 'Update bei Viewwechsel',
ru: 'Обновлять при смене страницы',
},
refreshWithNoQuery: {
en: 'Do not add anything to URL',
de: 'Addiere nichst zu URL',
ru: 'Ничего не добавлять к URL',
},
src_: { en: 'URL, by value=', de: 'URL falls Wert=', ru: 'Адрес при значении ' },
nav_view: { en: 'View to navigate', de: 'View zum Navigieren', ru: 'Перейти на страницу' },
group_effects: { en: 'Show/Hide Effects', de: 'Anzeige Effekte', ru: 'Эффекты появления/исчезновения' },
group_extended: { en: 'Extended settings', de: 'Erweiterte Eistellungen', ru: 'Расширенные настройки' },
'body-background': {
en: 'Background color by changing',
de: 'Hintegrund by Wechsel',
ru: 'Фон при смене страниц',
},
sync: {
en: 'Hide and show together:',
de: 'Anzeigen und verbergen gleichzeitig',
ru: 'Появления и исчезновение вместе',
},
// Effects
show: { en: 'show', de: 'show', ru: 'show' },
blind: { en: 'blind', de: 'blind', ru: 'blind' },
bounce: { en: 'bounce', de: 'bounce', ru: 'bounce' },
clip: { en: 'clip', de: 'clip', ru: 'clip' },
drop: { en: 'drop', de: 'drop', ru: 'drop' },
explode: { en: 'explode', de: 'explode', ru: 'explode' },
fade: { en: 'fade', de: 'fade', ru: 'fade' },
fold: { en: 'fold', de: 'fold', ru: 'fold' },
highlight: { en: 'highlight', de: 'highlight', ru: 'highlight' },
puff: { en: 'puff', de: 'puff', ru: 'puff' },
pulsate: { en: 'pulsate', de: 'pulsate', ru: 'pulsate' },
scale: { en: 'scale', de: 'scale', ru: 'scale' },
shake: { en: 'shake', de: 'shake', ru: 'shake' },
size: { en: 'size', de: 'size', ru: 'size' },
slide: { en: 'slide', de: 'slide', ru: 'slide' },
is_milliseconds: { en: 'Milliseconds', de: 'Millisekunden', ru: 'Миллисекунды' },
is_milliseconds_tooltip: {
en: 'Is object is milliseconds from 1970.01.01 00:00:00. Normally no.',
de: 'Ob das Wert die Milleskunden seit 1970.01.01 00:00:00 ist. Normalerweise nicht.',
ru: 'Является ли значение объекта миллисекундами с 1970.01.01 00:00:00. Обычно нет.',
},
format_date: { en: 'Dateformat', de: 'Datumformat', ru: 'Формат даты' },
format_date_tooltip: {
en: 'Dateformat',
de: 'Datumformat',
ru: 'Формат даты',
},
show_interval: { en: 'As interval', de: 'Als Intervall', ru: 'Как интервал' },
hide_effect: { en: 'Hide effect', de: 'Verbergeneffekt', ru: 'Эффект скрытия' },
hide_duration: { en: 'Hide duration(ms)', de: 'Verbergendauer', ru: 'Длительность скрытия(мс)' },
hide_options: { en: 'Hide options', de: 'Verbergenoptionen', ru: 'Опции скрытия' },
show_effect: { en: 'Show effect', de: 'Anzeigeeffekt', ru: 'Эффект появления' },
show_duration: { en: 'Show duration(ms)', de: 'Anzeigedauer', ru: 'Длительность появления(мс)' },
show_options: { en: 'Show options', de: 'Anzeigeoptionen', ru: 'Опции появления' },
left: { en: 'left', de: 'links', ru: 'лево' },
right: { en: 'right', de: 'rechts', ru: 'право' },
top: { en: 'top', de: 'oben', ru: 'верх' },
bottom: { en: 'bottom', de: 'unten', ru: 'низ' },
contains_view: { en: 'Contains view', de: 'Viewname', ru: 'Имя страницы' },
persistent: { en: 'Persistent', de: 'Bleibend', ru: 'Постоянно' },
persistent_tooltip: {
en: 'If persistent the view will not be destroyed when inactive, just hide.\nElsewise the view will be destroyed, if inactive.',
de: "Falls 'Bleibend', dann wird die View nicht zerstört, sondern nur versteckt wenn inaktive. Sonst wird die View immer wieder kreiert und zerstört.",
ru: "Если выбранно 'Постоянно', то страница не будет уничтожаться, если она не активна. В противном случае страница будет создаваться и разрушаться.",
},
notIfInvisible: { en: 'Only if visible', de: 'Nur falls sichtbar', ru: 'Только если видимо' },
notIfInvisible_tooltip: {
en: 'View will be used only if this widget is visible',
de: 'Die View wird nur benutzt, wenn dieses Widget sichtbar ist',
ru: 'Страница будет использоваться только в том случае, если виден этот виджет',
},
valuelist: { en: 'Values list', de: 'Wertenliste', ru: 'Список значений' },
valuelist_tooltip: {
en: "Divide values with semicolon, like 'ok;warning;alram'. Every text accordingly for value 0,1,2 and so on\nTo have ';' in text use §§ instead.",
de: "Die Werte mit Semikolon trennen, wie 'ok;Warnung;Alarm'. Jeder Text ist entsprechend für das Wert 0,1,2 usw.\nUm ';' im Text zu haben, schrein '§§'.",
ru: "Разделять значения точкой запятой, например 'ok;Внимание;Тревога'. Каждый текст соответственно для значения 0,1,2 итд.\nДля написания ';' в тексте используй '§§'.",
},
html_false: { en: "HTML by 'false'", de: "HTML bei 'false'", ru: 'HTML если 0' },
html_true: { en: "HTML by 'true'", de: "HTML bei 'true'", ru: 'HTML если 1' },
text_false: { en: "Text by 'false'", de: "Text bei 'false'", ru: 'Текст если 0' },
text_true: { en: "Text by 'true'", de: "Text bei 'true'", ru: 'Текст если 1' },
svg_false: { en: "SVG by 'false'", de: "SVG bei 'false'", ru: 'SVG если 0' },
svg_true: { en: "SVG by 'true'", de: "SVG bei 'true'", ru: 'SVG если 1' },
svg_opacity: { en: 'Opacity', de: 'Durchsichtigkeit', ru: 'Прозрачность' },
html_closed: { en: "HTML by 'closed'", de: "HTML bei 'zu'", ru: 'HTML если закрыто' },
html_open: { en: "HTML by 'open'", de: "HTML bei 'auf'", ru: 'HTML если открыто' },
html_tilt: { en: "HTML by 'tilted'", de: "HTML bei 'gekippt'", ru: 'HTML если наклоненно' },
html_tilt_tooltip: {
en: '0 - Closed, 1 - tilt, 2 - open',
de: '0- Zu, 1 - gekippt, 2 - auf',
ru: '0 - закрыто, 1 - откинуто, 2 - открыто',
},
color: { en: 'Color', de: 'Farbe', ru: 'Цвет' },
shadow: { en: 'Opacity', de: 'Durchsichtigkeit', ru: 'Тень' },
shadow_tooltip: {
en: "CSS Shadow, like '10px 10px 5px #888888'",
de: "CSS Shatten, wie '10px 10px 5px #888888'",
ru: "CSS Тень, как '10px 10px 5px #888888'",
},
reverse: { en: 'Revers value', de: 'Wert umkehren', ru: 'Перевернуть значение' },
border: { en: 'Border', de: 'Rand', ru: 'Окантовка' },
border_tooltip: {
en: "CSS border, like 'green 5px solid'",
de: "CSS Rand, wie 'green 5px solid'",
ru: "CSS бордюр, как 'green 5px solid'",
},
test_text: { en: 'Test text', de: 'Testtext', ru: 'Тестовый текст' },
max_width: { en: 'Max. width', de: 'Maximale Breite', ru: 'Максимальная ширина' },
style: { en: 'Style for ', de: 'Stil für ', ru: 'Стиль для ' },
style_tooltip: {
en: "Write here css style, like: 'color:red;background:white'",
de: "Hier muss CSS Stil stehen, wie 'color:red;background:white'",
ru: "CSS Стиль, например: 'color:red;background:white'",
},
count: { en: 'Values number to', de: 'Werteanzahl bis', ru: 'Количество значений до' },
test_list: { en: 'Test value', de: 'Testwert', ru: 'Тестовое значение' },
urlValue: { en: 'Call URL on click', de: 'Rufe URL bei click', ru: 'Вызвать URL при нажатии' },
group_ccontrol: { en: 'Advanced control', de: 'Extrasteuerung', ru: 'Продвинутое управление' },
urlFalse: { en: 'URL on false', de: 'URL bei false', ru: 'URL при false' },
urlTrue: { en: 'URL on true', de: 'URL bei true', ru: 'URL при true' },
oidFalse: { en: 'Object ID on false', de: 'Objekt ID bei false', ru: 'ID объекта при false' },
oidTrue: { en: 'Object ID on true', de: 'Objekt ID bei true', ru: 'ID объекта при true' },
oidTrueValue: { en: 'Value for OÍD on true', de: 'Wert für ID bei false', ru: 'Значение для ID при false' },
oidFalseValue: { en: 'Value for OÍD on false', de: 'Wert für ID bei true', ru: 'Значение для ID при true' },
square: { en: 'square', de: 'square', ru: 'квадрат' },
pentagone: { en: 'pentagone', de: 'pentagone', ru: 'Пятиуголник' },
hexagone: { en: 'hexagone', de: 'hexagone', ru: 'Шестиугольник' },
octagone: { en: 'octagone', de: 'octagone', ru: 'Восьмиугольник' },
circle: { en: 'circle', de: 'Kreis', ru: 'Круг' },
svgType: { en: 'Type', de: 'Typ', ru: 'Тип' },
strokeColor: { en: 'Stroke color', de: 'Liniefarbe', ru: 'Цвет линии' },
fill: { en: 'Fill color', de: 'Füllfarbe', ru: 'Цвет заливки' },
strokeWidth: { en: 'Stroke width', de: 'Liniebreite', ru: 'Ширина линии' },
rotate: { en: 'Rotate', de: 'Drehen', ru: 'Повернуть на' },
no_control: { en: 'Read only', de: 'Nur Anzeige', ru: 'Только показывать' },
numeric: { en: 'Number', de: 'Nummer', ru: 'Число' },
autoSet: { en: 'Auto set', de: 'Auto-setzen', ru: 'Авто запись' },
autoSet_tooltip: {
en: "Without 'Auto set' you must press ENTER,\x0ato write the value.",
de: "Ohne 'Auto-setzen' man muss danach ENTER drucken,\x0A um das Wert zu schreiben.",
ru: "Без 'Авто записи' нужно нажать ENTER,\x0Aчто бы записать значение.",
},
group_views: { en: 'Views', de: 'Views', ru: 'Страницы' },
group_frames: { en: 'iFrames', de: 'iFrames', ru: 'iFrames' },
horizontal: { en: 'horizontal', de: 'horizontal', ru: 'горизонтально' },
vertical: { en: 'vertical', de: 'senkrecht', ru: 'вертикально' },
orientation: { en: 'Orientation', de: 'Ausrichtung ', ru: 'Направление' },
noSandbox: { en: 'No sandbox', de: 'Kein Sandkasten', ru: 'Не запускать в песочнице' },
scrollX: { en: 'Scroll X', de: 'Scroll X', ru: 'Scroll X' },
scrollY: { en: 'Scroll Y', de: 'Scroll Y', ru: 'Scroll Y' },
seamless: { en: 'Seamless', de: 'Kein Rahmen', ru: 'Без рамки' },
filters: { en: 'Filters', de: 'Filter', ru: 'Фильтры' },
filters_Tooltip: {
en: 'Divided by semicolon,\x0Ae.g: light;control',
de: 'Geteilt mir Semikolon\x0Az.B.: Licht;Steuerung',
ru: 'Разделять точкой запятой\x0Aнапример: Свет;Управление',
},
'Select ID': { en: 'Select ID', de: 'ID auswählen', ru: 'Выбрать ID' },
redirect_url: { en: 'Redirect URL', de: 'Weiterleiten nach Logout', ru: 'Перейти на URL после выхода' },
in_app_close: { en: 'Close mobile APP', de: 'Mobiles APP schliessen', ru: 'Закрыть мобильное приложение' },
line: { en: 'line', de: 'Linie', ru: 'линия' },
triangle: { en: 'triangle', de: 'Dreieck', ru: 'треугольник' },
star: { en: 'star', de: 'Stern', ru: 'звезда' },
arrow: { en: 'arrow', de: 'Pfeil', ru: 'стрела' },
scaleWidth: { en: 'Scale width', de: 'breiten Skala', ru: 'Масштаб по ширине' },
scaleHeight: { en: 'Scale height', de: 'höhen Skala', ru: 'Масштаб по высоте' },
autoFocus: {
en: 'Auto focus',
de: 'Autofokus',
ru: 'Автофокус',
pt: 'Auto-foco',
nl: 'Autofocus',
fr: 'Mise au point automatique',
it: 'Messa a fuoco automatica',
es: 'Enfoque automático',
pl: 'Automatyczne ustawianie ostrości',
'zh-cn': '自动对焦',
},
});
}
$.extend(true, systemDictionary, {
'Edit note': { en: 'Edit note', de: 'Meldung eingeben', ru: 'Сообщение' },
Clear: { en: 'Clear', de: 'Löschen', ru: 'Очистить' },
Ok: { en: 'Ok', de: 'Ok', ru: 'Ok' },
Cancel: { en: 'Cancel', de: 'Abbrechen', ru: 'Отмена' },
all: { en: 'all', de: 'Alle', ru: 'Все' },
'just now': { en: 'just now', de: 'gerade jetzt', ru: 'только что' },
'for %s min.': { en: 'for %s min.', de: 'vor %s Min.', ru: '%s мин. назад' },
'for %s hr. and %s min.': {
en: 'for %s hr. and %s min.',
de: 'vor %s St. und %s Min.',
ru: '%s часов и %s мин. назад',
},
yesterday: { en: 'yesterday', de: 'gestern', ru: 'вчера' },
'for %s hours': {
en: 'for %s hours',
de: 'vor %s Stunden',
ru: '%s часов назад',
},
'click to create': { en: 'click to create', de: 'klicken um zu erzeugen', ru: 'нажать что бы создать' },
'This option works only in APP': {
en: 'This option works only in APP',
de: 'Funktioniert nur im APP',
ru: 'Работает только в мобильном приложении',
},
});
/*vis.binds.stateful = {
view: function (el, viewArr, persistent, notIfInvisible) {
const $this = $(el);
const oid = $this.attr('data-oid');
let timer = null;
function draw(val) {
timer = null;
const view = viewArr[val];
if (!persistent) {
$this.parent().find('div.vis-view').remove();
} else {
$this.parent().find('div.vis-view').hide().appendTo($('#vis_container'));
}
if (vis.views[view]) {
vis.renderView(view, view, true, function (_view) {
const $view = $('#visview_' + _view);
$view.show().data('persistent', persistent);
if (!$this.find('#visview_' + _view).length) {
$view.appendTo($this);
}
});
}
vis.destroyUnusedViews();
}
function onChange(e, newVal) {
if (newVal === 'true' || newVal === true) newVal = 1;
if (newVal === 'false' || newVal === false) newVal = 0;
if (notIfInvisible && !$this.is(':visible')) {
return;
}
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function () {
draw(newVal);
}, 50);
}
if (oid) {
vis.states.bind(oid + '.val', onChange);
// remember all ids, that bound
$this.parent().parent()
.data('bound', [oid + '.val'])
// remember bind handler
.data('bindHandler', onChange);
}
},
iframe: function (el, srcArr, refreshInterval) {
const $this = $(el).parent().find('iframe');
const oid = $this.attr('data-oid');
refreshInterval = parseInt(refreshInterval, 10) || 0;
function onChange (e, newVal) {
if (newVal === 'true' || newVal === true) newVal = 1;
if (newVal === 'false' || newVal === false) newVal = 0;
$this.attr('src', srcArr[newVal]);
}
if (oid) {
vis.states.bind(oid + '.val', onChange);
// remember all ids, that bound
$this.parent().parent()
.data('bound', [oid + '.val'])
// remember bind handler
.data('bindHandler', onChange);
if (vis.states[oid + '.val'] !== undefined) {
let val = vis.states[oid + '.val'];
if (val === 'true' || val === true) val = 1;
if (val === 'false' || val === false) val = 0;
$this.attr('src', srcArr[val]);
}
if (refreshInterval > 0) {
setInterval(function () {
let val = vis.states[oid + '.val'] || 0;
if (val === 'true' || val === true) val = 1;
if (val === 'false' || val === false) val = 0;
const src = srcArr[val];
$this.attr('src', src + (src.match(/\?/) ? '&' : '?') + '_vis_refts=' + Date.now());
}, refreshInterval);
}
}
},
image: function (el, srcArr, refreshInterval) {
const $this = $(el).parent().find('img');
const oid = $this.attr('data-oid');
refreshInterval = parseInt(refreshInterval, 10) || 0;
function onChange (e, newVal) {
if (newVal === 'true' || newVal === true) newVal = 1;
if (newVal === 'false' || newVal === false) newVal = 0;
$this.attr('src', srcArr[newVal]);
}
if (oid) {
vis.states.bind(oid + '.val', onChange);
// remember all ids, that bound
$this.parent().parent()
.data('bound', [oid + '.val'])
// remember bind handler
.data('bindHandler', onChange);
if (vis.states[oid + '.val'] !== undefined) {
let val = vis.states[oid + '.val'];
if (val === 'true' || val === true) val = 1;
if (val === 'false' || val === false) val = 0;
$this.attr('src', srcArr[val]);
}
if (refreshInterval > 0) {
setInterval(function () {
let val = vis.states[oid + '.val'] || 0;
if (val === 'true' || val === true) val = 1;
if (val === 'false' || val === false) val = 0;
const src = srcArr[val];
if (src) $this.attr('src', src + ((src.indexOf('?') !== -1) ? '&' : '?') + '_vis_refts=' + Date.now());
}, refreshInterval);
}
}
},
value: function (values, oid) {
if (oid !== 'nothing_selected' && vis.states.attr(oid + '.val') !== undefined) {
let val = vis.states.attr(oid + '.val');
if (val === 'true' || val === true) val = 1;
if (val === 'false' || val === false) val = 0;
return values[val];
} else {
return values[0];
}
}
};*/
vis.binds.container = function (el, view) {
const $this = $(el);
if (vis.views[view]) {
vis.renderView(view, view, true, function (_view) {
$('#visview_' + _view)
.appendTo($this)
.show();
});
}
};
vis.binds.basic = {
isFullScreen: false,
/* filterDropdown: function (el, filters, hideEffect, hideDuration, showEffect, showDuration) {
const $this = $(el);
if (filters) {
filters = filters.split(';');
for (let i = 0; i < filters.length; i++) {
$this.find('select').append('<option value="' + filters[i] + '">' + filters[i] + '</option>');
}
}
if (vis.viewsActiveFilter[vis.activeView]) {
$this.find('select option[value="' + vis.viewsActiveFilter[vis.activeView] + '"]').attr('selected', true);
}
$this.find('select').change(function () {
vis.changeFilter(null, $this.find('select option:selected').val(), hideEffect, hideDuration, showEffect, showDuration);
});
}, */
// used in metro
state: function (el, oid) {
const $this = $(el);
oid = oid || $this.attr('data-oid');
if (oid) {
$this.attr('data-ctrl-oid', oid);
}
if (!vis.editMode) {
let moved = false;
$this
.on('click touchend', function (e) {
// Protect against two events
if (vis.detectBounce(this)) {
return;
}
if (moved) {
return;
}
const oid = $(this).attr('data-ctrl-oid');
if ($(this).attr('url-value')) {
vis.conn.httpGet($(this).attr('url-value'));
}
if (oid) {
let val = $(this).attr('data-val');
if (val === undefined || val === null) {
val = false;
}
if (val === 'true') {
val = true;
}
if (val === 'false') {
val = false;
}
if (parseFloat(val).toString() == val) {
val = parseFloat(val);
}
if (oid) {
vis.setValue(oid, val);
}
}
})
.on('touchmove', function () {
moved = true;
})
.on('touchstart', function () {
moved = false;
});
}
},
pressed: null,
pressedNext: null,
increment: function (el, minmax, delay, interval) {
function fInterval($that) {
vis.binds.basic.pressedNext = true;
vis.binds.basic.pressed = null;
const oid = $that.attr('data-oid');
if (!vis.editMode) {
const step = parseFloat($that.attr('data-vis-step'));
const tmp = parseFloat(vis.states[oid + '.val']) + step;
if (step < 0) {
if (tmp >= minmax) {
vis.setValue($that.attr('data-oid'), tmp);
vis.binds.basic.pressed = _setTimeout(fInterval, interval, $that);
}
} else {
if (tmp <= minmax) {
vis.setValue($that.attr('data-oid'), tmp);
vis.binds.basic.pressed = _setTimeout(fInterval, interval, $that);
}
}
}
}
function intervalStart() {
vis.binds.basic.pressedNext = false;
const $this = $(this);
if (vis.binds.basic.pressed) {
clearInterval(vis.binds.basic.pressed);
vis.binds.basic.pressed = null;
}
vis.binds.basic.pressed = setTimeout(fInterval, delay, $this);
}
if (!vis.editMode) {
let moved = false;
$(el)
.on('click touchend', function () {
// Protect against two events
if (vis.detectBounce(this) || moved) {
return;
}
if (vis.binds.basic.pressed) {
clearInterval(vis.binds.basic.pressed);
vis.binds.basic.pressed = null;
}
if (vis.binds.basic.pressedNext) {
vis.binds.basic.pressedNext = false;
return;
}
const $this = $(this);
const oid = $this.attr('data-oid');
const step = parseFloat($this.attr('data-vis-step'));
const tmp = parseFloat(vis.states[oid + '.val']) + step;
if (step < 0) {
if (minmax === undefined || tmp >= minmax) {
vis.setValue($this.attr('data-oid'), tmp);
}
} else {
if (minmax === undefined || tmp <= minmax) {
vis.setValue($this.attr('data-oid'), tmp);
}
}
})
.on('touchmove', function () {
moved = true;
})
.on('touchstart', function () {
moved = false;
});
}
if (interval) {
$(el)
.on('mousedown', intervalStart)
.on('touchstart', intervalStart)
.on('touchend', function () {
if (vis.binds.basic.pressed) {
clearInterval(vis.binds.basic.pressed);
vis.binds.basic.pressed = null;
}
})
.on('mouseup', function () {
if (vis.binds.basic.pressed) {
clearInterval(vis.binds.basic.pressed);
vis.binds.basic.pressed = null;
}
})
.data('destroy', function (id, $widget) {
$widget && $widget.off('mousedown').off('touchstart').off('touchend').off('mouseup');
});
}
},
// Used in metro
navigation: function (el, options) {
if (!vis.editMode && options.nav_view) {
const $this = $(el);
let moved = false;
$this
.on('click touchend', function (e) {
// Protect against two events
if (vis.detectBounce(this) || moved) {
return;
}
if (options.background) {
$('body').css({ background: options.background });
}
vis.changeView(
options.nav_view,
options.nav_view,
options.hideOptions,
options.showOptions,
options.sync,
);
//e.preventDefault();
//return false;
})
.on('touchmove', function () {
moved = true;
})
.on('touchstart', function () {
moved = false;
});
}
},
/*hideOnTrue: function (el) {
const $this = $(el);
const oid = $this.attr('data-oid');
vis.states.bind(oid + '.val', function (e, newVal, oldVal) {
if (newVal === true || parseFloat(newVal) > 0) {
if (!vis.editMode) {
$this.hide();
}
} else {
$this.show();
}
});
if (!vis.editMode) {
if (parseFloat(vis.states.attr(oid + '.val')) !== 0 && vis.states.attr(oid + '.val') !== false) {
$this.hide();
}
}
},
showOnValue: function (el, val) {
const $this = $(el);
const oid = $this.attr('data-oid');
vis.states.bind(oid + '.val', function (e, newVal, oldVal) {
if (newVal != val) {
if (!vis.editMode) {
$this.hide();
}
} else {
$this.show();
}
});
if (!vis.editMode) {
if (vis.states.attr(oid + '.val') != val) {
$this.hide();
}
}
},*/
_onChange: function (el, oid, wid) {
const $this = $(el);
// If still working
//console.log(oid + ' ' + vis.states.attr(oid + '.val') + ' (' + vis.states.attr(oid + '.ack') + ') - ' + wid + ' ' + vis.states.attr(wid + '.val') + ' (' + vis.states.attr(wid + '.ack') + ')');
if (wid && vis.states.attr(wid + '.val') === true) {
return;
}
let val = vis.states.attr(oid + '.val');
if (val === 'false') {
val = false;
} else if (val === 'true') {
val = true;
} else if (typeof val === 'string') {
const f = parseFloat(val);
if (f == val) {
val = f;
} else if (val !== '') {
val = true;
} else {
val = false;
}
}
if ($this.data('data-numeric')) {
$this.prop('checked', val > ($this.data('data-max') - $this.data('data-min')) / 2);
} else {
$this.prop('checked', val);
}
},
// used in metro
checkbox: function (el, numeric, min, max) {
const $this = $(el);
const oid = $this.data('oid'); // Object ID
const wid = $this.data('oid-working'); // Work ID
function onChange() {
vis.binds.basic._onChange(el, oid, wid);
}
if (oid) {
const bound = [];
vis.states.bind(oid + '.val', onChange);
bound.push(oid + '.val');
if (wid) {
vis.states.bind(wid + '.val', onChange);
bound.push(wid + '.val');
}
// remember all ids, that bound
$this
.closest('.vis-widget')
.data('bound', bound)
// remember bind handler
.data('bindHandler', onChange);
}
if (numeric) {
if (min !== undefined && min !== null && min !== '') {
min = parseFloat(min);
} else {
min = 0;
}
if (max !== undefined && max !== null && max !== '') {
max = parseFloat(max);
} else {
max = 1;
}
} else {
min = false;
max = true;
}
$this.data('min', min);
$this.data('max', max);
$this.data('numeric', numeric);
vis.binds.basic._onChange(el, oid, wid);
if (!vis.editMode) {
$this.change(function () {
const $this_ = $(this);
if ($this_.prop('checked')) {
vis.setValue($this_.data('oid'), $this_.data('max'));
} else {
vis.setValue($this_.data('oid'), $this_.data('min'));
}
});
}
},
input: function (el, data) {
const $this = $(el);
const oid = $this.data('oid'); // Object ID
const wid = $this.data('oid-working'); // Work ID
function onChange(e, val) {
$this.val(val);
}
if (oid) {
const bound = [oid + '.val'];
vis.states.bind(oid + '.val', onChange);
if (wid) {
bound.push(wid + '.val');
vis.states.bind(wid + '.val', onChange);
}
// remember all ids, that bound
$this
.closest('.vis-widget')
.data('bound', bound)
// remember bind handler
.data('bindHandler', onChange);
}
if (data.numeric) {
$this.attr('type', 'number');
if (data.min !== undefined && data.min !== null && data.min !== '') {
data.min = parseFloat(data.min);
} else {
data.min = null;
}
if (data.max !== undefined && data.max !== null && data.max !== '') {
data.max = parseFloat(data.max);
} else {
data.max = null;
}
}
$this.val(vis.states[oid + '.val'] === undefined ? '' : vis.states[oid + '.val']);
setTimeout(function () {
$this.css('text-align', $this.parent().parent().css('text-align'));
$this.css('color', $this.parent().parent().css('color'));
$this.css('background', $this.parent().parent().css('background'));
$this.css('border', '0');
$this.css('text-font', $this.parent().parent().css('text-font'));
}, 0);
if (!vis.editMode) {
$this.change(function () {
const $this_ = $(this);
if (data.numeric) {
let value = parseFloat($this_.val());
if (data.min !== null && value < data.min) {
value = data.min;
$this_.val(value);
} else if (data.max !== null && value > data.max) {
value = data.max;
$this_.val(value);
}
vis.setValue($this_.data('oid'), value);
} else {
vis.setValue($this_.data('oid'), $this_.val());
}
});
if (data.autoSet) {
$this.keyup(function (e) {
const timer = $this.data('timer');
if (timer) {
clearTimeout(timer);
}
$this.data(
'timer',
setTimeout(function () {
$this.trigger('change');
}),
1000,
);
});
}
}
},
select: function (el, invert) {
const $this = $(el).prev();
const oid = $this.attr('data-oid');
let val = vis.states[oid + '.val'];
if (val === 'false') {
val = false;
} else if (val === 'true') {
val = true;
} else if (typeof val === 'string') {
const f = parseFloat(val);
if (f == val) {
val = f;
} else if (val !== '') {
val = true;
} else {
val = false;
}
}
if (invert) val = !val;
$this.val(val ? 1 : 0);
if (!vis.editMode) {
if (oid !== 'nothing_selected') {
$this.change(function () {
let val = $this.find('option:selected').val();
if (invert) {
val = !val;
}
vis.setValue(oid, val);
});
}
}
if (oid !== 'nothing_selected') {
}
function onChange(e, newVal, oldVal) {
if (newVal === 'false') {
newVal = false;
} else if (newVal === 'true') {
newVal = true;
} else if (typeof newVal === 'string') {
const f = parseFloat(newVal);
if (f == newVal) {
newVal = f;
} else if (newVal !== '') {
newVal = true;
} else {
newVal = false;
}
}
if (oldVal === 'false') {
oldVal = false;
} else if (oldVal === 'true') {
oldVal = true;
} else if (typeof oldVal === 'string') {
const f = parseFloat(oldVal);
if (f == oldVal) {
oldVal = f;
} else if (oldVal !== '') {
oldVal = true;
} else {
oldVal = false;
}
}
if (newVal == oldVal) {
return;
}
if (newVal === 'false' || newVal === false || parseFloat(newVal) === 0) {
if ($this.find('option[value="1"]').prop('selected')) {
$this.find('option[value="1"]').prop('selected', false);
$this.find('option[value="0"]').prop('selected', true);
$this.trigger('change');
}
} else {
if ($this.find('option[value="0"]').prop('selected')) {
$this.find('option[value="0"]').prop('selected', false);
$this.find('option[value="1"]').prop('selected', true);
$this.trigger('change');
}
}
}
if (oid) {
vis.states.bind(oid + '.val', onChange);
// remember all ids, that bound
$this
.closest('.vis-widget')
.data('bound', [oid + '.val'])
// remember bind handler
.data('bindHandler', onChange);
}
},
/*pushbutton: function(el, oid) {
if (!vis.editMode) {
const $this = $(el);
oid = oid || $this.data('oid');
$this.on('mousedown touchstart', function (e) {
// Protect against two events
if (vis.detectBounce(this)) {
return;
}
vis.setValue(oid, true);
});
$this.on('mouseup touchend touchcancel', function (e) {
// Protect against two events
if (vis.detectBounce(this, true)) {
return;
}
vis.setValue(oid, false);
});
}
},*/
// used in metro
toggle: function (el, oid) {
const $this = $(el);
oid = oid || $this.data('oid');
let min = $this.data('min');
let max = $this.data('max');
const urlTrue = $this.data('url-true');
let urlFalse = $this.data('url-false');
const oidTrue = $this.data('oid-true');
let oidFalse = $this.data('oid-false');
let oidTrueVal = $this.data('oid-true-value');
let oidFalseVal = $this.data('oid-false-value');
const readOnly = $this.data('read-only');
if (min === '') {
min = undefined;
}
if (max === '') {
max = undefined;
}
if ((oid || oidTrue || urlTrue) && !vis.editMode && !readOnly) {
let moved = false;
$this
.on('click touchend', function () {
// Protect against two events
if (vis.detectBounce(this) || moved) {
return;
}
let val;
if (oidTrue || urlTrue) {
if (!oidFalse && oidTrue) {
oidFalse = oidTrue;
}
if (!urlFalse && urlTrue) {
urlFalse = urlTrue;
}
if (!oid || oid === 'nothing_selected') {
val = !$(this).data('state');
// remember state
$(this).data('state', val);
} else {
val = vis.states[oid + '.val'];
if (max !== undefined) {
if (max === 'true') max = true;
if (max === 'false') max = false;
if (val === 'true') val = true;
if (val === 'false') val = false;
val = val == max;
} else {
val = val === 1 || val === '1' || val === true || val === 'true';
}
val = !val; // invert
}
if (min === undefined || min === 'false' || min === null) {
min = false;
}
if (max === undefined || max === 'true' || max === null) {
max = true;
}
if (oidTrue) {
if (val) {
if (oidTrueVal === undefined || oidTrueVal === null) {
oidTrueVal = max;
}
if (oidTrueVal === 'false') {
oidTrueVal = false;
}
if (oidTrueVal === 'true') {
oidTrueVal = true;
}
const f = parseFloat(oidTrueVal);
if (f.toString() == oidTrueVal) {
oidTrueVal = f;
}
vis.setValue(oidTrue, oidTrueVal);
} else {
if (oidFalseVal === undefined || oidFalseVal === null) {
oidFalseVal = min;
}
if (oidFalseVal === 'false') {
oidFalseVal = false;
}
if (oidFalseVal === 'true') {
oidFalseVal = true;
}
const f = parseFloat(oidFalseVal);
if (f.toString() == oidFalseVal) {
oidFalseVal = f;
}
vis.setValue(oidFalse, oidFalseVal);
}
}
if (urlTrue) {
if (val) {
vis.conn.httpGet(urlTrue);
} else {
vis.conn.httpGet(urlFalse);
}
}
// show new state
if (!oid || oid === 'nothing_selected') {
const img = $(this).data('img-class');
if (val) {