プログラミンGOO

プログラミングナレッジ、ワードプレス、広告収入等について、気づき・備忘録を残していきます。

AWSのMFA設定、QRコードはどこ?複数デバイスで使用する方法

AWSの認証、MFAに使用するスマホアプリ、Authenticator。

ディスプレイ_Authenticator

今回携帯電話を機種変更したのですが、このAuthenticatorの再設定のやり方を解説したドキュメントが見つからず少し苦戦しました。

AWSの管理画面からはQRコードは表示できない

Authenticatorの設定には、QRコードを読み込むか、セットアップキーを入力するしかないのですが、このQRコードが見つからない。

AWSの管理画面をいくら探しても無い。

まだ設定していない状態であれば、以下の手順で設定できるようですね。
右上の自身のアカウントをクリック>マイセキュリティ資格情報>多要素認証(MFA)>仮想MFAデバイス

なのですが、僕のように機種変更で認証アプリを別のデバイスで設定したい場合。
この最後の行程である『仮想MFAデバイス』が無いのです。

QRコードは過去に使用していたアプリから引き継ぐ

じゃあどうするかというと、QRコード過去に使用していたスマートフォンのアプリ画面で表示できます。

昔、認証に使用していたスマホを開いて、アプリを起動します。

そして、右上の三点リーダをクリックし、『アカウントのエクスポート』を選択。

Authenticator

ここからQRコードを設定することができます。

こんな単純なことですがかなり苦戦しました。

認証のアプリケーションはAmazonのものではないから仕方ないとはいえ、AWSの管理画面から表示できるようにならないもんかな…

要件定義の書き方、書くべき内容

背景
アプリケーション作成に至った背景、現状、課題を示す。

概要

システムの概要を記載する。

機能

アプリケーションの主たる機能を記載する。

ユースケース

┗アプリケーション提供者、ユーザなど、ステークホルダーの関係を図解する。
ユースケース図の中で記載した各アクションについて解説する。以下を明確にすること

  • 実行者(アクター)
  • 事前条件
  • メインフロー(アクターの行動内容とシステムの挙動を明記する)
  • 例外フロー(メインフローから外す正常でないアクターの動作と、その際のシステムの挙動を明記する)
  • 事後条件(正常に処理が完了した場合の結果となるアクターの行動、またはシステムの挙動を明記する)

外部設計書の書き方、書くべき内容

目的

本仕様書の作成目的を記載する

仕様ソフトウェア ※各ツールについてはバージョンも記載する

┗開発言語(JavaRubyjavascriptなど)
┗アプリケーションフレームワーク(Spring、Node.js、Vue.js、Vuex、Seleniumなど)

画面仕様

┗画面構成
┗画面遷移図
┗各画面

DB定義
┗DB構成
┗各テーブル定義

javascript備忘録

【基本事項】
■バージョン確認
自動でアップデートされていくので知っても意味がない。
確認方法も煩雑。
というか、ESの実装がjsであり、バージョンは無い?

・scriptで宣言した後

use strictを書いておくとエラーをコンソールに出力してくれる

基本的にファイルのコードはすべて{}でくくってあげる。

するとスコープがわかれるため、変数の干渉を防ぐことができる

・文字列にシングルクォーテーションを用いるか、ダブルクォーテーションを用いるかはどちらでも構わない。typescriptのESlintがシングルを強要することからシングルのほうが無難か。

'use strict';
{
//この中にコードを書く
}

■定義

const t = 'test';

ハイフンはNG、0始まりはNG

大文字、小文字は区別される

予約語は使えない(constなど)

・属性宣言(定数・変数定義)で関数を使う場合に

その関数は後から書いても良い

【フォームの処理】form

■参考

http://www.kogures.com/hitoshi/javascript/get-form/getform1.html

■inputの値が変更されるたびに発火 :oninput

<input type="text" id="input"> 入力された文字列: <span id="result"></span>

<script>

  input.oninput = function() {

    result.innerHTML = input.value;

  };

</script>


■イベントハンドラとイベントリスナーどっちを使用する?

参考:https://ichi.pro/js-no-ibentohandora-to-addeventlistener-no-chigai-wa-nani-desu-ka-165150920301620

>一般的にはイベントリスナー。イベントハンドラは複数あった場合に処理を上書きしてしまう。

<button onclick=”funk()”> //イベントハンドラ

addEventLister //イベントリスナ

■formタグって必要なの?

参考:https://marsquai.com/745ca65e-e38b-4a8e-8d59-55421be50f7e/f83dca4c-79db-4adf-b007-697c863b82a5/d3ffe8bf-0f83-4191-a660-f7e1388dfcda/

以下の違いがある

タグのデフォルトのバリデーションがされる
デフォルトでEnterキーによる送信処理が実装される
デフォルトの送信は非同期処理でされない

・js側でformタグを使うとnameをチェーンして取得できる

~index.html~

<form name=”myform”>

<input type=”text” name=”sample”>

<button type=”submit”>送信</button>

</form>


~main.js~

const form = document.forms.myform;

//formの送信をcatchする場合

form.addEventListener('submit', function() {

  event.preventDefault();

  console.log(form.sample.value);

});

//inputの変更をcatchする場合

form.sample.addEventListener('change', function() {

  event.preventDefault();

  console.log('状態が変化しました!');

});


【文字列の操作】

■エスケープ

前に\をつけるとエスケープ




■連結

  1. でつなぐ


■utlil

・文字数

t.length

・部分抽出

t.substring(start, end);

例)console.log(1,2); //'es'

・分割

t.split(str)  //strで分割し配列にする

一文字ずつに処理を行いたい場合はsplit(‘’)で一文字ずつの配列にする

function uuid() {

  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'

    .split('') //1文字ずつの配列に分割

    .map(c => { //1文字ずつに処理を行う

      switch (c) {

        case 'x': return (Math.random() + 16 | 0).toString(16);
        case 'y': return ((Math.random() + 4 | 0) + 8).toString(16);
        default: return c;
      }
    })

    .join('');
}

■テンプレートリテラル(文字列の埋め込み)

const msg = 'world';

console.log(`hello ${msg}`); //これはjQueryか?

■指定文字列の検索

・参考

https://qiita.com/kazu56/items/557740f398e82fc881df




・matchで検索

str.match('word')  //配列 or null

・indexOf

str.indexOf('word')  //位置のインデックス or -1

■文字列の置き換え

text.replace(/aaa/g, 'ccc'); //通常は初めの1回のみだが、gを指定すると複数回置き換える

str.indexOf(文字列) //あればインデックス、無ければ-1が帰る

■文字をクリップボードにコピー

input要素、textarea要素しかコピーできない。

要素をまるまる取得して、値でなく要素自体を取得し、その要素に対し入力されている文字列を選択する。

input要素、textarea要素しか取得できないのは、クリップボードはHTML上でしか操作できないためと思われる。




・方法

~index.html~

<textarea id="output"></textarea>

~main.js~

const output = document.getElementById('output');
output.addEventListener('click', function() {

  output.select(); //要素のテキストを画面上で選択
  document.execCommand('Copy'); //クリップボードにコピー

  alert('コピーしました');
})

■正規表現

let regex = startStr + ‘.*?’ + endStr: //正規表現を用意

・リプレイス

result = string.replace(new RegExp(regex, ‘g’), ‘’);
//regexを空白に置き換える
//初期値は最初に見つかった文字列のみを対象とするが
//'g'を指定することですべての文字列が対象となる

・存在を調べる

string.match(regex); //一致すればstring、一致しなければnullが返る

【数値の操作】

■少数

.toFixed(2) //小数点2桁まで表示


■ランダムな数値

Math.floor(Math.random() * 6 + 1); //6~1のランダムな数値を表示する
//random :0~0.9999のランダムな数値
//floor :小数点切り捨て

//フィッシャーイェーツのシャッフル
function shuffle(arr) {

  for (let i = arr.length - 1; i >= 0; i--) { //arr.length - 1; 配列の最後のインデックスを表現

    const j = Math.floor(Math.random() * (i + 1));  //ランダムに選ぶ要素のインデックスを表現

    [arr[j], arr[i]] = [arr[i], arr[j]];  //分割代入で要素を入れ替え
  }

  return arr;
}

【データ型】
■型判定
typeof(val)

データ型の変換 parse●●

console.log('5' + 3);

console.log(parseInt('5', 10)); //8
数値に変換できなかったら『NaN』が出力される

・基本データ型 :文字列、数値、真偽値など

・Object型 :配列、オブジェクト ※参照型




■参照型のオブジェクトを参照でなくコピーにするには

const shuffledChoices = shuffle(quizSet[currentNum].c);
//quizSet[currentNum].cは参照型

・[]でくくってスプレッド演算子で配列を参照する

shuffle([...quizSet[currentNum].c]);

【関数】

function fnc(msg = '初期値') {

  return msg;
}

console.log(fnc('test'));

※関数内でreturnするとそのあとの処理は実行されない




・関数式で定数や変数に直接代入もできる

※最後にセミコロンにつく点に注意!

const keisan = function(msg = '初期値') {

  return msg;
};

keisan('test'); //定数として扱われ、関数名がないので無名関数と呼ばれる

・アロー関数 関数式の書き換え

const keisan = (msg) => {    //msgは引数

  return msg;
};

※returnするだけの場合は

const keisan = (msg) => msg;

でOK

※さらに引数が1つだけなら()も不要

const 定数名 = 引数 => 処理;

【if文】

■基本形

if (arg == val) { }

★『=』だと代入が行われてしまうため注意!
■省略形

const score = 40;
score >= 80 ? console.log('OK') : console.log('NG');

&& :AND
|| :OR
! :NOT

【for文】

for (let i = 1; i <= 10; i++) { //初期化すること

  console.log(i);

  if (i === 4) {

continue; //スキップ
  }

  if (i === 7) {

break; //終了
  }
}

■forEach

※break、continueは使えない

a.forEach (

  function( item ) {

    console.log( item );
  }
)


・アロー関数で書いてみると

a.forEach(item => {

  console.log(item);
});

a.forEach(item => console.log(item); //Aに対してBの処理をする、と覚える

・インデックスもとる場合

a.forEach((item, index) => {

  console.log(`${index}:${item}`);
}

【while文】

let hp = 100;

while (hp > 0) {

  console.log(`${hp} HP left!`);

  hp -=15;
}

※条件を書き忘れると無限ループになりPC、ブラウザの再起動をする羽目になるので注意

do whileも使用できる




【配列】

■基本形

const arr = [80, 90, 40]; //constは、再定義はできないが、値の変更はできる

■プロパティ

arr.index

arr.length :長さを取得

■要素の追加

scores.unshift(100); //先頭に追加
scores.push(120); //末尾に追加

■要素の削除

scores.shift(); //先頭を削除
scores.pop(); //末尾を削除

■配列を空にする

arr.length = 0;

■途中の要素

scores.splice(2, 0, a, b); //第1:スタート地点、第2:削除個数、第3以降:追加要素

削除した要素は返り値で取得することもできる

const b = scores.splice(2, 2, a, b); //bに返り値が入る

■map  配列のすべての要素に対して処理を実行

const b = a.map(item => return item * 2);

■filter trueの要素だけとってくる

const b = scores.filter(item => item % 2 ===0); //偶数だけ取得

【オブジェクト】

const player = {

  name: 'taguchi',

  score: 32, //最後の行はカンマはつけてもつけなくてもOK
}

player.name または player[name] でアクセス




・プロパティ(メンバー)の追加 ただ、keyとvalueを渡せばOK

player.email = 'test@exsample.com';

・プロパティの削除

delete player.email;

■オブジェクトメソッド

Object.keys(player) //keyの配列

Object.values(player) //valueの配列

Object.entries(player) //[[key1, value1], [key2, value2]]といった2次元配列

■スプレッド演算子 『...●●』 :配列(オブジェクト)の連結

★配列でも参照型ではなく、コピーになる!

const a = [10, 20];
const b = [1, 2, ...a];
console.log(b); //[1, 2, 10, 20]

・引数にもよく使われる

const a = [10, 20];
const sum = (a, b) => a + b;
console.log(sum(...a)); //30 ※sum(10, 20)となる


・オブジェクトに使う場合

const o1 = {a: 1};
ocnst o2 = {...o1, b: 2}; //{a:1, b:2}

■分割代入 :配列(オブジェクト)の各値に対応させて代入

const numbers = [1, 2];
const [a, b] = numbers; //a=1, b=2

・スプレッド演算子との組み合わせ;

const numbers = [1, 2, 3, 8];
const [a, b, ...rest] = numbers; //a=1, b=2, rest=[3, 8]

・オブジェクトに使う場合

const player = {

  name: 'taguchi',
  score: 55,
  hp: 33,
}

const {name, ...points} = player; //name = 'taguchi', points = {score:55, hp:33}

【クラス】

class Player {

  constructor(name, score) {

    this.name = name;
    this.score = score;
  }

  showInfo() {

    console.log(`name: ${this.name} score: ${this.score}`);
  }

  static showVersion() { //クラスメソッド(静的メソッド)

    console.log('Player class ver 1.0');
  }
}

const taguchi = new Player('taguchi', '32'); //インスタンス化
console.log(taguchi.name); //呼び出し

・thisについて

this.nameのようにパラメータとして付与しているものは、本来であれば

const name = name;

のように宣言するものだが、パラメータとして付与する場合は宣言不要で

かつそのクラスに紐づいた要素になるので便利。




thisを付与するタイミングは以下の時
┗パラメータにアクセス
┗クラスメソッドにアクセス





■クラスの継承 ※上記のPlayerクラスを継承する

class SoccerPlayer extends Player {

  constructor(name, score, number) {

    super(name, score); //親クラスからメソッドを継承

    this.number = number;
  }
}

■カプセル化(オブジェクト思考)

クラスプロパティは外部から直接呼び出すのは避ける。

呼び出したい場合はクラス内でプロパティを呼び出す関数を定義し、

クラスメソッドとして呼び出す

例)

class Panel {

  constructor() {

    this.el = document.createElement('li');
  }

  getEl() { //メソッドでプロパティを呼び出す

    return this.el;
  }
}

board.appendChild(panel.getEl()); // カプセル化


【例外処理】

const a = 5;

try {

  console.log(a.toUpperCase()); //toUpperCaseは大文字にする処理なのでエラー

} catch (e) { //エラーオブジェクトをeに格納してくれる

  console.log(e.message); //eのmessageメソッド
}

【非同期処理】

javascriptはシングルスレッド処理。スタックに処理が積まれるため、ネストされた時間のかかるメソッドは後回しされる場合がある。

Promiseオブジェクトでラップすることで処理の終了を保証して次に進める。

async/awaitを使用することでよりシンプルにPromiseの機構を使用することができる。

asyncで定義した関数はPromiseオブジェクトにラップされるため、処理の終了が保証される。

awaitはasyncで定義した関数内で使用することができ、awaitで定義した関数内でPromiseが返されるまで待機する。asyncと何が違うのかいまいち理解できていない




【appendics】

■日付

const d = new Date();

//引数に数値を指定するとその日時のオブジェクトを作成できる(年,月は必須)

console.log(d.getFullYear()); //年

console.log(d.getMonth());  //★0-11

console.log(d.getDate()); //日

console.log(d.getDay());  //曜日0~6

console.log(d.getTime()); //世界共通の数値化された日時

・フォーム

~HTML~

<form name="myform">

  <input type="date" name="date" value="2012-02-16">

</form>

・日付のセット

d.setHours(10, 20, 30) //10時20分30秒

※自動補正が入る(Date(日)で32と入れると翌月になる)




・日付の追加

d.setDate(d.getDate() + 3);

・日付の経過計測

const d1 = new Date(2018, 11, 1); //11月1日
const d2 = new Date(2018, 11, 10); //11月10日
console.log(d2 - d1); //77760000ミリ秒
console.log((d2 - d1) / (24 * 60 * 60 * 1000)); //9日 86400000秒/1日

■アラート :ウィンドウオブジェクト

window.alert('hello');  //windowは省略可

const answer = confirm('Sure?') //承認を求める

console.log(answer);  //返り値はtrue or false

・HTMLで簡単にアラートを出す ※NOを押せばキャンセルされる

https://proengineer.internous.co.jp/content/columnfeature/8007

コード

<a href="http://www.google.co.jp/" onclick="return confirm('よろしいですか?')">リンク</a>

■タイマー

・一定間隔で処理を実行 :setInterval

★処理がどんどん進むのでシステムに負荷をかけないよう配慮が必要

const tim = () => { //関数式で定数に関数を代入

  console.log(new Date());

};

setInterval(tim, 1000); //関数, ミリ秒でセット

・タイマーを止める

変数にsetIntervalを格納

カウンタ変数を別途用意し、関数内でカウンタを増やす

カウンタに対してif分岐を設定しておいてclearInterval()する

let lim = 0;

const tim = () => {

  console.log(new Date());

  lim ++;

  if (lim > 3) {

    clearInterval(timer);
  }
};

let timer = setInterval(tim, 1000);

★・1回だけ実行する :setTimeout

setTimeoutは処理が終わってから実行するため

システムに負荷をかけない

const tim = () => {

  console.log(new Date());
};

setTimeout(tim, 1000);  //ミリ秒で指定

これをループさせることで、一定間隔での処理を実装することもできる

const tim = () => {

  console.log(new Date());

  setTimeout(tim, 1000);  //ミリ秒で指定
};

tim();

止めたい場合は

let lim = 0;

const tim = () => {

  console.log(new Date());

  lim ++;

  let timid = setTimeout(tim, 1000);

  if (lim > 2) {

    clearTimeout(timid);
  }
};

tim();

・カウントアップの基本

const timer = document.getElementById('timer');
let startTime;

cntUp() {

  let leftTime = Date.now() - startTime;
  textContent = (leftTime / 1000).toFixed(1);

  setTimeout(() => {

    cntUp();
  }, 100)
}

★関数を呼び出す

※定数の無名関数の場合、スコープの都合上creaTimeoutできないことがよくあるので関数を使うのがベター

setTimeout(fnc(), 1000); ではなく

setTimeout(() => {

fnc();

}, 1000);

とする。




■1つのjsファイルを複数ページで使いまわす。

複数ページで使いまわすと、現在のページ以外の要素が存在しないと怒られる。

ページごとにユニークなidなどをキーにif文で出しわける。

if(document.getElementById(‘uniqueId’)) {

uniqueIdを持つページの処理
}


■要素内のテキストが画面幅によって折り返しが起きているかどうかを判定する
RangeオブジェクトにNodeをつっこむことで解析できるようにする。
Rangeオブジェクトのメソッド、getClientRects()で表示されている行数を判定できる。
参考:
javascript - htmlでテキスト表示する際、(画面幅等により、)折り返しが発生するかどうかを事前に判定する方法はありますか? - スタック・オーバーフロー

const items = document.getElementsByClassName('item');
let texts;
let range = new Range();
for(let i = 0; i < items.length; i++) {
  texts = items[i].children;
  for(let j = 0; j < texts.length; j++) {
    range.selectNode(texts[j]);
    if(range.getClientRects().length > 2) {
      //複数行になっていた場合に行いたい処理
    }
  }
}


■即時関数の利用

javascriptはスコープがグローバルか関数内ローカルの2種類しかない。

そのため、画面読み込み時の初期化など、再利用される可能性の無いものは即時関数としてくくることでグローバル領域の汚染を防ぐ。

(function () {

    var label = document.getElementById('date_label'),

        now = new Date();

        label.innerText = now;

}()); //★ここに不思議なカッコがあるので注意

参考:https://qiita.com/katsukii/items/cfe9fd968ba0db603b1e




■数字を文字列として出力しても数値として演算ができる

※プラスの場合だけ、文字列の連結として扱われる




■わからないことがあったらMDNで調べよう




■jsはxss(クロスサイトスクリプティング)の危険があるので注意する

https://www.websec-room.com/2013/03/14/567




■javascriptが動作しているかテスト




以下のテストコードをmain.jsなどに記載し、

htmlの要素に id="target"を付与。

表示した要素をクリックして背景がピンクに変われば動作している


document.getElementById('target').addEventListener('click', () => {

document.getElementById('target').style.background = 'pink';

});

【検索ワード】

async await 違い

Promise 中身 取得

javascript備忘録 DOM操作編

【コンソールから操作する】

デベロッパーツール>コンソール

documentと打ち込むとDOMツリーを確認できる

jsのスクリプトからDOM(HTML)を操作する

【要素の取得】

■idで取得 :getElementById()

document.getElementById('target').textContent = 'Changed!';

■要素名、セレクタで取得 :getElementsByTagName()、querySelector()

document.getElementsByTagName('h1');

document.querySelector('h1').textContent = 'h1dayo!';
document.querySelectorAll('li').forEach(li => {
  li.textContent = 'list dayo!';
});

・クエリセレクタはノードを直接記述することもできる。
例)id="result"直下のp要素

let resultScore = document.querySelector('#result > p');

・フォーム部品の指定 input[type="text"]

const i = document.querySelector('input[type="text"]');

//textareaはHTMLでvalueが設定されていなくても.valueで値を取得する
const t = document.querySelector('textarea');
console.log(t.value);

//チェックボックス・ラジオボタン
~HTML~
<input type="checkbox" name="experience" value="done">
<input type="checkbox" name="decide" value="yes" checked>

~js~
console.log(document.querySelectorAll('input[type="checkbox"]')[1]);

//checked属性の指定
console.log(document.querySelectorAll('input[type="checkbox"]')[1].checked);

//プルダウン
~HTML~
<select>
  <option>item1</option>
  <option selected>item2</option>
</select>

~js~
>|??|
console.log(document.querySelectorAll('select > option')[1].selected); //true

・子要素の指定::nth-child()

document.querySelectorAll('li:nth-child(0)').forEach(li => {
  li.textContent = 'list dayo!';
}

//奇数の要素を取得
document.querySelectorAll('li:nth-child(odd)').forEach(li => {
  li.textContent = 'list dayo!';
}

■CSSクラス名で取得 :getElementsByClassName() //★Elementsとなることに注意!

■親要素の指定

const p = document.querySelector('li');
console.log(p.parentNode); //liの親要素であるul要素が取得できる

■子要素の指定

const p = document.querySelector('ul');
console.log(p.chilren);

複数要素がある場合はchildren[1]のようにアクセスできる
すべての要素を出力したい場合、HTMLコレクション(配列ではない)へのアクセスとなるのでforeachを使用すると以下のエラーが出力される。

forEach is not a function at HTMLDivElement

for文であればコレクションにも対応できるのでこちらで記述する。

const p = document.querySelector('ul');
  for (let i = 0; i < p.children.length; i++) {
    console.log(p.children[i]);
}

■カスタムデータ属性へのアクセス :dataset
HTMLで以下のようなカスタムデータ属性を設定していたとする。

<h1 title="this is title" data-app-id="app1">Title</h1>

その場合、以下の注意事項がある
┗データ属性名のハイフンは削る
┗2語目の文頭は大文字
┗jsからのアクセスはdataではなくdatasetとする

const h = document.querySelector('h1');
console.log(h.dataset.appId);

新たなカスタムデータ属性を付与する場合は以下のようにする

h.dataset.appIdd = 'this is changed';
>|??|
するとHTML側では以下のようになる
>|??|
<h1 title="this is title" data-app-idd="this is changed">Title</h1>

【要素の操作】

■基本

document.body.textContent = 'hello'; //bodyに文字を出力
document.title = 'catch me!' //タイトルを変更

基本的には定数に格納してそれに対して操作を用いることが多い

const h = document.querySelector('h1');
h1.textContent = 'hello!';

■テキストの挿入・変更

a.textContent = 'b'; //要素aのテキストをbにする

■属性の追加・変更

sample.setAttribute(name, value)
sample.setAttribute("href", "/sample")  //要素sampleにhref="/sample"が追加される

■CSSスタイルの追加

a.style.backgroundColor = 'gray';

■idの付与

const exam = "idname";  //id名を定数で定義
a.setAttribute("id", "idname");


■cssクラスの付与・変更 ※使いずらいので下のclassListの方がよく用いられる

a.className = 'b'; //要素aにクラスbを付与する

※上書きしてしまうので既存のクラスがある場合はそれも設定する
 例えばcというクラスがすでに設定されていた場合は、a.className = 'c b'; とする

■cssクラスの操作 :classList

a.classList.add('b') //要素aにクラスbを追加する
a.classList.remove('b') //要素aからクラスbを削除する

■特定のcssがあれば削除:contains

const d = document.querySelector('div');
if (d.classList.contains('border-pink')) {
  d.classList.remove('border-pink');
} else {
  d.classList.add('border-pink');
}

・単純な入れ替えは以下でもできる

d.classList.toggle('border-pink');

■要素の生成 :createElement()

const h = document.createElement('h1'); //要素を作成 ※まだ配置していない
h.textContent = 'Title';
document.body.appendChild(h); //bodyの最後の子要素に追加

※位置を指定する場合

const b = document.querySelector('body');
b.appendChild(b);

・要素の途中に追加するには?

const h = document.createElement('h1'); //要素を作成 ※まだ配置していない
h.textContent = 'Title';
const d = document.querySelector('div'); //HTMLの配置ポイントを取得
document.body.insertBefore(h, d); //hをdの直前に配置

※まだ配置していない要素に追加する場合はdocument.は不要

■要素のコピー

const d = document.querySelector('div');
const c = cloneNode(true); //falseにすると空の要素を作る

■要素の削除 ;removeChild

const d = document.getElementById(‘id’);
d.parentNode.removeChild(d); //親要素のノードからremoveChildすることで自身を削除

※複数の要素をリストに格納しfor文で削除する場合、削除のたびにリストの中身が変わるので、インデックスではなく常に先頭の要素を削除するなどの注意が必要。

■子要素をすべて削除

targetArea.innerHTML = '';

■要素のフォーカス
初期値でテキストエリアなど、要素にフォーカスさせたいとき

const t = document.querySelector('textarea');
t.focus();

・フォーカスさせつつ要素を全選択させたい場合 :select()

t.select();

・入力されないようグレーアウトさせる :disabled

t.disabled = true;

■イベントリスナーで関数を実行 :eventListener
ボタンがクリックされたとき、キーボードが操作された時など、様々なイベントをキーとして動作を追加できる

const b = document.querySelector('button');
b.addEventListener('click', () => {

  console.log('clicked!');
})

【appendix】

■スクロール
指定の要素までスクロール

targetNode.scrollIntoView()

・ゆっくりスクロールさせたい場合

targetNode.scrollIntoView({
  behavior: 'smooth'
})

・スクロール位置を微調整したい場合

const targetZahyou = targetNode.getBoundingClientRecte()
targetY = targetZahyou.top + window/pageYOffset

sindow.scrollTo({
  top: targetY,
  behavior: 'sooth'
})

■座標の取得 :mousemoveイベントのclientX,clientY

const d = document.querySelector('div'); //divに座標を表示するためにdを用意
document.addEventListener('mousemove', e => { //mousemoveイベントを実行。引数にeを設定
  d.textContent = `${e.clientX}:${e.clientY}`;  //eのclientXでX座標を取得できる
});

↑引数にeを渡してあげるとイベントオブジェクトが返ってくるので、それにアクセスすることで動作を指定できる。

・aタグに対し操作を行う際は href属性が空だと自身のページを読み込むためNG

★要素の規定の動作をキャンセル :preventDefault()
~HTML~

.hidden {
  display: none;
}

<p>テストだよ!<span class="hidden">隠しテキストだよ!</span><a href="">読み込む…</a></p>

~js~

const a = document.querySelector('a');
const s = document.querySelector('span');

a.addEventListener('click', e => {

  e.preventDefault(); //aタグの規定の動作(ページ遷移)をキャンセル
  a.classList.add('hidden');
  s.classList.remove('hidden');
});

■addEbentListenerいろいろ
参考:https://qiita.com/kogirix/items/77417702cbc474f49df1

■要素がクリックされたらイベントを起動

const st = document.getElementById('start'); //スタートボタンをidで取得
st.addEventListener('click', () => {

    sttime = Date.now(); //クリックされた時の処理
  });

■押されたキーボードの値を取得

window.addEventListener('keydown', (e) => {
  e.key //ウィンドウで押下されたキーの値を取得
})

■画面をクリックしたらイベントを起動

window.addEventListener('click', (e) => { //画面をクリックしたら
})

■アラートを表示

alert('Game Over'); //アラートを表示

■画面幅で改行が発生しているかを判定

window.addEventListener('DOMContentLoaded', () => {
	let range = new Range();
	range.selectNode(inlineNode);
	console.log(range.getClientRects().length) //行数が取得できる
})

【エラー対応】

■HTMLCollectionのlengthが取得できない
document.getElementsByClassNameで要素を取得するとHTMLCollectionが返ってくる。
console.logで出力するとlengthはしっかりカウントされている(ゼロでない)のだが、このlengthを取得しようとするとなぜか0になる。

const a = document.getElementsByClassName;
console.log(a);  //HTMLCollectionが表示され、プロパティのlengthは0ではなく、値も取得できている。
const b = a.length;
console.log(b);  //なぜか0になる

・解決方法
調べたところ、HTMLCollectionの値が取得される前にconsole.log(b)を実行してしまっている可能性。
正確な読み込みタイミングは調べていないが、以下の順?

  • 変数aが作成される
  • getElementsByClassNameが実行される(DOMがレンダリングされるまで待機)
  • 変数bが作成される
  • a.lengthが実行される(まだDOMレンダリング途中のためlength=0)
  • レンダリングが完了しaにHTMLCollectionが返る
window.addEventListener('DOMContentLoaded', () => {  //DOMが完全に読み込まれてから処理を行う
	if(document.getElementsByClassName('sample-class').length) {
		console.log('exist');
	} else {
		console.log('not');
	}
})

試してはいないけど、処理順の問題ならasinc、awaitでも解決できそう。

Uncaught ReferenceError: 

typescript備忘録

【概要】

マイクロソフト開発

JavaScriptの拡張。大規模開発に対応できるように

・静的な型付け(jsは動的)なので一度型が決まると変えられない

・クラスベースのオブジェクト指向

・公式サイト: https://www.typescriptlang.org/




【基本】

main.tsファイルを作成

tsc main.ts //実行

node main.js //コンソール出力




型推論が適用される

var i: number = 10; //型明示

var i = 10; //型推論でintと判断される

var x; //any型 

■配列

var results: number[];

results = [10, 5, 3];

■列挙

enum Signal {

    Red = 0,

    Blue = 1,

    Yellow = 2

}

enum Signal {   //数値は省略できる

    Red,    //0

    Blue = 3,

    Yellow  //4 ※設定の後からの連番になる

}

var result: Signal;

■関数

function 関数名(引数): 戻り値 {

    return a + b;

}

例)

function add(a: number, b: number): number {

    return a + b;
}

//戻り値が無い場合はvoid

//?を付けて引数の要求を任意にすることができる。(a: number, ?b: number)

ただし、任意の引数の後に必須の引数を定義することはできない

//引数に初期値を渡すこともできる(a: number = 10, ?b: number)




■無名関数

var add = function(a; number, b: number): number{ 

    return a + b;

}

アロー関数にすると

var add = (a; number, b: number): number => { 

    return a + b;
}

さらに短く

var add = (a; number, b: number): number => a + b;

■関数のオーバーロード(関数名が同じで型が違う)

function add(a: number, b: number): number;
function add(a: string, b: string): string;

function add(a: any, b: any): any { //関数宣言はany型にする
    if(typeof a === "string" && typeof b ==="string"){
        return a + " " + b;
    }

    return a + b;
}

console.log(add(5, 3)); //8
console.log(add("hello", " world"));    //hello world

//その他の組み合わせはコンパイルエラーになる

■クラス

class User {

    public name: string;

    constructor(name: string){

        this.name = name;
    }

//変数宣言とコンストラクタ処理を同時に行う場合、

//以下のように宣言もコンストラクタ内の記述も不要

    constructor(public name: string){

//private _nameのように、プライベートの場合は慣習的に_を付ける
    }

    sayHi(): void{  //メソッド。functionは書かない

        console.log("hi! i am " + this._name);
    }

    //ゲッター(getter)とセッター(setter)

    get name() {

        return this._name;
    }

    set name(newValue: string) {

        this._name = newValue;
    }
}

var tom = new User("Tom");

console.log(tom.name);

tom.sayHi();

■継承 ※例として上記のUserクラスを継承

class AdminUser extends User {

    constructor(_name: string, private _age: number) {

        super(_name);
    }

    public sayHi(): void {  //親クラスと同じメソッド名を使うとオーバーライドする

        console.log("my age: " + this._age);

        super.sayHi();  //親クラスのメソッドを呼ぶ
    }
}

継承される可能性があるクラスは、親クラスのプロパティの修飾子はprotectedが良い




■静的メンバ・静的メソッド

class User {

    constructor(private _name: string){

        User.count++; //静的メンバにアクセスするにはクラス名(User)を付ける
    }

    static count: number = 0; //静的メンバ

    static showDescription(): void { //静的メソッド

        console.log("this class is about users");
    }
}

console.log(User.count); //静的メンバ呼び出し

User.showDescription();

【環境構築】

参考:https://qiita.com/ochiochi/items/efdaa0ae7d8c972c8103

・node.jsのインストール

https://nodejs.org/ja/

コマンドプロンプトで確認

node -v

npm -v

・typescriptコンパイラのインストール

npm install -g typescript //-g:グローバル環境にインストール

確認

tsc -v

CSS備忘録

ファイル名に日本語を指定した場合

ブラウザによって文字化けすることがあるので文頭に

@charset "UTF-8";

と記載しておく



【テキスト】

■line-height:インライン要素の高さを設定する

余白(line-height - font-size)は上下均等に割り振られる

pxでの指定以外に以下のように設定することもできる

line-height: 2; font-sizeの2倍

em設定されているフォントサイズの2文字分

※Aは子要素ごとに再計算されるのでAの方が使われる。


■透明度:opacity
opacity: 0.9;

※0に近いほど薄くなる。デフォルトは1



■色
・background-color: hsl(色相,彩度,明度); //HSLでの設定


・透明度:rgbでもhslでも、最後にaをつけて表現する

background-color: hsla(色相,彩度,明度,1.0);
■フォント

sans-serif:総称フォント(よしなに選んでくれる)

※空白が入るフォント名はクォーテーションで囲う

font-family: Verdana, 'Arial Black', メイリオ, sans-serif;

■配置

・インライン要素の上下中央揃え
heightとline-heightを同じ値で指定する

・2行でも1行でも上下中央寄せ
display: flex;

align-items: center;

※box要素にしか使用できないため、inputなどはdivでラップする

左右中央寄せ

justify-content: center;

【BOX】

■線の角を丸める:border-radius
border-radius: 10px;

border-radius: 50%; :正円
■boxに対してborderを付与すると、boxの重なり部分だけ線が太くなる問題

Flexboxでborderの重なりが気になる場合 - Qiita

■背景

background-size: cover //領域を埋める

contain //画像がすべて表示されることを保証する

■影をつける:box-shadow、text-shadow
box-shadow: 右へpx 左へpx ぼかしpx 拡大px 影の色rgba(0, 0, 0, .3);

box-shadow: 5px 3px 2px 2px rgba(0, 0, 0, .3);

※text-shadowの場合は拡大pxの指定はできない


■背景:background
background-image: url(../img/header.png); :画像指定

background-position: center; ;中央揃え

background-size: cover; :縦横比を保持して最大幅表示

一括指定

background: center/cover pink url(../img/header.png);

※positionとsizeは一つにまとめる(順番固定)

【配置】

■注意点

・paddingはwidthやheightに足される。含めたい場合は以下のように記述する。

box-sizing: border-box;

※クラスの初めに書くこと

・marginは重なると相殺される(小さいほうが打ち消される)

・width、heightの%表示は親要素に対して決められる



■overflow :コンテンツがdivの幅から溢れた際の挙動を制御する
・hidden :隠す

・scroll :スクロールで見れるようにする
■margin(外)、padding(内)の指定
padding: 上px, 右px, 下px, 左px;

padding: 上px, 左右px, 下px;

padding: 上下px, 左右px;
■画像の中央ぞろえ

margin-left: auto;

margin-right: auto;



■ボックスの種類:display
・display: block //h1,p,div,sectionなどの初期値に設定されている
・display: inline
┗左詰めで横並びに配置
┗width、heightが設定できない
┗a,img,strongなどの初期値に設定されている

・display: inlineblock
┗左詰めで横並びに配置される
┗width、heightを設定できる
■ポジションを決める:position
・position: static; :定位置
・position: relative; :static(初期値)の位置を起点に計算
position: relative;
top: 30px;
left: 30px;

※親要素にrelative、子要素にabsoluteを指定して相対的に配置することはよくある

・position: fixed; :ウィンドウの左上を起点に計算

スクロールされても位置がウィンドウの中では変わらない

・absolute:絶対配置
 

※親要素がstaticかそれ以外かで挙動が変わる

親要素がstaticの場合
┗ウィンドウの左上を起点に配置

親要素がstatic以外の場合
┗親要素の左上を起点に配置

■vertical-align:行ボックス内での配置

baselineを基準に計算される

img {  vertical-align: top;}
■要素の重ね合わせを制御する:z-index

※何も指定しなければ後から書いたものが上にくる

各要素に

z-index: 1;
z-index: 2;

というように指定すると

数字の若い要素が上にくる



■flex :※別資料にて
■幅MAX

・flexを使う

display: flex;

・maginを使う

margin: 0 auto;

【リスト】

■リストの文頭記号

・リストの文頭記号の変化:list-style-type

list-style-type: circle; :白丸に変更

list-style-type: none; :なし

※左に余白ができるのでpadding: 0;を指定する

・olスタイルを英語表記に:lower-alpha;

list-style-type: lower-alpha;

・改行の際にどこにそろえるか:list-style-position

list-style-position: inside;

・画像に変更

list-style-image: url(../image/icon.png);
■複数指定する場合:list-style

※いくつか初期値が設定されているので上書きされないように注意

list-style: circle inside url(../image/icon.png);

【テーブル】

【フォーム】

■プレースホルダー
<input type=”text” placeholder=”ここに入力してください”>

【appendix】

■継承されないプロパティを継承する:inherit

例えばborderは継承されないが

body {  border: 1px solid pink;}

h1 {  border: inherit;}

とすると継承される

■文字の装飾:text-decoration

リンクの下線を消すのにもよく使われる。

a {  text-decoration: none;}

そのほかに

打消し線

などがある


■カーソルを変える
cursor: pointer;
■画像の挿入
<img src="../img/icon-search.png" alt="search-icon">
■クリックできなくする :user-select: none;

こっちの方が強力? pointer-events: none;

■行ボックス(inline-block)の余白をなくす:vertical-align

初期値はbaseline(文字のライン)

vertical-align: bottom;

とすれば、その要素の基準が完全に行ボックスの底に合わせられるため

余白がなくなる。



■要素に情報を持たせる~表出する:data、attr
<h1 data-subtitle=" - sub title">Title</h1>

※data-●●は自由に指定できる(呼び出すときに使用する)

h1::after {

  content: attr(data-subtitle);

}

【要素の指定】セレクタ

■注意事項

・クラスを持つ要素を指定する際は連続して書く

.thumbnails img.current //OK

.thumbnails img .current //NG

・特定の複数のクラスを持つ要素を指定する場合

.thumbnails.current

・詳細度

idの個数>class,属性,疑似クラスの個数>要素,疑似要素の個数

!important; 最優先(2つあったら後者)

■セレクタリスト

複数のクラスにCSSを適用 ※カンマ区切りで要素を指定する

.top-img, h3 { //mainクラスとh3要素に適用
■全称セレクタ ※ブラウザによっては重たくなるのであまり使われない

>|??|

{

|

■属性セレクタ フォームでよく使用する
input[type=text] {

input[class~=className] { //~を付けるとclassNameを含むとなる

//classが複数ある場合は=では反映されない

a[href^="https"] { :前方一致

a[href$="com"] { :後方一致

a[href*="com"] { :部分一致

a[class=className i] :大文字小文字を区別しない ※デフォルトは区別する
■子孫結合子 一般兄弟結合子 隣接結合子
div p { //div配下のp要素 ※直下でなくても良い

div > p { //div要素直下のp要素

h2 > p { //h2と並列にあるp ※h2には反映されない

p + p { //h2と並列にあるp ※h2には反映されない 最初の1つだけ

【疑似クラス】

■ホバーエフェクト
.btn-shadow:hover{

opacity: 0.8;

box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);

transition: 0.4s;

}

・選択済みのラジオボタンにホバー時の装飾を固定

※inputとlabelをセットにしている前提

label:hober,

input:checked + label {

  //装飾

}
■nth-child(n) :n番目の要素を指定 ※コンテンツ数に応じて折り返すときなど

子要素が並列して複数ある際に親要素に指定する

.main > p:nth-child(3) {

  background-color: pink;

}

※該当の要素がpではない場合スタイルは適用されない

適用したい場合は

.main > p:nth-of-type(3) {

とする。

.main > p:nth-child(3n) { :3の倍数の要素

.main > p:nth-child(odd) { :奇数番目の要素

.main > p:nth-child(even) { :偶数番目の要素

.main > p:first-child { :最初の要素

.main > p:last-child { :最後の要素
■notで特定の要素を除くこともできる

()内のセレクタ以外の要素

.main > p:not(:last-child) { //p要素の最後の要素以外

:not(a) { //aタグ以外の要素
■focus
input:focus { //クリックしてフォーカスが当たっている除隊

body:focus-within //フォーカスが当たっている要素の親要素のスタイル変更
■out-of-range
input:out-of-range { //以下のように最小値等をしているときに範囲外になると反映

//input type=”number” min=”1” max=”10”
■invalid
input:invalid { //required属性等を指定しているときに条件を満たしていない場合に反映
■link visited
a:link { //リンクテキストの装飾

a:visited { //訪問済みリンクの装飾
■target :アンカー(ページ内リンク)で飛んできた場合にその要素に適用
h2:target { //例えば以下のようなHTMLが指定されている場合に

//ページ内リンクで飛んできた時だけ該当のh2要素にCSSを適用

//※他のh2には適用されない

//<h2 id=”uncarName”></h2>
■その他
button:active { //クリックしている状態 クリックを離すと解除

input:checked { //チェックボックスやラジオボタンで選択されているとき

p:empty { //<p></p>のように要素内が空の時

【疑似要素】

■before、after ::で指定する ※contentの指定が必須
h1::before {

  content: '-'; //h1要素の前に『-』が入る

}
■first-letter //最初の1文字
p::first-letter { //p要素の最初の1文字目

p::first-line { //最初の行

【レスポンシブwebデザイン】画像幅の指定

■メタタグの設定
<meta name="viewport" content="width=device-width, initial-scale=1">

※content="width=device-width

 スマホの画面幅に表示領域を合わせる

※initial-scale=1

 最初の倍率を等倍にする
■レスポンシブ幅に応じてスタイルを調整(メディアクエリ):@media

例)要素:画像・テキスト・広告の順で表示

広告は800px以上で表示

600px以上で画像・テキストを横並びにする

//599px以下のスタイル
body {
  margin: 0;
}

aside {
  display: none; //小さい幅ではasideは非表示
}

.image {
  height: 100px; //画像は横幅は自由に広がる※これじゃダメじゃね?
}

.text {
  height: 100px;
}

@media (min-width: 600px) { //600~799pxのスタイル
  section {
    display: flex; //横並びにする
  }
  .image {
    width: 200px; //画像幅の固定
  }
  .text {
    flex: 1; //ブラウザ幅で可変
  }
}

@media (min-width: 800px) {
  section {
    width: 800px; //最大幅を指定
    margin: 0 auto; //中央揃え
  }
  aside {
    display: block; //noneにしていたasaideを表示
    width: 160px; //新しく表示されるasideの幅指定
  }


・メディアタイプを指定することでスクリーン、テレビ、プリンタ、プロジェクタなど

使用する端末ごとの設定をすることもできる。

http://www.htmq.com/csskihon/009.shtml

@media screen and (min-width: 800px) {

............................................................

【appendix】

■disabled
<input class=”sample” type=”text” disabled>

//disabledをつけるだけ。ちなみにこれはcssではなく属性。

・cssでdisabledされたときにcssを変える場合は以下のように疑似要素で指定する。

.sample:disabled {}
■アニメーション

・すごくいろいろできる

https://www.webdesignleaves.com/pr/css/css_basic_07.html




・基本っぽいやつ

https://qiita.com/7968/items/1d999354e00db53bcbd8

■floatで画像が下の要素にかぶる場合

下の要素にclearを使用する。

※display:blockの要素にしか対応できない点に注意

img {float: right;}

h2 {clear: right;}
■はみ出る画像をセンタリング中央寄せ

https://www.tam-tam.co.jp/tipsnote/html_css/post10099.html

サイズを決めるbox(親要素)に

position: relative;

画像の要素に

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

・もっと簡単なのがあった

子要素に

height: 100%;

width: 100%

object-fit: cover;

これをやると親要素のoverflow: hiddenすら必要なくなる

■テキストを右下に表示する

・それぞれの要素をdivでくくって、親要素にflex

<div class="budget-box">
    <div>
        <p class="budget-text">
            予算(月4回)税込
        </p>
    </div>
    <div>
        <p class="budget-text">
            キッズ(月4回)税込
        </p>
    </div>
</div>

.budget-box {
    height: 40px;
    margin-top: 8px;
    display: flex;
    justify-content: flex-end;
    align-items: flex-end;
    flex-direction: column;
}

.budget-text {
    margin-bottom: 0;
}
■ファイルアップロードフォームのCSS

既存のフォームは装飾が無くダサいうえにカスタマイズできない。

元のフォームはdisplay: hiddenで隠してしまって、別のテキストリンクを用意してlabelで紐づける。


~HTML~

<div class="row">

<label for="file_upload_top" class="link-text">トップ画像を変更</label>

//テキストリンクを用意

<input type="file" name="file" accept="image/jpeg, image/png"

  id="file_upload_top" style="display:none">

//実際のフォームは隠す

</div>

<div class="row">

<label for="submit" style="cursor: pointer;"

  class="btn btn-primary my-3 inactive" id="file-submit">送信</label>

//ボタンを用意

<input type="submit" id="submit" style="display:none">

//実際のフォームは隠す

<p id="file_upload_top_text" class="m-3 d-flex align-items-center">

ファイルが選択されていません

//ファイルが選択されたらファイル名に置き換え

</p>

</div>

~JavaScript~

※無くても良い。

 inactiveクラスはファイルがセットされたかどうかでグレーアウトの出し分けをしている

/* ファイルアップロードフォーム装飾 */

$(function(){

$('#file_upload_top').on('change', function(){

const file = $(this).prop('files')[0];

$('#file_upload_top_text').text(file.name); //ファイル名を表示

$('#file-submit').removeClass('inactive');

})

})
■トップ画像(ロゴ大)をスマホとPCでうまく表示したい

PCでは一定の大きさを維持したい。

しかし画像の大きさを維持する設定をするとスマホ表示の時に小さくなりすぎ




・場合分けをすると大変なのでimgではなく背景画像として表示する


~HTML~

<div class="cover"></div>


~CSS~

.cover {

background: url(img/dkt_search_top.png) no-repeat center center;

background-size: cover;

height:360px;

}
■改行禁止

テーブルの見出しなど、改行したくない場合

white-space: nowrap;
■命名規則
  • スネークケースでつける
  • ページ名-コンテンツ名[-配置][-詳細(アクション・状態など)]

例)

  • home-news
  • common-title
  • result-chart-left
  • survey-form-invalid-dialog