vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

JavascriptとCSSで表示切り替えとか

前回はTabを押した時にページ遷移をして(表示される内容は変わっていませんでしたが)内容を切り替えていました。

今回は、前回作ったものに更にボタン(ラジオボタン)を追加して、非同期でコンテンツの内容を変えてみます。

やったこと

  • ボタンを2つ追加して、それぞれを押した時にページの表示内容を非同期で切り替える
  • cssでビューポイントを設定して、ウインドウのサイズに合わせて表示内容のサイズを切り替える

はじめに

HTMLにおけるidとclassの関係を勘違いしており、前回のコードで一部同じidを複数箇所で使っているところがありました...。 また、idとclassは一つのタグに対してそれぞれ両方セットすることができるため、javascriptなどで特定の要素にアクセスする場合はidを、表示サイズなど複数要素で共有できるものはclassを使うことで、cssの量を減らすことができそうです。

ページ構成

public以下に、html/0.htmlとhtml/1.htmlというファイルを追加しています。
また、js/jquery-2.1.3.min.jsも追加しています(後述しますが、ネットから取得して利用する形でも問題ありません)。

プロジェクトのルートディレクトリ
Lapp.rb
Lconfig.ru
LGemfile
Lvendor
    Lbundle
        L...
Lpublic
    Ljs
        Ljavascript.js
        Ljquery-2.1.3.min.js
    Lhtml
        L0.html
        L1.html
Lviews
    Llayout.slim
    LviewTab.slim
    Lcss
        Lstylesheet.sass

ページ表示内容の切り替え

Ajaxについては以前もやりましたが、今回は表示したい部分のみを記述したHTMLファイルを作成しておき、それを呼び出して表示する、という処理を行います。

layout.slim

今回は非同期処理のためにjQueryを追加します。public/js/javascript.js同様、layout.htmlから読み込めるようにします。

doctype html
html
    head
        meta charset="utf-8"
        title TabTest
        link href="/css/stylesheet.css" rel="stylesheet"
    body onload==@updateTabs
        main#main
            == yield
        script src="/js/jquery-2.1.3.min.js"
        script src="/js/javascript.js"

viewTab.slim

前回のコードの「section#tab_frame」と同階層に、以下を追加します。

section#tab_frame
    〜(省略)〜
section#btn_frame
    input#btn_0 type="radio" name="btns" onchange="showContents(0);"
        label#btn_label_0.btn_label for="btn_0" ボタン0
    input#btn_1 type="radio" name="btns" onchange="showContents(1);"
        label#btn_label_1.btn_label for="btn_1" ボタン1
section#contents_frame
  • 「section#btn_frame」以下のボタンを切り替えることで、ページの表示内容を切り替えます。
  • 読み込んだhtmlは、「section#contents_frame」以下に追加します。

javascript.js

(function() {
    〜(省略)〜
    this.loadTabs = function(intNewTabNum, intLastRightTabNum){
        // ロード時に実行. Tabの表示切り替え、矢印ボタンのEnable/Disable.
        intTabNum = intNewTabNum;
        intRightTabNum = intLastRightTabNum;
        updateTabStyles();
        // デフォルトでボタン0のコンテンツが表示されるようにする
        document.getElementById("btn_0").checked = true;
        showContents(0);
    };
    〜(省略)〜
    this.showContents = function(intNewContentsNum){
        $.ajax({
            type: 'GET',
            url: '/async/' + intNewContentsNum,
            dataType: 'html',
            success: function(data) {
                $('#contents_frame').html(data);
            },
            error:function() {
                alert('Error');
            }
        });
    }
  • slimのボタンからだけでなくページロード時に実行する「loadTabs」からも「showContents」を呼んでいるのは、ページ表示時にコンテンツが表示されるようにするためです。

app.rb

〜(省略)〜
    get '/async/:name' do
        File.open("public/html/" + params[:name].to_s + ".html")
    end
end
  • 上記では(なんとなく)app.rbでルーティングし、取得したhtmlファイルを返す処理を入れています。
  • 「public/html」にアクセスするパスは、app.rbからの場合は「public/html/〜」、public/js/javascript.jsからは「/html/〜」となります。

非同期で呼び出すHTML

基本的には「section#contents_frame」以下に追加する部分だけをHTML形式で記述すればOKです。
ただし、そのままではHTMLは表示されてもCSSは反映されません。

そのため、呼び出すHTML内でスタイルを指定するか、CSSをロードする記述をしてやる必要があります。

0.html

< link href="/css/stylesheet.css" rel="stylesheet" >
< div class="zero" id="zero_1" >
< div class="zero_inside" id="zero_2" >< /div >
< /div >

1.html

< link href="/css/stylesheet.css" rel="stylesheet" >
< div class="one" id="one_1" >< /div >
< div class="one" id="one_2" >< / div >
< div class="one" id="one_3" >< /div >

レスポンシブデザインを取り入れてみる

画面やデバイスのサイズに合わせて、表示したコンテンツの大きさや並びなどを変更する、というレスポンシブデザインにトライしてみました。

やること

  • 画面サイズに合わせて複数CSSを作成して、HTMLで読み込むCSSを切り替える
  • 1枚のCSSファイルにそれぞれ記述して、画面やデバイスの状態に合わせて切り替える

今回は後者で作成しました。

stylesheet.sass

$screen_s: 768px
$screen_m_from: 769px
$screen_m_to: 1536px
$screen_l: 1537px

@media only screen and (max-width: $screen_s)
    #main
        background-color: green
        height: 350px
        width: 600px
@media only screen and (min-width: $screen_m_from) and (max-width: $screen_m_to)
    #main
        background-color: red
        height: 525px
        width: 900px
@media only screen and (min-width: $screen_l)
    #main
        background-color: blue
        height: 700px
        width: 1200px

基本的には上記のような感じで、表示したウインドウの横幅の最小値(min-width)や最大値(max-width)を設定して、合致したものを適用します。

  • 切り替え自体は自動で行われます。
  • 背景色など画面サイズに関係がないものは「@media 〜」の子や孫にならないように書いておけば、すべての条件で適用されます。
  • サイズを%で指定している場合は「@media 〜」の条件によらず親に合わせてサイズ変更されるため、これも別途書いておけばOKです。
  • 画面サイズを変数として使用できますが、「only screen and (max-width: 768px)」自体を変数とした場合はエラーとなり、使用できませんでした。

というわけでSASSのコードを載せておきます。

stylesheet.sass

$screen_s: 768px
$screen_m_from: 769px
$screen_m_to: 1536px
$screen_l: 1537px
@media only screen and (max-width: $screen_s)
    #main
        background-color: green
        height: 350px
        width: 600px
    .btn_label
        font-size: 10px
        height: 100%
        width: 20%
        border: 1px solid #000
        border-radius: 5px
        float: left
    #zero_1
        border-radius: 50%
        height: 190px
        width: 140px
        margin: 40px 0px 0px 230px
        overflow: hidden
    #zero_2
        border-radius: 50%
        height: 160px
        width: 110px
        margin: 15px 0px 0px 15px
    #one_1
        height: 45px
        width: 15px
        margin: 40px 0px 0px 282.5px
        transform: rotate(45deg)
        -moz-transform: rotate(45deg)
        -webkit-transform: rotate(45deg)
    #one_2
        height: 190px
        width: 15px
        margin: -43.5px 0px 0px 300px
    #one_3
        height: 15px
        width: 76px
        margin: 0px 0px 0px 269.5px
@media only screen and (min-width: $screen_m_from) and (max-width: $screen_m_to)
    #main
        background-color: red
        height: 525px
        width: 900px
    .btn_label
        font-size: 15px
        height: 100%
        width: 20%
        border: 1px solid #000
        border-radius: 7.5px
        float: left
    #zero_1
        border-radius: 50%
        height: 285px
        width: 210px
        margin: 60px 0px 0px 345px
        overflow: hidden
    #zero_2
        border-radius: 50%
        height: 240px
        width: 165px
        margin: 22.5px 0px 0px 22.5px
    #one_1
        height: 67.5px
        width: 22.5px
        margin: 60px 0px 0px 423.75px
        transform: rotate(45deg)
        -moz-transform: rotate(45deg)
        -webkit-transform: rotate(45deg)
    #one_2
        height: 285px
        width: 22.5px
        margin: -65.25px 0px 0px 450px
    #one_3
        height: 22.5px
        width: 114px
        margin: 0px 0px 0px 404.25px

@media only screen and (min-width: $screen_l)
    #main
        background-color: blue
        height: 700px
        width: 1200px
    .btn_label
        font-size: 20px
        height: 100%
        width: 20%
        border: 1px solid #000
        border-radius: 10px
        float: left
    #zero_1
        border-radius: 50%
        height: 380px
        width: 280px
        margin: 80px 0px 0px 460px
        overflow: hidden
    #zero_2
        border-radius: 50%
        height: 320px
        width: 220px
        margin: 30px 0px 0px 30px
    #one_1
        height: 90px
        width: 30px
        margin: 80px 0px 0px 565px
        transform: rotate(45deg)
        -moz-transform: rotate(45deg)
        -webkit-transform: rotate(45deg)
    #one_2
        height: 380px
        width: 30px
        margin: -87px 0px 0px 600px
    #one_3
        height: 30px
        width: 152px
        margin: 0px 0px 0px 539px
#arrow_button_left
    left: -999px
    position: absolute
    top: -999px
#arrow_button_right
    left: -999px
    position: absolute
    top: -999px
input[type="radio"]
    top: -999px
    left: -999px
    position: absolute
#tab_frame
    height: 10%
    width: 100%
.arrow_label
    background-color: #FFF
    height: 100%
    width: 3.3%
    border: 1px solid #000
    border-radius: 5%
    display: block
    float: left
input[type="button"]:disabled + #arrow_label
    background-color: #111
    height: 100%
    width: 20px
    border: 1px solid #FFF
    border-radius: 5%
    display: block
    float: left
.tab_label
    height: 100%
    width: 140px
    border: 1px solid #000
    border-radius: 5%
    float: left
#tab_label_0
    background-color: #FFF
#tab_0:checked + #tab_label_0
    background-color: #000
#tab_label_1
    background-color: #FFF
#tab_1:checked + #tab_label_1
    background-color: #000
#tab_label_2
    background-color: #FFF
#tab_2:checked + #tab_label_2
    background-color: #000
#tab_label_3
    background-color: #FFF
#tab_3:checked + #tab_label_3
    background-color: #000
#tab_label_4
    background-color: #FFF
#tab_4:checked + #tab_label_4
    background-color: #000
#btn_frame
    height: 5%
    width: 100%
    overflow: hidden
#btn_label_0
    background-color: #386B88
#btn_0:checked + #btn_label_0
    background-color: #DEB67E
#btn_label_1
    background-color: #386B88
#btn_1:checked + #btn_label_1
    background-color: #DEB67E
#contents_frame
    background-color: #7AB900
    height: 84.8%
    width: 100%
    overflow: hidden
.zero
    background-color: #E7850E
.zero_inside
    background-color: #7AB900
.one
    background-color: #E7850E

  • ちなみに表示されるのは、CSSで表現した0と1の文字です。
  • 角丸のborder-radiusは、正円を描く場合は%指定が必要ですが、ボタンなどの角を丸くする場合はpx指定しないと元の四角の形が崩れてしまい、うまく角が丸まりません。

参考

Ajax

Sinatraでのファイルアクセス

レスポンシブデザイン

CSS