[Ruby on Rails]AdminLTEをテンプレートとして使用する(2) – クライアントの実装

2015.09.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回に引き続き、RailsでAdminLTEをテンプレートとして使用する方法についてです。今回は前回解説したアプリのクライアント側の実装方法について書いていきたいと思います。

実装方法

1.フォルダ作成

まずはアプリのフォルダを作成します。前回書いたようにサーバとクライアントではフォルダを分けるので、アプリのルートとなるフォルダ配下に「client」フォルダを作成します。

2.ライブラリの配置

AdminLTEのページの「Download」ボタンを押下してライブラリとサンプルソースをダウンロードします。今回はAdminLTE自体のソースを変更しないので「Ready」の方をダウンロードしました。 AdminLTE-Download

clientフォルダ内にライブラリを配置するフォルダを作成します。前回書いたようにlibフォルダを作成し、その中にadminlteフォルダを作成してください。

ダウンロードしたzipを解凍すると、中にライブラリとサンプルソースがあります。これらから「bootstrap」「dist」「plugins」フォルダをlib/adminlteフォルダにコピーします。以下の様なフォルダ構成になるはずです。

.
├── client
│   ├── lib
│   │   └── adminlte
│   │       ├── bootstrap
│   │       ├── dist
│   │       ├── plugins

3.starter.html

先ほどのサンプルにstarter.htmlがあります。これをclientフォルダへコピーします。そしてlib/adminlteフォルダ内のライブラリを参照するよう、html内のstylesheetやjavascriptの参照先を変更します。以下のようになります。

<!DOCTYPE html>
<!--
This is a starter template page. Use this page to start your new project from
scratch. This page gets rid of all links and provides the needed markup only.
-->
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | Starter</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Bootstrap 3.3.5 -->
    <link rel="stylesheet" href="lib/adminlte/bootstrap/css/bootstrap.min.css">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <!-- Ionicons -->
    <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="lib/adminlte/dist/css/AdminLTE.min.css">
    <!-- AdminLTE Skins. We have chosen the skin-blue for this starter
          page. However, you can choose any other skin. Make sure you
          apply the skin class to the body tag so the changes take effect.
    -->
    <link rel="stylesheet" href="lib/adminlte/dist/css/skins/skin-blue.min.css">
    
    (中略)
    
    <!DOCTYPE html>
<!--
This is a starter template page. Use this page to start your new project from
scratch. This page gets rid of all links and provides the needed markup only.
-->
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | Starter</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Bootstrap 3.3.5 -->
    <link rel="stylesheet" href="lib/adminlte/bootstrap/css/bootstrap.min.css">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <!-- Ionicons -->
    <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="lib/adminlte/dist/css/AdminLTE.min.css">
    <!-- AdminLTE Skins. We have chosen the skin-blue for this starter
          page. However, you can choose any other skin. Make sure you
          apply the skin class to the body tag so the changes take effect.
    -->
    <link rel="stylesheet" href="lib/adminlte/dist/css/skins/skin-blue.min.css">

4.chartjs.html

chartjs.htmlについてもサンプルから流用します。pages/chartsフォルダを作成し、サンプルのchartjs.htmlをコピーしてください。

コピーしたらstarter.htmlと同様、stylesheetやjavascriptの参照先を変更します。以下のようになります。(全ての修正箇所は網羅できていないかもしれません)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>AdminLTE 2 | ChartJS</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- Bootstrap 3.3.5 -->
    <link rel="stylesheet" href="../../lib/adminlte/bootstrap/css/bootstrap.min.css">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    <!-- Ionicons -->
    <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
    <!-- Theme style -->
    <link rel="stylesheet" href="../../lib/adminlte/dist/css/AdminLTE.min.css">
    <!-- AdminLTE Skins. Choose a skin from the css/skins
         folder instead of downloading all of them to reduce the load. -->
    <link rel="stylesheet" href="../../lib/adminlte/dist/css/skins/_all-skins.min.css">
    
    (中略)
    
    <!-- jQuery 2.1.4 -->
    <script src="../../lib/adminlte/plugins/jQuery/jQuery-2.1.4.min.js"></script>
    <!-- Bootstrap 3.3.5 -->
    <script src="../../lib/adminlte/bootstrap/js/bootstrap.min.js"></script>
    <!-- ChartJS 1.0.1 -->
    <script src="../../lib/adminlte/plugins/chartjs/Chart.min.js"></script>
    <!-- FastClick -->
    <script src="../../lib/adminlte/plugins/fastclick/fastclick.min.js"></script>
    <!-- AdminLTE App -->
    <script src="../../lib/adminlte/dist/js/app.min.js"></script>
    <!-- AdminLTE for demo purposes -->
    <script src="../../lib/adminlte/dist/js/demo.js"></script>
    
    (以下略)

次にデータの取得とグラフの表示です。サンプルではJavaScriptで固定のデータを表示していますが、chartjs.htmlではサーバよりデータを取得するようにします。サーバとの通信はベーシックなjQueryで行います(jQueryがAdminLTEのライブラリに入っていることもある)。以下の様なソースとなります。

    <script>
      $(function () {
        $.getJSON(
          'http://localhost:3000/api/v1/pages/charts/chartjs/area_chart.json',
          function(data) {
            //--------------
            //- AREA CHART -
            //--------------

            // Get context with jQuery - using jQuery's .get() method.
            var areaChartCanvas = $("#areaChart").get(0).getContext("2d");
            // This will get the first returned node in the jQuery collection.
            var areaChart = new Chart(areaChartCanvas);

            var areaChartData = data;

            var areaChartOptions = {
              //Boolean - If we should show the scale at all
              showScale: true,
              //Boolean - Whether grid lines are shown across the chart
              scaleShowGridLines: false,
              //String - Colour of the grid lines
              scaleGridLineColor: "rgba(0,0,0,.05)",
              //Number - Width of the grid lines
              scaleGridLineWidth: 1,
              //Boolean - Whether to show horizontal lines (except X axis)
              scaleShowHorizontalLines: true,
              //Boolean - Whether to show vertical lines (except Y axis)
              scaleShowVerticalLines: true,
              //Boolean - Whether the line is curved between points
              bezierCurve: true,
              //Number - Tension of the bezier curve between points
              bezierCurveTension: 0.3,
              //Boolean - Whether to show a dot for each point
              pointDot: false,
              //Number - Radius of each point dot in pixels
              pointDotRadius: 4,
              //Number - Pixel width of point dot stroke
              pointDotStrokeWidth: 1,
              //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
              pointHitDetectionRadius: 20,
              //Boolean - Whether to show a stroke for datasets
              datasetStroke: true,
              //Number - Pixel width of dataset stroke
              datasetStrokeWidth: 2,
              //Boolean - Whether to fill the dataset with a color
              datasetFill: true,
              //String - A legend template
              legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
              //Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
              maintainAspectRatio: true,
              //Boolean - whether to make the chart responsive to window resizing
              responsive: true
            };

            //Create the line chart
            areaChart.Line(areaChartData, areaChartOptions);

            //-------------
            //- LINE CHART -
            //--------------
            var lineChartCanvas = $("#lineChart").get(0).getContext("2d");
            var lineChart = new Chart(lineChartCanvas);
            var lineChartOptions = areaChartOptions;
            lineChartOptions.datasetFill = false;

            lineChart.Line(areaChartData, lineChartOptions);

            //-------------
            //- BAR CHART -
            //-------------
            var barChartCanvas = $("#barChart").get(0).getContext("2d");
            var barChart = new Chart(barChartCanvas);
            var barChartData = areaChartData;
            barChartData.datasets[1].fillColor = "#00a65a";
            barChartData.datasets[1].strokeColor = "#00a65a";
            barChartData.datasets[1].pointColor = "#00a65a";
            var barChartOptions = {
              //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
              scaleBeginAtZero: true,
              //Boolean - Whether grid lines are shown across the chart
              scaleShowGridLines: true,
              //String - Colour of the grid lines
              scaleGridLineColor: "rgba(0,0,0,.05)",
              //Number - Width of the grid lines
              scaleGridLineWidth: 1,
              //Boolean - Whether to show horizontal lines (except X axis)
              scaleShowHorizontalLines: true,
              //Boolean - Whether to show vertical lines (except Y axis)
              scaleShowVerticalLines: true,
              //Boolean - If there is a stroke on each bar
              barShowStroke: true,
              //Number - Pixel width of the bar stroke
              barStrokeWidth: 2,
              //Number - Spacing between each of the X value sets
              barValueSpacing: 5,
              //Number - Spacing between data sets within X values
              barDatasetSpacing: 1,
              //String - A legend template
              legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
              //Boolean - whether to make the chart responsive
              responsive: true,
              maintainAspectRatio: true
            };

            barChartOptions.datasetFill = false;
            barChart.Bar(barChartData, barChartOptions);

          }
        );

        $.getJSON(
          'http://localhost:3000/api/v1/pages/charts/chartjs/pie.json',
          function(data) {
            //-------------
            //- PIE CHART -
            //-------------
            // Get context with jQuery - using jQuery's .get() method.
            var pieChartCanvas = $("#pieChart").get(0).getContext("2d");
            var pieChart = new Chart(pieChartCanvas);
            
            var pieOptions = {
              //Boolean - Whether we should show a stroke on each segment
              segmentShowStroke: true,
              //String - The colour of each segment stroke
              segmentStrokeColor: "#fff",
              //Number - The width of each segment stroke
              segmentStrokeWidth: 2,
              //Number - The percentage of the chart that we cut out of the middle
              percentageInnerCutout: 50, // This is 0 for Pie charts
              //Number - Amount of animation steps
              animationSteps: 100,
              //String - Animation easing effect
              animationEasing: "easeOutBounce",
              //Boolean - Whether we animate the rotation of the Doughnut
              animateRotate: true,
              //Boolean - Whether we animate scaling the Doughnut from the centre
              animateScale: false,
              //Boolean - whether to make the chart responsive to window resizing
              responsive: true,
              // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
              maintainAspectRatio: true,
              //String - A legend template
              legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
            };
            //Create pie or douhnut chart
            // You can switch between pie and douhnut using the method below.
            pieChart.Doughnut(data, pieOptions);
          }
        );
      });
    </script>

ちょっと長いですが、大きく2つに分かれます。getJSON()で囲まれている3行目〜110行目までと、112行目以降です。

3行目〜110行目までは「http://localhost:3000/api/v1/pages/charts/chartjs/area_chart.json」にアクセスし、コールバック内で取得したJSONデータをAreaChart、LineChart、BarChartに設定しています。

112行目は「http://localhost:3000/api/v1/pages/charts/chartjs/pie.json」にアクセスし、コールバック内でPieチャートにデータを設定しています。

今回は「http://localhost:3000〜」とベタ書きしていますが、実案件ではこの辺は定数などに切り出した方がいいでしょう。

5.クライアントをWebサーバで動かす

クライアントをWebサーバ内で動かし、http〜でアクセスする方法についてです。starter.htmlについてはサーバと通信していないので、クライアントのみで動かすことができます。いろいろなWebサーバがありますが、今回はRubyのみで動かすことできる「WEBrick」を使用しました。ターミナルでclientフォルダへ移動し、以下のコマンドを実行します。

$ ruby -rwebrick -e 'WEBrick::HTTPServer.new({:DocumentRoot => "./", :Port => 8888}).start'

ポートは8888で起動しています。この状態でブラウザより「http://localhost:8888/starter.html」でアクセスすると、以下の様が画面が表示されるはずです。 スクリーンショット 2015-09-06 18.09.26

まとめ

クライアント側の実装について見てきました。クライアントをサーバから分離したことにより、サンプルから流用したhtmlファイルの修正箇所が少なく済んだかと思います。特にchartjs.htmlのJavaScriptについては、getJSON()のコールバック内のソースはサンプルをほとんど変更することなく実装できています。

次回、サーバ側の実装について書いていきたいと思います。

参考サイト

AdminLTE公式サイト
コマンド1つで今すぐWebサーバを起動させるためのワンライナー