JavaScript 第8回 初歩のモードレスウィンドウ（必要最低限）

# はじめに
今回は、モーダルウィンドウの第一歩として、必要最低限のモードレスウィンドウを作成します。
今後、何回かにわけてモードレスウィンドウの表示をパワーアップして、インターネットによくあるようなモーダルウィンドウを作り出すことができればと思います。

# 今回実施する内容
必要最低限のモードレスウィンドウを作成します。
画面のボタンを押下するとモードレスウィンドウが画面上部に表示され、ウィンドウ上の「ｘ」を押下するとウィンドウをクローズします。
![modalwindow1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/bc882ef8-55b0-a0cc-74bc-b33b3ad0fe83.gif)
モードレスであることを確認するため、もうひとつウィンドウを作ってもみます。
![modeless2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/c9ce29ec-1164-bca7-5449-42d1ab5f1d8a.gif)

# ソースコード(Git Hub)
https://github.com/Build-Mount/JS_08_modeless

# 環境
OS: Windows 11 JP (64bit)
Microsoft Edge：バージョン 120.0.2210.91 (公式ビルド) (64 ビット)

# 参考
[border-radius](https://developer.mozilla.org/ja/docs/Web/CSS/border-radius)

# 用語

# モーダルウィンドウとモードレスウィンドウとは
モーダルウィンドウの定義が何かはよくわからないのですが、一般的には、 **「ウィンドウを開くと、ウィンドウを閉じるまで、モーダルウィンドウ内しか操作できず他のウィンドウは操作ができないウィンドウ」** といったものだと思います。
これに対して、モードレスウィンドウがあり、**「モードレスウィンドウを開いても他のウィンドウの操作が可能なウィンドウ」** と思います。

# 必要最低限のモードレスウィンドウ

## モードレスウィンドウのソース
```html:modeless.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modeless</title>
    <link rel="stylesheet" href="modeless.css" type="text/css">
    <script src="modeless.js" defer></script>
</head>
<body>
    <div>- 画面表示 -</div>
    <div id="showTop">画面上部表示</div>
    <div id="topDiv">
        <div class="closeCircle" id="closeTop">×</div>
        画面の上に表示されます。
    </div>
</body>
</html>
```
```css:modeless.css
.closeCircle {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 18px;
  text-align: center;
  position: absolute;
  right: 3px;
  top: 2px;
}

#topDiv .closeCircle {
  background-color: orange;
}

#topDiv {
  visibility: hidden;
  background-color:yellow;
  position: absolute;
  top: 0px;
  left: 20%;
  right: 20%;
  bottom: 80%;
}
```
```javascript:modeless.js
document.getElementById("showTop").addEventListener("click", () => {
    showWindow("topDiv");
});

document.getElementById("closeTop").addEventListener("click", () => {
    closeWindow("topDiv");
});

function showWindow(divId) {
    document.getElementById(divId).style.visibility = "visible";
}

function closeWindow(divId) {
    document.getElementById(divId).style.visibility = "hidden";
}
```

## `modeless.html`の説明
```html
    <div id="showTop">画面上部表示</div>
    <div id="topDiv">
        <div class="closeCircle" id="closeTop">×</div>
        画面の上に表示されます。
    </div>
```
HTMLは、「画面上部表示」の`div`タグ作成と、その画面上部用の`div`タグ作成を行います。
「画面上部表示」は、`id="showTop"`で`divタグを作成します。
これを押下すると、画面上部のモードレスウィンドウを開くようにしますが、それはJavaScriptで設定します。
`id="topDiv"`の`div`タグは、画面上部に表示するモードレスウィンドウの本体です。
この中には、
- モードレスウィンドウをクローズするｘボタン（クローズボタン）。
- 「画面の上に表示されます。」の文字列。
が含まれます。

クローズボタンは、`<div class="closeCircle" id="closeTop">×</div>`で`div`タグで作成します。
`class="closeCircle"は、クローズボタンを作成するためのクラスです。`id="closeTop"`は、クローズボタンを押下時にモードレスウィンドウを非表示に切り替えるためのJavaScriptが必要ですので、関連付けるためのidとして設定します。
ボタンとなる文字は、「×」を記載しています。フォントは特に指定していませんが、ユーザー環境によっては「ｘ」に見えない可能性もありますが、簡単のためこのようにします。

## `modeless.css`の説明
CSSは、以下の３つのセレクターで構成します。
- `.closeCircle`
- `#topDiv .closeCircle`
- `#topDiv`

`.closeCircle`は、クローズボタンを示す円を描くためのセレクターです。今回の画面上部に表示するモードレスウィンドウだけでなく、他の箇所でも使えるかなと思い、一般的なクローズボタンというつもりで、クラスで設定します。
```css
.closeCircle {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 18px;
  text-align: center;
  position: absolute;
  right: 3px;
  top: 2px;
}
```
幅(`width`)、高さ(`height`)は18pxとし、円の直径のサイズです。
[border-radius](https://developer.mozilla.org/ja/docs/Web/CSS/border-radius)は、以下の記載があります。
>`border-radius` は CSS のプロパティで、要素の境界の外側の角を丸めます。1 つの半径を設定すると円の角になり、2 つの半径を設定すると楕円の角になります。

`border-radius: 50%`を設定すると、円になります。
`font-size`は、この円よりも少し小さめにし、`line-height`は、この円と同じ大きさにします。
これで縦方向はセンタリングされます。
横方向は、`text-align: center`でセンタリングします。
`position: absolute`とし、このクローズボタンを含む親要素からのオフセットとし、`right: 3px`、`top: 2px`とします。これで枠内ですがこの親要素の`topDiv`の右上に円が配置されます。

```css
#topDiv .closeCircle {
  background-color: orange;
}
```
`#topDiv`の後に半角スペースを入れて、`.closeCircle`を記載することで、親要素の`id`が`topDiv`で、子要素の`class`が`closeCircle`のセレクターができます。
感覚的に半角スペースというのが違和感なのでではすが、「/」などで区切ってくれたほうがわかりやすいのですが、仕様なので仕方ないですね。「/」だと都合が悪かったんだろうと思います。
ということで、`id`が`topDiv`である子の要素のクラスが`closeCircle`である要素の背景色をオレンジに設定します。
画面上部に表示するモードレスウィンドウのクローズボタンはオレンジ色にするために実施します。
その他のウィンドウでは、親要素を変えることで、色やその他のプロパティを設定すればよいと思い、このようにしました。

```css
#topDiv {
  visibility: hidden;
  background-color:yellow;
  position: absolute;
  top: 0px;
  left: 20%;
  right: 20%;
  bottom: 80%;
}
```
`topDiv`のDivタグ用のセレクターです。
`visibility: hidden`で初期は非表示にします。背景色は何でもよいのですが、今回は、`background-color:yellow`としました。
`position: absolute`、`top: 0px`、`left: 20%`、`right: 20%`、`bottom: 80%`で、`topDiv`を画面上部に配置します。

## `modeless.js`の説明
`id`が`showTop`と`closeTop`の`div`タグに`addEventListener`を追加し、`div`タグクリック時の動作を設定します。
`showTop`は`showWindow`関数を実行し、`closeTop`は`closeWindow`関数を実行します。
`showWindow`関数は、`topDiv`の`div`タグを表示し、`closeWindow`関数は、`topDiv`の`div`タグを非表示にします。いずれも引数に`divId`としており、表示・非表示する`div`を選択できるようにしました。

# モードレスウィンドウ２つ
モードレスウィンドウということなので、他のウィンドウも操作できますが、その動作の確認をします。

## モードレスウィンドウ２つのソース
```html:modeless2.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modeless</title>
    <link rel="stylesheet" href="modeless2.css" type="text/css">
    <script src="modeless2.js" defer></script>
</head>
<body>
    <div>- 画面表示 -</div>
    <div id="showTop">画面上部表示</div>
    <div id="showRight">画面右部表示</div>
    <div id="topDiv">
        <div class="closeCircle" id="closeTop">×</div>
        画面の上に表示されます。
    </div>
    <div id="rightDiv">
        <div class="closeCircle" id="closeRight">×</div>
        画面の右に表示されます。
    </div>
</body>
</html>
```
```css:modeless2.css
.closeCircle {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  font-size: 16px;
  line-height: 18px;
  text-align: center;
  position: absolute;
  right: 3px;
  top: 2px;
}

#topDiv .closeCircle {
  background-color: orange;
}

#topDiv {
  visibility: hidden;
  background-color:yellow;
  position: absolute;
  top: 0px;
  left: 20%;
  right: 20%;
  bottom: 80%;
}

#rightDiv .closeCircle {
  background-color: blue;
  top: -20px;
}

#rightDiv {
  visibility: hidden;
  background-color:blueviolet;
  position: absolute;
  top: 50px;
  left: 80%;
  right: 0%;
  bottom: 20%;
}
```
```javascript:modeless2.js
document.getElementById("showTop").addEventListener("click", () => {
    showWindow("topDiv");
});

document.getElementById("closeTop").addEventListener("click", () => {
    closeWindow("topDiv");
});

document.getElementById("showRight").addEventListener("click", () => {
    showWindow("rightDiv");
});

document.getElementById("closeRight").addEventListener("click", () => {
    closeWindow("rightDiv");
});

function showWindow(divId) {
    document.getElementById(divId).style.visibility = "visible";
}

function closeWindow(divId) {
    document.getElementById(divId).style.visibility = "hidden";
}
```

## `modeless2.html`の説明
```html
    <div id="showRight">画面右部表示</div>
    ...
    <div id="rightDiv">
        <div class="closeCircle" id="closeRight">×</div>
        画面の右に表示されます。
    </div>
```
HTMLは、最初のソースに加えて、「画面右部表示」と、右側に表示する`div`タグを作成します。

## `modeless2.css`の説明
CSSは、2つ目用に２つのセレクターで構成します。
- `.closeCircle`
- `#rightDiv .closeCircle`
- `#rightDiv`

`.closeCircle`は、１つ目用のものと同じです。

```css
#rightDiv .closeCircle {
  background-color: blue;
  top: -20px;
}
```

`#topDiv .closeCircle`は、右側用のクローズボタンの個別設定です。`top: -20px`を設定し、`rightDiv`の`div`タグの上にクローズボタンが表示するように変更しました。

```css
#rightDiv {
  visibility: hidden;
  background-color:blueviolet;
  position: absolute;
  top: 50px;
  left: 80%;
  right: 0%;
  bottom: 20%;
}
```
`rightDiv`の`div`タグ用のセレクターです。
`right: 0%`で右側に表示されるようにしたことくらいが1つ目のものとの違いです。

## `modeless2.js`の説明
１つ目用に加え、`rightDiv`表示用、および非表示用の関数を追加しました。

# おわりに
今回はモードレスウィンドウを作成しました。
今後は、このウィンドウをもとにモーダルウィンドウへ更新していきたいと思います。