2013年2月28日木曜日

[JavaScript]JSのlive関数のように動的に取得した要素にstyleを反映させるには

AJAXなどで動的に取得したHTML要素にstyleを反映させるにはどうするか。
最初からcssファイルに記述しておけばいいんだけど、値自体を動的に決めたい場合はどうするか。例えば、windowサイズに合わせて何かのサイズを決めたい時とか。

そんなときはhead内に動的にstyle要素を追加すればよいということがわかった。。
このサイトが参考になります。

jQueryのlive関数のように、後から追加されたエレメントに対して事前にスタイルを設定する方法

2013年2月12日火曜日

[Bootstrap]modal時に背景のスクロールを止める方法

https://github.com/jschr/bootstrap-modal/

このプラグインを導入すればいけますね。
ajaxとかも楽にできそうな感じなので今後使っていきたいと思います。

[Bootstrap]簡単にmodalにajaxでコンテンツを取得するスクリプト

http://twitter.github.com/bootstrap/javascript.html#modals 

ここで紹介されている方法だと、html内にdiv要素で枠組み準備しておかなかったりと、面倒くさいので以下のスクリプトを使うことにした。非常に簡単。

Dynamic (AJAX) loaded Bootstrap Modal (Bootstrap 2.1)




2013年2月11日月曜日

CakePHPでTwitter Bootstrapのpaginationを楽に表示するコード

pagination element for CakePHP on twitter bootstrap

このコードでいけました。超絶便利。
ただ、誰かのコメントにあるようソースの2行目の$modules$modulusに修正してね。

・使い方はこのファイルをelementsディレクトリに格納。
・view側で表示したい部分で以下のように呼び出す。
 ※カレントモデルと違うモデルでpaginationを行う場合は以下のようにモデル名を第二引数で指定してあげる。

<?php echo $this->element('pagination',array('model'=>'Theme')); ?> 

ちなみに、elementへ変数を渡せることを本件で知りました。
マニュアルには以下で載っています。

http://book.cakephp.org/1.3/ja/The-Manual/Developing-with-CakePHP/Views.html#id4

※CakePHPのバージョンはcakephp-cakephp-1.3.15-9-gacd25c3.zip

2013年2月9日土曜日

[JavaScript]画面ロード時にレイアウトがガタッっと一瞬崩れないようにするため

レイアウトに影響を与えるJavaScriptが外部ファイル化されていると、読み込み完了まで時間がかかるので、一瞬ガタっとレイアウトが崩れるように見えることがある。
今回の場合、それは、例えば以下のようなonload時に実行されるレイアウトに影響を与えるコマンドが、外部ファイルにあるためだった。

if($(window).width()>=980){
     $("#itemList").css("padding-top",$(".hero-unit").height()+50+"px");//hero-unitの大きさに合わせてpadding-topを変更
 }
なので、こちらをHTMLファイル内のbodyの閉じタグ直前の方に移した。
すると、ほとんど気にならないほど画面表示が速くなった。

2013年2月7日木曜日

[jQuery]flatheightsとheightLine.jsの使い勝手比較

ブロックレベル要素の高さをそろえてくれるjsライブラリについて使い勝手を比較する。

・jquery.flatheights.js
【メリット】
 対象の要素にクラス名を付与せずに使用できる。

【デメリット】
 呼び出すjsを書く必要がある。
 要素にpaddingやmarginが指定してある場合、高さがおかしくなる。
  http://d.hatena.ne.jp/AyeBee_TY/20120710/1341926286

heightLine.js
【メリット】
 要素にpaddingやmarginが指定してあっても正しく高さを調整してくれる。
 呼び出すスクリプトを書く必要がない。あるクラスを指定するだけで動作する。
http://blog.webcreativepark.net/2007/07/26-010338.html

【デメリット】
 クラス名をつけてあげなければ動かない


結局paddingとかで高さがおかしくなるのが嫌なので後者を使うことにした。


 
 

2013年2月1日金曜日

[CakePHP]どのviewでも共通して使うjsやcssをdefault.ctpで指定する

どのviewからも呼び出すjsファイルやcssファイルはdefault.ctp等のlayout側で指定してしまった方がコードの量が減らせます。

その指定の仕方。

default.ctp
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo $title_for_layout?></title>
<?php
    echo $html->css(array(
        '/bootstrap/css/bootstrap.min',
        '/bootstrap/css/bootstrap-responsive.min',
        'style'
        ),
        'stylesheet',
        array('inline'=>true)
    );
    echo $html->script(array(
        'jquery'
        ),
        array('inline'=>true)
    );
    echo $scripts_for_layout;
?>
</head> 
 
通常、view側で$html->css()や$html->script()を使用して指定したものが、レイアウト側の$scripts_for_layoutで出力されます。ですが、ここでは、どのviewからも呼び出すものは7~19行目のようにdefault.ctp側で指定しています。注意点は二つ。

・echoなどの出力系コマンドで出力する。(7,15行目)


 →view側で指定する場合は、 "echo $scripts_for_layout;"で出力されるのでecho等は必要なかった。

・inlineをtrueとする。(13、18行目)


 →ここで指定したものは$scripts_for_layoutではかせるのではなく、「その場」で吐かせるため。
   (inlineをfalseにするのは$scripts_for_layoutの中に入れ込むということ。ただし、layout側でfalseを指定した場合、$scripts_for_layoutに入ってこない。)

あと、これは作り方によりますが、基本的には上のコードのように"echo $scripts_for_layout;"の直前で出力させることになるかと思います。ベーシックなjs、cssなので、先に読み込ませるべきものが多いと思います。

[bootstrap]responsive時のnavbarのサブメニューが展開されない

Twitter Bootstrapにてsubmenuを表示するために下記の部分をクリックしてもなぜかサブメニューが表示されなかった。




このサンプルサイトを見たところ正常に動いていたので、ソースを見比べたところ下記の部分にcollapseというクラスが足りていなかった。

<div class="nav-collapse collapse">

下記のTwitterの説明ページの「Responsive navbar」のサンプルソースにもcollapseが書いてあるので、僕がどこかから変なソースを持ってきてしまったんだと思います。

http://twitter.github.com/bootstrap/components.html#navbar

[jQuery]CakePHPでjquery.infinitescroll.jsを使用した場合にスクロールを正常に終わらせるには

http://www.infinite-scroll.com/

上記で配布されているjquery.infinitescroll.jsであるが、スクロールが終わる条件は、私の知る限る二つある。

1.オプションのnextSelectorで指定されたリンクで指定された、次ページへのリクエストに対し404エラーが返される。
 →こちらの場合、オプションのfinishedMsgで指定された文言が最後に表示される。

2.オプションのmaxPageで最終ページを指定する。
→こちらの場合、finishedMsgはなぜか表示されない。

2の方法は、総ページ数をmaxPageに入れてしまえばいいので楽チンなのだが、やはり終わった時のメッセージは欲しい。
1の方法に関して。
当方、サーバサイドはCakePHPを使用している。CakePHPはデフォルトでは、最終ページを超えた数字が指定されても、最終ページの内容を出力し404エラーは出力しない。
なので、最終ページのnextSelectorで指定されたaタグに存在しないURLを指定したのだが、どうもうまくいかない。相変わらず最終ページの内容が出力される。
なぜかと思いfirebugで観察していたところ、どうやら、ベースになるURLは最初のページを表示したタイミングで作られ、incrementした数字をお尻に付加しているようだった。つまり、2ページ目以降のnextSelectorのaタグは見られていない。

なので、CakePHPで最終ページを超えた数字を指定された場合は404となるように細工することにした。その方法は以下で紹介している。

[CakePHP]pagination時に存在しないpageの場合は404を出すには

※CakePHPのバージョンはcakephp-cakephp-1.3.15-9-gacd25c3.zip


[CakePHP]pagination時に存在しないpageの場合は404を出すには

CakePHP1.3でのpaginationでは、urlの最後に"page:2"などのようにpageを指定する。
(2ページ目を表示させたい場合)
実際に存在するpage数より大きな数字を指定した場合、どうなるかというと、最終ページの内容が表示されてしまう。

発行されたSQLを見たところ、select文の最後に"LIMIT 20 10"のように指定し、目的のページのデータを取得する仕様のようだ。"LIMIT 20 10"の場合は、21行目から10件取得する時に付与される場合だ。つまり、1ページにつき10件の表示で3ページ目を表示する場合だ。
最終ページが3ページなのに4ページ目を表示しようとURLに"page:4"と付与しリクエストを行い、発行されたSQLを見たところ、"LIMIT 20 10"のままだった。これが原因のようだ。
なぜこのようになってしまうかはわからない。

最終ページより大きな数字を指定した場合でも、最終ページの内容を表示するのではなく、404などのエラーを出力させたいこともあると思う。そんな時は以下のコードをcontroller側に記述する。

if(!empty($this->params['named']['page'])){
    if($this->params['paging']['Theme']['pageCount']<$this->params['named']['page']){
        $this->cakeError('error404');
    }
}

$this->params['paging']['Theme']['pageCount']はページの総数、$this->params['named']['page']はリクエストがあったページ、が格納されている。後者は、ページ指定無しの場合(1ページ目を表示)は格納されないので、!emptyで確認している。

※CakePHPのバージョンはcakephp-cakephp-1.3.15-9-gacd25c3.zip

【追記2013/2/10】
上記の'Theme'は$this->paginate()で指定したモデル名を指定する。
ちなみに、どうやら上記のコードは$this->paginate()コマンドよりも後にやらないと正常に動かない。おそらく、paramsに入るこれらの値はpaginate()コマンドにより格納されるもののため。たぶん。