2015-04-19 16:46:59 +02:00

794 lines
31 KiB
JavaScript

(function($) {
$(document).ready(function(){
var match_count = 0, match_page_size=5, match_offset = 0,
cobalt_visible = false, cobalt_out_visible = false,
matches = [], match_idx = 0, handler_idx = 0,
current_text, current_action_text='', handler, item, actions, match_count=0,
plugins = {}, plugin_names=[], catalogs = {}, global_handlers = [], handlers = {},
update_queue = [], required_updates = [];
var log_error = function(message, err) {
if (typeof(window.console) != 'undefined') {
console.error(message);
if(err) {
console.log(err);
}
}
};
var log_msg = function(message) {
if (typeof(window.console) != 'undefined') {
console.log(message);
}
};
var db = null;
// Initialize database
if (!db && typeof(openDatabase)=='function') {
try {
db = openDatabase('cobalt', '1.0', 'Cobalt Database', 204800);
}
catch (err) {
if (err.name === 'SECURITY_ERR') {
log_msg(Drupal.t('Failed to open database using the Web SQL Database API due to a security-related error.'));
}
else {
log_msg(Drupal.t('Failed to open database using the Web SQL Database API.'));
}
}
}
if (!db) {
log_error(Drupal.t('Could not open a client-side database. Cobalt requires a browser that implements the Web SQL Database API.'));
return;
}
var nullDataHandler = function(transaction, results) { };
var current_state = function() {
if (typeof(Drupal.settings.cobalt) != 'undefined' &&
typeof(Drupal.settings.cobalt.state) != 'undefined') {
return Drupal.settings.cobalt.state;
}
else {
return 0;
}
};
// Initialize Cobalt
var cobalt = {
'dbErrorHandler': function(transaction, error)
{
$(document).trigger('cobalt-db-error');
if (window.console) {
console.error(error.message+' (Code: '+error.code+')');
}
return false;
},
'registerPlugin': function(name, plugin) {
plugin_names.push(name);
plugins[name] = plugin;
if(typeof(plugin['catalogs'])!='undefined') {
for(var c_name in plugin.catalogs) {
catalogs[c_name] = plugin.catalogs[c_name];
}
}
if(typeof(plugin['handlers'])!='undefined') {
var h_len = plugin.handlers.length;
for(var i=0; i<h_len; i++) {
register_handler(plugin.handlers[i]);
}
}
},
'catalogUpdated': function(catalog, updated) {
if (typeof(updated)=='undefined') {
updated = new Date().getTime();
}
db.transaction(function (transaction) {
transaction.executeSql("UPDATE catalogs SET updated=?, state=? WHERE name = ?;", [ updated, Drupal.settings.cobalt.state, catalog ], nullDataHandler,cobalt.dbErrorHandler);
});
},
'emptyCatalog': function(name) {
db.transaction(function (transaction) {
transaction.executeSql("DELETE FROM entries WHERE catalog=?;", [ name ], nullDataHandler,cobalt.dbErrorHandler);
});
},
'addKeyBinding': function(binding, catalog, id, handler, active, state) {
if (typeof(state)=='undefined') {
state = current_state();
}
if (typeof(active)=='undefined') {
active = 1;
}
bind_key(binding, catalog, id, handler);
db.transaction(function (transaction) {
transaction.executeSql("INSERT OR REPLACE INTO key_bindings(binding, catalog, id, handler, active, state) VALUES(?,?,?,?,?,?);", [ binding, catalog, id, handler, active, state ], nullDataHandler,cobalt.dbErrorHandler);
});
},
'loadEntry': function(catalog, id, callback) {
var state = current_state();
db.transaction(function (transaction) {
transaction.executeSql("SELECT * FROM entries WHERE catalog=? AND id=? AND state=?;", [ catalog, id, state ], function(transaction, results) {
var item = null;
if (results.rows.length) {
item = results.rows.item(0);
item.information = JSON.parse(item.data);
}
callback(item);
},cobalt.dbErrorHandler);
});
},
'deleteEntry': function(catalog, id) {
db.transaction(function (transaction) {
transaction.executeSql("DELETE FROM entries WHERE catalog=? AND id=?;", [ catalog, id ], nullDataHandler,cobalt.dbErrorHandler);
});
},
'addTemporaryEntry': function(id, name, information, classname) {
cobalt.addEntry({id:id, name:name, information:information, catalog:'*temporary*', classname:classname, active:1, state:current_state()});
},
'addEntry': function(data) {
if (typeof(data.state)=='undefined') {
data.state = current_state();
}
if (typeof(data.active)=='undefined') {
data.active = 1;
}
if (typeof(data.extra)=='undefined') {
data.extra = '';
}
db.transaction(function (transaction) {
transaction.executeSql("INSERT OR REPLACE INTO entries(id, name, extra, data, catalog, data_class, state, active) VALUES(?,?,?,?,?,?,?,?);", [data['id'], data['name'], data.extra, JSON.stringify(data.information), data.catalog, data.classname, data.state, data.active], nullDataHandler,cobalt.dbErrorHandler);
});
},
'actionCandidates': function(item, callback) {
action_candidates(item, callback);
},
'showHtml': function(html) {
if (typeof(html) == 'string') {
cobalt_output.html(html);
}
else {
cobalt_output.empty().append(html);
}
if (!cobalt_out_visible) {
toggle_output();
}
}
};
if (typeof(Drupal.settings.cobalt) != 'undefined' && typeof(Drupal.settings.cobalt.update) != 'undefined') {
cobalt.updateVersion = function(transaction, name, version) {
transaction.executeSql('UPDATE versions SET version=? WHERE name=?', [version, name], nullDataHandler,cobalt.dbErrorHandler);
};
$(document).trigger('cobalt-update', [cobalt, db, Drupal.settings.cobalt.update]);
return;
}
var register_handler_use = function(handler, item, transaction) {
transaction.executeSql("INSERT OR IGNORE INTO handler_usage_data(catalog, id, handler, weight) VALUES(?,?,?,?)",
[item.catalog, item.id, handler.id, 0], nullDataHandler, cobalt.dbErrorHandler);
transaction.executeSql("UPDATE handler_usage_data SET weight=weight+1 WHERE catalog=? AND id=? AND handler=?",
[item.catalog, item.id, handler.id], nullDataHandler, cobalt.dbErrorHandler);
if (item.id) {
handler.weight++;
register_handler_use(handler, {id:0, catalog: ''}, transaction);
}
};
var register_use = function(text, item, handler) {
db.transaction(function (transaction) {
register_handler_use(handler, item, transaction);
transaction.executeSql("UPDATE usage_data SET last=null WHERE last = 1", [], nullDataHandler, cobalt.dbErrorHandler);
if (item.weight == null) {
// IGNORE in the rare event a handler that don't refresh the page
// (e.g "show") is used multiple times and the weight initially was null.
transaction.executeSql("INSERT OR IGNORE INTO usage_data(catalog, id, weight, abbreviation, last) VALUES(?,?,?,?,?)",
[item.catalog, item.id, 1, text, 1], nullDataHandler,cobalt.dbErrorHandler);
}
else {
transaction.executeSql("UPDATE usage_data SET weight=weight+1, abbreviation=?, last=1 WHERE catalog=? AND id=?",
[text, item.catalog, item.id], nullDataHandler,cobalt.dbErrorHandler);
}
});
};
var register_handler = function(handler) {
if (typeof(handler['data_class'])=='undefined') {
handler['data_class'] = null;
}
handler.weight = 0;
handler.context_weight = 0;
// Get the weight of the handler
db.transaction(function (transaction) {
transaction.executeSql("SELECT weight FROM handler_usage_data WHERE catalog='' AND handler=?",
[handler.id], function(transaction, results) {
if (results.rows.length) {
handler.weight = results.rows.item(0).weight;
}
});
});
if (!handler['data_class']) {
global_handlers.push(handler);
}
else {
if (!handlers[handler.data_class]) {
handlers[handler.data_class] = [];
}
handlers[handler.data_class].push(handler);
}
};
$(document).trigger('cobalt-load', cobalt);
cobalt.registerPlugin('cobalt', {
'version': 1,
'handlers': [
{
'id': 'cobalt_show',
'name': Drupal.t('Show'),
'handler': function(text, item) {
cobalt.showHtml('<h2>' + item.name + '</h2>' +
Drupal.t('text') + ': <i>' + text + '</i><br/>' +
Drupal.t('id') + ': ' + item.id + '<br/>' +
Drupal.t('catalog') + ': ' + item.catalog + '<br/>' +
Drupal.t('class') + ': ' + item.data_class + '<br/>' +
Drupal.t('data') + ': ' + item.data + '<br/>' +
Drupal.t('weight') + ': ' + item.weight);
}
},
{
'id': 'cobalt_abbrev',
'name': Drupal.t('Assign shortcut'),
'handler': function(text, item) {
cobalt.actionCandidates(item, function(cand) {
var out = $('<div class="shortcut-add"><h2>' + item.name + '</h2>' +
Drupal.t('The keys !input should trigger the action:', {'!input': '<input class="key-combo" type="text" value="Ctrl+"/>'}) +
'<br/> <select class="action-select"></select>' +
'<p><button class="ok">' + Drupal.t('Ok') + '</button></p></div>');
var actions = $(out).find('.action-select');
var key_combo = $(out).find('.key-combo').css('width',50);
var cand_count = cand.length;
for(var i=0; i<cand_count; i++) {
actions.append('<option value="' + cand[i].id + '">' + cand[i].name + '</option>');
}
$(out).find('button.ok').bind('click',function(){
toggle_output('hide');
cobalt.addKeyBinding(key_combo.val(), item.catalog, item.id, actions.val());
});
cobalt.showHtml(out);
key_combo.focus();
});
}
}
]
});
db.transaction(function (transaction) {
transaction.executeSql('CREATE TABLE IF NOT EXISTS versions(' +
'name TEXT NOT NULL, version INTEGER NOT NULL DEFAULT 0, ' +
'CONSTRAINT pk_versions PRIMARY KEY(name));', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE TABLE IF NOT EXISTS entries(' +
'catalog TEXT NOT NULL, id TEXT NOT NULL, name TEXT NOT NULL, extra TEXT DEFAULT "", data TEXT NOT NULL DEFAULT "", data_class TEXT NOT NULL, ' +
'state INTEGER NOT NULL DEFAULT 0, active INTEGER NOT NULL DEFAULT 1, ' +
'CONSTRAINT pk_entries PRIMARY KEY(catalog, id));', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('DELETE FROM entries WHERE catalog=?', ['*temporary*'], nullDataHandler, cobalt.dbErrorHandler);
transaction.executeSql('CREATE TABLE IF NOT EXISTS key_bindings(' +
'binding TEXT NOT NULL, catalog TEXT NOT NULL, id TEXT NOT NULL, handler TEXT NOT NULL, ' +
'state INTEGER NOT NULL DEFAULT 0, active INTEGER NOT NULL DEFAULT 1, ' +
'CONSTRAINT pk_bindings PRIMARY KEY(binding, state));', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE TABLE IF NOT EXISTS usage_data(catalog TEXT NOT NULL, id TEXT NOT NULL, ' +
'weight INTEGER NOT NULL DEFAULT 0, abbreviation TEXT NOT NULL DEFAULT "", last INTEGER, ' +
'CONSTRAINT pk_usage_data PRIMARY KEY(catalog, id));', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE TABLE IF NOT EXISTS handler_usage_data(catalog TEXT NOT NULL, id TEXT NOT NULL, ' +
'handler TEXT NOT NULL, weight INTEGER NOT NULL DEFAULT 0,' +
'CONSTRAINT pk_handler_usage_data PRIMARY KEY(catalog, id, handler));', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE INDEX IF NOT EXISTS idx_entries_catalog ON entries(catalog);', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE INDEX IF NOT EXISTS idx_entries_abbreviation ON usage_data(abbreviation);', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE INDEX IF NOT EXISTS idx_entries_active ON entries(active DESC);', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE INDEX IF NOT EXISTS idx_entries_weight ON usage_data(weight DESC);', [], nullDataHandler,cobalt.dbErrorHandler);
transaction.executeSql('CREATE TABLE IF NOT EXISTS catalogs(' +
'name TEXT NOT NULL PRIMARY KEY, updated INTEGER NOT NULL DEFAULT 0, state INTEGER NOT NULL DEFAULT 0, active INTEGER NOT NULL DEFAULT 1, uninstall INTEGER NOT NULL DEFAULT 0);', [], nullDataHandler,cobalt.dbErrorHandler);
});
var cobalt_output = $('<div id="cobalt-out"></div>').appendTo('body').hide();
var bind_key = function (binding, catalog, id, handler) {
$(document).bind('keydown', binding, function(){
cobalt.loadEntry(catalog, id, function(item) {
if (item) {
cobalt.actionCandidates(item, function(cand){
var cand_count = cand.length;
for(var i=0; i<cand_count; i++) {
if (cand[i].id == handler) {
cand[i].handler(item.name, item);
}
}
});
}
});
});
};
var toggle_output = function(arg) {
if (cobalt_out_visible) {
cobalt_output.hide();
cobalt_out_visible = false;
}
else if (arg!='hide') {
cobalt_output.show();
cobalt_out_visible = true;
}
};
var keypress_reaction = function() {
if(cobalt_input.val()==current_text) {
return;
}
current_text = cobalt_input.val();
if($.trim(current_text)!='') {
lookup();
}
};
var action_keypress_reaction = function() {
if(cobalt_h_input.val()==current_action_text) {
return;
}
current_action_text = cobalt_h_input.val();
action_candidates(item, function(candidates) {
actions = candidates;
set_handler(0, true);
});
};
var clear_ac = function() {
match_idx = 0;
matches = null;
item = 0;
$('#cobalt .inner').attr('class','inner');
$('#cobalt .inner label').hide();
cobalt_ac.hide().empty();
cobalt_paging.hide().empty();
};
var lookup = function(preserve_offset) {
if (!preserve_offset) {
match_offset = 0;
}
var like_expr = '%' + current_text + '%';
db.transaction(function (transaction) {
transaction.executeSql("SELECT e.*, u.weight FROM entries AS e " +
"LEFT OUTER JOIN usage_data AS u ON (e.catalog=u.catalog AND e.id=u.id) " +
"WHERE e.active=1 AND (u.abbreviation = ? OR e.name LIKE ? OR e.extra LIKE ?) " +
"ORDER BY nullif(?,u.abbreviation), nullif(?,e.name), u.weight DESC LIMIT ?,?;", [
current_text, like_expr, like_expr, current_text, current_text, match_offset, match_page_size ], lookup_finished,cobalt.dbErrorHandler);
});
};
var lookup_finished = function(transaction, results) {
if (results.rows.length) {
match_idx = 0;
$('#cobalt .left label').hide();
cobalt_ac.empty().hide();
for (var i=0; i<results.rows.length; i++) {
var item = results.rows.item(i);
item.information = JSON.parse(item.data);
if (typeof(catalogs[item.catalog]) !='undefined' && typeof(catalogs[item.catalog].item_formatter) == 'function'){
var title = catalogs[item.catalog].item_formatter(item);
}
else {
var title = item.name;
}
$('<li class="ac-opt-' + i + '"></li>').html(title).appendTo(cobalt_ac);
}
matches = results.rows;
//Only count for paging when we're not already offsetting the result and
//have a match count equal to the page size
if (match_offset) {
update_pager(match_count);
}
else if (matches.length==match_page_size) {
var like_expr = '%' + current_text + '%';
db.transaction(function (transaction) {
transaction.executeSql("SELECT COUNT(*) as match_count FROM entries AS e " +
"LEFT OUTER JOIN usage_data AS u ON (e.catalog=u.catalog AND e.id=u.id) " +
"WHERE e.active=1 AND (u.abbreviation = ? OR e.name LIKE ? OR e.extra LIKE ?);", [
current_text, like_expr, like_expr], function(transaction, results) {
if (results.rows.length) {
match_count = results.rows.item(0).match_count;
update_pager(match_count);
}
},cobalt.dbErrorHandler);
});
}
else {
update_pager(matches.length);
}
cobalt_ac.show();
}
ac_select(0);
};
var update_pager = function(new_match_count) {
match_count = new_match_count;
cobalt_paging.hide().empty();
var page_count = Math.min(Math.ceil(match_count/match_page_size),25);
for (var i=0; i<page_count; i++ ) {
var p = $('<li>&nbsp;</li>').appendTo(cobalt_paging);
if (i==match_offset/match_page_size) {
p.attr('class','current');
}
}
cobalt_paging.show();
};
var ac_page = function(new_offset) {
if (new_offset>=match_count || new_offset<0) {
return;
}
match_offset = new_offset;
lookup(true);
};
var ac_select = function(idx) {
if (idx<0 || idx >= matches.length) {
item = null;
return;
}
item = matches.item(idx);
item.information = JSON.parse(item.data);
var old_item = matches.item(match_idx);
$('#cobalt .ac-opt-' + match_idx).removeClass('active');
match_idx = idx;
// Generate path specific classes that can be used for icons.
// Matches the classes used in the Rubik admin theme.
var classes = '';
if (item.data_class === 'url_data') {
var path = JSON.parse(item.data);
if (typeof(path) == 'object') {
path = path.path;
}
classes = [];
var args = path.split('/');
while(args.length) {
classes[args.length - 1] = 'path-' + args.join('-');
args.pop();
}
classes = classes.join(' ');
};
$('#cobalt .left .inner').attr('class','inner cobalt-item-' + item.data_class + ' ' + classes);
$('#cobalt .left label').text(item.name).show();
$('#cobalt .ac-opt-' + match_idx).addClass('active');
action_candidates(item, function(candidates){
actions = candidates;
set_handler(0, true);
});
};
var action_candidates = function(item, callback) {
var candidates = [], gcount, i, j, cls_count, rc, cc, item,
add_applicable = function(handler) {
// Check if the handler matches the current_action_text (from closure),
// or run the handlers own applicability check if it has one.
if ((current_action_text=='' || handler['name'].toLowerCase().indexOf(current_action_text)!=-1) &&
(!handler['applicable'] || handler.applicable(current_text, item))) {
candidates.push(handler);
}
};
// Add handlers for the items data class that match the current_action_text
if (typeof(handlers[item.data_class])!='undefined') {
cls_count = handlers[item.data_class].length;
for (i=0; i<cls_count; i++) {
add_applicable(handlers[item.data_class][i]);
}
}
// Add global handlers that match the current_action_text
g_count = global_handlers.length;
for (i=0; i<g_count; i++) {
add_applicable(global_handlers[i]);
}
// Load the usage data for the candidates so that we may sort them
db.transaction(function (transaction) {
transaction.executeSql("SELECT handler, weight FROM handler_usage_data WHERE catalog=? AND id=?",
[item.catalog, item.id], function(transaction, results) {
rc = results.rows.length;
cc = candidates.length;
for (j=0; j<cc; j++) {
candidates[j].context_weight = 0;
for (i=0; i<rc; i++) {
r = results.rows.item(i);
if (r.handler == candidates[j].id) {
candidates[j].context_weight = r.weight;
}
}
}
// Sort the candidates after context_weight and weight
candidates.sort(function(a, b){
var cwd = b.context_weight-a.context_weight;
if (cwd==0) {
return b.weight-a.weight;
}
return cwd;
});
callback(candidates);
});
});
};
var handler_class = function() {
if (handler) {
return handler['class'] ? handler['class'] : 'default';
}
};
var set_handler = function(idx, update) {
if (update) {
cobalt_actions.empty();
var a_count = actions.length;
for(var i=0; i<a_count; i++) {
$('<li class="action-opt-' + i + '"></l i>').html(actions[i]['name']).appendTo(cobalt_actions);
}
}
if (idx<0 || idx >= actions.length) {
return;
}
$('#cobalt .action-opt-' + handler_idx).removeClass('active');
$('#cobalt .action-opt-' + idx).addClass('active');
handler_idx = idx;
var new_handler = actions[idx];
handler = new_handler;
if (handler) {
var newClass = handler_class();
$('#cobalt .right .inner').attr('class','inner cobalt-action-' + newClass);
$('#cobalt .right label').text(handler.name).show();
}
};
var run_handler = function() {
if (item && typeof(handler['handler']) == 'function') {
var text = $.trim(cobalt_input.val());
register_use(text, item, handler);
try {
handler.handler(text, item);
}
catch(err) {
log_error(Drupal.t("The handler threw a exception"), err);
}
}
hide();
};
var get_last_entry = function() {
db.transaction(function (transaction) {
transaction.executeSql("SELECT e.*, u.weight FROM entries AS e INNER JOIN usage_data AS u ON u.catalog = e.catalog AND u.id = e.id WHERE last = 1;", [], function(transaction, results) {
lookup_finished(transaction, results);
}, cobalt.dbErrorHandler);
});
};
var toggle = function(arg) {
if (cobalt_visible) {
cb.hide();
cobalt_visible = false;
}
else if (arg!='hide') {
toggle_output('hide');
cobalt_input.val($.trim(cobalt_input.val()));
cb.show();
cobalt_visible = true;
setTimeout(function(){ cobalt_input.focus(); cobalt_input.select(); }, 100);
}
};
var hide = function() {
toggle('hide');
};
var init = function() {
$(document).trigger('cobalt-init', cobalt);
// Load key bindings
db.transaction(function (transaction) {
transaction.executeSql('SELECT binding, catalog, id, handler FROM key_bindings', [], function(transaction, results) {
for (var i=0; i<results.rows.length; i++) {
var b = results.rows.item(i);
bind_key(b.binding, b.catalog, b.id, b.handler);
}
},cobalt.dbErrorHandler);
});
get_last_entry();
db.transaction(function (transaction) {
transaction.executeSql("SELECT * FROM catalogs ORDER BY updated;", [ ], function(transaction, results) {
var info = {};
var state = current_state();
// Queue catalogs for update
for (var i = 0; i < results.rows.length; i++) {
var item = results.rows.item(i);
info[item.name] = item;
update_queue.push({'name': item.name, 'updated': (item.state==state?item.updated:0) });
}
// Install new catalogs and queue them for updates
for (var key in catalogs) {
(function(key) {
if (!info[key]) {
if (catalogs[key]['install']) {
catalogs[key].install();
}
db.transaction(function (transaction) {
transaction.executeSql("INSERT INTO catalogs(name) VALUES(?)", [key], nullDataHandler,cobalt.dbErrorHandler);
});
update_queue.unshift({'name': key, 'updated': 0 });
}
})(key);
}
// Update loop
var update_counter = 0;
var update_loop = function() {
setTimeout(function() {
if(update_queue.length) {
var inf = update_queue.shift();
var now = new Date().getTime();
var catalog = catalogs[inf.name];
if (typeof(catalog['update_rate'])!='undefined' && inf.updated + catalog.update_rate > now) {
update_queue.push(inf);
update_loop();
}
else {
if (catalog['update']) {
catalog.update(inf.updated, function(enqueue){
var now = new Date().getTime();
cobalt.catalogUpdated(inf.name);
if (enqueue) {
update_queue.push({'name': inf.name, 'updated': now });
}
update_counter++;
update_loop();
});
}
else {
update_loop();
}
}
}
},update_counter?1000:100);
};
update_loop();
},cobalt.dbErrorHandler);
});
$(document).trigger('cobalt-post-init', cobalt);
cb.bind('click', function(e){ return false; });
$([cobalt_input[0], cobalt_h_input[0]]).bind('keydown', 'esc', function(){ toggle('hide'); toggle_output('hide'); return false; }).
bind('keydown', 'return', function(){ run_handler(); return false; });
cobalt_input.bind('keydown', 'up', function(){ ac_select(match_idx-1); return false; }).
bind('keydown', 'down', function(){ ac_select(match_idx+1); return false; }).
bind('keydown', 'Alt+left', function(){ ac_page(match_offset-match_page_size); return false; }).
bind('keydown', 'Alt+right', function(){ ac_page(match_offset+match_page_size); return false; }).
bind('keyup', function(){ keypress_reaction(); return false; }).
bind('focus', function() {
if (matches && matches.length) {
cobalt_ac.show();
cobalt_paging.show();
}
cobalt_actions.hide();
});
cobalt_h_input.bind('keydown', 'up', function(){ set_handler(handler_idx-1); return false; }).
bind('keydown', 'down', function(){ set_handler(handler_idx+1); return false; }).
bind('keyup', function(){ action_keypress_reaction(); return false; }).
bind('focus', function(){ cobalt_paging.hide(); cobalt_ac.hide(); cobalt_actions.show(); });
cobalt_output.bind('click', function(e){ return false; });
$('.cell.left', cb).bind('click', function(){ cobalt_input[0].focus(); });
$('.cell.right', cb).bind('click', function(){ cobalt_h_input[0].focus(); });
$(document).bind('click', function(){ toggle('hide'); toggle_output('hide'); });
if (Drupal && Drupal.settings && Drupal.settings.cobalt) {
var bindings = Drupal.settings.cobalt.bindings,
bind_count = bindings.length, i;
for (i=0; i<bind_count; i++) {
$(document).bind('keydown', bindings[i], toggle);
}
}
else {
$(document).bind('keydown', 'Alt+space', toggle)
.bind('keydown', 'Ctrl+space', toggle);
}
};
// Initialize GUI
var cb = $('<div id="cobalt">'+
'<div class ="cells"><div class="cell left"><div class="inner"><span class="icon"></span><input type="text" id="cobalt-input" /><label></label></div></div>'+
'<div class="cell right"><div class="inner"><input type="text" id="cobalt-handler-input" /><label></label></div></div></div>'+
'<ol class="cobalt-paging"></ol><ul class="cobalt-autocomplete"></ul><ul class="cobalt-actions"></ul></div>').appendTo('body').hide();
var cobalt_input = $('#cobalt-input');
var cobalt_h_input = $('#cobalt-handler-input');
var cobalt_ac = $('#cobalt .cobalt-autocomplete');
var cobalt_actions = $('#cobalt .cobalt-actions');
var cobalt_paging = $('#cobalt .cobalt-paging');
$('#cobalt .right label').hide();
// Check if we need to update anything before initializing
db.transaction(function (transaction) {
transaction.executeSql('SELECT name, version FROM versions', [], function(transaction, results) {
var v = {};
for (var i=0; i<results.rows.length; i++) {
var vi = results.rows.item(i);
v[vi.name] = vi.version;
}
db.transaction(function (transaction) {
var plugin_count = plugin_names.length;
for (var i=0; i<plugin_count; i++) {
var n=plugin_names[i];
if (typeof(v[n])=='undefined') {
transaction.executeSql('INSERT INTO versions(name, version) VALUES(?,?)', [ n, plugins[n].version ], nullDataHandler,cobalt.dbErrorHandler);
}
else if (v[n]<plugins[n].version) {
required_updates.push([n, v[n], plugins[n].version]);
}
}
if (required_updates.length) {
var update_notice = function () {
var update_url = Drupal.settings.basePath + 'cobalt/update';
for (var i=0; i<required_updates.length; i++) {
var u = required_updates[i];
update_url += '/' + u[0] + '/' + u[1] + '/' + u[2];
}
cobalt.showHtml('<h1>' + Drupal.t('Update required') + '</h1>' +
'<p>' + Drupal.t('Cobalt must be updated before it can be used') + '</p>' +
'<p><a class="cobalt-update-link" href="' + update_url + '">' + Drupal.t('Click here to update') + '</a></p>');
};
$(document).bind('click', function(){ toggle_output('hide'); });
if (Drupal && Drupal.settings && Drupal.settings.cobalt) {
var bindings = Drupal.settings.cobalt.bindings,
bind_count = bindings.length, i;
for (i=0; i<bind_count; i++) {
$(document).bind('keydown', bindings[i], update_notice);
}
}
else {
$(document).bind('keydown', 'Alt+space', update_notice)
.bind('keydown', 'Ctrl+space', update_notice);
}
}
else {
init();
}
});
},cobalt.dbErrorHandler);
});
});
})(jQuery);