2012年3月3日土曜日

IMG要素のonloadイベントについて

ふと見かけたので正しいのかわかりませんが、書き留めておきます。 IMG要素のonloadイベントがIE系でうまくいかないときの対処とかやっぱりIE9でもキャッシュ有効時のimg要素はonloadを無視する件とか見つけました。 しかし、onload eventを読むと

To ensure that an event handler receives the onload event for these objects, place the script object that defines the event handler before the object and use the onload attribute in the object to set the handler.
You need to set the image.onload before you set the image.src.
書かれています。 つまり、
  • IMGタグよりも前にイベント内容を含むSCRIPTタグを配置する
  • src属性を設定する前にonloadイベントを設定する
ですかねぇ。

2011年7月13日水曜日

IStructuralEquatableの使い方

IStructuralEquatableについて今までいまいちわからずにいました。ググって出てきたページを読んでいたら使い方が微妙で違和感を覚えたためじっくり調べてみました。そうしたらもうちょっと使いやすいものだということがわかりました。
StructuralComparisons.StructuralEqualityComparerはオブジェクトそのものではなく、その要素を比較するIEqualityComparerを提供します。これを使ってIEqualityComparer<T>の実装例を書いてみました。

public class StructuralEqualityComparer<T> : IEqualityComparer<T> where T: IStructuralEquatable { public bool Equals(T x, T y) { return StructuralComparisons.StructuralEqualityComparer.Equals(x, y); } public int GetHashCode(T obj) { return StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj); } }
こう書いてしまえばどう使うのかわかりやすいでしょうか。このサンプルそのものは new StructuralEqualityComparer<int[]>() のように使えます。
なんでこんなクラスをわざわざ作るのかというと、LINQで要求される比較演算子はどれもIEqualityComparerでなくIEqualityComparer<T>だからです。

2011年2月1日火曜日

TransactionScope classの使い方

.NET Frameworkでtransactionを扱うにはTransactionScope classを使いますが、嵌りやすいのでメモっておきます。

class説明にはisolation levelについて記載されていませんが、デフォルトではSerializableになっています。例えばSQL ServerのデフォルトはReadCommittedなので勘違いしてしまいそうです。では、isolation levelを指定しようとすると、constructorにもpropertyにもそれらしいものがありません。実はpublic TransactionScope( TransactionScopeOption scopeOption, TransactionOptions transactionOptions )のTransactionOption classで指定することになります。 しかし今度は余計なparameterまで渡す必要があります。

  • TransactionScopeOption…これはRequiredがデフォルトです。
  • TransactionOptionsのIsolationLevel…これは指定したかったReadCommittedにします。
  • TransactionOptionsのTimeout…これは指定しないと初期化されず0になってしまい、timeoutなしになってしまいます。デフォルトの値にするためにはTransactionManager.DefaultTimeoutを指定します。
結局、
using( var transaction = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions{ IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.DefaultTimeout, } ) ){ ...; transaction.Complete(); }
とやることになるでしょう。

2010年12月29日水曜日

IsDuplicated拡張メソッド

気が向いたので何となく書いてみました。

public static class Enumerable { public bool IsDuplicated<TSource>( this IEnumerable<TSource> source ) { var keys = new HashSet<TSource>(); return !source.All( keys.Add ); } public bool IsDuplicated<TSource, TKey>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector ) { var keys = new HashSet<TKey>(); return !source.Select( keySelector ).All( keys.Add ); } }
IsDuplicated() つまり重複があるかどうかを判断する拡張メソッドです。
巷にはDistinct()を使ったりして項目数を数えている方法もありますが、数えるということはIEnumerableを最後まで確認する必要があります。

しかし、重複があるかどうか知りたいだけ、同じものが1ヶ所でもダブっていればそれが知りたい、そんなときに最後まで確認するのは無駄です。IsUnique()でなくIsDuplicated()というメソッド名にしたのもそのためです。どうせダブってるんでしょ? ダブってるなら早く教えてよ、と。

仕組みは簡単。HashSetを使います。HashSet.Add()メソッドは戻り値として重複の有無を教えてくれるのでそれを使います。
更にAll()拡張メソッドは1つでもfalseを見つけると即座に中断して返ってきます。

2010年2月14日日曜日

Dojo基礎文法最速マスター ~CSS編~

Dojoにはテーマがあります。

<style type="text/css"> @import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/resources/dojo.css"; @import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dijit/themes/soria/soria.css"; @import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dijit/themes/nihilo/nihilo.css"; @import "http://ajax.googleapis.com/ajax/libs/dojo/1.4/dijit/themes/tundra/tundra.css"; </style>
最初の1つはいわゆるリセットCSS。残りの3つがテーマ。読み込んだだけでは適用されません。 テーマを適用したい範囲にclass="テーマ名"の属性を付けます。全体に適用したいなら、
<body class="soria">
こんな感じで<body>タグに設定します。
Dojoは読み込まれると<html>タグに次のクラスを設定します。
  • dj_ie / dj_ie6 / dj_ie7 / dj_ie8 / dj_iequirks
  • dj_gecko / dj_ff2 / dj_ff3
  • dj_khtml / dj_safari / dj_chrome
  • dj_opera
  • dj_contentBox / dj_borderBox
このため、ブラウザごとに挙動が違う場合もCSSで簡単に解決できます。 たとえば、IEだけ異なる挙動をする場合、
<style type="text/css"> /* ブラウザ共通 */ .someClass { ...; } /* IEのみ異なる部分を上書き */ .dj_ie .someClass { ...; } </style>
こうすると、CSSの優先順位により!importantしなくてもIEでのみ上書きされます。 CSSだけで解決できるので、JavaScriptで書き換えとかしなくて済みます。

Dojo基礎文法最速マスター ~HTML編~

Dojoにはdojo.parserという機能があり、これがhtmlを編集してくれます。ページ読み込み時にdojo.parserを動作させるには

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" djconfig="parseOnLoad: true"> </script>
と読み込み時に設定するだけ。

dojo.parserはdojotype属性に反応します。
<input dojotype="dijit.form.TextBox" jsid="textbox1" type="text" name="textbox" value="てきすと" />
これで、このtextboxにはdojoの追加機能が付与されます。dojoにはこのinputに対応するJavaScriptオブジェクトがあるわけですがjsid="textbox1"と指定されていた場合、JavaScriptのtextbox1という変数に割り当てられます。
よくdocument.getElementById()で毎回検索しているコードを見かけますが、変数に割り当てられているので必要な時はいつでも簡単にアクセスできます。

dojo.parserは入れ子にも対応していて
<form dojotype="dijit.form.Form" jsid="form1"> <input dojotype="dijit.form.TextBox" type="text" name="textbox1" value="てきすと1" /> <input dojotype="dijit.form.TextBox" type="text" name="textbox2" value="てきすと2" /> </form>
今度はformを拡張してJavaScript変数のform1に割り当てています。
どんな機能があるかというと、form1.attr('value')とやると{textbox1:"てきすと1",textbox2:"てきすと2"}が返ってきたり。逆にform1.attr('value', {textbox1:"ほえほえ",textbox2:"はにゃ~ん"})と値を初期化できたり。

クラスはたくさんあって、それぞれ機能が違うのでそこは調べてください☆

Dojo基礎文法最速マスター ~JavaScript編~

何はともあれまずは読み込み。 Google AJAX Libraries APIならダウンロード&インストール不要。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js"> </script>
以降はJavaScriptの説明になるので、<script type="text/javascript">~</script>内に書きます。
Dojoは細かくモジュール分けされているので、必要なモジュールは読み込む必要があります。
dojo.require("dijit.form.Button");
などなど。 JavaScriptとhtml読み込み完了後に処理をするにはdojo.addOnLoad()を使います。
dojo.addOnLoad(function(){ ...; // やりたいこと });
JavaScriptについてはほとんど説明することはありません。
というのもこれに続くHTML編とCSS編の説明が必要になるからです。