同じにやっても動かない

書いてある通りやっているのに動かないのです

navbarからmodal windowを呼び出すと、操作できないmodal windowが描画される on Twitter Bootstrap

何を言っているのかわからないと思いますので、まずは画像をどうぞ。

f:id:nyarugo:20130709233257p:plain


画像上部にNavigation barがあって、右端の Modal A / Modal B リンクをクリックすることでModal windowが描画されます。
画像は、Modal Aをクリックした状態です。


Modal window ボタンA/BというのがあるWindowがModal windowなのですが、全部後ろに描画されてしまっていて操作ができません。

調べてみると ".navbar .navbar-fixed-top" の z-indexが1030であるのに対し、半透明の黒いレイヤーである ".modal-backdrop" の z-index が1040なので、これが原因のようです。

cssでz-indexを1030より小さい値でオーバライドしてみます。

.modal-backdrop {
  z-index: 1020; 
}


治りました。


f:id:nyarugo:20130709233809p:plain


でも、画像の上部を見るとわかるように navbar も有効になってしまっているので、厳密にはmodal windowではありません。


例の様にnavbarに modal windowへのリンクを2種類持っている場合は、どちらもクリックできてしまうので2つのmodal windowが同時に描画されてしまいます。

これをさけるために、modal windowの toggleはjavascriptを使う事にしました。

<script type="text/javascript">
function clickModalA() {
    $("#modalA").modal('hide');
    $("#modalB").modal('show');
}

function clickModalB() {
    $("#modalB").modal('hide');
    $("#modalA").modal('show');
}
</script>
<ul class="nav pull-right">
  <li><%= link_to "Modal A", "#", {"onclick"=>"clickModalA()"} %></li>
  <li><%= link_to "Modal B", "#", {"onclick"=>"clickModalB()"} %></li>
</ul>


よくわからないのが、この問題、ブラウザをフルウィンドウで表示しているときにだけ発生します。
ブラウザを少しでもリサイズしている場合は、z-indexをオーバライドしなくても、全部後ろに描画されることも navbar が有効になることもなく、問題無く動くのです。


[ブラウザサイズをリサイズしてある場合。z-indexのオーバライドはしていない]
f:id:nyarugo:20130709234405p:plain


media typeで色々とCSSを書き換えている(しかも適当に)ので、それが原因しているかもしれないのですが、とりあえずこれでしのぐことにします。

サムネイルが2段目からずれる on Twitter Bootstrap その2 (IE対応)

Bootstrapのサムネイルが2段目からずれる件、cssのnth-childを使用して対応したエントリを先日書きましたが、IEだとnth-childプロパティが効かない事がわかりました。。。

調べてみると、jqueryにもnth-childというメソッドがあるようでしたので、こんな感じで試してみます。

$(document).ready(function(){
    $(function() {
	$("ul.thumbnails li.span3:nth-child(4n+1)").css("margin-left", "0px")
    })
})

IEでもずれなくなりました。

span3 と nth-cildの中身(4n+1)の関係はこちらを参照くださませ。


クロスブラウザ対応って大変なんですね。

formのtextarea幅が変わらない on Twitter Bootstrap

Bootstrapのフォームのtextarea 幅が変わらないんです。
size属性を指定しても、style属性でwidthを指定してもtextareの幅は全く変わらず。

グーグル先生に登場願ったら、なんと、グリッドレイアウトが効くと書いてありました

これならレスポンシブデザインでも問題なしです。


結局こんな感じで使っています。

  <%= f.input :profile, input_html:{class: "span7", rows: 10} %>

Dragonflyでファイルが本当に画像ファイルかチェックしたい

Dragonflyのドキュメントを見ると、ファイルの拡張子を見て画像ファイルかを判断しvalidationを行う例が載っています

例えばモデルにこの様に設定すると、指定拡張子のファイル以外はvalidationエラーとなります。

  validates_property :format, :of => :photo_image, :in => [:jpeg, :jpg, :png, :gif], :case_sensitive => false

これってファイルの中身まで見て判断しているのか、それとも拡張子名だけで判断しているのか知りたかったので、適当なテキストファイルの拡張子をpngに変えて登録してみました。

Validationエラーは出ず、しっかり登録されてしまいました。


画像ファイルの中身が壊れていたりということもあると思うので、ファイルのフォーマットをチェックしてくるメソッドがないかなあと思って、Documentを漁っていた所、さすがです、しっかり用意してあります。

def image?(temp_object)
  !!catch(:unable_to_handle){ identify(temp_object) }
end

ImageMagickのidentifyコマンドを使用しているので、ちゃんと中身を見ています。

textファイルの拡張子をpngに変更したファイルを登録し、コンソールで試してみたらバッチリでした。
※ image_file、dummy_fileとも拡張子はpngファイルですが、dummy_fileの中身はテキストです。

> rails c
irb(main):002:0> image_file = Photo.find(:correct_image_file_id)
irb(main):003:0> image_file.photo_image.image?
=> true
irb(main):002:0> dummy_file = Photo.find(:dummy_file_id)
irb(main):003:0> dummy_file.photo_image.image?
=> false

というわけで、こんな感じのValidationにすることとします。

  validates_property :format, :of => :photo_image, :in => [:jpeg, :jpg, :png, :gif], :case_sensitive => false
  validates_property :image?, :of => :photo_image, :in => [true]

菜箸と統計的思考

うちには持ち手の部分の色が赤と黒で、他の部分は長さも形も全部同じ見た目の菜箸が二膳あります。


その菜箸、二膳で四本を箸先を上にしてごカゴに入れてあり、料理をするときはそこから二本取るのですが、カゴの中は見えない(色が付いている持ち手の部分が見えない)ので菜箸の組み合わせが必ずしも正しくならないわけです。

というか、非常に高い確率で間違った組み合わせ(赤と黒)になってしまう。
同じ二本ずつなのになんで間違った組み合わせばかりになるのだろうと、ずっと不思議だったので、まじめに確率を考えてみました。

そしたらなんと二倍違う。
すなわち観測結果は正しいという事。


[同じ色の組み合わせになる確率]
1/3 ※ 最初の一本と同じ色は、残りの三本の内一本だけ


[間違った組み合わせになる確率]
2/3 ※ 1 - 1/3


私の確率的思考が全く訓練されていないのが原因なわけですが、
人間の直感はこんな簡単な確率ですら正しく扱えないのだなあと、改めて感じた次第。


で、下記は人間の直感はどういうときに正しくて、どういうときに間違えるのかという話が、脳は統計的思考が苦手だという沢山の実験と一緒に説明されている本です。

また読んでみるかなあ。

フォームボタンもbootstrapのUIにしたら、operaで動かなくなった

フォームのボタンをbootstrapのUIにしたい

form_forでフォームを生成するとファイル選択ボダンが普通のボタンになってしまい、せっかくbootstrapを使っているのに残念でなりません。

ググってみると同じ事を思っている方は沢山いらっしゃるようで、先人の智恵を借り、下記のようにbootstrap UIのダミーボタンを使うことにより解決できました。

<!-- bootstrap UIのダミーボダン。onclickイベントで、フォーム(#photo_photo_image)をクリック -->
<div class="upload-button"><a class="btn btn-default" onclick="$('#photo_photo_image').click()">ファイルの選択</a></div>

<!-- ファイルアップロードフォーム。display:"none"で非表示に -->
<%= form_for(@photo, :html=>{:multipart=>true}) do |f| %>
  <div class="field">
    <%= f.file_field :photo_image, style:"display: none" %>
  </div>
<% end %>


これで、Chrome / Firefox / IE は問題なく動作したのですが、なぜかOperaではうんともすんともいいません。

Operaで動かす

がんばってググると、完全に同じ問題がstackoverflowでやり取りされていました。

Operaで動かすには、下記2点がポイントになるようです。

  1. "display: none"のかわりに、"visibility: hidden" を使う
  2. htmlのonclick属性ではなく、全部jqueryでやる

これでOperaでも動くようになりました。
ソースはこんな感じです。

<!-- ダミーボタンクリックでフォームボタンをトリガーするJQuery -->
<script type="text/javascript">
$('#dummy-btn').on('click', function() {
  $('#photo_photo_image').click()
});
</script>

<!-- ダミーボタン JQueryからトリガーするために id="dummy-btn"を追加 -->
<div class="upload-button"><a class="btn btn-default" id="dummy-btn">ファイルの選択</a></div>

<!-- "visibility: hidden"で見えなくしたフォーム -->
<%= form_for(@photo, :html=>{:multipart=>true}) do |f| %>
  <div class="field">
    <%= f.file_field :photo_image, style:"visibility:hidden" %>
  </div>
<% end %>


"visibility: hidden"だと、input要素の大きさがそのまま余白となってしまうので、CSSで適当につぶしておきました。