JavaScript/Adobe/Home.md
... ...
@@ -0,0 +1,200 @@
1
+[[_TOC_]]
2
+
3
+# 自作スクリプト
4
+- [[createSerialImg]]
5
+- [[doAction]]
6
+- [[downSample]]
7
+- [[dumpObjInfo]]
8
+
9
+# リンク
10
+- etc/Typography_PDF
11
+
12
+## Adobe
13
+- [Adobe Scripting Center](http://www.adobe.com/devnet/scripting.html)
14
+ - CS5
15
+ - [JavaScript Tools Guide](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/scripting/pdfs/javascript_tools_guide.pdf)
16
+ - [Photoshop CS5 JavaScript Reference](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/photoshop/pdfs/photoshop_cs5_javascript_ref.pdf)
17
+ - [Adobe Illustrator CS5 Reference: JavaScript](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/illustrator/scripting/illustrator_scripting_reference_javascript_cs5.pdf)
18
+ - [Adobe InDesign CS5.5 Scripting Guide: JavaScript](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/InDesignScripting/InDesign-ScriptingGuide-JS-JP.pdf)
19
+ - [Adobe InDesign CS5.5 Server Scripting Guide](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/InDesignServer/ids-scriptingguide.pdf)
20
+ - CS4
21
+ - [JavaScript Tools Guide CS4.pdf](http://www.adobe.com/devnet/scripting/pdfs/javascript_tools_guide_cs4.pdf) (削除済)
22
+ - [Photoshop CS4 JavaScript Reference](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/photoshop/pdfs/photoshop_cs4_javascript_ref.pdf)
23
+ - [Adobe Illustrator CS4 Reference: JavaScript](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/illustrator/pdfs/illustrator_scripting_reference_javascript.pdf)
24
+ - [InDesign CS4 JavaScript guide](http://wwwimages.adobe.com/www.adobe.com/products/indesign/scripting/pdfs/InDesignCS4_ScriptingGuide_JS.pdf)
25
+
26
+- [Adobe Developer Connection](http://www.adobe.com/devnet.html)
27
+ - [Adobe Photoshop File Formats Specification](http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/)
28
+ - [Adobe Photoshop SDK](http://www.adobe.com/devnet/photoshop/sdk.html)
29
+ - [Acrobat Developer Center](http://www.adobe.com/devnet/acrobat.html)
30
+
31
+## OpenSpace
32
+- [OpenSpace](http://www.openspc2.org/)
33
+ - CS6
34
+ - [Adobe Photoshop CS6自動化作戦](http://www.openspc2.org/book/PhotoshopCS6/)
35
+ - [Adobe Illustrator CS6自動化作戦](http://www.openspc2.org/book/IllustratorCS6/)
36
+ - [InDesign CS6自動化作戦](http://www.openspc2.org/book/InDesignCS6/)
37
+ - [ExtendScript Toolkit CS6自動化作戦](http://www.openspc2.org/book/ExtendScriptToolKitCS6/)
38
+ - CS5
39
+ - [Adobe Photoshop CS5自動化作戦](http://www.openspc2.org/book/PhotoshopCS5/)
40
+ - [Adobe Illustrator CS5自動化作戦](http://www.openspc2.org/book/IllustratorCS5/)
41
+ - [InDesign CS5自動化作戦](http://www.openspc2.org/book/InDesignCS5/)
42
+ - CS4
43
+ - [Adobe Photoshop CS4自動化作戦](http://www.openspc2.org/book/PhotoshopCS4/)
44
+ - [Adobe Illustrator CS4自動化作戦](http://www.openspc2.org/book/IllustratorCS4/)
45
+ - [InDesign CS4自動化作戦](http://www.openspc2.org/book/InDesignCS4/)
46
+ - [クリエイター手抜きプロジェクト](http://www.openspc2.org/projectX/)
47
+ - [Illustrator アクションファイルを書き換える](http://www.openspc2.org/projectX/Illustrator/0008/)
48
+- 古籏一浩/&amazon(4844395955);
49
+
50
+## なにする?DTP+WEB
51
+- [なにする?DTP+WEB](http://d.hatena.ne.jp/kamiseto/)
52
+ - [イラストレーターの書体を置換する「FontChanger」GUI版](http://d.hatena.ne.jp/kamiseto/20100117/1263738865)
53
+ - [イラストレーターのスクリプトを高速化させるためのコツ](http://d.hatena.ne.jp/kamiseto/20091113/1258118098)
54
+ - [InDesignからフォントファミリーとスタイルのリストを作る。](http://d.hatena.ne.jp/kamiseto/20090721/1248181924)
55
+ - [イラストレーターに埋め込まれた画像を書き出して再配置するスクリプト](http://d.hatena.ne.jp/kamiseto/20090611/1244704103)
56
+ - [インデザインで曜日の字形を○●□■等に変えるスクリプト](http://d.hatena.ne.jp/kamiseto/20090529/1243547647)
57
+ - [出てると安心。「プログレスバー」](http://d.hatena.ne.jp/kamiseto/20090408/1239163517)
58
+ - [ScriptUIを簡単に生成できるライブラリを発見](http://d.hatena.ne.jp/kamiseto/20090204/1233736220)
59
+ - [イラストレーターで文字幅を揃えたい](http://d.hatena.ne.jp/kamiseto/20090116/1232121703)
60
+ - [スクリプトで擬似立体を作る(四角形限定)](http://d.hatena.ne.jp/kamiseto/20081128/1227873443)
61
+ - [選択したものを表のようにあつかうため?のクラス(多方向対応/インデザイン・イラストレーター対応版)](http://d.hatena.ne.jp/kamiseto/20081127/1227801672) hvg.js
62
+ - [無理やりにでもIllustraorでdoScriptを使う](http://d.hatena.ne.jp/kamiseto/20081105/1225875643)
63
+ - [クリップボードの中身を操作する](http://d.hatena.ne.jp/kamiseto/20081105/1225857246)
64
+
65
+## 名もないテクノ手に
66
+- [名もないテクノ手に](http://seuzo.hatenablog.com/)
67
+ - [特定のTweet引用時の正書法](http://seuzo.net/entry/2012/03/10/163354)
68
+ - [生データをそのまま使うフォントのアイデア](http://seuzo.hatenablog.com/entry/2012/01/31/155502)
69
+ - [TK TYPE](http://www.tktype.com/) / [Chartwell](http://www.tktype.com/chartwell.php)
70
+- [名もないテクノ手](http://d.hatena.ne.jp/seuzo/)
71
+ - [InDesign CS5ではスクリプトラベル使用禁止](http://d.hatena.ne.jp/seuzo/20100724/1279904204)
72
+ - [InDesignのドキュメント中にデータを埋め込む](http://d.hatena.ne.jp/seuzo/20100723/1279822441) XMPにデータを埋め込むやり方。
73
+ - [「プログラマのための文字コード技術入門」](http://d.hatena.ne.jp/seuzo/20100223/1266889867)
74
+ - [2010年はJapan-eBook元年か?!](http://d.hatena.ne.jp/seuzo/20100102/1262425125)
75
+ - [【正規表現02】電話番号の再フォーマット](http://d.hatena.ne.jp/seuzo/20091215/1260853900)
76
+ - [【正規表現01】日付の表現](http://d.hatena.ne.jp/seuzo/20091201/1259635998)
77
+ - [女子高生とぼくとKindleと](http://d.hatena.ne.jp/seuzo/20091115/1258224729)
78
+ - [PDF校正にはFDFの活用をおすすめしますが...](http://d.hatena.ne.jp/seuzo/20091110/1257779126)
79
+ - [「書体の研究」](http://d.hatena.ne.jp/seuzo/20091104/1257260462)
80
+ - [ボタンについて](http://d.hatena.ne.jp/seuzo/20091020/1256017709)
81
+ - [欧文の凸版植字&印刷](http://d.hatena.ne.jp/seuzo/20091018/1255861064)
82
+ - [スクリプトで正規表現スタイルの追加](http://d.hatena.ne.jp/seuzo/20091015/1255537020)
83
+ - [PDFファイルに含まれるリンク先(URL)の一覧を得る](http://d.hatena.ne.jp/seuzo/20091013/1255359723)
84
+ - [アルファベットの縦中横](http://d.hatena.ne.jp/seuzo/20091006/1254812542)
85
+ - [アポストロフィーとかピリオドとかの縦中横](http://d.hatena.ne.jp/seuzo/20091005/1254723264)
86
+ - [hyperlinkURLDestinations.destinationURLの置換](http://d.hatena.ne.jp/seuzo/20090929/1254181707)
87
+ - [選択したテキストをタグ付けする](http://d.hatena.ne.jp/seuzo/20090928/1254072019)
88
+ - [スクリプトで生成したオブジェクトは線幅(strokeWeight)が適用(変更)できない](http://d.hatena.ne.jp/seuzo/20090911/1252600247) 解決方法はコメントに
89
+ - [HTMLなどの文字列を操作したい時にタグを一時退避させる](http://d.hatena.ne.jp/seuzo/20090903/1251967520)
90
+ - [フォントの言語を調べる(Illustrator編)](http://d.hatena.ne.jp/seuzo/20090819/1250608439)
91
+ - [フォントの言語を調べる(InDesign編)](http://d.hatena.ne.jp/seuzo/20090818/1250521429)
92
+ - [miエディタ「チラシの裏」モード](http://d.hatena.ne.jp/seuzo/20090817/1250435162)
93
+ - [正規表現にマッチしたら、指定のセルスタイルを適用する「regex_cellstyle 0.2」](http://d.hatena.ne.jp/seuzo/20090814/1250176724)
94
+ - [File.openDialogのフィルタ](http://d.hatena.ne.jp/seuzo/20090807/1249570963)
95
+ - [セクションマーカーにUnicode文字を入れる](http://d.hatena.ne.jp/seuzo/20090805/1249441879)
96
+ - [PageItemの変形 〜変形マトリクス(transformationMatrix)の基礎〜](http://d.hatena.ne.jp/seuzo/20090804/1249311877)
97
+ - [多角形ツールで図形を作成時に、矢印キーで「頂点の数」と「星形の比率」を自在に変える](http://d.hatena.ne.jp/seuzo/20090724/1248402054)
98
+ - [個人授業のサンプル](http://d.hatena.ne.jp/seuzo/20090710/1247201358)
99
+ - [スクリプト個人授業](http://d.hatena.ne.jp/seuzo/20090708/1247020206)
100
+ - [フォントを素早く選ぶんだ](http://d.hatena.ne.jp/seuzo/20090629/1246244382) Winにもショートカットあるのかな?
101
+ - [InDesign コントロールパネルのショートカットキー](http://help.adobe.com/ja_JP/InDesign/6.0/WSa285fff53dea4f8617383751001ea8cb3f-7001a.html)
102
+ - [AcrobatのJavaScriptはドキュメント単位でグローバル変数を保持する](http://d.hatena.ne.jp/seuzo/20090623/1245752994)
103
+ - [InDesignのハイパーリンクをPDFに書き出したなら...](http://d.hatena.ne.jp/seuzo/20090619/1245340297)
104
+ - [アラビア数字を漢数字に変換](http://d.hatena.ne.jp/seuzo/20090611/1244701472)
105
+ - [変換の難しい漢字を入力する](http://d.hatena.ne.jp/seuzo/20090608/1244388838)
106
+ - [テキストのままパンチアウトにする](http://d.hatena.ne.jp/seuzo/20090601/1243828882)
107
+ - [スクリプトのユーザーインターフェイスをFlashで作成する](http://d.hatena.ne.jp/seuzo/20090528/1243439545)
108
+ - [丸数字などを簡単に変換できる「round_num 0.3」](http://d.hatena.ne.jp/seuzo/20090527)
109
+ - [SayKanaを使ってInDesignで読み上げテスト](http://d.hatena.ne.jp/seuzo/20090519/1242726767)
110
+ - [オートコンプリート(コード補完)を有効にする。](http://d.hatena.ne.jp/seuzo/20090426/1240730870)
111
+ - [IDML公式ドキュメントの日本語訳](http://d.hatena.ne.jp/seuzo/20090421/1240239935)
112
+ - [IDMLのポータルサイト「IDMLWiki」](http://d.hatena.ne.jp/seuzo/20090311/1236698409)
113
+ - [IDMSことはじめ:(1)IDMSとは](http://d.hatena.ne.jp/seuzo/20090310/1236612582)
114
+ - [正規表現の文字クラスまとめ](http://d.hatena.ne.jp/seuzo/20090309/1236525090)
115
+ - [InDesign CS4のドキュメントをInDesign CS2でムリムリ開くぜ。](http://d.hatena.ne.jp/seuzo/20090305/1236178999)
116
+ - [インタラクティブなPDFを作ってみよう](http://d.hatena.ne.jp/seuzo/20090219/1235014650)
117
+ - [Javascriptの正規表現置換で後方参照を使いたい](http://d.hatena.ne.jp/seuzo/20090218/1234926645)
118
+ - [Mac OS X時代のフォント作成ツール](http://d.hatena.ne.jp/seuzo/20090214/1234574969)
119
+ - [リッチなダイアログ作成ライブラリ](http://d.hatena.ne.jp/seuzo/20090209/1234149676)
120
+ - [【失敗から学ぶシリーズ】#includeは実行前に評価される](http://d.hatena.ne.jp/seuzo/20090209/1234162460)
121
+ - [【日本初】IDML名刺ジェネレータ【テスト】](http://d.hatena.ne.jp/seuzo/20090204/1233740769)
122
+ - [ナカトジールで中綴る。](http://d.hatena.ne.jp/seuzo/20090130/1233252528)
123
+ - [IDML File Format Specififation::9 IDMLの文法](http://d.hatena.ne.jp/seuzo/20090119/1232328850)
124
+ - [IDML File Format Specififation::8 IDMLのドキュメント構造](http://d.hatena.ne.jp/seuzo/20090114/1231866816)
125
+ - [IDML File Format Specififation::7 IDMLデザインアプローチ](http://d.hatena.ne.jp/seuzo/20090113/1231773552)
126
+ - [IDML File Format Specififation::6 IDMLの目標](http://d.hatena.ne.jp/seuzo/20090112/1231687621)
127
+ - [IDML File Format Specififation::5 IDMLの用途](http://d.hatena.ne.jp/seuzo/20090110/1231515231)
128
+ - [IDML File Format Specififation::4 INXとIDML、InDesign Scripting](http://d.hatena.ne.jp/seuzo/20090109/1231428596)
129
+ - [IDML File Format Specififation::3 用語](http://d.hatena.ne.jp/seuzo/20090108/1231341208)
130
+ - [IDML File Format Specififation::2 イントロダクション](http://d.hatena.ne.jp/seuzo/20090107/1231256510)
131
+ - [IDML File Format Specififation::1 要約](http://d.hatena.ne.jp/seuzo/20090106/1231203030)
132
+ - [IDML的HelloWorld](http://d.hatena.ne.jp/seuzo/20090103/1230969363)
133
+ - [IDMLがやってくる](http://d.hatena.ne.jp/seuzo/20081015/1224037162)
134
+
135
+## Double-talk Publisher
136
+- [Double-talk Publisher](http://detaramedia.blog95.fc2.com/)
137
+ - [BridgeTalkのアヤシイ挙動(中間報告)](http://detaramedia.blog95.fc2.com/blog-entry-95.html)
138
+ - [BridgeTalkのアヤシイ挙動(情報求ム)](http://detaramedia.blog95.fc2.com/blog-entry-94.html)
139
+ - [噂の真相](http://detaramedia.blog95.fc2.com/blog-entry-91.html) 電子出版と出版権
140
+ - [音声合成なう(mac)](http://detaramedia.blog95.fc2.com/blog-entry-90.html)
141
+ - [BridgeTalk考(2)](http://detaramedia.blog95.fc2.com/blog-entry-83.html)
142
+ - [設定ファイルの保存](http://detaramedia.blog95.fc2.com/blog-entry-80.html) uneval()とeval()を使ってJSON形式で保存・読み出し
143
+ - [BridgeTalk考](http://detaramedia.blog95.fc2.com/blog-entry-79.html)
144
+
145
+## deadpop
146
+- [deadpop archives](http://d-p.2-d.jp/)
147
+ - [イラレで便利 for Adobe Illustrator](http://d-p.2-d.jp/ai-js/)
148
+
149
+## そらかぜ工場
150
+- [そらかぜ工場](http://www016.upp.so-net.ne.jp/sorakaze/)
151
+ - [Photoshop Scripting 覚書き](http://www016.upp.so-net.ne.jp/sorakaze/script/)
152
+ - [Photoshop Scripting サンプル](http://www016.upp.so-net.ne.jp/sorakaze/script/script1.html)
153
+ - [Photoshop Scripting スクリプト作成](http://www016.upp.so-net.ne.jp/sorakaze/script/script2.html)
154
+ - [Photoshop Scripting Tips](http://www016.upp.so-net.ne.jp/sorakaze/script/script_tips1.html)
155
+
156
+## Omino.com
157
+- [omino.com](http://omino.com/)
158
+ - [omino pixel blog](http://omino.com/pixelblog/)
159
+ - [Omino Dialog Maker for ExtendScript](http://omino.com/pixelblog/tag/omino-dialog/)
160
+
161
+## diary NET. 1.2mg
162
+- [diary NET. 1.2mg](http://www.milligramme.cc/wp/)
163
+<!----- [[InDesign_合成フォントの覚え書き:http://www.milligramme.cc/weblog/2010/02/indesign-84.html]]-->
164
+ - [[InDesign]合成フォントの覚え書き](http://www.milligramme.cc/wp/archives/585)
165
+<!----- [[ExtendScript_共通点を探す旅(おまじない編):http://www.milligramme.cc/weblog/2009/08/extendscript-1.html]]-->
166
+ - [[ExtendScript]共通点を探す旅(おまじない編)](http://www.milligramme.cc/wp/archives/498)
167
+<!----- [[ExtendScript_共通点を探す旅(保存せずに閉じる編):http://www.milligramme.cc/weblog/2009/07/extendscript.html]]-->
168
+ - [[ExtendScript]共通点を探す旅(保存せずに閉じる編)](http://www.milligramme.cc/wp/archives/493)
169
+
170
+## ディザInDesign
171
+- [ディザInDesign](http://www15.ocn.ne.jp/~preopen/)
172
+ - [InDesign Object Model について](http://www15.ocn.ne.jp/~preopen/dom_about.html)
173
+ - [InDesign Object Model CS-CS5.5](http://www15.ocn.ne.jp/~preopen/iddomjs/domCS-CS55.html)
174
+ - [InDesign Object Model CS-CS4](http://www15.ocn.ne.jp/~preopen/iddom/domCS-CS4.html)
175
+ - [Story](http://www15.ocn.ne.jp/~preopen/iddom/Story.html)
176
+ - [PDFExportPreference](http://www15.ocn.ne.jp/~preopen/iddom/PDFExportPreference.html)
177
+ - [PDFExportPreset](http://www15.ocn.ne.jp/~preopen/iddom/PDFExportPreset.html)
178
+
179
+## その他のリンク
180
+- [数字入りの連番ダミー画像を作る](http://katapad.com/flash/wiki/?photoshop/js/jsx) @ [スーパー肩パッドの「Flashセレブ道」](http://katapad.com/flash/wiki/)
181
+
182
+- [web掲載用画像自動生成](http://www.tky.3web.ne.jp/~katsu2/script/CS3/mk4web/) @ [かつかつのページ](http://www.tky.3web.ne.jp/~katsu2/)
183
+
184
+- [InDesign Hacking with JavaScript](http://kmuto.jp/indesign/) @ [Kenshi Muto](http://kmuto.jp/)
185
+
186
+- [Illustratorの作業を自動化して効率化でき、今すぐ役立つ便利なスクリプトいろいろ](http://gigazine.net/index.php?/news/comments/20080922_illustrator_script/)
187
+
188
+- [画像サイズの変更](http://buruge.net/?p=46) @ [ブルゲノム](http://buruge.net/)
189
+
190
+- [Illustrator スクリプト](http://homepage2.nifty.com/upright/download.html) @ [「いられ」のはなし](http://homepage2.nifty.com/upright/)
191
+
192
+- [テキスト&画像ロゴ自動合成スクリプト ver.2](http://webtra.web-tracks.net/2010/01/logo-auto-add-ver2.html) @ [WEBTRA](http://webtra.web-tracks.net/)
193
+
194
+- [Perlでフォトショップ CS](http://www2.tba.t-com.ne.jp/tail/prog/perl/photoshop.html) @ [Storeroom](http://www2.tba.t-com.ne.jp/tail/)
195
+
196
+- [Rubyとか Illustratorとか SFとか折紙とか](http://d.hatena.ne.jp/hs9587/)
197
+ - [内部スクリプトと外部スクリプト](http://d.hatena.ne.jp/hs9587/20080406/1207447814)
198
+
199
+- [ps-scripts Homepage](http://ps-scripts.sourceforge.net/)
200
+ - [xtools](http://ps-scripts.sourceforge.net/xtools.html)
JavaScript/Adobe/createSerialImg.md
... ...
@@ -0,0 +1,217 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- Photoshop/Illustrator で画像に連番を付けて保存する。
5
+- ドキュメント中のテキストレイヤ(Photoshop)またはテキストフレーム(Illustrator)に連番を入れてEPS形式で保存します。
6
+- 連番が入れられるのは「ID」という名前を持つテキストレイヤまたはテキストフレームです。
7
+- Photoshop CS3/CS4 では途中で中断できますが、Illustrator CS3/CS4 では中断ボタンは利かず最後まで処理が止まりません。
8
+- Photoshop CS3/CS4, Illustrator CS3/CS4 で動作確認。(2010/03/09)
9
+
10
+# ソース
11
+- [createSerialImg.zip](createSerialImg.zip)
12
+```javascript
13
+ // ドキュメント中のオブジェクト名"ID"に連番を入れてEPS形式で保存
14
+ // by TakeAsh
15
+ // 2010/03/09
16
+ #target 'Photoshop'
17
+ #includepath "~/Local Settings/Application Data/Adobe/JavaScript/"
18
+ #include "ominoDialogMaker.jsx" // http://omino.com/sw/ominoAdobeScriptsSuite/shared/ominoDialogMaker.jsx
19
+ #include "packZero.js"
20
+
21
+ var prefix = 'Pref';
22
+ var start = 1;
23
+ var goal = 10;
24
+ var destFolder = '~';
25
+ var closeAtFinish = true;
26
+ var keta = 5;
27
+
28
+ var appPhotoshop = 'Adobe Photoshop';
29
+ var appIllustrator = 'Adobe Illustrator';
30
+
31
+ if ( app.name != appPhotoshop && app.name != appIllustrator ){
32
+ exit(); // エラーになる
33
+ }
34
+
35
+ switch( app.name ){
36
+ case appPhotoshop:
37
+ // ダイアログさない、アラートは出す。
38
+ app.displayDialog = DialogModes.ERROR;
39
+ break;
40
+ case appIllustrator:
41
+ // ダイアログ出さない
42
+ app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;
43
+ break;
44
+ }
45
+
46
+ var omd = newOminoDialog("連番保存");
47
+ omd.boxedText( 2, 'ドキュメント中のオブジェクト名"ID"に連番を入れてEPS形式で保存します。\n'
48
+ + 'Photoshop CS3/CS4は中断できますが、Illustrator CS3/CS4は中断が利きません。' );
49
+ omd.string( '接頭辞', 'prefix', prefix );
50
+ omd.number( '開始値', 'start', start );
51
+ omd.number( '終了値', 'goal', goal );
52
+ omd.selectFolder( '保存先フォルダ', 'destFolder', destFolder, 'EPS ファイルの保存先フォルダを選択してください。' );
53
+ omd.checkbox( '', 'closeAtFinish', closeAtFinish, '終了時にドキュメントを破棄' );
54
+ var result = omd.run();
55
+
56
+ if ( result != null ){
57
+ prefix = result[ 'prefix' ];
58
+ start = result[ 'start' ];
59
+ goal = result[ 'goal' ];
60
+ destFolder = result[ 'destFolder' ];
61
+ closeAtFinish = result[ 'closeAtFinish' ];
62
+
63
+ try {
64
+ var obj_ID = null;
65
+
66
+ switch( app.name ){
67
+ case appPhotoshop:
68
+ var objs = activeDocument.artLayers;
69
+ for( var i=0; i<objs.length; ++i ){
70
+ if ( objs[i].kind == LayerKind.TEXT && objs[i].name == 'ID' ){
71
+ obj_ID = objs[i].textItem;
72
+ break;
73
+ }
74
+ }
75
+ break;
76
+ case appIllustrator:
77
+ var objs = activeDocument.textFrames;
78
+ for( i=0; i<objs.length; i++ ){
79
+ if ( objs[i].name == 'ID' ){
80
+ obj_ID = objs[i];
81
+ break;
82
+ }
83
+ }
84
+ break;
85
+ }
86
+
87
+ if ( obj_ID != null ){
88
+ var win = new Window( 'palette', '連番保存', [100, 100, 210, 170] );
89
+ var postfix = '/' + packZero( goal, keta )
90
+ win.msg = win.add( 'statictext', [8, 8, 100, 30], packZero( start, keta ) + postfix );
91
+ win.abort = win.add( 'button', [8,30, 100, 56], '中断' );
92
+ win.abort.onClick = function(){ this.parent.aborted = true; };
93
+ win.aborted = false;
94
+ win.show();
95
+
96
+ var options = this.getOptions();
97
+
98
+ switch( app.name ){
99
+ case appPhotoshop:
100
+ for(var i=start; i<=goal; ++i){
101
+ if ( win.aborted ){
102
+ break;
103
+ }
104
+ var IDStr = packZero( i, keta );
105
+ win.msg.text = IDStr + postfix;
106
+ obj_ID.contents = IDStr;
107
+ var targetFile = this.getTargetFile( prefix+IDStr, '.eps', destFolder);
108
+ activeDocument.saveAs( targetFile, options, true, Extension.LOWERCASE );
109
+ }
110
+ break;
111
+ case appIllustrator:
112
+ for( var i=start; i<=goal; ++i ){
113
+ if ( win.aborted ){
114
+ break;
115
+ }
116
+ var IDStr = packZero( i, keta );
117
+ win.msg.text = IDStr + postfix;
118
+ obj_ID.contents = IDStr;
119
+ var targetFile = this.getTargetFile( prefix+IDStr, '.eps', destFolder);
120
+ activeDocument.saveAs( targetFile, options );
121
+ }
122
+ break;
123
+ }
124
+ if ( win.aborted ){
125
+ alert( '中断されました。' );
126
+ } else {
127
+ if ( closeAtFinish ){
128
+ app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
129
+ }
130
+ }
131
+ } else {
132
+ alert('名前が"ID"のオブジェクトがありません。');
133
+ }
134
+ }
135
+ catch(e) {
136
+ alert( e.message, 'スクリプト警告', true);
137
+ }
138
+ }
139
+
140
+ switch( app.name ){
141
+ case appPhotoshop:
142
+ // ダイアログもアラートも出す
143
+ app.displayDialog = DialogModes.ALL;
144
+ break;
145
+ case appIllustrator:
146
+ // ダイアログ出す
147
+ app.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;
148
+ break;
149
+ }
150
+
151
+ function getOptions()
152
+ {
153
+ // Create the required options object
154
+ var options = new EPSSaveOptions();
155
+ switch( app.name ){
156
+ case appPhotoshop:
157
+ options.embedColorProfile = true;
158
+ options.encoding = SaveEncoding.JPEGHIGH;
159
+ options.halftoneScreen = false;
160
+ options.interpolation = false;
161
+ options.preview = Preview.MACOSJPEG;
162
+ options.psColorManagement = false;
163
+ options.transferFunction = false;
164
+ options.transparentWhites = false;
165
+ options.vectorData = true;
166
+ break;
167
+ case appIllustrator:
168
+ options.compatibility = Compatibility.ILLUSTRATOR13;
169
+ options.cmykPostScript = true;
170
+ options.embedAllFonts = true;
171
+ options.embedLinkedFiles = true;
172
+ options.includeDocumentThumbnails = false;
173
+ options.overprint = PDFOverprint.PRESERVEPDFOVERPRINT;
174
+ //options.preview = false;
175
+ break;
176
+ }
177
+
178
+ return options;
179
+ }
180
+
181
+ /**
182
+ Returns the file to save or export the document into.
183
+ @param docName the name of the document
184
+ @param ext the extension the file extension to be applied
185
+ @param destFolder the output folder
186
+ @return File object
187
+ */
188
+ function getTargetFile(docName, ext, destFolder) {
189
+ var newName = '';
190
+
191
+ // if name has no dot (and hence no extension),
192
+ // just append the extension
193
+ if (docName.indexOf('.') < 0) {
194
+ newName = docName + ext;
195
+ } else {
196
+ var dot = docName.lastIndexOf('.');
197
+ newName += docName.substring(0, dot);
198
+ newName += ext;
199
+ }
200
+
201
+ // Create the file object to save to
202
+ var myFile = new File( destFolder + '/' + newName );
203
+
204
+ // Preflight access rights
205
+ if (myFile.open('w')) {
206
+ myFile.close();
207
+ } else {
208
+ throw new Error('アクセスは拒否されました。');
209
+ }
210
+ return myFile;
211
+ }
212
+
213
+ // EOF
214
+```
215
+
216
+# リンク
217
+- [数字入りの連番ダミー画像を作る](http://katapad.com/flash/wiki/?photoshop/js/jsx) @ [スーパー肩パッドの「Flashセレブ道」](http://katapad.com/flash/wiki/)
JavaScript/Adobe/doAction.md
... ...
@@ -0,0 +1,47 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- 登録済みのアクションを実行する。
5
+- VBScript の場合、DoAction (Photoshop)、DoScript (Illustrator) の引数の順序が「アクション名」「アクションセット名」だったのでそれに合わせた。(2010/03/19)
6
+- 関数名変更。(execAction → doAction, 2010/03/19)
7
+
8
+# ソース
9
+- [doAction.zip](doAction.zip)
10
+```javascript
11
+// Action実行
12
+
13
+/**
14
+ 登録済みのアクションを実行する。
15
+ @param Actn アクション名
16
+ @param ActSet アクションセット名
17
+*/
18
+function doAction( Actn, ActSet )
19
+{
20
+ var actRef = new ActionReference();
21
+ actRef.putName( charIDToTypeID( "Actn" ), Actn );
22
+ actRef.putName( charIDToTypeID( "ASet" ), ActSet );
23
+ var actDesc = new ActionDescriptor();
24
+ actDesc.putReference( charIDToTypeID( "null" ), actRef );
25
+ executeAction( charIDToTypeID( "Ply " ), actDesc, DialogModes.NO );
26
+}
27
+
28
+// EOF
29
+```
30
+
31
+# 備考
32
+- Illustrator は、JavaScript からアクションを実行することができないようです。
33
+
34
+- [Visual Basic でエラーメッセージ「DLL 読み込み時のエラーです」が表示される(Illustrator CS3)](http://kb2.adobe.com/jp/cps/233/233473.html)
35
+
36
+- [Lucent crafts](http://lucentcrafts.blog102.fc2.com/)
37
+ - [Illustrator のスクリプトからアクションを実行](http://lucentcrafts.blog102.fc2.com/blog-entry-48.html) (VBScript)
38
+ - [Illustrator の ActionIsRunning がおかしい](http://lucentcrafts.blog102.fc2.com/blog-entry-49.html)
39
+
40
+- [なにする?DTP+WEB](http://d.hatena.ne.jp/kamiseto/)
41
+ - [無理やりにでもIllustraorでdoScriptを使う](http://d.hatena.ne.jp/kamiseto/20081105/1225875643)
42
+ - [クリップボードの中身を操作する](http://d.hatena.ne.jp/kamiseto/20081105/1225857246)
43
+
44
+- [Rubyist Magazine](http://jp.rubyist.net/magazine/)
45
+ - [Win32OLE 活用法 Adobe Illustrator](http://jp.rubyist.net/magazine/?0006-Win32OLE)
46
+- [Rubyとか Illustratorとか SFとか折紙とか](http://d.hatena.ne.jp/hs9587/)
47
+ - [内部スクリプトと外部スクリプト](http://d.hatena.ne.jp/hs9587/20080406/1207447814)
JavaScript/Adobe/downSample.md
... ...
@@ -0,0 +1,98 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- Photoshop でフォルダ内の画像を解像度を変えて書き出し。
5
+- 変換元フォルダの画像(.eps)を解像度を下げて変換先フォルダに保存します。
6
+- 変換後はファイル名の末尾に「追加文字」が付きます。
7
+- 「アクション」と「バッチ処理」で同様なことができるみたい。
8
+
9
+# ソース
10
+- [downSample.zip](downSample.zip)
11
+```javascript
12
+ // 解像度変換
13
+ // by TakeAsh
14
+ // 2010/03/18
15
+
16
+ #target 'Photoshop'
17
+ #includepath "~/Local Settings/Application Data/Adobe/JavaScript/"
18
+ #include "ominoDialogMaker.jsx" // http://omino.com/sw/ominoAdobeScriptsSuite/shared/ominoDialogMaker.jsx
19
+ #include "getTargetFile.jsx"
20
+ #include "getEpsOptions.jsx"
21
+
22
+ var srcFolder = '~';
23
+ var dstFolder = '~';
24
+ var destResolution = 72;
25
+
26
+ var ext = '.eps';
27
+ var modName = 's';
28
+
29
+ app.displayDialog = DialogModes.ERROR;
30
+
31
+ var omd = newOminoDialog( '解像度変換' );
32
+ omd.boxedText( 2, "変換元フォルダの画像("+ext+")を解像度を下げて変換先フォルダに保存します。\n"
33
+ + "変換後はファイル名の末尾に「追加文字」が付きます。" );
34
+ omd.selectFolder( '変換元フォルダ', 'srcFolder', srcFolder, '変換元フォルダを選択してください。' );
35
+ omd.selectFolder( '変換先フォルダ', 'dstFolder', dstFolder, '変換先フォルダを選択してください。' );
36
+ omd.number( '解像度', 'destResolution', destResolution );
37
+ omd.string( '追加文字', 'modName', modName );
38
+ var result = omd.run();
39
+
40
+ if ( result != null ){
41
+ srcFolder = result[ 'srcFolder' ];
42
+ dstFolder = result[ 'dstFolder' ];
43
+ destResolution = result[ 'destResolution' ];
44
+ modName = result[ 'modName' ];
45
+
46
+ var originalUnit = preferences.rulerUnits;
47
+ preferences.rulerUnits = Units.MM;
48
+
49
+ var win = new Window( 'palette', '解像度変換', [100, 100, 210, 170] );
50
+ win.msg = win.add( 'statictext', [8, 8, 100, 30], '0/0' );
51
+ win.abort = win.add( 'button', [8,30, 100, 56], '中断' );
52
+ win.abort.onClick = function(){ this.parent.aborted = true; };
53
+ win.aborted = false;
54
+ win.show();
55
+
56
+ try {
57
+ srcFolder = new Folder( srcFolder );
58
+ var fileList = srcFolder.getFiles( '*' + ext );
59
+ var goal = fileList.length;
60
+ var options = getEpsOptions();
61
+ var postfix = '/' + goal;
62
+
63
+ for( var i=0; i<goal; ++i ){
64
+ if ( win.aborted ){
65
+ break;
66
+ }
67
+ win.msg.text = i + postfix;
68
+ open( fileList[i] );
69
+ if ( activeDocument.resolution > destResolution ){
70
+ activeDocument.resizeImage( null, null, destResolution, ResampleMethod.BICUBIC );
71
+ }
72
+ var fName = fileList[i].name;
73
+ var dot = -1;
74
+ if ( (dot = fName.lastIndexOf('.')) >= 0 ){
75
+ fName = fName.substring(0, dot);
76
+ }
77
+ fName += modName;
78
+ var targetFile = getTargetFile( fName, ext, dstFolder);
79
+ activeDocument.saveAs( targetFile, options, true, Extension.LOWERCASE );
80
+ app.activeDocument.close( SaveOptions.DONOTSAVECHANGES );
81
+ }
82
+ }
83
+ catch(e) {
84
+ alert( e.message, 'スクリプト警告', true);
85
+ }
86
+
87
+ preferences.rulerUnits = originalUnit;
88
+ if ( win.aborted ){
89
+ alert( '中断されました。' );
90
+ } else {
91
+ app.beep();
92
+ }
93
+ }
94
+
95
+ app.displayDialog = DialogModes.ALL;
96
+
97
+ // EOF
98
+```
JavaScript/Adobe/dumpObjInfo.md
... ...
@@ -0,0 +1,85 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- 選択したオブジェクトのプロパティを YAML 形式でファイルに出力する。
5
+
6
+# ソース
7
+- [dumpObjInfo.zip](dumpObjInfo.zip)
8
+```javascript
9
+// 選択したオブジェクトのプロパティを YAML 形式でファイルに出力する。
10
+#target 'InDesign'
11
+#includepath "~/AppData/Roaming/Adobe/JavaScript/lib"
12
+#include "ominoDialogMaker.jsx" // http://omino.com/pixelblog/tag/omino-dialog/
13
+
14
+var maxDepth = 2;
15
+var fileName = 'D:/_temp/ObjInfo.yml';
16
+var reIgnore = new RegExp( '^(parent|all|event)' );
17
+
18
+var doc = app.activeDocument;
19
+var selected = doc.selection;
20
+
21
+var omd = newOminoDialog("dump Object Info");
22
+omd.saveFile( 'Output', 'fileName', fileName );
23
+omd.number( 'Depth', 'maxDepth', maxDepth );
24
+var result = omd.run();
25
+if ( result ){
26
+ fileName = result[ 'fileName' ];
27
+ maxDepth = result[ 'maxDepth' ];
28
+
29
+ var pltProgress = new Window( 'palette', 'dump Object Info', [100, 100, 210, 150] );
30
+ pltProgress.msg0 = pltProgress.add( 'statictext', [10, 10, 100, 20], 'Scanning...' );
31
+ pltProgress.msg1 = pltProgress.add( 'statictext', [10, 30, 100, 40], '0/' + selected.length );
32
+ pltProgress.show();
33
+
34
+ var result = '';
35
+ for( var i=0; i<selected.length; ++i ){
36
+ pltProgress.msg1.text = ( i + 1 ) + '/' + selected.length;
37
+ result += i + ':\n' + dump( selected[i], 1 );
38
+ }
39
+
40
+ var file = new File( fileName );
41
+ if ( file.open('w') ){
42
+ file.write( result );
43
+ file.close();
44
+ alert( 'Success: ' + file.fullName );
45
+ } else {
46
+ alert( 'Failed: ' + file.fullName );
47
+ }
48
+}
49
+
50
+function dump( obj, ind ){
51
+ var ret = '';
52
+ ind = ind || 0;
53
+ if ( ind <= maxDepth ){
54
+ for( var p in obj ){
55
+ try{
56
+ if ( !p.match(reIgnore) ){
57
+ ret += ( typeof( obj[p] ) == 'object' )
58
+ ? indent( ind ) + p + ':\n' + dump( obj[p], ind+1 )
59
+ : ( ( typeof( obj[p] ) != 'string' )
60
+ ? indent( ind ) + p + ': ' + obj[p] + '\n'
61
+ : indent( ind ) + p + ': "' + obj[p] + '"\n');
62
+ } else {
63
+ ret += indent( ind ) + p + ': "' + obj[p] + '"\n';
64
+ }
65
+ }
66
+ catch(e){
67
+ ret += indent( ind ) + p + ': "<forbidden>"\n';
68
+ }
69
+ }
70
+ } else {
71
+ ret += indent( ind ) + '"' + obj + '"\n';
72
+ }
73
+ return ret;
74
+}
75
+
76
+function indent( ind ){
77
+ var ret = '';
78
+ for( var i=0; i<ind; ++i ){
79
+ ret += ' ';
80
+ }
81
+ return ret;
82
+}
83
+
84
+// EOF
85
+```
JavaScript/Bookmarklet.md
... ...
@@ -1,7 +1,849 @@
1 1
[[_TOC_]]
2 2
3
-# Bookmarklet
3
+# [[Wayback Machine:http://www.archive.org/web/web.php]]で現在表示しているサイトの過去のアーカイブを見る
4
+```javascript
5
+javascript: location = 'http://web.archive.org/web/*/' + location.href
6
+```
4 7
5
-## PukiWiki
8
+# Google Cache から現在表示しているサイトの過去のアーカイブを見る
9
+```javascript
10
+javascript: location = 'http://webcache.googleusercontent.com/search?q=cache:'
11
+ + encodeURIComponent(location.href.replace(/^http:\/\//,''));
12
+```
6 13
7
-## Golluum
14
+# [[Google翻訳:http://translate.google.com/]]でサイトを翻訳
15
+```javascript
16
+javascript: location = 'http://translate.google.com/translate?sl=auto&tl=ja&u='
17
+ + encodeURIComponent(location.href);
18
+```
19
+
20
+# Google検索へのリンク(PukiWiki 用)
21
+```javascript
22
+javascript: (function () {
23
+var types = {
24
+ 'isch': 'Image', 'vid': 'Video', 'nws': 'News', 'bks': 'Books',
25
+};
26
+var target = location.hash || location.href;
27
+var type = '';
28
+if (location.pathname != '/maps') {
29
+ target.match(/[\?&#]tbm=([^&#]+)/);
30
+ type = RegExp.$1 || '';
31
+ type = (types[type])
32
+ ? types[type]
33
+ : type.charAt(0).toUpperCase() + type.slice(1);
34
+} else {
35
+ type = 'Maps';
36
+}
37
+target.match(/[\?&#]q=([^&#]+)/);
38
+var query = decodeURIComponent(RegExp.$1.replace(/\+/g, ' ') || '').replace(/\u3000/g, ' ');
39
+prompt(
40
+ 'Google Link\nType:\t' + type + '\nQuery:\t' + query,
41
+ '[[Google' + type + ':' + query + ']]'
42
+);
43
+})();
44
+```
45
+- [Google検索結果のURLをすっきり短くするには](http://hisame72.blog133.fc2.com/blog-entry-302.html) @ [ラブandナチュラルandピース](http://hisame72.blog133.fc2.com/)
46
+
47
+# MSDN の言語指定を変更
48
+- en -> ja
49
+```javascript
50
+javascript: location = location.href.replace(/\/en-us\//i, '/ja-jp/');
51
+```
52
+- ja -> en
53
+```javascript
54
+javascript: location = location.href.replace(/\/ja-jp\//i, '/en-us/');
55
+```
56
+
57
+# MSDN のバージョン指定を削除
58
+```javascript
59
+javascript: location = location.href.replace(/\(.*?\)(\.aspx)/i, '$1');
60
+```
61
+
62
+# [[Web Sniffer:http://web-sniffer.net/]]で現在表示しているサイトのhttpリクエストヘッダ/レスポンスヘッダを確認する
63
+```javascript
64
+javascript: location = 'http://web-sniffer.net/?url=' + encodeURIComponent(location.href)
65
+```
66
+
67
+# 現在のページのタイトルをポップアップで表示
68
+```javascript
69
+javascript: void(function(){prompt(document.title, document.title);})()
70
+```
71
+
72
+# 現在のページのタイトルとURLをポップアップで表示
73
+```javascript
74
+javascript: void(function () {
75
+ var title = document.title.replace(/\|/g, '-');
76
+ var uri = location.href;
77
+ prompt(title + '\n' + uri, title + '\n' + uri + '\n');
78
+})()
79
+```
80
+
81
+# 現在のページのタイトルとURLをポップアップで表示(PukiWiki用)
82
+```javascript
83
+javascript: void(function () {
84
+ var title = document.title.replace(/\|/g, '-');
85
+ var uri = location.href;
86
+ prompt(title + '\n' + uri, '[[' + title + ':' + uri + ']]');
87
+})()
88
+```
89
+
90
+# 現在のページのタイトルとURLをポップアップで表示(Markdown用)
91
+```javascript
92
+javascript: (function(title, uri) {
93
+ prompt(title + '\n' + uri, '[' + title + '](' + uri + ')');
94
+})(document.title, location.href);
95
+```
96
+
97
+# 現在の画像のファイル名とURLをポップアップで表示(Markdown Image用)
98
+```javascript
99
+javascript: (function(uri) {
100
+ uri.match(/([^\/\\]+)\.[0-9A-Za-z]+$/);
101
+ var title = RegExp.$1;
102
+ prompt(title + '\n' + uri, '![' + title + '](' + uri + ' "' + title + '")');
103
+})(location.href);
104
+```
105
+
106
+# 1つ上のフォルダに移動
107
+```javascript
108
+javascript: location = location.href.replace(/[^\/]*\/?$/, '');
109
+```
110
+
111
+# 前のページに移動
112
+```javascript
113
+javascript: location = location.href.replace(/([0-9]+)([^0-9]*)$/, function(whole, p1, p2) {
114
+ return (p1 - 1) + p2;
115
+});
116
+```
117
+
118
+# 次のページに移動
119
+```javascript
120
+javascript: location = location.href.replace(/([0-9]+)([^0-9]*)$/, function(whole, p1, p2) {
121
+ return (p1 - 0 + 1) + p2;
122
+});
123
+```
124
+
125
+# Locationオブジェクトのプロパティを表示
126
+```javascript
127
+javascript: (function () {
128
+var result = '<table border="1">\n<tr><th>Property</th><th>Type</th><th>Value</th></tr>\n';
129
+for (var p in location) {
130
+ if (p == 'href' || p == 'search' || p == 'hash') {
131
+ var param = location[p].replace(/([\?&#])/g, '<br>$1');
132
+ result += '<tr><td>' + p + '</td><td>' + typeof (location[p]) + '</td><td>' + param + '</td></tr>\n';
133
+ } else {
134
+ result += '<tr><td>' + p + '</td><td>' + typeof (location[p]) + '</td><td>' + location[p] + '</td></tr>\n';
135
+ }
136
+};
137
+result += '</table>';
138
+var docNew = window.open('', '_blank').document;
139
+docNew.open('text/html');
140
+docNew.write('<html><body>\n' + result + '</body></html>');
141
+docNew.close();
142
+})();
143
+```
144
+
145
+# flashvarsの値を表示
146
+```javascript
147
+javascript: (function () {
148
+ var flashvars = '';
149
+ var elmParams = document.getElementsByTagName('param');
150
+ if (elmParams.length) {
151
+ for (var i = 0; i < elmParams.length; ++i) {
152
+ if (elmParams[i].getAttribute('name') == 'flashvars') {
153
+ flashvars += decodeFlashVars(elmParams[i].getAttribute('value'));
154
+ }
155
+ }
156
+ }
157
+ var elmEmbeds = document.getElementsByTagName('embed');
158
+ if (elmEmbeds.length) {
159
+ for (var i = 0; i < elmEmbeds.length; ++i) {
160
+ var value;
161
+ if (value = elmEmbeds[i].getAttribute('flashvars')) {
162
+ flashvars += decodeFlashVars(value);
163
+ }
164
+ }
165
+ }
166
+ if (flashvars != '') {
167
+ var oWin = window.open('', '_blank');
168
+ oWin.document.open('text/html');
169
+ oWin.document.write('<html><body>\n' + flashvars + '</body></html>');
170
+ oWin.document.close();
171
+ } else {
172
+ alert('flashvars not found');
173
+ }
174
+
175
+ function decodeFlashVars(flashvar) {
176
+ var params = flashvar.split(/&/).sort();
177
+ var result = '<table border="1">\n<tr><th>Key</th><th>Value</th></tr>\n';
178
+ for (var i = 0; i < params.length; ++i) {
179
+ var kv = params[i].split(/=/);
180
+ result += '<tr><td>' + kv[0] + '</td>';
181
+ result += '<td>' + decodeURIComponent(kv[1] || '') + '</td></tr>\n';
182
+ }
183
+ result += '</table>\n';
184
+ return result;
185
+ }
186
+})();
187
+```
188
+
189
+# 現在のDOMを表示
190
+```javascript
191
+javascript: (function () {
192
+ var strXML = new XMLSerializer().serializeToString(document.documentElement);
193
+ var docNew = window.open().document;
194
+ docNew.open('text/html; charset="UTF-8"').write(htmlEscape(strXML).replace(/[\r\n]+/g, '<br>'));
195
+ docNew.close();
196
+
197
+ function htmlEscape(s) {
198
+ return s.replace(/[&<>"']/g, function (m) {
199
+ return '&#x' + m.charCodeAt(0).toString(16) + ';'
200
+ });
201
+ }
202
+})();
203
+```
204
+- [DOM操作後のHTMLを取得するブックマークレット - Yahoo!知恵袋](http://note.chiebukuro.yahoo.co.jp/detail/n31331)
205
+- [XMLのMIMEタイプ » サイキョウライン](http://saikyoline.jp/weblog/2005/07/27/010044.html)
206
+- [floatingdays: JavaScriptの HTMLエスケープ関数を 140字以内で書いてみる](http://fdays.blogspot.jp/2011/06/javascript-html-140.html)
207
+
208
+# 現在のページの Cookie を表示
209
+```javascript
210
+javascript: (function() {
211
+ var html = '';
212
+ html += '<html><body>';
213
+ html += '<table border="1">';
214
+ html += '<tr><th>key</th><th>value</th></tr>';
215
+ var pairs = document.cookie.split(/\s*;\s*/);
216
+ for (var i = 0, pair; pair = pairs[i]; ++i) {
217
+ pair.match(/^\s*([^=]+)\s*=\s*(.*)\s*$/);
218
+ html += '<tr><td>' + decodeURIComponent(RegExp.$1) + '</td><td>' + decodeURIComponent(RegExp.$2) + '</td></tr>';
219
+ }
220
+ html += '</table>';
221
+ html += '</body></html>';
222
+ var docNew = window.open('', '_blank').document;
223
+ docNew.open('text/html; charset=UTF-8');
224
+ docNew.write(html);
225
+ docNew.close();
226
+})();
227
+```
228
+
229
+# 現在のページの localStorage を表示
230
+```javascript
231
+javascript: (function() {
232
+ var html = '';
233
+ html += '<html><body>';
234
+ html += '<table border="1">';
235
+ html += '<tr><th>key</th><th>value</th></tr>';
236
+ for (var key in localStorage) {
237
+ html += '<tr><td>' + decodeURIComponent(key) + '</td><td>' + decodeURIComponent(localStorage[key]) + '</td></tr>';
238
+ }
239
+ html += '</table>';
240
+ html += '</body></html>';
241
+ var docNew = window.open('', '_blank').document;
242
+ docNew.open('text/html; charset=UTF-8');
243
+ docNew.write(html);
244
+ docNew.close();
245
+})();
246
+```
247
+
248
+# リンクされているzipやlzh、pdfをリストアップ
249
+- Opera 9.25ではftpサイトで動作しません。<br />
250
+Firefox 2.0.0.11ではftpサイトでも動作します。
251
+
252
+```javascript
253
+javascript: void(function () {
254
+ var exts = [
255
+ 'exe', 'msi', 'reg', 'zip', 'lzh', 'dmg', 'sit', 'hqx',
256
+ 'pdf', 'txt', 'htm', 'html', 'css', 'js', 'swf',
257
+ 'jpg', 'jpeg', 'eps', 'png', 'gif', 'tif', 'tiff', 'ico',
258
+ ];
259
+ var reExts = new RegExp('^.*\.(' + exts.join('|') + ')$', 'i');
260
+ var links = document.getElementsByTagName('a');
261
+ var urls = '';
262
+ for (var i = 0; i < links.length; i++) {
263
+ if (links[i].href && links[i].href.match(reExts)) {
264
+ urls += links[i].href + '<br>\r\n'
265
+ }
266
+ }
267
+ if (urls != '') {
268
+ var docNew = window.open('', '_blank').document;
269
+ docNew.open('text/html');
270
+ docNew.write('<html><body>\n' + urls + '</body></html>');
271
+ docNew.close();
272
+ }
273
+})()
274
+```
275
+
276
+# ページの更新日時をポップアップ
277
+```javascript
278
+javascript: void(function () {
279
+ var title = '更新日時' + ((frames.length > 0)
280
+ ? '\nフレームが使われています。正しい日時が得られていないかもしれません。'
281
+ : '');
282
+ prompt(title, new Date(window.document.lastModified).toLocaleString());
283
+})();
284
+```
285
+
286
+# 現在のページのレスポンスヘッダを表示
287
+```javascript
288
+javascript: (function(uri) {
289
+ var req = new XMLHttpRequest();
290
+ req.onreadystatechange = function() {
291
+ if (req.readyState === 4) {
292
+ var regHeader = /^\s*([^:]+):\s*([\s\S]+)\s*$/;
293
+ var result = '<table border="1">\n<tr><th>Response Header</th><th>Value</th></tr>\n';
294
+ var headers = req.getAllResponseHeaders().replace(/\s+$/, '').split(/\r?\n/).sort();
295
+ for (var i = 0, header; header = headers[i]; ++i) {
296
+ if (regHeader.exec(header)) {
297
+ result += '<tr><td>' + RegExp.$1 + '</td><td>' + RegExp.$2 + '</td></tr>\n';
298
+ }
299
+ }
300
+ result += '</table>\n';
301
+ var docNew = window.open('', '_blank').document;
302
+ docNew.open('text/html');
303
+ docNew.write('<html><body>\n' + result + '</body></html>');
304
+ docNew.close();
305
+ }
306
+ };
307
+ req.open('GET', uri, false);
308
+ req.send(null);
309
+})(location.href);
310
+```
311
+- [Accessing the web page's HTTP Headers in JavaScript - Stack Overflow](https://stackoverflow.com/questions/%32%32%30%32%33%31)
312
+
313
+# 選択した時刻文字列(EST, -05:00)をローカル時刻(JST, +09:00)に変換
314
+- [JavaScript/選択範囲/選択状態のテキストを扱う - yanor.net/wiki](http://yanor.net/wiki/?JavaScript%2F%E9%81%B8%E6%8A%9E%E7%AF%84%E5%9B%B2%2F%E9%81%B8%E6%8A%9E%E7%8A%B6%E6%85%8B%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%82%92%E6%89%B1%E3%81%86)
315
+
316
+```javascript
317
+javascript: (function () {
318
+var SrcTimeZone = '-05:00';
319
+var src = (window.getSelection().rangeCount)
320
+ ? window.getSelection().getRangeAt(0).cloneContents().firstChild.nodeValue
321
+ : prompt('Time in ' + SrcTimeZone);
322
+if (src) {
323
+ var date = new Date(src + ' ' + SrcTimeZone);
324
+ var year = padZero(date.getFullYear(), 4);
325
+ var month = padZero(date.getMonth() + 1, 2);
326
+ var day = padZero(date.getDate(), 2);
327
+ var wday = new Array("日", "月", "火", "水", "木", "金", "土")[date.getDay()];
328
+ var hour = padZero(date.getHours(), 2);
329
+ var min = padZero(date.getMinutes(), 2);
330
+ var sec = padZero(date.getSeconds(), 2);
331
+ var jst = year + '-' + month + '-' + day + ' (' + wday + ') ' + hour + ':' + min + ':' + sec;
332
+ prompt(SrcTimeZone + ' -> JST(+09:00)\nSrc: ' + src, jst);
333
+} else {
334
+ alert("Invalid Range.");
335
+}
336
+
337
+function padZero(x, n) { /* n: 2 or 4 */
338
+ return ('0000' + x).slice(-n);
339
+}
340
+})();
341
+```
342
+
343
+# 選択した文字列中の非ASCII文字をエスケープ
344
+```javascript
345
+javascript: (function() {
346
+ var src = window.getSelection().rangeCount ?
347
+ window.getSelection().getRangeAt(0).cloneContents().firstChild.nodeValue :
348
+ prompt('Paste string');
349
+ var enc = '';
350
+ for (var i = 0; i < src.length; ++i) {
351
+ var code = src.charCodeAt(i);
352
+ enc += 0x20 <= code && code < 0x7f ?
353
+ src.charAt(i) :
354
+ '&#x' + code.toString(16) + ';';
355
+ }
356
+ prompt('encoded', enc);
357
+})();
358
+```
359
+
360
+# ニコニコ動画のタイトルとIDを抽出
361
+```javascript
362
+javascript:void(function(){
363
+var title = (document.title.match(/(.+)\s‐\s[^\‐]+$/))[1];
364
+title = title.replace( /([A-Za-z0-9_ ])/g, function(ch){
365
+ return String.fromCharCode(ch.charCodeAt(0)-65248);
366
+});
367
+var vid = (location.href.match(/watch\/([^\?]+)/))[1];
368
+prompt( 'Nico Video', '[[' + title + '>Nico:' + vid + ']]' );
369
+})()
370
+```
371
+
372
+# Ustream のチャンネル (PukiWiki用)
373
+```javascript
374
+javascript:(function(){
375
+prompt( 'UstCh', '[[UstCh:' + ( location.href.match( /\/channel\/(.+)/ ))[1] + ']]' );
376
+})();
377
+```
378
+
379
+# Ustream の録画済み番組へのリンク (PukiWiki 用)
380
+```javascript
381
+javascript:void(function(){
382
+var elm = document.getElementById( 'VideoTitle' );
383
+location.href.match( /\/recorded\/(\d+(\/highlight\/\d+)?)/ );
384
+var RecChannel = RegExp.$1;
385
+prompt( 'Ustream Recorded', '[[' + elm.textContent + '>UstRec:' + RecChannel + ']]' );
386
+})()
387
+```
388
+
389
+# Ustream を全画面で見る
390
+```javascript
391
+javascript:void(function(){
392
+location.href = 'http://www.ustream.tv/flash/live/' + ustream.vars.channelId;
393
+})()
394
+```
395
+
396
+# http://srad.jp/ の記事のタイトルとIDを抽出
397
+- セクション名が付いている場合に対応。(2015/06/02)
398
+- ホスト変更に対応。(2015/05/12)
399
+- タイトルの並び順変更に対応。(2011/09/23)
400
+- システム変更に対応。(2011/08/31)
401
+<!---- headエレメントではなくdocument.titleを参照するようにした。(2010/04/28)-->
402
+
403
+```javascript
404
+javascript: (function() {
405
+ var title = document.title;
406
+ title = title.replace(/\s+\|\s+スラド.*$/, "");
407
+ var link = (location.href.match(/\/story\/(\d+\/\d+\/\d+\/\d+)/))[1];
408
+ prompt('SlashDotJp: ' + link + '\n' + title, '[[' + title + '>SlashDotJp:' + link + ']]');
409
+})();
410
+```
411
+
412
+# Amazon の ASIN を抜き出す (PukiWiki 用)
413
+```javascript
414
+javascript: (function() {
415
+ var authers = [];
416
+ var elmBooksTitle = document.getElementById('booksTitle');
417
+ var links = (elmBooksTitle ? elmBooksTitle : document).getElementsByTagName('A');
418
+ for (var i = 0, link; link = links[i]; ++i) {
419
+ if (link.href.match(/field-author|_athr_/) || link.className.split(/\s/).indexOf('contributorNameID') >= 0) {
420
+ var auther = link.textContent.replace(/\s/, "");
421
+ if (!auther.match(/著者ページを見る$|検索結果/)) {
422
+ authers.push(auther);
423
+ }
424
+ }
425
+ }
426
+ var ASIN = (location.href.match(/[\/\?](dp|ASIN|product|product-description|samples)[\/=]([0-9A-Z]{10})/))[2];
427
+ prompt(authers.join("\n") + "\n" + ASIN, ((authers.length > 0) ? authers.join(",") + "/" : "") + "&amazon(" + ASIN + ");");
428
+})();
429
+```
430
+
431
+# twitter の発言者へのリンク (PukiWiki 用)
432
+```javascript
433
+javascript: (function () {
434
+ location.pathname.match(/^\/([^\/]+)(\/.*)?/);
435
+ var dispName = RegExp.$1;
436
+ var fullName = (!RegExp.$2)
437
+ ? scanElements('h1', 'fullname')
438
+ : scanElements('strong', 'fullname');
439
+ var name = fullName + ' (' + dispName + ')';
440
+ prompt(name, '[[' + name + '>Twitter:' + dispName + ']]');
441
+
442
+ function scanElements(tagName, className) {
443
+ var ret = '';
444
+ var elms = document.getElementsByTagName(tagName);
445
+ for (var i = 0; i < elms.length; ++i) {
446
+ if (elms[i].className.slice(0, className.length) == className) {
447
+ ret = elms[i].innerText.replace(/^\s+|\s+$/g, '');
448
+ break;
449
+ }
450
+ }
451
+ return ret;
452
+ }
453
+})();
454
+```
455
+
456
+# twitter の発言へのリンク
457
+```javascript
458
+javascript:(function(){
459
+var fullName = '';
460
+var userLink = '';
461
+var description = '';
462
+var message = '';
463
+var elms = document.getElementsByTagName( 'a' );
464
+for( var i=0; i<elms.length; ++i ){
465
+ if ( elms[i].className == 'tweet-user-block-screen-name user-profile-link' ){
466
+ fullName = elms[i].title;
467
+ userLink = elms[i].href;
468
+ break;
469
+ }
470
+}
471
+var elms = document.getElementsByTagName( 'div' );
472
+for( var i=0; i<elms.length; ++i ){
473
+ if ( elms[i].className == 'tweet-text tweet-text-large' ){
474
+ description = elms[i].textContent || elms[i].innerText;
475
+ break;
476
+ }
477
+}
478
+var exLinks = [];
479
+checkLink( /^(.*)\s*(#\w+)\s*$/, linkTwitHash );
480
+checkLink( /^(.*)\s*(http\:\/\/[^\s]+)\s*$/, function(x){ return x; } );
481
+checkLink( /^(.*)\s*(#\w+)\s*$/, linkTwitHash );
482
+message += '[[' + fullName + '>' + userLink + ']]';
483
+message += '「[[' + description + '>' + location.href + ']]';
484
+for( var i=exLinks.length; --i>=0; ){
485
+ message += ' [['+exLinks[i].key+'>'+exLinks[i].url+']]';
486
+}
487
+message += '」';
488
+prompt( 'twitLink', message );
489
+
490
+function checkLink( regex, func ){
491
+ while( description.match(regex) ){
492
+ description = RegExp.$1;
493
+ exLinks.push({
494
+ 'key': RegExp.$2,
495
+ 'url': func(RegExp.$2),
496
+ });
497
+ }
498
+}
499
+
500
+function linkTwitHash(x){
501
+ return 'http://twitter.com/#!/search?q=' + encodeURIComponent(x);
502
+}
503
+})();
504
+```
505
+
506
+# twitter の発言へのリンク (日時付き, PukiWiki用)
507
+- [Twitter API 仕様書 (勝手に日本語訳シリーズ)](http://watcher.moe-nifty.com/memo/2007/04/twitter_api.html) @ [[観] 観測気球](http://watcher.moe-nifty.com/)
508
+
509
+```javascript
510
+javascript:(function(){
511
+var host = location.protocol + '//' + location.host;
512
+location.href.match( /([^\/]+\/[^\/]+\/([^\/]+))$/ );
513
+var TwitUrl = RegExp.$1;
514
+var statusId = RegExp.$2;
515
+
516
+var httpRequest = false;
517
+if ( window.XMLHttpRequest ){
518
+ /* Firefox, Opera など */
519
+ httpRequest = new XMLHttpRequest();
520
+ httpRequest.overrideMimeType('text/xml');
521
+} else if( window.ActiveXObject ){
522
+ /* IE */
523
+ try {
524
+ httpRequest = new ActiveXObject('Msxml.XMLHTTP');
525
+ } catch(e){
526
+ httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
527
+ }
528
+}
529
+
530
+httpRequest.abort();
531
+httpRequest.open( 'GET', host + '/statuses/show/' + statusId + '.json', true );
532
+httpRequest.onreadystatechange = function(){
533
+ if ( httpRequest.readyState == 4 && httpRequest.status == 200 ){
534
+ var statusInfo = eval( '(' + httpRequest.responseText + ')' );
535
+ /* alert( _dump( statusInfo ) ); */
536
+ var date = new Date( statusInfo.created_at );
537
+ prompt(
538
+ date.toLocaleString() + '\n' + statusInfo.text,
539
+ '[[' + date.toLocaleString() + '>Twitter:' + TwitUrl + ']]&br;'
540
+ + statusInfo.text + '\n'
541
+ );
542
+ }
543
+};
544
+httpRequest.send( null );
545
+
546
+function _dump( obj ){
547
+ var ret = '';
548
+ for( var p in obj ){
549
+ if ( typeof(obj[p]) == 'object' ){
550
+ ret += '\n' + p + ':\n';
551
+ ret += _dump( obj[p] );
552
+ } else {
553
+ ret += p + ': ' + obj[p] + '\n';
554
+ }
555
+ }
556
+ return ret;
557
+}
558
+})();
559
+```
560
+
561
+# twitter の表示されているタイムラインを単純テキスト化
562
+- 発言時刻を相対値ではなく絶対値にする。
563
+- 発言の個別 URI を表示する。
564
+- 発言中のリンクを展開する。
565
+- 発言中の「<>」を実体参照に変換。(2012/07/02, 発言全体をencodeURI()すると漢字等もエスケープされてしまうので不採用)
566
+- ScreenName の前に「/#!/」を付けるのをやめ、「/」だけに変更。(2012/08/13)
567
+- 「認証済みアカウント」がリンクにならないように変更。(2013/02/20)
568
+
569
+- [Introduction to using XPath in JavaScript - MDN](https://developer.mozilla.org/ja/Introduction_to_using_XPath_in_JavaScript)
570
+- [多趣旨の国](http://uhyohyohyo.sakura.ne.jp/) / [JavaScript初級者から中級者になろう](http://uhyohyohyo.sakura.ne.jp/javascript.html) / [十章第三回 属性の取得と型](http://uhyohyohyo.sakura.ne.jp/javascript/10_3.html)
571
+- [素人がプログラミングを勉強するブログ](http://d.hatena.ne.jp/javascripter/) / [XPath入門、実用例](http://d.hatena.ne.jp/javascripter/20080425/1209094795)
572
+
573
+```javascript
574
+javascript: (function () {
575
+var sTwHost = 'https://twitter.com';
576
+var itrOriginalTweets = getIteratorByXpath('//div[starts-with(@class,"tweet original-tweet")]', document);
577
+var sTweets = '';
578
+var sNow = new Date().toLocaleString();
579
+sTweets += sNow + '<br>\n';
580
+try {
581
+ var nodeTweet;
582
+ while (nodeTweet = itrOriginalTweets.iterateNext()) {
583
+ var sUserName = getStringByXpath('./div/div/a[starts-with(@class,"account-group")]/strong', nodeTweet);
584
+ var isVerified = getStringByXpath('./div/div/a[starts-with(@class,"account-group")]/strong/span[starts-with(@class,"icon verified")]', nodeTweet);
585
+ if ( isVerified ){
586
+ sUserName = sUserName.replace( new RegExp( isVerified + '$' ), '' );
587
+ }
588
+ var sScreenName = getStringByXpath('./@data-screen-name', nodeTweet);
589
+ /* var sDateTime = getStringByXpath( './div/div/small/a/@title', nodeTweet ); */
590
+ var nDateTime = 1 * getStringByXpath('./div/div/small/a/span/@data-time', nodeTweet);
591
+ if (nDateTime < 1151679600 * 1000) { /* 2006-07-01 以前だったら ms 単位に変換 */
592
+ nDateTime *= 1000;
593
+ }
594
+ var sDateTime = new Date(nDateTime).toLocaleString();
595
+ var sTweetId = getStringByXpath('./@data-tweet-id', nodeTweet);
596
+ var sTweetUrl = sTwHost + '/' + sScreenName + '/status/' + sTweetId;
597
+ sTweets += '----<br>\n';
598
+ sTweets += '<a href="' + sTwHost + '/' + sScreenName + '" target="_blank">' + sUserName + '</a>\t';
599
+ sTweets += ( isVerified ) ? '[' + isVerified + ']\t' : '';
600
+ sTweets += '<a href="' + sTwHost + '/' + sScreenName + '" target="_blank">@' + sScreenName + '</a>\t';
601
+ sTweets += sDateTime + '<br>\n';
602
+ sTweets += '<a href="' + sTweetUrl + '" target="_blank">' + sTweetUrl + '</a><br>\n';
603
+ sTweets += getStringByXpath('./div/p', nodeTweet).replace(/^\s+|\s+$/g, '').replace(/[<>]/g, function (c) {
604
+ return '&#' + c.charCodeAt(0) + ';'
605
+ }).replace(/[\r\n]+/g, '<br>\n') + '<br>\n';
606
+ var itrLinks = getIteratorByXpath('./div/p/a', nodeTweet);
607
+ if (itrLinks) {
608
+ var nodeLink;
609
+ while (nodeLink = itrLinks.iterateNext()) {
610
+ var sLinks = getStringByXpath('./@data-ultimate-url', nodeLink)
611
+ || getStringByXpath('./@data-expanded-url', nodeLink) || getStringByXpath('./@href', nodeLink);
612
+ if (sLinks.slice(0, 1) == '/') {
613
+ sLinks = sTwHost + sLinks;
614
+ }
615
+ sTweets += '<a href="' + sLinks + '" target="_blank">' + sLinks + '</a><br>\n';
616
+ }
617
+ }
618
+ }
619
+} catch (e) {
620
+ alert('Error: ' + e);
621
+}
622
+var winOutput = window.open('', '_blank');
623
+winOutput.document.open('text/html; charset=UTF-8');
624
+winOutput.document.write('<html>\n<head><title>TwTextifier ' + sNow + '</title></head>\n<body>\n');
625
+winOutput.document.write(sTweets);
626
+winOutput.document.write('</body>\n</html>\n');
627
+winOutput.document.close();
628
+
629
+function getIteratorByXpath(xpath, context) {
630
+ return document.evaluate(xpath, context, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
631
+}
632
+
633
+function getStringByXpath(xpath, context) {
634
+ var sRet = "";
635
+ var nodeTmp = document.evaluate('string(' + xpath + ')', context, null, XPathResult.STRING_TYPE, null);
636
+ if (nodeTmp) {
637
+ sRet = nodeTmp.stringValue;
638
+ }
639
+ return sRet;
640
+}
641
+})();
642
+```
643
+
644
+# twitter の発言を twittaku で確認
645
+```javascript
646
+javascript:(function(url){
647
+if ( location.host == 'twitter.com' ){
648
+ if ( url.match( /\/status\/(\d+)/ ) ){
649
+ location = 'http://twittaku.info/view.php?id=' + RegExp.$1;
650
+ } else if( url.match( /\/([^\/]+)$/ ) ){
651
+ location = 'http://twittaku.info/searchtweet.php?type=name&word=' + RegExp.$1;
652
+ }
653
+}
654
+})(location.href);
655
+```
656
+
657
+# twitter.com から twilog.org へ転送
658
+```javascript
659
+javascript: (function () {
660
+ if (location.hostname == 'twitter.com' && location.pathname.match(/^\/([0-9a-zA-Z_]+)/)) {
661
+ location = 'http://twilog.org/' + RegExp.$1;
662
+ }
663
+})();
664
+```
665
+
666
+# togetter へのリンク (PukiWiki 用)
667
+```javascript
668
+javascript:(function(){
669
+if ( location.href.match( /^http:\/\/togetter.com\/(\w)([^\/]+)\/(.*)/ ) ){
670
+ var type = 'Toget' + RegExp.$1.toUpperCase() + RegExp.$2;
671
+ var id = RegExp.$3;
672
+ var title = document.title.replace( /\s+-\s+Togetter$/, "" );
673
+ prompt(
674
+ type + ': ' + id + '\n' + title,
675
+ '[[' + title + '>' + type + ':' + id + ']]'
676
+ );
677
+}
678
+})();
679
+```
680
+
681
+# twemoji を現在のページに適用
682
+```javascript
683
+javascript: (function() {
684
+ var twemojiStyleElm = document.createElement('style');
685
+ twemojiStyleElm.type = 'text/css';
686
+ twemojiStyleElm.appendChild(document.createTextNode(
687
+ 'img.emoji { height: 1em; width: 1em; margin: 0.05em 0.1em; vertical-align: -0.1em; }'
688
+ ));
689
+ document.getElementsByTagName('head')[0].appendChild(twemojiStyleElm);
690
+ var twemojiScriptElm = document.createElement('script');
691
+ twemojiScriptElm.id = 'twemoji';
692
+ twemojiScriptElm.type = 'text/javascript';
693
+ twemojiScriptElm.src = '//twemoji.maxcdn.com/twemoji.min.js';
694
+ twemojiScriptElm.addEventListener('load', (function(win) {
695
+ return function() {
696
+ twemoji.parse(win.document.body);
697
+ };
698
+ })(window), false);
699
+ document.getElementsByTagName('body')[0].appendChild(twemojiScriptElm);
700
+})();
701
+```
702
+- [Open sourcing Twitter emoji for everyone - Twitter Blogs](https://blog.twitter.com/2014/open-sourcing-twitter-emoji-for-everyone)
703
+- [GitHub:twitter/twemoji](https://github.com/twitter/twemoji)
704
+
705
+# WikiPediaへのリンク (PukiWiki 用)
706
+```javascript
707
+javascript:(function(){
708
+location.href.match(/(\w+)\.wikipedia\.org\/wiki\/(.*)/);
709
+prompt('WikiPedia Link','[[WikiPedia.'+RegExp.$1+':'+decodeURI(RegExp.$2)+']]');
710
+})();
711
+```
712
+
713
+# CPANへのリンク (PukiWiki 用)
714
+```javascript
715
+javascript:(function(){
716
+location.href.match(/search\.cpan\.org\/dist\/(.*[^\/])\/?/);
717
+prompt('CPAN Link','[[CPAN:'+RegExp.$1+']]');
718
+})();
719
+```
720
+
721
+# Pixivプロフィールへのリンク (PukiWiki 用)
722
+```javascript
723
+javascript: (function() {
724
+ if (location.hostname != 'www.pixiv.net') {
725
+ return;
726
+ }
727
+ var userName = '';
728
+ var h1s = document.getElementsByTagName('h1');
729
+ for (var i = 0, h1; h1 = h1s[i]; ++i) {
730
+ if (h1.className == 'user') {
731
+ userName = h1.textContent;
732
+ break;
733
+ }
734
+ }
735
+ location.href.match(/member.php\?id=(\d+)/);
736
+ prompt('Pixiv Member', '[[' + userName + '>PixivMember:' + RegExp.$1 + ']]');
737
+})();
738
+```
739
+
740
+# Pixivイラストへのリンク (PukiWiki 用)
741
+```javascript
742
+javascript:(function(){
743
+if ( location.hostname == 'www.pixiv.net' ){
744
+ var Title = '';
745
+ var IllustId = pixiv.context.illustId;
746
+ var elmMetas = document.getElementsByTagName('meta');
747
+ for(var i=0; i<elmMetas.length; ++i){
748
+ if(elmMetas[i].outerHTML.match(/property="og:title"/)){
749
+ Title = elmMetas[i].content;
750
+ } else if(elmMetas[i].outerHTML.match(/property="og:url"/)){
751
+ IllustId = (elmMetas[i].content.match(/illust_id=(\d+)/))[1];
752
+ }
753
+ }
754
+ if ( !Title ){ /* 小説用 */
755
+ Title = (document.title.match(/^「([^」]+)」/))[1];
756
+ IllustId = (location.href.match(/id=(\d+)$/))[1];
757
+ }
758
+ var UserId = pixiv.context.userId;
759
+ var UserName = '';
760
+ var elmAnchors = document.getElementsByTagName('a');
761
+ for(var i=0; i<elmAnchors.length; ++i){
762
+ if(elmAnchors[i].href.match(/member.php\?id=(\d+)/)){
763
+ UserId = RegExp.$1;
764
+ UserName = elmAnchors[i].innerText.replace(/^\s+|\s+$/g, '');
765
+ if ( UserName != 'プロフィール' && UserName != '' ){
766
+ break;
767
+ }
768
+ }
769
+ }
770
+ prompt(
771
+ 'Pixiv Member & Illust',
772
+ '[[' + UserName + '>PixivMember:' + UserId + ']]'
773
+ + ' / [[' + Title + '>PixivIllust:' + IllustId + ']] '
774
+ );
775
+}
776
+})();
777
+```
778
+
779
+# GitHub リポジトリのリンク (PukiWiki 用)
780
+```javascript
781
+javascript: (function() {
782
+ if (location.host != 'github.com') {
783
+ return;
784
+ }
785
+ location.pathname.match(/^\/([^\/]+\/[^\/]+)/);
786
+ var key = RegExp.$1;
787
+ prompt(key, '[[GitHub:' + key + ']]');
788
+})();
789
+```
790
+
791
+# Stackoverflow へのリンク (PukiWiki 用)
792
+```javascript
793
+javascript: (function(title, uri) {
794
+ if (!uri.match(/^https?:\/\/(?:(\w+)\.)?stackoverflow.com\/questions\/(\d+)\//)) {
795
+ return;
796
+ }
797
+ var alias = 'Stackoverflow' + (RegExp.$1 != "" ? '.' + RegExp.$1 : '') + ':' + RegExp.$2;
798
+ prompt(title + '\n' + alias, '[[' + title + '>' + alias + ']]');
799
+})(document.title, location.href);
800
+```
801
+
802
+# IETF RFC へのリンク (PukiWiki 用)
803
+```javascript
804
+javascript: void(function() {
805
+ if (location.host != 'www.ietf.org' && location.host != 'tools.ietf.org') {
806
+ return;
807
+ }
808
+ var title = document.title;
809
+ location.pathname.match(/\/(rfc|html)\/rfc(\d+)/);
810
+ var id = RegExp.$2;
811
+ prompt(title + '\n' + id, '[[' + title + '>RFC:' + id + ']]');
812
+})();
813
+```
814
+
815
+# テーブル内の特定のセルの内容をポップアップ
816
+- [外国為替相場一覧表 - 三菱東京UFJ銀行](http://www.bk.mufg.jp/gdocs/kinri/list_j/kinri/kawase.html)の「EUR/T.T.S.」をポップアップする。<br />
817
+参考: [三菱UFJリサーチ&コンサルティング - 外国為替相場 - 1990年以降の為替相場](http://www.murc-kawasesouba.jp/fx/past_3month.php)
818
+```javascript
819
+javascript: (function () {
820
+ var currency = 'EUR';
821
+ var xpath = '//tr[./td/font[starts-with(text(),"' + currency + '")]]/td[3]';
822
+ var nodeTmp = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
823
+ var nodeTarget = nodeTmp.singleNodeValue;
824
+ if (nodeTarget) {
825
+ prompt(currency + '/T.T.S.', (nodeTarget.textContent || nodeTarget.innerText).replace(/^\s+|\s+$/g, ''));
826
+ } else {
827
+ alert('Not found');
828
+ }
829
+})();
830
+```
831
+
832
+# PukiWiki エイリアス
833
+- body の最初の h2 タグをエイリアス名として抽出
834
+```javascript
835
+javascript: (function () {
836
+var pageTitle = getStringByXpath('//div[@id="body"]/h2[1]', document);
837
+var pageName = getStringByXpath('//div[@id="header"]/h1[@class="title"]/a', document);
838
+prompt(pageTitle + '\n' + pageName, '[[' + pageTitle + '>' + pageName + ']]');
839
+
840
+function getStringByXpath(xpath, context) {
841
+ var sRet = "";
842
+ var nodeTmp = document.evaluate('string(' + xpath + ')', context, null, XPathResult.STRING_TYPE, null);
843
+ if (nodeTmp) {
844
+ sRet = nodeTmp.stringValue;
845
+ }
846
+ return sRet;
847
+}
848
+})();
849
+```
... ...
\ No newline at end of file
JavaScript/GoogleCalendarAPI.md
... ...
@@ -0,0 +1,29 @@
1
+[[_TOC_]]
2
+
3
+# Node.js Quickstart
4
+- [Node.js Quickstart - Google Calendar API - Google Developers](https://developers.google.com/google-apps/calendar/quickstart/nodejs)
5
+
6
+## Google Calendar API の有効化
7
+1. [ウィザード](https://console.developers.google.com/start/api?id=calendar)を使って、Google Developers Console に新規プロジェクトを作成するか、既存のプロジェクトを選択する。「続行」をクリックする。「API が有効化されました」と表示されるので「認証情報に進む」をクリックする。
8
+1. [API Manager](https://console.developers.google.com/apis)で、該当プロジェクトの認証情報を作成する。「OAuth同意画面」タブを選択する。「メールアドレス」を選択し、「ユーザーに表示するサービス名 」を入力する。「保存」をクリックする。
9
+1. 「認証情報」タブを選択する。「認証情報を作成」ボタンをクリックする。「OAuth クライアント ID」を選択する。
10
+1. 「アプリケーションの種類」で「その他 」を選択し「名前」に「Google Calendar API Quickstart」を入力する。「作成」をクリックする。
11
+1. 作成された「OAuth クライアント」の「クライアント ID」と「クライアント シークレット」が表示される。「OK」を押して閉じる。
12
+1. 「JSON をダウンロード」ボタンをクリックして認証情報をローカルに保存する。
13
+1. ファイル名を「client_secret.json」に変更する。
14
+
15
+## クライアントライブラリをインストール
16
+```
17
+$ npm install googleapis --save
18
+$ npm install google-auth-library --save
19
+```
20
+
21
+## サンプルのセットアップ
22
+- [quickstart.zip](quickstart.zip)
23
+- サンプルの実行
24
+```
25
+$ node quickstart.js
26
+```
27
+- 「許可のリクエスト」ページの URL が表示されるので、ブラウザの URL 欄にコピー&ペーストし、ページを開く。
28
+- 「許可」ボタンをクリック。
29
+- 表示された「コード」をコピーして、コマンドラインにペーストし、エンター。
... ...
\ No newline at end of file
JavaScript/GoogleMapAPI.md
... ...
@@ -0,0 +1,206 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- Google Map API を使って始点終点の経路情報と地図画像を得る。
5
+- [Google Maps JavaScript API](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html) - [DirectionsService](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html#DirectionsService)を使って経路検索を行ないます。
6
+- [Static Maps API](http://code.google.com/intl/ja/apis/maps/documentation/staticmaps/)を使って地図画像を得ます。
7
+- coderepos.org にアクセスできないようなので uneval をコメントアウト。(2013-12-06)
8
+
9
+# ソース
10
+- [gmap.zip](gmap.zip)
11
+
12
+## gmap.html
13
+- [http://www.takeash.net/Etc/gmap.html](http://www.takeash.net/Etc/gmap.html)
14
+```html
15
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
16
+<html lang="ja">
17
+<head>
18
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
19
+<meta http-equiv="Content-Script-Type" content="text/javascript">
20
+<meta http-equiv="Content-Style-Type" content="text/css">
21
+<title>Google Map API</title>
22
+<link rel="stylesheet" type="text/css" href="http://www.takeash.net/take.css">
23
+<style TYPE="text/css">
24
+<!--
25
+.debug {
26
+ display: none;
27
+}
28
+-->
29
+</style>
30
+</head>
31
+<body onload="init()">
32
+<h1>Google Map API</h1>
33
+<ul>
34
+<li><p><a href="http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html">Google Maps JavaScript API</a> - <a href="http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html#DirectionsService">DirectionsService</a>を使って経路検索を行ないます。</p></li>
35
+<li><p><a href="http://code.google.com/intl/ja/apis/maps/documentation/staticmaps/">Static Maps API</a>を使って地図画像を得ます。</p></li>
36
+</ul>
37
+<form id="FORMGMAP" action="#">
38
+<table summary="Map Options" border="1">
39
+<tr><th>出発地</th><td><input id="START" type="text" value="東京駅"></td></tr>
40
+<tr><th>目的地</th><td><input id="GOAL" type="text" value="東京ビックサイト"></td></tr>
41
+<tr><th>手段</th><td>
42
+<select id="TRAVELMODE">
43
+<option value="W" selected>徒歩</option>
44
+<option value="D">自動車</option>
45
+<option value="B">自転車</option>
46
+</select>
47
+</td></tr>
48
+<tr><th>マップタイプ</th><td>
49
+<select id="MAPTYPE">
50
+<option value="R" selected>道路地図</option>
51
+<option value="S">航空写真</option>
52
+<option value="T">地形図</option>
53
+<option value="H">組み合わせ</option>
54
+</select>
55
+</td></tr>
56
+<tr><th>大きさ</th><td>
57
+<select id="MAPSIZE">
58
+<option value="200x200">200x200</option>
59
+<option value="300x300" selected>300x300</option>
60
+<option value="400x400">400x400</option>
61
+<option value="400x640">400x640</option>
62
+<option value="500x500">500x500</option>
63
+<option value="640x400">640x400</option>
64
+<option value="640x640">640x640</option>
65
+</select>
66
+</td></tr>
67
+<tr class="debug"><th>モバイル</th><td><input id="MOBILE" name="MOBILE" type="checkbox" value="on"> <label for="mobile">モバイルモード</label></td></tr>
68
+<tr><td colspan="2" align="center"><input type="button" value=" 表示 " onclick="getMap()"></td></tr>
69
+</table>
70
+</form>
71
+
72
+<h2 id="TITLE">出発地 - 目的地</h2>
73
+<p><img id="GMAP" alt="gmap" src="http://code.google.com/images/code_logo.png"></p>
74
+<div class="debug"><textarea id="DEBUG" rows="30" cols="100">debug</textarea></div>
75
+
76
+<!-- http://www.openspc2.org/reibun/Google/Maps/API/ver3/ -->
77
+<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
78
+<!-- http://blog.livedoor.jp/dankogai/archives/50958256.html -->
79
+<!-- <script type="text/javascript" src="http://coderepos.org/share/browser/lang/javascript/clone/trunk/uneval.js?format=txt"></script> -->
80
+<script type="text/javascript" src="http://www.takeash.net/Etc/gmap.js"></script>
81
+</body>
82
+</html>
83
+```
84
+
85
+## gmap.js
86
+- [http://www.takeash.net/Etc/gmap.js](http://www.takeash.net/Etc/gmap.js)
87
+```javascript
88
+/*
89
+ Google Map 表示(経路付き)
90
+ gmap.js
91
+ 2010.11.07 初版。
92
+ 2010.11.08 LatLng のアクセス方法変更。地図の中心を求めるのに LatLngBounds を使うようにした。タイトルを検索結果で置き換えるようにした。
93
+*/
94
+
95
+var GoogleMapStaticAPI = "http://maps.google.com/maps/api/staticmap?sensor=false";
96
+var TravelMode = { 'W':'WALKING', 'D':'DRIVING', 'B':'BICYCLING' };
97
+var MapType = { 'R':'roadmap', 'S':'satellite', 'T':'terrain', 'H':'hybrid' };
98
+
99
+function getMap(){
100
+ var directionsService = new google.maps.DirectionsService();
101
+ var elmStart = document.getElementById( "START" );
102
+ var elmGoal = document.getElementById( "GOAL" );
103
+ var elmTravelMode = document.getElementById( "TRAVELMODE" );
104
+ var travelmode = TravelMode[ elmTravelMode.options[ elmTravelMode.selectedIndex ].value ] || TravelMode[ 'W' ];
105
+ var elmMapType = document.getElementById( "MAPTYPE" );
106
+ var maptype = MapType[ elmMapType.options[ elmMapType.selectedIndex ].value ] || MapType[ 'R' ];
107
+ var elmMapSize = document.getElementById( "MAPSIZE" );
108
+ var mapsize = elmMapSize.options[ elmMapSize.selectedIndex ].value;
109
+ if ( !mapsize.match( /\d+x\d+/ ) ){
110
+ mapsize = "300x300";
111
+ }
112
+ var elmMobile = document.getElementById( "MOBILE" );
113
+
114
+ var elmTitle = document.getElementById( "TITLE" );
115
+ var elmGMap = document.getElementById( "GMAP" );
116
+ var elmDebug = document.getElementById( "DEBUG" );
117
+
118
+ directionsService.route(
119
+ {
120
+ origin : elmStart.value,
121
+ destination: elmGoal.value,
122
+ travelMode: google.maps.DirectionsTravelMode[ travelmode ]
123
+ },
124
+ function( response, status ){
125
+ if ( status == google.maps.DirectionsStatus.OK ) {
126
+ var legs = response['routes'][0]['legs'][0];
127
+ //elmDebug.value = uneval( legs );
128
+ if ( elmTitle.textContent ){
129
+ elmTitle.textContent = legs['start_address'] + ' - ' + legs['end_address'];
130
+ } else {
131
+ elmTitle.innerText = legs['start_address'] + ' - ' + legs['end_address'];
132
+ }
133
+
134
+ var start_loc = legs['start_location'];
135
+ var end_loc = legs['end_location'];
136
+ // var center_loc = new LatLngBounds(start_loc,end_loc).getCenter() だと
137
+ // スタートとエンドを入れ替えたときに変な値を返すことがある
138
+ var bounds = new google.maps.LatLngBounds();
139
+ bounds.extend( start_loc );
140
+ bounds.extend( end_loc );
141
+ var center_loc = bounds.getCenter();
142
+ elmGMap.src = GoogleMapStaticAPI
143
+ + '&maptype=' + maptype
144
+ + '&size=' + mapsize
145
+ + '&mobile=' + elmMobile.checked
146
+ + '&center=' + center_loc.toUrlValue()
147
+ + '&markers=label:S|' + start_loc.toUrlValue()
148
+ + '&markers=label:G|' + end_loc.toUrlValue()
149
+ + '&path=enc:' + response['routes'][0]['overview_polyline']['points'];
150
+ }else{
151
+ //elmDebug.value = uneval( response );
152
+ if ( elmTitle.textContent ){
153
+ elmTitle.textContent = "Error: " + response.status;
154
+ } else {
155
+ elmTitle.innerText = "Error: " + response.status;
156
+ }
157
+ elmGMap.src = "http://code.google.com/images/code_logo.png";
158
+ }
159
+ }
160
+ );
161
+}
162
+
163
+// JavaScriptの動かないコード (中級編) onKeydownイベントが認識されない
164
+// http://d.hatena.ne.jp/language_and_engineering/20081112/1226507019
165
+function init(){
166
+ document.onkeyup = myExec;
167
+}
168
+
169
+// <input type="text">でEnterを押してもsubmitさせない方法【HTML, JavaScript】
170
+// http://www.programming-magic.com/20080119212425/
171
+function myExec(e){
172
+ if (!e) var e = window.event;
173
+ if( e.keyCode == 13 ){
174
+ getMap();
175
+ }
176
+}
177
+
178
+// EOF
179
+```
180
+
181
+# リンク
182
+- [[Perl/GoogleMapAPI]]
183
+
184
+- [Google Maps APIs - Google Developers](https://developers.google.com/maps/documentation/)
185
+ - [Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript/)
186
+ - [Get a Key/Authentication](https://developers.google.com/maps/documentation/javascript/get-api-key)
187
+ - [Google Static Maps API](https://developers.google.com/maps/documentation/static-maps/)
188
+
189
+- [Google Maps API ファミリー - Google Code](http://code.google.com/intl/ja/apis/maps/)
190
+ - [Google Maps JavaScript API](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html)
191
+ - [DirectionsService](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html#DirectionsService)
192
+ - [LatLng](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html#LatLng)
193
+ - [LatLngBounds](http://code.google.com/intl/ja/apis/maps/documentation/javascript/reference.html#LatLngBounds)
194
+ - [Static Maps API](http://code.google.com/intl/ja/apis/maps/documentation/staticmaps/)
195
+
196
+- [OpenSpace](http://www.openspc2.org/)
197
+ - [逆引きGoogle Maps APIリファレンス ver 3](http://www.openspc2.org/reibun/Google/Maps/API/ver3/)
198
+
199
+- [404 Blog Not Found](http://blog.livedoor.jp/dankogai/)
200
+ - [javascript - uneval() for the rest of us!](http://blog.livedoor.jp/dankogai/archives/50958256.html)
201
+
202
+- [主に言語とシステム開発に関して](http://d.hatena.ne.jp/language_and_engineering/)
203
+ - [JavaScriptの動かないコード (中級編) onKeydownイベントが認識されない](http://d.hatena.ne.jp/language_and_engineering/20081112/)
204
+
205
+- [Programming Magic](http://www.programming-magic.com/)
206
+ - [<input type="text">でEnterを押してもsubmitさせない方法【HTML, JavaScript】](http://www.programming-magic.com/20080119212425/)
JavaScript/Home.md
... ...
@@ -1,3 +1,430 @@
1
-# JavaScirpt
1
+[[_TOC_]]
2 2
3
-- [[Bookmarklet]]
3
+# リンク
4
+- [ECMAScript](http://ja.wikipedia.org/wiki/%45%43%4d%41%53%63%72%69%70%74)
5
+- [Dynamic HTMLリファレンス](http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpisdk/dhtml/references/dhtmlrefs.asp)
6
+- [HTML and DHTML Reference](http://msdn2.microsoft.com/en-us/library/ms533050.aspx)
7
+- [OperaWiki:User JavaScript](http://ja.opera-wiki.com/User JavaScript)
8
+- [オブジェクト指向プログラム言語としてのJavaScript](http://www.tokumaru.org/JavaScript/)
9
+- [HTA Developers Center](http://www.microsoft.com/technet/scriptcenter/hubs/htas.mspx) / [HTML Applications Reference](http://msdn.microsoft.com/en-us/library/ms536473(VS.85).aspx) / [HTA Helpomatic](http://www.microsoft.com/downloads/details.aspx?FamilyId=231D8143-F21B-4707-B583-AE7B9152E6D9&displaylang=en)
10
+- [jquery.jsを読み解く](http://gihyo.jp/dev/feature/01/jquery)
11
+- [JavaScriptリファレンス@ITpro](http://itpro.nikkeibp.co.jp/article/Reference/20081119/319583/)
12
+- [Online JavaScript beautifier](http://jsbeautifier.org/)
13
+ - [GitHub:beautify-web/js-beautify](https://github.com/beautify-web/js-beautify)
14
+- [kangax projects](http://kangax.github.io/)
15
+ - [ECMAScript 5 compatibility table](http://kangax.github.io/es5-compat-table/)
16
+ - [ECMAScript 6 compatibility table](http://kangax.github.io/es5-compat-table/es6/)
17
+ - [Javascript 2D canvas libraries comparison table](https://docs.google.com/spreadsheet/ccc?key=0Aqj_mVmuz3Y8dHNhUVFDYlRaaXlyX0xYSTVnalV5ZlE#gid=0)
18
+
19
+# Anchor Synchronization
20
+ある<a>に連動して他の<a>のリンク先が変化するサンプル。
21
+- [AnchorSynch.html](AnchorSynch.html)
22
+
23
+# URI/URIコンポーネントのエンコード/デコード
24
+- [EncDec.html](EncDec.html)
25
+```html
26
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
27
+<html lang="ja">
28
+<head>
29
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
30
+ <meta http-equiv="Content-Script-Type" content="text/javascript">
31
+ <title>URI/URIコンポーネントのエンコード/デコード</title>
32
+</head>
33
+<body>
34
+<script type="text/javascript">
35
+<!--
36
+function EncURI(){
37
+ document.formEncDec.txtDst.value = encodeURI( document.formEncDec.txtSrc.value );
38
+}
39
+
40
+function DecURI(){
41
+ document.formEncDec.txtDst.value = decodeURI( document.formEncDec.txtSrc.value );
42
+}
43
+
44
+function EncURIC(){
45
+ document.formEncDec.txtDst.value = encodeURIComponent( document.formEncDec.txtSrc.value );
46
+}
47
+
48
+function DecURIC(){
49
+ document.formEncDec.txtDst.value = decodeURIComponent( document.formEncDec.txtSrc.value );
50
+}
51
+
52
+function Cpy(){
53
+ document.formEncDec.txtSrc.value = document.formEncDec.txtDst.value;
54
+}
55
+// -->
56
+</script>
57
+
58
+<h1>URI/URIコンポーネントのエンコード/デコード</h1>
59
+
60
+<form name="formEncDec" action="#">
61
+<table summary="Encode Decode Form">
62
+<tr><td><input type="text" name="txtSrc" size="100" value=""></td></tr>
63
+<tr><td align="center">
64
+<input type="button" name="btnEnc" value="↓EncURI" onClick="EncURI()">
65
+<input type="button" name="btnDec" value="↓DecURI" onClick="DecURI()">
66
+<input type="button" name="btnEncC" value="↓EncURIC" onClick="EncURIC()">
67
+<input type="button" name="btnDecC" value="↓DecURIC" onClick="DecURIC()">
68
+<input type="button" name="btnCpy" value="↑Copy" onClick="Cpy()">
69
+</td></tr>
70
+<tr><td><input type="text" name="txtDst" size="100" value=""></td></tr>
71
+</table>
72
+</form>
73
+
74
+</body>
75
+</html>
76
+```
77
+
78
+# 半角数字を漢数字に変換
79
+- [NumberString.html](NumberString.html)
80
+- [Excel即効テクニック 数値を漢数字で表示したい](http://pc.nikkeibp.co.jp/article/NPC/20060214/229266/)
81
+```html
82
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
83
+<html lang="ja">
84
+<head>
85
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
86
+<meta http-equiv="Content-Script-Type" content="text/javascript">
87
+<title>NumberString</title>
88
+</head>
89
+<body>
90
+<h1>NumberString</h1>
91
+<p>半角数字を漢数字に変換</p>
92
+<form id="FORMNUMBERSTRING" name="FORMNUMBERSTRING" action="#">
93
+<p>入力: <input id="TEXTSOURCE" name="TEXTSOURCE" type="text" size="40" value="123,456,789,000"></p>
94
+<p><input type="button" value="↓変換" onClick="NumberString(document.FORMNUMBERSTRING.TEXTSOURCE.value)"></p>
95
+<p>出力: <input id="TEXTDESTINATION" name="TEXTDESTINATION" type="text" size="40" value=""></p>
96
+</form>
97
+<script type="text/javascript">
98
+<!--
99
+function NumberString(src){
100
+ var dictionary = {
101
+ '0':'〇', '1':'一', '2':'二', '3':'三', '4':'四',
102
+ '5':'五', '6':'六', '7':'七', '8':'八', '9':'九',
103
+ ',':'、'
104
+ };
105
+
106
+ for( var key in dictionary ){
107
+ src = src.replace( RegExp(key,'g'), dictionary[ key ] );
108
+ }
109
+
110
+ document.FORMNUMBERSTRING.TEXTDESTINATION.value = src;
111
+}
112
+// -->
113
+</script>
114
+</body>
115
+</html>
116
+```
117
+
118
+# 数字の頭にゼロを付けて桁を揃える
119
+- [packZero.html](packZero.html)
120
+- [文字列繰り返しベンチマーク take 3](http://d.hatena.ne.jp/moriyoshi/20090130/1233335471) @ [muddy brown thang](http://d.hatena.ne.jp/moriyoshi/)
121
+```html
122
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
123
+<html lang="ja">
124
+<head>
125
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
126
+ <meta http-equiv="Content-Script-Type" content="text/javascript">
127
+ <title>ゼロ詰め</title>
128
+</head>
129
+<body>
130
+<script type="text/javascript">
131
+<!--
132
+function packZero( x, n )
133
+{
134
+ var n1 = (""+x).length;
135
+ var n0 = ( n > n1 ) ? n : n1 ;
136
+ var z = "0";
137
+ var d = "";
138
+ while( n > 0 ){
139
+ if ( n & 1 ){
140
+ d += z;
141
+ }
142
+ z += z;
143
+ n >>= 1;
144
+ }
145
+ return ( d + x ).slice( - n0 );
146
+}
147
+// -->
148
+</script>
149
+
150
+<h1>ゼロ詰め</h1>
151
+
152
+<ul>
153
+<li><p>数値の頭にゼロを付けて桁数をそろえます。</p></li>
154
+<li><p></p></li>
155
+</ul>
156
+
157
+<form name="formPackZero" action="#">
158
+<table summary="Pack Zero Form">
159
+<tr><th>元データ</th><td><input type="text" name="txtX" size="15" value="123"></td></tr>
160
+<tr><th>桁数</th><td><input type="text" name="txtN" size="15" value="5"></td></tr>
161
+<tr><td align="center" colspan="2">
162
+<input type="button" name="btnPackZero" value="ゼロ詰め" onClick="javascript: document.formPackZero.txtDst.value = packZero( document.formPackZero.txtX.value, document.formPackZero.txtN.value )">
163
+</td></tr>
164
+<tr><th>結果</th><td><input type="text" name="txtDst" size="15" value=""></td></tr>
165
+</table>
166
+</form>
167
+
168
+<h2>参考</h2>
169
+<ul>
170
+<li><p><a href="http://d.hatena.ne.jp/moriyoshi/20090130/1233335471">文字列繰り返しベンチマーク take 3</a></p></li>
171
+</ul>
172
+
173
+</body>
174
+</html>
175
+```
176
+
177
+# Selenium による Web アプリの自動テスト
178
+- [[Selenium による Web アプリの自動テスト|JavaScript/Selenium]]へ移動。
179
+
180
+# 画像へのリンクにサムネイルを追加
181
+- [Links2Images](http://userjs.org/scripts/general/enhancements/links-2-images)を改変。
182
+- すでにサムネイルが表示されている場合はスキップ。
183
+- フルサイズ表示から縦100pxへ制限。
184
+- 元のinnerHTMLは残す。
185
+- 画像を別のタブに出す。
186
+- [links-2-images.user.js](links-2-images.user.js)
187
+```javascript
188
+// ==UserScript==
189
+// @name Links2Images
190
+// @author Tomasz Wojcikowski
191
+// @description Replaces links to images with the actual images.
192
+// @ujs:category general: enhancements
193
+// @ujs:published 2005-05-28 12:47
194
+// @ujs:modified 2005-09-19 09:19
195
+// @ujs:documentation http://userjs.org/scripts/general/enhancements/links-2-images
196
+// @ujs:download http://userjs.org/scripts/download/general/enhancements/links-2-images.user.js
197
+// @ujs:download.gm http://userjs.org/scripts/download/general/enhancements/links-2-images.user.js
198
+// @exclude http://*.2chan.net/b/*
199
+// ==/UserScript==
200
+
201
+/*
202
+ * Copyright (c) 2005 by Tomasz Wojcikowski
203
+ * Modified by take-ash
204
+ *
205
+ * This program is free software; you can redistribute it and/or modify
206
+ * it under the terms of the GNU General Public License as published by
207
+ * the Free Software Foundation; either version 2 of the License.
208
+ *
209
+ * This program is distributed in the hope that it will be useful, but
210
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
211
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
212
+ * General Public License for more details.
213
+ *
214
+ * You should have received a copy of the GNU General Public License
215
+ * along with this program; if not, write to the Free Software
216
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
217
+ * USA
218
+ */
219
+
220
+(function(){
221
+ var links = document.getElementsByTagName( "a" );
222
+ for ( var i = links.length; --i >= 0; ){
223
+ // search for all links with href to image file
224
+ if ( links[i].href
225
+ && links[i].href.match( /^.*\.(jpe?g|png|bmp|gif)$/i )
226
+ && links[i].getElementsByTagName( "img" ).length == 0
227
+ ){
228
+ var img = document.createElement( "img" );
229
+ img.setAttribute( "src", links[i].href );
230
+ img.setAttribute( "class", "image-link" );
231
+ img.setAttribute( "alt", links[i].getAttribute( "title" ) ) ;
232
+ img.setAttribute( "height", 100 ) ;
233
+ links[i].appendChild( img );
234
+ links[i].setAttribute( "target", "_blank" );
235
+ }
236
+ }
237
+})();
238
+```
239
+
240
+# ボタンを押したときに文字列と画像を変更する
241
+- [changePic.html](changePic.html)
242
+```html
243
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
244
+<html lang="ja">
245
+<head>
246
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
247
+ <meta http-equiv="Content-Script-Type" content="text/javascript">
248
+ <title>change String and Pic by buttons</title>
249
+</head>
250
+<body onLoad="init()">
251
+<SCRIPT type="text/javascript">
252
+<!--
253
+var elmPicImg;
254
+var elmPicName;
255
+
256
+function init(){
257
+ elmPicImg = document.getElementById("PicImg");
258
+ elmPicName = document.getElementById("PicName");
259
+}
260
+
261
+function showImg1(){
262
+ elmPicImg.src = "http://www.takeash.net/Etc/BABY.GIF";
263
+ elmPicName.innerHTML = "Baby";
264
+}
265
+
266
+function showImg2(){
267
+ elmPicImg.src = "http://www.takeash.net/Etc/MyMelo.png";
268
+ elmPicName.innerHTML = "MyMelody";
269
+}
270
+
271
+function showImg3(){
272
+ elmPicImg.src = "http://www.takeash.net/Etc/Usamimi.png";
273
+ elmPicName.innerHTML = "Usamimi";
274
+}
275
+
276
+-->
277
+</SCRIPT>
278
+<h1>change String and Pic by buttons</h1>
279
+
280
+<form name="formSwapImg" action="#">
281
+<input type="button" onclick="showImg1()" value="Baby">
282
+<input type="button" onclick="showImg2()" value="MyMelody">
283
+<input type="button" onclick="showImg3()" value="Usamimi">
284
+</form>
285
+
286
+<div id="PicName">Baby</div>
287
+<div><img src="http://www.takeash.net/Etc/BABY.GIF" id="PicImg" alt="changing image" width="256" height="256"></div>
288
+
289
+</body>
290
+</html>
291
+```
292
+
293
+# 離散的な配列のソート
294
+- sortによって元のインデックスは破壊される。
295
+- lengthプロパティは「最大の添え字+1」で元のまま。
296
+
297
+## ソース
298
+- [sortDispersedArray.zip](sortDispersedArray.zip)
299
+```javascript
300
+// 離散的な配列のソート
301
+// sortによって元のインデックスは破壊される。
302
+// lengthプロパティは「最大の添え字+1」で元のまま。
303
+
304
+function testArray(){
305
+ var ret = 'Browser: ' + navigator.userAgent + '\n';
306
+ var a = [];
307
+ a[2] = { 'index':2, 'value':200, 'name':'std' };
308
+ a[5] = { 'index':5, 'value':400, 'name':'high' };
309
+ a[9] = { 'index':9, 'value':100, 'name':'low' };
310
+ ret += '\nソート前 / length: ' + a.length + '\n' + showObj( a );
311
+ a.sort( function(a,b){ return b['value'] - a['value']; } );
312
+ ret += '\nソート後 / length: ' + a.length + '\n' + showObj( a );
313
+ return ret;
314
+}
315
+
316
+function showObj( obj, indent ){
317
+ indent = indent || 0;
318
+ var ret = '';
319
+ for( var p in obj ){
320
+ if ( typeof( obj[p] ) == 'object' ){
321
+ ret += repeatStr( '\t', indent ) + p + ':\n' + showObj( obj[p], indent + 1 );
322
+ } else {
323
+ ret += repeatStr( '\t', indent ) + p + ':\t' + obj[p] + '\n';
324
+ }
325
+ }
326
+ return ret;
327
+}
328
+
329
+function repeatStr( s, n )
330
+{
331
+ var ret = '';
332
+ while( n > 0 ){
333
+ if ( n & 1 ){
334
+ ret += s;
335
+ }
336
+ s += s;
337
+ n >>= 1;
338
+ }
339
+ return ret;
340
+}
341
+// EOF
342
+```
343
+
344
+## Opera 11.50
345
+```
346
+Browser: Opera/9.80 (Windows NT 6.1; U; ja) Presto/2.9.168 Version/11.50
347
+
348
+ソート前 / length: 10
349
+2:
350
+ index: 2
351
+ value: 200
352
+ name: std
353
+5:
354
+ index: 5
355
+ value: 400
356
+ name: high
357
+9:
358
+ index: 9
359
+ value: 100
360
+ name: low
361
+
362
+ソート後 / length: 10
363
+0:
364
+ index: 5
365
+ value: 400
366
+ name: high
367
+1:
368
+ index: 2
369
+ value: 200
370
+ name: std
371
+2:
372
+ index: 9
373
+ value: 100
374
+ name: low
375
+```
376
+
377
+## Firefox 5.0.1
378
+```
379
+Browser: Mozilla/5.0 (Windows NT 6.1; rv:5.0.1) Gecko/20100101 Firefox/5.0.1
380
+
381
+ソート前 / length: 10
382
+2:
383
+ index: 2
384
+ value: 200
385
+ name: std
386
+5:
387
+ index: 5
388
+ value: 400
389
+ name: high
390
+9:
391
+ index: 9
392
+ value: 100
393
+ name: low
394
+
395
+ソート後 / length: 10
396
+0:
397
+ index: 5
398
+ value: 400
399
+ name: high
400
+1:
401
+ index: 2
402
+ value: 200
403
+ name: std
404
+2:
405
+ index: 9
406
+ value: 100
407
+ name: low
408
+```
409
+
410
+# Greasemonkey
411
+- [Greasemonkey スクリプト](http://jp.opera.com/support/tutorials/userjs/examples/#greasemonkey)
412
+
413
+- [Opera のユーザーJavaScript は「.js」か「.user.js」かで実行されるタイミングが違う](http://orera.g.hatena.ne.jp/miya2000/20070314/p0)
414
+
415
+- [Pukipochi](http://nanokawa.net/archives/individual/2006/0223213537.php) - PukiWikiのボタンを常にページの右下に表示<br />
416
+メニューバーもフローティング化<br />
417
+「整形済みテキスト」で右端がはみ出してるとメニューバーの下に body がもぐりこんじゃうなぁ。
418
+```
419
+var menub = document.getElementById('menubar');
420
+menub.style.position = 'fixed';
421
+menub.style.top = '10em';
422
+menub.style.left = '2em';
423
+menub.style.padding = '2px 3px';
424
+menub.style.borderWidth = '1px 0 0 1px';
425
+menub.style.borderColor = '#ccc';
426
+menub.style.borderStyle = 'solid';
427
+menub.style.backgroundColor = '#eee';
428
+```
429
+
430
+- [Mouseover DOM Inspector](http://slayeroffice.com/tools/modi/v2.0/modi_help.html)
JavaScript/Selenium.md
... ...
@@ -0,0 +1,181 @@
1
+[[_TOC_]]
2
+
3
+# その1
4
+## 概要
5
+- [Selenium](http://seleniumhq.org/)([日本語](http://oss.infoscience.co.jp/seleniumhq/))で Web アプリのテストを自動化する。ここでは上記の「半角数字を漢数字に変換」をテストする。
6
+- テストする値はローカルの設定ファイルから読み込む。(D:\_temp\TestNumStr.json)
7
+- テスト結果はローカルのファイルに保存する。(D:\_temp\Result.txt)
8
+- Firefox 3.6.3にて動作確認。(2010/04/16, Selenium IDE 1.0.6)
9
+
10
+- [SeleniumでJavaScriptを使う方法いろいろ(変数・関数などの利用)](http://colo-ri.jp/develop/2008/04/seleniumjavascript.html)
11
+- [Selenium IDE で無限ループ - ヽ( ・∀・)ノくまくまー - s21g](http://blog.s21g.com/articles/1619)
12
+
13
+## ダウンロード
14
+- [TestNumStr.zip](TestNumStr.zip)
15
+- 「D:\_temp\」に展開したときに動作するように作成しています。別の場所に配置する場合は適宜書き換えて下さい。
16
+- LocalFileIO.js, isGood.js は Selenium の「オプション - 設定」から「Selenium IDE拡張スクリプトのパス」に登録して下さい。
17
+
18
+## Selenium テストケース
19
+- [testNumStr.html](testNumStr.html)
20
+
21
+## テスト値設定ファイル TestNumStr.json
22
+```javascript
23
+{
24
+ 'BaseURL': 'file:///D:/_temp/NumberString.html',
25
+ 'PageTitle': 'NumberString',
26
+
27
+ 'input1': '123456789',
28
+ 'output1': '一二三四五六七八九',
29
+
30
+ 'input2': '999999',
31
+ 'output2': '九九九九九九',
32
+
33
+ 'input3': '987654321',
34
+ 'output3': '九八七六五四三二一'
35
+}
36
+```
37
+
38
+## ユーザー拡張スクリプト LocalFileIO.js
39
+<!---- [[File I/O - MDC:https://developer.mozilla.org/ja/Code_snippets/File_I//O]]-->
40
+- [File I/O - MDN](https://developer.mozilla.org/index.php?title=Ja/Code_snippets/File_I%2F%2FO)
41
+- [CMLog :: Firefoxのjavascriptでローカルファイルにアクセスする方法まとめ](http://cyprus.ex.nii.ac.jp/~kameda/blog/KMKM/KMKM0711030805.htm)
42
+- [Selenium IDEで1つ1つのテストの処理時間を計測 (悪戦苦闘) - bonlife](http://d.hatena.ne.jp/bonlife/20080213/1202913177)
43
+```javascript
44
+ // ローカルファイルの読み書き
45
+ // Firefox専用
46
+ // http://cyprus.ex.nii.ac.jp/~kameda/blog/KMKM/KMKM0711030805.htm
47
+ // modified by TakeAsh, 2010/04/16
48
+
49
+ function readFromFile( filePath ){
50
+ var data = "";
51
+ try {
52
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
53
+ var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
54
+ file.initWithPath(filePath);
55
+ var fInStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
56
+ fInStream.init(file, -1, 0, 0);
57
+ var charset = "UTF-8";
58
+ const replacementChar = Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
59
+ var cvtInStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].createInstance(Components.interfaces.nsIConverterInputStream);
60
+ cvtInStream.init(fInStream, charset, 1024, replacementChar);
61
+ var str = {};
62
+ while ( cvtInStream.readString(4096, str) ){
63
+ data += str.value;
64
+ }
65
+ cvtInStream.close();
66
+ } catch(e){
67
+ throw e;
68
+ }
69
+ return data;
70
+ }
71
+
72
+ function writeToFile( filePath, content, append ){
73
+ try {
74
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
75
+ var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
76
+ file.initWithPath(filePath);
77
+ if (!file.exists()){
78
+ file.create(0, 0666);
79
+ }
80
+ var fOutStream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
81
+ // https://developer.mozilla.org/ja/Code_snippets/File_I//O
82
+ // 0x02:PR_WRONLY 0x10:PR_APPEND 0x20:PR_TRUNCATE
83
+ var flag = 0x02 | ( (append) ? 0x10 : 0x20);
84
+ fOutStream.init(file, flag, 0666, null);
85
+ var charset = "UTF-8";
86
+ var cvtOutStream = Components.classes["\@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
87
+ cvtOutStream.init(fOutStream, charset, 0, 0x0000);
88
+ cvtOutStream.writeString(content);
89
+ cvtOutStream.close();
90
+ } catch(e){
91
+ throw e;
92
+ }
93
+ }
94
+
95
+ // EOF
96
+```
97
+
98
+## ユーザー拡張スクリプト isGood.js
99
+```javascript
100
+ function isGood( cond ){
101
+ return ( cond ) ? 'Good' : 'NG';
102
+ }
103
+```
104
+
105
+# その2
106
+## 概要
107
+- [Selenium](http://seleniumhq.org/)([日本語](http://oss.infoscience.co.jp/seleniumhq/))で Web アプリのテストを自動化する。ここではテスト項目の繰り返し、ドロップダウンリスト、チェックボックスをテストする。
108
+- テストする値はローカルの設定ファイルから読み込む。(D:\_temp\testSelenium.json)
109
+- テスト結果はローカルのファイルに保存する。(D:\_temp\resultSelenium.log)
110
+- Firefox 3.6.3にて動作確認。(2010/04/26, Selenium IDE 1.0.6)
111
+
112
+## ダウンロード
113
+- [SeleniumTest.zip](SeleniumTest.zip)
114
+- 「D:\_temp\」に展開したときに動作するように作成しています。別の場所に配置する場合は適宜書き換えて下さい。
115
+- LocalFileIO.js, isGood.js は Selenium の「オプション - 設定」から「Selenium IDE拡張スクリプトのパス」に登録して下さい。
116
+
117
+## Selenium テストケース
118
+- [testSelenium.html](testSelenium.html)
119
+- Headerの出力はループさせなくてもjoin('\t')でできるが、出力結果が複数箇所の場合に取り込んだ結果をループでまとめて出力させたいのでその雛形としてループを使っている。
120
+
121
+## テスト値設定ファイル testSelenium.json
122
+```javascript
123
+{
124
+ 'BaseURL': 'file:///D:/_temp/SeleniumTest.html',
125
+ 'PageTitle': 'Seleniumテストサンプル',
126
+
127
+ 'JobCondition': [
128
+ // Src1 Operation Src2 chkKanji Result
129
+ [ 3, '+', 4, 'off', 7, ],
130
+ [ 3, '+', 4, 'on', '七', ],
131
+ [ 3, '−', 4, 'off', -1, ],
132
+ [ 3, '−', 4, 'on', '−一', ],
133
+ [ 3, '×', 4, 'off', 12, ],
134
+ [ 3, '×', 4, 'on', '一二', ],
135
+ [ 3, '÷', 4, 'off', 0.75, ],
136
+ [ 3, '÷', 4, 'on', '〇.七五', ],
137
+ [ 1, '+', 0, 'off', 1, ],
138
+ [ 1, '+', 0, 'on', '一', ],
139
+ [ 1, '−', 0, 'off', 1, ],
140
+ [ 1, '−', 0, 'on', '一', ],
141
+ [ 1, '×', 0, 'off', 0, ],
142
+ [ 1, '×', 0, 'on', '〇', ],
143
+ [ 1, '÷', 0, 'off', 'Infinity', ],
144
+ [ 1, '÷', 0, 'on', '無限大', ],
145
+ [ 1, '+', 'a', 'off', 'NaN', ],
146
+ [ 1, '+', 'a', 'on', '非数値', ],
147
+ ],
148
+}
149
+```
150
+
151
+## テスト結果 resultSelenium.log
152
+```
153
+PageTitle: Seleniumテストサンプル
154
+BaseURL: file:///D:/_temp/SeleniumTest.html
155
+TestDate: Tue Apr 27 2010 00:51:25 GMT+0900
156
+
157
+Src1 Op Src2 Kanji Correct Actual Result
158
+3 + 4 off 7 7 Good
159
+3 + 4 on 七 七 Good
160
+3 − 4 off -1 -1 Good
161
+3 − 4 on −一 −一 Good
162
+3 × 4 off 12 12 Good
163
+3 × 4 on 一二 一二 Good
164
+3 ÷ 4 off 0.75 0.75 Good
165
+3 ÷ 4 on 〇.七五 〇.七五 Good
166
+1 + 0 off 1 1 Good
167
+1 + 0 on 一 一 Good
168
+1 − 0 off 1 1 Good
169
+1 − 0 on 一 一 Good
170
+1 × 0 off 0 0 Good
171
+1 × 0 on 〇 〇 Good
172
+1 ÷ 0 off Infinity Infinity Good
173
+1 ÷ 0 on 無限大 無限大 Good
174
+1 + a off NaN NaN Good
175
+1 + a on 非数値 非数値 Good
176
+```
177
+
178
+# リンク
179
+- [CMLog :: Firefoxのjavascriptでローカルファイルにアクセスする方法まとめ](http://cyprus.ex.nii.ac.jp/~kameda/blog/KMKM/KMKM0711030805.htm)
180
+- [JavaScript++かも日記: 【セキュリティ】ローカルファイルのセキュリティ警告を出さないおまじない](http://jsgt.org/mt/archives/01/001948.html)
181
+- [WebDriverの採用で生まれ変わったOSSのブラウザテストツール「Selenium 2」入門:CodeZine](http://codezine.jp/article/corner/502)
JavaScript/Twitter_TimeLineBrowser.md
... ...
@@ -0,0 +1,343 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- Twitter API を利用してタイムラインを表示します。
5
+- 「Profile/StatusId」の横のテキストボックスに「https://twitter.com/#!/twj/status/90937652819398656」のようなリンクをペーストして同ボタンをクリックすると、そのツイート以前のツイートを表示します。
6
+- 約200ツイート単位または一週間、二週間、一ヶ月単位で切替えられます。
7
+- 前後はいずれも概算です。
8
+- 古いツイートは表示されないようです。(max_idの制限?)
9
+- Opera, Firefox, Chrome で動作確認。
10
+- IE は table タグの innerHTML を書き換えられないようなので動きません。([仕様です](http://support.microsoft.com/kb/239832/ja))
11
+- リンクは自前で判別せずに[Tweet Entities](https://dev.twitter.com/docs/tweet-entities)を使うようにしてるけど、結構リンクにならないことが多いな。
12
+- 鍵付きのアカウントのツイートは読み取れません。
13
+- URLの表示を短縮しないオプションを追加。(2011/12/10)
14
+
15
+# 動作デモ
16
+- http://www.takeash.net/Etc/TTLBrowser.html
17
+
18
+# ソース
19
+- [TTLBrowser.zip](TTLBrowser.zip)
20
+
21
+## TTLBrowser.html
22
+```html
23
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
24
+<html lang="ja">
25
+<head>
26
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
27
+<meta http-equiv="Content-Script-Type" content="text/javascript">
28
+<meta http-equiv="Content-Style-Type" content="text/css">
29
+<link rel="stylesheet" type="text/css" href="http://www.takeash.net/take.css">
30
+<title>Twitter TimeLine Browser</title>
31
+</head>
32
+<body>
33
+<h1>Twitter TimeLine Browser</h1>
34
+<form name="form1" action="#">
35
+<div id="Control">
36
+<table>
37
+<tr>
38
+ <th><button type="button" onclick="javascript:form1.tbSpecifiedId.value.match(/([^\/]+)(?:\/\w+\/(\d+))?$/); form1.tbUserName.value=RegExp.$1; browseTL(form1.tbUserName.value, RegExp.$2, form1.cbTruncate.checked);">Profile/StatusId</button></th>
39
+ <td><input type="text" id="tbSpecifiedId" name="tbSpecifiedId" value="" size="70"></td>
40
+</tr>
41
+<tr>
42
+ <th>UserName</th>
43
+ <td><input id="tbUserName" name="tbUserName" type="text" value="" size="70"></td>
44
+</tr>
45
+<tr><td colspan="2" align="center">
46
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, '', form1.cbTruncate.checked);">現在</button>
47
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnAfterId.value, form1.cbTruncate.checked);">後の200件</button>
48
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnAgoId.value, form1.cbTruncate.checked);">前の200件</button>
49
+</td></tr>
50
+<tr><td colspan="2" align="center">
51
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnOneMonthAfterId.value, form1.cbTruncate.checked);">一ヶ月後</button>
52
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnTwoWeeksAfterId.value, form1.cbTruncate.checked);">二週間後</button>
53
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnOneWeekAfterId.value, form1.cbTruncate.checked);">一週間後</button>
54
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnOneWeekAgoId.value, form1.cbTruncate.checked);">一週間前</button>
55
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnTwoWeeksAgoId.value, form1.cbTruncate.checked);">二週間前</button>
56
+ <button type="button" onclick="javascript:browseTL(form1.tbUserName.value, form1.hdnOneMonthAgoId.value, form1.cbTruncate.checked);">一ヶ月前</button>
57
+</td></tr>
58
+<tr><td colspan="2">
59
+ <input type="checkbox" id="cbTruncate" name="cbTruncate" checked> <label for="cbTruncate">URLの表示を短縮</label>
60
+</td></tr>
61
+</table>
62
+<input type="hidden" id="hdnAfterId" name="hdnAfterId" value="" size="30">
63
+<input type="hidden" id="hdnAgoId" name="hdnAgoId" value="" size="30">
64
+<input type="hidden" id="hdnOneMonthAfterId" name="hdnOneMonthAfterId" value="" size="30">
65
+<input type="hidden" id="hdnTwoWeeksAfterId" name="hdnTwoWeeksAfterId" value="" size="30">
66
+<input type="hidden" id="hdnOneWeekAfterId" name="hdnOneWeekAfterId" value="" size="30">
67
+<input type="hidden" id="hdnOneWeekAgoId" name="hdnOneWeekAgoId" value="" size="30">
68
+<input type="hidden" id="hdnTwoWeeksAgoId" name="hdnTwoWeeskAgoId" value="" size="30">
69
+<input type="hidden" id="hdnOneMonthAgoId" name="hdnOneMonthAgoId" value="" size="30">
70
+</div>
71
+<div id="Result">
72
+<p id="ResultUserName"></p>
73
+<table id="ResultTable">
74
+</table>
75
+</div>
76
+</form>
77
+<div id="Caution">
78
+<h2>注意</h2>
79
+<ul>
80
+<li>Twitter API を利用してタイムラインを表示します。</li>
81
+<li>「Profile/StatusId」の横のテキストボックスに「<a href="https://twitter.com/#!/twj/status/90937652819398656">https://twitter.com/#!/twj/status/90937652819398656</a>」のようなリンクをペーストして同ボタンをクリックすると、そのツイート以前のツイートを表示します。</li>
82
+<li>約200ツイート単位または一週間、二週間、一ヶ月単位で切替えられます。</li>
83
+<li>前後はいずれも概算です。</li>
84
+<li>古いツイートは表示されないようです。(max_idの制限?)</li>
85
+<li>Opera, Firefox, Chrome で動作確認。</li>
86
+<li>IE は table タグの innerHTML を書き換えられないようなので動きません。(<a href="http://support.microsoft.com/kb/239832/ja">仕様です</a>)</li>
87
+<li>リンクは自前で判別せずに<a href="https://dev.twitter.com/docs/tweet-entities">Tweet Entities</a>を使うようにしてるけど、結構リンクにならないことが多いな。</li>
88
+</ul>
89
+</div>
90
+<div id="Link">
91
+<h2>Link</h2>
92
+<ul>
93
+<li><a href="http://www.takeash.net/wiki/?JavaScript/Twitter_TimeLineBrowser">Twitter TimeLine Browser</a></li>
94
+<li><a href="https://github.com/remy/twitterlib">remy Twitter Lib</a></li>
95
+<li><a href="http://code.google.com/p/twitterjs/">remy twitterjs</a></li>
96
+<li><a href="http://watcher.moe-nifty.com/memo/2007/04/twitter_api.html">Twitter API 仕様書 (勝手に日本語訳シリーズ)</a></li>
97
+<li><a href="https://dev.twitter.com/docs/api">REST API Resources</a></li>
98
+<li><a href="https://dev.twitter.com/docs/api/1/get/statuses/user_timeline">GET statuses/user_timeline</a></li>
99
+<li><a href="https://dev.twitter.com/docs/tweet-entities">Tweet Entities</a></li>
100
+</ul>
101
+</div>
102
+<script type="text/javascript" src="twitterlib_tak.js"></script>
103
+<script type="text/javascript" src="TTLBrowser.js"></script>
104
+</body>
105
+</html>
106
+```
107
+
108
+## TTLBrowser.js
109
+```javascript
110
+function browseTL(username, maxid, truncate){
111
+ var twhost = 'https://twitter.com/#!/';
112
+ var options = {};
113
+ options.enableLinks = true;
114
+ options.truncateLinks = truncate;
115
+ // options.limit = 50;
116
+ options.target_username = document.getElementById('ResultUserName');
117
+ options.target_table = document.getElementById('ResultTable');
118
+ options.template_username = '<a href="' + twhost + '%user_screen_name%" target="_blank">'
119
+ + '<img width="48" height="48" src="%user_profile_image_url%"></a> '
120
+ + '<a href="'+twhost+'%user_screen_name%" target="_blank">%user_name% '
121
+ + '(%user_screen_name%)</a>';
122
+ options.template_head = '<tr><th>#</th><th>日時</th><th>本文</th><th>返信</th></tr>';
123
+ options.template_table = '<tr><td align="center"><button type="button" '
124
+ + 'onclick="javascript:browseTL(form1.tbUserName.value, \'%id_str%\');">%index%</button></td>'
125
+ + '<td><a href="' + twhost + '%user_screen_name%/status/%id_str%" target="_blank">%time%</a></td>'
126
+ + '<td>%text%</td><td align="center">%reply%</td>'
127
+ + '</tr>';
128
+ options.maxid = (maxid && maxid.match(/^\d+$/)) ? maxid : undefined ;
129
+ options.tags = {};
130
+ options.tags.afterid = document.getElementById('hdnAfterId');
131
+ options.tags.agoid = document.getElementById('hdnAgoId');
132
+ options.tags.onemonthafterid = document.getElementById('hdnOneMonthAfterId');
133
+ options.tags.twoweeksafterid = document.getElementById('hdnTwoWeeksAfterId');
134
+ options.tags.oneweekafterid = document.getElementById('hdnOneWeekAfterId');
135
+ options.tags.oneweekagoid = document.getElementById('hdnOneWeekAgoId');
136
+ options.tags.twoweeksagoid = document.getElementById('hdnTwoWeeksAgoId');
137
+ options.tags.onemonthagoid = document.getElementById('hdnOneMonthAgoId');
138
+ twitterlib_tak.timeline( username, options, function(tweets, options){
139
+ var html = [];
140
+ html.push( options.template_head );
141
+ for (var i = 0; i < tweets.length; ++i){
142
+ tweets[i].time = twitterlib_tak.time.localtime( tweets[i].created_at );
143
+ tweets[i].reply = tweets[i].in_reply_to_status_id_str
144
+ ? '<a href="' + twhost + tweets[i].in_reply_to_screen_name + '/status/'
145
+ + tweets[i].in_reply_to_status_id_str + '" target="_blank">元</a> '
146
+ + '<button type="button" onclick="javascript:form1.tbUserName.value=\''
147
+ + tweets[i].in_reply_to_screen_name + '\'; browseTL(\''
148
+ + tweets[i].in_reply_to_screen_name + '\', \''
149
+ + tweets[i].in_reply_to_status_id_str + '\');">表示</button>'
150
+ : '';
151
+ tweets[i].index = i + 1;
152
+ for (var key in tweets[i].user) {
153
+ tweets[i]['user_' + key] = tweets[i].user[key];
154
+ }
155
+ if (options.template_table) {
156
+ html.push( options.template_table.replace(/%([a-z_\-\.]*)%/ig, function (m, l){
157
+ var r = tweets[i][l] + "" || "";
158
+ if (l == 'text') {
159
+ r = twitterlib_tak.expandLinks(tweets[i], options.truncateLinks);
160
+ r = r.replace( /\n/g, "<br>\n" );
161
+ }
162
+ return r;
163
+ }));
164
+ } else {
165
+ html.push(twitterlib_tak.render(tweets[i]));
166
+ }
167
+ }
168
+ options.target_table.innerHTML = html.join('');
169
+ if ( tweets.length > 0 ){
170
+ options.target_username.innerHTML =
171
+ options.template_username.replace(/%([a-z_\-\.]*)%/ig, function (m, l){
172
+ var r = tweets[0][l] + "" || "";
173
+ if (l == 'text') r = twitterlib_tak.expandLinks(tweets[0], options.truncateLinks);
174
+ return r;
175
+ });
176
+ if ( tweets.length > 1 ){
177
+ var newest_id = parseInt( tweets[0].id_str );
178
+ var oldest_id = parseInt( tweets[tweets.length - 1].id_str );
179
+ var newest_sec = new Date( tweets[0].created_at ).getTime();
180
+ var oldest_sec = new Date( tweets[tweets.length - 1].created_at ).getTime();
181
+ var diff_id = newest_id - oldest_id;
182
+ var postrate = diff_id / (( newest_sec - oldest_sec) / (24 * 3600 * 1000));
183
+ options.tags.afterid.value = newest_id + diff_id;
184
+ options.tags.agoid.value = oldest_id;
185
+ options.tags.onemonthafterid.value = newest_id + postrate * 30;
186
+ options.tags.twoweeksafterid.value = newest_id + postrate * 14;
187
+ options.tags.oneweekafterid.value = newest_id + postrate * 7;
188
+ options.tags.oneweekagoid.value = newest_id - postrate * 7;
189
+ options.tags.twoweeksagoid.value = newest_id - postrate * 14;
190
+ options.tags.onemonthagoid.value = newest_id - postrate * 30;
191
+ }
192
+ }
193
+ });
194
+}
195
+```
196
+
197
+## twitterlib_tak.js
198
+- [remy Twitter Lib](https://github.com/remy/twitterlib)との差分
199
+
200
+```
201
+--- RemySharp\twitterlib.js 2011-10-31 10:31:23.444145000 +0900
202
++++ twitterlib_tak.js 2011-12-08 21:22:34.251240700 +0900
203
+@@ -1,5 +1,7 @@
204
+ // twitterlib.js (c) 2011 Remy Sharp
205
+ // Licensed under the terms of the MIT license.
206
++// Original: https://github.com/remy/twitterlib
207
++// Modified by TakeAsh
208
+ (function (twitterlib, container) {
209
+ var guid = +new Date,
210
+ window = this,
211
+@@ -13,11 +15,11 @@
212
+ '&gt;': '>'
213
+ },
214
+ URLS = {
215
+- search: 'http://search.twitter.com/search.json?q=%search%&page=%page|1%&rpp=%limit|100%&since_id=%since|remove%&result_type=recent', // TODO allow user to change result_type
216
+- timeline: 'http://api.twitter.com/1/statuses/user_timeline.json?screen_name=%user%&count=%limit|200%&page=%page|1%&since_id=%since|remove%include_rts=%rts|false%&include_entities=true',
217
+- list: 'http://api.twitter.com/1/%user%/lists/%list%/statuses.json?page=%page|1%&per_page=%limit|200%&since_id=%since|remove%&include_entities=true&include_rts=%rts|false%',
218
+- favs: 'http://api.twitter.com/1/favorites/%user%.json?page=%page|1%include_entities=true&skip_status=true',
219
+- retweets: 'http://api.twitter.com/1/statuses/retweeted_by_user.json?screen_name=%user%&count=%limit|200%&since_id=%since|remove%&page=%page|1%'
220
++ search: 'https://search.twitter.com/search.json?q=%search%&page=%page|1%&rpp=%limit|100%&since_id=%since|remove%&result_type=recent', // TODO allow user to change result_type
221
++ timeline: 'https://api.twitter.com/1/statuses/user_timeline.json?id=%user%&count=%limit|200%&page=%page|1%&since_id=%since|remove%include_rts=%rts|false%&max_id=%maxid|remove%&include_entities=true',
222
++ list: 'https://api.twitter.com/1/%user%/lists/%list%/statuses.json?page=%page|1%&per_page=%limit|200%&since_id=%since|remove%&include_entities=true&include_rts=%rts|false%',
223
++ favs: 'https://api.twitter.com/1/favorites/%user%.json?page=%page|1%include_entities=true&skip_status=true',
224
++ retweets: 'https://api.twitter.com/1/statuses/retweeted_by_user.json?id=%user%&count=%limit|200%&since_id=%since|remove%&page=%page|1%'
225
+ },
226
+ urls = URLS, // allows for resetting debugging
227
+ undefined,
228
+@@ -51,7 +53,7 @@
229
+ };
230
+ }();
231
+
232
+- var expandLinks = function (tweet) {
233
++ var expandLinks = function (tweet, truncateLinks) {
234
+ if (tweet === undefined) return '';
235
+
236
+ var text = tweet.text,
237
+@@ -60,14 +62,48 @@
238
+ // replace urls with expanded urls and let the ify shorten the link
239
+ if (tweet.entities.urls && tweet.entities.urls.length) {
240
+ for (i = 0; i < tweet.entities.urls.length; i++) {
241
+- if (tweet.entities.urls[i].expanded_url) text = text.replace(tweet.entities.urls[i].url, tweet.entities.urls[i].expanded_url); // /g ?
242
++ var link = tweet.entities.urls[i].expanded_url;
243
++ if ( link ) {
244
++ text = text.replace(tweet.entities.urls[i].url, '<a title="' + link + '" href="'+ link + '">'+((truncateLinks && link.length > 36) ? link.substr(0, 35) + '&hellip;' : link)+'</a>');
245
++ }
246
+ }
247
+ }
248
+
249
+ // replace media with url to actual image (or thing?)
250
+ if (tweet.entities.media && tweet.entities.media.length) {
251
+ for (i = 0; i < tweet.entities.media.length; i++) {
252
+- if (tweet.entities.media[i].media_url || tweet.entities.media[i].expanded_url) text = text.replace(tweet.entities.media[i].url, tweet.entities.media[i].media_url ? tweet.entities.media[i].media_url : tweet.entities.media[i].expanded_url); // /g ?
253
++ var imgurl = tweet.entities.media[i].media_url_https || tweet.entities.media[i].media_url || tweet.entities.media[i].expanded_url;
254
++ if ( imgurl ) {
255
++ text = text.replace(tweet.entities.media[i].url, '<a href="' + imgurl + '" title="' + imgurl + '" target="_blank">' + ((truncateLinks && imgurl.length > 36) ? imgurl.substr(0, 35) + '&hellip;' : imgurl) + '</a>' ); // /g ?
256
++ text += '\n<a href="' + imgurl + '" target="_blank"><img src="' + imgurl + '" width="' + tweet.entities.media[i].sizes.small.w + '" height="' + tweet.entities.media[i].sizes.small.h + '"></a>'
257
++ }
258
++ }
259
++ }
260
++
261
++ // replace user mentions with user link
262
++ if ( tweet.entities.user_mentions && tweet.entities.user_mentions.length ) {
263
++ tweet.entities.user_mentions.sort( function( a, b ){ return ( a.screen_name.length < b.screen_name.length ) ? 1 : -1 ; } );
264
++ for (i = 0; i < tweet.entities.user_mentions.length; i++) {
265
++ var screen_name = tweet.entities.user_mentions[i].screen_name;
266
++ var re = new RegExp( '@'+screen_name, 'gi' );
267
++ if ( screen_name ) text = text.replace( re, '@<a href="https://twitter.com/' + screen_name + '">' + screen_name + '</a>');
268
++ }
269
++ }
270
++
271
++ // replace hash tag with search link
272
++ if ( tweet.entities.hashtags && tweet.entities.hashtags.length ) {
273
++ //alert( tweet.entities.hashtags.length );
274
++ tweet.entities.hashtags.sort( function( a, b ){ return ( a.text.length < b.text.length ) ? 1 : -1 ; } );
275
++ for (i = 0; i < tweet.entities.hashtags.length; i++) {
276
++ var hashtext = tweet.entities.hashtags[i].text;
277
++ var re = new RegExp( "(#|#)" + hashtext, 'g' );
278
++ if ( hashtext ) {
279
++ //alert(hashtext);
280
++ if ( text.match( re ) ){
281
++ //alert(RegExp.$1 + "\n" + hashtext + "\n" + text);
282
++ }
283
++ text = text.replace( re, '$1<a href="https://search.twitter.com/search?q=%23' + encodeURIComponent(hashtext) + '">' + hashtext + '</a>');
284
++ }
285
+ }
286
+ }
287
+
288
+@@ -170,7 +206,10 @@
289
+ }
290
+
291
+ return r;
292
+- }
293
++ },
294
++ localtime: function(time_value){
295
++ return new Date( time_value ).toLocaleString();
296
++ }
297
+ };
298
+ }();
299
+
300
+@@ -318,7 +357,7 @@
301
+ html += tweet.user.screen_name + '" ';
302
+ html += 'title="' + tweet.user.name + '">' + tweet.user.screen_name + '</a></strong> ';
303
+ html += '<span class="entry-content">';
304
+- html += container[twitterlib].ify.clean(container[twitterlib].expandLinks(tweet));
305
++ html += container[twitterlib].expandLinks(tweet);
306
+ html += '</span> <span class="meta entry-meta"><a href="http://twitter.com/' + tweet.user.screen_name;
307
+ html += '/status/' + tweet.id_str + '" class="entry-date" rel="bookmark"><span class="published" title="';
308
+ html += container[twitterlib].time.datetime(tweet.created_at) + '">' + container[twitterlib].time.relative(tweet.created_at) + '</span></a>';
309
+@@ -590,4 +629,4 @@
310
+ container[twitterlib].custom('timeline');
311
+ container[twitterlib].custom('favs');
312
+ container[twitterlib].custom('retweets');
313
+-})('twitterlib', this);
314
++})('twitterlib_tak', this);
315
+```
316
+
317
+# リンク
318
+- [remy Twitter Lib](https://github.com/remy/twitterlib)
319
+- [remy twitterjs](http://code.google.com/p/twitterjs/)
320
+
321
+- [Twitter API 仕様書 (勝手に日本語訳シリーズ)](http://watcher.moe-nifty.com/memo/2007/04/twitter_api.html)
322
+
323
+- [API reference index — Twitter Developers](https://developer.twitter.com/en/docs/api-reference-index)
324
+ - [Entities](https://dev.twitter.com/overview/api/entities)
325
+ - [Upcoming changes to Tweets](https://dev.twitter.com/overview/api/upcoming-changes-to-tweets)
326
+ - [GET statuses/user_timeline](https://dev.twitter.com/docs/api/1/get/statuses/user_timeline)
327
+ - [API Status](https://dev.twitter.com/overview/status)
328
+ - [About Twitter Cards](https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards)
329
+ - [Card Validator](https://cards-dev.twitter.com/validator)
330
+
331
+- [@Anywhere](https://dev.twitter.com/docs/anywhere/welcome)
332
+- [Twitter ヘルプセンター - ブロードキャスト、その他オフラインメディアでのツイート利用に関するガイドライン](https://support.twitter.com/articles/277644)
333
+
334
+- [自分のTwitterアカウントの設定](https://twitter.com/settings/)
335
+ - [アプリ連携](https://twitter.com/settings/applications)
336
+
337
+- [oauth - API needz authorized? - Google Project Hosting](http://code.google.com/p/oauth/)
338
+ - http://code.google.com/p/oauth/source/browse/#svn/code/javascript
339
+ - http://oauth.googlecode.com/svn/code/javascript/
340
+- [特集:ゼロから学ぶOAuth|gihyo.jp … 技術評論社](http://gihyo.jp/dev/feature/01/oauth)
341
+
342
+- [松下響の天輪返し](http://h2s.roheisen.net/blog/)
343
+ - [Twitter API開発者利用規則 和訳](http://h2s.roheisen.net/blog/archives/3362.html)
... ...
\ No newline at end of file
JavaScript/XMLMaker.md
... ...
@@ -0,0 +1,149 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- 雛形となる XML の所定の位置に、属性/子要素を追加した XML を出力する。
5
+- 位置指定は、XPath で行う。
6
+- Windows 版の Opera12, Firefox15, Chrome21 で動作確認。
7
+- あれ? DOMParser を用意しても IE だと既存オブジェクトにメソッド追加できないぞ?
8
+```
9
+オブジェクトでサポートされていないプロパティまたはメソッドです。
10
+```
11
+
12
+# 動作サンプル
13
+- [XMLMaker](http://www.takeash.net/Etc/XMLMaker.html)
14
+
15
+# ソース
16
+- [XMLMaker.zip](XMLMaker.zip)
17
+
18
+## XMLMaker.js
19
+```javascript
20
+// XMLMaker.js
21
+/** XMLの所定の位置に値を追加する */
22
+function makeXML(item1, item2, item3, item4) {
23
+ var xmlDoc = addExMethods((new DOMParser()).parseFromString(baseXML(), "text/xml"));
24
+
25
+ xmlDoc.setAttributeByXPath('//item1', 'name', item1);
26
+ xmlDoc.setAttributeByXPath('//item2/param[1]', 'opt', item2);
27
+ xmlDoc.addTextByXPath('//item3', item3);
28
+ xmlDoc.addTextByXPath('//item4/param[@name="01"]', item4);
29
+
30
+ var strXML = (new XMLSerializer()).serializeToString(xmlDoc);
31
+ strXML = htmlEscape(strXML);
32
+ /* インデントを可視化 */
33
+ strXML = strXML.replace(/([\r\n])(\s+)(&#x3c;)/g, function (whole, p1, p2, p3) {
34
+ return p1 + p2.replace(/\s/g, '&nbsp;') + p3;
35
+ }).replace(/[\r\n]+/g, '<br>');
36
+ var docNew = window.open().document;
37
+ docNew.open('text/html; charset="UTF-8"').write(strXML);
38
+ docNew.close();
39
+
40
+ /** XMLの雛形を戻す */
41
+ function baseXML() {
42
+ return [
43
+ '<?xml version="1.0" encoding="UTF-8"?>',
44
+ '<root>',
45
+ ' <item1></item1>',
46
+ ' <item2>',
47
+ ' <param name="00" />',
48
+ ' <param name="01" />',
49
+ ' </item2>',
50
+ ' <item3></item3>',
51
+ ' <item4>',
52
+ ' <param name="00" />',
53
+ ' <param name="01" />',
54
+ ' <param name="02" />',
55
+ ' </item4>',
56
+ '</root>',
57
+ ].join('\n');
58
+ }
59
+
60
+ /** XPath で指定した位置に属性や要素を追加するメソッドを追加 */
61
+ function addExMethods(obj) {
62
+ /** 属性の追加/上書き */
63
+ obj.setAttributeByXPath = function (xpath, attrName, text) {
64
+ var nodeTmp = this.evaluate(xpath, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
65
+ var nodeTarget = nodeTmp.singleNodeValue;
66
+ if (nodeTarget) {
67
+ nodeTarget.setAttribute(attrName, text);
68
+ } else {
69
+ prompt('XPath is not valid', xpath);
70
+ }
71
+ };
72
+ /** テキストノードを子要素として追加 */
73
+ obj.addTextByXPath = function (xpath, text) {
74
+ var nodeTmp = this.evaluate(xpath, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
75
+ var nodeTarget = nodeTmp.singleNodeValue;
76
+ if (nodeTarget) {
77
+ var nodeText = this.createTextNode(text);
78
+ nodeTarget.appendChild(nodeText);
79
+ } else {
80
+ prompt('XPath is not valid', xpath);
81
+ }
82
+ };
83
+ return obj;
84
+ }
85
+
86
+ /** HTMLタグを数値参照としてエスケープ */
87
+ function htmlEscape(s) {
88
+ return s.replace(/[&<>"']/g, function (m) {
89
+ return '&#x' + m.charCodeAt(0).toString(16) + ';'
90
+ });
91
+ }
92
+}
93
+
94
+// EOF
95
+```
96
+
97
+## XMLMaker.html
98
+```html
99
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
100
+<html lang="ja">
101
+<head>
102
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
103
+<meta http-equiv="Content-Script-Type" content="text/javascript">
104
+<meta http-equiv="Content-Style-Type" content="text/css">
105
+<link rel="stylesheet" type="text/css" href="http://www.takeash.net/take.css">
106
+<title>XML Maker</title>
107
+</head>
108
+<body>
109
+<h1>XML Maker</h1>
110
+<form id="form1" name="form1" action="#">
111
+<table summary="Automation Engine Settings" border="1">
112
+<tr><th>項目1</th><td><input id="item1" name="item1" type="text" value="項目1"></td></tr>
113
+<tr><th>項目2</th><td><input id="item2" name="item2" type="text" value="項目2"></td></tr>
114
+<tr><th>項目3</th><td><input id="item3" name="item3" type="text" value="項目3"></td></tr>
115
+<tr><th>項目4</th><td><input id="item4" name="item4" type="text" value="項目4"></td></tr>
116
+<tr><td colspan="2" align="center"><input type="button" value=" 作成 " onclick="makeXMLHelper();"></td></tr>
117
+</table>
118
+</form>
119
+<script type="text/javascript" src="XMLMaker.js"></script>
120
+<script type="text/javascript">
121
+<!--
122
+function makeXMLHelper(){
123
+ makeXML(
124
+ document.form1.item1.value,
125
+ document.form1.item2.value,
126
+ document.form1.item3.value,
127
+ document.form1.item4.value
128
+ );
129
+}
130
+// -->
131
+</script>
132
+</body>
133
+</html>
134
+```
135
+
136
+# リンク
137
+- [Introduction to using XPath in JavaScript - MDN](https://developer.mozilla.org/ja/docs/Introduction_to_using_XPath_in_JavaScript)
138
+
139
+- [erik's weblog » Blog Archive » DOMParser for IE and Safari](http://erik.eae.net/archives/2005/07/03/20.19.18/)
140
+
141
+- [404 Blog Not Found](http://blog.livedoor.jp/dankogai/)
142
+ - [javascript - typeof()を再発明する](http://blog.livedoor.jp/dankogai/archives/51755873.html)
143
+ - [javascript - Yet Another Base64 transcoder](http://blog.livedoor.jp/dankogai/archives/51067688.html)
144
+
145
+- [Object.defineProperty 関数 (JavaScript)](http://msdn.microsoft.com/ja-jp/library/dd548687.aspx)
146
+
147
+- [Save file Javascript with file name - Stack Overflow](http://stackoverflow.com/questions/7717851/save-file-javascript-with-file-name)
148
+
149
+- [Joel - Downloading generated files in Opera extensions](http://my.opera.com/spadija/blog/2012/07/11/downloading-generated-files-in-opera-extensions)
JavaScript/YouTube.md
... ...
@@ -0,0 +1,191 @@
1
+[[_TOC_]]
2
+
3
+# ビデオを直接ダウンロードするためのリンクを追加するスクリプト
4
+- [YoutubeDownloader_Tak.user2.zip](YoutubeDownloader_Tak.user2.zip)
5
+ - 2012/12/08 デザイン変更に追従(左のガイドの下にリンクが出るようにした)。
6
+ - 2012/09/21 signatureを追加するように変更。
7
+ - 2012/01/30 flashvarsを読み取るように変更。
8
+ - 2011/08/13 ytオブジェクトを使用するように変更。
9
+ - 2011/08/07 url_encoded_fmt_stream_map を元にリンクを作成するようにした。
10
+ - 2011/07/01 エラーの場合に理由を表示するようにした。
11
+ - 2011/01/01 fmt_url_map を参照するように変更。フォーマットの表示形式を変更。タイトル対応。
12
+ - 2010/11/06 YouTubeの仕様変更に対応。
13
+ - 2010/04/01 YouTubeの体裁変更に対応。
14
+ - 2009年4月頭に仕様が変わったようでこれまでのスクリプトが使えなくなったんで書き直し。<br />
15
+そのフォーマットが存在するかどうかは fmt_map 見て判断するようにしたけど、実際に存在してても fmt_map に含まれてないのはどうしたもんかな。(--;)
16
+```javascript
17
+// ==UserScript==
18
+// @name YoutubeDownloader_Tak
19
+// @namespace http://www.TakeAsh.net/
20
+// @description Add downloadable links in Youtube Page
21
+// @ujs:modified 2012-12-08 15:30
22
+// @include http://*.youtube.com/watch*
23
+// @include https://*.youtube.com/watch*
24
+// ==/UserScript==
25
+(function () {
26
+ var fmt_list = {};
27
+ var fmt_stream_map = [];
28
+ var flashvars = '';
29
+ var elmEmbeds = document.getElementsByTagName('embed');
30
+ for (var i = 0; i < elmEmbeds.length; ++i) {
31
+ if (flashvars = elmEmbeds[i].getAttribute('flashvars')) {
32
+ break;
33
+ }
34
+ }
35
+ if (flashvars) {
36
+ flashvars = getMap(flashvars, '&', /^([^=]+)=(.*)$/);
37
+ fmt_list = getMap(flashvars.fmt_list, ',', /^(\d+)\/(\d+x\d+)/i);
38
+ fmt_stream_map = getIndexedMap(flashvars.url_encoded_fmt_stream_map, 'itag');
39
+ }
40
+ var title = '';
41
+ var elmMetas = document.getElementsByTagName('meta');
42
+ for (var i = 0; i < elmMetas.length; ++i) {
43
+ if (elmMetas[i].name == 'title') {
44
+ title = encodeURIComponent(
45
+ elmMetas[i].content.replace(/([\\\/\:\*\?\"\|<>])/g, '_')
46
+ );
47
+ break;
48
+ }
49
+ }
50
+ //alert(_dump(fmt_stream_map));
51
+ for (var p in fmt_list) {
52
+ fmt_stream_map[p]['size'] = fmt_list[p];
53
+ fmt_stream_map[p]['width'] = parseInt(fmt_list[p]);
54
+ fmt_stream_map[p]['type'].match(/^\w+\/(?:x-)?([^;]+)/);
55
+ fmt_stream_map[p]['ext'] = RegExp.$1;
56
+ }
57
+ fmt_stream_map.sort(function (a, b) {
58
+ return (b['width'] - a['width'] != 0)
59
+ ? b['width'] - a['width']
60
+ : ((a['ext'] > b['ext']) ? 1 : -1);
61
+ });
62
+ document.getElementById('guide-main').innerHTML
63
+ += '<div id="DL-YT-video" align="right"></div>';
64
+ /* Firefoxバグ?対策 */
65
+ document.getElementById('DL-YT-video').innerHTML
66
+ += '<div id="DL-YT-video-formats-dummy">&nbsp;</div>';
67
+ for (var i = 0; i < fmt_stream_map.length; ++i) {
68
+ var fmt = fmt_stream_map[i];
69
+ if (fmt) {
70
+ var params = [];
71
+ for (var p in fmt) {
72
+ params.push(p + ': ' + escapeHTML(fmt[p]));
73
+ }
74
+ document.getElementById('DL-YT-video').innerHTML
75
+ += '<div id="DL-YT-video-formats-' + fmt['itag'] + '">'
76
+ + '<a href="' + fmt['url'] + '&signature=' + fmt['sig']
77
+ + '&title=' + title + '" title="' + params.sort().join('\n') + '">'
78
+ + fmt['ext'] + ' / ' + fmt['size'] + '</a></div>';
79
+ } else {
80
+ // ソートしたときに undefined が入った要素ができる
81
+ break;
82
+ }
83
+ }
84
+
85
+ function getMap(param, separater, regex) {
86
+ var map = {};
87
+ var tmp = param.split(separater);
88
+ for (var i = 0; i < tmp.length; ++i) {
89
+ tmp[i].match(regex);
90
+ map[RegExp.$1] = decodeURIComponent(RegExp.$2);
91
+ }
92
+ return map;
93
+ }
94
+
95
+ function getIndexedMap(param, primary) {
96
+ var map = [];
97
+ var tmp1 = param.split(',');
98
+ for (var i = 0; i < tmp1.length; ++i) {
99
+ var tmp2 = getMap(tmp1[i], '&', /^([^=]+)=(.*)$/);
100
+ map[tmp2[primary]] = tmp2;
101
+ }
102
+ return map;
103
+ }
104
+
105
+ function escapeHTML(str) {
106
+ var mapEscape = {
107
+ '&': 'amp', '<': 'lt', '>': 'gt', '"': 'quot',
108
+ };
109
+ var classEscape = '';
110
+ for (p in mapEscape) {
111
+ classEscape += p;
112
+ }
113
+ var reg = new RegExp(
114
+ '([' + classEscape.replace(/([^0-9A-Za-z_])/g, '\\$1') + '])',
115
+ 'g'
116
+ );
117
+ return ('' + str).replace(reg, function (whole, p1) {
118
+ return '&' + mapEscape[p1] + ';';
119
+ });
120
+ }
121
+
122
+ function _dump(obj) {
123
+ var ret = '';
124
+ for (var p in obj) {
125
+ if (typeof (obj[p]) == 'object') {
126
+ ret += '\n' + p + ':\n';
127
+ ret += _dump(obj[p]);
128
+ } else {
129
+ ret += p + ': ' + obj[p] + '\n';
130
+ }
131
+ }
132
+ return ret;
133
+ }
134
+})();
135
+```
136
+
137
+## リンク
138
+ - [YouTube がブッコ抜きを IP でブロックするようになったらしい…とその回避方法](http://sakuratan.biz/archives/513)
139
+ - [MEMO:Youtube の動画URLを取得する2](http://nondelion.com/archives/2009/04/08/2255)
140
+ - [YouTube HD Suite](http://creazy.net/youtubehdsuite/)
141
+ - [YouTube Downloader の大幅アップデート(2009-03-22)](http://creazy.net/2009/03/youtube_downloader_update_2009-03-22.html)
142
+ - [YoutubeのHD動画正式対応で、改めて動画形式をまとめてみる](http://creazy.net/2008/12/youtube_video_format_list.html)
143
+ - [YoutubeでHD動画がダウンロード可能か判別する方法と、作ったAPIとブックマークレット](http://creazy.net/2008/11/howto_find_youtube_hd_file_api_and_bookmarklet.html)
144
+ - [うえぽんSW局](http://shinshu.fm/MHz/14.30/)
145
+ - [YouTubeブックマークレット(2011年8月ver+0.0)](http://shinshu.fm/MHz/14.30/archives/0000366366.html)
146
+ - [Adds a link to download video for YouTube for Greasemonkey](http://escher.userscripts.org/scripts/show/57674)
147
+ - [Quality YouTube Videos - The Hacker Factor Blog](http://www.hackerfactor.com/blog/index.php?/archives/344-Quality-YouTube-Videos.html)
148
+ - fmt_map から codec が分かるかと思ったんだけど、要求される Flash のバージョンでしかないみたい。
149
+ - [XMLHttpRequest の使い方](http://webos-goodies.jp/archives/50548720.html)
150
+
151
+# YouTubeのビデオIDを抽出
152
+- 今見ているYouTubeのビデオIDを抽出
153
+```javascript
154
+javascript:void(function(){
155
+var url=location.href;
156
+prompt( 'YouTube Video ID', (url.match(/v=([^&\s]+)/))[1] );
157
+})()
158
+```
159
+
160
+# YouTubeのタイトルとビデオIDを抽出(PukiWiki用)
161
+```javascript
162
+javascript:void(function(){
163
+var elm = document.getElementsByTagName( 'meta' );
164
+var title = '';
165
+for(var i=0; i<elm.length; ++i){
166
+ if( elm[i].name == 'title' ){
167
+ title = elm[i].content;
168
+ break;
169
+ }
170
+}
171
+prompt(
172
+ 'YouTube Video ID',
173
+ '[[' + title + '>YouTube:' + (location.href.match(/v=([^&\s]+)/))[1] + ']]'
174
+);
175
+})()
176
+```
177
+
178
+# YouTube の URL を短縮
179
+```javascript
180
+javascript: location = 'http://www.youtube.com/watch?hd=1&v=' + (location.href.match(/v=([^&]+)/))[1];
181
+```
182
+
183
+# YouTubeをHDで見る
184
+- 480x360, 480x270 (fmt=18)
185
+```
186
+javascript:location=location.href.replace(/&fmt=\d+/g,'')+'&fmt=18'
187
+```
188
+- 1280x720 (fmt=22)
189
+```
190
+javascript:location=location.href.replace(/&fmt=\d+/g,'')+'&fmt=22'
191
+```
JavaScript/embedPNG.md
... ...
@@ -0,0 +1,221 @@
1
+[[_TOC_]]
2
+
3
+# 概要
4
+- PNG に文字列を埋め込む。
5
+- HTML5 の Canvas を使って PNG 画像に文字列を埋め込んだり、取り出したりする。
6
+- 文字列を埋め込む際に、不透明度を 0 にしておけば見た目で分からなくなると思ったんだが、そう上手くいかなかったわ。
7
+- ゴミデータが表示されるのに対処。(割り算を int だと思い込んでたわ, 2011.03.04)
8
+- ヘッダとして「EmbPng」が埋め込まれてるときだけ取り出し処理をするようにした。(2011.03.04)
9
+- 本来はiTXtチャンクに埋め込むべきなんだろうけど、JavaScriptからバイナリをいじれるのかな? Base64をデコードしてやればいけるんだろか。
10
+
11
+# ソース
12
+- [embedPNG.zip](embedPNG.zip)
13
+
14
+## index.html
15
+```html
16
+<!DOCTYPE html>
17
+<html lang="ja">
18
+<head>
19
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
20
+<meta http-equiv="Content-Script-Type" content="text/javascript">
21
+<meta http-equiv="Content-Style-Type" content="text/css">
22
+<link rel="stylesheet" type="text/css" href="take.css">
23
+<title>PNGへの文字列の埋め込み</title>
24
+</head>
25
+<body onload="loadImage()">
26
+<h1>PNGへの文字列の埋め込み</h1>
27
+<div><a id="aCanvas" href=""><canvas id="cvsImg" width="300" height="300"></canvas></a></div>
28
+<div><textarea id="txtSrc" cols="60" rows="8"></textarea></div>
29
+
30
+<h2>埋め込み</h2>
31
+<p>
32
+文字列を埋め込んだ後、画像をクリックすると保存ダイアログが出るので拡張子を「png」に変えて保存すること。<br>
33
+<button id="btnEmbed" onclick="embed();">埋め込み</button>
34
+</p>
35
+
36
+<h2>取り出し</h2>
37
+<p>
38
+アップロードする画像ファイルはこのスクリプトのあるフォルダの「data」に予め入れておくこと。<br>
39
+<input id="fInput" name="fInput" type="file"> <button id="btnLoad" onclick="loadImage();">読み込み</button>
40
+</p>
41
+
42
+<h2>セキュリティ設定</h2>
43
+<p>ローカルファイルを読み込んで加工しようとするとセキュリティ違反となることがある。<br>
44
+設定で許可することができるが、セキュリティを弱めることになるので使用には注意すること。</p>
45
+<dl>
46
+<dt>Firefoxの場合</dt><dd>「about:config」で「security.fileuri.strict_origin_policy」を「false」に設定する。</dd>
47
+<dt>Google Chromeの場合</dt><dd>起動オプションに「--allow-file-access-from-files」を付加する。</dd>
48
+</dl>
49
+
50
+<h2>雑感</h2>
51
+<ul>
52
+<li><p>文字列を埋め込むときに不透明度を0にして見た目で分からなくなる予定だったが、そう上手くいかなかったわ。</p></li>
53
+<li><p>Firefox 3.6.13 だと色が変わらないけど、Opera 10.63 だと色が変わっちゃうなぁ。(--;)</p></li>
54
+</ul>
55
+
56
+<h2>リンク</h2>
57
+<ul>
58
+<li><p><a href="http://www.html5.jp/">HTML5.JP</a> / <a href="http://www.html5.jp/canvas/">Canvas</a> / <a href="http://www.html5.jp/canvas/how6.html">画像を組み込む</a> / <a href="http://www.html5.jp/canvas/ref/method/getImageData.html">getImageData</a></p></li>
59
+<li><p><a href="http://blog.livedoor.jp/silverlight2_games/">silverlight3でgamesのブログ</a> / <a href="http://blog.livedoor.jp/silverlight2_games/archives/1216100.html">JavaScript を PNG画像化</a></p></li>
60
+<li><p><a href="http://d.hatena.ne.jp/edvakf/">by edvakf in hatena</a> / <a href="http://d.hatena.ne.jp/edvakf/20091009/1255052759">「HTML5のcanvasで作る画像フィルター」は自分ならこう書く</a></p></li>
61
+<li><p><a href="http://d.hatena.ne.jp/chiheisen/">地平線に行く</a> / <a href="http://d.hatena.ne.jp/chiheisen/20100815/1281885412">canvas の getImageDataが少しめんどくさい</a></p></li>
62
+<li><p><a href="http://www.webtoolkit.info/">Webtoolkit.info</a> / <a href="http://www.webtoolkit.info/javascript-utf8.html">Javascript UTF-8</a></p></li>
63
+</ul>
64
+<script type="text/javascript" src="embedPNG.js"></script>
65
+<script type="text/javascript" src="webtoolkit.utf8.js"></script>
66
+</body>
67
+</html>
68
+```
69
+
70
+## embedPNG.js
71
+```javascript
72
+/*
73
+ PNGへの文字列の埋め込み
74
+*/
75
+
76
+// Opera対応 http://d.hatena.ne.jp/edvakf/20091009/1255052759
77
+if (window.CanvasRenderingContext2D && !CanvasRenderingContext2D.prototype.createImageData && window.ImageData) {
78
+ CanvasRenderingContext2D.prototype.createImageData = function(w,h){return new ImageData(w,h) };
79
+}
80
+
81
+var _myID = 'EmbPng';
82
+
83
+function embed(){
84
+ var txtSrc = Utf8.encode(document.getElementById('txtSrc').value);
85
+ var pSrc = 0;
86
+ var Src = [];
87
+ for( var i=0; i<_myID.length; ++i ){
88
+ Src[ pSrc++ ] = _myID.charCodeAt( i );
89
+ }
90
+ var lenTxt = txtSrc.length;
91
+ Src[ pSrc++ ] = lenTxt % 256;
92
+ Src[ pSrc++ ] = Math.floor(lenTxt / 256) % 256;
93
+ Src[ pSrc++ ] = Math.floor(lenTxt / 256) / 256;
94
+ lenTxt += pSrc;
95
+ for( var i=0; i<txtSrc.length; ++i ){
96
+ Src[ pSrc++ ] = txtSrc.charCodeAt( i );
97
+ }
98
+ for( var i=0; i<4; ++i ){
99
+ Src[ Src.length ] = 0;
100
+ }
101
+ var ctx = document.getElementById('cvsImg').getContext('2d');
102
+ ctx.width = 300;
103
+ ctx.height = 300;
104
+ var img = ctx.getImageData(0, 0, ctx.width, ctx.height);
105
+ var rgba = img.data;
106
+ var pImg = 0;
107
+ for( pSrc=0; pSrc < lenTxt && pImg < ctx.width * ctx.height * 4; ){
108
+ rgba[ pImg++ ] = Src[ pSrc++ ]; // R
109
+ rgba[ pImg++ ] = Src[ pSrc++ ]; // G
110
+ rgba[ pImg++ ] = Src[ pSrc++ ]; // B
111
+ rgba[ pImg++ ] = 255; // A
112
+ }
113
+ img.data = rgba;
114
+ ctx.putImageData(img, 0, 0);
115
+
116
+ var cvs = document.getElementById('cvsImg');
117
+ var aCvs = document.getElementById('aCanvas');
118
+ aCvs.href = cvs.toDataURL().replace('image/png', 'application/octet-stream');
119
+};
120
+
121
+function pickout(){
122
+ var LF = String.fromCharCode(10);
123
+ var ctx = document.getElementById('cvsImg').getContext('2d');
124
+ var img = ctx.getImageData(0, 0, ctx.width, ctx.height);
125
+ var rgba = img.data;
126
+ var pImg = 0;
127
+ var key = '';
128
+ for( var i=0; i<3; ++i ){
129
+ key += String.fromCharCode( rgba[ pImg++ ] );
130
+ }
131
+ pImg++;
132
+ for( var i=0; i<3; ++i ){
133
+ key += String.fromCharCode( rgba[ pImg++ ] );
134
+ }
135
+ pImg++;
136
+ if ( key != _myID ){
137
+ return;
138
+ }
139
+ var lenTxt = 0;
140
+ for( var i=0; i<3; ++i ){
141
+ lenTxt += rgba[ pImg++ ] * Math.pow( 256, i )
142
+ }
143
+ pImg++;
144
+ var pSrc = 0;
145
+ var Src = [];
146
+ for( ; pSrc < lenTxt && pImg < ctx.width * ctx.height * 4; ){
147
+ Src[ pSrc++ ] = rgba[ pImg++ ]; // R
148
+ Src[ pSrc++ ] = rgba[ pImg++ ]; // G
149
+ Src[ pSrc++ ] = rgba[ pImg++ ]; // B
150
+ pImg++; // A
151
+ }
152
+ var txtDst = '';
153
+ var txtDebug = LF + lenTxt + LF;
154
+ for( var i=0; i < lenTxt; ++i ){
155
+ txtDst += String.fromCharCode( Src[ i ] );
156
+ txtDebug += ('0' + Src[ i ].toString(16)).slice(-2) + ' ';
157
+ }
158
+ document.getElementById('txtSrc').value = Utf8.decode( txtDst ); // + txtDebug;
159
+};
160
+
161
+function loadImage(){
162
+ var fname = document.getElementById('fInput').value || 'base.png';
163
+ fname.match( /([^\\\/\:]+)$/ );
164
+ fname = 'data/' + RegExp.$1;
165
+// alert(fname);
166
+ var cvs = document.getElementById('cvsImg');
167
+ if ( ! cvs || ! cvs.getContext ) { return false; }
168
+ var ctx = cvs.getContext('2d');
169
+ ctx.width = 300;
170
+ ctx.height = 300;
171
+ var img = ctx.createImageData(ctx.width, ctx.height);
172
+ var rgba = img.data;
173
+ for( var i=0; i<rgba.length; ++i ){
174
+ rgba[ i ] = 0x00;
175
+ }
176
+ img.data = rgba;
177
+ ctx.putImageData(img, 0, 0);
178
+
179
+ /* Imageオブジェクトを生成 */
180
+ var img = new Image();
181
+ img.src = fname + "?" + new Date().getTime();
182
+ /* 画像が読み込まれるのを待ってから処理を続行 */
183
+ img.onload = function(){
184
+ ctx.drawImage(img, 0, 0);
185
+ pickout();
186
+ }
187
+};
188
+
189
+// EOF
190
+```
191
+
192
+# リンク
193
+- [Portable Network Graphics (PNG) Specification](http://www.w3.org/TR/PNG/)
194
+ - [Textual information](http://www.w3.org/TR/PNG/#11textinfo)
195
+
196
+- [libpng.org](http://www.libpng.org/)
197
+ - [PNG (Portable Network Graphics) Home Site](http://www.libpng.org/pub/png/)
198
+ - [PNG (Portable Network Graphics) Specification and Extensions](http://www.libpng.org/pub/png/spec/)
199
+
200
+- [HTML5.JP](http://www.html5.jp/)
201
+ - [Canvas](http://www.html5.jp/canvas/)
202
+ - [画像を組み込む](http://www.html5.jp/canvas/how6.html)
203
+ - [createImageData, getImageData, putImageData メソッド](http://www.html5.jp/canvas/ref/method/getImageData.html)
204
+
205
+- [silverlight3でgamesのブログ](http://blog.livedoor.jp/silverlight2_games/)
206
+ - [JavaScript を PNG画像化](http://blog.livedoor.jp/silverlight2_games/archives/1216100.html)
207
+
208
+- [by edvakf in hatena](http://d.hatena.ne.jp/edvakf/)
209
+ - [「HTML5のcanvasで作る画像フィルター」は自分ならこう書く](http://d.hatena.ne.jp/edvakf/20091009/1255052759)
210
+
211
+- [地平線に行く](http://d.hatena.ne.jp/chiheisen/)
212
+ - [canvas の getImageDataが少しめんどくさい(特にローカルで動かす場合)](http://d.hatena.ne.jp/chiheisen/20100815/1281885412)
213
+
214
+- [Webtoolkit.info](http://www.webtoolkit.info/)
215
+ - [Javascript UTF-8](http://www.webtoolkit.info/javascript-utf8.html)
216
+
217
+- [hiChangeLog - 個人的なPC関連メモ](http://aki.issp.u-tokyo.ac.jp/itoh/hiChangeLog/html/)
218
+ - [PNGにコメントを埋め込む](http://aki.issp.u-tokyo.ac.jp/itoh/hiChangeLog/html/2007-10.html#2007-10-16-1) (C++)
219
+
220
+- [nulog / nulog, NULL::something : out of the washer](http://lowreal.net/)
221
+ - [PNG iTXt チャンク編集ツール](http://lowreal.net/logs/2004/11/12/1) (Ruby)