Cordova の上で jQuery Mobile と RequireJS を組み合わせて使えるか試した。
一応動いた(ただし確認したのは Android だけ)。
データベースのところ特に力入れた。
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<link rel="stylesheet" type="text/css" href="css/jquery.mobile.min.css" />
<title>Hello World</title>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>header</h1>
</div>
<div role="main">
<p id="console">
</p>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/lib/require.js" data-main="js/index"></script>
</body>
</html>
普通に require.js
を読み込んで、 data-main
に index.js
を指定。
index.js
requirejs.config({
paths: {
'jquery': 'lib/jquery.min',
'jquery-mobile': 'lib/jquery.mobile.min'
}
});
require(['root', 'database', 'jquery-mobile'], function(root) {
root.deviceready(function() {
root.log('Hello Cordova with RequireJS!!');
root.db.readTransaction(function(tx) {
root.deferredTransaction(tx)
.first('SELECT * FROM SAMPLE_TABLE')
.done(function(exec, result) {
for (var i=0; i<result.rows.length; i++) {
var row = result.rows.item(i);
root.log('[database rows] id=' + row.ID + ', message=' + row.MESSAGE);
}
});
});
});
});
先頭で jQuery
と jQuery Mobile
のパスを定義して、
require()
でデータベースの初期化をしているモジュール(database
)と jquery-mobile
を依存対象として定義。
root.js
define(['jquery'], function($) {
return {
log: function(message) {
// weinre console is not work!!
$('#console').append(message + '<br>');
// console.log(message);
},
deviceready: function(callback) {
var root = this;
document.addEventListener('deviceready', function() {
try {
callback();
} catch (e) {
root.log('error : ' + e);
}
});
},
deferredTransaction: function(transaction) {
var root = this;
exec.first = executeSql;
return exec;
function exec(sql, params) {
return function(exec, result) {
return exec.first(sql, params);
};
}
function executeSql(sql, params) {
var d = new $.Deferred();
root.log('execute sql : ' + sql + ', params=' + params);
transaction.executeSql(
sql,
params || [],
function(tx, result) {
d.resolve(root.deferredTransaction(tx), result);
},
function(tx, result) {
d.reject(root.deferredTransaction(tx), result);
}
);
return d.promise();
}
}
};
});
root
は、共通処理とかをまとめたオブジェクトを定義したモジュール。
標準のデータベース API はコールバック地獄必至なので、 jQuery の Deferred を使ってシンプルに書けるように頑張った(deferredTransaction()
)。
database.js
define(['root', 'jquery'], function(root, $) {
root.deviceready(function() {
root.log('initializing database...');
root.db = openDatabase('sampledb', '', 'Sample Database', 1024 * 1024 * 10);
root.db.transaction(
function(tx) {
var exec = root.deferredTransaction(tx);
exec.first('DROP TABLE IF EXISTS SAMPLE_TABLE')
.then(exec('CREATE TABLE SAMPLE_TABLE (ID INTEGER PRIMARY KEY, MESSAGE)'))
.then(exec('INSERT INTO SAMPLE_TABLE (MESSAGE) VALUES (?)', ['Hoge']))
.then(exec('INSERT INTO SAMPLE_TABLE (MESSAGE) VALUES (?)', ['Fuga']))
.then(exec('INSERT INTO SAMPLE_TABLE (MESSAGE) VALUES (?)', ['Piyo']))
.then(exec('SELECT * FROM SAMPLE_TABLE'))
.then(function(exec, result) {
root.log('count=' + result.rows.length);
return exec.first('DELETE FROM SAMPLE_TABLE WHERE MESSAGE=?', ['Fuga']);
})
.done(function() {
root.log('success to initialize database');
})
.fail(function(exec, result) {
root.log('fail to initialize database : ' + JSON.stringify(result));
});
},
function(error) {
root.log('fail to initialize database');
});
});
});
画面の様子
結論: Deferred って素晴らしい。