ほんじゃらねっと

ダイエット中プログラマのブログ

Node.jsでRedmineのREST APIにアクセスしてチケット取得&一括登録

とあるWeb開発プロジェクトで

WBS(Excel製)に書かれた、機能ごとの開発担当・開始日・期日・予定工数を

そのままRedmineのチケットとして登録するという、

手作業でやったらえらく時間のかかりそうな作業があったので、

RedmineのAPI経由でチケットを一括登録できるスクリプトを作成した。

続きを読む

Node.jsのRESTクライアントモジュールでBit.lyのAPIにアクセスする

Node.jsのRESTクライアントモジュールを試すため、 以前Groovyで作成したBit.lyの履歴を取得するスクリプトをNode.jsで焼きなおしてみる。

node-rest-client」というモジュールを使用した。

get_bitlinks.js

var RestClient = require('node-rest-client').Client;

var ACCESS_TOKEN = '<your access token>';
var ENDPOINT_BASE = 'https://api-ssl.bitly.com/';
var bitlyClient = new RestClient();

bitlyClient.get(ENDPOINT_BASE + 'v3/user/link_history', {
    headers: {
        'Content-type': 'application/json'
    },
    parameters: {
        access_token: ACCESS_TOKEN,
        limit: 10,
        offset: 0
    }
}, function (data, response) {
    var result = JSON.parse(data.toString('utf8'));
    var linkList = result.data.link_history;
    linkList.forEach(function (link) {
        console.log(link.title);
    }); 
});

RestClientで呼び出すメソッドをgetからpostやputに変更すれば 登録、更新も行えるようなので、これ1つ覚えておけば色々なAPIアクセスに 使用できそうだ。

RESTful Webサービス

RESTful Webサービス

MongoDBに保存したデータをNode.js+ExpressでWeb表示する簡単なサンプル

そろそろNode.jsスクリプト作成にも慣れてきたので、

簡単なWebアプリ作成に挑戦してみた。

Meteor、MEAN.js、Sails.jsなど色々あって迷ったけど、

まずはシンプルにExpressを使ってみる。

MongoDBコレクションに保存された情報を

Webページ上に一覧表示するスクリプトを、

Node.js+Express+MongoDBで作成した。

続きを読む

ApacheのアクセスログをMongoDBコレクションにインポートするNode.jsスクリプト

MongoDBの勉強を兼ねて、Apacheアクセスログを後でログ分析や ビジュアライズに使えるようにMongoDBにインポートするスクリプトを書いた。

下記のスクリプトはログファイルを行単位で読み込んでMongoDBの 特定のコレクションに登録する。 行単位のファイル読み込み処理はNode.js標準で簡単にできる方法が用意されていない ようなので、node-bylineを使用している。

log_importer.js

var fs = require('fs');
var byline = require('byline');
var MongoClient = require('mongodb').MongoClient;

var dbUrl = 'mongodb://localhost:27017/<database name>';
var targetPath = '<path to access log>';

var logPattern = /(\S+) \- \- \[([^\]]+)\] '([^']+)' (\d+) (\S+) '([^']+)' '([^']*)'/;

var rs = fs.createReadStream(targetPath);
var stream = byline.createStream(rs);

MongoClient.connect(dbUrl, function (err, db) {
    if (err) {
        throw err;
    }   

    var apacheLogs = db.collection('apache_logs');

    var i = 0;
    stream.on('readable', function () {

        var line = null;
        while (null !== (line = stream.read())) {
            console.log(i + ':line start ' + line);
            var match = logPattern.exec(line);
            if (match != null) {
                var methodParams = match[3].split(' ');
                var method = methodParams[0];
                var path = methodParams[1];
                var http = methodParams[2];
                var log = {
                    host: match[1],
                    ts: match[2],
                    method: method,
                    path: path,
                    http: http,
                    status: match[4],
                    size: match[5],
                    agent: match[7]
                };
                apacheLogs.insert(log, function (err, result) {
                    if (err) {
                        console.log('log insert error:', err);
                    } else {
                        console.log(i + ':inserted');
                    }
                });
            } else {
                console.log(i + ':match error');
            }
            i++;
        }
    });
    stream.on('end', function () {
        db.close();
    });
});

参考にしたサイトや使用したライブラリ:

RegExp - Mdn https://developer.mozilla.org/ja/doc/Web/JavaScript/Reference/Global_Objects/RegExp

Read large text files in nodejs https://coderwall.com/p/ohjerg/read-large-text-files-in-nodejs

Node.js how to read one line of numbers from a file into an array http://stackoverflow.com/questions/7379310/node-js-how-to-read-one-line-of-numbers-from-a-file-into-an-array

npm line-reader https://github.com/nickewing/line-reader

npm node-byline https://github.com/jahewson/node-byline

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

Nashornスクリプト実行時のクラスパス設定を容易にするためにNasven.jsを使う

Nashornというのは、Java8に同梱されている新しいJavascriptエンジンで、 Javaライブラリを呼び出して利用するJavascriptプログラムを作成することができる。 Node.jsで適当なライブラリが見つからない場合やJavaライブラリに精通していて ちょっとしたスクリプトを作成したい場合の良い選択肢になりそうだ。

Java8環境をインストールしたら標準で付属してくる「jjs」コマンドを使うことで 作成したNashornスクリプトを実行することができる。

Javascriptの言語仕様に加えて、いくつかJavaクラスを呼び出すための関数が 追加されている。Node.jsでnpmライブラリをrequireする感覚でJavaのライブラリを 呼び出せるようになる。

詳細は下記のユーザーガイド参照: Nashorn User's guide https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/

ここからが今回の本題。

NashornスクリプトはJavaのクラスと同じ扱いなので Apache Projectや自作のJar等の標準以外のJavaライブラリを使おうとすると、 当然ながらクラスパスにそのJarファイルを追加して実行する必要がある。

jjsコマンドにはclasspathオプションがあり、ここでjarファイルを指定すれば それで実行できるのだけど、多くのjarファイルを使用している場合などは 毎回classpathを指定するのが面倒で、せっかくコンパイル無しでサクッと 実行できるのだからクラスパス指定ももっと簡単にしたい。

と思って探してみたら、「Nasven.js」(Nashorn + Maven + .js)というスクリプトが 公開されてた。これを使うとMavenと同じ感じでビルドファイルを作成しておき、 そこでクラスパス等のビルド情報を記述しておくことができる。

詳細は下記の記事参照: Nashorn Maven: Easy Library Classpath Setup https://blogs.oracle.com/brunoborges/entry/nashorn_maven_easy_library_classpath

試しにApache POIを使用するスクリプトを作ってみたら、うまく動作した。

nasven.jsを使用するNashornスクリプトの入手から作成・実行までの手順:

  1. Githubからnasven.jsをダウンロード
  2. nasven.jsようのビルドファイル(例:app1.mvn)を作成する
  3. メインのNashornスクリプトを作成する
  4. nasven.js経由でNashornスクリプトを実行する

ビルドファイルの例:

app1.mvn

var maven = { 
    main: 'app1.js',
    options: '-scripting',
    dependencies: [
      'org.apache.poi:poi:3.11',
      'org.apache.poi:poi-ooxml:3.11',
      'org.mongodb:mongo-java-driver:3.0.0'
    ]   
};

Nashornスクリプトの例:

app1.js

var Biff8EncryptionKey = Java.type('org.apache.poi.hssf.record.crypto.Biff8EncryptionKey');
var WorkbookFactory = Java.type('org.apache.poi.ss.usermodel.WorkbookFactory');
var XSSFWorkbook = Java.type('org.apache.poi.xssf.usermodel.XSSFWorkbook');
var MongoClient = Java.type('com.mongodb.MongoClient');
...

Nashornスクリプトを実行する(Linux環境の場合):

$ nashven.js -- app1.mvn

Windows7環境では下記のようにコマンドを変更したら動作した。

Nashornスクリプトを実行する(Windows環境の場合):

$ jjs -scripting nashven.js -- app1.mvn

Maven Centralからのライブラリのダウンロードも自動化されるので、 スクリプトの作成から実行までの手間が軽減され、手軽に使用できるようになった。

Apache Maven 3クックブック Javaソフトウェア開発のための特選レシピ集

Apache Maven 3クックブック Javaソフトウェア開発のための特選レシピ集

Javascriptでできることを調べて、メイン言語にするメリットを確認する

Javascriptプログラミング言語としてどうか、ということはさておいて、 「もうJavascriptさえ覚えておけば何でもできるんじゃない?」 というくらいJavascriptでできることが増えているので、それをまとめてみる。

Javascriptでできること

  1. Webサイトのクライアント側言語として使える
  2. Node.js+npmでWindowsも含めたクロスプラットフォームなバッチスクリプトが作れる
  3. Node.js+Gruntで作業自動化ツールが作れる
  4. Node.js+Express等でWebアプリのサーバサイド開発もできる
  5. Phantom.jsで擬似ブラウザを作成してキャプチャ取得等を自動化できる
  6. Java8以降ならNashornでJavaライブラリを使ったプログラムを作って実行できる
  7. JScriptExcel操作スクリプトが書ける
  8. Windows8アプリが作れる
  9. JXAでMac操作自動化スクリプトが作れる
  10. ElectronでクロスプラットフォームGUIアプリが作れる
  11. Atomテキストエディタの拡張に使える
  12. MongoDBのデータ操作に使える
  13. Microsoftのmainfold.jsでiOSAndroidWindowsアプリが作れる
  14. Google Apps ScriptもJavascriptベースな言語で作れる

つらくなったらこの記事を読み返して、モチベーションを回復しよう。 また思いついたら追加します。

パーフェクトJavaScript

パーフェクトJavaScript

Javascript(node.js)でExcelのシート一覧を出力する

node.jsはWindowsでもLinuxでも同じスクリプトが そこそこ安定して動くので嬉しい。

今回は、ExcelJSモジュールを使って、 Excelのシート一覧を出力するスクリプトを書いた。 リダイレクトでファイルに出力できる。 簡単なスクリプトだけど、こういうものを作っておくと必要な時にすぐ使えて便利。

output_excel_sheets.js

var Excel = require('exceljs');

var targetExcelPath = '<Excelファイルのパス>';

var workbook = new Excel.Workbook();
workbook.xlsx.readFile(targetExcelPath).then(function () {
    workbook.eachSheet(function (worksheet, sheetId) {
        console.log(worksheet.name);
    }); 
}); 

Node.jsとwebshotパッケージでWebサイトのスクリーンショットリスト作成を自動化する

Web開発を仕事にしていると

「マニュアルやプレゼンに使うのでWebアプリのスクリーンショットをくれ」

と依頼されることがよくある。

ChromeのFireshotのようなブラウザの拡張機能を使ったりすれば

1画面ずつ撮っていけるのだけど、

chrome.google.com

たくさんのページのスクリーンショットを、

変更がある度に撮り直すのは面倒なのでなんとか自動化したい。

「node-webshot」モジュールを使う

探してみると、

Node.jsの「node-webshot」パッケージを使えば

手軽にスクリーンショット撮影スクリプトが作れそうだ。

www.npmjs.com

Node.jsでWebKitブラウザの機能を利用可能にするPhantomJSの

スクリーンキャプチャ機能をラップしたものらしい。

PhantomJS | PhantomJS

PhantomJSはブラウザで行っている処理を

色々自動化するのに使えそうなので、また調査してみよう。

「node-webshot」パッケージは

下記のnpmコマンドでアプリにインストールできる。

npm install webshot --save-dev

URLのリストを作って、連続でスクリーンショットを撮るスクリプトを作成する

早速このwebshotパッケージを使って

スクリーンショット自動撮影スクリプトを作ってみる。

URLのリストを読み込んで

各URLのスクリーンショットを保存するようなものを作っておけば

画面に変更があってもコマンド1つで再作成できるので良さそうだ。

下記のようなスクリプトを作成してみた。

capture_screen.js

var webshot = require('webshot');
var fs = require('fs');

// 保存ファイル名とURLのリストを作成する
var baseUrl = 'http://test-domain.com';
var links = { 
    '01_login': baseUrl + '/login.html',
    '02_top': baseUrl + '/top.html',
    '03_shohin_list': baseUrl + '/shohin_list.html',
    '04_shohin_edit': baseUrl + '/shohin_edit.html'
};

// 各URLのスクリーンショットを指定したファイル名で「shots」フォルダに保存する
Object.keys(links).forEach(function (key) {
    var href = links[key];
    webshot(href, 'shots/' + key + '.png', {}, function () {}); 
}); 

URLリストの部分は撮影したいWebサイトのアドレスに合わせて変更する。

今回はデフォルトの設定で撮影を行っているが、

生成される画像のサイズ等はwebshot関数のオプションで指定できる。

サーバサイドJavaScript Node.js入門 (アスキー書籍)

サーバサイドJavaScript Node.js入門 (アスキー書籍)

  • 作者: 清水俊博,大津繁樹,小林秀和,佐々木庸平,篠崎祐輔,高木敦也,西山雄也,Jxck
  • 出版社/メーカー: KADOKAWA / アスキー・メディアワークス
  • 発売日: 2014/02/27
  • メディア: Kindle版
  • この商品を含むブログを見る

treeコマンドで出力したJSONをExcelで階層表示できるように変換する

あるプロジェクトのソース分析を行う必要があったので、

まずはソースファイルの一覧をExcelに出力してみることにした。

treeコマンドがいい感じで階層出力してくれるのだけど、

それをそのままExcelに持っていくと文字化けするので、

treeコマンドから一旦JSON形式で階層情報を出力し、

それをnodejsスクリプトで変換してcsvに出力する方法をとった。

treeコマンドで「-J」オプションを指定するとJSON形式で出力してくれる。

$ cd <プロジェクトディレクトリ>
$ tree -J &gt; file_tree.json

こうやって出力したjsonを下記のスクリプトでCSVにコンバートする。

階層毎に列がインデントされるようにして、

Excel上で拡張子でフィルタリングできるようにファイルの拡張子を出力する。

filetree2csv.js

//treeから出力したJSONをrequireで読み込み
var fileTreeJson = require('./file_tree.json');
var path = require('path');

//カンマの繰り返し出力のためのfunctionをStringに追加
String.prototype.repeat = function (num) {
    for (var str = ''; (this.length * num) > str.length; str += this);
    return str;
};

var parseFileList = function (level, fileNo, fileList) {
    fileList.forEach(function (file) {
        if (file.type != 'report') {
            var line = ''; 
            var type = ''; 
            if (file.type == 'file') {
                fileNo += 1;
                line += fileNo;
                type = path.extname(file.name);
            } else {
                type = 'dir';
            }   
            line += ',' + type;
            line += ','.repeat(level) + file.name;
            console.log(line);
            if (file.type == 'directory') {
                fileNo = parseFileList(level + 1, fileNo, file.contents);
            }   
        }   
    }); 
    return fileNo;
};

parseFileList(0, 0, fileTreeJson);

これを、下記のコマンドで実行する。

$ node filetree2csv.js > file_tree.csv

出力されたCSVをExcelで開き、タイトル行や罫線を整えたら、

ファイル一覧資料として使える。

Java8のJavascriptエンジンNashornでパスワード付きExcelを開く

以前Groovyで作成したパスワード付きExcelを開くスクリプトJavascriptでも 書いてみよう、ということでnode.jsで色々試してみたところ、パスワード付き Excelに対応しているライブラリが見つからなかった。 (普通にExcelを操作するだけならxlsjs等良さげなライブラリはあった)

他の手段がないかと調べてみると、Java SE 8に新JavascriptエンジンNashornが搭載され、 JavascriptからJavaのライブラリが使えるとのことだったので試してみた。

excel_decryption_test.js

var XLS_PATH= 'encrypted_file.xls';

var Biff8EncryptionKey = Java.type('org.apache.poi.hssf.record.crypto.Biff8EncryptionKey');
var WorkbookFactory = Java.type('org.apache.poi.ss.usermodel.WorkbookFactory');
var FileInputStream = Java.type('java.io.FileInputStream');

Biff8EncryptionKey.setCurrentUserPassword('<パスワード>');

var fis = new FileInputStream(XLS_PATH);
var workbook = WorkbookFactory.create(fis);
var sheet0 = workbook.getSheetAt(0);
var companyName = sheet0.getRow(4).getCell(1);
print('company Name: ' + companyName);

fis.close();

pom.xml

<project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd'>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>sample</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Maven Quick Start Archetype</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.11</version>
        </dependency>
    </dependencies>
</project>

mavenで必要なjarをダウンロードしておき、 jdkのbinフォルダに含まれる「jjs」コマンドでclasspathを指定して Javascriptファイルを指定して実行する。

$ mvn dependency:copy-dependencies
$ jjs -scripting -cp target/dependency/poi-3.11.jar:target/dependency/poi-ooxml-3.11.jar:target/dependency/poi-ooxml-schemas-3.11.jar excel_decryption_test.js

うまくいった。

nashhornにはいくつかJavascript拡張関数が追加されており、 たとえばJavaのライブラリはJava.typeという関数を呼び出すことで簡単に使える。 クラスパス指定さえもうちょっと楽にできるようになれば、もっと使い勝手はよくなるはず。

他に、Java.load関数を使えばほかのjavascriptファイルを読み込むことができる。 これを使えば、jQuery等のライブラリを使って処理することも可能だろう。

Nashornの日本語ユーザーガイド

JavascriptライブラリとJavaライブラリを組み合わせて使えるのは、 色々と夢が広がって楽しみ。 文法としてJavascriptさえ使えるようになっておけば、Nashhorn、Node.js、JScript、ブラウザJavascriptなどの 実装を使い分けることで何でもできるようになりそう。

CakePHPとjQueryで汎用的なリンククリックカウンターを作成する

ページに記載した外部リンクが何回クリックされたかを知りたかったので、 リンククリックをカウントするスクリプトを作成した。 Google Analyticsのイベントトラッキング機能の簡易版。

リンクにあらかじめ決めたCSSクラスとリンクを識別するための属性を 設定しておき、リンクがクリックされた時にAjax処理でサーバに属性情報を 送信して記録する。

サーバ側はCakePHPで作成したけど、 大したことはしていないので他の言語でも実現できるはず。 1つコントローラを作成しておけばどのページからのリンクでもカウントできる。

HTMLソース

<html>
    <head>
        <script src='//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'></script>
        <script type='text/javascript' src='/js/click_counter.js'></script>
    </head>
    <body>
        ...
        <a href='http://honjala.net/' class='click-count' data-linkname='ブログ'>ほんじゃら堂</a>
        <a href='https://twitter.com/honjala' class='click-count' data-linkname='Twitter'>Twitter</a>
        ...
    </body>
</html>

click_counter.js

$(document).ready(function () {
    (function($) {
         var ClickTrackService = {
            track: function (name, url, options) {
                var callerUrl = location.href;
                $.ajax({
                    'type': 'POST',
                    'dataType': 'json',
                    'url': '/click_tracks/track/',
                    'data': {
                        'name': name,
                        'url': url,
                        'caller_url': callerUrl
                    },
                    'success': options.success || function (data) {},
                    'error': options.error || function (xml, status, e) {}
                });
            }
        };

        $('a.click-count').live('click', function (e) {
            var linkName = $(this).attr('data-linkname');
            var url = $(this).attr('href');
            if (linkName != null &amp;&amp; linkName != '') {
                ClickTrackService.track(linkName, url);
            }
        });
    })(jQuery);
});

保存用テーブル定義

CREATE TABLE IF NOT EXISTS click_tracks(
    id integer not null auto_increment,
    name varchar(100),
    url text,
    caller_url varchar(255),
    ip varchar(20),
    created datetime,
    PRIMARY KEY (id)
) ENGINE=InnoDB;

click_tracks_controller.php

<?php
class ClickTracksController extends AppController {
    public $name = 'ClickTracks';
    public $uses = array(
        'ClickTrack',
    );  

    public function track() {
        $url = null;
        $name = null;
        $caller_url = null;
        if (array_key_exists('form', $this->params)) {
            if (array_key_exists('url', $this->params['form'])) {
                $url = $this->params['form']['url'];
            }
            if (array_key_exists('name', $this->params['form'])) {
                $name = $this->params['form']['name'];
            }
            if (array_key_exists('caller_url', $this->params['form'])) {
                $caller_url = $this->params['form']['caller_url'];
            }
        }

        $ip = $_SERVER['REMOTE_ADDR'];

        $this->ClickTrack->create();
        $track = array(
            'url' => $url,
            'name' => $name,
            'caller_url' => $caller_url,
            'ip' => $ip
        );  
        $this->ClickTrack->save($track);

        //JSONレスポンス処理
    }
}

本当はGoogle Analyticsのイベントトラッキングを使いたかったのだけど、 うまくクリックを認識してくれなかった。

jQuery MobileでiPhone用Webサイトを作成する

jQuery Mobile
http://jquerymobile.com/


いろいろはまったので、メモ。
バージョンは 1.0 ALPHA 2。

page毎にHTMLを分けて作成する

これは好みだと思うのだけど、URL直指定でそれぞれのページを呼び出せたりするようにするなら、分けた方が簡単な気がした。


構成としては、下記のような形にしてる。

<html>
<head>
    <!-- 全ページ共通のリソース読み込み -->
    <link rel="stylesheet" type="text/css" href="sample_base.css" />
    <script type="text/javascript" src="sample_base.js"></script>
  </head>
<body>
<div data-role="page" class="user-home-page">
<!-- このページ専用のリソース読み込み -->
<link rel="stylesheet" type="text/css" href="sample_user_home.css" />
<script type="text/javascript" src="sample_user_home.js"></script>
<!-- ページレイアウト定義 -->
<div data-role="header">
</div>
<div data-role="content">
</div>
<div data-role="footer">
</div>
</div>
</body>
</html>


jQuery Mobile はページ遷移時に遷移先の[data-role="page"]なタグだけを読み込むらしく、pageタグの外で定義されたcssやjsは読み込んでくれないので、pageタグ内でページ固有のリソースを読み込むようにしてる。


最初にURLを指定して呼び出したページのみ、完全なHTMLとして読み込んでくれるようなので、各ページを上記のような形にしておくことで直URL指定とページ遷移の両方に対応できるらしい。


ただ、ドキュメントを読んだところでは、JSやCSSについては1つにまとめておいて、表示するページ毎に処理を切り替えるのがオススメらしい。


pageタグの名前定義にclassを使っているけど、これはID属性が定義されているとページ遷移で呼び出した時にjQuery MobileがdivタグでラップしてIDを別途つけちゃうから。これをされるとページ遷移時とURL直指定時とでDOM構造が変わって色々面倒なのでclassを使用する。ドキュメントにも「classで指定すりゃいいよ」的なことが書いてあった。

ページ初期化処理

ページ遷移時にJSで初期化処理を行ないたい時は、$(document).ready(function () {}) ではなく、$(".ページクラス").live("pagecreate", function () {}) を使う。readyは最初のページ表示時点で呼び出し済みなので、2ページ目以降では呼び出されないっぽい。

$(".home-page").live("pagecreate", function () {
var page = $.homePage();
});

formタグに設定されたlive submitイベントが強敵

formタグにはあらかじめliveなsubmitイベントのハンドラが設定されていて、submitするとajax処理でページ遷移しようとしちゃう。

$('form').live("submit", function () { ... });


な感じで定義されてるので、特定のフォームのみsubmit処理をしないようにしたくてもうまくいかなかった。dieしたら他のページのフォームが効かなくなるし。設定($.mobile.ajaxFormsEnabled)で無効にした場合もやっぱり全フォームの送信処理が効かなくなっちゃう。


これに関してはまだ解決策は見つかっておらず、フォームを送信したくない場合はsubmit以外のイベントで処理するようにしてる。

Google AJAX Search API でシンプルにローカル検索

Google AJAX Search API
http://code.google.com/intl/ja/apis/ajaxsearch/


ドキュメントに掲載されているサンプルでは備えつけのフォームや検索結果を表示する
ようになっているのだけど、Javascript内で検索処理を実行して
結果をJSONで処理する方法もあったので、そのサンプルを掲載しておく。


jQueryも使用している。

// 地図生成
var center = new google.maps.LatLng(37.67008923368245, -223.881025375);
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 4,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// ローカル検索用サーチャーオブジェクト生成
var searcher = new google.search.LocalSearch();
// 検索範囲を設定
searcher.setCenterPoint(map.getCenter());
// 検索結果処理を定義(ここではマーカーを配置してる)
var markers = [];
searcher.setSearchCompleteCallback(self, function () {
/* このへんに既存のマーカー削除処理 */
$.each(searcher.results, function (i, result) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(result.lat), parseFloat(result.lng)),
map: map
});
result.marker = marker;
markers.push(marker);
});
});
// 検索を実行
searcher.execute('大阪城');

jQuery UI でダイアログ表示

別の記事でも書いたけど、個人で開発しているWebアプリでは、だいたいjQuery UIを使用してる。


今回はその中でもよく利用しているdialogの使い方をまとめておく。
dialog機能を使うと、割と簡単にエラーダイアログやフォーム表示用のサブウィンドウを作成することができる。
http://jqueryui.com/demos/dialog/


僕の使い方としては、あらかじめ使用するダイアログやサブウィンドウをHTML内に非表示で埋め込んでおき、
必要な時にダイアログとして表示する、という方法をとっている。
1つのファイルにまとまってると、本体のHTML、ダイアログ、サブウィンドウを区別なく編集できるので結構楽だと思う。


OKダイアログ(通知やエラー表示用)、確認ダイアログ、フォームダイアログを
それぞれ表示できるサンプルを書いておく。
よく使うOKダイアログや確認ダイアログは関数化しておくと便利。


sample.html

...
<head>
...
<link rel="stylesheet" href="/css/sunny/jquery-ui-1.8.custom.css" type="text/css" />
<link rel="stylesheet" href="/css/sample.css" type="text/css" />
<script type="text/javascript"> google.load("jquery", "1.4.2"); </script>
<script type="text/javascript"> google.load("jqueryui", "1.8.0"); </script>
<script type="text/javascript" src="/js/sample.js"></script>
...
</head>
<body>
...
<a href="#" id="show-error-dialog-btn">エラーダイアログを表示</a>
<a href="#" id="show-confirm-dialog-btn">確認ダイアログを表示</a>
<a href="#" id="show-form-dialog-btn">フォームダイアログを表示</a>
...
<div class="dialog" id="delete-confirm-dialog" title="メッセージ削除確認">
<div class="ui-state-highlight">
<span class="ui-icon ui-icon-info"></span>
本当にメッセージを削除してもよろしいですか?
</div>
</div>
<div class="dialog" id="message-update-failed-dialog" title="サーバエラー">
<div class="ui-state-error">
<span class="ui-icon ui-icon-alert"></span>
メッセージの更新に失敗しました
</div>
</div>
<div class="dialog" id="message-edit-dialog" title="メッセージを編集">
<form id="message-edit-form" method="POST">
<input type="text" id="message-field" />
</form>
</div>
...


sample.css

.dialog {
display: none;
}


sample.js

var Page = {
show_ok_dialog: function (dialog_id) {
$(dialog_id).dialog({
bgiframe: true,
modal: true,
buttons: {
"OK": function () {
$(this).dialog("destroy");
}
}
});
},
show_confirm_dialog: function (dialog_id, ok_func, cancel_func) {
$(dialog_id).dialog({
bgiframe: true,
modal: true,
buttons: {
"OK": ok_func,
"キャンセル": cancel_func
}
});
}
};
$(document).ready(function () {
$("#show-error-dialog-btn").click(function (e) {
e.preventDefault();
Page.show_ok_dialog("#message-update-failed-dialog");
});
$("#show-confirm-dialog-btn").click(function (e) {
e.preventDefault();
Page.show_confirm_dialog("#delete-confirm-dialog",
function () {
// OKボタンをクリックした時の処理
...
$(this).dialog("destroy"); // ダイアログを削除
},
function () {
// キャンセルボタンをクリックした時の処理
...
$(this).dialog("destroy");
}
);
});
$("#show-form-dialog-btn").click(function (e) {
e.preventDefault();
$("#message-edit-dialog").dialog({
bgiframe: true,
modal: true,
buttons: {
"更新": function () {
// 更新ボタンを押した時の処理
var message = $("#message-field").val(); // 同じHTML内なのでフォームの値も取得できる
// サーバに送信したり処理したり
...
$(this).dialog("destroy");
},
"キャンセル": function () {
// キャンセルボタンを押した時の処理
...
$(this).dialog("destroy");
}
}
});
});
});