diff --git a/docs/MQB/3Q0_assistants.md b/docs/MQB/3Q0_assistants.md index 8d3f6f38..f854ea66 100644 --- a/docs/MQB/3Q0_assistants.md +++ b/docs/MQB/3Q0_assistants.md @@ -277,7 +277,7 @@ Lane_departure_warning: available ``` Данную кодировку нужно очень внимательно проверить относительно того, какие опции имеются в машине. Для удобства можно воспользоваться [калькулятором битов](../../utils/longCoding) с расшифровкой А5 блока. - Например, готовую кодировку можно [Открыть в калькуляторе](../../utils/longCoding/?code=000307060007040100222346C154890098000E20004000&label=A5) + Например, готовую кодировку можно [Открыть в калькуляторе](../../utils/longCoding/?code=000307060007040100222346C154890098000E20004000&label=A5_3Q0) ``` yaml Блок A5 (камера ассистентов) → Кодирование: diff --git a/docs/assets/js/fecGenerator.js b/docs/assets/js/fecGenerator.js index 49b3a74a..543685bd 100644 --- a/docs/assets/js/fecGenerator.js +++ b/docs/assets/js/fecGenerator.js @@ -1,61 +1,152 @@ -var e = Math.floor((new Date).getTime() / 1e3), - t = [], - s = 0, - n = "
"; +const TRAILER_HEX = "0000000000000000003B0FC769BFFF15ECD445B8196D2203D6D56BD8F22748B37D68F863DAC57E23C90A5FEEF0C06394C8D48A2EAA4F0FB658557400E66441DDC7D5AC3610AA4D45056C0C6E17C7E4B60C40E52FFA891938AF186ED20AE83A99EB10F3088479E6CBD2770C1563B5AE235B440BEF16EBE696576E108F2F9F897D963DEFBAD3ABDF2FFE"; -function r(e, t, s, n) { - e === t ? $("#" + s).removeClass("alert-danger").addClass("alert-success").html(n + " status: OK") : e > 0 && e < t ? $("#" + s).removeClass("alert-success").addClass("alert-danger").html(n + " should be " + t + " length size! " + e + - "/" + t + "").show() : $("#" + s).removeClass("alert-success").addClass("alert-danger").html(n + " input could not be empty!").show() +let codes = []; +let selectedCount = 0; + +function $(selector) { + return document.querySelector(selector); } -function i() { - for (let s = 0; s < t.length; s++) t[s].visible && $("#codes").append(n + t[s].name + a + t[s].code + "03" + t[s].vcrn.toUpperCase() + h(t[s].vin).toUpperCase() + "00" + e.toString(16).toUpperCase() + l + o) +function $all(selector) { + return document.querySelectorAll(selector); } -function c(e, t) { - for (let s = 0; s < e.length; s++) - if (e[s].code === t) return !0; - return !1 +function validateLength(actual, expected, alertId, label) { + const el = document.getElementById(alertId); + if (!el) return; + + el.classList.remove('alert-success', 'alert-danger'); + + if (actual === 0) { + el.classList.add('alert-danger'); + el.innerHTML = `${label} input cannot be empty!`; + el.style.display = ''; + } else if (actual !== expected) { + el.classList.add('alert-danger'); + el.innerHTML = `${label} should be ${expected} characters long! ${actual}/${expected}`; + el.style.display = ''; + } else { + el.classList.add('alert-success'); + el.innerHTML = `${label} status: OK`; + el.style.display = ''; + } } -function h(e) { - let t = []; - let n = e.length; - let s = 0; - for (; s < n; s++) { - const a = Number(e.charCodeAt(s)).toString(16); - t.push(a) - } - return t.join("") -} - -$("#vin").keyup(function () { - $("#codes").html(""); - for (var e = 0; e < t.length; e++) t[e].vin = this.value; - r(this.value.length, 17, "avin", "VIN"), i() -}), $("#vcrn").keyup(function () { - $("#codes").html(""); - for (var e = 0; e < t.length; e++) t[e].vcrn = this.value; - r(this.value.length, 10, "avcrn", "VCRN"), i() -}), $(".checkbox input").change(function () { - if ($("#codes").html(""), this.checked) { - if (c(t, this.value)) - for (var e = 0; e < t.length; e++) t[e].code === this.value && (t[e].visible = !0); - else t.push({ - code: this.value, - vcrn: $("#vcrn").val(), - vin: $("#vin").val(), - visible: !0, - name: this.name +function stringToHex(str) { + return Array.from(str) + .map(ch => ch.charCodeAt(0).toString(16)) + .join(""); +} + +function hasCode(list, code) { + return list.some(item => item.code === code); +} + +function renderCodes() { + const codesContainer = document.getElementById("codes"); + const vinInput = document.getElementById("vin"); + const vcrnInput = document.getElementById("vcrn"); + const jumbotron = document.querySelector(".jumbotron"); + + if (!codesContainer || !vinInput || !vcrnInput) return; + + codesContainer.innerHTML = ""; + + const vin = vinInput.value; + const vcrn = vcrnInput.value; + + const timestampHex = Math.floor(Date.now() / 1000) + .toString(16) + .toUpperCase(); + + codes.forEach(item => { + if (!item.visible) return; + + const hexVin = stringToHex(vin).toUpperCase(); + const finalCode = `1102${item.code}03${vcrn.toUpperCase()}${hexVin}00${timestampHex}${TRAILER_HEX}`; + + const wrapper = document.createElement("div"); + wrapper.className = "form-group"; + + const label = document.createElement("label"); + label.className = "font-weight-bold"; + label.textContent = item.name; + + const textarea = document.createElement("textarea"); + textarea.className = "form-control h-100"; + textarea.readOnly = true; + textarea.value = finalCode; + + // Выделять текст при клике/фокусе + textarea.addEventListener("click", function () { + this.select(); + }); + textarea.addEventListener("focus", function () { + this.select(); + }); + + wrapper.appendChild(label); + wrapper.appendChild(textarea); + codesContainer.appendChild(wrapper); + }); + + if (jumbotron) { + jumbotron.style.display = selectedCount > 0 ? "none" : ""; + } +} + +const vinEl = document.getElementById("vin"); +if (vinEl) { + vinEl.addEventListener("keyup", function () { + const value = this.value; + codes.forEach(item => (item.vin = value)); + + validateLength(value.length, 17, "avin", "VIN"); + renderCodes(); + }); +} + +const vcrnEl = document.getElementById("vcrn"); +if (vcrnEl) { + vcrnEl.addEventListener("keyup", function () { + const value = this.value; + codes.forEach(item => (item.vcrn = value)); + + validateLength(value.length, 10, "avcrn", "VCRN"); + renderCodes(); + }); +} + +$all(".checkbox input").forEach(input => { + input.addEventListener("change", function () { + const codeValue = this.value; + const name = this.name; + + if (this.checked) { + if (hasCode(codes, codeValue)) { + codes.forEach(item => { + if (item.code === codeValue) item.visible = true; + }); + } else { + const vinVal = vinEl ? vinEl.value : ""; + const vcrnVal = vcrnEl ? vcrnEl.value : ""; + + codes.push({ + code: codeValue, + vcrn: vcrnVal, + vin: vinVal, + visible: true, + name: name }); - s++ + } + selectedCount++; } else { - for (e = 0; e < t.length; e++) t[e].code === this.value && (t[e].visible = !1); - s-- + codes.forEach(item => { + if (item.code === codeValue) item.visible = false; + }); + selectedCount--; } - s > 0 ? $(".jumbotron").hide() : $(".jumbotron").show(), i() + + renderCodes(); + }); }); diff --git a/docs/assets/js/fec_jquery.js b/docs/assets/js/fec_jquery.js deleted file mode 100644 index 2a171fcb..00000000 --- a/docs/assets/js/fec_jquery.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(g,e){"use strict";var t=[],v=g.document,r=Object.getPrototypeOf,s=t.slice,y=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,m=n.hasOwnProperty,a=m.toString,l=a.call(Object),b={},x=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},w=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function C(e,t,n){var r,i,o=(n=n||v).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function T(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector",E=function(e,t){return new E.fn.init(e,t)},d=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function p(e){var t=!!e&&"length"in e&&e.length,n=T(e);return!x(e)&&!w(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+R+")"+R+"*"),U=new RegExp(R+"|>"),V=new RegExp(W),X=new RegExp("^"+B+"$"),Q={ID:new RegExp("^#("+B+")"),CLASS:new RegExp("^\\.("+B+")"),TAG:new RegExp("^("+B+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,J=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+R+"?|("+R+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){C()},ae=xe(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{O.apply(t=P.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){O={apply:t.length?function(e,t){q.apply(e,P.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&((e?e.ownerDocument||e:m)!==T&&C(e),e=e||T,E)){if(11!==d&&(u=Z.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return O.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return O.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!S[t+" "]&&(!v||!v.test(t))&&(1!==d||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===d&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=N),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+be(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return O.apply(n,f.querySelectorAll(c)),n}catch(e){S(t,!0)}finally{s===N&&e.removeAttribute("id")}}}return g(t.replace(F,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>x.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[N]=!0,e}function ce(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in p=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==T&&9===r.nodeType&&r.documentElement&&(a=(T=r).documentElement,E=!i(T),m!==T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),p.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),p.getElementsByTagName=ce(function(e){return e.appendChild(T.createComment("")),!e.getElementsByTagName("*").length}),p.getElementsByClassName=J.test(T.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=N,!T.getElementsByName||!T.getElementsByName(N).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(x.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},x.find.CLASS=p.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=J.test(T.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+R+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+N+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+N+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=T.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+R+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(p.matchesSelector=J.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",W)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=J.test(a.compareDocumentPosition),y=t||J.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument===m&&y(m,e)?-1:t===T||t.ownerDocument===m&&y(m,t)?1:u?H(u,e)-H(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===T?-1:t===T?1:i?-1:o?1:u?H(u,e)-H(u,t):0;if(i===o)return de(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?de(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==T&&C(e),p.matchesSelector&&E&&!S[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){S(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&V.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=d[e+" "];return t||(t=new RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&d(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function L(e,n,r){return x(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):"string"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:v,!0)),D.test(r[1])&&E.isPlainObject(t))for(r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=v.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,j=E(v);var O=/^(?:parents|prev(?:Until|All))/,P={children:!0,contents:!0,next:!0,prev:!0};function H(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,pe=/^$|^module$|\/(?:java|ecma)script/i,he={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ge(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&S(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;nx",b.noCloneChecked=!!ye.cloneNode(!0).lastChild.defaultValue;var we=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function Ne(){return!1}function Ae(e,t){return e===function(){try{return v.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ne;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return E().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=E.guid++)),e.each(function(){E.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(G.set(e,i,!1),E.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=G.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(E.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),G.set(this,i,r),t=o(this,i),this[i](),r!==(n=G.get(this,i))||t?G.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(G.set(this,i,{value:E.event.trigger(E.extend(r[0],E.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===G.get(e,i)&&E.event.add(e,i,Ee)}E.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&E.find.matchesSelector(ie,i),n.guid||(n.guid=E.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof E&&E.event.triggered!==e.type?E.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(I)||[""]).length;while(l--)p=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),p&&(f=E.event.special[p]||{},p=(i?f.delegateType:f.bindType)||p,f=E.event.special[p]||{},c=E.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&E.expr.match.needsContext.test(i),namespace:h.join(".")},o),(d=u[p])||((d=u[p]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(p,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,c):d.push(c),E.event.global[p]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.hasData(e)&&G.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(I)||[""]).length;while(l--)if(p=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),p){f=E.event.special[p]||{},d=u[p=(r?f.delegateType:f.bindType)||p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=d.length;while(o--)c=d[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(d.splice(o,1),c.selector&&d.delegateCount--,f.remove&&f.remove.call(e,c));a&&!d.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||E.removeEvent(e,p,v.handle),delete u[p])}else for(p in u)E.event.remove(e,p+t[l],n,r,!0);E.isEmptyObject(u)&&G.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=E.event.fix(e),u=new Array(arguments.length),l=(G.get(this,"events")||{})[s.type]||[],c=E.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,Le=/\s*$/g;function Oe(e,t){return S(e,"table")&&S(11!==t.nodeType?t:t.firstChild,"tr")&&E(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Ie(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(G.hasData(e)&&(o=G.access(e),a=G.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(b.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||E.isXMLDoc(e)))for(a=ge(c),r=0,i=(o=ge(e)).length;r
",2===pt.childNodes.length),E.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=v.implementation.createHTMLDocument("")).createElement("base")).href=v.location.href,t.head.appendChild(r)):t=v),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&E(o).remove(),E.merge([],i.childNodes)));var r,i,o},E.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=E.css(e,"position"),c=E(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=E.css(e,"top"),u=E.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),x(t)&&(t=t.call(e,n,E.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},E.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){E.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===E.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===E.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=E(e).offset()).top+=E.css(e,"borderTopWidth",!0),i.left+=E.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-E.css(r,"marginTop",!0),left:t.left-i.left-E.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===E.css(e,"position"))e=e.offsetParent;return e||ie})}}),E.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;E.fn[t]=function(e){return z(this,function(e,t,n){var r;if(w(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),E.each(["top","left"],function(e,n){E.cssHooks[n]=ze(b.pixelPosition,function(e,t){if(t)return t=Fe(e,n),Me.test(t)?E(e).position()[n]+"px":t})}),E.each({Height:"height",Width:"width"},function(a,s){E.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){E.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return z(this,function(e,t,n){var r;return w(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?E.css(e,t,i):E.style(e,t,n,i)},s,n?e:void 0,n)}})}),E.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){E.fn[n]=function(e,t){return 0 response.text()) - .then(text => labelsFromFile = text.split("\n")) - .then(() => selByte(0)); - } else { - selByte(curSelectedByte); - } - return true; - } else { - alert("Кодировка содержит неверные символы. Поддерживаются только только латинские буквы A-F и цифры 0-9. Coding has wrong symbols. Latin characters A-F and digits 0-9 are allowed. "); - clearFields(); + let retval = ""; + let i = 0; + + while (intnum > 0) { + i++; + const digit = intnum % radix; + retval = ConvArray[digit] + retval; + intnum = Math.floor(intnum / radix); + + if (i > 100) { + return "NaN"; // } - } else { - alert("Неверное значение. Кодировка должна содержать четное количество символов. Incorrect value. Coding should have odd number of symbols."); - clearFields(); } - return false; + + return retval || "0"; } -function trim(str) { - return str.replace(/^\s*|\s*$/g, ""); +function hexToBin(value) { + const dezVal = parseInt(value, 16); + const bitValueBin = from10toradix(dezVal, 2); + return addLeadingZeros(bitValueBin); } -function initArray() { - this.length = initArray.arguments.length; - for (var i = 0; i < this.length; i++) { - this[i] = initArray.arguments[i]; +function addLeadingZeros(binVal) { + let retString = binVal || ""; + const anz = 8 - retString.length; + for (let i = 0; i < anz; i++) { + retString = "0" + retString; } + return retString; } -function hexToBin(value){ - var bitValueBin; +function activateFields() { + const loading = document.getElementById("loading"); + const bitDescription = document.getElementById("bitDescription"); + if (loading) loading.style.display = "none"; + if (bitDescription) bitDescription.style.display = "block"; +} - dezVal = parseInt(value, 16); - bitValueBin = from10toradix(dezVal, 2); +// ========== Initialisation ========== - return addLeadingZeros(bitValueBin); -} +function init() { + const urlParams = new URLSearchParams(window.location.search); -function from10toradix(value, radix) { - var retval = ''; - var ConvArray = new initArray(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'); - var intnum; - var tmpnum; - var i = 0; - - intnum = parseInt(value, 10); - if (isNaN(intnum)) { - retval = 'NaN'; - } else { - while (intnum > 0.9) { - i++; - tmpnum = intnum; - - // concat ret string with new digit - retval = ConvArray[tmpnum % radix] + retval; - intnum = Math.floor(tmpnum / radix); - if (i > 100) { - // break infinite loops - retval = 'NaN'; - break; - } + createByteDescription(defaultByteSize); + createBitDescription(); + wireBitEvents(); + wireByteEvents(); + + const codeParam = urlParams.get("code"); + const labelParam = urlParams.get("label"); + + if (labelParam != null) { + const langSel = document.getElementById("langBits"); + if (langSel) langSel.value = labelParam; + } + if (codeParam != null) { + const orig = document.getElementById("origCode"); + if (orig) { + orig.value = codeParam; + checkOrig(); } } - return retval; } -function calculateByteIdFromNumber(num) { - var byteId = num; - if (num < 10) { - byteId = "0" + num; +// ========== Main functions ========== + +function checkOrig() { + const filter = /^[A-F0-9]+$/; + const origEl = document.getElementById("origCode"); + if (!origEl) return false; + + let orig = origEl.value; + orig = cleanHexValue(orig); + origEl.value = orig; + + const bitDescription = document.getElementById("bitDescription"); + if (bitDescription) bitDescription.style.display = "none"; + + if (orig.length % 2 === 0 && orig.length > 0) { + if (filter.test(orig)) { + const loading = document.getElementById("loading"); + if (loading) loading.style.display = "inline-block"; + + fillBytes(); + + const langBits = document.getElementById("langBits"); + if (langBits && langBits.value !== "none") { + fetch("../../labels/" + langBits.value + "_labels.txt") + .then(response => response.text()) + .then(text => { + labelsFromFile = text.split("\n"); + }) + .then(() => { + selByte(0); + }) + .catch(() => { + labelsFromFile = null; + selByte(0); + }); + } else { + selByte(curSelectedByte >= 0 ? curSelectedByte : 0); + } + return true; + } else { + alert( + "Кодировка содержит неверные символы. Поддерживаются только латинские буквы A-F и цифры 0-9. " + + "Coding has wrong symbols. Latin characters A-F and digits 0-9 are allowed." + ); + clearFields(); + } + } else { + if (orig.length > 0) { + alert( + "Неверное значение. Кодировка должна содержать чётное количество символов. " + + "Incorrect value. Coding should have even number of symbols." + ); + } + clearFields(); } - return byteId; + return false; } function fillBytes() { - var orig = document.getElementById("origCode").value; - var newNum = orig.toString().match(/.{1,2}/g) + const origEl = document.getElementById("origCode"); + const calcEl = document.getElementById("calcCode"); + if (!origEl || !calcEl) return; + + const orig = origEl.value; + const newNum = orig.toString().match(/.{1,2}/g) || []; - //Set new length if (newNum.length > defaultByteSize) { defaultByteSize = newNum.length; - //Recreate byte table with new size createByteDescription(defaultByteSize); + wireByteEvents(); } - //Fill bytes to table - for (var i = 0; i < newNum.length; i++) { - document.getElementById("byte" + calculateByteIdFromNumber(i)).value = newNum[i]; + for (let i = 0; i < newNum.length; i++) { + const el = document.getElementById("byte" + calculateByteIdFromNumber(i)); + if (el) el.value = newNum[i]; } - //Fill calculated field - document.getElementById("calcCode").value = orig; - - //Select 0 byte by default + calcEl.value = orig; curSelectedByte = 0; } -function addLeadingZeros(binVal) { - var anz; - var retString = binVal; - - anz = 8 - binVal.length; - for (var i = 0; i < anz; i++) { - retString = "0" + retString; - } - return retString; -} - function fillDezAndBits(bin) { - for (var i = 0; i < 8; i++) { - document.getElementById("bit" + i).value = bin.substr(7 - i, 1); + for (let i = 0; i < 8; i++) { + const bit = document.getElementById("bit" + i); + if (bit) bit.value = bin.substr(7 - i, 1); } } function comparingOfBits(bin1, bin2) { - //return if values are equal - if (bin1 == bin2) { - return true; - } - - //Convert values to arrays and check by digits - let bin1a = bin1.split('').map(Number); - let bin2a = bin2.split('').map(Number); - - let equal = false; - for (var i = 0; i < bin2a.length; i++) { - if (bin2a[i] == 1){ - if (bin2a[i] == bin1a[i]) { - equal = true; - } else { - return false; - } - } - } - - return equal; + if (bin1 === bin2) return true; + + const bin1a = bin1.split("").map(Number); + const bin2a = bin2.split("").map(Number); + + let equal = false; + for (let i = 0; i < bin2a.length; i++) { + if (bin2a[i] === 1) { + if (bin2a[i] === bin1a[i]) { + equal = true; + } else { + return false; + } + } + } + return equal; } function calculateBitValue(binOld, binNew) { - //return if values are equal - if (binNew == binOld) { - return binNew; - } - - let binNewAr = binNew.split('').map(Number); - let binOldAr = binOld.split('').map(Number); - - for (var i = 0; i < binNewAr.length; i++) { - if (binNewAr[i] != binOldAr[i]) { - if (binNewAr[i] == 0) - document.getElementById("setModifiedBits" + (7 - i)).checked = false; - else - document.getElementById("setModifiedBits" + (7 - i)).checked = true; - chgBit(7 - i); - } - } + if (binNew === binOld) return binNew; + + const binNewAr = binNew.split("").map(Number); + const binOldAr = binOld.split("").map(Number); + + for (let i = 0; i < binNewAr.length; i++) { + if (binNewAr[i] !== binOldAr[i]) { + const idx = 7 - i; + const cb = document.getElementById("setModifiedBits" + idx); + if (cb) cb.checked = binNewAr[i] === 1; + chgBit(idx); + } + } } function fillBitCheckBoxes(bin, reduced) { - for (var i = 0; i < 8; i++) { - if (bin.substr(i, 1) == 0) - document.getElementById("setModifiedBits" + (7 - i)).checked = false; - else - document.getElementById("setModifiedBits" + (7 - i)).checked = true; - } - - //fill values - if (reduced != null) { - reduced.forEach(function(label) { - if (!isNaN(label.bit)) { - document.getElementById("setModifiedBitsLabel" + label.bit).innerHTML = " " + label.description; - } else { - //Create select box - var selectElement = document.createElement("select"); - selectElement.id = "select" + label.bit; - var variants = label.variants.split(';'); - for (var i = 0; i < variants.length; i++) - { - var variant = variants[i].split('-'); - var currentOption = comparingOfBits(bin, hexToBin(trim(variant[0]))); - var option = new Option (trim(variants[i]), trim(variant[0]), currentOption, currentOption); - selectElement.options[selectElement.options.length] = option; - } - document.getElementById("bitVariants").innerHTML = document.getElementById("bitVariants").innerHTML + label.description + " (bits " + label.bit + "): "; - document.getElementById("bitVariants").appendChild (selectElement); - document.getElementById("bitVariants").innerHTML = document.getElementById("bitVariants").innerHTML + "

"; - - let previous; - document.addEventListener('click', (event) => { - if (event.target && event.target.id == "select" + label.bit) { - previous = event.target.value; - } - }); - document.addEventListener('change', (event) => { - if (event.target && event.target.id == "select" + label.bit && previous != event.target.value) { - calculateBitValue(hexToBin(previous), hexToBin(event.target.value)); - } - }); - } - }); + for (let i = 0; i < 8; i++) { + const cb = document.getElementById("setModifiedBits" + (7 - i)); + if (cb) cb.checked = bin.substr(i, 1) === "1"; } - activateFields(); -} -function setByte(ctrl, byteName) { - //Check value - var regexp = /^[0-9a-fA-F]+$/; - if(regexp.test(ctrl.value)) { - } else { - alert(ctrl.value + ' - неверный формат введенного значения! Incorrect value!'); - ctrl.value = '00'; + const bitVariants = document.getElementById("bitVariants"); + if (bitVariants) bitVariants.innerHTML = ""; + + for (let j = 0; j < 8; j++) { + const label = document.getElementById("setModifiedBitsLabel" + j); + if (label) label.innerHTML = " Bit " + j; } - resetCalcCode(); - selByte(byteName); -} -function selByte(noByte) { + if (reduced && reduced.length) { + reduced.forEach(label => { + if (!label) return; - document.getElementById("Byte").innerHTML = "(Byte " + noByte + ")"; + if (!isNaN(label.bit)) { + const lab = document.getElementById("setModifiedBitsLabel" + label.bit); + if (lab) lab.innerHTML = " " + label.description; + } else { + if (!bitVariants) return; + + const wrapper = document.createElement("div"); + const text = document.createElement("span"); + text.textContent = label.description + " (bits " + label.bit + "): "; + + const selectElement = document.createElement("select"); + selectElement.id = "select" + label.bit; + + const variants = (label.variants || "").split(";"); + variants.forEach(vStr => { + const cleaned = trim(vStr); + if (!cleaned) return; + + const parts = cleaned.split("-"); + const hex = trim(parts[0] || ""); + const desc = trim(parts[1] || cleaned); + + const currentOption = comparingOfBits(bin, hexToBin(hex)); + + const opt = document.createElement("option"); + opt.value = hex; + opt.textContent = desc; + if (currentOption) opt.selected = true; + selectElement.appendChild(opt); + }); + + let previous = selectElement.value; + + selectElement.addEventListener("focus", e => { + previous = e.target.value; + }); + + selectElement.addEventListener("change", e => { + const newVal = e.target.value; + if (previous !== newVal) { + calculateBitValue(hexToBin(previous), hexToBin(newVal)); + previous = newVal; + } + }); + + wrapper.appendChild(text); + wrapper.appendChild(selectElement); + wrapper.appendChild(document.createElement("br")); + wrapper.appendChild(document.createElement("br")); + bitVariants.appendChild(wrapper); + } + }); + } - var bitValueHex = ""; - var fullBitString = ""; - var startPos = noByte * 2; + activateFields(); +} + +function selByte(noByte) { + const byteLabel = document.getElementById("Byte"); + if (byteLabel) byteLabel.innerHTML = "(Byte " + noByte + ")"; curSelectedByte = noByte; - bitValueHex = document.getElementById("calcCode").value.substr(startPos, 2); + const calcCode = document.getElementById("calcCode"); + if (!calcCode) return; + + const startPos = noByte * 2; + const bitValueHex = calcCode.value.substr(startPos, 2); - if (bitValueHex == "") { - //Clean bits and buttons + if (bitValueHex === "") { clearBits(); - for (var i = 0; i < 8; i++) { - document.getElementById("bit" + i).value = "0"; + for (let i = 0; i < 8; i++) { + const bit = document.getElementById("bit" + i); + if (bit) bit.value = "0"; } - return false; + toggleSelectedByteColor(noByte); + return; } - // hex2bin conversion - fullBitString = hexToBin(bitValueHex); + const fullBitString = hexToBin(bitValueHex); - //Find labels + let reduced = null; if (labelsFromFile != null) { - var reduced = labelsFromFile.reduce(function(filtered, option) { - let opt = option.split(','); - if (opt[0] == noByte) { - var labelValue = { byte: opt[0], bit: opt[1], description: opt[2], variants: opt[3] } - filtered.push(labelValue); - } - return filtered; - }, []); - } - - //Reset all labels in checkboxes - document.getElementById("bitVariants").innerHTML = ""; - for (var i = 0; i < 8; i++) { - document.getElementById("setModifiedBitsLabel" + i).innerHTML = " Bit " + i; + reduced = labelsFromFile.reduce((filtered, option) => { + const opt = option.split(","); + if (opt[0] == noByte) { + const labelValue = { + byte: opt[0], + bit: opt[1], + description: opt[2], + variants: opt[3] + }; + filtered.push(labelValue); + } + return filtered; + }, []); } - //Set new values fillDezAndBits(fullBitString); fillBitCheckBoxes(fullBitString, reduced); - toggleSelectedByteColor(noByte); } function chgBit(no) { - if (document.getElementById("setModifiedBits" + no).checked){ - document.getElementById("bit" + no).value = "1"; - } else { - document.getElementById("bit" + no).value = "0"; - } + const cb = document.getElementById("setModifiedBits" + no); + const bit = document.getElementById("bit" + no); + if (!cb || !bit) return; + bit.value = cb.checked ? "1" : "0"; setBits(); } -function resetCalcCode() { - var tmpVal = ""; - for (var i = 0; i < defaultByteSize; i++) { - tmpVal += document.getElementById("byte" + calculateByteIdFromNumber(i)).value; - } - document.getElementById("calcCode").value = trim(tmpVal); -} - -function resetByteHex(hexVal) { - document.getElementById("byte" + calculateByteIdFromNumber(curSelectedByte)).value = hexVal; - resetCalcCode(); -} - - function setBits() { - var tmpBitStr = ""; - for (var i = 7; i >= 0; i--) { - tmpBitStr += document.getElementById("bit" + i).value; + let tmpBitStr = ""; + for (let i = 7; i >= 0; i--) { + const bit = document.getElementById("bit" + i); + tmpBitStr += bit ? bit.value : "0"; } - var tmpVal; - var hexValue; + if (!tmpBitStr) return false; - if (tmpBitStr == "") { - return false; - } else { - tmpVal = parseInt(tmpBitStr, 2); - hexValue = from10toradix(tmpVal, 16) + const tmpVal = parseInt(tmpBitStr, 2); + let hexValue = from10toradix(tmpVal, 16); - if (hexValue.length == 1) { - hexValue = "0" + hexValue; - } else if (hexValue.length < 1) { - hexValue = "00"; - } + if (hexValue.length === 1) hexValue = "0" + hexValue; + else if (hexValue.length < 1) hexValue = "00"; - resetByteHex(hexValue); - selByte(curSelectedByte); - return true; - } + resetByteHex(hexValue); + selByte(curSelectedByte); + return true; } -function clearBits() { - //Clear bits fields - for (var i = 0; i < 8; i++) { - document.getElementById("bit" + i).value = ""; +function resetCalcCode() { + let tmpVal = ""; + for (let i = 0; i < defaultByteSize; i++) { + const el = document.getElementById("byte" + calculateByteIdFromNumber(i)); + if (el) tmpVal += el.value; } + const calcCode = document.getElementById("calcCode"); + if (calcCode) calcCode.value = trim(tmpVal); +} - //Clear checkboxes - for (var i = 0; i < 8; i++) { - document.getElementById("setModifiedBits" + i).checked = false; - } +function resetByteHex(hexVal) { + const el = document.getElementById("byte" + calculateByteIdFromNumber(curSelectedByte)); + if (el) el.value = hexVal; + resetCalcCode(); +} - //Reset all labels in checkboxes - for (var i = 0; i < 8; i++) { - document.getElementById("setModifiedBitsLabel" + i).innerHTML = " Bit " + i; +function clearBits() { + for (let i = 0; i < 8; i++) { + const bit = document.getElementById("bit" + i); + if (bit) bit.value = ""; + } + for (let j = 0; j < 8; j++) { + const cb = document.getElementById("setModifiedBits" + j); + if (cb) cb.checked = false; + const label = document.getElementById("setModifiedBitsLabel" + j); + if (label) label.innerHTML = " Bit " + j; } - document.getElementById("bitVariants").innerHTML = ""; + const bitVariants = document.getElementById("bitVariants"); + if (bitVariants) bitVariants.innerHTML = ""; } function clearFields() { - curSelectedByte = -1; - document.getElementById("Byte").innerHTML = ""; + const byteLabel = document.getElementById("Byte"); + if (byteLabel) byteLabel.innerHTML = ""; - //Clear bytes fields - for (var i = 0; i < defaultByteSize; i++) { - document.getElementById("byte" + calculateByteIdFromNumber(i)).value = ""; + for (let i = 0; i < defaultByteSize; i++) { + const el = document.getElementById("byte" + calculateByteIdFromNumber(i)); + if (el) el.value = ""; } clearBits(); - document.getElementById("calcCode").value = ""; + + const calcCode = document.getElementById("calcCode"); + if (calcCode) calcCode.value = ""; + defaultByteSize = 30; + createByteDescription(defaultByteSize); + wireByteEvents(); } function clearAll() { labelsFromFile = null; clearFields(); - document.getElementById("origCode").value = ""; - document.getElementById("bitDescription").style.display = "none"; - document.getElementById("langBits").value = "none"; + + const orig = document.getElementById("origCode"); + if (orig) orig.value = ""; + + const bitDescription = document.getElementById("bitDescription"); + if (bitDescription) bitDescription.style.display = "none"; + + const langBits = document.getElementById("langBits"); + if (langBits) langBits.value = "none"; + + const loading = document.getElementById("loading"); + if (loading) loading.style.display = "none"; } function clearLabels() { labelsFromFile = null; + clearBits(); + if (curSelectedByte >= 0) { + selByte(curSelectedByte); + } } function toggleSelectedByteColor(noByte) { - for (i = 0; i < defaultByteSize; i++) { - if (i != noByte) { - document.getElementById('byte' + calculateByteIdFromNumber(i)).className = 'byteNotSelected'; - } else { - document.getElementById('byte' + calculateByteIdFromNumber(i)).className = 'byteSelected'; - } + for (let i = 0; i < defaultByteSize; i++) { + const el = document.getElementById("byte" + calculateByteIdFromNumber(i)); + if (!el) continue; + el.className = i === noByte ? "byteSelected" : "byteNotSelected"; } } function selectAll(ctrl) { - ctrl.focus(); - ctrl.select(); + if (ctrl && typeof ctrl.select === "function") { + ctrl.select(); + } } function isBinary(event) { - var charCode = (event.which) ? event.which : event.keyCode - //0 = 48, 1 = 49 - if (charCode == 48 || charCode == 49 || charCode == 13) { - if (charCode == 13) - setBits(); + const charCode = event.which ? event.which : event.keyCode; + + const controlKeys = [8, 9, 13, 35, 36, 37, 39, 46]; + if (controlKeys.includes(charCode)) { + if (charCode === 13) setBits(); + return true; + } + + if (charCode === 48 || charCode === 49) { return true; - } else - return false; + } + + event.preventDefault(); + return false; } +// ========== Generation of html tables ========== + function createByteDescription(countOfBytes) { - var bytesPerLine = 30; - var html = ""; - html += ""; - html += "" - html += ""; + const container = document.getElementById("bytesDescription"); + if (!container) return; + + const bytesPerLine = 30; + const colsFirstLine = Math.min(countOfBytes, bytesPerLine); + const lines = Math.ceil(countOfBytes / bytesPerLine); + + let html = "
Байты / Bytes
"; + html += ""; + + for (let line = 0; line < lines; line++) { + const start = line * bytesPerLine; + const end = Math.min(start + bytesPerLine, countOfBytes); - //Lines can be several - for (var line = 0; line < Math.ceil(countOfBytes/bytesPerLine); line++){ html += ""; - for (var i = 0; i < bytesPerLine; i++) { - var current = bytesPerLine * line + i; - html += ""; + for (let i = start; i < end; i++) { + html += ""; } html += ""; - for (var i = 0; i < bytesPerLine; i++) { - var current = bytesPerLine * line + i; - var byteName = calculateByteIdFromNumber(current); + for (let j = start; j < end; j++) { + const byteName = calculateByteIdFromNumber(j); html += ""; + html += " class=\"byteNotSelected\" data-index=\"" + j + "\">"; + html += ""; } - html += ""; + html += ""; } html += "
Байты / Bytes
" + calculateByteIdFromNumber(current) + "" + calculateByteIdFromNumber(i) + "
"; html += "
"; - document.getElementById("bytesDescription").innerHTML = html; + container.innerHTML = html; } function createBitDescription() { - var html = ""; + const container = document.getElementById("bitDescription"); + if (!container) return; + + let html = "
"; html += ""; - html += " "; + html += ""; html += ""; html += ""; - html += "
"; - html += " Bits
"; - html += "
"; + html += "Bits
"; + html += "
"; - html += " "; - html += " "; + html += ""; html += ""; html += ""; html += "
"; + html += ""; + html += ""; - for (var i = 7; i >= 0; i--) { + for (let i = 7; i >= 0; i--) { html += ""; } - html += " "; - html += " "; + html += ""; - for (var i = 7; i >= 0; i--) { - html += ""; + for (let j = 7; j >= 0; j--) { + html += ""; } html += "
" + i + "
"; - for (var i = 0; i < 8; i++) { - html += ""; - html += "
"; + for (let k = 0; k < 8; k++) { + html += ""; + html += "
"; } html += "
"; - document.getElementById("bitDescription").innerHTML = html; + container.innerHTML = html; +} + +// ========== Events handling ========== + +function wireBitEvents() { + for (let i = 0; i < 8; i++) { + const bit = document.getElementById("bit" + i); + if (!bit) continue; + + bit.onkeydown = e => isBinary(e); + bit.onclick = () => selectAll(bit); + bit.onblur = () => setBits(); + } + + for (let j = 0; j < 8; j++) { + const cb = document.getElementById("setModifiedBits" + j); + if (!cb) continue; + cb.onclick = () => chgBit(j); + } +} + +function wireByteEvents() { + const container = document.getElementById("bytesDescription"); + if (!container) return; + + container.addEventListener("click", e => { + const target = e.target; + if (!target || target.tagName !== "INPUT") return; + if (!target.id || !target.id.startsWith("byte")) return; + + const index = parseInt(target.getAttribute("data-index"), 10); + if (Number.isNaN(index)) return; + + selByte(index); + selectAll(target); + }); + + container.addEventListener("change", e => { + const target = e.target; + if (!target || target.tagName !== "INPUT") return; + if (!target.id || !target.id.startsWith("byte")) return; + + const index = parseInt(target.getAttribute("data-index"), 10); + if (Number.isNaN(index)) return; + + setByte(target, index); + }); +} + +function setByte(ctrl, byteIndex) { + const regexp = /^[0-9a-fA-F]*$/; + if (!regexp.test(ctrl.value)) { + alert(ctrl.value + " - неверный формат введенного значения! Incorrect value!"); + ctrl.value = "00"; + } else { + ctrl.value = ctrl.value.toUpperCase(); + } + resetCalcCode(); + selByte(byteIndex); } \ No newline at end of file diff --git a/docs/assets/js/tiresGenerator.js b/docs/assets/js/tiresGenerator.js index 5b615e11..663932d0 100644 --- a/docs/assets/js/tiresGenerator.js +++ b/docs/assets/js/tiresGenerator.js @@ -1,441 +1,524 @@ +"use strict"; + function addToDataset(dataset, info) { - dataset.value += info; + dataset.value += info; } function generateHeader(dataset, docType, ecuName, ecuOffset) { - if (docType === "vcp") { - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "20103\n"); - addToDataset(dataset, "24\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "" + ecuName + "\n"); - addToDataset(dataset, "DFN_HEX\n"); - addToDataset(dataset, "" + ecuOffset + "\n"); - addToDataset(dataset, "0x0800\n"); - addToDataset(dataset, ""); - } else if (docType === "odis") { - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, ""); - } else { - addToDataset(dataset, "\n\nERROR! Unknown docType (" + docType + ")\n\n"); - } + if (docType === "vcp") { + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "20103\n"); + addToDataset(dataset, "24\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "" + ecuName + "\n"); + addToDataset(dataset, "DFN_HEX\n"); + addToDataset(dataset, "" + ecuOffset + "\n"); + addToDataset(dataset, "0x0800\n"); + addToDataset(dataset, ""); + } else if (docType === "odis") { + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset( + dataset, + "" + ); + } else { + addToDataset(dataset, "\n\nERROR! Unknown docType (" + docType + ")\n\n"); + } } function generateFooter(dataset, docType) { - if (docType === "vcp") { - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - } else if (docType === "odis") { - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - addToDataset(dataset, "\n"); - } else { - addToDataset(dataset, "\n\nERROR! Unknown docType\n\n"); - } + if (docType === "vcp") { + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + } else if (docType === "odis") { + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + addToDataset(dataset, "\n"); + } else { + addToDataset(dataset, "\n\nERROR! Unknown docType\n\n"); + } } function appendType(byteStream, ecuType) { - let type = parseInt(ecuType, 16); - - byteStream.push(type); + const type = parseInt(ecuType, 16); + byteStream.push(Number.isNaN(type) ? 0x00 : type); } function appendSetName(byteStream, setName) { - byteStream.push(setName.length); + let name = String(setName || ""); + let length = name.length; + + if (length > 60) { + name = name.substring(0, 60); + length = name.length; + } - for (let index = 0; index < setName.length; index++) - byteStream.push(setName.charCodeAt(index)); + byteStream.push(length); - for (let index = setName.length; index < 61; index++) - byteStream.push(0x00); + for (let i = 0; i < length; i++) { + byteStream.push(name.charCodeAt(i)); + } + + for (let i = length; i < 61; i++) { + byteStream.push(0x00); + } } function calcPressureValue(pressureStr) { - if (pressureStr.length === 0) - return 0xFF; + let trimmed = (pressureStr || "").trim(); + if (trimmed.length === 0) return 0xFF; + + trimmed = trimmed.replace(",", "."); + const val = parseFloat(trimmed); + + if (Number.isNaN(val)) return 0xFF; - return Math.round(parseFloat(pressureStr) * 10); + let scaled = Math.round(val * 10); + if (scaled < 0) scaled = 0; + if (scaled > 0xFF) scaled = 0xFF; + return scaled; } function appendSetPressure(byteStream, ecuName, pressureValues) { - if (ecuName === "3AA907273H") { - byteStream.push(calcPressureValue(pressureValues.frontPartial)); - byteStream.push(calcPressureValue(pressureValues.frontFull)); - byteStream.push(calcPressureValue(pressureValues.frontComfort)); - byteStream.push(calcPressureValue(pressureValues.rearPartial)); - byteStream.push(calcPressureValue(pressureValues.rearFull)); - byteStream.push(calcPressureValue(pressureValues.rearComfort)); - } else { - byteStream.push(calcPressureValue(pressureValues.frontFull)); - byteStream.push(calcPressureValue(pressureValues.frontPartial)); - byteStream.push(calcPressureValue(pressureValues.frontComfort)); - byteStream.push(calcPressureValue(pressureValues.rearFull)); - byteStream.push(calcPressureValue(pressureValues.rearPartial)); - byteStream.push(calcPressureValue(pressureValues.rearComfort)); - } + if (ecuName === "3AA907273H") { + byteStream.push(calcPressureValue(pressureValues.frontPartial)); + byteStream.push(calcPressureValue(pressureValues.frontFull)); + byteStream.push(calcPressureValue(pressureValues.frontComfort)); + byteStream.push(calcPressureValue(pressureValues.rearPartial)); + byteStream.push(calcPressureValue(pressureValues.rearFull)); + byteStream.push(calcPressureValue(pressureValues.rearComfort)); + } else { + byteStream.push(calcPressureValue(pressureValues.frontFull)); + byteStream.push(calcPressureValue(pressureValues.frontPartial)); + byteStream.push(calcPressureValue(pressureValues.frontComfort)); + byteStream.push(calcPressureValue(pressureValues.rearFull)); + byteStream.push(calcPressureValue(pressureValues.rearPartial)); + byteStream.push(calcPressureValue(pressureValues.rearComfort)); + } } function appendTireSet(byteStream, ecuName, tireSet) { - for (let index = 0; index < 61; index++) - byteStream.push(0x00); + for (let i = 0; i < 61; i++) { + byteStream.push(0x00); + } - appendSetName(byteStream, tireSet.name); - appendSetPressure(byteStream, ecuName, tireSet); + appendSetName(byteStream, tireSet.name); + appendSetPressure(byteStream, ecuName, tireSet); - for (let index = 0; index < 6; index++) - byteStream.push(0x00); + for (let i = 0; i < 6; i++) { + byteStream.push(0x00); + } } function appendVersion(byteStream, ecuVersion) { - let version1 = ecuVersion.charCodeAt(0); - let version2 = ecuVersion.charCodeAt(1); + const v = String(ecuVersion || ""); + const version1 = v.charCodeAt(0) || 0x00; + const version2 = v.charCodeAt(1) || 0x00; - byteStream.push(version1); - byteStream.push(version2); + byteStream.push(version1); + byteStream.push(version2); } function appendCRC(byteStream) { - let lookupTable = []; - - for (let index = 0; index < 256; index++) { - let c = index; + const lookupTable = []; - for (let k = 0; k < 8; k++) - c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1); + for (let i = 0; i < 256; i++) { + let c = i; - lookupTable[index] = c; + for (let k = 0; k < 8; k++) { + c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1); } - let crc = 0xFFFFFFFF; + lookupTable[i] = c; + } - for (let index = 0; index < byteStream.length; index++) - crc = (crc >>> 8) ^ lookupTable[(crc ^ byteStream[index]) & 0xFF]; + let crc = 0xFFFFFFFF; - crc = crc ^ 0xFFFFFFFF; + for (let i = 0; i < byteStream.length; i++) { + crc = (crc >>> 8) ^ lookupTable[(crc ^ byteStream[i]) & 0xFF]; + } - byteStream.push((crc >>> 24) & 0xFF); - byteStream.push((crc >>> 16) & 0xFF); - byteStream.push((crc >>> 8) & 0xFF); - byteStream.push(crc & 0xFF); + crc = crc ^ 0xFFFFFFFF; + + byteStream.push((crc >>> 24) & 0xFF); + byteStream.push((crc >>> 16) & 0xFF); + byteStream.push((crc >>> 8) & 0xFF); + byteStream.push(crc & 0xFF); } function generateDataset(ecuName, ecuType, ecuVersion, tireSets) { - let byteStream = []; + const byteStream = []; - appendType(byteStream, ecuType); - byteStream.push(0x00); + appendType(byteStream, ecuType); + byteStream.push(0x00); - for (let index = 0; index < 11; index++) - appendTireSet(byteStream, ecuName, tireSets[index]); + for (let i = 0; i < 11; i++) { + appendTireSet(byteStream, ecuName, tireSets[i]); + } - for (let index = 0; index < 555; index++) - byteStream.push(0xFF); + for (let i = 0; i < 555; i++) { + byteStream.push(0xFF); + } - appendVersion(byteStream, ecuVersion); - appendCRC(byteStream); + appendVersion(byteStream, ecuVersion); + appendCRC(byteStream); - return byteStream; + return byteStream; } function generateBody(dataset, ecuName, ecuType, ecuVersion, tireSets) { - let byteStream = generateDataset(ecuName, ecuType, ecuVersion, tireSets); + const byteStream = generateDataset(ecuName, ecuType, ecuVersion, tireSets); - for (let index = 0; index < byteStream.length; index++) { - let str = byteStream[index].toString(16).toUpperCase(); + for (let i = 0; i < byteStream.length; i++) { + let str = byteStream[i].toString(16).toUpperCase(); - if (str.length < 2) - str = '0' + str; + if (str.length < 2) { + str = "0" + str; + } - if (index > 0) - addToDataset(dataset, ",0x" + str); - else - addToDataset(dataset, "0x" + str); + if (i > 0) { + addToDataset(dataset, ",0x" + str); + } else { + addToDataset(dataset, "0x" + str); } + } } function doGenerate() { + const numTireSetsRaw = document.getElementById("numTireSets").value; + let numTireSets = parseInt(numTireSetsRaw, 10); + if (Number.isNaN(numTireSets)) numTireSets = 0; + + if (numTireSets < 1) { + window.alert("Количество комплектов шин должно быть больше 0.\nNumber of tire sets should be greater than 0."); + return; + } + + const dataset = document.getElementById("dataset"); + dataset.value = ""; + + const docType = document.getElementById("docType").value; + const ecuObj = document.getElementById("ecuModel"); + const ecuOptions = ecuObj.options[ecuObj.selectedIndex]; + const ecuName = ecuOptions.text; + const ecuOffset = ecuOptions.getAttribute("ecuOffset"); + const ecuVersion = ecuOptions.getAttribute("ecuVersion"); + const ecuType = ecuOptions.getAttribute("ecuType"); + + const tireSets = []; + + for (let index = 1; index <= 11; index++) { + const table = document.getElementById("t" + index); + const isHidden = table.hasAttribute("hidden"); + + if (isHidden) { + tireSets.push({ + name: "", + frontFull: "", + rearFull: "", + frontPartial: "", + rearPartial: "", + frontComfort: "", + rearComfort: "" + }); + } else { + const nameValue = document.getElementById("t" + index + "name").value; - let numTireSets = document.getElementById("numTireSets").value; - if (numTireSets < 1) { - window.alert("Количество комплектов шин должно быть больше 0.\nNumber of tire sets should be greater than 0."); + if (!/^[a-zA-Z]+$/.test(nameValue)) { + window.alert( + "Имя конфигурации #" + index + " может содержать только латинские буквы.\n" + + "Configuration name should have only latin symbols." + ); return; - } - - let dataset = document.getElementById('dataset'); - dataset.value = ""; - - let docType = document.getElementById('docType').value; - let ecuObj = document.getElementById('ecuModel'); - let ecuOptions = ecuObj.options[ecuObj.selectedIndex]; - let ecuName = ecuOptions.text; - let ecuOffset = ecuOptions.getAttribute('ecuOffset'); - let ecuVersion = ecuOptions.getAttribute('ecuVersion'); - let ecuType = ecuOptions.getAttribute('ecuType'); - - let tireSets = []; - - for (let index = 1; index <= 11; index++) { - if (document.getElementById("t" + index).hasAttribute("hidden")) { - let set = { - name: "", - frontFull: "", - rearFull: "", - frontPartial: "", - rearPartial: "", - frontComfort: "", - rearComfort: "" - }; - - tireSets.push(set); - } else { - let value = document.getElementById("t" + index + "name").value; - if (!/^[a-zA-Z]+$/.test(value)) { - window.alert("Имя конфигурации #" + index + " может содержать только латинские буквы.\nConfiguration name should have only latin symbols."); - return; - } - let set = { - name: value, - frontFull: document.getElementById("t" + index + "pff").value, - rearFull: document.getElementById("t" + index + "prf").value, - frontPartial: document.getElementById("t" + index + "pfp").value, - rearPartial: document.getElementById("t" + index + "prp").value, - frontComfort: document.getElementById("trcomfort" + index).hasAttribute("hidden") ? "" : document.getElementById("t" + index + "pfc").value, - rearComfort: document.getElementById("trcomfort" + index).hasAttribute("hidden") ? "" : document.getElementById("t" + index + "prc").value - }; - - tireSets.push(set); - } - } + } - if (docType === "binary") { - let byteStream = generateDataset(ecuName, ecuType, ecuVersion, tireSets); + const comfortHidden = document.getElementById("trcomfort" + index).hasAttribute("hidden"); - for (let index = 0; index < byteStream.length; index++) { - if ((index % 16) === 0) { - if (index > 0) - addToDataset(dataset, "\n"); + const set = { + name: nameValue, + frontFull: document.getElementById("t" + index + "pff").value, + rearFull: document.getElementById("t" + index + "prf").value, + frontPartial: document.getElementById("t" + index + "pfp").value, + rearPartial: document.getElementById("t" + index + "prp").value, + frontComfort: comfortHidden ? "" : document.getElementById("t" + index + "pfc").value, + rearComfort: comfortHidden ? "" : document.getElementById("t" + index + "prc").value + }; - let offset = index.toString(16).toUpperCase(); - - while (offset.length < 4) - offset = '0' + offset; + tireSets.push(set); + } + } - addToDataset(dataset, offset + " "); - } + if (docType === "binary") { + const byteStream = generateDataset(ecuName, ecuType, ecuVersion, tireSets); - let value = byteStream[index].toString(16).toUpperCase(); + for (let i = 0; i < byteStream.length; i++) { + if ((i % 16) === 0) { + if (i > 0) addToDataset(dataset, "\n"); - if (value.length < 2) - value = '0' + value; + let offset = i.toString(16).toUpperCase(); + while (offset.length < 4) offset = "0" + offset; + addToDataset(dataset, offset + " "); + } - addToDataset(dataset, value + " "); - } + let value = byteStream[i].toString(16).toUpperCase(); + if (value.length < 2) value = "0" + value; - return new Uint8Array(byteStream); - } else { - generateHeader(dataset, docType, ecuName, ecuOffset); - generateBody(dataset, ecuName, ecuType, ecuVersion, tireSets); - generateFooter(dataset, docType); + addToDataset(dataset, value + " "); + } - let byteStream = new Uint8Array(dataset.value.length); + return new Uint8Array(byteStream); + } else { + generateHeader(dataset, docType, ecuName, ecuOffset); + generateBody(dataset, ecuName, ecuType, ecuVersion, tireSets); + generateFooter(dataset, docType); - Array.prototype.forEach.call(dataset.value, function(character, index) { - byteStream[index] = character.charCodeAt(0); - }); + const text = dataset.value; + const byteStreamXml = new Uint8Array(text.length); - return byteStream; + for (let i = 0; i < text.length; i++) { + byteStreamXml[i] = text.charCodeAt(i); } + + return byteStreamXml; + } } function doGenerateDl() { - let content = doGenerate(); - let blob = new Blob([content], { - type: "application/octet-stream" - }); - - let element = window.document.createElement('a'); - - if ('download' in element) { - let docType = document.getElementById('docType').value; - let ecuObj = document.getElementById('ecuModel'); - let ecuOptions = ecuObj.options[ecuObj.selectedIndex]; - let ecuName = ecuOptions.text; - let ext = (docType === "binary") ? ".bin" : ".xml"; - - element.href = window.URL.createObjectURL(blob); - element.download = ecuName + ext; - document.body.appendChild(element); - element.click(); - document.body.removeChild(element); - } else { - let fileReader = new FileReader(); - - fileReader.onload = function() { - location.href = this.result; - }; - - fileReader.readAsDataURL(blob); - } + const content = doGenerate(); + if (!content) return; + + const blob = new Blob([content], { type: "application/octet-stream" }); + const element = window.document.createElement("a"); + + if ("download" in element) { + const docType = document.getElementById("docType").value; + const ecuObj = document.getElementById("ecuModel"); + const ecuOptions = ecuObj.options[ecuObj.selectedIndex]; + const ecuName = ecuOptions.text; + const ext = (docType === "binary") ? ".bin" : ".xml"; + + element.href = window.URL.createObjectURL(blob); + element.download = ecuName + ext; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + } else { + const fileReader = new FileReader(); + fileReader.onload = function () { + location.href = this.result; + }; + fileReader.readAsDataURL(blob); + } } function generatePD(id) { - let html = ""; + let html = ""; - html += ""; + html += ""; - for (let index = 0; index < 36; index++) - html += ""; + for (let index = 0; index < 36; index++) { + html += ""; + } - html += ""; + html += ""; - return html; + return html; } function updateTireSets() { - let numTireSets = document.getElementById("numTireSets").value; - let enableIndividual = document.getElementById("enableIndividual").checked; - let enableComfort = document.getElementById("enableComfort").checked; - - for (let index = 1; index <= 11; index++) { - let table = document.getElementById("t" + index); - let br1 = document.getElementById("br1" + index); - let trcomfort = document.getElementById("trcomfort" + index); - - if ((!((index === 11) && (enableIndividual))) && (index > numTireSets)) { - table.setAttribute("hidden", ""); - br1.setAttribute("hidden", ""); - } else { - table.removeAttribute("hidden"); - br1.removeAttribute("hidden"); - } - - if (enableComfort) - trcomfort.removeAttribute("hidden"); - else - trcomfort.setAttribute("hidden", ""); + const numTireSetsRaw = document.getElementById("numTireSets").value; + let numTireSets = parseInt(numTireSetsRaw, 10); + if (Number.isNaN(numTireSets)) numTireSets = 0; + + const enableIndividual = document.getElementById("enableIndividual").checked; + const enableComfort = document.getElementById("enableComfort").checked; + + for (let index = 1; index <= 11; index++) { + const table = document.getElementById("t" + index); + const br1 = document.getElementById("br1" + index); + const trcomfort = document.getElementById("trcomfort" + index); + + const shouldShowThisSet = + ((index === 11) && enableIndividual) || + (index <= numTireSets); + + if (shouldShowThisSet) { + table.removeAttribute("hidden"); + br1.removeAttribute("hidden"); + } else { + table.setAttribute("hidden", ""); + br1.setAttribute("hidden", ""); + } + + if (enableComfort) { + trcomfort.removeAttribute("hidden"); + } else { + trcomfort.setAttribute("hidden", ""); } + } } function createTireSets() { - let html = ""; - - for (let index = 1; index <= 11; index++) { - html += " "; - html += " "; - - if (index === 11) - html += " "; - else - html += " "; - - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += " "; - html += "
Индивидуальная настройка давления в шинах / Tire set IndividualНастройка давления в шинах / Tire set: #" + index + "
Имя
Тип загрузки машины / Load situationПередние колеса / Front wheelsЗадние колеса / Rear wheels
Полная загрузка / Full load" + generatePD("t" + index + "pff") + "" + generatePD("t" + index + "prf") + "
Стандартная загрузка / Standard load" + generatePD("t" + index + "pfp") + "" + generatePD("t" + index + "prp") + "
Комфортная загрузка / Comfort load" + generatePD("t" + index + "pfc") + "" + generatePD("t" + index + "prc") + "
"; - html += "
"; + let html = ""; + + for (let index = 1; index <= 11; index++) { + html += " "; + html += " "; + + if (index === 11) { + html += " "; + } else { + html += " "; } - document.getElementById("tireSetList").innerHTML = html; - updateTireSets(); + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += " "; + html += "
Индивидуальная настройка давления в шинах / Tire set IndividualНастройка давления в шинах / Tire set: #" + index + "
Имя
Тип загрузки машины / Load situationПередние колеса / Front wheelsЗадние колеса / Rear wheels
Полная загрузка / Full load" + generatePD("t" + index + "pff") + "" + generatePD("t" + index + "prf") + "
Стандартная загрузка / Standard load" + generatePD("t" + index + "pfp") + "" + generatePD("t" + index + "prp") + "
Комфортная загрузка / Comfort load" + generatePD("t" + index + "pfc") + "" + generatePD("t" + index + "prc") + "
"; + html += "
"; + } + + document.getElementById("tireSetList").innerHTML = html; + updateTireSets(); } let configVersion = "1.0"; -let configFields = [ - "docType", "ecuModel", "numTireSets", "@enableIndividual", "@enableComfort", - "t1name", "t1pff", "t1prf", "t1pfp", "t1prp", "t1pfc", "t1prc", - "t2name", "t2pff", "t2prf", "t2pfp", "t2prp", "t2pfc", "t2prc", - "t3name", "t3pff", "t3prf", "t3pfp", "t3prp", "t3pfc", "t3prc", - "t4name", "t4pff", "t4prf", "t4pfp", "t4prp", "t4pfc", "t4prc", - "t5name", "t5pff", "t5prf", "t5pfp", "t5prp", "t5pfc", "t5prc", - "t6name", "t6pff", "t6prf", "t6pfp", "t6prp", "t6pfc", "t6prc", - "t7name", "t7pff", "t7prf", "t7pfp", "t7prp", "t7pfc", "t7prc", - "t8name", "t8pff", "t8prf", "t8pfp", "t8prp", "t8pfc", "t8prc", - "t9name", "t9pff", "t9prf", "t9pfp", "t9prp", "t9pfc", "t9prc", - "t10name", "t10pff", "t10prf", "t10pfp", "t10prp", "t10pfc", "t10prc", - "t11name", "t11pff", "t11prf", "t11pfp", "t11prp", "t11pfc", "t11prc" +const configFields = [ + "docType", "ecuModel", "numTireSets", "@enableIndividual", "@enableComfort", + "t1name", "t1pff", "t1prf", "t1pfp", "t1prp", "t1pfc", "t1prc", + "t2name", "t2pff", "t2prf", "t2pfp", "t2prp", "t2pfc", "t2prc", + "t3name", "t3pff", "t3prf", "t3pfp", "t3prp", "t3pfc", "t3prc", + "t4name", "t4pff", "t4prf", "t4pfp", "t4prp", "t4pfc", "t4prc", + "t5name", "t5pff", "t5prf", "t5pfp", "t5prp", "t5pfc", "t5prc", + "t6name", "t6pff", "t6prf", "t6pfp", "t6prp", "t6pfc", "t6prc", + "t7name", "t7pff", "t7prf", "t7pfp", "t7prp", "t7pfc", "t7prc", + "t8name", "t8pff", "t8prf", "t8pfp", "t8prp", "t8pfc", "t8prc", + "t9name", "t9pff", "t9prf", "t9pfp", "t9prp", "t9pfc", "t9prc", + "t10name", "t10pff", "t10prf", "t10pfp", "t10prp", "t10pfc", "t10prc", + "t11name", "t11pff", "t11prf", "t11pfp", "t11prp", "t11pfc", "t11prc" ]; function loadConfig() { - - let result = window.prompt("Восстановление конфигурации. Load configuration\n\nПожалуйста введите код, созданный ранее в данном приложении.\nPlease enter configuration code, created earlier with this tool", ""); - - if (result === null) + const result = window.prompt( + "Восстановление конфигурации. Load configuration\n\n" + + "Пожалуйста введите код, созданный ранее в данном приложении.\n" + + "Please enter configuration code, created earlier with this tool", + "" + ); + + if (result === null) return; + + let code; + try { + code = window.atob(result); + } catch (e) { + window.alert("Введён некорректный код конфигурации (не base64).\nInvalid configuration code."); + return; + } + + const keyValue = code.split("&"); + + for (let i = 0; i < keyValue.length; i++) { + const data = keyValue[i].split("="); + + if (data.length !== 2) continue; + + if (data[0] === "configVersion") { + if (data[1] !== configVersion) { + window.alert( + "Введенный код конфигурации не может может быть восстановлен\n" + + "Configuration was created using an incompatible version of this tool and can not be restored\n\n" + + "Created version: " + data[1] + "\nCurrent version: " + configVersion + ); return; - - let code = window.atob(result); - let keyValue = code.split("&"); - - for (let index = 0; index < keyValue.length; index++) { - let data = keyValue[index].split("="); - - if (data.length !== 2) - continue; - - if (data[0] === "configVersion") { - if (data[1] !== configVersion) { - window.alert("Введенный код конфигурации не может может быть восстановлен\nConfiguration was created using an incompatible version of this tool and can not be restored\n\nCreated version: " + data[1] + "\nCurrent version: " + configVersion); - return; - } - } else if (data[0].charAt(0) === '@') - document.getElementById(data[0].substr(1)).checked = (data[1] === "true"); - else - document.getElementById(data[0]).value = data[1]; + } + } else if (data[0].charAt(0) === "@") { + const idCheck = data[0].substr(1); + const elCheck = document.getElementById(idCheck); + if (elCheck) { + elCheck.checked = (data[1] === "true"); + } + } else { + const el = document.getElementById(data[0]); + if (el) { + el.value = data[1]; + } } + } - updateTireSets(); + updateTireSets(); } function saveConfig() { - let code = "configVersion=" + configVersion + "&"; + let code = "configVersion=" + configVersion + "&"; - for (let index = 0; index < configFields.length; index++) { - if (configFields[index].charAt(0) === '@') - code += configFields[index] + "=" + document.getElementById(configFields[index].substr(1)).checked + "&"; - else - code += configFields[index] + "=" + document.getElementById(configFields[index]).value + "&"; + for (let i = 0; i < configFields.length; i++) { + const fieldName = configFields[i]; + + if (fieldName.charAt(0) === "@") { + const idCheck = fieldName.substr(1); + const elCheck = document.getElementById(idCheck); + code += fieldName + "=" + (elCheck ? elCheck.checked : false) + "&"; + } else { + const el = document.getElementById(fieldName); + code += fieldName + "=" + (el ? el.value : "") + "&"; } + } + + const encoded = window.btoa(code); - window.prompt("Сохранить настройки. Save configuration\n\nПожалуйста, сохраните код, приведённый ниже. Он может быть использован для восстановления настроек в любое время.\nPlease backup the configuration code below, it can be used to restore the current configuration at a later point in time.", window.btoa(code)); + window.prompt( + "Сохранить настройки. Save configuration\n\n" + + "Пожалуйста, сохраните код, приведённый ниже. Он может быть использован для восстановления настроек в любое время.\n" + + "Please backup the configuration code below, it can be used to restore the current configuration at a later point in time.", + encoded + ); } -window.onload = function() { - createTireSets(); -} \ No newline at end of file +window.onload = function () { + createTireSets(); +}; diff --git a/docs/assets/js/xor.js b/docs/assets/js/xor.js index 57639aeb..6301ccfc 100644 --- a/docs/assets/js/xor.js +++ b/docs/assets/js/xor.js @@ -1,39 +1,44 @@ - let decodeString = "c9d2"; - let codeLength = 4; - - function init() { - - //Read variables - const urlParams = new URLSearchParams(window.location.search); - - //Read parameter - const codeParam = urlParams.get('code'); - - if (codeParam != null) { - document.getElementById("origCode").value = codeParam; - calculateXor(); - } - } - - function calculateXor() { - let input = document.getElementById("origCode").value; - let result = '' - if (input.length % 2 !== 0) { - alert("Вводимое значение должно содержать четное количество символов.\nInput HEX value should have odd count of symbols"); - return - } - if (input.length !== codeLength) { - alert("Длина вводимого значения должна быть " + codeLength + " символа.\nInput HEX value should be no longer than " + codeLength + " characters."); - return - } - for (let index = 0; index < 4; index++) { - const temp = (parseInt(input.charAt(index), 16) ^ parseInt(decodeString.charAt(index), 16)).toString(16).toUpperCase() - result += temp - } - document.getElementById("calcCode").value = result; - } - - function clearAll() { - document.getElementById("origCode").value = ""; - document.getElementById("calcCode").value = ""; - } \ No newline at end of file +let decodeString = "c9d2"; +let codeLength = 4; + +function init() { + const urlParams = new URLSearchParams(window.location.search); + const codeParam = urlParams.get('code'); + + if (codeParam) { + document.getElementById("origCode").value = codeParam; + calculateXor(); + } +} + +function calculateXor() { + let input = document.getElementById("origCode").value.trim(); + let result = ''; + + if (input.length !== codeLength) { + alert( + "Длина вводимого значения должна быть " + codeLength + " символа.\n" + + "Input HEX value must be exactly " + codeLength + " characters long." + ); + return; + } + + if (!/^[0-9a-fA-F]+$/.test(input)) { + alert("Допустимы только HEX символы (0-9, A-F).\nOnly HEX characters (0-9, A-F) are allowed."); + return; + } + + for (let index = 0; index < codeLength; index++) { + const a = parseInt(input.charAt(index), 16); + const b = parseInt(decodeString.charAt(index), 16); + const temp = (a ^ b).toString(16).toUpperCase(); + result += temp; + } + + document.getElementById("calcCode").value = result; +} + +function clearAll() { + document.getElementById("origCode").value = ""; + document.getElementById("calcCode").value = ""; +} diff --git a/docs/history.md b/docs/history.md index 8d486cce..7b69fc62 100644 --- a/docs/history.md +++ b/docs/history.md @@ -3,6 +3,12 @@ comments: false --- # История изменений +### 10.12.2025 +1. Обновлен UI +2. Добавлены новые кодировки для ряда платформ +3. Обновлены кодировки, исправлено множество ошибок +4. Исправлены скрипты для работы с утилитами + ### 21.02.2025 1. Обновление файла кодировки камеры A5 2q diff --git a/mkdocs.yml b/mkdocs.yml index d0aebc70..e978c620 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,7 +2,7 @@ site_name: Кодирование автомобилей VAG site_description: Основные кодировки и адаптации платформ концерна VAG. Прошивки и параметрии. SWaP коды site_author: VWCODING -site_url: http://www.vwcoding.ru +site_url: https://vwcoding.ru/ # Hot news hot_news_title: Все ваши предложения и новые идеи можно присылать на info@vwcoding.ru diff --git a/overrides/pages/fec.html b/overrides/pages/fec.html index f4e2de9f..bdd9060f 100644 --- a/overrides/pages/fec.html +++ b/overrides/pages/fec.html @@ -296,6 +296,5 @@

Generated codes

- \ No newline at end of file