Javascript-1

=====================================================================================

<< BACK >>

=====================================================================================

then…catch

「非同期処理が終わった後に、次に何をするか」を予約するための仕組み。try…catchと似た動作を行うが、tryは動作が終了する前に次の動作へ移動するが、thenは終了するまで待つ。

書き方特徴
then / catch処理を数珠つなぎ(チェーン)にする書き方。古いコードやシンプルな処理に多い。
try / catch (+ async/await)非同期処理を、普通の(上から下へ流れる)コードのように書くモダンな書き方。

比較例(カメラ起動)

【then を使う場合】

navigator.mediaDevices.getUserMedia({video: true})
    .then(stream => {
        video.srcObject = stream;
    })
    .catch(e => {
        console.log("失敗");
    });

【try…catch (async) を使う場合】

async function start() {
    try {
        const stream = await navigator.mediaDevices.getUserMedia({video: true});
        video.srcObject = stream;
    } catch (e) {
        console.log("失敗");
    }
}

<< BACK >>

=====================================================================================

try…catch

「エラーが起きそうな場所を囲んで、もしエラーが起きてもプログラムを止めずに、別の処理(リカバリ)を行う」

1. 基本的な構造

try {
    // 【1】 実行したい処理
    // ここでエラーが発生すると、即座に catch へ飛びます。
} 
catch (e) {
    // 【2】 エラーが起きた時の処理
    // 変数 e には「何が起きたか」というエラー情報が入ります。
} 
finally {
    // 【3】 最後に必ず実行される処理(省略可能)
    // 成功しても失敗しても、共通で行いたい後片付けを書きます。
}

2. なぜ WebRTC で使う必要があるのか?

WebRTCでは、コードが正しくても「外的な要因」でエラーが頻発するためです。

  • カメラが使えない: ユーザーが拒否した、またはカメラが他のアプリで使われている。
  • ネットワーク断絶: 接続中にWi-Fiが切れた。
  • 古いブラウザ: 使おうとした関数が実装されていない。

<< BACK >>

=====================================================================================

「ビデオ映像のキャプチャ」→「Canvasへの描画」→「サーバーへのアップロード(保存)」

<!DOCTYPE html>
<html lang="ja">
<body>
    <video id="remoteVideo" autoplay playsinline style="width: 320px; border: 1px solid #ccc;"></video>
    <canvas id="snapshotCanvas" style="display: none;"></canvas>
    
    <br>
    <button onclick="captureAndUpload()">写真を撮ってサーバーに保存</button>

    <script>
        async function captureAndUpload() {
            const video = document.getElementById('remoteVideo');
            const canvas = document.getElementById('snapshotCanvas');
            const context = canvas.getContext('2d');

            // --- A. キャプチャ処理 ---
            // ビデオのサイズをCanvasに反映
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            
            // 現在のフレームを描画
            context.drawImage(video, 0, 0, canvas.width, canvas.height);

            // --- B. アップロード処理 ---
            // CanvasをBlob形式(バイナリファイル)に変換
            canvas.toBlob(async (blob) => {
                if (!blob) return;

                const formData = new FormData();
                // 'image' というキーでファイルをセット
                formData.append('image', blob, `snapshot_${Date.now()}.png`);

                try {
                    const response = await fetch('/upload-endpoint', { // ここにサーバーのURLを記述
                        method: 'POST',
                        body: formData
                    });

                    if (response.ok) {
                        const result = await response.json();
                        alert('保存に成功しました!');
                    } else {
                        alert('保存に失敗しました。');
                    }
                } catch (error) {
                    console.error('通信エラー:', error);
                }
            }, 'image/png');
        }
    </script>
</body>
</html>

1. キャンバスサイズの同期

canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
  • video.videoWidth / videoHeight とは:
       これはビデオ要素の表示サイズ(CSSで設定した幅)ではなく、ビデオ信号そのものの解像度
       (例:1280×720など)を指します。
  • なぜこれが必要か:
        Canvasには「描画領域」という概念があります。デフォルトでは 300×150 程度しかないため、
       この設定を行わないと、高画質なビデオを撮ってもCanvas側でトリミングされたり、逆に引き
       伸ばされて画質が劣化したりします。

2. 描画の実行

context.drawImage(video, 0, 0, canvas.width, canvas.height);

このメソッドが「シャッター」の役割を果たします。

  • 第1引数 (video):
      描画ソースです。HTML5の drawImage は、単なる画像だけでなく video 要素も受け取ることができます。
      この時、実行された瞬間のビデオフレームがソースとして採用されます。
  • 第2・第3引数 (0, 0):
      Canvas内のどこから描き始めるか(左上の座標)を指定します。
  • 第4・第5引数 (canvas.width, canvas.height):
      Canvas内のどのくらいの大きさで描くかを指定します。ここではCanvas全体いっぱいに描画
      するように設定しています。

3. 内部的なデータの流れ

このコードが実行されると、ブラウザの内部では以下のような「データのコピー」が行われます。

  1. GPU/ビデオメモリ:
      現在再生中のビデオの1コマがバッファに存在します。
  2. コピー:
      drawImage が呼ばれると、その1コマのピクセルデータ(RGB/RGBA値)が、Canvasが管理するメモリ空間
      (ビットマップ)へコピーされます。
  3. 固定化:
      ビデオは次の瞬間には別のフレームに変わりますが、Canvasにコピーされたデータは、
      次に上書きするまでそこに留まります。

4. 注意点:実行のタイミング

このコードを動かす際、以下の状態である必要があります。

  • ビデオが再生中であること:
      video.readyStateHAVE_CURRENT_DATA (2) 以上でないと、真っ黒な画像が生成されることがあります。
  • セキュリティ(CORS):
      もし WebRTC ではなく外部の URL から動画を読み込んでいる場合、サーバー側で許可(CORS設定)
      がないと、drawImage はできても、その後の「保存(Blob変換)」の段階でセキュリティエラー
      (汚染されたキャンバス)が発生します。

このコードの仕組み

  1. Canvasの非表示化:
      style="display: none;" を指定することで、ユーザーにはビデオだけを見せ、裏側で静止画を作成しています。
  2. Date.now() を使ったファイル名:
      サーバー側でファイルが上書きされないよう、タイムスタンプをファイル名に含めています。
  3. toBlob による効率化: 前述の通り、画像を文字列(Base64)ではなく「ファイル」として扱うため、通信が非常にスムーズです。

動作させるための注意点

  • /upload-endpoint:
      ここは実際のサーバー側のURLに書き換えてください。
  • WebRTC/カメラの起動:
      remoteVideo に映像が流れている状態(srcObject が設定されている状態)で実行してください。
  • CORS:
      フロントエンドとサーバーのドメインが異なる場合は、サーバー側でCORS許可設定が必要です。

video.readyState

状態(数値)の意味一覧

readyState0 から 4 までの整数値を返します。

定数名状態の解説
0HAVE_NOTHING情報が全くない。まだ何も読み込まれていない。
1HAVE_METADATAメタデータ完了。 幅・高さ・再生時間などの基本情報だけわかった状態。
2HAVE_CURRENT_DATA現在のコマあり。 今この瞬間の静止画は描画できるが、次のコマがない。
3HAVE_FUTURE_DATA少し先のデータもある。カクつくかもしれないが再生は可能。
4HAVE_ENOUGH_DATA準備万端。 最後までスムーズに再生できるだけのデータがある。

Google スプレッドシートにエクスポート


なぜキャプチャ時に重要なのか?

スナップショット(drawImage)を撮るためには、最低でも 2 (HAVE_CURRENT_DATA) 以上である必要があります。

もし、カメラを起動した瞬間に captureAndUpload() 関数が実行されてしまうと、まだ映像データがメモリに届いておらず、videoWidth0 だったり、中身が空っぽの画像がサーバーに送られたりしてしまいます。

async function captureAndUpload() {
    const video = document.getElementById('remoteVideo');
    const canvas = document.getElementById('snapshotCanvas');
    const context = canvas.getContext('2d');

    // 内部関数:実際の描画とアップロード処理
    const performCapture = async () => {
        // 1. 解像度の確定(readyStateが2以上なら正確な値が取れる)
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        
        // 2. Canvasへ描画
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        console.log("Canvasへの描画が完了しました");

        // 3. サーバーへの送信
        canvas.toBlob(async (blob) => {
            if (!blob) return;
            const formData = new FormData();
            formData.append('image', blob, `snapshot_${Date.now()}.png`);

            try {
                const response = await fetch('/upload-endpoint', {
                    method: 'POST',
                    body: formData
                });
                if (response.ok) alert('保存成功!');
            } catch (err) {
                console.error("アップロード失敗:", err);
            }
        }, 'image/png');
    };

    // --- readyStateによる分岐処理 ---
    if (video.readyState >= 2) {
        // すでに映像データがある場合は即実行
        await performCapture();
    } else {
        // まだデータがない場合は、'loadeddata'イベントを一度だけ待機
        console.log("映像データを待機中...");
        video.addEventListener('loadeddata', performCapture, { once: true });
    }
}

変更のポイント

  1. video.readyState >= 2 の条件分岐: 現在表示できるフレームがあるかどうかを確認します。これにより、真っ黒な画像(サイズ 0x0)が送られるのを防ぎます。
  2. loadeddata イベントの活用: もし準備ができていない場合、ブラウザが「最初のフレームを読み込んだよ!」と通知してくれるのを待ってから処理を続行します。
  3. { once: true } オプション: イベントリスナーが一度実行されたら自動的に削除されるようにし、メモリリークや二重実行を防いでいます。

<< BACK >>

=====================================================================================

Canvasでキャプチャした画像をサーバーにアップロード

1. クライアント側(JavaScript)の実装

Canvasのデータを Blob 形式に変換し、fetch APIを使って送信します。

function uploadImage() {
    var canvas = document.querySelector('canvas');

    // 1. CanvasをBlob(ファイルデータ)に変換
    canvas.toBlob(function(blob) {
        // 2. フォームデータを作成
        var formData = new FormData();
        formData.append('image', blob, 'snapshot.png'); // 名前、データ、ファイル名

        // 3. fetchでサーバーに送信
        fetch('/upload', { // サーバーのURL
            method: 'POST',
            body: formData
        })
        .then(response => response.json())
        .then(data => {
            console.log('アップロード成功:', data);
        })
        .catch(error => {
            console.error('エラー発生:', error);
        });
    }, 'image/png');
}

2. データの流れ(イメージ図)

このプロセスでは、メモリ上のピクセルデータがバイナリ形式にパッキングされ、HTTPリクエストのボディに乗ってサーバーへ運ばれます。


3. 注意点とアドバイス

  • toBlob の利点: かつては toDataURL(Base64文字列)を使う方法が主流でしたが、Base64は元のデータより
           サイズが約33%大きくなってしまいます。toBlob を使うことで、ネットワーク帯域を節約できます。
  • 画像の軽量化: もしサーバーのストレージを節約したい場合は、JPEG形式にして画質を調整することも可能です。
    • 例: canvas.toBlob(callback, 'image/jpeg', 0.8); (画質を80%に設定)
  • セキュリティ(CORS): サーバー側で、フロントエンドからのPOSTリクエストを許可するCORS設定が必要です。

4. サーバー側(Node.js/Expressの例)での受け取り

サーバー側では、multer などのライブラリを使ってファイルを受け取ります。

const express = require('express');
const multer  = require('multer');
const upload = multer({ dest: 'uploads/' }); // 保存先ディレクトリ
const app = express();

app.post('/upload', upload.single('image'), (req, res) => {
    console.log('保存されたファイル情報:', req.file);
    res.json({ message: 'アップロード完了!' });
});

この流れを実装すれば、Webカメラで撮ったスナップショットをそのままデータベースやクラウドストレージ(S3など)に保存できるようになります。

<< BACK >>

=====================================================================================

演算子

1. 算術演算子

演算子内容例 (x=10,y=3)
+加算(足し算)x+y→13
-減算(引き算)x−y→7
*乗算(掛け算)x∗y→30
/除算(割り算)x/y→3.33…
%剰余(余り)x%y→1
**べき乗(累乗)10∗∗3→1000

2. 代入演算子(変数に値を入れる)

  • = : 基本の代入(x = 10
  • += : 加算代入(x += 5x = x + 5 と同じ)
  • -= : 減算代入(x -= 2x = x - 2 と同じ)

3. 比較演算子(比べる)

演算子内容注意点
==等しい型変換が行われる('5' == 5 は真)
===厳密に等しい基本はこちらを使うべき。 型も一致しているか見る
!=等しくない
!==厳密に等しくない
>, <より大きい / 小さい
>=, <=以上 / 以下

4. 論理演算子(条件を組み合わせる)

  • && (AND / 論理積) : すべての条件が true なら true
  • || (OR / 論理和) : どれか1つでも true なら true
  • ! (NOT / 論理否定) : 真偽を反転させる(truefalse

5. その他の重要な演算子

  • インクリメント・デクリメント
    • x++ : x を 1 増やす
    • x-- : x を 1 減らす
  • 三項演算子 (条件演算子)
    • 条件 ? 真の場合の値 : 偽の場合の値
    • 例: const status = (age >= 20) ? "大人" : "子供";

<< BACK >>

=====================================================================================

新しい要素(<option>)の追加

1. new Option() を使う方法(おすすめ)

new Option(text, value, defaultSelected, selected) 。

第1引数 :
    テキスト(表示名) です。
    ブラウザの画面上でユーザーの目に触れる文字になります。

第2引数 :
    値(value属性) です。
    フォームを送信した際や、JavaScriptで select.value を取得したときに送られるデータです。

const select = document.getElementById('mySelect');

// 書き方:new Option(表示テキスト, 設定する値)
const newOp = new Option("新しい項目", "999");

// リストの最後に追加
select.add(newOp);

2. createElement を使う方法

const select = document.getElementById('mySelect');
const op = document.createElement('option');

op.text = "追加アイテム";
op.value = "val_123";

select.appendChild(op);

<< BACK >>

=====================================================================================

特定の項目を選択

1. 値(value)で選択する

select 要素の value プロパティに、選択したい optionvalue を代入するだけです。

const select = document.getElementById('mySelect');

// value="apple" の項目を選択状態にする
select.value = "apple";

2. インデックス(順番)で選択する

「上から◯番目」という指定方法です。0から数え始めます。

const select = document.getElementById('mySelect');

// 一番上の項目(0番目)を選択する
select.selectedIndex = 0;

// 何も選択されていない状態にする
select.selectedIndex = -1;

3. option 要素を直接操作して選択する

特定の条件に合うものを探して選択したい場合に使います。

const select = document.getElementById('mySelect');

// 全てのoptionの中から、テキストが "--- No File ---" のものを探して選択
for (let i = 0; i < select.options.length; i++) {
  if (select.options[i].text === "--- No File ---") {
    select.options[i].selected = true;
    break;
  }
}

4. 実践:fetchしたデータに初期選択を合わせる

サーバーからデータを読み込み、リストを作った後に「デフォルトで特定の項目を選んでおく」という一連の流れです。

async function loadAndSelect() {
  const select = document.getElementById('mySelect');
  
  // 1. fetchでデータ取得
  const res = await fetch("https://192.168.1.200/api/files");
  const files = await res.json();

  // 2. リストを構築
  select.innerHTML = "";
  files.forEach(file => {
    select.add(new Option(file.name, file.id));
  });

  // 3. 構築後に、IDが "123" のものを選択状態にする
  select.value = "123";
}

💡 注意点

  • valueが存在しない場合: select.value に存在しない値を代入しても、選択は変わりません(あるいは空の状態になります)。
  • 動的に追加した直後: add() で項目を追加した直後に value を設定しても反映されますが、HTMLが複雑な場合は await などで処理の順序を意識する必要がありま

<< BACK >>

=====================================================================================

特定の選択肢(<option>)を削除

1. インデックス(順番)を指定して削除する

指定した位置を消す

const select = document.getElementById('mySelect');

// 0番目(一番上)を削除
select.remove(0);

// 現在選択されている項目を削除
select.remove(select.selectedIndex);

2. 値(value)やテキストを指定して削除する

値 (value) で探して消す

const select = document.getElementById('mySelect');
const valueToRemove = "apple"; // 消したい値

for (let i = 0; i < select.options.length; i++) {
  if (select.options[i].value === valueToRemove) {
    select.remove(i);
    break; // 見つけたらループを抜ける
  }
}

3. 全ての要素を削除する(初期化)

const select = document.getElementById('mySelect');
select.innerHTML = "";

<< BACK >>

=====================================================================================

配列(Array)からプルダウンリスト()を作成

let itemList = ["リンゴ", "バナナ", "オレンジ", "メロン"];

function renderSelect() {
    const select = document.getElementById('mySelect');
    
    // 一旦、現在のプルダウンの中身を空にする(文字列としての代入)
    select.innerHTML = "";

    // 最新の配列を元に、optionタグを再構築
    itemList.forEach((item, i) => {
        const option = document.createElement('option');
        option.value = i;        // インデックスをvalueにする例
        option.textContent = item; // 表示名
        select.appendChild(option);
    });
    
    console.log("プルダウンを更新しました。現在のデータ:", itemList);
}

<< BACK >>

=====================================================================================

プルダウンリスト()からJavaScriptの配列(Array)を作る

1. 表示されている「テキスト」を配列にする

ユーザーに見えている項目名をすべて配列にまとめます。

const selectElement = document.getElementById('mySelect');

// selectElement.options(HTMLCollection)を配列に変換して抽出
const textArray = Array.from(selectElement.options).map(opt => opt.textContent);

console.log(textArray); 
// 例: ["リンゴ", "バナナ", "オレンジ"]

2. 設定されている「value(値)」を配列にする

サーバーに送信するための value 属性を配列にまとめます。

const valueArray = Array.from(selectElement.options).map(opt => opt.value);

console.log(valueArray);
// 例: ["apple", "banana", "orange"]

3. テキストと値を「オブジェクトの配列」にする

名前も値も両方保持しておきたい場合に最も便利な形です。

const objectArray = Array.from(selectElement.options).map(opt => {
    return {
        text: opt.textContent,
        val: opt.value
    };
});

console.log(objectArray);
// 例: [{text: "リンゴ", val: "apple"}, {text: "バナナ", val: "banana"}]

<< BACK >>

=====================================================================================

splice()

指定した位置から、指定した個数分だけ削除する。削除された後の配列は自動的に詰められます。

// 配列の準備
let fruits = ["リンゴ", "バナナ", "オレンジ", "メロン"];

// 2番目(インデックスは1)を削除して詰める
let n = 1; 
fruits.splice(n, 1);

console.log(fruits); // ["リンゴ", "オレンジ", "メロン"]

プルダウンリストとの連携

selectedIndex と組み合わせると、画面上の選択項目を削除して配列を更新する処理

const select = document.getElementById('mySelect');
const index = select.selectedIndex; // 選択された数値(N番目)

if (index !== -1) {
    // 1. 配列から削除して詰める
    myArray.splice(index, 1);
    
    // 2. 画面(プルダウン)からも削除して詰める
    select.remove(index); 
}

<< BACK >>

=====================================================================================

.onreadystatechange

XMLHttpRequest (XHR) オブジェクトで使用されるイベントハンドラ。通信の状態(リクエストが送られた、レスポンスが届いたなど)が変化するたびに呼び出されます。

1. 状態(readyState)の種類

通信の状態は readyState という数値で表されます。.onreadystatechange はこの数値が変わるたびに実行されます。

readyState の値状態内容
0 (UNSENT)未オープンopen() メソッドがまだ呼び出されていない。
1 (OPENED)オープンopen() が呼び出され、リクエストが準備中。
2 (HEADERS_RECEIVED)ヘッダ受信send() が呼ばれ、レスポンスヘッダを受信した。
3 (LOADING)受信中レスポンスの本体(データ)を受信中。
4 (DONE)完了通信がすべて完了した状態。

2. 基本的なコード例

通常、通信が「正常に完了(readyStateが4、かつステータスが200)」したときだけ処理を行いたい場合に以下のように書きます。

JavaScript

var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data", true);

// 状態が変化するたびに実行される
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) { // 通信完了
        if (xhr.status === 200) { // かつ、成功(OK)
            console.log("成功:", xhr.responseText);
        } else {
            console.log("エラー発生:", xhr.status);
        }
    }
};

xhr.send();

3. 注意点とモダンな書き方

現在は、.onreadystatechange よりも簡潔で分かりやすい onload イベントや、さらに新しい fetch() API を使うのが一般的です。

onload を使う場合(XHRの改善版)

readyState === 4 のチェックを省略できます。

JavaScript

xhr.onload = function() {
    if (xhr.status === 200) {
        console.log(xhr.responseText);
    }
};

fetch() を使う場合(現代の標準)

.onreadystatechange を使わずに、Promiseベースで非常に綺麗に書けます。

JavaScript

fetch("https://api.example.com/data")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error("失敗:", error));

<< BACK >>

=====================================================================================

.addEventListener

HTML内の特定の要素に対して、ユーザーの操作(クリックや入力など)を検知して特定の処理を実行させる

基本的な構文

const table = document.getElementById('v_table');
table.addEventListener('イベント名', function(event) {
    // ここに実行したい処理を書く
});

1. マウス系のイベント(最も一般的)

イベント名発生するタイミング
click左クリックしたとき
dblclickダブルクリックしたとき
mouseoverマウスカーソルが要素の上に乗ったとき
mouseoutマウスカーソルが要素から離れたとき
contextmenu右クリック(コンテキストメニュー)を開こうとしたとき

2. キーボード系のイベント

イベント名発生するタイミング
keydownキーを押し下げたとき
keyup押していたキーを離したとき
keypressキーを押している間(現在は keydown 推奨)

3. フォーム・編集系のイベント

イベント名発生するタイミング
input内容が変更されるたび(リアルタイム)
changeフォーカスが外れたときなどに、内容の変更が確定したとき
focus要素にフォーカスが当たったとき
blur要素からフォーカスが外れたとき

実装のヒント:イベントデリゲーション

v_table のようなテーブル要素の場合、各セル(<td>)一つひとつにイベントを設定するのは効率が悪いです。親である table に一つだけイベントを設定し、クリックされた場所を特定する方法が推奨されます。
JavaScript

const vTable = document.getElementById('v_table');

vTable.addEventListener('click', (event) => {
    // 実際にクリックされた要素(セルなど)を取得
    const target = event.target;

    // クリックされたのが <td> の場合のみ処理を実行
    if (target.tagName === 'TD') {
        console.log("セルの内容:", target.innerText);
        target.style.backgroundColor = "pink";
    }
});

<< BACK >>

=====================================================================================

await、then

どちらも非同期処理の結果が出るまで待つ。awaitの方が直感的で読みやすい。
awaitを使う関数には必ず「async」を付けるルールです

【await を使った書き方】
async function no_ret() {
  // fetchが終わるまでここで一時停止する
  await fetch('URL', { mode: 'no-cors' });
  
  // fetchが終わった後に実行される
  console.log("送信完了");
}

【then を使った書き方】
function no_ret() {
  fetch('URL', { mode: 'no-cors' })
    .then(res => {
      console.log("送信完了");
    });
}

<< BACK >>

=====================================================================================

ページ(HP)を維持しサーバーにGETする方法(返信無し)

ブラウザの標準的な動作 <a>タグや<form>タグは、サーバーからの返事を受け取ると、画面をその返事で「上書き」しようとします。現在のページ(HP)を維持したままサーバーにGETするにはFetch API を使う(最もモダンな方法)。fetch は非同期(Async)で動作するため、サーバーからの返信を待たずに次のコードを実行できます。

function no_ret() {
  fetch('http://192.168.1.200:8090/?1=_REC', { 
    method: 'GET',        // 明示的にGETと指定
    mode: 'no-cors',      // サーバー側の許可(CORS)がなくても送信だけは行う
    cache: 'no-cache',    // 古いデータを読み込まない
    credentials: 'omit'   // クッキーなどを送らない(エラー回避のため)
  })
  .then(() => {
    console.log("リクエスト送信に成功しました");
  })
  .catch(err => {
    // ここでエラーが出る場合は、ネットワークの物理的な遮断が疑われます
    console.error("ネットワークエラーが発生しました:", err);
  });
}
  • http://192.168.1.200:8090/ ー> サーバのアドレス
  • ?1=_REC ー>クエリ URLの末尾に「?」マークを付け、続けて「名前=値」の形式で記述する。
           値が複数あるときは「&」で区切り、続けて「名前=値」の形式で記述する。

クライアントが no-cors で送ってくるなら、サーバーは 「204を返して、さっさとコネクションを閉じる」
Pythonの場合
  self.send_response(204)
  self.end_headers()
と処理する。何を返しても不透明(Opaque)になる。

サーバーの返答ブラウザ(JS)から見た statusJavaScriptでの挙動
200 OK 0 (Opaque)不透明 .then() に入るが中身は空
204 No Content0 (Opaque) 不透明.then() に入るが中身は空
404 / 500 0 (Opaque)不透明.then() に入る(エラー扱いにならない!)
ネットワーク切断 (なし) .catch() に入る

end_headers() を忘れる:

ブラウザは「ヘッダーがいつ終わるか」をずっと待機し続け、タイムアウト(送信エラー)になります。

<< BACK >>

=====================================================================================

Content-Type一覧

種類説明
text/plainプレーンテキストデータ
text/htmlHTMLデータ
text/cssCSSデータ
text/javascriptJavaScriptデータ
application/jsonJSON形式のデータ
application/octet-stream任意のバイナリデータ(EXEなどの実行ファイル)
application/x-msgpackMessagepackデータ
application/xmlXML形式のデータ
application/x-www-form-urlencodedHTMLフォームからのデータ
multipart/form-dataファイルを含むフォームデータ
image/gifGIF画像データ
image/pngPNG画像データ
image/bmp汎用BMP画像データ
image/x-ms-bmpMS BMP画像データ
image/jpegJPEG画像データ
image/svg+xmlSVGファイル
audio/wavWAV音声データ
audio/mp3MP3音声データ
video/mpegMPEG動画データ
video/mp4MP4動画データ
application/pdfPDFドキュメントデータ
application/mswordWordドキュメントデータ
application/vnd.openxmlformats-officedocument.wordprocessingml.documentWordドキュメントデータ(.docx 2007以降)
application/vnd.ms-excelExcelドキュメントデータ
application/vnd.openxmlformats-officedocument.spreadsheetml.sheetExcelドキュメントデータ(.xlsx 2007以降)
application/vnd.ms-powerpointPowerPointドキュメントデータ
application/vnd.openxmlformats-officedocument.presentationml.presentationPowerPointドキュメントデータ(.pptx 2007以降)
application/octet-stream任意のバイナリデータ
application/gzipGzip圧縮データ
application/zipZIP圧縮データ
application/x-lzhLZHファイル
application/x-tartarファイル/tar&gzipファイル

<< BACK >>

=====================================================================================

changeイベント

<input>、<select>、<textarea>などのフォーム要素でユーザーが値を変更し、その変更が確定した(通常はフォーカスが外れた)ときに発生するイベント

  • 対象要素: <input type="text/checkbox/radio/file/date"><select><textarea>など。
  • 発火タイミング:
    • チェックボックス/ラジオボタン: チェックされた(またはチェック解除された)とき。
    • セレクトボックス: 選択肢が選ばれたとき。
    • テキスト系 (input, textarea): 値が変更された後、要素からフォーカスが外れたとき(例:別の場所をクリックしたとき)。
  • 用途: ユーザーの入力内容に基づいてリアルタイムでバリデーションを行う、選択された値に応じて表示内容を変える、などの処理。 

addEventListenerを使う

const myInput = document.getElementById('myInput');

myInput.addEventListener('change', (event) => {
  console.log('値が変更されました:', event.target.value);
});

HTMLのonchange属性を使う

<input type="text" id="myInput" onchange="handleChange(this.value)">
<script>
  function handleChange(value) {
    console.log('値が変更されました:', value);
  }
</script>

<< BACK >>

=====================================================================================

ポップアップメッセージ

alert()

メッセージを表示し「OK」ボタンで閉じます。情報通知や簡単な注意喚起。

alert("こんにちは!これはアラートメッセージです。");

confirm()

「OK」と「キャンセル」ボタンを表示し、どちらが押されたか(真偽値)を返します。確認処理

if (confirm("本当に削除しますか?")) {
    // OKが押された場合の処理
    console.log("削除実行");
} else {
    // キャンセルが押された場合の処理
    console.log("キャンセルされました");
}

prompt()

メッセージと入力欄を表示し、ユーザーの入力を文字列として返します。初期値も設定可能

let userName = prompt("お名前を入力してください:", "ゲスト");
if (userName) {
    alert("ようこそ、" + userName + "さん!");
}

<< BACK >>

=====================================================================================

(value)を設定してフォームを送信(submit)

type属性が “submit”の場合

<form method='get' id='file_op'>
      <button type='submit' name='name' id='v_del' onclick='f_del()' >Del</button>
</form> 

function f_del() {
    document.getElementById('v_del').value = 'abcdef';
}

Query:  ?name=abcdf

type属性を指定しないの場合

<form method='get' id='file_op'>
      <button name='name' id='v_del' onclick='f_del()' >Del</button>
</form> 

function f_del() {
    document.getElementById('v_del').value = 'abcdef';
    document.getElementById('file_op').submit();
}

Query:  ?name=abcdf

注) 関数名をidと同じにしない。

   <button type=’button’ id=’v_del‘ onclick=’v_del()’ >Del</button>  ー> NG
   <button type=’button’ id=’v_del‘ onclick=’f_del()’ >Del</button>  ー> OK

<< BACK >>

=====================================================================================

ファイルをダウンロード

サーバにあるmp4ファイルをダウンロード

function downloadVideo() {
  const videoUrl = 'your-video-file.mp4'; // Replace with the actual URL
  const link = document.createElement('a');
  link.href = videoUrl;
  link.setAttribute('download', 'my_downloaded_video.mp4'); // Suggests a filename
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

<< BACK >>

=====================================================================================

選択されているoptionのインデックス(0から始まる番号)を取得

<select name="mySelect">
  <option value="apple">りんご</option>
  <option value="banana" selected>バナナ</option> // ← これがデフォルトで選択される
  <option value="orange">みかん</option>
</select>

const selectElement = document.getElementById('mySelect');
console.log(selectElement.selectedIndex); // バナナなら 1 が出力される

<< BACK >>

=====================================================================================

ドロップダウンリストで選択された項目をリストの一番上に移動

<select id="mySelect" onchange="moveToTop(this)">
    <option value="option1">Option 1</option>
    <option value="option2">Option 2</option>
    <option value="option3">Option 3</option>
    <option value="option4">Option 4</option>
</select>

function moveToTop(selectElement) {
    // 現在選択されているオプション要素を取得します
    var selectedOption = selectElement.options[selectElement.selectedIndex];

    // 選択されている項目がすでに一番上(インデックス0)でない場合にのみ移動させます
    if (selectElement.selectedIndex !== 0) {
        // removeChild()は、要素を削除するだけでなく、その要素への参照を保持します
        // そのため、後で再度挿入することができます
        selectElement.removeChild(selectedOption);

        // insertBefore() を使用して、選択されたオプションを最初の子要素として挿入します
        // selectElement.firstChild は最初のオプションを指します
        selectElement.insertBefore(selectedOption, selectElement.firstChild);
        
        // または、selectElement.add() を使用する方法もあります
        // selectElement.add(selectedOption, selectElement.options[0]);
    }
}

<< BACK >>

=====================================================================================

セレクトボックスの値を取得/設定する

getElementByIdメソッド

<select id="color">
    <option value="1">red</option>
    <option value="2">yellow</option>
    <option value="3">blue</option>
</select>

<script>
function clickBtn3(){
    const str = document.getElementById("color").value;     //値を取得
    console.log(str);

    document.getElementById("color").selectedIndex = 2;     //値を設定
}

フォームとname

<form name="form1">
	<select name="color1">
	    <option value="red">red</option>
	    <option value="yellow">yellow</option>
	    <option value="blue">blue</option>
	</select>
</form>
<input type="button" value="ボタン1" onclick="clickBtn1()"/>

<script>
function clickBtn1(){
    // 値(数値)を取得
    const num = document.form1.color1.selectedIndex;

    // 値(数値)から値(value値)を取得
    const str = document.form1.color1.options[num].value;

    // 値(数値)から値(value値)を設定
    document.form1.color1.selectedIndex = 2;

<< BACK >>

=====================================================================================

ドロップダウンリストの選択されている項目の表示テキストを取得

<select id="mySelect">
  <option value="value1">Option 1 (テキスト)</option>
  <option value="value2">Option 2 (テキスト)</option>
  <option value="value3">Option 3 (テキスト)</option>
</select>

function getInnerHTML() {
  // 1. select要素を取得する
  const selectElement = document.getElementById("mySelect");

  // 2. 選択されている option 要素のインデックスを取得する
  const selectedIndex = selectElement.selectedIndex;

  // 3. そのインデックスを使って option 要素自体を取得する
  const selectedOption = selectElement.options[selectedIndex];

  // 4. option 要素の innerHTML を取得する
  // optionタグ内にHTMLが含まれる可能性がある場合に利用
  const innerHTMLResult = selectedOption.innerHTML;

  // または、表示テキストのみを取得したい場合は textContent/innerText を使用する
  // こちらの方が一般的で推奨されることが多い
  const textContentResult = selectedOption.textContent;

  // 結果を表示する
  document.getElementById("output").textContent = innerHTMLResult;
  console.log("innerHTML:", innerHTMLResult);
  console.log("textContent:", textContentResult);
}

<< BACK >>

=====================================================================================

Date()

現在時刻や特定の日時の情報を取得。

1. 現在時刻のタイムスタンプ(ミリ秒)を取得する

const now = new Date();
const timestamp = now.getTime(); // または Date.now();
console.log(timestamp); // 例: 1735728000000 (ミリ秒)

2. 時・分・秒などの特定の部分を取得する

const now = new Date();
const hours = now.getHours();     // 現在の時 (0-23)
const minutes = now.getMinutes(); // 現在の分 (0-59)
const seconds = now.getSeconds(); // 現在の秒 (0-59)
const year = now.getFullYear();   // 現在の年
const month = now.getMonth();     // 現在の月 (0-11)
const day = now.getDate();        // 現在の日 (1-31)

console.log(`${year}年${month+1}月${day}日 ${hours}時${minutes}分${seconds}秒`);

3. 地域形式の文字列で取得する

const now = new Date();
const formattedTime = now.toLocaleString();
console.log(formattedTime); // 例: "2025/1/1 10:30:00"

<< BACK >>

=====================================================================================

Date.now()

1970年1月1日0時0分0秒(UTC)からの経過ミリ秒を取得する。オブジェクト生成が不要。
パフォーマンスが重要な場合に推奨。主に経過時間の測定などに使用。 

1. 実行時間の計測に使う

const startTime = Date.now();
// 何らかの処理...
let sum = 0;
for(let i=0; i<1000000; i++){ sum += i; }
const endTime = Date.now();
const duration = endTime - startTime;
console.log(`処理時間: ${duration}ミリ秒`);

オブジェクト生成が不要なため、パフォーマンスが重要な場合に推奨され、主に経過時間の測定などに使われます。 

<< BACK >>

=====================================================================================