UNPKG

node-red-contrib-sun-position

Version:
859 lines (824 loc) 72.2 kB
<!DOCTYPE HTML> <!-- This code is licensed under the Apache License Version 2.0. Copyright (c) 2022 Robert Gester Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. --> <script type="text/javascript"> (function() { RED.nodes.registerType('time-comp', { category: 'time and astro', color: '#FDF0C2', icon: 'time-comp-black.svg', inputs: 1, outputs: 1, defaults: { outputs: { value: 1 }, name: { value: '', required: false }, positionConfig: { value: '', type: 'position-config', required: true }, // #region input input: { value: 'payload', validate: RED.validators.typedInput('inputType') }, inputType: { value: 'msgPayload' }, inputFormat: { value: 0, required: true, validate(v){ return (v !== ''); } }, inputNext: { value: false }, inputOffset: { value: 0, required: true, validate(v){ return RED.validators.typedInput('inputOffsetType')(v) || $('#node-input-inputOffsetType').val() === 'none' || this.inputOffsetType === 'none'; } }, inputOffsetType: { value: 'none' }, inputOffsetMultiplier: { value: 60000, required: true, validate(v){ return RED.validators.number()(v) || $('#node-input-inputOffsetType').val() === 'none' || this.inputOffsetType === 'none'; } }, // #endregion input // #region rules rules: { value: {} }, checkall: { value: 'true', required: true }, // #endregion rules // #region result1 results: { value: [ { p: '', pt: 'msgPayload', v: '', vt: 'input', o: 1, oT: 'none', oM: 60000, f: 0, next: false, days: '*', months: '*' } ] }, result1: { value: 'none' }, // p result1Type: { value: '' }, // pt result1Value: { value: '' }, // v result1ValueType: { value: '' }, // vt result1Format: { value: 0 }, // f result1Offset: { value: 0 }, // o result1OffsetType: { value: 'none' }, // oT result1OffsetMultiplier: { value: 60000 } // oM // #endregion result1 }, outputLabels(index) { let label = ''; if (this.rules.length) { const rule = this.rules[index]; if (rule) { label = rule.operatorText + ' ' + RED.nodes.getType('position-config').getRDGNodeValLbl(this, rule.operandType, rule.operandValue); if (rule.propertyType !== 'none') { label += ' only if ' + RED.nodes.getType('position-config').getRDGNodeValLbl(this, rule.propertyType, rule.propertyValue) + ' is true'; } return label; } if (this.checkall === 'true') { return 'always'; } return 'otherwise'; // return ["msg if comparision is true", "msg if comparision is false"]; } return 'input msg after evaluation'; }, label() { if (this.name) { return this.name; } if (!this.rules || this.rules.length <= 1) { const op1 = RED.nodes.getType('position-config').getRDGNodeValLbl(this, this.inputType, this.input); return op1; } else if (this.rules.length === 1) { const op1 = RED.nodes.getType('position-config').getRDGNodeValLbl(this, this.inputType, this.input); const cmp = RED.nodes.getType('position-config').getRDGNodeValLbl(this, this.rules[0].operandType, this.rules[0].operandValue); return op1 + this.rules[0].operatorText + cmp; } const op1 = RED.nodes.getType('position-config').getRDGNodeValLbl(this, this.inputType, this.input); return op1 + ' ' + this._('time-comp.label.compare'); // return this._('time-comp.label.time-comp'); }, labelStyle() { return this.name ? 'node_label_italic' : ''; }, paletteLabel: 'time compare and change', align: 'left', oneditprepare() { setTimeout(() => { $('.is-to-show-initially').show(); $('.is-to-hide-initially').hide(); }, 300); const node = this; const $nodeConfig = $('#node-input-positionConfig'); const setup = function(node) { /* global getTypes getSelectFields appendOptions setupTInput autocomplete addLabel initCombobox getBackendData bdDateToTime getCheckboxesStr setMultiselect multiselect setTInputValue */ const types = getTypes(node, () => $nodeConfig.val()); const selFields = getSelectFields(); const operatorTypesShort = [ {selection: /(^\*$|^(11,)?12,13,14,15,16(,17)?(,18)?$)/, label: 'DT'}, {selection: /^(11,)?12,13,14$/, label: 'T'}, {selection: /^15,16(,17)?(,18)?$/, label: 'D'} ]; // #region input setupTInput(node, { typeProp: 'inputType', valueProp: 'input', width: 'calc(100% - 110px)', defaultType: types.MsgPayload.value, types: [ 'msg', types.MsgPayload, types.MsgTs, types.MsgLc, 'flow', 'global', 'date', types.DateSpecific, 'num', 'str', types.DateEntered, types.TimeEntered, types.TimeSun, types.TimeSunCustom, types.TimeSunNow, types.TimeMoon, types.DayOfMonth, 'env' ], onChange(_type, _value) { const $input = $('#node-input-input'); const opType = $input.typedInput('type'); if (opType === types.TimeEntered.value) { $('.time-row-inputNext').show(); $('.time-row-inputFormat').hide(); $('.time-row-inputOffset').show(); } else if (opType === types.DateSpecific.value || opType === types.TimeEntered.value || opType === types.DateEntered.value || opType === types.DayOfMonth.value) { $('.time-row-inputNext').hide(); $('.time-row-inputFormat').hide(); $('.time-row-inputOffset').show(); } else if ( opType === types.TimeSun.value || opType === types.TimeSunCustom.value || opType === types.TimeMoon.value) { $('.time-row-inputNext').show(); $('.time-row-inputFormat').hide(); $('.time-row-inputOffset').show(); } else if ( opType === 'msg' || opType === types.MsgPayload.value || opType === types.MsgTs.value || opType === 'flow' || opType === 'global' || opType === 'str' || opType === 'num' || opType === 'env') { $('.time-row-inputNext').hide(); $('.time-row-inputFormat').show(); $('.time-row-inputOffset').show(); } else { $('.time-row-inputNext').hide(); $('.time-row-inputFormat').hide(); $('.time-row-inputOffset').hide(); } getBackendData(d => { const $div = $('#node-input-input-div'); const titleOrg = $div.attr('titleOrg'); $div.attr('title', bdDateToTime(d, ' - ') + titleOrg); }, { nodeId: node.id, kind: 'getTimeData', config: $nodeConfig.val(), type: opType, value: $input.typedInput('value'), next: $('#node-input-inputNext').is(':checked'), format: $('#node-input-inputFormat').val(), offsetType: $('#node-input-inputOffset').typedInput('type'), offset: $('#node-input-inputOffset').typedInput('value'), multiplier: $('#node-input-inputOffsetMultiplier').val(), noOffsetError: true }); } }); initCombobox(node, $('#node-input-inputFormatsel'), $('#node-input-inputFormat'), 'dateParseFormat', 'parseFormats', node.inputFormat, 20); const inputMultiplierField = $('#node-input-inputOffsetMultiplier'); appendOptions(node, inputMultiplierField, 'multiplier'); inputMultiplierField.val(node.inputOffsetMultiplier); setupTInput(node, { typeProp: 'inputOffsetType', valueProp: 'inputOffset', width: 'calc(100% - 255px)', defaultType: types.Undefined.value, types: [types.Undefined, 'num', 'msg', 'flow', 'global', 'env', types.randomNumber, types.randmNumCachedDay, types.randmNumCachedWeek], onChange(_type, _value) { const type = $('#node-input-inputOffset').typedInput('type'); if (type === types.Undefined.value) { $('#node-input-inputOffsetMultiplier').prop('disabled', true); } else { $('#node-input-inputOffsetMultiplier').prop('disabled', false); } $('#node-input-input').change(); } }).change(); // #endregion input // #region rule-container /** * resizes the rule container */ function resizeRuleContainer() { const editorRow = $('.node-input-rule-container-row ol'); const height = editorRow.outerHeight(true); const rowCount = $('#node-input-rule-container').editableList('length'); if (rowCount > 0) { $('#node-input-rule-container').editableList('height', height + 40); } else { $('#node-input-rule-container').editableList('height', 20); } } /** * resizes a rule * @param {jQuery} rule - the jQuery selector of the rule */ function resizeRule(rule) { const newWidth = rule.width() - 10; const $operator = rule.find('.node-input-rule-operator'); const $operand = rule.find('.node-input-rule-operand'); const $formatSel = rule.find('.node-input-rule-operandFormatSel'); const $formatIp = rule.find('.node-input-rule-operandFormatIp'); // const $cbrlNext = rule.find('.node-input-rule-next'); const $offset = rule.find('.node-input-rule-offset'); const $multiplier = rule.find('.node-input-rule-multiplier'); const $property = rule.find('.node-input-rule-property'); const $propertyLbl = rule.find('.node-input-rule-property-lbl'); const $propertySpanLbl = $propertyLbl.find('.node-input-rule-property-span'); const lblWidth = 25; // row1 if (Number($operator.val()) === 99) { $operator.width(newWidth - lblWidth - 10); } else { $operator.width(60); const operatorWidth = 120; $operand.typedInput('width', (newWidth - operatorWidth - lblWidth - 50)); } // row2 let formatWidth = (newWidth - lblWidth - 18); if (Number($formatSel.val()) === 99) { $formatIp.show(); formatWidth = Math.floor(formatWidth / 3); $formatSel.width(formatWidth - 5); $formatIp.width((formatWidth * 2) - 34); } else { $formatIp.hide(); // $formatIp.width(0); $formatSel.width(formatWidth); } // row3 // $cbrlNext // row4 const multiplierWidth = 125; $multiplier.width(multiplierWidth); $offset.typedInput('width', (newWidth - multiplierWidth - lblWidth - 40)); // row5 const lblwidth = $propertySpanLbl.width() + lblWidth; $property.typedInput('width', (newWidth - lblwidth - 30)); $propertyLbl.width(lblwidth); } $('#node-input-rule-container').css('min-height', '20px').css('min-width', '300px').editableList({ addItem($containerRow, containerIndex, data) { $containerRow.css({overflow: 'hidden', whiteSpace: 'nowrap'}); const $row1 = $('<div/>').appendTo($containerRow); const $row2 = $('<div/>', {style: 'padding-top: 5px;'}).appendTo($containerRow); const $row3 = $('<div/>', {style: 'padding-top: 5px;'}).appendTo($containerRow); const $row4 = $('<div/>', {style: 'padding-top: 5px;'}).appendTo($containerRow); const $row5 = $('<div/>', {style: 'padding-top: 5px;'}).appendTo($containerRow); // row1 // operator const $operator = $('<select/>', { class: 'node-input-rule-operator', id: 'node-input-rule-operator' + containerIndex }).appendTo($row1); appendOptions(node, $operator, 'operators'); const operatorTypeField = multiselect(node, $row1, 'operatorTypes', 'node-red-contrib-sun-position/position-config:common.operatorTypes','node-input-rule-operatorType-' + containerIndex); $operator.val(data.operator || selFields.operators[0].id); setMultiselect(data.operatorType, operatorTypeField, operatorTypesShort); const $operandDiv = $('<span />').appendTo($row1); // { style: 'display: inline-block;' } addLabel($operandDiv, 'node-input-rule-operand', 'fa fa-clock-o'); const $operand = $('<input/>', { class: 'node-input-rule-operand', id: 'node-input-rule-operand' + containerIndex, type: 'text', value: (data.operandValue || '') }).appendTo($operandDiv).typedInput({ default: (data.operandType || types.DateEntered.value), types: [ 'msg', 'flow', 'global', types.DateSpecific, 'num', 'str', types.DateEntered, types.TimeEntered, types.TimeSun, types.TimeSunCustom, types.TimeSunNow, types.TimeMoon, types.DayOfMonth, 'env' ] }); const finalspan = $('<span/>', { style: 'float: right; margin-top: 6px;' }).appendTo($row1); finalspan.append(' &#8594; <span class="node-input-rule-index">' + (containerIndex + 1) + '</span> '); // row2 const operandFormatSelFieldName = 'node-input-rule-operandFormatSel'; addLabel($row2, operandFormatSelFieldName, 'fa fa-file-code-o'); const $formatSel = $('<select/>', { class: operandFormatSelFieldName, id: operandFormatSelFieldName + containerIndex }).appendTo($row2); const $formatIp = $('<input/>', { class: 'node-input-rule-operandFormatIp', id: 'node-input-rule-operandFormatIp' + containerIndex, type: 'text' }).appendTo($row2); initCombobox(node, $formatSel, $formatIp, 'dateParseFormat', 'parseFormats', data.format, 20); // row3 - 1 - Next selection const $divNext = $('<div/>').appendTo($row3); addLabel($divNext, 'node-input-rule-next', 'fa fa-clock-o', node._('node-red-contrib-sun-position/position-config:common.label.nextOccurrence')); const $cbrlNext = $('<input/>', { class: 'node-input-rule-next', type: 'checkbox', style: 'display:inline-block; width:15px; vertical-align:baseline;' }) .css('width', 'calc(30% - 30px)') .appendTo($divNext); if (data.next === true || data.next === 'true') { $cbrlNext.prop('checked', true); } else { $cbrlNext.prop('checked', false); } // row4 addLabel($row4, 'node-input-rule-offset', 'fa fa-plus'); const $offset = $('<input/>', { class: 'wg-offset-spinner node-input-rule-offset', id: 'node-input-rule-offset' + containerIndex, type: 'text', value: (data.offsetValue || '') }).appendTo($row4).typedInput({ default: (data.offsetType || types.Undefined.value), types: [types.Undefined, 'num', 'msg', 'flow', 'global', types.randmNumCachedDay, types.randmNumCachedWeek] }); const $multiplier = $('<select/>', { class: 'node-input-rule-multiplier', id: 'node-input-rule-multiplier' + containerIndex }).appendTo($row4); appendOptions(node, $multiplier, 'multiplier'); $multiplier.val(data.multiplier || 60000); // row5 addLabel($row5, 'node-input-rule-property', 'fa fa-puzzle-piece', node._('time-comp.label.onlyif')); $('<input/>', { class: 'node-input-rule-property', id: 'node-input-rule-property' + containerIndex, type: 'text', value: (data.propertyValue || '') }).appendTo($row5).typedInput({ default: (data.propertyType || types.Unlimited.value), types: [types.Unlimited, 'msg', 'flow', 'global', 'env'] }); // changes $operand.change(() => { // $operand.show(); const opType = $operand.typedInput('type'); if (Number($operator.val()) === 99) { $operandDiv.hide(); operatorTypeField.hide(); $row2.hide(); // format $row3.hide(); // next $row4.hide(); // offset $row5.show(); // limit } else { $operandDiv.show(); operatorTypeField.show(); if (opType === types.TimeEntered.value) { $row2.hide(); // format $row3.show(); // next $row4.show(); // offset $row5.show(); // limit } else if (opType === types.DateEntered.value || opType === types.DateSpecific.value) { $row2.hide(); // format $row3.hide(); // next $row4.show(); // offset $row5.show(); // limit } else if (opType === types.TimeSun.value || opType === types.TimeSunCustom.value || opType === types.TimeMoon.value ) { $row2.hide(); // format $row3.show(); // next $row4.show(); // offset $row5.show(); // limit } else if (opType === 'msg' || opType === 'flow' || opType === 'global' || opType === 'str' || opType === 'num' || opType === 'env') { $row2.show(); // format $row3.hide(); // next $row4.show(); // offset $row5.show(); // limit } else { $row2.hide(); // format $row3.hide(); // next $row4.hide(); // offset $row5.show(); // limit } } getBackendData(d => { $operandDiv.attr('title', bdDateToTime(d)); }, { nodeId: node.id, kind: 'getTimeData', config: $nodeConfig.val(), type: opType, value: $operand.typedInput('value'), format: $formatIp.val(), next: $cbrlNext.is(':checked'), offsetType: $offset.typedInput('type'), offset: $offset.typedInput('value'), multiplier: $multiplier.val(), noOffsetError: true }); resizeRule($containerRow); }); $operator.change(() => $operand.change()); $multiplier.change(() => $operand.change()); $cbrlNext.change(() => $operand.change()); $offset.change(() => $operand.change()); $formatSel.change(() => $operand.change()); $formatIp.change(() => $operand.change()); $operand.change(); // resizeRule($containerRow); autocomplete($formatIp, 'dateParseFormat'); resizeRuleContainer(); }, sortItems(rules) { rules.each(function (i) { $(this).find('.node-input-rule-index').html(i + 1); }); }, resizeItem: resizeRule, sortable: true, removable: true, removeItem: resizeRuleContainer }); if (node.rules) { for (let i = 0; i < node.rules.length; i++) { const rule = node.rules[i]; $('#node-input-rule-container').editableList('addItem', rule); } } // #endregion rule-container // #region result-container /** resizes result container */ function resizeResultContainer() { const editorRow = $('.node-input-result-container-row ol'); const height = editorRow.outerHeight(true); const rowCount = $('#node-input-result-container').editableList('length'); if (rowCount > 0) { $('#node-input-result-container').editableList('height', height + 40); } else { $('#node-input-result-container').editableList('height', 20); } } $('#node-input-result-container').css('min-height', '40px').css('min-width', '400px').editableList({ addItem($containerRow, containerIndex, data) { $containerRow.css({ overflow: 'hidden', whiteSpace: 'nowrap' }); const $row1 = $('<div/>').appendTo($containerRow); const $row2 = $('<div/>', { style: 'padding-top: 5px;' }).appendTo($containerRow); const $row3 = $('<div/>', { style: 'padding-top: 5px;' }).appendTo($containerRow); const $row4 = $('<div/>', { style: 'padding-top: 5px;' }).appendTo($containerRow); // row1 - Property / Type Selection let prop = data; if (!Object.prototype.hasOwnProperty.call(prop, 'p')) { prop = { p : '', pt : types.MsgPayload.value, v : '', vt : 'input', o : '', oT : types.Undefined.value, oM : 60000, f : 0, next : false, days : '*', months: '*' }; } if (prop.p === 'payload' && (!prop.pt || prop.pt === 'msg')) { prop.pt = types.MsgPayload.value; } else if (prop.p === 'topic' && (!prop.pt || prop.pt === 'msg')) { prop.pt = types.MsgTopic.value; } else if (prop.p === 'ts' && (!prop.pt || prop.pt === 'msg')) { prop.pt = types.MsgTs.value; } else if (prop.p === 'lc' && (!prop.pt || prop.pt === 'msg')) { prop.pt = types.MsgLc.value; } else if (prop.p === 'value' && (!prop.pt || prop.pt === 'msg')) { prop.pt = types.MsgValue.value; } const $propertyName = $('<input/>', { class: 'node-input-prop-result-name', type: 'text' }) .css('width', '40%') .appendTo($row1) .typedInput({ default: types.MsgPayload.value, types: [ types.MsgPayload, types.MsgTopic, types.MsgTs, types.MsgLc, types.MsgValue, 'msg', 'flow', 'global' ] }); setTInputValue($propertyName, prop.p, prop.pt); $('<div/>', { style: 'display:inline-block; padding:0px 6px;' }) .text('=') .appendTo($row1); const $propertyValue = $('<input/>', { class: 'node-input-prop-result-value', type: 'text' }) .css('width', 'calc(60% - 30px)') .appendTo($row1) .typedInput({ default: 'input', types: [ { value: 'input', label: node._('time-comp.typeLabel.input'), hasValue: false }, 'str', 'num', 'bool', 'date', types.DateSpecific, types.TimeEntered, types.DateEntered, types.TimeSun, types.TimeSunCustom, types.TimeSunNow, types.TimeMoon, types.DayOfMonth, types.strPlaceholder, 'json', 'bin', 'env', 'msg', 'flow', 'global', 'jsonata', types.SunCalc, types.SunInSky, types.MoonCalc, types.MoonPhase, types.SunAzimuth, types.SunElevation, types.SunTimeByAzimuth, types.SunTimeByElevationObj, types.SunTimeByElevationNext, types.SunTimeByElevationRise, types.SunTimeByElevationSet, types.isDST, types.WeekOfYear, types.WeekOfYearEven, types.DayOfYear, types.DayOfYearEven, types.numPercent, types.randomNumber, types.randmNumCachedDay, types.randmNumCachedWeek, types.nodeId, types.nodeName, types.nodePath ] }); setTInputValue($propertyValue, prop.v, prop.vt); // row2 - Format Selection const operandFormatSelFieldName = 'node-input-prop-result-FormatSel'; addLabel($row2, operandFormatSelFieldName, 'fa fa-file-code-o'); const $formatSel = $('<select/>', { class: operandFormatSelFieldName }).appendTo($row2); const $formatIp = $('<input/>', { class: 'node-input-prop-result-FormatIp', type: 'text' }) .css('width', 'calc(100% - 30px)') .appendTo($row2); initCombobox(node, $formatSel, $formatIp, 'dateOutFormat', 'outputFormats', prop.f ? prop.f : 0, -70); // row3 - Offset and Multiplier addLabel($row3, 'node-input-prop-result-offset', 'fa fa-plus'); const $offset = $('<input/>', { class: 'node-input-prop-result-offset', type: 'text', value: (prop.o ? prop.o : '') }) .css('width', '70%') .appendTo($row3) .typedInput({ default: (prop.oT ? prop.oT : types.Undefined.value), types: [types.Undefined, 'num', 'msg', 'flow', 'global', 'env', types.randomNumber, types.randmNumCachedDay, types.randmNumCachedWeek] }); setTInputValue($offset, prop.o, prop.oT); const $multiplier = $('<select/>', { class: 'node-input-prop-result-multiplier' }) .css('width', 'calc(30% - 30px)') .appendTo($row3); appendOptions(node, $multiplier, 'multiplier'); $multiplier.val(prop.oM ? prop.oM : 60000); // row4 - Next, Day, Month selection // row4 - 1 - Next selection const $divNext = $('<div/>').appendTo($row4); addLabel($divNext, 'node-input-prop-result-next', 'fa fa-clock-o', node._('node-red-contrib-sun-position/position-config:common.label.nextOccurrence')); const $cbOutNext = $('<input/>', { class: 'node-input-prop-result-next', type: 'checkbox', style: 'display:inline-block; width:15px; vertical-align:baseline;' }) .css('width', 'calc(30% - 30px)') .appendTo($divNext); if (typeof prop.next === 'undefined' || prop.next === null || prop.next === true || prop.next === 'true') { $cbOutNext.prop('checked', true); } else { $cbOutNext.prop('checked', false); } // row4 - 2 - Day selection const $divMnDays = $('<div/>', { style: 'margin-top:5px;border-top: 1px solid #000;margin-bottom: 0;' } ).appendTo($row4); addLabel($divMnDays, 'node-input-prop-result-days', 'fa fa-clock-o', node._('node-red-contrib-sun-position/position-config:common.label.validForDays')); const $divDays = $('<div/>', { class: 'node-input-prop-result-days', style: 'style="display:inline-block;' }).appendTo($divMnDays); const $divDays2 = $('<div/>').appendTo($divDays); for (let d = 0; d < 7; d++) { const $lbl = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.days.' + d) }) .css('width', 'calc(14% - 7px)') // (100% / 7 = 14%) - (30 px / 7 = 7px) .appendTo($divDays2); const $cb = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-day-' + d, value: d, style: 'width: auto;' }).appendTo($lbl); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.days.' + (d + 7))).appendTo($lbl); if (typeof prop.days === 'undefined' || prop.days === null || prop.days === '*') { $cb.prop('checked', true); } else if (prop.days !== '' && prop.days !== 'none') { $cb.prop('checked', false); prop.days.split(',').forEach(v => { if (v == d) { // eslint-disable-line eqeqeq $cb.prop('checked', true); } }); } } // row4 - 3 - Special Limit selection const $divSpecLimit = $('<div/>', { style: 'margin-top:5px;border-top: 1px solid #000;margin-bottom: 0;' } ).appendTo($row4); addLabel($divSpecLimit, 'node-input-prop-result-speciallimits', 'fa fa-clock-o', node._('node-red-contrib-sun-position/position-config:common.label.specialLimits')); const $divSpecLimits = $('<div/>', { class: 'node-input-prop-result-speciallimits', style: 'style="display:inline-block;' }).appendTo($divSpecLimit); const $divSpecLimits2 = $('<div/>').appendTo($divSpecLimits); const $lblSL1 = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.label.onlyEvenDays') }) .css('width', 'calc(50% - 15x)') // (100% / 2) - (30 px / 2) .appendTo($divSpecLimits2); const $cbOnlyEvenDays = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-onlyEvenDays', style: 'width: auto;' }).appendTo($lblSL1); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.label.onlyEvenDays')).appendTo($lblSL1); $cbOnlyEvenDays.prop('checked', (prop.onlyEvenDays === 'true' || prop.onlyEvenDays === true)); const $lblSL2 = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.label.onlyOddDays') }) .css('width', 'calc(50% - 15x)') // (100% / 2) - (30 px / 2) .appendTo($divSpecLimits2); const $cbOnlyOddDays = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-onlyOddDays', style: 'width: auto;' }).appendTo($lblSL2); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.label.onlyOddDays')).appendTo($lblSL2); $cbOnlyOddDays.prop('checked', (prop.onlyOddDays === 'true' || prop.onlyOddDays === true)); const $lblSL3 = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.label.onlyEvenWeeks') }) .css('width', 'calc(50% - 15x)') // (100% / 2) - (30 px / 2) .appendTo($divSpecLimits2); const $cbOnlyEvenWeeks = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-onlyEvenWeeks', style: 'width: auto;' }).appendTo($lblSL3); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.label.onlyEvenWeeks')).appendTo($lblSL1); $cbOnlyEvenWeeks.prop('checked', (prop.onlyEvenWeeks === 'true' || prop.onlyEvenWeeks === true)); const $lblSL4 = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.label.onlyOddWeeks') }) .css('width', 'calc(50% - 15x)') // (100% / 2) - (30 px / 2) .appendTo($divSpecLimits2); const $cbOnlyOddWeeks = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-onlyOddWeeks', style: 'width: auto;' }).appendTo($lblSL4); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.label.onlyOddWeeks')).appendTo($lblSL2); $cbOnlyOddWeeks.prop('checked', (prop.onlyOddWeeks === 'true' || prop.onlyOddWeeks === true)); // row4 - 3 - Month selection const $divMnMonth = $('<div/>', { style: 'margin-top:5px;border-top: 1px solid #000;margin-bottom: 0;' } ).appendTo($row4); addLabel($divMnMonth, 'node-input-prop-result-months', 'fa fa-clock-o', node._('node-red-contrib-sun-position/position-config:common.label.validForMonths')); const $divMonths = $('<div/>', { class: 'node-input-prop-result-months', style: 'style="display:inline-block;' }).appendTo($divMnMonth); const $divMonths2 = $('<div/>').appendTo($divMonths); const $divMonths3 = $('<div/>').appendTo($divMonths); for (let m = 0; m < 12; m++) { const $lbl = $('<label/>', { title: node._('node-red-contrib-sun-position/position-config:common.months.' + m) }) .css('width', 'calc(16% - 6px)') // (100% / 7 = 14%) - (30 px / 7 = 6px) .appendTo((m > 5) ? $divMonths2 : $divMonths3); const $cb = $('<input/>', { type: 'checkbox', class: 'node-input-prop-result-month-' + m, value: m, style: 'width: auto;' }).appendTo($lbl); $('<span/>').text(node._('node-red-contrib-sun-position/position-config:common.months.' + (m + 12))).appendTo($lbl); if (typeof prop.months === 'undefined' || prop.months === null || prop.months === '*') { $cb.prop('checked', true); } else if (prop.months !== '' && prop.months !== 'none') { $cb.prop('checked', false); prop.months.split(',').forEach(v => { if (v == m) { // eslint-disable-line eqeqeq $cb.prop('checked', true);