IntersectionObserver 複数 バグ? スクロール
1つのオブザーバで複数のアイテムを監視する場合、(頭も)バグる
結論
2つのオブザーバで同じコンテナ内の異なるアイテムをそれぞれ1つずつ監視することで解決した
observer1.observe(document.querySelector(".container").firstElementChild) observer2.observe(document.querySelector(".container").lastElementChild);
失敗した例は observer 1つだけ
observer1.observe(document.querySelector(".container").firstElementChild) observer1.observe(document.querySelector(".container").lastElementChild)
関連記事
m-rai.hatenablog.com
m-rai.hatenablog.com
経緯
例えばスクロールコンテナ内のアイテムを1つのオブザーバで複数監視する
交差した時にアイテムに色を付与する
1つ目が交差したら赤、2つ目が…青、3つ目が…緑に色を変化させる
この時、
監視したアイテムをコンテナに収まるように設定し、複数のアイテムが全て見えている状態であれば問題なく動作する
アイテムそれぞれ、赤、青、緑である
しかしスクロールとは、見えないアイテムをスクロールして見るというものである
そのためアイテムをコンテナからはみ出すように設定すると、おかしな挙動をする
なぜか、全て赤になる
スクロールしても、しても、全て赤に染まる
DOMを調べてみると監視の対象が undefined になったり、異なるアイテムを監視していたり、モンスター化する
それ以外にもさんざん検証してみたが、書ききれない
全てのアイテムがコンテナに収まり見えている状態のDOMは正常だが、収まらず見えない状態になると突然発症するので制御不能
今回はスクロールアイテムの最初と最後のアイテムを監視し、クリックしてスクロールする機能である矢印ボタンの表示/非表示をしたかった
最初のアイテムが見えているなら preview 矢印を非表示にして、現在地より前にアイテムは存在しないという意図を伝える
次へスクロールしてアイテムが見えなくなったらそれを表示させ、アイテムが前に存在する意図へ変更する
最後のアイテムまでスクロールしたなら next 矢印を非表示にして、ここから先はアイテムが存在しない意図にするもの
無限スクロール infinite scroll 「intersection observer」
適当に実装してみた
option で渡す root は null の場合と任意の場合があるので場合分け
いずれもその viewport 内の最後の要素を監視
上にスクロールして戻る時は監視不要
よってその都度監視を停止して新しい監視を開始
class InfiniteScroller { Id = 0; constructor(option) { const observer = new IntersectionObserver( this.onIntersectedHandler.bind(this), option ); if (option.root === null) { observer.observe(document.querySelector('body').lastElementChild); } else { observer.observe(option.root.lastElementChild); } this.viewport = option.root; } // 交差したら呼ばれる async onIntersectedHandler(entries, observer) { const entry = entries[0]; if (entry.isIntersecting) { const contentList = await this.fetchContent(this.Id); this.appendArticle(contentList); observer.disconnect(); let newTarget; if (this.viewport === null) { newTarget = document.querySelector('body').lastElementChild; } else { newTarget = document.querySelector(`.${this.viewport.className}`) .lastElementChild; } observer.observe(newTarget); this.Id++; } } // コンテンツ追加 appendArticle(contentList) { let newViewport; if (this.viewport === null) { newViewport = document.querySelector('body'); } else { newViewport = document.querySelector(`.${this.viewport.className}`); } contentList.forEach((content) => { newViewport.insertAdjacentHTML( 'beforeend', `<article class="article"> <img class="article__img" src="sample.jpg"> <p>${JSON.parse(content)}</p> <article> ` ); }); } // コンテンツ取得 async fetchContent(Id) { try { const res = await fetch( `http://localhost?Id=${Id}` ); if (!res.ok) { throw new Error(res.status); } return await res.json(); } catch (err) { console.log(err); } } } export { InfiniteScroller };
【composer dump-autoload 効かない】Fatal error: Uncaught Error: Class 'XXX' not found
composer dump-autoload が効かない
composer dump-autoload --optimize が効かない
結論
プロジェクトのディレクトリ構造を全身全霊の力を持って強く意識して、それから composer.json を正しく記述する
composer.json
変更前 "autoload": { "psr-4": { "App\\": "app/" } 変更後 "autoload": { "psr-4": { "App\\": "code/app/" }
というのも、
autoload_psr4.php
$vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); 'App\\' => array($baseDir . '/app')
上記の $baseDir が指すものは
$baseDir = www
よって、$baseDir . '/app'
は www/app
である
ここで、プロジェクトのディレクトリ構造
www ├── code //プロジェクトルート │ ├── app │ ├── bootstrap │ ├── config │ ├── index.php │ └── src
www/app
は code をすっ飛ばしている
composer dump-autoload が効くはずなどないのだ
可及的速やかに www/code/app
にしなければならない
ゆえに
composer.json
"autoload": { "psr-4": { "App\\": "code/app/" }
git revert コンフリクト CONFLICT (modify/delete)
状態を確認
git status
git status -b
git status -sb
コマンドが実行可能か dry run してみる
git add -n .
git push -n origin main
本題
CONFLICT (modify/delete)
ファイル作成と同じファイルを更新のコミットがそれぞれ存在し
ファイル作成のコミットを revert した場合、更新と削除どちらかを選ぶ必要がある
現状として add, commit, push いずれもできる状態
git status -b
git status -sb
以下 git status -b の内容を参考に実施
あなたのブランチは 'origin/main' で最新の状態になっています。
あなたは現在コミット 48df9e3 をリバートしています。
(コンフリクトを修正して "git revert --continue" を実行してください)
(このパッチをスキップするには "git revert --skip" を使用します)
(revert 操作をキャンセルするには "git revert --abort" を使用します)マージされていないパス。
(unstage するには "git restore --staged..." を使用します)
(解決策をマークするには "git add/rm..." を適切に使用します)
彼らによって削除された:ファイルコミットに変更が加えられていません ("git add" や "git commit -a" を使用します)。
削除する場合
git rm ファイル名
削除の内容を add, commit (message: 削除), push する
⇒ 以下のようにログが残り、ファイルはなくなる
git log --graph --oneline
* f6bc160 (HEAD -> main, origin/main) 削除
* d4eddb7 更新
* 6cfcb68 作成
削除しない場合 (更新する)
add しても commit および continue ができない
commit ができない理由として
あなたのブランチは 'origin/main' より 2 コミット先行しています。
(ローカルでのコミットを公開するには "git push" を使用します。
なので push
再び continue してみるもできない
なので git revert --skip
スキップするとプロンプトの (main|REVERTING) が (main)になって
git status -b の表示もなくなる
結局 そのまま push する場合も
addして commit できなくて push する場合も
結果が同じである
アロー関数 this
javascript
アロー関数は this を持たず、レキシカルスコープの this を使用する
持たないことを束縛しないとも表現される
アロー関数をクロージャとして、エンクロージャがどこのスコープで宣言されたかで使用する this を決定する
エンクロージャが存在しなければ window オブジェクト
エンクロージャがオブジェクト内に宣言されていれば、そのレキシカルスコープの this = そのオブジェクト
※ただしエンクロージャが function の場合である
エンクロージャもアロー関数ならば this を持たなくなるからである
そこに function 、つまりエンクロージャのエンクロージャが存在しなければ存在するのは window オブジェクトである
補足: this 以外にもarguments, super, new.target を束縛しない
docker phpmyadmin config.inc.php でセッション変更
デフォルトの1440秒を変更したい
手順
/etc/phpmyadmin/config.inc.php をに以下を記述
$cfg['LoginCookieValidity'] = 秒数;
結果 (60秒)
※たぶん /etc/phpmyadmin/config.secret.inc.php に設定してもできる
windows 10 home に wsl2 をインストール
修理に出したPCの windows のバージョンが最新になってた。 windows update で配信されるまでダウンロードしないで待っていたのだが仕方ない。
wsl2 をインストールできる条件 (Ver.2004、ビルド19041以降) を満たしていたので導入する。
スタート → 設定 → システム → バージョン情報
手順
windows の機能の有効化または無効化の一覧にある
以下にチェックを入れて再起動
コマンドで上記と同じことをしたいなら、管理者権限の PowerShell にて
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
再起動後
Linux カーネル (コンポーネント) をダウンロードして更新
更新後
管理者権限の PowerShell にて現在の設定 (wsl) を wsl2 に変更
wsl --set-default-version 2
あとは Microsoft Store で Linux ディストリビューションを導入するだけ。
おまけ
導入したディストリビューション一覧確認コマンド
wsl --list --verbose