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秒)

f:id:m_rai:20200819205340p:plain

※たぶん /etc/phpmyadmin/config.secret.inc.php に設定してもできる

windows 10 home に wsl2 をインストール

修理に出したPCの windows のバージョンが最新になってた。 windows update で配信されるまでダウンロードしないで待っていたのだが仕方ない。

wsl2 をインストールできる条件 (Ver.2004、ビルド19041以降) を満たしていたので導入する。

スタート → 設定 → システム → バージョン情報
f:id:m_rai:20200803203948p:plain

手順

windows の機能の有効化または無効化の一覧にある
以下にチェックを入れて再起動
f:id:m_rai:20200803204723p:plain
f:id:m_rai:20200803204816p:plain

コマンドで上記と同じことをしたいなら、管理者権限の PowerShell にて
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

再起動後

Linux カーネル (コンポーネント) をダウンロードして更新

docs.microsoft.com

更新後

管理者権限の PowerShell にて現在の設定 (wsl) を wsl2 に変更
wsl --set-default-version 2

あとは Microsoft Store で Linux ディストリビューションを導入するだけ。

おまけ
導入したディストリビューション一覧確認コマンド

wsl --list --verbose