【JavaScript】ブックマークレット【業務効率化】

（すごく自分用メモ）

最近ブックマークレットにはまってしまった。
1週回ってめんどい気もするけど、ちゃんと動いたら嬉しい。そんなもん。

ブックマークレットとはなんぞやって人は、↓のサイトへ。

https://rashita.net/blog/?p=26093

簡単に言えばブラウザを自分用に便利にしていこう、ってやつです。

JavaScriptでできることは大概できるはず。
↓に実験で作ってみたIPアドレス計算機能。

どのブラウザでも動くと思われ。
なぜかFireFoxに入れると、コード全体がアスキー化されちゃった。

```javascript:IPアドレス計算
javascript:(function(){let ipAdd = prompt('IPアドレスを入力\n例：192.168.0.35/24','192.168.0.35/24');let ip = ipAdd.split('/');let oxet = ip[0].split('.');let oxetNum = Math.floor(ip[1] / 8); let hostBit = 32 - ip[1];let ipAddStock = 2**(hostBit);let oxetStock = 0;if(hostBit > 24){oxetStock = 2 ** (hostBit - 24);}else if(hostBit > 16){oxetStock = 2 ** (hostBit - 16);}else if(hostBit > 8){oxetStock = 2 ** (hostBit - 8);}else {oxetStock = 2 ** hostBit}let NWAdd = 0;let BCAdd = 0;for(let i = 0; oxetStock * i <= 256 ; i++){    if(oxetStock * i == oxet[oxetNum])  {    NWAdd = oxetStock * i;    BCAdd = (oxetStock * (i + 1)) - 1;    break;  }  else if(oxetStock * i > oxet[oxetNum])  {    NWAdd = oxetStock * (i - 1);    BCAdd = (oxetStock * i) - 1;    break;}}let viewNWAdd;let viewBCAdd;let viewMinAdd;let viewMaxAdd;function setViewAdd(getAdd, setAdd, type){if(oxetNum  < oxet.length - 1){for(let i = 1; i < oxet.length - oxetNum;i++){switch(type){case "NW":oxet[oxetNum + i] = 0;break;case "BC":oxet[oxetNum + i] = 255;break;case "Min":oxet[oxetNum + i] = 0;oxet[oxet.length - 1] = 1;break;case "Max":oxet[oxetNum + i] = 255;oxet[oxet.length - 1] = 254;break;}}}else if(type == "Min"){getAdd += 1;}else if(type == "Max"){getAdd -= 1;}oxet[oxetNum] = getAdd;setAdd = oxet[0] + '.' +oxet[1] + '.' +oxet[2] + '.' +oxet[3];return setAdd;}viewNWAdd = setViewAdd(NWAdd, viewNWAdd, "NW");viewBCAdd = setViewAdd(BCAdd, viewBCAdd, "BC");viewMinAdd = setViewAdd(NWAdd, viewMinAdd, "Min");viewMaxAdd = setViewAdd(BCAdd, viewMaxAdd, "Max");alert(  ipAdd + 'について\n\n' +  'NWアドレス：' + viewNWAdd +   '\n--------------------\nホスト割り当て可能アドレス\n' +  viewMinAdd + '  から\n' +  viewMaxAdd + '  まで' +  '\n--------------------\n' +  'BCアドレス：' + viewBCAdd );if(ip[1] == 32 || ip[0] == 0){alert('サブネットマスクを見直してください');}})();
```

プロンプトにCIDR形式(XX.XX.XX.XX/XX)でIPアドレス入れたら、ネットワークアドレスと、ブロードキャストアドレスと、割り当て可能ホストの範囲をポップで表示してくれる。
たぶんちゃんと計算してくれてるはず。
形式守らないで入れたものについては知りません。

全容は以下の通り。ゴリ押しコード。相変わらずコメントそのまま。
これをブラウザのコンソールにぶち込んでも動くはず。

もうちょっときれいに書けるようになりたひ。

```javascript:IPアドレス計算
(function(){
let ipAdd = prompt('IPアドレスを入力\n例：192.168.0.35/24','192.168.0.35/24');

//入力をアドレスとマスクに分解、アドレスはオクセットごとに分解
let ip = ipAdd.split('/');  //["192.168.0.35" , "24"]
let oxet = ip[0].split('.');  // ["192", "168", "0", "35"]

//どのオクセットの値を見るかを決める。oxet[]の添え字に
//小数切り捨て
//24 -> 3（第4オクセット）, 15 -> 1(第2オクセット)
let oxetNum = Math.floor(ip[1] / 8); 

//ホストビット(全体-サブネットマスク)
let hostBit = 32 - ip[1];

//アドレス最大数
//24 -> 256, 28 -> 16, 31 -> 2, 22-> 1024 10 -> 4194304
let ipAddStock = 2**(hostBit);

//オクセットごとに0‐255入れるための変数
//そのNWのアドレス最大個数 /22 -> hostBit=10 -> 4
let oxetStock = 0;

if(hostBit > 24){oxetStock = 2 ** (hostBit - 24);}
else if(hostBit > 16){oxetStock = 2 ** (hostBit - 16);}
else if(hostBit > 8){oxetStock = 2 ** (hostBit - 8);}
else {oxetStock = 2 ** hostBit}

let NWAdd = 0;
let BCAdd = 0;

for(let i = 0; oxetStock * i <= 256 ; i++)
{
  //NW内最大数とアドレスが同じ→NWアドレスが入っている
  if(oxetStock * i == oxet[oxetNum])
  {
    NWAdd = oxetStock * i;
    BCAdd = (oxetStock * (i + 1)) - 1;
    break;
  }
  else if(oxetStock * i > oxet[oxetNum])
  {
    NWAdd = oxetStock * (i - 1);
    BCAdd = (oxetStock * i) - 1;
    break;
  }
}

//24 -> NW 0, BC 255

//表示用変数
let viewNWAdd;
let viewBCAdd;
let viewMinAdd;
let viewMaxAdd;

//表示用に整える。XX.XX.XX.XXの形に
function setViewAdd(getAdd, setAdd, type)
{
  //typeによって、NW or BC or Min or Maxごとにうめていく

  //maskが24以下の時、下位オクセットを255で埋める
  //(BCアドの事しか考慮できてなかった NWアドの場合.0.1もいる)
  //(添え字と個数を混同してしまった)
  if(oxetNum  < oxet.length - 1)
  {
    //1始まりで調整、差が0ならスルー
    for(let i = 1; i < oxet.length - oxetNum;i++)
    {
      switch(type)
      {
        case "NW":
          oxet[oxetNum + i] = 0;
          break;
        case "BC":
          oxet[oxetNum + i] = 255;
          break;
        case "Min":
          oxet[oxetNum + i] = 0;
          oxet[oxet.length - 1] = 1;
          break;
        case "Max":
          oxet[oxetNum + i] = 255;
          oxet[oxet.length - 1] = 254;
          break;
      }
    }
  }
  else if(type == "Min")
  {
    getAdd += 1;
  }
  else if(type == "Max")
  {
    getAdd -= 1;
  }

  oxet[oxetNum] = getAdd;
  setAdd = oxet[0] + '.' +
           oxet[1] + '.' +
           oxet[2] + '.' +
           oxet[3];

  return setAdd;
}

viewNWAdd = setViewAdd(NWAdd, viewNWAdd, "NW");
viewBCAdd = setViewAdd(BCAdd, viewBCAdd, "BC");
viewMinAdd = setViewAdd(NWAdd, viewMinAdd, "Min");
viewMaxAdd = setViewAdd(BCAdd, viewMaxAdd, "Max");

alert(
  ipAdd + 'について\n\n' +
  'NWアドレス：' + viewNWAdd + 
  '\n--------------------\nホスト割り当て可能アドレス\n' +
  viewMinAdd + '  から\n' +
  viewMaxAdd + '  まで' +
  '\n--------------------\n' +
  'BCアドレス：' + viewBCAdd 
);


//ついでの警告文
//これで/32 をはじきoxetNumに4は入らない
//ついでに/0も弾いとくか
if(ip[1] == 32 || ip[0] == 0)
{
  alert('サブネットマスクを見直してください');
}
})();

/*20211106
とりあえず完成した
*/
```

ちょっと作ってみようと思っただけなのに、一日がつぶれてしまった。

# ■2021.11.27追記

処理の内容が10進数のままやっていて複雑になっちゃったので、2進数つかって処理してみた。
if文無くなって順次になりあちこちいかなくなったので多少読みやすくなったのでは。

```javascript:IPアドレス計算（2進数）
(function(){
//2進数を使って計算してみる

let ipAdd = prompt('IPアドレスを入力\n例：192.168.0.35/24','192.168.0.35/24');

//入力をアドレスとマスクに分解、アドレスはオクセットごとに分解

let ip = ipAdd.split('/');  //["192.168.0.35" , "24"]
let oxet = ip[0].split('.');  // ["192", "168", "0", "35"] 

/** 
 * 2023_08_09 追記
 * IPアドレスの桁数、数値が255 以上になってないかチェック
 * 2進数にして、桁が8以上なら処理を抜ける。
 */
let checkFlg = true;
oxet.filter(x => parseInt(x).toString(2).length > 8 ? checkFlg = false: true);
if(checkFlg == false){
  alert("数値が大きいようです。\n見直してください");
  return;
}

//数字は文字列で入って来るのでparseIntで数値化
//toString(2)で2進数化、
//128→10000000になるが、8とか1000になる。頭の0なくなる
//桁合わせにpadStart(全体桁数,'足りない桁を埋める数字');

for(let i = 0; i < oxet.length; i++){
  oxet[i] = parseInt(oxet[i]).toString(2).padStart(8, '0');
}

//192.168.0.35 なら 11000000 10101000 00000000 00100011

//空文字で結合 ※一つの文字列になる。'.'入れたら間に'.'入る。

let addBit = oxet.join('');

// -> 11000000101010000000000000100011

//表示用にドットで連結

let addBitJoin = oxet.join('.');

// -> "11000000.10101000.00000000.00100011"

//ホスト部のビット数(全体-サブネットマスク)
let hostBit = 32 - ip[1];

//サブネットマスクを2進数化。
//padStartつかうならホスト側から作っていく必要あり。
//let subnetMaskBit = ("").padStart(hostbit, 0).padStart(ip[1], 1);
//padEnd 使う方ががみやすいかか

let subnetMaskBit = ("").padEnd(ip[1], '1').padEnd(32, '0').match(/.{8}/g);

// -> [ "11111111", "11111111", "11111111", "00000000" ]

//表示用にドットで結合

let subnetMaskBitJoin = subnetMaskBit.join('.');

// -> [ "11111111.11111111.11111111.00000000" ]

//10進数化してドットで結合

let subnetMaskDeci = parseDeci(subnetMaskBit).join('.');

// -> "255.255.255.0"

//アドレス最大数は ホスト部ビット数を2のべき乗の指数へ入れて
//出てきた数から2を引けばれば求まる
//24 -> 256(2の8乗), 28 -> 16(2の4乗), 31 -> 2(2の1乗),
//22-> 1024(2の10乗) 10 -> 4194304(2の22乗)

let ipAddStock = 2**(hostBit) - 2;

//左からサブネットマスク分は変わらないので、分ける
//AND演算した感じにする
//文字列.substr(開始,文字数)で開始から文字数文を切り取れる
//192.168.0.35/24 ->110000001010100000000000　が入る。

let NWBit = addBit.substr(0, ip[1]);

//192.168.0.35/24 ->00100011 

let varBit = addBit.substr(ip[1], hostBit);

//NWアドレスはホスト部全て0
//割り当て可能最若番すべて0で一番右だけ1
//割り当て可能最老番すべて1で一番右だけ0
//BCアドレスはホスト部全て1
//それぞれ作り、NWBitに繋げればよい。
// "^" はXOR排他的論理和、片方が1の時１それ以外は0
//同じ数をXORすればすべてが0になるはず
//10進に戻っちゃうので2進化。パディング
// str.match(/.{任意の数}/g) は任意の文字数ずつで分割。

let zerobit = (varBit ^ varBit).toString(2).padStart(varBit.length, 0);

let viewAdd = []; //格納用
viewAdd[0] = (NWBit + zerobit).match(/.{8}/g);
viewAdd[1] = (NWBit + (zerobit[zerobit.length - 1] = 1).toString(2).padStart(varBit.length, 0)).match(/.{8}/g);
viewAdd[2] = (NWBit + (zerobit[zerobit.length - 1] = 0).toString(2).padStart(varBit.length, 1)).match(/.{8}/g);
viewAdd[3] = (NWBit + (zerobit[zerobit.length - 1] = 1).toString(2).padStart(varBit.length, 1)).match(/.{8}/g);

//viewAdd の中身、match(/.{8}/g)で8個ずつで分割されている
// [ 
//  ["11000000", "10101000", "00000000", "00000000"],
//  ["11000000", "10101000", "00000000", "00000001"],
//  ["11000000", "10101000", "00000000", "11111110"],
//  ["11000000", "10101000", "00000000", "11111111"]
// ]

//2進数から10進数へ戻す関数
function parseDeci(arr)
{
  let result = [];
  for(let i = 0; i < arr.length; i++)
  {
    result[i] = parseInt(arr[i], 2);
  }
  return result;
}

//10進数に戻したものを表示用にドットで結合

viewAddDeci = [];
viewAddDeci[0] = parseDeci(viewAdd[0]).join('.');
viewAddDeci[1] = parseDeci(viewAdd[1]).join('.');
viewAddDeci[2] = parseDeci(viewAdd[2]).join('.');
viewAddDeci[3] = parseDeci(viewAdd[3]).join('.');

//viewAddDeciの中身
// [ 
//  ["192", "168", "0", "0"],
//  ["192", "168", "0", "1"],
//  ["192", "168", "0", "254"],
//  ["192", "168", "0", "255"],
// ]

//できあがったものをアラートで表示。
//10進数と、2進数それぞれ。

alert(
  ipAdd + 'について\n\n'
  + '入力アドレス\t：' + ip[0]
  + '\nサブネットマスク\t：' + subnetMaskDeci
  + '\nNWアドレス\t：' + viewAddDeci[0]
  + '\n最若番アドレス\t：' + viewAddDeci[1]
  + '\n最老番アドレス\t：' + viewAddDeci[2]
  + '\nBCアドレス\t：' + viewAddDeci[3]
  + '\n割り当て可能ホスト数：' + ipAddStock

  + '\n\n■■　2進数表記　■■\n\n'

  + '入力アドレス\n' + addBitJoin
  + '\nサブネットマスク\n' + subnetMaskBitJoin
  + '\nNWアドレス\n' + viewAdd[0].join('.')
  + '\n最若番アドレス\n' + viewAdd[1].join('.')
  + '\n最老番アドレス\n' + viewAdd[2].join('.')
  + '\nBCアドレス\n' + viewAdd[3].join('.')
);

console.log(
  ipAdd + 'について\n\n'
  + '入力アドレス\t：' + ip[0]
  + '\nサブネットマスク\t：' + subnetMaskDeci
  + '\nNWアドレス\t：' + viewAddDeci[0]
  + '\n最若番アドレス\t：' + viewAddDeci[1]
  + '\n最老番アドレス\t：' + viewAddDeci[2]
  + '\nBCアドレス\t：' + viewAddDeci[3]
  + '\n割り当て可能ホスト数：' + ipAddStock

  + '\n\n■■　2進数表記　■■\n\n'

  + '入力アドレス\n' + addBitJoin
  + '\nサブネットマスク\n' + subnetMaskBitJoin
  + '\nNWアドレス\n' + viewAdd[0].join('.')
  + '\n最若番アドレス\n' + viewAdd[1].join('.')
  + '\n最老番アドレス\n' + viewAdd[2].join('.')
  + '\nBCアドレス\n' + viewAdd[3].join('.')
);
})();
```

ブックマークレット版

```javascript:IPアドレス計算
javascript:(function(){let ipAdd = prompt('IPアドレスを入力\n例：192.168.0.35/24','192.168.0.35/24');let ip = ipAdd.split('/');let oxet = ip[0].split('.');for(let i = 0; i < oxet.length; i++){oxet[i] = parseInt(oxet[i]).toString(2).padStart(8, '0');}let addBit = oxet.join('');let addBitJoin = oxet.join('.');let hostBit = 32 - ip[1];let subnetMaskBit = ("").padEnd(ip[1], '1').padEnd(32, '0').match(/.{8}/g);let subnetMaskBitJoin = subnetMaskBit.join('.');let subnetMaskDeci = parseDeci(subnetMaskBit).join('.');let ipAddStock = 2**(hostBit) - 2;let NWBit = addBit.substr(0, ip[1]);let varBit = addBit.substr(ip[1], hostBit);let zerobit = (varBit ^ varBit).toString(2).padStart(varBit.length, 0);let viewAdd = [];viewAdd[0] = (NWBit + zerobit).match(/.{8}/g);viewAdd[1] = (NWBit + (zerobit[zerobit.length - 1] = 1).toString(2).padStart(varBit.length, 0)).match(/.{8}/g);viewAdd[2] = (NWBit + (zerobit[zerobit.length - 1] = 0).toString(2).padStart(varBit.length, 1)).match(/.{8}/g);viewAdd[3] = (NWBit + (zerobit[zerobit.length - 1] = 1).toString(2).padStart(varBit.length, 1)).match(/.{8}/g);function parseDeci(arr){let result = [];for(let i = 0; i < arr.length; i++){result[i] = parseInt(arr[i], 2);}return result;}viewAddDeci = [];viewAddDeci[0] = parseDeci(viewAdd[0]).join('.');viewAddDeci[1] = parseDeci(viewAdd[1]).join('.');viewAddDeci[2] = parseDeci(viewAdd[2]).join('.');viewAddDeci[3] = parseDeci(viewAdd[3]).join('.');alert(ipAdd + 'について\n\n'  + '入力アドレス\t：' + ip[0]  + '\nサブネットマスク\t：' + subnetMaskDeci  + '\nNWアドレス\t：' + viewAddDeci[0]  + '\n最若番アドレス\t：' + viewAddDeci[1]  + '\n最老番アドレス\t：' + viewAddDeci[2]  + '\nBCアドレス\t：' + viewAddDeci[3]  + '\n割り当て可能ホスト数：' + ipAddStock + '\n\n■■　2進数表記　■■\n\n'  + '入力アドレス\n' + addBitJoin  + '\nサブネットマスク\n' + subnetMaskBitJoin  + '\nNWアドレス\n' + viewAdd[0].join('.')  + '\n最若番アドレス\n' + viewAdd[1].join('.')  + '\n最老番アドレス\n' + viewAdd[2].join('.')  + '\nBCアドレス\n' + viewAdd[3].join('.'));})();
```

FireFoxで動かしてみた図。
たぶんうまくいっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494508/e06defda-e1c0-cf61-0e32-f9fe4d4916cd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494508/257a0705-3f67-5a4f-9b12-037fbe8675d2.png)


エラー処理書いてない。
また気が向いたら。