Chatter.comを試用してみた!
一応、自分はアジャイルでシステム開発をやっている。
そのシステム開発等の話し合いで使えると感じた。
チャットベースで話し合いを行うと、議事録をとる必要がないし、自分のメモでも他の人の役に立つことがあるからだ。
印象としては、グループ内(会社)とかで使うtwitterっぽい感じ。
でも、twitterより閉じた世界で、社内コミュニケーションを活性化できそう!
Chatterを使ってみて良いと感じた点
- グループチャットが出来るので、話し合いった結果のログをとっておける。
- ファイル送信も可能なので、メールで送る必要もない。
- 検索も可能なので、履歴も参照できる。
- スマフォアプリもあるので、スマフォでも閲覧できる。
- ハッシュタグとかも使える。
Chatterを使ってみて悪いと感じた点
- コメントはメッセージにぶら下がって表示されるが、タイムラインの順序がメッセージ順なので、コメントの新規追加が分かりづらい。
- リツイート的なものがない。(閉じた世界なので必要ないかも?)
以上、使ってみて思ったのは、すごくいいプロダクトだと思った。
これからも使っていくと思う。
JMockitでSeasar2のInterceptorのテストケースを書く。
テストフレームワークにJMockit、WebフレームワークにSeasar2を使用した場合に、Interceptorのテストケースを書いたので、忘れないように書いておく。
TestInterceptor
第一引数に文字列が渡されたら、「test」という文字列に変換するインターセプタ。
public class TestInterceptor implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { Object[] args = invocation.getArguments(); if(args.length == 0) { return invocation.proceed(); } Object obj = args[0]; if(obj instanceof String) { String str = (String) obj; str = "test"; } return invocation.proceed(); } }
TestInterceptorTest
JMockitを使って、上記インターセプタのテストケースを書く。
public class TestInterceptorTest { /** テスト対象 */ private final TestInterceptor target = new TestInterceptor(); private String testStr = ""; /** MethodInvocationモック */ @Mocked private MethodInvocation invocation; @Test public final void testInvoke() { new Expectations() { { invocation.getArguments(); result = new Object[] {testStr }; invocation.proceed(); result = "test"; } }; target.invoke(invocation); assertEquals("test", testStr); } }
こんな感じでよいのか。。
まだまだ勉強中。。
javascriptでの環境依存変数の管理方法
javascriptを使用しているときに、環境に依存する設定(例えばコンテキストパス等)が出てくる。
そんな時に、いろんなソースに環境設定を記述していては、後でソースを見直したときに分かりづらくなる。
今回、そんな環境設定を安全に管理しておくためのJavascriptを考えてみた。
env.js
/** * 環境設定<br /> */ var Env = function() { }; /** * 環境設定を初期化する<br /> */ Env.init = function(envType) { // カプセル化し、他からアクセス不可能にする。 var _env = null, ENV_TYPE_DEVELOPMENT = '0', ENV_TYPE_STAGING = '1', ENV_TYPE_PRODUCT = '2'; // 環境ごとの環境設定 var _settings = { local: { contextPath: '/', ajaxTimeout: 60000, debug: true }, development: { contextPath: '/dev', ajaxTimeout: 60000, debug: true }, staging: { contextPath: '/staging', ajaxTimeout: 60000, debug: false }, product: { contextPath: '/product', ajaxTimeout: 20000, debug: false } } // 環境ごとに読み込む設定を変更する。 if(envType == ENV_TYPE_DEVELOPMENT) { _env = _settings.development; } else if(envType == ENV_TYPE_STAGING) { _env = _settings.staging; } else if(envType == ENV_TYPE_PRODUCT) { _env = _settings.product; } else { _env = _settings.local; } // 各変数のアクセッサー。 this.getContextPath = function() { return _env.contextPath; }; this.getAjaxTimeout = function() { return _env.ajaxTimeout; }; this.isDebug = function() { return _env.debug; }; };
環境設定の呼び出し方法は下記。
<html> <head> <script type="text/javascript" src="./env.js"></script> <script type="text/javascript"> // 開発環境用の設定を行う。 Env.init('0'); // 環境設定変数の取り出し。 alert(Env.getContextPath()); </script> </head> <body> ... </body> </html>
こうする事で、環境依存の変数を一元管理し、後は、envType等はJSPで変数を取得すればよい。
Jqueryでグラフ表示
仕事でグラフを表示したいという要件が出てきた。
そのため、Jqueryでグラフ表示できるプラグインがないか調査することに。
んで、下記が候補として見つかったプラグイン。
グラフの見栄えがよく、様々なグラフを表示できる。 表現方法が多い。(色やプロットの形など) 特に、グラフをドラッグで変更できる点などは、素晴らしい。 APIも整備されていて、実装時に、探しやすい。
見栄えはjqplotより落ちるが、様々なグラフを表示できる。 機能的な部分が多い。ズーム、スクロール、リアルタイム描画、描画対象の変更等。 軽量のスクリプトになっているので、ソースリーディングが容易。
上記2つで作成した所、スマフォでのグラフ表示ということもあり、グラフ内部のスクロールが出来なければならないため、今回は「flot」を採用することにした。
それぞれで作成した方法を記述しておく。
jqplot
まず、WEBアプリ側で下記のようなJSONを返却するものを作成する。(今回は割愛。)
{"tempList":[["0","25"],["1","30"],["2","0"],["3","10"],["4","80"],["5","50"],["6","70"]],"rainList":[["0","18"],["1","13"],["2","12"],["3","13"],["4","9"],["5","4"],["6","3"]]}
そして、javascriptで上記JSONを返却するURLを非同期で呼び出し、結果からグラフを作成する。
JavaScriptは下記。
$.ajax({ type: 'GET', url: '/json/', dataType: 'json', async: true, success: function(data, textStatus) { var line1 = data.tempList; var line2 = data.rainList; var xticks = [[0, '12時'], [1, '13時'], [2, '14時'], [3, '15時'], [4, '16時'], [5, '17時'], [6, '18時']]; var yticks = [0, 5, 10, 15, 20]; var yticks2 = [0, 25, 50, 75, 100]; var jqplot = $.jqplot('plotGraf', [line1, line2], { legend: {show:true}, title: '2010/01/01', grid: {background:'#f3f3f3', gridLineColor:'#accf9b'}, series: [ {label:'気温', markerOptions:{style:'square'}}, {label:'降水確率', markerOptions:{style:'circle'}, yaxis:'y2axis'} ], axes: { xaxis:{ticks:xticks}, yaxis:{ticks:yticks, tickOptions:{formatString:'%d度'}}, y2axis:{ticks:yticks2, tickOptions:{formatString:'%d%'}} } }); }, error: function() { console.log('error'); } });
flot
同じく、WEBアプリ側で下記のようなJSONを返却するものを作成する。(今回は割愛。)
{"tempList":[["1293850800000","25"],["1293854400000","30"],["1293858000000","0"],["1293861600000","10"],["1293865200000","80"],["1293868800000","50"],["1293872400000","70"],["1293876000000","50"],["1293879600000","70"]],"rainList":[["1293850800000","18"],["1293854400000","13"],["1293858000000","12"],["1293861600000","13"],["1293865200000","9"],["1293868800000","4"],["1293872400000","3"],["1293876000000","3"],["1293879600000","3"]]}
そして、javascriptで上記JSONを返却するURLを非同期で呼び出し、結果からグラフを作成する。
JavaScriptは下記。
$.ajax({ type: 'GET', url: '/json/', dataType: 'json', async: true, success: function(data, textStatus) { var tempData = data['tempList']; var rainData = data['rainList']; var options = { series: { lines: { show: true }, shadowSize: 0 }, grid: { backgroundColor: '#FFFFFF' }, xaxes: [ { panRange: [tempData[0][0], tempData[tempData.length-1][0]], min: tempData[0][0], max: tempData.length < 4 ? tempData[tempData.length-1][0] : tempData[3][0], // 4つぶん出力する tickSize: 3600000, // 1日ぶんの間隔を空ける tickFormatter: function(val, axis) { var date = new Date(val); return date.getDate() + "日" + date.getHours() + "時"; } } ], yaxes: [ { panRange: false, tickFormatter: function(val, axis) { return val + '度'; } }, { panRange: false, alignTicksWithAxis: "right", position: "right", tickFormatter: function(val, axis) { return val + '%'; } } ], pan: { interactive: true } }; var plot = $.plot($("#placeholder"), [ {data: data.list, label: '気温', points: { show: true } }, {data: data.list2, label: '降水確率', points: { show: true }, yaxis: 2}, ], options); }, error: function() { console.log('error'); } });
また、flotのグラフスクロールは、スマフォには対応しておらず、少し改良が必要になる。
jquery.flot.navigation.jsの改良。
//147行目 function onDragStart(e) { // modify by ochi0218 // スマートフォンで対応出来るように修正。 // if (e.which != 1) // only accept left-click // return false; // var c = plot.getPlaceholder().css('cursor'); // if (c) // prevCursor = c; // plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor); if(!$.support.touch) { if (e.which != 1) // only accept left-click return false; var c = plot.getPlaceholder().css('cursor'); if (c) prevCursor = c; plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor); } e = (event.changedTouches && event.changedTouches.length) ? event.changedTouches[0] : e; // modify by ochi0218 prevPageX = e.pageX; prevPageY = e.pageY; } function onDrag(e) { var frameRate = plot.getOptions().pan.frameRate; if (panTimeout || !frameRate) return; // add by ochi0218 e = (event.changedTouches && event.changedTouches.length) ? event.changedTouches[0] : e; // add by ochi0218 panTimeout = setTimeout(function () { plot.pan({ left: prevPageX - e.pageX, top: prevPageY - e.pageY }); prevPageX = e.pageX; prevPageY = e.pageY; panTimeout = null; }, 1 / frameRate * 1000); } function onDragEnd(e) { if (panTimeout) { clearTimeout(panTimeout); panTimeout = null; } // add by ochi0218 e = (event.changedTouches && event.changedTouches.length) ? event.changedTouches[0] : e; // add by ochi0218 plot.getPlaceholder().css('cursor', prevCursor); // modify by ochi0218 // iphoneで正常に動作しないため、コメントアウト。 // plot.pan({ left: prevPageX - e.pageX, // top: prevPageY - e.pageY }); // modify by ochi0218 } --------------------------------------------------------------------------------- // 191行目 if (o.pan.interactive) { // modify by ochi0218 // スマートフォンで対応出来るように修正。 // eventHolder.bind("dragstart", { distance: 10 }, onDragStart); // eventHolder.bind("drag", onDrag); // eventHolder.bind("dragend", onDragEnd); if ($.support.touch) { eventHolder.bind("touchstart", { distance: 10 }, onDragStart); eventHolder.bind("touchmove", onDrag); eventHolder.bind("touchend", onDragEnd); } else { eventHolder.bind("dragstart", { distance: 10 }, onDragStart); eventHolder.bind("drag", onDrag); eventHolder.bind("dragend", onDragEnd); } // modify by ochi0218 } --------------------------------------------------------------------------------- //316行目 function shutdown(plot, eventHolder) { eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick); eventHolder.unbind("mousewheel", onMouseWheel); // modify by ochi0218 // eventHolder.unbind("dragstart", onDragStart); // eventHolder.unbind("drag", onDrag); // eventHolder.unbind("dragend", onDragEnd); if ($.support.touch) { eventHolder.unbind("touchstart", onDragStart); eventHolder.unbind("touchmove", onDrag); eventHolder.unbind("touchend", onDragEnd); } else { eventHolder.unbind("dragstart", onDragStart); eventHolder.unbind("drag", onDrag); eventHolder.unbind("dragend", onDragEnd); } // modify by ochi0218 if (panTimeout) clearTimeout(panTimeout); } plot.hooks.bindEvents.push(bindEvents); plot.hooks.shutdown.push(shutdown); }
その結果がこれ。
スマートフォンブラウザでも、PCブラウザでも、ドラッグorスワイプで次の要素を表示させることが出来る。
やっぱり、見栄えはjqplotの方がよいね。。
flotでも、見栄えが近づけれるようにもうちょい頑張ってみよう!
最近のももんが達
うちで飼っているペットのご紹介!
去年の2月に初めて購入した「ももんが」のまりもちゃん(♀)。
そして、去年の11月に購入した「ももんが」のるいちゃん(♂)。
ももんがって、飼ってみて分かったけど、めちゃめちゃなつっこい。
最近、飼い主以外の人には凶暴になってしまったけど。。
んで、2匹はそれぞれ別のケージで飼っているんだけど、ついに1カ月ほど前に2匹をあわせてみることに!
ももんがの繁殖期がそろそろなので、2匹の子供が生まれるのがめちゃ楽しみ!
うちのはフクロモモンガっていう種類のももんがなんだけど、子供が生まれたら、カンガルーみたいな袋で育てるらしい。
想像しただけでかわゆす!!
↓何回か会わせているうちに、2匹の距離が親密になって、LOVELOVEし始めた画像(笑)↓
これからも、ちょこちょこ2匹を追いかけていくので、よろしく☆
yuicompressor-maven-pluginでJS、CSSファイルを圧縮・難読化
Webサイトを作成していて、Javascriptのコードが増えてきた場合、Javascript圧縮&難読化をしたい場合が出てくる。
その処理を、mavenのwar作成処理の中に加えたい。
そんな時に、yuicompressor-maven-pluginというものが便利だったので紹介。
利用方法は以下。
pom.xml
<pluginRepositories> <pluginRepository> <name>oss.sonatype.org</name> <id>oss.sonatype.org</id> <url>http://oss.sonatype.org/content/groups/public</url> </pluginRepository> </pluginRepositories> <build> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <warSourceExcludes>WEB-INF/classes/**/*.*,WEB-INF/lib/*.jar</warSourceExcludes> <!-- 圧縮したものを加える。 --> <webResources> <resource> <directory>${project.build.directory}/minimized</directory> <targetPath>/</targetPath> <filtering>false</filtering> </resource> </webResources> </configuration> </plugin> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>yuicompressor-maven-plugin</artifactId> <executions> <execution> <goals> <goal>compress</goal> </goals> </execution> </executions> <configuration> <webappDirectory>${project.build.directory}/minimized</webappDirectory> <linebreakpos>-1</linebreakpos> <!-- 1行にまとめる --> <encoding>UTF-8</encoding> <nosuffix>true</nosuffix> <!-- 圧縮後のファイルに接尾語を付けない。 --> <force>true</force> <jswarn>false</jswarn> <!-- すでに圧縮済みのファイルは除外する --> <excludes> <exclude>**/*.min.js</exclude> <exclude>**/*.min.css</exclude> </excludes> </configuration> </plugin> </plugins> </build>
その他の機能として、圧縮ファイルを1ファイルにまとめることも可能なようです。
こちらを参考にしてください。
URLDispatcher
WEB+DBPressの第60回にJQueryの特集をしていた。
JQuery好きとしては是非見たいところ。
- 作者: まつもとゆきひろ,西尾泰和,山田憲晋,城戸忠之,増井俊之,羽生章洋,uupaa,ミック,塙与志夫,原悠,奥一穂,はまちや2,大沢和宏,吾郷協,浜本階生,中島拓,中島聡,矢野りん,角田直行,能登信晴,田村哲也,吉村譲,結城亜砂子,角谷信太郎,石橋秀仁,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2010/12/22
- メディア: 大型本
- 購入: 12人 クリック: 185回
- この商品を含むブログ (24件) を見る
その中に、URLDispatcherというものが紹介されていたので、自分なりに作り変えてみた。
どういうものかと言うと、URLごとに実行するJavascriptのコードを変更するという物。
結構Javascriptって、コードが散らばってたりするので、このJavascriptを1行読み込んで、URLごとに処理を切り出すようにする。
変更を加えた物は以下。
url.dispatcher.js
// 実行するものの定義 dispatcher([ { // 全体の処理。 path: '.', func: function() { // 全体に関わる処理を記述する。 } }, { // 「/hoge」で始まるURLでの処理。 path: '^/hoge', func: function() { // 「/hoge」配下での処理を記述する。 } } ]); /** * パスによって指定の関数を実行する。 * @param mappings * path:現在のパスにマッチする正規表現 * func:実行させたい関数 */ function dispatcher(mappings) { var pathname = location.pathname; for(var i = 0, len = mappings.length; i < len; i++) { var path = mappings[i]['path'], func = mappings[i]['func']; if(path && func) { if (pathname.match(new RegExp(path))) { func.apply(this); } } } };