フローティング・ウィンドウ ライブラリ JSFrame.js の紹介

# はじめに
フローティングウィンドウを作成・表示するためのjavascriptライブラリ JSFrame.js の紹介です。

過去に自Webサービス用につくったライブラリですが、さいきんいくらか需要があったので紹介します  

ソースはこちらにてMITで公開してます。
https://github.com/riversun/JSFrame.js

# JSFrame.jsの特徴

- 他ライブラリに依存していない独立ライブラリ。jQuery等は不要
- 複数のウィンドウ表示（マルチウィンドウ）、モーダルウィンドウ、トーストの表示に対応
- ポップアップウィンドウ、フローティングウィンドウに期待されること（移動、リサイズ、見た目の変更、アニメーション等）はだいたい対応

## こんなことができます
こういったフローティングウィンドウをブラウザ上で実現するためのライブラリです
https://riversun.github.io/jsframe/examples/jaq/preset_yosemite.html
https://riversun.github.io/jsframe/examples/jaq/preset_win10.html

![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/c5ff5dd3-1b4c-21fe-7de0-2558b4af6b08.png)


# 使い方
- このように、ブラウザでライブラリを読み込むようにします

```html
<script src="https://riversun.github.io/jsframe/jsframe.js"></script>
```

- npmでも利用可能です

```shell
npm install jsframe.js
```

さっそくサンプルで使い方を説明します

## ウィンドウを表示する

- **jsFrame#create** でウィンドウの初期化のための初期化パラメータを指定します。
- 初期化パラメータの**html**にはウィンドウ内に表示するコンテンツをHTMLで記述します。
- **frame#show**でウィンドウを表示します

```js:ウィンドウを表示する
const jsFrame = new JSFrame();
const frame = jsFrame.create({
    title: 'ウィンドウ',
    left: 20, top: 20, width: 320, height: 220,
    movable: true,//マウスで移動可能
    resizable: true,//マウスでリサイズ可能
    html: '<div id="my_element" style="padding:10px;font-size:12px;color:darkgray;">Contents of window</div>'
});
//ウィンドウを表示する
frame.show();
```
[デモをみる](https://riversun.github.io/jsframe/examples/jaq/index.html)

**実行結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/b1d3df9e-2640-1f95-b590-3b0e99be9c9d.png)

**Tips**

- 初期化パラメータで指定したコンテンツとなるHTML内の要素には **frame.$([セレクタ])**でアクセスできる。$('#my_element')とすれば、id='my_element'の要素が取得できます。

```js
 frame.$('#my_element').innerHTML = '<span style="color:red">Hello world</span>';
```

## 指定したURLをウィンドウのコンテンツとして表示する

- 初期化パラメータに **url**を指定すれば、そのURLの内容を表示します
- この場合、ウィンドウのコンテンツはiframeとして表示されます
- **urlLoaded**にはコールバック関数をセットします。指定したurlの読み込みが終わると呼び出されます。

```js:指定したURLを表示する(iframe機能)
const frame01 = jsFrame.create({
    title: 'ウィンドウ1',
    name: 'window01',
    left: 20, top: 20, width: 320, height: 160,
    url: 'iframe_content01.html',//iframe内に表示するURL
    urlLoaded: (_frame) => {}
});
frame01.show();
```
[デモをみる](https://riversun.github.io/jsframe/examples/jaq/iframe.html)

**実行結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/8ae97cbd-bfc1-7141-b84d-95bc066aa076.png)
**Tips**
- iframe内の要素も**html**で指定したときと同様 **frame.$('#my_element')**のように取得可能です

## モーダルウィンドウを開く

- モーダルウィンドウを表示するには**frame#showModal**とします。
- **showModal(callbackFunc)**メソッドにコールバック関数**callbackFunc**を指定すると、モーダルウィンドウを閉じたときに呼び出されます。
 
```js:モーダルウィンドウ
 const modalFrame = jsFrame.create({
      name: 'my-modal-window',
      title: 'モーダルウィンドウ',
      left: 0, top: 0, width: 320, height: 220,
      html: 'something'
  });

  //モーダルウィンドウとして開く
  modalFrame.showModal(_frame => {
  //モーダルウィンドウが閉じられるとコールバックされる
  });

```

[デモをみる](https://riversun.github.io/jsframe/examples/jaq/modal.html)

**実行結果**
![img_04_modal.png](https://qiita-image-store.s3.amazonaws.com/0/170905/c2b9bd32-3e92-1250-5de6-9ec5c8a8e06b.png)


## スタイリング（ウィンドウの見た目）

- ウィンドウの見た目をプリセットから選んだり、自作することができます
- 初期化パラメータの **appearanceName**にプリセット名を指定できます
- 自前で作りたい場合は初期化パラメータの**appearance**にアピアランスオブジェクト(appearance)を指定します。

```js:スタイリング
const jsFrame = new JSFrame();

 //プリセットアピアランスをプリセット名で指定する
 const frame01 = jsFrame.create({
     title: 'Yosemite style',
     left: 20, top: 20, width: 320, height: 220,
     appearanceName: 'yosemite',//プリセット名は 'yosemite','redstone','popup'
     style: {
         backgroundColor: 'rgba(220,220,220,0.8)',
     },
     html: '<div style="padding:10px;">プリセット名で指定する</div>'
 }).show();
```

[デモをみる](https://riversun.github.io/jsframe/examples/jaq/styling.html)

**実行結果**
![img_05_styling.gif](https://qiita-image-store.s3.amazonaws.com/0/170905/84cab172-7440-9d68-f144-112b19610fcd.gif)



**Tips**
- プリセットで表示されるウィンドウタイトルバー上のボタン名は以下のようになっています
 **closeButton**・・・閉じるボタン
 **minimizeButton・・・**最小化ボタン
 **maximizeButton**・・・最大化ボタン
 **zoomButton**・・・ズームボタン

たとえば、非表示にしたい場合は以下のようにします

```js:タイトルバー上ボタンを非表示にする
  frame02.hideFrameComponent('minimizeButton');
```

## クリックイベントなどのハンドリング

- タイトルバー上ボタンや初期化パラメータで**html**や**url**で指定したコンテンツ内にあるDOM要素に対してイベントハンドラー（コールバック関数）をセットすることができます

- クリックイベントなら**frame#on('セレクタ','click',function(frame,event){});**のようにしてセットできます

```js:イベントハンドラーのセット
//タイトルバー上のボタンにクリックイベントをセットする
frame.on('minimizeButton', 'click', (_frame, evt) => {
});

//htmlやurl指定したコンテンツ内のDOM要素のid名でクリックイベントをセットする
frame.on('#bt_cancel', 'click', (_frame, evt) => {
});
```

[デモをみる](https://riversun.github.io/jsframe/examples/jaq/event_handling.html)

**実行結果**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/170905/601b71f5-7a80-0cec-3201-045330e20ed1.png)

## トースト・メッセージを表示する

- トーストとは情報通知などのために一瞬あらわれるウィンドウです
- **JSFrame#showToast**で表示することができます
- 登場の仕方や見た目のカスタマイズも可能です

```js:トーストの表示
const jsFrame = new JSFrame();
  jsFrame.showToast({
      html: '標準トーストです'
  });
```

[デモをみる](https://riversun.github.io/jsframe/examples/jaq/toast.html)


**実行結果**
![toast.gif](https://qiita-image-store.s3.amazonaws.com/0/170905/577d58a3-f8f5-8a2d-9a30-bb9d3ac1c747.gif)

**Tips**

- 表示位置を変更するには **align**を指定します。
 
**align:'top'**・・・上部(デフォルト)
**align:'center'**・・・上下中央
**align:'bottom'**・・・下部(デフォルト)

```js:トーストの表示位置
jsFrame.showToast({
    align: 'center', html: '中央トーストです'
});
```

- トーストのカスタマイズ

以下のようにカスタマイズが可能です

```js:トーストのカスタマイズ
jsFrame.showToast({
    width: 260,//幅
    height: 100,//高さ
    duration: 2000,//表示時間(millis)
    align: 'center',// 表示位置 'top'/'center'/'bottom'(default)
    style: {
        borderRadius: '2px',
        backgroundColor: 'rgba(0,124,255,0.8)',
    },
    html: '<span style="color:white;">カスタムトーストです</span>',
    closeButton: true,//閉じるボタンを表示
    closeButtonColor: 'white'//閉じるボタンの色
});
```
上の例だとこんな感じになります
![toast2.gif](https://qiita-image-store.s3.amazonaws.com/0/170905/bf2dd521-5101-0b18-58ab-1f3307371364.gif)

# ウィンドウの各種操作（位置、フォーカス、閉じるなど)


## **frame#setPosition**でアンカー指定で位置を決める

**frame#setPosition(x,y,anchor)**で位置を指定するときにウィンドウのどの位置を基準点（アンカー）にするか指定して位置決めすることができます。

```js:アンカーによって位置を指定する
//位置を指定する
const align = 'CENTER_CENTER';//アンカー

//(x,y)座標として画面の中央を指定、基準点（アンカー）をウィンドウの水平垂直の中心(CENTER_CENTER)にセット
const x = window.innerWidth / 2;
const y = window.innerHeight / 2;
frame0.setPosition(x, y, align);
```

**アンカーの種類**

|水平|垂直|指定値|
|---|---|---|
|左寄 | 上寄 |'LEFT_TOP'|
|左右中央 |上寄 |'CENTER_TOP'|
|右寄 |上寄 |'RIGHT_TOP'|
|左寄 |上下中央|'LEFT_CENTER'|
|左右中央 |上下中央 |'CENTER_CENTER'|
|右寄 |上下中央  |'RIGHT_CENTER'|
|左寄 |下寄  |'LEFT_BOTTOM'|
|左右中央 |下寄| 'CENTER_BOTTOM'|
|右寄 |下寄| 'RIGHT_BOTTOM'|



## ウィンドウを閉じる

- コードからウィンドウを閉じることができます

```javascript
frame.closeFrame();
```

## ウィンドウを非表示にする

```js
frame.hide();
```

## ウィンドウを最前面に持ってくる

- **frame#requestFocus**で複数ウィンドウがあるときにコードからウィンドウを最前面に表示します
- また、最前面にもってきたあとに、そのウィンドウにフォーカスします

```javascript
frame.requestFocus();
```

## ウィンドウ名からウィンドウを取得する
- 初期化パラメータで **name**を指定すると、以下のようにjsFrameオブジェクトからウィンドウを取得することができます

```js
 var frame = jsFrame.getWindowByName('my-modal-window');
```


## ウィンドウの初期化パラメータ一覧

- ウィンドウを初期化するときに指定できるパラメータ一覧です

```js:初期化パラメータ一覧
const frame = jsFrame.create(
    {
        name: 'my-window-name',//ウィンドウの名前。一意なもの。
        title: 'ウィンドウ',//ウィンドウのタイトル
        left: 20,//ウィンドウ左上のx座標
        top: 20,//ウィンドウ左上のy座標
        width: 320,//ウィンドウの幅
        height: 220,//ウィンドウの高さ
        minWidth: 160,//ウィンドウの最小の幅（これ以上小さくできない大きさ)
        minHeight: 100,//ウィンドウの最小の高さ（これ以上小さくできない大きさ)
        movable: true,//true:マウスで移動可能
        resizable: true,//true:マウスでリサイズ可能
        appearance: appearanceObj,//アピアランス（見た目を定義した）オブジェクト
        appearanceName: 'yosemite',//見た目のプリセット名(appearanceと同時に指定できない)
        style: {//ウィンドウのコンテンツ領域のスタイル。要素のインライン style 属性と同じように指定可能
            backgroundColor: 'rgba(220,220,220,0.8)',//例：コンテンツ領域の背景色（半透明も指定可能)
            overflow: 'auto',//例：コンテンツ領域で描画がはみ出すときどうするか
        },
        html: 'ウィンドウ内に表示するコンテンツ',//コンテンツ領域に表示するHTML(urlと同時に指定できない)
        url: 'content01.html',//コンテンツ領域に表示するページのURL。iframeで表示される。
        urlLoaded: (frame) = {}//urlの読み込み終了時に呼び出されるコールバック関数をセットする

    });
```

# まとめ

**本投稿について**

- 拙作フローティングウィンドウライブラリ**JSFrame.js**をご紹介しました
- ソースコードは https://github.com/riversun/JSFrame.js にあります

**JSFrameの経緯**

- 2004年にfirst commitしました。
- 2006年頃、自サービスで活用して以降、メンテ放置期間も含めそれなりに時間たちました。原版のソースコードを最近のJS事情にあわせある程度手直ししましたが、基本は200x年代スタイルで記述されています。
- 2017年には、Qiitaで紹介させていただきました
- 2018年には、npmライブラリ化したり、新機能をいくつか追加しました。