====== Titanium Mobileに神の火を! - Prometheus.js ======
コメントと更新履歴は[[http://0-oo.net/log/category/javascript/prometheus/|Prometheus Archive - ゼロと無限の間のログ]]でどうぞ。
{{:javascript:fire_beiz.jp_s05820.jpg?nolink&|}}
iPhoneアプリもAndroidアプリもJavaScriptで作れてしまう[[http://www.appcelerator.com/products/titanium-mobile-application-development/|Titanium Mobile]]。便利なのだがその構成は良くも悪くもきちんと体系だっている。(JavaやYUIを連想させる?)
そこで、もう少しだけ手軽にTitamium Mobileを使えるように、Titaniumをラップするライブラリを作ってみた。その名も、**Prometheus.js**。
===== ライセンス =====
MITライセンス
===== 使用例 =====
==== UIを生成する ====
=== 全てのUIを、本家Titaniumよりちょっと短いコードで生成できる ===
// Titaniumの場合
var win = Ti.UI.createWindow();
// Prometheus.jsの場合
var win = Pr.window();
=== UI生成時のパラメータはTitaniumと同様に渡すことができる ===
var label = Pr.label({text:"ラベルだよ", fontWeight:"bold"});
=== ラベルとボタンは、パラメータが表示文字列のみなら、それを文字列として渡すことができる ===
Hashにしない分、ちょっと短くて済む
// Titaniumの場合
var label = Ti.UI.createLabel({text:"ラベルだよ"});
// Prometheus.jsの場合
var label = Pr.label("ラベルだよ");
=== ボタンやダイアログは、第2匹数としてonclickのイベントハンドラーを渡すことができる ===
// Titaniumの場合
var button = Ti.UI.creatButton({title:"押してみる?"});
button.addEventListener("click", function() { alert("押しちゃったね"); });
// Prometheus.jsの場合
var button = Pr.button("押してみる?", function() { alert("押しちゃったね"); });
=== Viewは第2匹数としてView上に載せるUIを渡すことができる ===
var view = Pr.view({}, Pr.label("viewに載るよ"));
// 複数の場合は配列で渡す
var view = Pr.view({}, [Pr.label("ラベル1"), Pr.label("ラベル2")]);
=== パラメータの共通の初期値を指定できる ===
見た目のデザイン等を後から一括して変えたい時に便利
// ラベルは全て太字にする場合
Pr.params.label.fontWeight = "bold";
この後にPrometheus.jsで生成したlabelは全てfontWeightがboldになる
また、いくつかのUIはデフォルトで使いやすいように初期値が設定されている
=== これらを合わせると、Titaniumに比べてこれぐらいコードが短くなる ===
// Titaniumの場合
var win = Ti.UI.createWindow({backgroundColor:"#000", layout:"vertical"});
var view = Ti.UI.createView({layout:"horizontal"});
win.add(view);
view.add(Ti.UI.createLabel({text:"ラベル1", fontWeight:"bold"}));
view.add(Ti.UI.createLabel({text:"ラベル2", fontWeight:"bold"}));
var button = Ti.UI.createButton({title:"ボタン"});
button.addEventListener("click", function() {
Ti.UI.createAlertDialog(message:"こんにちはこんにちは!", buttonNames:["OK"]).show();
});
win.add(button);
// Prometheus.jsの場合
var win = Pr.win();
Pr.params.label.fontWeight = "bold";
win.add(Pr.view({}, [Pr.label("ラベル1"), Pr.label("ラベル2")]);
win.add(Pr.button("ボタン", function() {
pr.alertDialog(message:"こんにちはこんにちは!").show();
}));
==== DBにアクセスする ====
ローカルのSQLiteに簡単にアクセスできる\\
DatabaseやResultsetのclose()もしてくれるので楽ちん
var db = Pr.db("dbName");
// テーブル生成(該当のテーブルが既にある場合は無視される)
db.table("people(id INTEGER, name TEXT, email TEXT)");
// SELECT(パラメータは、取得列、テーブル名、取得条件、その他)
var rows = db.select("id, name", "people", { name: "Taro", email: "taro@example.com" }, "ORDER BY id");
// 戻り値はResultsetオブジェクトではなく配列なので扱いやすい
for (var i = 0; i < rows; i++) {
var id = rows[i]["id"];
}
// INSERT(パラメータは、テーブル名、登録データ。戻り値は(あれば)連番のキー値)
var id = db.insert("poeple", { id: 1, name: "Taro" });
// UPDATE(パラメータは、テーブル名、更新値、更新条件。戻り値は更新レコード数)
var count = db.update("people", { name: "Jiro", email: "jiro@example.com" }, { id: 2, name: "Taro" });
// DELETE(パラメータは、テーブル名、削除条件。戻り値は削除レコード数)
var count = db.remove("people", { id: 2, name: "Taro" });
// メソッド名が"delete"でないので注意!
// その他のSQLを実行したい場合はTi.Database#execute()と同様に
var results = db.execute(sql, params);
while(rows.isValidRow()){
var something = rows.field(0);
// 略
rows.next();
}
// この場合は勝手にclose()してくれないので注意
results.close();
==== HTTPで通信する ====
Ti.Network.createHTTPClientによる一連の処理のショートカット
Pr.http("POST", "http://www.example.com/", {q:"hoge"}, function(json) {
// サーバからのレスポンスのJSONをHash化したものが渡される
});
JSONにしたくない場合は、第6引数で"TEXT"を指定すればよい
==== ディスプレイのサイズを取得する ====
var w = Pr.width();
var h = Pr.height();
===== ソースコード =====
Promethus.jsを使いたい場合は(ダウンロードできるファイルを用意してないので)下記のソースコードをコピーして使ってください
/**
* Prometheus.js - The library for Titanium Mobile
*
* @see http://0-oo.net/sbox/javascript/prometheus
* @version 0.2.0
* @copyright 2012 dgbadmin@gmail.com
* @license http://0-oo.net/pryn/MIT_license.txt (The MIT license)
*
* See also the references of Titanium Mobile
* @see http://tidocs.com/mobile/latest/
* @see http://code.google.com/p/titanium-mobile-doc-ja/wiki/toc
*/
var Prometheus = {};
var Pr = Prometheus;
Ti.UI.setBackgroundColor('#000');
/*************************************************
* The wrapper object of Ti.Database
************************************************/
/**
* Get a wrapper of a database
* @param String dbName
* @return Object
*/
Pr.db = function(dbName) {
var wrapper = {dbName:dbName, db:null};
/**
* Execute SQL (It is the wrapper of Ti.Database.execute())
* @param String sql
* @param Object (Optional) value(s) of place holder(s)
* @return Object Ti.Database.Resultset or something Ti.Database.execute() returns
*/
wrapper.execute = function() {
if (!this.db) {
this.db = Ti.Database.open(this.dbName);
this.db.execute.apply = Function.prototype.apply;
}
return this.db.execute.apply(this.db, arguments);
};
/**
* Close the database
*/
wrapper.close = function() {
this.db.close();
this.db = null;
};
/**
* Create a table, if it does not exist
* @param String sql SQL to create a table
*/
wrapper.table = function(sql) {
this.execute('CREATE TABLE IF NOT EXISTS ' + sql);
this.close();
};
/**
* Select columns
* @param String columns Columns to select
* @param String from Name of a table
* @param Hash where (Optional) Conditions to select
* @param String ohters (Optional) SQL after WHERE
* @return Array Results
*/
wrapper.select = function(columns, from, where, others) {
var params = this._where(where || {});
params[0] = "SELECT " + columns + " FROM " + from + params[0] + " " + (others || "");
var arr = this.rows2arr(this.execute.apply(this, params));
this.close();
return arr;
};
/**
* Insert a row
* @param String table Name of a table
* @param Hash values Values to insert
* @return Number ID of the last inserted row
*/
wrapper.insert = function(table, values) {
var cols = [];
var vals = [];
var params = [""];
for (var col in values) {
cols.push(col);
vals.push("?");
params.push(values[col]);
}
params[0] = "INSERT INTO " + table + "(" + cols.join(",") + ") VALUES(" + vals.join(",") + ")";
this.execute.apply(this, params);
var rowId = this.db.lastInsertRowId;
this.close();
return rowId;
};
/**
* Update colulmns
* @param String table Name of a table
* @param Hash set Values to update
* @param Hash where (Optional) Conditions to update
* @return Number the number of the updated rows
*/
wrapper.update = function(table, set, where) {
var sets = [];
var params = [""];
for (var col in set) {
sets.push(col + " = ?");
params.push(set[col]);
}
var cond = this._where(where || {});
params[0] = "UPDATE " + table + " SET " + sets.join(",") + cond.shift();
this.execute.apply(this, params.concat(cond));
var affected = this.db.rowsAffected;
this.close();
return affected;
};
/**
* Delete rows
* @param String table Name of a table
* @param Hash where (Optional) Conditions to delete
* @return Number The number of the deleted rows
*/
wrapper.remove = function(table, where) {
var params = this._where(where || {});
params[0] = "DELETE FROM " + table + params[0];
this.execute.apply(this, params);
var affected = this.db.rowsAffected;
this.close();
return affected;
};
/**
* Build a SQL of "WHERE"
* @param Hash hash
* @return Array SQL and values of placeholders
*/
wrapper._where = function(hash) {
var sql = [];
var arr = [""];
for (var key in hash) {
sql.push(key + " = ?");
arr.push(hash[key]);
}
if (sql.length) {
arr[0] = " WHERE " + sql.join(" AND ");
}
return arr;
};
/**
* Convert a Ti.Database.Resultset to an array
*/
wrapper.rows2arr = function(rows) {
var arr = [];
while(rows.isValidRow()){
var row = {}
for (var i = 0, cnt = rows.fieldCount; i < cnt; i++) {
row[rows.fieldName(i)] = rows.field(i);
}
arr.push(row);
rows.next();
}
rows.close();
return arr;
};
return wrapper;
};
/*************************************************
* The utility functions
************************************************/
/**
* Send a HTTP request and get a response
* @param String httpMethod "GET" or "POST"
* @param String url
* @param Hash params
* @param Function onload
* @param Function onerror (Optioanl)
* @param String format (Optioanl) "TEXT" or "JSON"(default)
*/
Pr.http = function(httpMethod, url, params, onload, onerror, format) {
var http = Ti.Network.createHTTPClient({
onload: function() {
var res;
switch (format) {
case "TEXT":
res = this.responseText;
default:
res = JSON.parse(this.responseText);
}
onload(res);
},
onerror: onerror || function(error){
Pr.alertDialog({title:"Error", message:error}).show();
}
});
http.open(httpMethod, url);
http.send(params || {});
};
/**
* Get width of the display
* @return Number
*/
Pr.width = function() {
return Ti.Platform.displayCaps.platformWidth;
};
/**
* Get height of the display
* @return Number
*/
Pr.height = function() {
return Ti.Platform.displayCaps.platformHeight;
};
/**
* Merge hashes
* @param Hash data1
* @param Hash data2
* @return Hash
*/
Pr.merge = function(data1, data2) {
var dst = {};
if (data1) {
for (var i in data1) {
dst[i] = data1[i];
}
}
if (data2) {
for (var j in data2) {
dst[j] = data2[j];
}
}
return dst;
};
/**
* Add a click listener
* @param Object obj
* @param Function onclick
* @return Object
*/
Pr.clickable = function(obj, onclick) {
if (onclick) {
obj.addEventListener("click", onclick);
}
return obj;
};
/*************************************************
* The default parameters of UIs
************************************************/
Pr.params = {
ui2DMatrix: {}, // With the prefix "ui"
ui3DMatrix: {}, // With the prefix "ui"
activityIndicator:{},
alertDialog:{buttonNames:["OK"]},
animation:{},
button:{},
buttonBar:{},
coverFlowView:{},
dashboardItem:{},
dashboardView:{},
emailDialog:{},
imageView:{},
label:{},
optionDialog:{},
picker:{},
pickerColumn:{},
pickerRow:{},
progressBar:{},
scrollView:{},
scrollableView:{},
searchBar:{},
slider:{},
uiSwitch:{}, // With the prefix "ui"
tab:{},
tabGroup:{},
tabbedBar:{},
tableView:{},
tableViewRow:{},
tableViewSection:{},
textArea:{},
textField:{passwordMask:false},
toolbar:{},
view:{layout:"horizontal"}, // "vertical" or "horizontal" or false
webView:{backgroundColor:"#000"},
window:{backgroundColor:"#000", layout:"vertical"}
};
/*************************************************
* The creaters of UIs
************************************************/
/**
* Create a 2dMatrix
* @param Hash params
* @return Object
*/
Pr.ui2DMatrix = function(params) {
return Ti.UI.create2DMatrix(Pr.merge(Pr.params.ui2DMatrix, params));
};
/**
* Create a ui3DMatrix
* @param Hash params
* @return Object
*/
Pr.ui3DMatrix = function(params) {
return Ti.UI.create3DMatrix(Pr.merge(Pr.params.ui3DMatrix, params));
};
/**
* Create an activityIndicator
* @param Hash params
* @return Object
*/
Pr.activityIndicator = function(params) {
return Ti.UI.createActivityIndicator(Pr.merge(Pr.params.activityIndicator, params));
};
/**
* Create an alertDialog
* @param Hash params
* @param Function onclick (Optional)
* @return Object
*/
Pr.alertDialog = function(params, onclick) {
return Pr.clickable(Ti.UI.createAlertDialog(Pr.merge(Pr.params.alertDialog, params)), onclick);
};
/**
* Create an animation
* @param Hash params
* @return Object
*/
Pr.animation = function(params) {
return Ti.UI.createAnimation(Pr.merge(Pr.params.animation, params));
};
/**
* Create a button
* @param Hash params
* @param Function onclick (Optional)
* @return Object
*/
Pr.button = function(params, onclick) {
if (typeof(params) == "string") {
params = {title:params};
}
return Pr.clickable(Ti.UI.createButton(Pr.merge(Pr.params.button, params)), onclick);
};
/**
* Create a buttonBar
* @param Hash params
* @return Object
*/
Pr.buttonBar = function(params) {
return Ti.UI.createButtonBar(Pr.merge(Pr.params.buttonBar, params));
};
/**
* Create a coverFlowView
* @param Hash params
* @return Object
*/
Pr.coverFlowView = function(params) {
return Ti.UI.createCoverFlowView(Pr.merge(Pr.params.coverFlowView, params));
};
/**
* Create a dashboardItem
* @param Hash params
* @return Object
*/
Pr.dashboardItem = function(params) {
return Ti.UI.createDashboardItem(Pr.merge(Pr.params.dashboardItem, params));
};
/**
* Create a dashboardView
* @param Hash params
* @return Object
*/
Pr.dashboardView = function(params) {
return Ti.UI.createDashboardView(Pr.merge(Pr.params.dashboardView, params));
};
/**
* Create an emailDialog
* @param Hash params
* @return Object
*/
Pr.emailDialog = function(params) {
return Ti.UI.createEmailDialog(Pr.merge(Pr.params.emailDialog, params));
};
/**
* Create an imageView
* @param Hash params
* @return Object
*/
Pr.imageView = function(params) {
return Ti.UI.createImageView(Pr.merge(Pr.params.imageView, params));
};
/**
* Create a label
* @param Hash params
* @return Object
*/
Pr.label = function(params) {
if (typeof(params) == "string") {
params = {text:params};
}
return Ti.UI.createLabel(Pr.merge(Pr.params.label, params));
};
/**
* Create a optionDialog
* @param Hash params
* @param Function onclick (Optional)
* @return Object
*/
Pr.optionDialog = function(params, onclick) {
return Pr.clickable(Ti.UI.createOptionDialog(Pr.merge(Pr.params.optionDialog, params)), onclick);
};
/**
* Create a picker
* @param Hash params
* @return Object
*/
Pr.picker = function(params) {
return Ti.UI.createPicker(Pr.merge(Pr.params.picker, params));
};
/**
* Create a pickerColumn
* @param Hash params
* @return Object
*/
Pr.pickerColumn = function(params) {
return Ti.UI.createPickerColumn(Pr.merge(Pr.params.pickerColumn, params));
};
/**
* Create a pickerRow
* @param Hash params
* @return Object
*/
Pr.pickerRow = function(params) {
return Ti.UI.createPickerRow(Pr.merge(Pr.params.pickerRow, params));
};
/**
* Create a progressBar
* @param Hash params
* @return Object
*/
Pr.progressBar = function(params) {
return Ti.UI.createProgressBar(Pr.merge(Pr.params.progressBar, params));
};
/**
* Create a scrollView
* @param Hash params
* @return Object
*/
Pr.scrollView = function(params) {
return Ti.UI.createScrollView(Pr.merge(Pr.params.scrollView, params));
};
/**
* Create a scrollableView
* @param Hash params
* @return Object
*/
Pr.scrollableView = function(params) {
return Ti.UI.createScrollableView(Pr.merge(Pr.params.scrollableView, params));
};
/**
* Create a searchBar
* @param Hash params
* @return Object
*/
Pr.searchBar = function(params) {
return Ti.UI.createSearchBar(Pr.merge(Pr.params.searchBar, params));
};
/**
* Create a slider
* @param Hash params
* @return Object
*/
Pr.slider = function(params) {
return Ti.UI.createSlider(Pr.merge(Pr.params.slider, params));
};
/**
* Create a uiSwitch
* @param Hash params
* @return Object
*/
Pr.uiSwitch = function(params) {
return Ti.UI.createSwitch(Pr.merge(Pr.params.uiSwitch, params));
};
/**
* Create a tab
* @param Hash params
* @return Object
*/
Pr.tab = function(params) {
return Ti.UI.createTab(Pr.merge(Pr.params.tab, params));
};
/**
* Create a tabGroup
* @param Hash params
* @return Object
*/
Pr.tabGroup = function(params) {
return Ti.UI.createTabGroup(Pr.merge(Pr.params.tabGroup, params));
};
/**
* Create a tabbedBar
* @param Hash params
* @return Object
*/
Pr.tabbedBar = function(params) {
return Ti.UI.createTabbedBar(Pr.merge(Pr.params.tabbedBar, params));
};
/**
* Create a tableView
* @param Hash params
* @return Object
*/
Pr.tableView = function(params) {
return Ti.UI.createTableView(Pr.merge(Pr.params.tableView, params));
};
/**
* Create a tableViewRow
* @param Hash params
* @return Object
*/
Pr.tableViewRow = function(params) {
return Ti.UI.createTableViewRow(Pr.merge(Pr.params.tableViewRow, params));
};
/**
* Create a tableViewSection
* @param Hash params
* @return Object
*/
Pr.tableViewSection = function(params) {
return Ti.UI.createTableViewSection(Pr.merge(Pr.params.tableViewSection, params));
};
/**
* Create a textArea
* @param Hash params
* @return Object
*/
Pr.textArea = function(params) {
return Ti.UI.createTextArea(Pr.merge(Pr.params.textArea, params));
};
/**
* Create a textField
* @param Hash params
* @return Object
*/
Pr.textField = function(params) {
return Ti.UI.createTextField(Pr.merge(Pr.params.textField, params));
};
/**
* Create a toolbar
* @param Hash params
* @return Object
*/
Pr.toolbar = function(params) {
return Ti.UI.createToolbar(Pr.merge(Pr.params.toolbar, params));
};
/**
* Create a view
* @param Hash params
* @param Object or Array children (Optional) Children of a webView
* @return Object
*/
Pr.view = function(params, children) {
var view = Ti.UI.createView(Pr.merge(Pr.params.view, params));
if (children) {
if (children instanceof Array) {
for (var i = 0; i < children.length; i++) {
view.add(children[i]);
}
} else {
view.add(children);
}
}
return view;
};
/**
* Create a webView
* @param Hash params
* @return Object
*/
Pr.webView = function(params) {
return Ti.UI.createWebView(Pr.merge(Pr.params.webView, params));
};
/**
* Create a window
* @param Hash params
* @return Object
*/
Pr.window = function(params) {
return Ti.UI.createWindow(Pr.merge(Pr.params.window, params));
};