2 * This file is part of WolneLektury-Mobile, licensed under GNU Affero GPLv3 or later.
3 * Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
9 var categories = {'author': 'autor',
16 // FIXME: htmlescape strings!
19 // for preparing sql statements
21 // var s = new Sql("INSERT ... '{0}', '{1}' ...";
22 // s.prepare("abc", ...)
23 var Sql = function(scheme) {
27 self.sql_escape = function(term) {
28 return term.toString().replace("'", "''");
31 self.prepare = function() {
33 return self.text.replace(/{(\d+)}/g, function(match, number) {
34 return self.sql_escape(args[parseInt(number)]);
40 var Catalogue = new function() {
41 /* API for database */
46 this.init = function(success, error) {
47 console.log('Catalogue.init');
49 self.updateDB(function() {
50 self.db = window.openDatabase("wolnelektury", "1.0", "WL Catalogue", 1);
54 error && error('Nie mogę otworzyć bazy danych: ' + err);
58 error && error('Błąd migracji: ' + err);
62 self.sqlSanitize = function(term) {
63 return term.toString().replace("'", "''");
67 /* check if DB needs updating and upload a fresh copy, if so */
68 this.updateDB = function(success, error) {
69 var has_ver = window.localStorage.getItem('db_ver');
70 if (has_ver == DB_VER) {
71 console.log('db ok, skipping')
76 var done = function() {
77 window.localStorage.setItem('db_ver', DB_VER);
78 console.log('db updated');
83 // this is Android-specific for now
84 self.upload_db_android(done, error);
88 this.upload_db_android = function(success, error) {
89 console.log('upload db for Android 2.x+');
91 var dbname = "wolnelektury";
92 window.AssetCopy.copy("initial/Databases.db",
93 "/data/data/pl.org.nowoczesnapolska.wloffline/app_database/Databases.db", true,
95 console.log('db descriptor upload successful');
96 window.AssetCopy.copy("initial/0000000000000001.db",
97 "/data/data/pl.org.nowoczesnapolska.wloffline/app_database/file__0/0000000000000001.db", true,
99 console.log('db upload successful');
100 success && success();
102 error && error("database upload error: " + data);
105 error && error("database descriptor upload error: " + data);
109 this.withState = function(callback) {
110 self.db.transaction(function(tx) {
111 tx.executeSql("SELECT * FROM state", [],
112 function(tx, results) {
113 if (results.rows.length) {
114 callback(results.rows.item(0));
117 callback({last_checked: 0});
124 this.withBook = function(id, callback, error) {
125 console.log('withBook '+id)
126 self.db.transaction(function(tx) {
127 tx.executeSql("SELECT * FROM book WHERE id="+id, [],
128 function(tx, results) {
129 if (results.rows.length) {
130 callback(results.rows.item(0));
139 this.withBooks = function(ids, callback) {
140 console.log('withBooks ' + ids)
141 self.db.transaction(function(tx) {
142 tx.executeSql("SELECT * FROM book WHERE id IN ("+ids+") ORDER BY sort_key", [],
143 function(tx, results) {
145 var count = results.rows.length;
146 for (var i=0; i<count; ++i) {
147 items.push(results.rows.item(i));
155 this.withChildren = function(id, callback) {
156 console.log('withChildren ' + id)
157 self.db.transaction(function(tx) {
158 tx.executeSql("SELECT * FROM book WHERE parent="+id+" ORDER BY parent_number, sort_key", [],
159 function(tx, results) {
161 var count = results.rows.length;
162 for (var i=0; i<count; ++i) {
163 books.push(results.rows.item(i));
170 this.withTag = function(id, callback, error) {
171 console.log('withTag '+id)
172 self.db.transaction(function(tx) {
173 tx.executeSql("SELECT * FROM tag WHERE id="+id, [],
174 function(tx, results) {
175 if (results.rows.length) {
176 callback(results.rows.item(0));
185 this.withCategory = function(category, callback) {
186 console.log('withCategory ' + category)
187 self.db.transaction(function(tx) {
188 tx.executeSql("SELECT * FROM tag WHERE category='"+category+"' ORDER BY sort_key", [],
189 function(tx, results) {
191 var count = results.rows.length;
192 for (var i=0; i<count; ++i)
193 items.push(results.rows.item(i));
200 /* takes a query, returns a list of {view,id,label} objects to a callback */
201 this.withSearch = function(term, callback) {
202 console.log('searching...');
203 term = term.replace(/^\s+|\s+$/g, '') ;
206 function booksFound(tx, results) {
207 var len = results.rows.length;
208 console.log('found books: ' + len);
209 for (var i=0; i<len; i++) {
210 var item = results.rows.item(i);
218 function tagsFound(tx, results) {
219 var len = results.rows.length;
220 console.log('found tags: ' + len);
221 for (var i=0; i<len; i++) {
222 var item = results.rows.item(i);
228 // TODO error handling
234 // TODO pliterki, start of the word match
235 self.db.transaction(function(tx) {
236 sql_term = self.sqlSanitize(term); // this is still insane, % and _
237 tx.executeSql("SELECT * FROM book WHERE title LIKE '%"+sql_term+"%' ORDER BY sort_key LIMIT 10", [],
238 //tx.executeSql("SELECT * FROM book WHERE title REGEXP '.*"+sql_term+".*' ORDER BY sort_key", [],
239 function(tx, results) {
241 booksFound(tx, results);
242 // and proceed to tags
243 tx.executeSql("SELECT * FROM tag WHERE name LIKE '%"+sql_term+"%' ORDER BY sort_key LIMIT 10",
247 console.log('ERROR:search: '+err.code);
253 self.chainSqls = function(sqls, success, error) {
254 self.db.transaction(function(tx) {
255 var do_next = function() {
257 var sql = sqls.shift();
259 tx.executeSql(sql, [], do_next, error);
262 success && success();