diff --git a/Changelog.md b/Changelog.md index cbe5f48..61f5a2e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -179,3 +179,5 @@ __*Why "v3.0.0" instead of "v1.0.0?"*__ Prior to phpMussel v3, the "phpMussel Co [2023.12.12; Maikuolan]: Split the code for most of the various front-end pages, which the view method was responsible for, into their own distinct files. [2023.12.26; Maikuolan]: Refactored the page greeting. + +[2023.12.29; Bug-fix; Maikuolan]: Some of the more unusual available number formatting choices (e.g., choices not using base-10 or Arabic numerals) didn't mesh well with the JavaScript code responsible for using them; Fixed. diff --git a/assets/numberJs.js b/assets/numberJs.js new file mode 100644 index 0000000..a6353f5 --- /dev/null +++ b/assets/numberJs.js @@ -0,0 +1,109 @@ +/** + * JavaScript version of Maikuolan\Common\NumberFormatter's format method. + * Formats the supplied number according to definitions. + * + * @param {any} Number The number to format (int, float, string, etc). + * @param {number} Decimals The number of decimal places (optional). + * @returns {string} The formatted number, or an empty string on failure. + */ +function nft(Number, Decimals = 0) { + let ConversionSet = JSON.parse('%s'); + let GroupSeparator = '%s'; + let GroupSize = %s; + let GroupOffset = %s; + let DecimalSeparator = '%s'; + let Base = %s; + if (Base < 2 || Base > 36) { + return ''; + } + var DecPos = String(Number).indexOf('.'); + let Fraction; + if (DecPos !== -1) { + if (Decimals > 0 && DecimalSeparator && !ConversionSet['.']) { + Fraction = (String(Number).substring(DecPos + 1)) || ''; + let Len = Fraction.length; + if (Len > 0) { + Fraction = convertFraction(Fraction, 10, Base, Decimals); + Fraction = Fraction.substring(0, Decimals); + Len = Fraction.length; + } + if (Len < Decimals) { + Fraction += '0'.repeat(Decimals - Len); + } + } + Number = String(Number).substring(0, DecPos); + } else { + Number = String(Number); + } + if (Base !== 10) { + Number = parseInt(Number).toString(Base); + } + let Formatted = ''; + let WholeLen = -1; + if (typeof ConversionSet['=' + Number] != 'undefined') { + Formatted = ConversionSet['=' + Number]; + WholeLen = -1; + } else { + WholeLen = Number.length; + } + let ThouPos = GroupOffset; + for (let Unit = 0, Pos = WholeLen - 1; Pos > -1; Pos--, Unit++) { + if (ThouPos >= GroupSize) { + ThouPos = 1; + Formatted = GroupSeparator + Formatted; + } else { + ThouPos++; + } + var Key = Number.substring(Pos, Pos + 1); + var Double = (Pos > 0) ? Number.substring(Pos - 1, Pos) + Key : ''; + let Power = ''; + let Digit = ''; + if (typeof ConversionSet['^' + Unit + '+' + Double] != 'undefined') { + Digit = ConversionSet['^' + Unit + '+' + Double]; + } else if (typeof ConversionSet['^' + Unit + '+' + Key] != 'undefined') { + Digit = ConversionSet['^' + Unit + '+' + Key]; + } else if (typeof ConversionSet['+' + Key] != 'undefined') { + Digit = ConversionSet['+' + Key]; + } else { + Digit = (typeof ConversionSet[Key] != 'undefined') ? ConversionSet[Key] : Key; + if (typeof ConversionSet['^' + Unit + '*' + Key] != 'undefined') { + Power = ConversionSet['^' + Unit + '*' + Key]; + } else if (typeof ConversionSet['^' + Unit] != 'undefined') { + Power = ConversionSet['^' + Unit]; + } + } + Formatted = Digit + Power + Formatted; + } + if (Fraction && Decimals && DecimalSeparator && !ConversionSet['.']) { + Formatted += DecimalSeparator; + for (let Pos = 0, Len = Fraction.length; Pos < Len; Pos++) { + var Key = Fraction.substring(Pos, Pos + 1); + let Power = ''; + let Digit = ''; + if (typeof ConversionSet['^-' + Pos + '+' + Key] != 'undefined') { + Digit = ConversionSet['^-' + Pos + '+' + Key]; + } else if (typeof ConversionSet['-+' + Key] != 'undefined') { + Digit = ConversionSet['-+' + Key]; + } else { + if (typeof ConversionSet['-' + Key] != 'undefined') { + Digit = ConversionSet['-' + Key]; + } else { + Digit = (typeof ConversionSet[Key] != 'undefined') ? ConversionSet[Key] : Key; + } + if (typeof ConversionSet['^-' + Pos + '*' + Key] != 'undefined') { + Power = ConversionSet['^-' + Pos + '*' + Key]; + } else if (typeof ConversionSet['^-' + Pos] != 'undefined') { + Power = ConversionSet['^-' + Pos]; + } + } + Formatted += Digit + Power; + } + } + var DecLen = DecimalSeparator.length; + if (DecLen && Formatted.substring(0, DecLen) === DecimalSeparator) { + Formatted = Formatted.substring(DecLen); + } + return Formatted; +} + +// https://chat.openai.com/c/2df8e967-edd7-471a-9eb5-23044aff6819 diff --git a/assets/default/scripts.js b/assets/scripts.js similarity index 99% rename from assets/default/scripts.js rename to assets/scripts.js index ce2795b..5f2e1b0 100644 --- a/assets/default/scripts.js +++ b/assets/scripts.js @@ -1,4 +1,3 @@ - function $(c,i,d,r,a,m){if('POST'===c||'GET'===c){var x=new XMLHttpRequest;x.onreadystatechange=function(){null!==r&&3==this.readyState&&200==this.status&&r(x.responseText),null!==a&&4==this.readyState&&200==this.status&&a(x.responseText),null!==m&&4==this.readyState&&200!==this.status&&m(x.responseText)},'POST'===c?x.open('POST',i,!0):x.open('GET',i,!0),x.responseType='text',null===d?x.send():(fd=new FormData,d.forEach(function(c){fd.append(c,null===window[c]?1:window[c])}),fd.append('ASYNC',1),x.send(fd))}} function showid(e){b=document.getElementById(e),b.style.display='inline'} function hideid(e){b=document.getElementById(e),b.style.display='none'} diff --git a/src/FrontEnd.php b/src/FrontEnd.php index ecba509..9d4bacc 100644 --- a/src/FrontEnd.php +++ b/src/FrontEnd.php @@ -8,7 +8,7 @@ * License: GNU/GPLv2 * @see LICENSE.txt * - * This file: Front-end handler (last modified: 2023.12.26). + * This file: Front-end handler (last modified: 2023.12.29). */ namespace phpMussel\FrontEnd; @@ -907,6 +907,11 @@ private function getAssetPath(string $Asset, bool $CanFail = false): string return $this->AssetsPath . 'default' . DIRECTORY_SEPARATOR . $Asset; } + /** Assets base directory. */ + if (is_readable($this->AssetsPath . $Asset)) { + return $this->AssetsPath . $Asset; + } + /** Failure. */ if ($CanFail) { return ''; @@ -915,31 +920,20 @@ private function getAssetPath(string $Asset, bool $CanFail = false): string } /** - * Generates JavaScript code for localising numbers locally. + * JavaScript code for localising numbers locally. * * @return string The JavaScript code. */ - private function numberJS(): string + private function numberJs(): string { - if ($this->NumberFormatter->ConversionSet === 'Western') { - $ConvJS = 'return l10nd'; - } else { - $ConvJS = 'var nls=[' . $this->NumberFormatter->getSetCSV( - $this->NumberFormatter->ConversionSet - ) . '];return nls[l10nd]||l10nd'; - } return sprintf( - 'function l10nn(l10nd){%4$s};function nft(r){var x=r.indexOf(\'.\')!=-1?' . - '\'%1$s\'+r.replace(/^.*\./gi,\'\'):\'\',n=r.replace(/\..*$/gi,\'\').rep' . - 'lace(/[^0-9]/gi,\'\'),t=n.length;for(e=\'\',b=%5$d,i=1;i<=t;i++){b>%3$d' . - '&&(b=1,e=\'%2$s\'+e);var e=l10nn(n.substring(t-i,t-(i-1)))+e;b++}var t=' . - 'x.length;for(y=\'\',b=1,i=1;i<=t;i++){var y=l10nn(x.substring(t-i,t-(i-' . - '1)))+y}return e+y}', - $this->NumberFormatter->DecimalSeparator, + $this->Loader->readFile($this->getAssetPath('numberJs.js')), + $this->NumberFormatter->getSetJSON($this->NumberFormatter->ConversionSet), $this->NumberFormatter->GroupSeparator, $this->NumberFormatter->GroupSize, - $ConvJS, - $this->NumberFormatter->GroupOffset + 1 + $this->NumberFormatter->GroupOffset, + $this->NumberFormatter->DecimalSeparator, + $this->NumberFormatter->Base ); } @@ -1263,7 +1257,7 @@ private function initialPrepwork(array &$FE, string $Title = '', string $Tips = $FE['FE_Tip'] = $this->Loader->parse([], $Tips); /** Load main front-end JavaScript data. */ - $FE['JS'] = $JS ? $this->Loader->readFile($this->getAssetPath('scripts.js')) : ''; + $FE['JS'] = $JS ? "\n" . $this->Loader->readFile($this->getAssetPath('scripts.js')) : ''; } /** diff --git a/src/pages/config.php b/src/pages/config.php index bc16ee3..e6f76ab 100644 --- a/src/pages/config.php +++ b/src/pages/config.php @@ -8,7 +8,7 @@ * License: GNU/GPLv2 * @see LICENSE.txt * - * This file: The configuration page (last modified: 2023.12.13). + * This file: The configuration page (last modified: 2023.12.29). */ namespace phpMussel\FrontEnd; @@ -21,7 +21,7 @@ $this->initialPrepwork($FE, $this->Loader->L10N->getString('link.Configuration'), $this->Loader->L10N->getString('tip.Configuration')); /** Append number localisation JS. */ -$FE['JS'] .= $this->numberJS() . "\n"; +$FE['JS'] .= $this->numberJs() . "\n"; /** Directive template. */ $ConfigurationRow = $this->Loader->readFile($this->getAssetPath('_config_row.html')); diff --git a/src/pages/siginfo.php b/src/pages/siginfo.php index 7e6b7b2..e1b4c87 100644 --- a/src/pages/siginfo.php +++ b/src/pages/siginfo.php @@ -8,7 +8,7 @@ * License: GNU/GPLv2 * @see LICENSE.txt * - * This file: The signature information page (last modified: 2023.12.13). + * This file: The signature information page (last modified: 2023.12.29). */ namespace phpMussel\FrontEnd; @@ -21,7 +21,7 @@ $this->initialPrepwork($FE, $this->Loader->L10N->getString('link.Signature Information'), $this->Loader->L10N->getString('tip.Signature Information')); /** Append number localisation JS. */ -$FE['JS'] .= $this->numberJS() . "\n"; +$FE['JS'] .= $this->numberJs() . "\n"; $FE['InfoRows'] = ''; $FE['SigInfoMenuOptions'] = '';