e57e54d848ac12979b1e6a7fa6f4f7e6b5f859ab
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 | + + '¢er=' + 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 | + '>': '>' |
|
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) + '…' : 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) + '…' : 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+)(<)/g, function (whole, p1, p2, p3) { |
|
34 | + return p1 + p2.replace(/\s/g, ' ') + 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"> </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) |