LoginSignup
0
1

More than 5 years have passed since last update.

jQueryでダイアログっぽいものを作ってみた

Posted at

動機

以前、JavaScriptを使って、HTMLベースのツールを作った。
ツールでは、コンテンツの表示領域をなるべく広くしたかったので、ボタンとかフォームとかの配置に困り、結局、半透明のパネル(モードレスダイアログ)に配置してコンテンツ上にかぶせることにした。

HTML5+JavaScriptでモードレスダイアログを作る方法を探したところ、dialogタグが見つかったがChromeしか対応していないらしい。
JavaScriptのライブラリを探したのだが意外と見つからないので、自作することにした。

設計

Panelクラスを作って、パネルの作成・表示を管理する。

パネルのDOMの構造を一定に保ちたいので、HTMLを直書きせずにDOMを自動生成することにする。
また、パネルの表示・非表示ボタンも自動生成し、ボタンを押したときのアクションも同時に登録する。

PanelのコンストラクタでDOMを生成してそのまま参照を保持して、という設計もあるが、オブジェクトとDOMが密結合になってしまう。
そこで、コンストラクタではDOMの'id'をプロパティに入れるにとどめ、別関数でDOMを生成することにした。
DOMを操作するときはidclassを使うことにする。

実装

要点だけ。

var Panel = (function() {
  var PANEL_CLASS = 'modeless-panel';
  var PANEL_Z = 1000;

  var Panel = function( title_ )
  {
    var self = this;
    self.title = title_;
    self.elmId = {
      'show': 'panel-show-' + title_,
      'panel': 'panel-frame-' + title_,
      'titlebar': 'panel-titlebar-' + title_,
      'body': 'panel-body-' + title_
    };
  };

  Panel.prototype.activate = function( active_ = true )
  {
    var self = this;
    $( '.' + PANEL_CLASS ).css( 'z-index', ( PANEL_Z - 1 ) );
    if ( active_ ) $( '#' + self.elmId.panel ).css( 'z-index', PANEL_Z );
  };

  Panel.prototype.show = function()
  {
    var self = this;
    $( '#' + self.elmId.show ).hide();
    $( '#' + self.elmId.panel ).show();
    self.activate();
  };

  Panel.prototype.hide = function()
  {
    var self = this;
    $( '#' + self.elmId.show ).show();
    $( '#' + self.elmId.panel ).hide();
  };

  Panel.create = function( title_ )
  {
    var panel = new Panel( title_ );

    // initialize show buttons' area, if not exist.
    var elmShowButtons = $( '#panel-show-buttons' );
    if ( elmShowButtons.length == 0 ) {
      elmShowButtons = $( '<div></div>', {
        'id': 'panel-show-buttons',
      } ).css( {
        'z-index': ( PANEL_Z - 2 ),
        'position': 'fixed',
        'top': '0px',
        'right': '0px'
      } ).appendTo( 'body' );
    }

    // create show button.
    var elmShow = $( '<button></button>', {
      'id': panel.elmId.show,
      'text': title_,
      'click': function( e_ ) { panel.show(); }
    } ).css( {
      'display': 'none'
    } ).appendTo( elmShowButtons );

    // create titlebar with hide button.
    var elmHide = $( '<button></button>', {
      'text': 'x',
      'click': function( e_ ) { panel.hide(); }
    } );
    var elmTitlebar = $( '<div></div>', {
      'id': panel.elmId.titlebar,
      'text': title_
    } ).prepend( elmHide );
    // create empty body.
    var elmBody = $( '<div></div>', {
      'id': panel.elmId.body
    } );
    // create panel with titlebar and body.
    var elmPanel = $( '<div></div>', {
      'class': PANEL_CLASS,
      'id': panel.elmId.panel,
      'click': function( e_ ) { panel.activate(); }
    } ).css( {
      'z-index': 1000,
      'position': 'fixed',
      'top': $( '.' + PANEL_CLASS ).length * 20 + 'px',
      'left': $( '.' + PANEL_CLASS ).length * 20 + 'px'
    } ).append( elmTitlebar, elmBody ).appendTo( 'body' );

    return panel;
  };

  return Panel;
})();

使用例

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>panels</title>
    <!-- jQuery -->
    <script src="js/jquery-3.2.1.js"></script>
    <!-- panel -->
    <script src="js/panel.js"></script>
    <script>
      $( function() {
        var foo = Panel.create( 'foo' );
        $( '#' + foo.elmId.body ).text( 'I am foo.' );
        var bar = Panel.create( 'bar' );
        $( '#' + bar.elmId.body ).text( 'I am bar.' );
        bar.hide();
      } );
    </script>
  </head>
  <body>
  </body>
</html>

拡張案

  • デザイン:DOMにidclassを付与してcssを書けば、色とか大きさとかを変更できる。
  • パネルのドラッグ:イベントmousedown, mouseup,mousemoveをハンドルしてマウスの移動量をパネルの位置に反映すれば、ドラッグ移動できるはず。
    • パネルの中身:HTMLで描く場合は、パネル作成後に$('#bodyid').detach().appendTo('#'+panelobj.elmId.body)とすれば良い。

終わりに

React.jsとかAngular2とか使えばよかったのかもしれない。
しかし、作ったツールが、Webサーバ不要でブラウザだけで動作するものだったので、大仰な仕組みは不要と思いい自作してしまった。
最終的に色々と機能を追加してしまったので、手間を考えるとそれらのライブラリに頼った方が良かったかもしれない。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1