変奏現実

パソコンやMMORPGのことなどを思いつくまま・・・記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。

この画面は、簡易表示です

[javascript]varとlet

再宣言の差異は

再宣言可なvarと再宣言不可のlet。

どっちがいいのか微妙だけど、外部変数の宣言の場合には・・・

概ね宣言が被る方が困るので、letにしておこう。

尚、スコープの差異は

ブロックスコープなletの方が関数スコープのvarより使いやすい。

結論、varは要らない。



[JavaScript]配列のkeyとvalueの両方を使う

const createHtmlElement = (elementName, options) => {
・・・
・・・
  const rc = Object.keys(options).map(
    (key) => (chkOriginal(key) || chkStyle(key) || chkEvent(key) || setAttribute(key)));
  );
}

と書くと、呼び出された各処理で

function chkOriginal(key) {
  const value = options[key];
  ...
}
function chkStyle(key) {
  const value = options[key];
  ...
}
function chkEvent(key) {
  const value = options[key];
  ...
}
function setAttribute(key) {
  const value = options[key];
  ...
}

と書いてたけど・・・

const createHtmlElement = (elementName, options) => {
・・・
const chkOriginal = (key,value) => {
  ...
}
const chkStyle = (key,value) => {
  ...
}
const chkEvent = (key,value) => {
  ...
}
const setAttribute = (key,value) => {
  ...
}

・・・
  const rc = Object.keys(options).map(
    const value = options[key];
    (key) => (chkOriginal(key,value) || chkStyle(key,value) || chkEvent(key,value) || setAttribute(key,value)));
  );
}

としてみた。自分で書いたコードから、ローカル関数で元関数のパラメータを見ても特に支障は無いけど、functionを使わない書き方で統一できた。

MDNを見ると、mapでも第2パラメータ(thisArgs)が使えるみたいなので、

const rc = Object.keys(options).map(function (key) {
    const value = this[key];
    return chkOriginal(key, value) || chkStyle(key, value) || chkEvent(key, value) || setAttribute(key, value);
}, options);

としてみた。

本来はコールバックに特定のオブジェクトをthisとして引き渡したい場合に使うものだし、コールバックの中でoptionsを書きたくないと意地を張ったものの、optionsを2回書いてしまう事に変わりは無いので、無駄なthisArgsの使い方になってしまった。外部の変数を見てる怪しい部分も修正したら結果がコレ。

/**
 * HTMLエレメントを作成する
 * @param {string} elementName                              エレメント名
 * @param {{attributeName:,... eventName:,...}}} options    設定内容
 * @returns {HTMLElement}                                   作成したHTMLElement
 */
const createHtmlElement = (elementName, options) => {
    const fileName = 'js/lib/createHtmlElement.js';
    const funcName = 'createHtmlElement'; //debugLog(`${fileName}:${funcName}(elementName: ${elementName}, options)`);
    /**
     * 独自の処理が必要な場合
     * @param {} param      属性
     * @returns {boolean}   結果
     */
    const chkOriginal = (param) => {
        let rc = false;
        try {
            switch (param.name) {
                case 'className': // classNameはメソッドで、\x20で文字列を区切って複数の属性を指定できる
                case 'classList': // classListはメソッド
                    let v = param.value;
                    if (!Array.isArray(v)) { v = v.split('\x20'); }
                    param.element.classList.add(...v);  // 配列を展開してクラスリストに追加する
                    rc = true;
                    break;
                case 'innerHTML': // innerHTMLはメソッド扱い    ※未使用
                    param.element.innerHTML = param.value;
                    rc = true;
                    break;
                case 'innerText': // innerTextはメソッド扱い
                    param.element.innerText = param.value;
                    rc = true;
                    break;
                case 'parent':      // parentはメソッド
                    param.value.appendChild(param.element);
                    rc = true;
                    break;
                case 'appendChild': // appendChildはメソッド    ※未使用
                    param.element.appendChild(param.value);
                    rc = true;
                    break;
                case 'insertBefore':    // insertBeforeはメソッド   ※スクロール処理で座標の小さい方向へセルを作る際に使用
                    param.value.parentNode.insertBefore(param.element, param.value);
                    rc = true;
                    break;
            }   // end of switch
        } catch (ex) {
            debugLog(`${funcName}(elementName: ${elementName}) '${param.name}'属性の固有処理に失敗 '${ex}'`);
            rc = false;
        }
        return rc;
    };
    /**
     * スタイル属性の場合
     * @param {} param      属性
     * @returns {boolean}   結果
     */
    const chkStyle = (param) => {
        let rc;
        try {
            //  style-xxxxのキーの場合
            let styleChk = param.name.match(/^style_(.*)/);
            if (styleChk) {
                let styleName = styleChk[1];
                switch (styleName) {
                    case 'width':
                        param.element.style.width = param.value;
                        break;
                    case 'height':
                        param.element.style.height = param.value;
                        break;
                    default:
                        styleChk = null;
                        break;
                }   // end of switch
            }
            rc = styleChk !== null;
        } catch (ex) {
            debugLog(`${funcName}(elementName: ${elementName}) '${param.name}'スタイル属性に${param.value}を設定失敗 '${ex}'`);
            rc = false;
        }
        return rc;
    }
    /**
     * eventの場合
     * @param {} param      属性
     * @returns {boolean}   結果
     */
    const chkEvent = (param) => {
        let rc;
        try {
            const eventList = ['ended'];    // イベントリスト
            rc = eventList.includes(param.name);   // イベントリストに含まれているかどうか
            if (rc) {   // イベントリスナを登録する
                param.element.addEventListener(param.name, param.value);
            }
        } catch (ex) {
            debugLog(`${funcName}(elementName: ${elementName}) '${param.name}'イベントリスナの登録に失敗 '${ex}'`);
            rc = false;
        }
        return rc;
    }
    /**
     * HTMLエレメントに属性を追加する
     * @param {} param      属性
     * @returns {boolean}   結果
     */
    const setAttribute = (param) => {
        try {
            param.element.setAttribute(param.name, param.value);
            return true;
        } catch (ex) {
            debugLog(`${funcName}(elementName: ${elementName}) '${param.name}'属性に${param.value}を設定失敗 '${ex}'`);
            return false;
        }
    }
    let elm = document.createElement(elementName);
    //  optionsの設定名を取得しぶん回す!
    const rc = Object.keys(options).map(function (key) {
        const value = this[key];
        const param = { 'name': key, 'value': value, 'element': elm };
        return chkOriginal(param) || chkStyle(param) || chkEvent(param) || setAttribute(param);
    }, options)
        .filter(v => !v);   // trueならば削除する
    if (0 < rc.length) {
        debugLog(`${funcName}(elementName: ${elementName}) 未処理属性数:${rc.length}件`);
    }
    return elm;
}

数か月経つと

※未使用

と書かないと、「どこかで使っている(気がする」し、

※スクロール処理で座標の小さい方向へセルを作る際に使用

とか書いておかないと、「要らない(気がする」する、

なぜか、逆バイアスがかかってしまうのは・・・謎。

あ、使い方も忘れた。

こんな感じだった。

let a = createHtmlElement('a', {
    href: url,
    download: fileName,
    text: "re-download",
});

色々設定したいHTMLエレメントを作る時に

const div = createElement('div');
shadow.addChiled(div);
div.className = 'scroll';
div.id = `div${sn}`;
div.style.height = _spreadSheet.width;
div.style.width = _spreadSheet.height;
div.tabIndex =  `${sn}`;

を1行で書ける。更にそんなモノがいっぱいある場合には、

//  シャドールートを作成
_layout.shadowRoot = (!_layout.shadowRoot) ? _spreadSheet.customElement.attachShadow({ mode: "open" }) : _layout.shadowRoot;
const shadow = _layout.shadowRoot;
//  既存のHTMLElementを削除
Array.from(_layout.shadowRoot.children).forEach((ch) => ch.remove());
//  スタイルシート部
const style = _layout.createStyle(sn, _spreadSheet.rows, _spreadSheet.cols, true, true);
shadow.appendChild(style);
//  スプレッドシート部
_layout.divTableN = createHtmlElement('div', { parent: shadow, className: 'scroll', id: `div${sn}`, style_height: _spreadSheet.width, style_width: _spreadSheet.height, tabIndex: `${sn}`, });
_layout.tableN = await _layout.createTableElement(_layout.divTableN, 'spread-sheet', `table${sn}`);
_layout.divScrollX = createHtmlElement('div', { parent: _layout.divTableN, className: 'scroll-x', id: `divScrollX${sn}`, style_height: '17px', style_width: _spreadSheet.height, tabIndex: `${sn}`, });
_layout.divScrollY = createHtmlElement('div', { parent: _layout.divTableN, className: 'scroll-y', id: `divScrollY${sn}`, style_height: _spreadSheet.width, style_width: '17px', tabIndex: `${sn}`, });

と書け、すっきりする。

もっとも、インターネットの記事でそんなケースはまず有り得ないし、必要に応じてcreateHtmlElementの機能を増設していかないと「すっきり」しないので、仕事で作るソースにも使ったことはないね。

最初はcreateDivElementとかcreateAElementとかタグ毎に作っていたけど多すぎるので、createTableElementを除いて一本化した。

createTableElementみたいに複雑で同期を取る必要もあるモノは別物にするしかないが、コード全般の流れを単純化するとスッキリした。勿論、createTableElementの中のアチコチでcreateHtmlElementを呼び出している。

今見ると、イベント登録まで入れたのはやり過ぎ感があるなぁ。



[VScode1.93]プロファイルエディタ

メニューの「ファイル」で

「プロファイルを含む新しいウインドウ」⇒「新しいプロファイル…」を選択すると、

「新しいプロファイル」のウインドウが出るので

「v」⇒「テンプレートから」で、言語が色々選べる。

何に使うのかと云えば、チームでアプリを開発する際に、「プロファイルのインポート」で、同じプロファイルを使う様にすると開発環境(スニペや拡張機能のインストとか)を揃える手間が減るかもしれない。

でも、使い道がよく判りません。

画面左下の「設定(歯車)」の内容も随分増えてる。

訳が判らない。



[windows11]emscriptenのインスト

WebAssemblyを使いたくてemscriptenをインスト。

まずはcドライブのルートで「ターミナルを開く」。※最新PowerShellに連動済み

PowerShell 7.4.5
PS C:\> git clone https://github.com/emscripten-core/emsdk
Cloning into 'emsdk'...
remote: Enumerating objects: 4162, done.
remote: Counting objects: 100% (97/97), done.
remote: Compressing objects: 100% (76/76), done.
remote: Total 4162 (delta 47), reused 54 (delta 19), pack-reused 4065 (from 1)
Receiving objects: 100% (4162/4162), 2.38 MiB | 1.65 MiB/s, done.
Resolving deltas: 100% (2722/2722), done.
PS C:\> cd emsdk
PS C:\emsdk> ./emsdk.bat install latest
Resolving SDK alias 'latest' to '3.1.65'
Resolving SDK version '3.1.65' to 'sdk-releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'
Installing SDK 'sdk-releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'..
Installing tool 'node-18.20.3-64bit'..
Downloading: C:/emsdk/downloads/node-v18.20.3-win-x64.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v18.20.3-win-x64.zip, 30476796 Bytes
Unpacking 'C:/emsdk/downloads/node-v18.20.3-win-x64.zip' to 'C:/emsdk/node/18.20.3_64bit'
Done installing tool 'node-18.20.3-64bit'.
Installing tool 'python-3.9.2-nuget-64bit'..
Downloading: C:/emsdk/downloads/python-3.9.2-4-amd64+pywin32.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/python-3.9.2-4-amd64+pywin32.zip, 14413267 Bytes
Unpacking 'C:/emsdk/downloads/python-3.9.2-4-amd64+pywin32.zip' to 'C:/emsdk/python/3.9.2-nuget_64bit'
Done installing tool 'python-3.9.2-nuget-64bit'.
Installing tool 'java-8.152-64bit'..
Downloading: C:/emsdk/downloads/portable_jre_8_update_152_64bit.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/portable_jre_8_update_152_64bit.zip, 69241499 Bytes
Unpacking 'C:/emsdk/downloads/portable_jre_8_update_152_64bit.zip' to 'C:/emsdk/java/8.152_64bit'
Done installing tool 'java-8.152-64bit'.
Installing tool 'releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'..
Downloading: C:/emsdk/downloads/fdcf56c75a1d27fdff6525a7e03423595485ca19-wasm-binaries.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/fdcf56c75a1d27fdff6525a7e03423595485ca19/wasm-binaries.zip, 523605271 Bytes
Unpacking 'C:/emsdk/downloads/fdcf56c75a1d27fdff6525a7e03423595485ca19-wasm-binaries.zip' to 'C:/emsdk/upstream'
Done installing tool 'releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'.
Done installing SDK 'sdk-releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'.
PS C:\emsdk> ./emsdk.bat activate latest
Resolving SDK alias 'latest' to '3.1.65'
Resolving SDK version '3.1.65' to 'sdk-releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit'
Setting the following tools as active:
   node-18.20.3-64bit
   python-3.9.2-nuget-64bit
   java-8.152-64bit
   releases-fdcf56c75a1d27fdff6525a7e03423595485ca19-64bit

Next steps:
- Consider running `emsdk activate` with --permanent or --system
  to have emsdk settings available on startup.
Adding directories to PATH:
PATH += C:\emsdk
PATH += C:\emsdk\node\18.20.3_64bit\bin
PATH += C:\emsdk\upstream\emscripten

Setting environment variables:
PATH = C:\emsdk;C:\emsdk\node\18.20.3_64bit\bin;C:\emsdk\upstream\emscripten;C:\Program Files\WindowsApps\Microsoft.PowerShell_7.4.5.0_x64__8wekyb3d8bbwe;C:\app\[ユーザ名]\product\19.0.0\client_1;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\PROGRA~1\JPKI;C:\Program Files\Git\cmd;C:\Users\[ユーザ名]\AppData\Local\Microsoft\WindowsApps;C:\Users\[ユーザ名]\AppData\Local\Programs\Microsoft VS Code\bin
EMSDK = C:/emsdk
EMSDK_NODE = C:\emsdk\node\18.20.3_64bit\bin\node.exe
EMSDK_PYTHON = C:\emsdk\python\3.9.2-nuget_64bit\python.exe
JAVA_HOME = C:\emsdk\java\8.152_64bit
Clearing existing environment variable: EMSDK_PY
The changes made to environment variables only apply to the currently running shell instance. Use the 'emsdk_env.bat' to re-enter this environment later, or if you'd like to register this environment permanently, rerun this command with the option --permanent.

インストしたが、

PowerShell 7.4.5
PS C:\emsdk> emmake
emmake: The term 'emmake' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

環境変数を追加しないといけないらしい。

悩んだ末emcmdprompt.batの存在に気が付いた。

PowerShellじゃないけどね(笑

やっとコマンドが使えるようになったのでインスト完了。

どこのフォルダでも使える様にするには

emsdk activate --permanent or --system

で環境変数を直接書き換えてしまった方がいいだろう。(※未確認

さて、インストしたらどれくらいのサイズを使ったのかな?

なんてこったい!1.63GBもある!

node.jsとpythonとJavaも入っている様だから仕方が無いかな?



[Windows11,VScode]diagrams.net

旧名draw.ioの描画ツール。

MicrosoftStoreからインストールできファイル作成もテンプレ選択があるので使いやすい。

VScodeの拡張機能でもインスト可能だがいつものようにファイルの拡張子に連動してメニューが出る仕組みなので、まずdrawio拡張子でファイルを新規作成しなければ触ることすらできないし、一見するとテンプレは無い様に観えるが、メニューのの中にテンプレがある。

メニューのの「高度な設定」がなかなか奥が深い。

  • SQLを選択しCREATE TABLE文を入れるとDBのテーブルの図形が出る。
  • Marmaidを選択し、Marmaidのマークアップなテキストを貼り付けると、それらしい図形が出る。

スクラッチパッドがあるのであちこちに図形の組み合わせを複製するのが楽そう。

メニューのファイル>Exportから、svgやpngファイルに出力できるので、こんな感じの図形をブログの記事に埋め込むこともできるから使い道は結構ありそう。

欲を云えば、MS-WORDやMS-EXCELと線画のままコピペできたら便利そうだけど、どっちもインストしてないマシン(例えばスマホ等)で観れないだろうから、注意して取り扱わないといけない気がする。

MS-ExcelやGooleのSpreadSheetの図形や肝心な機能を制限してる無償ツールでUMLなシーケンス図描きに悩まさたのを思い出した。適材適所って重要だよね?(大笑



[Windows11]gitインスト

残念ながらStoreには無いので、公式のDownloadボタンでexeファイルをダウンンロード。

ここからは長い。基本Nextボタンで進めるが、

GitのエディタをVisualStudio Codeに変更する。

新規リポジトリ作成時のブランチの名前は手入力に変更する。

他への影響を抑えつつPowerShellからもgitを使えるようオプションを選択する。

シンボリックリンクも使えるオプションを追加で選択する。

で、インスト開始。

これでスタートの全てのアプリで見れるハズ。

このGit BashでGitでのデフォルトのアカウントを設定しておく。

git config --global user.name "ユーザー名"



[Windows11]PowerShellのアップグレードとその後

フォルダとかでターミナルを開くと

アップデートしよう!と毎回出てくる。

ちなみに今現在は・・・

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.22621.4111
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.4111
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

先のリンク先へジャンプすると・・・

Windows PowerShell 5.1 から PowerShell 7 への移行

のページが開くが、インストール方法s(msiファイルとかzipファイルとか…)の解説ページだった。

その中で一番簡単そうなのはMicrosoft Storeからのダウンロードだ。

Microsoft StoreでPowerShellを検索すると

表記されたバージョンが古いとおもったけど「4.2★」が、「人気度4.2」の意味だった。

アプリ名の下の数値は普通「人気度」なんだけど、

ツール系のアプリの場合はその前にバージョンを表記するのが普通だから・・・紛らわしい。

PowerShellのプレートにマウスをフォーカスすると、取得済み(アンスコした後なせいかな?)からインストールに変わるのでボタンを押す。

PowerShell 7.4.5
PS C:\Windows\System32> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.4.5
PSEdition                      Core
GitCommitId                    7.4.5
OS                             Microsoft Windows 10.0.22631
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

無事今の最新版になったのでこれでOK。

と思ったが、フォルダからターミナルで開くをすると古いまま。

スタート全てのアプリからPowerShellをスタートにピン止めしクリックすれば新しいバージョンが起動できるけど、他は古いまま。

サイドバイサイド(同じOSで新旧のバージョンがどっちも使える)だけどさぁ?

新旧どうやって使い分ければいいのかな?

ちなみに

環境変数PATHを確認してみるとC:\Program Files\PowerShell\7がありここにインストしたかのように見えるが、削除して再インスコしても出てこないので、これは過去のインスーラのせいな気がする。

実際には他のアプリ同様にC:\Users\[ユーザ名]\AppData\Local\Microsoft\WindowsAppsにpwsh.exeとしてインストされている。

Microsoft Windows [Version 10.0.22631.4112]
(c) Microsoft Corporation. All rights reserved.

C:\Users\[ユーザ名]>where pwsh.exe
C:\Users\[ユーザ名]\AppData\Local\Microsoft\WindowsApps\pwsh.exe

先のページではバージョン別の居場所は

Windows PowerShell 5.1$env:WINDIR\System32\WindowsPowerShell\v1.0
PowerShell 6.x$env:ProgramFiles\PowerShell\6
PowerShell 7$env:ProgramFiles\PowerShell\7
バージョン別の居場所

となっているが、C:\ProgramFiles\PowerShellなんてフォルダすらできてない。

C:\Windows\System32\WindowsPowerShell\v1.0にはpowershell.exeがあるのでこれが旧バージョンらしい。

Microsoft Windows [Version 10.0.22631.4112]
(c) Microsoft Corporation. All rights reserved.

C:\Users\[ユーザ名]>where powershell.exe
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

つまり、現在はEXEのファイル名で新旧バージョンを切り替えて使うのが良いのかもしれない。

と云う訳で、新版はターミナルでpwshで起動するのが一番簡単かな?

ターミナルのタイトルの「v」の設定の「新しいプロファイルを追加します」から

新バージョン用のプロファイルを作ってみた。

注意点としてはコマンドラインを指定する際に参照ボタンからpwsh.exe ファイルを探し出して開くボタンを押してしまうと

となってしまうので、見つけたpwsh.exeでパスのコピーでクリップボードに入れ、エントリーボックスに貼り付ける様にすることかな?

ついでに旧版のプロファイルの名前にバージョンを加えてみた。

最後に設定のスタートアップで新バージョンを指定した。

これで、フォルダのターミナルを開くで、すぐPowerShell新バージョンで使える。

とりあえずコレで良い???かな???????



日刊?週刊?Google Chromeアップデート

時々Google Chromeのセキュリティ・アップデートの記事を見るけど、多すぎない?

自動的にアップデートして欲しいけど、そうなると・・・

  • 起動する度に「アップデートを有効にするために再起動しますか?」が出る。
  • 「OK」押し、再起動
  • 振出しに戻る

たまに~~~的な状況もありそうだから、しないんだろうけど。

今時のペイントで①とか描くと円の上が切れるんだね(笑




top