Latest Publications

第三回勉強会、開催します

前回からかなり間が空いていしまった勉強会ですが、やっと第三回の告知を行うことが出来ました。

デザイナーのためのプログラミング入門

↑詳細はコチラから

開催日は5月23日(土)、13:00~です。参加費は無料です。

今回はCSSとPHPの二本立てでお送りします。

う~ん、CSSはプログラミング言語なのか?という疑問は置いておいて、要望を頂いたのでやります。

テキストも現在作成中ですが、CSS初心者の方向けで、かつ「CSS知ってるよ」という方にもちょっと読み応えのある

内容になりそうです。若干マニアックです。

PHPは前回の続きになりますね。…といっても、また基礎に戻ってループやら関数やらをまとめようという感じです。

基礎は大事ですよね、何事も。

でも、ただ単にループとかやってもきっと退屈なので、何か趣向を凝らさねば、と。

ともあれ、無料なので5月末にちょっと時間のある方はどうぞご参加下さい。

とっても優しい講師&スタッフが、分かるまで教えます。交流会もあるので個人的な質問もあればその時にどうぞ。

ブラウザ判定スクリプト

JavaScriptを扱う上で必須となるブラウザの判定。

一般的には、

IEなら document.all かdocument.createPopup があるかで判定、

Operaなら window.opera があるかで判定

ってやるのが簡易的でしょうか。

ただ、毎回document.allってやるってどうにも冗長な感じがしたので、

navigator.userAgentから判定するスクリプトを作ってみた。いや、作ったって言うほどすごいものでははないですね。

function Browser(){
var res = {};
var ua = navigator.userAgent.toLowerCase();
res.IE = (ua.indexOf(‘msie’, ua) != -1 && ua.indexOf(‘opera’,ua) == -1) ? true : false;
res.IE7 = (ua.indexOf(‘msie’, ua) != -1 && ua.indexOf(‘7.0′, ua) != -1 && ua.indexOf(‘opera’) == -1) ? true : false;
res.IE8 = (ua.indexOf(‘msie’, ua) != -1 && ua.indexOf(‘8.0′, ua) != -1 && ua.indexOf(‘opera’) == -1) ? true : false;
res.IE6 = (ua.indexOf(‘msie’, ua) != -1 && ua.indexOf(‘6.0′, ua) != -1 && ua.indexOf(‘opera’) == -1) ? true : false;
res.Firefox = (ua.indexOf(‘gecko’, ua) != -1) ? true : false;
res.Safari = (ua.indexOf(’safari’, ua) != -1 && ua.indexOf(‘chrome’, ua) == -1) ? true : false;
res.Opera = (ua.indexOf(‘opera’, ua) != -1) ? true : false;
res.GoogleChrome = (ua.indexOf(‘chrome’, ua) != -1) ? true : false;
return res;
}

こんな感じ。本当ならSafariは 「indexOf(‘Appleうんたらかんたら」 をチェックすべきなのかも知れないですね。

まぁ普段使いには問題ないかと。

br = new Browser();

でインスタンスを作って、判定のときに、

if (br.IE){ //IEだけの処理  }

ってやれば判定は簡単。IEならバージョン分けもできるので楽ですね。

今更知ったsubstr

PHPでも「substr」ってありますよね。

特定位置から先の文字列を抽出するアレです。

JavaScriptにもあります。

String.substr

見たいな感じで。

最近PHPばかり書いててJavaScriptをあんまり書かなかったせいかもしれませんが、

PHPで、

substr($str, -1);

とかやると末尾から文字を切り取りますよね。

で、JavaScript。

文字列 str = ‘abcdefg1′;

str.substr(-1, 1);

とかやると、Firefoxではちゃんと1が返ってくる。

ところがIEだと、何故かaが返ってくる。おいおい、-1を解釈しないのかよ><

意外なところでまたブラウザの違いに悩まされた。特定のIDから配列のインデックスを抽出しようとしたら、

IEは何度やってもundefined。30分はハマった。

本当に困った方ですね、IEさんは。

・・・っていうかこんな細かいところに挙動の違いが有るなんて知らなくて驚いた。

IEのイベント設定(window.mousemoveはダメらしい)

ツールチップを表示するライブラリを作っていますが、結構既出な問題のくせにすっかり忘れてました。

イベントモデルレベル2だと問題なうのですが、IEのイベントモデルにおいて、

window.attachEvent(‘onmousemove’, listerner);

これだとマウスを動かしても検出してくれない。すっかり忘れていた。

正しくは、

window.document.attachEvent(‘onmousemove’, listener); (windowは省略可能)

ですね。documentが無いとダメってことは、やっぱり基本的にDOMが構築されてからじゃないとイベント設定は難しいのかな。

前処理的に必要なイベントリスナを登録しておきたいのに。

結局30分悩んでしまいました。

やっぱりクロスブラウザで動作するイベントライブラリ作ろう、うん。

関数オブジェクトを入れ子関数内からスコープを外して参照させる?

ライブラリとかを作っていると、そのクラス内で全てメソッドを共有してその関数内で処理をまとめて書くのが普通ですよね。

グローバル汚染をしないのが一般的な考え方なもんですが、ここでつまづく方が多い?というか私はすっ転びましたね。

結局は「スコープチェーン」と「参照」の問題なのですが、理解していながらも上手い解決法が見つかりませんでした。

クラス内でクロージャに押し込めた関数内では基本的にクラスのプロパティが参照できません。

例えば、

function class(){

this.num = 1;

this.func = function(){

document.getElementById(‘hogehoge’).onclick = function(){

alert(this.num);

}

this.func()

}

DOMlevel1はそろそろやめないといけないですね(笑)まぁサンプルってことで。

ドキュメントロード時にクラスを生成し、hogehogeのidが付いたものをクリックするとアラートさせるシンプルコード。

しかしこれだとアラート内はundefinedになります。クロージャを知ってたら当たり前ですが。

ドキュメント内でクラスインスタンスを生成していればそのまま変数名でアクセスでき・・・・

といったところで解決しました。

javascriptにおけるオブジェクトは全て「参照渡し」なんですよね。

ってことは、引数にクラスオブジェクトを仮想的に渡して参照させればあら不思議。

引数にはクラスのオブジェクトが「参照」されるので、そのままプロパティにアクセスできるんですね~。知らなかった。

つまり、クロージャに押し込める「前」の階層にクラスオブジェクトを参照させる変数を定義しておく。これがポイント?

function class(){

this.num = 1;

this.func = function(thisclass){

var class = thisclass;

document.getElementById(‘hogehoge’).onclick = function(){

alert(class.num);

}

this.func(this);

}

みたいな感じでやれば、クラス生成時にアラートは1と表示されます。インスタンスを格納する必要が無く、ただnewすればいいだけですね。

スコープの飛び越え、というのは少し違う気がしますが、逆にそのスコープ内にオブジェクトを持ってくる、という逆転の発想?

まぁおのおかげで一つのクラス内でクロージャも使い放題になります。イベント設定とかしてる時には特に便利。

このテの話題が少なかったのでメモ書き程度に。

クロージャは便利であり、厄介でもありますね。

※追記

function.applyでバインドして実行する方法もあるようです。こっちの方がスマートかな。

http://d.hatena.ne.jp/kminoru/20080228/1204250525