プログラミングのメモ用BLOGです 自己紹介:あんどれ へっぽこプログラマです

ラベル

2007年12月22日

「名台詞100+Flickr」作成時のメモ(JSON)

とりえあず参考リンクのみ

JSON in JavaScript - 実用
第三章 データを解析し表示しよう:JSONのデータを表示する
s.h.log: JavaScript - JSONでデータを受信する方法2種類
[ajax] JKL.ParseXML/ajax通信処理ライブラリ
・安全にjsonを読み込むためのパーサ。
Japan.internet.com デベロッパー - JSONを使ってAJAXベースのアプリケーションを高速化する
・evalは、実際はJavaScriptインタプリタ

JSONの特徴
・javascriptのオブジェクトをテキストで記述するデータフォーマット
・取得した文字列をeval(文字列からJavaScriptコードを実行する関数)で解析。
・<script type="text/javascript" src="xxxxx"></script>でもオブジェクトを取得できる。
xxxxxはjson形式で記述されたテキストへのリンク
・javascriptのサブセット。

参考
Andre's garden: 「名台詞100+Flickr」サイドバーに貼れるようにしてみました

「名台詞100+Flickr」作成時のメモ(Flickr API利用)

Flickr APIのドキュメント
http://www.flickr.com/services/api/

Flickr APIの使用例

JavaScriptからFlickr APIで画像検索
今回は、上記の画像検索用のソースflickr-search.jsを改変。

ライセンスの設定

ライセンスの種類
flickr.photos.licenses.getInfoに記述

Example Response


<licenses>
<license id="4" name="Attribution License"→「表示」
url="http://creativecommons.org/licenses/by/2.0/" />
<license id="6" name="Attribution-NoDerivs License"→「表示・改変禁止」
url="http://creativecommons.org/licenses/by-nd/2.0/" />
<license id="3" name="Attribution-NonCommercial-NoDerivs License"→「表示・非営利・改変禁止」
url="http://creativecommons.org/licenses/by-nc-nd/2.0/" />
<license id="2" name="Attribution-NonCommercial License"→「表示・非営利」
url="http://creativecommons.org/licenses/by-nc/2.0/" />
<license id="1" name="Attribution-NonCommercial-ShareAlike License"→「表示・非営利・継承」
url="http://creativecommons.org/licenses/by-nc-sa/2.0/" />
<license id="5" name="Attribution-ShareAlike License"→「表示・継承」
url="http://creativecommons.org/licenses/by-sa/2.0/" />
</licenses>

Flick上でのクリエイティブコモンズ(CC)ライセンスの写真検索ページ
http://www.flickr.com/creativecommons/

CCのホームページ(右上の「使う」からライセンスの説明を確認)
http://www.creativecommons.jp/

flickr.photos.searchの引数licenseにライセンスID(license idの値)をセット。
複数指定はカンマ区切り。

写真の種類ごとのURL


Photo Source URLsを参照

The URL takes the following format:
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}.jpg
or
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg
or
http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{o-secret}_o.(jpg|gif|png)

farm-id、server-id、secretはいずれもflickr.photos.searchの結果から取得可能。

URL例
http://farm1.static.flickr.com/2/1418878_1e92283336_m.jpg

flickr.photos.searchに限らずAPIの動作を各APIの説明の「API Explorer」から確認できる。

参考 Andre's garden: 「名台詞100+Flickr」サイドバーに貼れるようにしてみました

2007年12月15日

ウインドウの幅と高さの取得

参考URL
ユーザーのウインドウ表示幅を取得するjavascript - WEBデザイン BLOG

クロスブラウザ対応

幅だけだったので高さもついでに

var getBrowserWidth = function() {
if ( window.innerWidth ) { return window.innerWidth; }
else if ( document.documentElement && document.documentElement.clientWidth != 0 ) { return document.documentElement.clientWidth; }
else if ( document.body ) { return document.body.clientWidth; }
return 0;
}

var getBrowserHeight = function() {
if ( window.innerHeight ) { return window.innerHeight; }
else if ( document.documentElement && document.documentElement.clientHeight != 0 ) { return document.documentElement.clientHeight; }
else if ( document.body ) { return document.body.clientHeight; }
return 0;
}

Amazonウィッシュリング(リンク起動)で利用

要素の絶対位置の取得

クロスブラウザ対策

参考URL
anything from here offsetLeft,offsetTop,offsetWidthそしてoffsetHeight──静的配置要素の絶対位置を確実に取得する方法について

利用時には、元のソースからfunctionを変数に入れ変えて利用しました。

//必要となるGlobal変数の定義
// 間違いのないように全文字列を小文字に変換
var agt = navigator.userAgent.toLowerCase();
var is_ie  = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
var is_gecko = (agt.indexOf('gecko') != -1);
var is_opera = (agt.indexOf("opera") != -1);

 //要素のスタイル属性を取得する関数
var getElementStyle = function (targetElm,IEStyleProp,CSSStyleProp) {
 var elem = targetElm;
 if (elem.currentStyle) {
  return elem.currentStyle[IEStyleProp];
 } else if (window.getComputedStyle) {
  var compStyle = window.getComputedStyle(elem,"");
  return compStyle.getPropertyValue(CSSStyleProp);
 }
}//---End Function

var getPosition = function (that) {
 var targetEle = that;   //thatは位置を取得したい要素Object
 var pos = new function(){ this.x = 0; this.y = 0; }
 while( targetEle ){
  pos.x += targetEle.offsetLeft;
  pos.y += targetEle.offsetTop;
  targetEle = targetEle.offsetParent;
   //IEの補正:上記計算で無視されてしまう各親要素のborder幅を加算
  if ((targetEle) && (is_ie)) {
   pos.x += (parseInt(getElementStyle(targetEle,"borderLeftWidth","border-left-width")) || 0);
   pos.y += (parseInt(getElementStyle(targetEle,"borderTopWidth","border-top-width")) || 0);
  }
 }
  //geckoの補正:カウントしないbody部border幅をマイナスしてしまうので2倍して加算
 if (is_gecko) {
   //以下の部分でbody部を取得し、borderの減算を補正する。
  var bd = document.getElementsByTagName("BODY")[0];  //body部を取得
  pos.x += 2*(parseInt(getElementStyle(bd,"borderLeftWidth","border-left-width")) || 0);
  pos.y += 2*(parseInt(getElementStyle(bd,"borderTopWidth","border-top-width")) || 0);
 }
 return pos;
}//---End Function

Amazonウィッシュリング(リンク起動)で利用

SWFObject2.0でページのロード後にFlashオブジェクトの再表示を行うには?

Flashオブジェクトを埋め込むときには通常では色々問題があるので以下のサイトを参考にしました。

SWFObject v2.0 ドキュメント日本語訳

SWFObjectというライブラリを使って


<!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" lang="en" xml:lang="en">
<head>
<title>SWFObject v2.0 dynamic embed - step 3</title>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script type="text/javascript" src="swfobject.js"></script>


<script type="text/javascript">
swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0");
</script>

</head>
<body>
<div id="myContent">
<p>Alternative content</p>
</div>

</body>
</html>


と書けば、Flashは問題なくページ上に表示されます。
上記の例では、htmlがロードされる前にHeadに書いたJavascript宣言(swfobject.embedSWF)からおそらく(?)

1.swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0");
2.embedSWF内のaddDomLoadEvent→ロード時に走るイベントを定義する関数
3.addDomLoadEvent内でcreateSWFを(Flashオブジェクトを生成する関数)を定義。
4.ページ読み込み後に、onDomLoadイベントが走ってcallDomLoadFunctionsを呼び出す。
5.callDomLoadFunctionsで定義されたcreateSWFが処理される

といった順序で処理が走ります。

ただ、残念なことにロード後にHTMLを動的に生成して再表示したい場合、embedSWFを呼びだしただけでは上手くいきませんでした。

調べてみるとロード後は、embedSWFを呼んでもcreateSWFが呼ばれないからということがわかってきました。

でもって結構詰まったのですが、色々探してみるとありがたいことに解決策が以下のフォーラムに載っていました。
http://groups.google.com/group/swfobject/browse_thread/thread/c857d29662509809

I've been develeoping with the old swfObject (1.5) and recently
switched over to the new 2.0 beta.
I noticed that you can't embed a flash object after the pages loads as
the embedding with the new version happens only on the onload. Is
there a way to use this JS to replace an existing flash?

SWFObject2.0でロード後にFlashの再表示をする方法はないか?といった内容でまさに知りたいことです。

解決策のソースを書いているエントリ
http://groups.google.com/group/swfobject/msg/0a04ea40128088c2

一部抜粋
The fix is really just the first inserted line. This:
<元のソース>
function addDomLoadEvent(fn) {
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only
available in IE5.5+
}

becomes this:
<変更後のソース>

function addDomLoadEvent(fn) {
if (isDomLoaded) return fn(); // if the DOM is already loaded,
trigger directly
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only
available in IE5.5+
}

ロード済みなら引数(fnはcreateSWFを含む)をすぐ実行するというコードが追加されています。

さらに詳しい比較のコードが別ページに解説されており非常に助かりました。
http://pastie.textmate.org/private/4ftrnrhae7h50nko8k6sg
ここまで詳細に書いてくれていると助かります。

修正したSWFObject.jsを置いときます。
もし、利用してもいいかもと思う方はどうぞ持っていって下さい。(動作保障は自己責任でよろしくお願いします。)
(SWFObject.jsは、MIT Licenseです。)

SWFObject.js

※よくわかってないながらもSWFObject2.0でロード後にFlashの再表示をしたかったので書いてみましたが、よくわかっている人からのいいやり方がありましたらぜひコメント・トラックバックでご指摘下さい。

2007年7月1日

クロージャ(Closure)のメモ

(javascript上での)クロージャの理解のためのサンプル


<html>
<head>
<script laungage="javascript">

var x1 = function() {
var Y = 0;
return function(Z) {
Y += Z;
return Y;
}
}

var x2 = x1();//x2は、x2 = function(Z){...}と同じ
var x3 = x1();//x3は、x3 = function(Z){...}と同じ

document.writeln("x2(1)は"+x2(1));//1
document.writeln("x2(2)は"+x2(2));//3
document.writeln("x2(3)は:"+x2(3));//6

document.writeln("x3(1):"+x3(1));//1
document.writeln("x3(2):"+x3(2));//3

x1= function(){return function() {return 1}};
x3 = x1();

document.writeln("x3(3):"+x3(3));//X1()が戻す関数が新しくなったので1

</script>
</head>
<body>
</body>
</html>



※今までvar x2 = x1()をx2 = x1(C#の参照と勘違い)と同じと思っていた。
※x2 = function(Z){...}でわかりやすくなった。
※x1内の関数が入れ代わらない限りローカル変数Yは保持されている。

参考サイト
javascriptを理解するためのたった2つの大切なこと:改
JavaScriptの巧い書き方のコメント内(「関数実行後も内部で定義したデータにアクセス出来る」で検索)

以下はまだ読んでいない
クロージャとOOPとJavaScriptの謎仕様
Martin Fowler's Bliki in Japanese - Closure

2007年6月19日

WebServiceの戻り値に利用しているDataSet,DataTableをJSONに変換する(asp.net ajax利用)

Jason氏のAjaxComponentLibraryを利用します。
1.(a Weblog by Jason Diamond)からJacl Release 3をダウンロードする。
http://jason.diamond.name/weblog/2007/06/07/jacl-release-3
  のrelease からダウンロードできます。(This was posted by Jason Diamond on Thursday, June 7th, 2007 at 2:57 pm.)

ネタ元:@ITの掲示板「件名:ajaxの返す値が2つ以上の場合」(※1)

2.Jacl-3.zipを解凍してビルド。AjaxComponentLibrary.dllを探して(※2)コピー。自分のプロジェクトから参照できるようにする。

3.利用する。
(1)Web.configに以下の内容(※3)を追加


<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="DataConverter" type="AjaxComponentLibrary.DataConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>

(2)後は、普通に使えます。

[WebMethod]
public DataTable GetData()
{
DataTable dt = new DataTable();

dt.Columns.Add("id", typeof(string));
dt.Columns.Add("title", typeof(string));

dt.Rows.Add(new object[] { "0001", "Table Convert" });
dt.Rows.Add(new object[] { "0002", "Good Job!" });

return dt;
}


responseデータ(firebugで確認)
{"columns":["id","title"],"rows":[{"id":"0001","title":"Table Convert"},{"id":"0002","title":"Good Job!"}],"__type":"System.Data.DataTable"}

※1 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=24246&forum=7
※2 ?ajaxcomponent3\Jacl\AjaxComponentLibrary\bin\Debug\AjaxComponentLibrary.dll
※3 詳細は、http://ajax.asp.net/docs/ConfiguringASPNETAJAX.aspxのThe <system.web.extensions> Elementを参照


以下は、思いついたことを適当に・・・
・Web.configの<jsonSerialization>で設定した情報をどこで使っているかまではみていない。誰か調べた方がいたら教えてほしいです^^;
・JavaScriptConverterを継承したDataConverterでDataSet,Datatableをジェネリクス型のDistionaryに変換している。
・XMLから直接JSONにするなら参考になるかも。簡単にできなさそうだったので見ただけ。
 HttpWebRequest を使用して ASP.NET AJax のメソッドを呼び出す(1)
 HttpWebRequest を使用して ASP.NET AJax のメソッドを呼び出す(2)
How to convert XML to JSON in ASP.NET C#→これもXMLをJSONにする方法。例がわかりやすそう。

・Jason's AJAX Component LibraryのサンプルWebsiteには他にもすばらしいコンポーネントサンプルがあるが必要になったら見ることにする。

An introduction to extender controls and behaviors
Extender control examples

* ReorderColumnsExtender
* ResizeColumnsExtender
* SelectActionExtender
* SortRowsExtender
* TableDataBinderExtender
* TableRowCheckedChangedExtender
* TextBoxImageButtonExtender
* TextChangedExtender

Non-visual component examples

* TextSizeWatcher

Other examples

* Returning DataSet and DataTable objects from web services
* Using both ReorderColumnsExtender and ResizeColumnsExtender on the same target
* Using both ReorderColumnsExtender and SortRowsExtender on the same target
* Persisting sorted tables with cookies

2007年6月17日

Calling Web Services from Client Script in ASP.NET AJAXのメモ

Calling Web Services from Client Script in ASP.NET AJAXを読んだのでメモ書き。

Calling Web Services from Client Script in ASP.NET AJAX
http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx

初めに
JavaScriptからWebサービスを呼び出すための方法について
・WEBサービス利用のためにページ上にプロキシクラス(javascript)を生成する。設定方法等。

WEBサービスを呼び出す方法


・値を返さないWEBサービスの呼び出し
・値を返すWEBサービスの呼び出し
・パラメータを取るWEBサービスメソッドの呼び出し
・「HTTP GET」を使うWEBサービスメソッドの呼び出し
・XMLドキュメントを返すWEBサービスメソッドの呼び出し

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.CallWebServiceMethods/cs/CallWebServiceMethods.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.CallWebServiceMethods%23CallWebServiceMethods.aspx


デフォルトプロパティとしての個別コールバック関数

パラメータを並べなくても個別コールバック関数を利用すれば以下の事を別々に処理できる。
メリットはWEBサービスを呼び出すシンタックスが簡潔になります。
・成功時の処理
・失敗時の処理
・ユーザーコンテキストを使った処理
・引数を利用する処理

プロキシクラスのインスタンス上のプロパティとしてコールバック関数を設定する

プロキシクラスのインスタンスを作るとWEBサービスのメソッドを複数呼びだしたり、別々の初期値を設定できる。

追加情報:プロキシクラスの生成についての説明
http://ajax.asp.net/docs/ClientReference/Sys.Net/GeneratedProxyClasses/default.aspx

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.UsingProxyClass/cs/default.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.CallWebServiceMethods%23CallWebServiceMethods.aspx

[メモ1]
UsingProxyClass.jsのpageload()はwindows.pageload()?ページがロードされる前の事前準備のイベント。
[メモ2]
次に呼び出すWEBサービスを事前に指定することによって、成功時、失敗時、ユーザーコンテキスト、引数の関数を個々に呼べるかわりに、呼び出されたWEBメソッドが何だったかを判断する必要あり。(methodName)

例:SucceededCallbackの場合
// Callback function invoked when the call to
// the Web service methods succeeds.
function SucceededCallback(result, userContext, methodName)
{
var message;
switch(methodName)
{
case ("GetDefaultColor"):
case ("SetColor"):
{
// Get the server default color.
message = result.message;
defaultRgb = result.rgb;


// Transform the rgb array into a string.
var serverColor = defaultRgb[0]+ defaultRgb[1] + defaultRgb[2];

// Display the result.
displayResult.style.color = "yellow";
displayResult.style.fontWeight = "bold";
displayResult.style.backgroundColor = "#" + serverColor;
DisplayMessage(message);
break;
}
default:
{
DisplayMessage("Method unknown");
}
}
}


WEBサービスメソッドの呼び出し中にエラーをハンドリングする

WebServiceMethodError.js Samples.AspNet.WebService.Div(a, b, SucceededCallback, FailedCallback);
に対してa=10、b=0をセット(処理は10/0で0除算のエラー)してFailedCallbackに流れる処理(エラーのハンドリング)のサンプル。

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.ErrorHandlingTutorial/cs/WebServiceMethodError.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.ErrorHandlingTutorial%23WebServiceMethodError.aspx


複数のWEBメソッドから1つのコールバックを呼ぶ

引数の数、セットする値(※)によってコールバック内の処理を呼び分ける方法についてのサンプル。
[メモ2]の拡張。呼び出す条件に「ユーザーコンテキストの有無」「メソッド名の有無」を利用

※呼び出しのサンプル
Samples.AspNet.WebService.Add(a, b,
SucceededCallbackWithContext, FailedCallback, userContext, null);

Samples.AspNet.WebService.Add(a, b,
SucceededCallbackWithContext, FailedCallback);

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.MultipleCallers/cs/MultipleCallers.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.MultipleCallers%23MultipleCallers.aspx

複合型を返す

WEBサービスの戻り値をJavaScriptのオブジェクト(JSON)で返すことについてのサンプル。
ASP.NET側(HandleColor.asmx)のWEBサービスメソッドは、ColorObjectクラス(文字列を返すpublicメソッドが3つ)
WEBサービスメソッドに[GenerateScriptType(typeof(ColorObject))]属性を付加。
HandleColor.js側ではJavaScriptオブジェクト(JSON)で処理可能になる。

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.ReturnComplexType/cs/Default.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.ExchangeComplexTypes

ジェネリクスや配列(array)型を返す

ジェネリクスや配列(array)型を返すWEBサービスのサンプル。
・ジェネリクスのList型が戻り値。generics.js側ではJSONで処理できる。
※SimpleClassはカスタムクラス
※WEBサービスメソッドに[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]属性がなくても同じ結果。

・ジェネリクスのDistionary<String, String>型が戻り値。generics.js側ではJSONで処理できる。

・ジェネリクスのDistionary<String, SimpleClass2>型が戻り値。generics.js側ではJSONで処理できる。
※SimpleClass2はカスタムクラス

・ジェネリクスのDistionary型を引数にして呼び出す。generics.js側ではJSONで引数をセット。(Samples.AspNet.TestService.PassGenericDictionary({"first":simple});)
※WEBサービスクラスに[GenerateScriptType(typeof(SimpleClass2))]属性が必要

※※引数の型が1つの場合、List型が引数の時は属性は必要なかった。(Samples.AspNet.TestService.PassGenericList([simple]);)

根拠になりそうな箇所を抜粋
Passing Parameters Typed as Generics or Arrays
However if a generic type takes more than one type argument, such as Dictionary<string, <T>>, ASP.NET AJAX does not generate proxy classes for the types.

・配列型(Array)が戻り値。generics.js側では配列型で処理できる。

動くサンプル
http://ajax.asp.net/docs/Samples/Sys.Net.WebServiceGenerics/cs/default.aspx
サンプルソース
http://ajax.asp.net/docs/ViewSample.aspx?sref=Sys.Net.WebServiceGenerics%23default.aspx


Enumerators型を返す

You cannot access enumerators by using instances of the generated proxy class.
サンプルがエラー無理らしい。