Chrome Extension の createHTMLNotification メソッドでデータを渡してフレキシブルに内容を構成するには

Chrome拡張でデスクトップ通知の実装時に、HTMLを使うときデータを簡単に渡す方法について。 Desktop Notifications chrome.notifications - Google Chrome を見ると、通常のタイトル、イメージ、テキストの三つを渡して表示する通知と、HTMLで自由に組める通知がある。 1 2 3 4 5 6 // Create a simple text notification: var notification = webkitNotifications.createNotification( '48.png', // icon url - can be relative 'Hello!', // notification title 'Lorem ipsum...' // notification body text ); このように前者の通知は引数でデータを渡せるが、後者では HTML ファイル名を指定するだけになっている。 1 2 3 4 // Or create an HTML notification: var notification = webkitNotifications.createHTMLNotification( 'notification.html' // html url - can be relative ); これで内容を可変にしたいときは、例として ...

2013年2月20日 · Toshimitsu Takahashi

JavaScript の Array で forEach したときに break するには

jQuery.each メソッドだと、return true で continue, return false で break できます。 しかし、node で普通に array.forEach で同じようにやろうとしたらできない。 node の実装つまり ECMAScript 5 においては、array.forEach に break 処理はない。代わりに some メソッドを使うと意図したことができることがわかった。 1 2 3 4 5 6 7 8 9 array.some(function(item){ if (item.isEmpty) { return false; // continue } if (item.isLast) { return true; // break } }); some メソッドは、要素に対して評価(コールバック)関数を実行し、true になるものが一つでもあれば true を返します。これが本来の用途です。

2012年11月14日 · Toshimitsu Takahashi

Mongoose で MongoDB の Embedded Documents の扱いで嵌まったこと

node(.js)と相性が良いということで、MongoDB とそのJavaScript O/R マッパーライクなモデリングライブラリの Mongoose を使い始めました。 MongoDBと言えばドキュメント指向モデルでそれを特徴づける Embedded Documents が有名ですが、この機能を Mongoose から利用する上で躓いたので、メモしておきます。 Embbed Document の Array について var Users = new Schema({ name : String }); var Comments = new Schema({ title : String , body : String , date : Date }); var BlogPost = new Schema({ author : { type: ObjectId, ref: ‘User’ } , title : String , body : String , date : Date , comments : [Comments] , meta : { votes : Number , favs : Number } }); mongoose.model(‘User’, Users); mongoose.model(‘BlogPost’, BlogPost); ...

2011年10月30日 · Toshimitsu Takahashi

Flex のテンプレート HTML ラッパーに細工をしてクエリ引数を flashVars へ引き継ぐには

この話は要 JavaScript です。index.template.html に細工します。 index.template.html 49行目付近 ブラウザの現在のURL引数を取得して params にセットする処理を挿入します。 // Get Parameters var params = “”; var pos = window.location.href.indexOf(’?’); if (pos == -1) { params = “”; } else { params = window.location.href.substr(pos + 1); } 94行目付近 「“flashVars”, params」を挿入します。(前の行の「,」を忘れずに。) } else if (hasRequestedVersion) { // if we’ve detected an acceptable version // embed the Flash Content SWF when all tests are passed AC_FL_RunContent( “src”, “${swf}”, “width”, “${width}”, “height”, “${height}”, “align”, “middle”, “id”, “${application}”, “quality”, “high”, “bgcolor”, “${bgcolor}”, “name”, “${application}”, “allowScriptAccess”,“sameDomain”, “type”, “application/x-shockwave-flash”, “pluginspage”, “http://www.adobe.com/go/getflashplayer", “flashVars”, params );

2009年9月4日 · Toshimitsu Takahashi

Opera 対象 JavaScript でASCIIコード以外の値を書く場合は必ず charset を定義する

何故か Opera だけでエラーになっていた Ajax アプリがある調べてみると、ASCII コード以外の値が存在する JavaScript ファイルを化けて読み込んでいたようだ。 読み込み元のHTMLも js ファイルも全て UTF-8 にして Content-Type でも UTF-8 としていたのだが Opera だけ上手く動かなかった。 ということで下記のように必ず charset を指定した方が良い。

2009年4月10日 · Toshimitsu Takahashi

Adobe AIR の SQL 機能を試してみるためにデモアプリを作ってみた

AIR には Flex(MXML/ActionScript) と Ajax(HTML/JavaScript) の二つの作成方法があるが、今回は後者を選んだ。 http://help.adobe.com/ja_JP/AIR/1.5/devappshtml/ http://www.adobe.com/jp/devnet/air/ajax/ 開発環境は Aptana Studio を使った。 デモアプリはテキストエリアに SQL 文を書いて実行すると、結果が表示されるというもの。SELECT であればテーブルに結果が表示される。テーブルの表示は、Adobe だけに Spry のデータセット機能を使ってみることにした。 Aptana Studio でプロジェクトを作成 File -> New.. -> Project -> Adobe AIR Project を選択する。 プロジェクトに「AirSQLiteTest」を設定する。 Import JavaScript Library までそのまま [Next] をクリック。 Adobe Spry 1.6 にチェックを入れて [Finish] をクリック。 ソースコード AirSQLiteTest.html が AIR 本体を構成する。ソースコードは以下。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 <html> <head> <title>AIR SQL Test</title> <script type="text/javascript" src="lib/air/AIRAliases.js"></script> <script type="text/javascript" src="lib/spry/includes/SpryData.js"></script> <style type="text/css"> div { margin:16px; } #textSql { width:100%; height:120px; } #textResult { width:100%; height:60px; } p { margin:4px 0; } table th, table td { border:1px solid gray; } th, td { padding:8px } th { cursor: default; } </style> <script type="text/javascript"> /** \* AIR SQL を操作する DBClient \* \* @param {String} dbname データベース名 \* @param {Function} closure クロージャ(省略可能) \* 指定された場合はクロージャ引数にこのオブジェクトが渡り、 \* 処理終了とともに接続が閉じられる。 */ function DBClient(dbname, closure){ if (closure) { var dbc = new DBClient(dbname); closure(dbc); dbc.close(); } else { this.open(dbname); } } DBClient.prototype = { /* \* データベースを開く \* \* @param {String} dbname データベース名 */ open: function(dbname){ try { this.conn = new air.SQLConnection(); var dbfile = null; if (dbname) { dbfile = air.File.applicationStorageDirectory.resolvePath(dbname + ".db"); } this.conn.open(dbfile); } catch (error) { statustext.innerText = "Error opening database"; air.trace("error.message:", error.message); air.trace("error.details:", error.details); return; } }, /* \* データベース接続を開じる */ close: function(){ if (this.conn) { this.conn.close(); this.conn = null; } }, /* \* SQL文を実行する \* \* @param {String} sqltext SQL文 \* @param {Function} cbsuccess クエリ成功時のコールバック関数 \* @param {Function} cberror クエリ失敗時のコールバック関数 */ execute: function(sqltext, cbsuccess, cberror){ try { var stmt = new air.SQLStatement(); stmt.sqlConnection = this.conn; stmt.text = sqltext; stmt.execute(); cbsuccess(stmt.getResult()); return true; } catch (error) { if (cberror) cberror(error); return false; } } } </script> </head> <body> <div> <div> <p>SQL Statement:</p> <textarea id="textSql">CREATE TABLE IF NOT EXISTS sample ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, score INTEGER )</textarea> </div> <div> <button id="buttonExecute">execute SQL</button> </div> <div> <p>Query Result:</p> <textarea id="textResult"></textarea> </div> <div> <table spry:region="Results"> <caption>Select Result</caption> <thead> <tr> <th spry:sort="{ds_RowNumberPlus1}">#</th> <th spry:sort="id">id</th> <th spry:sort="content">content</th> <th spry:sort="score">score</th> </tr> </thead> <tbody spry:repeatchildren="Results"> <tr> <td>{ds_RowNumberPlus1}</td><td>{id}</td><td>{content}</td><td>{score}</td> </tr> </tbody> </table> </div> </div> <script type="text/javascript"><!-- function $(id) { return document.getElementById(id) }; var Results = new Spry.Data.DataSet(); $("buttonExecute").onclick = function(e){ // SQLを実行する DBClient("sampledb", function(dbh){ dbh.execute($("textSql").value, function(result){ // 成功 $("textResult").value = "QUERY OK, " \+ result.rowsAffected + " rows affected"; Results.data = result.data ? result.data : {}; Results.loadData(); }, function(error){ // 失敗 $("textResult").value = error.message + "\\n" \+ error.detailID + ": " \+ error.details; }); }); }; //--> </script> </body> </html> 試してみる プロジェクトを選択した状態で、Run -> Run… デフォルトで SQL 文には CREATE TABLE が入っている。 データをインサート。 SELECT でテーブルを表示。 ...

2009年1月30日 · Toshimitsu Takahashi

jQuery 1.3.1 リリース

ちょうどタイムリーな話題がわかったので、書いておきます。 jQuery 1.3.1 Released | Official jQuery Blog 23個のバグフィックスリスト Error: Invalid Report Number – jQuery Core - Bug Tracker 1.3 系最初のリビジョンアップとあって、既に使っている方は早速置き換えた方がいいでしょう。

2009年1月22日 · Toshimitsu Takahashi

jQuery を用いて大きな画像などを Google Map ライクにスクロール表示する UI

下記のサンプルは jQuery プラグインとして公開しています。(2009/05/20 追記) jquery-scrollview - This jQuery plugin applies grab-and-drag scroll view to block elements. - Google Project Hosting 壁紙などの大きなサイズの画像を表示するのに Google マップのようなインターフェイスを提供したい。 Google マップのような、 マウスドラッグでスクロール ダブルクリックした所にセンタリング するような処理である。ただ、ズームに関しては実装しない。 ということで実装したサンプルは ScrollViewer Sample である。 ScrollViewer jQuery を必要とする。 function ScrollViewer(){ this.initialize.apply(this, arguments); } ScrollViewer.prototype = { initialize: function(container){ // // Dragging Cursor Set. // // http://docs.jquery.com/Utilities/jQuery.browser // jQuery.browser Deprecated in jQuery 1.3 // if (navigator.userAgent.indexOf(“Gecko/”) != -1) { this.grab = “-moz-grab”; this.grabbing = “-moz-grabbing”; } else { this.grab = “default”; this.grabbing = “move”; } // Get container and image. this.m = $(container); this.i = this.m.children().css(“cursor”, this.grab); this.isgrabbing = false; // Set mouse events. var self = this; this.i.mousedown(function(e){ self.startgrab(); this.xp = e.pageX; this.yp = e.pageY; return false; }).mousemove(function(e){ if (!self.isgrabbing) return true; self.scrollTo(this.xp - e.pageX, this.yp - e.pageY); this.xp = e.pageX; this.yp = e.pageY; return false; }) .mouseout(function(){ self.stopgrab() }) .mouseup(function(){ self.stopgrab() }) .dblclick(function(){ var _m = self.m; var off = _m.offset(); var dx = this.xp - off.left - _m.width() / 2; if (dx < 0) { dx = “+=” + dx + “px”; } else { dx = “-=” + -dx + “px”; } var dy = this.yp - off.top - _m.height() / 2; if (dy < 0) { dy = “+=” + dy + “px”; } else { dy = “-=” + -dy + “px”; } _m.animate({ scrollLeft: dx, scrollTop: dy }, “normal”, “swing”); }); this.centering(); }, centering: function(){ var _m = this.m; var w = this.i.width() - _m.width(); var h = this.i.height() - _m.height(); _m.scrollLeft(w / 2).scrollTop(h / 2); }, startgrab: function(){ this.isgrabbing = true; this.i.css(“cursor”, this.grabbing); }, stopgrab: function(){ this.isgrabbing = false; this.i.css(“cursor”, this.grab); }, scrollTo: function(dx, dy){ var _m = this.m; var x = _m.scrollLeft() + dx; var y = _m.scrollTop() + dy; _m.scrollLeft(x).scrollTop(y); } } ...

2009年1月22日 · Toshimitsu Takahashi

JavaScript エンジン V8 を使ってライブラリの開発にユニットテストを利用したい

大きなプログラムになると JavaScript といえどもブラウザから操作してテストする以外にも、単体でコマンドラインからテストしたくなりますね。 JsUnit はどうなのか JavaScript のユニットテストフレームワークというと、xUnit の JsUnit が思い浮かびます。使ったことがなかったので、ちょっと調べてみました。 http://hisasann.com/housetect/2008/04/javascriptunitjsunit.html http://bobchin.ddo.jp/wiki/index.php?Javascript%2FJsUnit どうも JsUnit は html ファイルを開いてブラウザベースでテスト実行するみたいです。共同でテストに使えるサーバーコンポーネントもあるようですが、専用の HTTP サービスを立ち上げて使うようです。 やっぱり CUI で使えるインタプリタとかシェルベースでだと便利です。 V8 を使えないのか 以前 id:amachang さんの Google Chrome の JavaScript エンジン V8 を試す - IT戦記 をみて、V8 の shell を試しにコンパイルしていました。 v8/sample/shell.cc をさらっと見てみると、 // Bind the global ‘print’ function to the C++ Print callback. global->Set(v8::String::New(“print”), v8::FunctionTemplate::New(Print)); // Bind the global ’load’ function to the C++ Load callback. global->Set(v8::String::New(“load”), v8::FunctionTemplate::New(Load)); と print, load がネイティブ関数として組み込まれていることがわかります。 だから JavaScript での Ruby の irb みたいに使えるのです。 ...

2009年1月19日 · Toshimitsu Takahashi

はてなダイアリーのカテゴリーを管理ツールでソートするブックマークレットを書いてみた

http://d.hatena.ne.jp/claddvd/20090112/1231767107 をみて、「そうそう、増えるとその度に手動並び替えをしていてどうにかしたかった」ことを思い出しました。 どうせならその場で直したい、ということでブックマークレットを書いてみました。(もう既に誰か作っているかもしれませんが、探すよりも自作した方が速そうだったので。) Bookmarklet javascript:var t=document.getElementsByTagName(“textarea”)[0];var a=t.value.split("\n");t.value=a.sort().join("\n");alert(“Categories sorted.”) 速攻で書いたので見てのとおり、テキトウです。今のところ最初に出てくる textarea なので。あと、Array.sort() なのでタグの大文字・小文字を区別します。

2009年1月13日 · Toshimitsu Takahashi