Techracho

JavaScriptって便利ですね

このエントリーをはてなブックマーク Share
2009.08.28    CakePHP, PHP, Web, javascript, 渡辺      peter   

JavaScriptってあまり好きじゃないけど便利なものありますね。
先達者の皆様にいつも感謝です。

中でも普段の受注制作で使えそうで、
個人的に興味がある/好きなもの紹介してみます。

Anything Slider
http://css-tricks.com/examples/AnythingSlider/#panel-5
画像とか動画とかスライドできちゃいます。
ちょっとした“魅せ”にはいいですよね。
以外と感動してくれるお客様もいそうです。

CakePHP×FCK Editor
http://d.hatena.ne.jp/slywalker/20081125/1227621414
CMSで自由に画像を加えたりフォーマットをいじるためには、
HTMLを許容したり自由度を下げたりしないといけないですよね。
WordPress-likeなエディタUIを加えてあげることで
編集しやすいCMSをつくるのもいいですよね。

dojoの細かいTIPS

このエントリーをはてなブックマーク Share
2009.08.22    CSS, HTML, dojo toolkit, javascript, 馬場      baba   

dojo使いには当たり前かもしれない、ちょっとしたTIPSです。

(1)dojo.byId
dojo.byIdは、HTMLのエレメントを渡すと、そのまま帰ってきます。
つまり、dojo.byId(dojo.byId(’hoge’)); とやっても正常に動作します。

なので、dijit等で「ノードのIDを渡す」と書かれているところに、直接エレメントを渡しても、たいてい上手く動きます。
動的に要素が増えてIDを付けにくい場合などに、ちょっと役立ちます。

(2)dojo.query
dojo.queryは、CSSのセレクタで要素を選択できる便利なものです。
この第2引数にHTMLのエレメントを渡すと、その子要素のみ検索対象になります。

var img = dojo.query('img', hogeNode)[0];

基本かつ必須な機能のはずなのに、なぜか解説サイトにあまり書いていないという。。

(3)dojox.layout.ResizeHandle
ドラッグ&ドロップはサンプルがたくさんあるのに、リサイズはなぜか少ないですね。
dojoはリサイズも簡単なので、以下にサンプルを載せておきます。

<html>
<head>
	<script type=”text/javascript” src=”dojo/dojo.js”></script>
	<script type=”text/javascript”>
		dojo.require(’dojox.layout.ResizeHandle’);
		dojo.addOnLoad(function() {
		var handle = new dojox.layout.ResizeHandle({
		activeResize:true,
		minWidth:30,
		minHeight:30,
		targetId: ‘box’
		}, dojo.byId(’handle’));
		});
	</script>
	<link rel=”stylesheet” href=”dojox/layout/resources/ResizeHandle.css” />
</head>
<body>
	<div id=”box” style=”position:relative; background:yellow;”>
		<p>リサイズできます</p>
		<div id=”handle”></div>
	</div>
</body>
</html>

↓動作サンプル


リサイズ可能

JavaScriptでCSSのプロパティを削除する(IEでfilterがあるとClearTypeが無効になるバグ対策)

このエントリーをはてなブックマーク Share
    CSS, dojo toolkit, javascript, 馬場      baba   

javascriptからCSSを変更したい場合は、

//生
var node = document.getElementById('hoge');
node.style.marginLeft = '10px';

//dojo
dojo.style(dojo.byId('hoge'), 'marginLeft', '10px');

といった感じになります。

しかしこれだと、CSSのプロパティ自体を削除することはできません。

普段はそんな必要も無いのですが、IEにはfilterプロパティの付いた要素のその子要素でフォントのアンチエイリアス(ClearType)が効かなくなるというバグがあるので、filterプロパティ自体を削除したいことがあります。

node.styleで取得できるオブジェクトはCSSStyleDeclarationで、これにはremoveProperty()というメソッドがあるので、

node.style.removeProperty('filter');

とすれば良さそうです。

しかしIEではなぜかこれが未定義です。代わりにremoveAttributeが使えます。

なので、

var node = document.getElementById(’hoge’);
if (node.style.removeProperty) {
	node.style.removeProperty(’filter’);
}
if (node.style.removeAttribute) {
	node.style.removeAttribute(’filter’);
}

のような使い方になります。

—–具体的な使用例—–
dojoでは簡単にフェードインが使えます。
しかし、IEだと、フェードインした要素はフォントがガタガタになります。特にメイリオ等のアンチエイリアス前提フォントだと悲惨です。
以下のようにonEndを設定することで、フェードイン完了後はなめらかになります。

//fadeInを使うのであらかじめ透明度を0にする
dojo.style(dojo.byId(’hoge’), ‘opacity’, ‘0′);

(new dojo.fadeIn({
	node: ‘hoge’, //フェードインさせるノードのID
	duration: 1000, //ミリ秒
	onEnd: function() {
		var node = dojo.byId(’hoge’);
		if (node.style.removeProperty) {
			node.style.removeProperty(’filter’);
		}
		if (node.style.removeAttribute) {
			node.style.removeAttribute(’filter’);
		}
	}
})).play();

上がonEndを設定しない場合、下が設定した場合です。メイリオフォント使用。
090822_cleartype

dojoで角丸ボタン

このエントリーをはてなブックマーク Share
2009.08.11    CSS, dojo toolkit, javascript, 馬場      baba   

dojo toolkitはデフォルトで各種ウィジェットが付いていて便利ですが、現時点ではまだテーマが充実していません。
実質的に使えるのは、tundraとsoriaくらいだと思います。

どちらもコントロールが角張っているので、丸くしたくなることがあります。

ダイアログの角丸は、-moz-border-radius / -webkit-border-radius を使えば簡単にできますが、IEなどにも対応しようと思うと、ウィジェットテンプレートを書き換えたりJavascriptで要素を書き換えたりしないといけません。

ボタン(高さ固定)は、IEを含め比較的簡単に角丸にできますので、今回はこちらを紹介します。

テーマの自作になりますので、まずはsoriaあたりをコピーして、これを上書きしていくことにします。
soria.css を mytheme.css にリネームして、.soria を .mytheme に一括置換(手抜き)してしまいましょう。

そして、角丸実現のために以下のような記述を追加します。

.mytheme .dijitButtonNode .dijitButtonContents {
	background: url(images/button_back.png) repeat-x 0 0;
}
.mytheme .dijitButton .dijitRight {
	background: url(images/button_right.png) no-repeat top right;
}
.mytheme .dijitLeft.dijitButton {
	background: url(images/button_left.png) no-repeat top left;
}

button_leftは左側の丸い画像、button_rightは右側の丸い画像、button_backは中央の矩形部分の画像です。
これらのファイルは自分で作ってimagesに入れておきます。
これだけで丸くなります。

ちゃんとやるときは、soriaテーマをきちんと解読して矛盾が無いようにすべきですが、小規模ならこんな安易な改造も可能です。

IE7でmarginが消える

このエントリーをはてなブックマーク Share
2009.06.25    CSS, HTML, 馬場   タグ: , —    baba   

たぶん既出ネタですが、ふと見つけたので一応。
IE7で、marginが消える場合があります。

再現条件は、
・paddingが0以外のブロック要素Aに囲まれている
・Aの最初の子要素(空白・TAB・改行以外)がブロック要素Bである
・Bにheightとmarginが指定してある(たぶんhasLayoutがtrueになるならheight以外でも該当)
こんな感じみたいです。

これらを満たすと、Bのmarginが無視されます。
シンプルな再現HTMLは以下の通りです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<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>test</title>
</head>
<body>

<div style="padding:1px;">
<div style="margin:100px; height:20px;">こんにちは</div>
<div style="margin:100px; height:20px;">ハロー</div>
</div>

</body>
</html>

これを開くと、IE7以外では「こんにちは」と「ハロー」の左端はそろいますが、IE7では「こんにちは」が左に寄ってしまいます。

解決するには、Bを先頭子要素でなくせばいいので、適当なコメントを入れます。

<div style="padding:1px;">
<!– bugfix for IE7 –>
<div style="margin:60px; height:20px;">こんにちは</div>
<div style="margin:60px; height:20px;">ハロー</div>
</div>

やっぱりIE7は地雷ですね。
自動更新でIE8が入るようになったのがせめてもの救いです。

EthnaのimportFormの強化版

このエントリーをはてなブックマーク Share
2009.04.15    Ethna, PHP, Web, 馬場      baba   

EthnaのAppObject::importForm()は便利ですが、DBの全カラムと同じ名前のform値を取得してしまうため、たとえばzipcodeはハイフン前後で2つのFormを用意して結合した値をセットする、等の処理が少々やりにくいです。
また、どの値がインポートされるのか見えにくいのが何となく気持ち悪い、という人もいると思います。

そこで、AppObjectに下記のようなメソッドを作ってみました。
実際には全AppObjectの基底クラスにすると良いと思います。

class AppId_Hoge extends Ethna_AppObject
{
  function setAll($list, $option = null)
  {
    foreach ($list as $key => $data) {
      $name = ”;
      $value = ”;
      if (is_int($key)) {
        //連想配列のキーが数値の場合は、連想配列の値と同名のform値をセットする
        $name = $data;
        $value = $this->af->get($data);

        //値がNULLの場合、オプション指定によって、無視するか空文字列に変換するかを決定する
        if (is_null($value)) {
          if ($option == OBJECT_IMPORT_IGNORE_NULL) {
            //NULLを無視
            continue;
          } else {
            $value = ”;
          }
        }
      } else {
        //それ以外の場合、連想配列のキーがそのまま名前に、連想配列の値がそのまま設定すべき値になる
        $name = $key;
        $value = $data;
      }

      if (isset($this->prop_def[$name]) == false) {
        Ethna::raiseError(”Unknown property $name”);
        return null;
      }
      $this->set($name, $value);
    }
  }
}

使うときは

$list = array(
  ’user_name’,
  ’password’,
  ’zipcode’ => $this->af->get(’zipcode1′).$this->af->get(’zipcode2′)
);
$obj =& $this->backend->getObject(’Hoge’);
$obj->setAll($list);

のようにすると、単純に配列指定したuser_nameとpasswordはForm値が直接セットされ、連想配列になっているzipcodeは、$list['zipcode']の値がセットされます。
これによって、ほとんどの値はActionFormからそのままセットするが、任意のフィールドだけを特別な値にする、といった処理が簡単になります。

Ethnaでレイアウト

このエントリーをはてなブックマーク Share
    Ethna, PHP, Web, 馬場   タグ: —    baba   

割と既出ネタですが。。。

Ethnaでも、CakePHPなどのようなレイアウトテンプレートを使いたくなります。
ViewClassのforwardを変更すると、意外と簡単に実現できました。
Controllerの$directoryに’layout’のパスをセットして、ViewClassのforwardを下記のようにオーバーライドします。

class AppId_ViewClass extends Ethna_ViewClass
{
function forward()
{
//Rendererを取得
$renderer =& $this->_getRenderer();
$this->_setDefault($renderer);

//各Viewのコンテンツを取得
$contents = $renderer->perform($this->forward_path, true);


//レイアウトを取得
$layout = $renderer->getProp(’layout_file’);
if ($layout) {
$controller =& $this->backend->getController();
$dir = $controller->getDirectory(’layout’);
$layout_file = $controller->getDirectory(’layout’) . ‘/’ . $layout . ‘.’ . $controller->getExt(’tpl’);
$renderer->setProp(’contents’, $contents);
$renderer->perform($layout_file);
} else {
echo $contents;
}
}

これで、各tplで
{assign var=”layout_file” value=”default”}
と指定すれば、default.tplが呼ばれて、default.tpl内の {$contents} のところに各Viewのコンテンツが挿入されます。

レイアウトファイルに各Viewのテンプレート内から値を渡したいときは、{assign}を使えばOKです。
tplの見通しが良くなって、便利ですよ。

EthnaでXML-RPCの引数を連想配列にする

このエントリーをはてなブックマーク Share
2009.03.04    PHP, Web, ネットワーク, 馬場   タグ: , —    baba   

Ethnaは標準でXML-RPCに対応しているので、
# ethna add-action-xmlrpc hoge
とやるだけで app/action-xmlrpc にActionのテンプレートが作れますし、クライアントからHogeメソッドをコールすると、自動的にHogeアクションが実行されます。
(エントリポイントはindex.phpではなくxmlrpc.phpになります)

しかし、デフォルトでは引数がActionFormのform定義と順番に1対1で対応するため、引数が多くなると使いづらくなります。

ここは、PHPらしく引数名をキーにした連想配列にしたいところ。
(プロジェクト名)_Controller に以下のメソッドを定義(オーバーライド)することで、XMLRPCの第一引数を連想配列として扱い、対応する名前のformに値がセットされるようになります。

function trigger_XMLRPC($method, $param)
{
    // アクション定義の取得
    $action_obj =& $this->_getAction($method);
    if (is_null($action_obj)) {
        return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
    }

    // オブジェクト生成
    $backend =& $this->getBackend();

    $form_name = $this->getActionFormName($method);
    $this->action_form =& new $form_name($this);
    $def = $this->action_form->getDef();
    
    /***** ここから変更 *****/
    if (isset($param[0]) && is_array($param[0]))
    {
        foreach ($param[0] as $key => $value)
        {
            if (isset($def[$key]))
            {
                $this->action_form->set($key, $value);
            }
        }
    }
    /***** ここまで変更 *****/

    // バックエンド処理実行
    $backend->setActionForm($this->action_form);

    $session =& $this->getSession();
    $session->restore();
    $r = $backend->perform($method);

    return $r;
}

これで、クライアント側では引数の順番を気にせずに済みます。

IE7でposition:relativeの要素が重なるバグ

このエントリーをはてなブックマーク Share
2009.03.03    HTML, javascript, 馬場   タグ: , , , , —    baba   

IE7で、JavaScriptを使って動的に要素を表示・非表示した場合、要素が重なってしまうことがあります。

実験ページ

IE7だと問題が再現し、IE8やFirefoxは再現しません。また、冒頭のDOCTYPE宣言を外してQuarksモードにしても再現しません。
IE7でのみ、Showボタンを押すと、文字が重なってしまうはずです。

不思議なことに、21行目のbackground指定を外すと、再現しません。
また、21行目の<div>開きと22行目の<div>開きの間に「スペース・TAB・改行以外の何か(コメントでも可)」を入れると、再現しません。
22行目の[height:2em] は、hasLayoutがtrueになれば何でもOKです。

まとめると、
・ブロック要素Aがある。
・Aの最初の子要素はブロック要素Bである。
・AはCSSで背景がnone以外に指定されていて、[hasLayout=false]である。
・Bは[position:relative] であり、なおかつ[hasLayout=true]である。

これらの条件を満たす場合、「Aの前にある要素の高さが変わり、AのY座標が変更になっても、BのY座標は再計算されない」というIE7独自のバグと言えそうです。

DebugToolbar等で位置の再計算を行うと、正しい位置に移動します。

おそらく計算順序にバグがあるのだと思います。position:relativeを使うときは気をつけましょう。

Ruby on Railsでコントローラでヘルパーメソッドを呼ぶ

このエントリーをはてなブックマーク Share
    Ruby, Ruby on Rails, Web, フレームワーク, 伊藤   タグ: , —    tomotaka   
# app/controllers/application.rb
ApplicationController < ActionController::Base
  class HelperImpl
    include ::Singleton
    include ::ApplicationHelper
  end

  protected

  def helper
    return HelperImpl.instance
  end
end

これでコントローラからApplicationHelperに定義されてるメソッドをhelperメソッド経由で呼べる。

« 新しい投稿古い投稿 »

COPYRIGHT [C] 2009 BEYOND PERSPECTIVE SOLUTIONS LTD. ALL RIGHTS RESERVED.