cartoonreader-libs.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. function jQueryEventProxy(debug) {
  2. this.m_debug = debug;
  3. }
  4. jQueryEventProxy.prototype = {
  5. eventHandler: function(event) {
  6. try {
  7. var proxy = event.data.proxy;
  8. if(proxy.checkIfEventDataContainsHandler(event.data)) {
  9. proxy.callEventHandler($(this),
  10. event);
  11. }
  12. }
  13. catch(e) {
  14. alert("jQueryEventProxy.eventHandler: Event handling malfunctioned: " + e);
  15. }
  16. },
  17. checkIfEventDataContainsHandler: function(data) {
  18. var contains = false;
  19. if(data &&
  20. data.proxy &&
  21. data.handler &&
  22. data.handler.that &&
  23. data.handler.handler) {
  24. contains = true;
  25. }
  26. return contains;
  27. },
  28. callEventHandler: function(target,
  29. event) {
  30. var handler = event.data.handler;
  31. try {
  32. handler.handler.call(handler.that,
  33. target,
  34. event);
  35. }
  36. catch(e) {
  37. if(this.m_debug) {
  38. this.m_debug.error(e);
  39. alert(e);
  40. }
  41. }
  42. },
  43. buildEventData: function(handler) {
  44. var data = { proxy: this,
  45. handler: handler};
  46. if(!this.checkIfEventDataContainsHandler(data)) {
  47. throw "jQueryEventProxy.buildEventData: event handler invalid.";
  48. }
  49. return data;
  50. },
  51. bind: function(object, eventName, handler) {
  52. try {
  53. var eventData = this.buildEventData(handler);
  54. object.bind(eventName,
  55. eventData,
  56. this.eventHandler);
  57. }
  58. catch(e) {
  59. alert("jQueryEventProxy.bind: Couldn't bind event to object because: " + e);
  60. }
  61. }
  62. };
  63. function DnDHelper() {
  64. }
  65. DnDHelper.prototype = {
  66. disableDragging: function(elements) {
  67. elements.attr("draggable", false);
  68. elements.bind("mousedown",
  69. function(event) {
  70. event.preventDefault();
  71. return false;
  72. });
  73. }
  74. };
  75. function CartoonParser() {
  76. this.m_callbackObject= undefined;
  77. }
  78. CartoonParser.prototype = {
  79. parseCartoonsFromFeed: function(feed,
  80. callbackObject) {
  81. this.m_callbackObject = callbackObject;
  82. var cartoons = undefined;
  83. if(feed.status == "ok") {
  84. cartoons = this.parseCartoons(feed);
  85. }
  86. else {
  87. this.forwardError(feed.URL);
  88. }
  89. if(cartoons !== undefined &&
  90. cartoons.cartoons.length > 0) {
  91. this.forwardCartoons(cartoons);
  92. }
  93. else {
  94. this.forwardError(feed.URL);
  95. }
  96. },
  97. parseCartoons: function(feed) {
  98. var cartoons = {URL: feed.URL,
  99. title: '',
  100. lastModified: '',
  101. cartoons: []};
  102. if(feed &&
  103. feed.status == "ok") {
  104. cartoons.lastModified = feed.lastModified;
  105. cartoons.title = feed.title;
  106. for(var i =0; i < feed.items.length; i++) {
  107. var cartoon = this.parseCartoon(feed.items[i]);
  108. if(cartoon !== undefined) {
  109. cartoons.cartoons.push(cartoon);
  110. }
  111. }
  112. }
  113. return cartoons;
  114. },
  115. parseCartoon: function(feedItem) {
  116. var cartoon = undefined;
  117. var cartoonImage = this.determineTheActualCartoon(feedItem);
  118. if(cartoonImage.imageURL !== '') {
  119. cartoon = { title: feedItem.title,
  120. URL: feedItem.url,
  121. date: feedItem.date,
  122. imageURL: cartoonImage.imageURL,
  123. altText: cartoonImage.altText,
  124. titleText: cartoonImage.titleText};
  125. }
  126. return cartoon;
  127. },
  128. determineTheActualCartoon: function(item){
  129. // Let's check if there are any images in description
  130. var cartoonImage = {imageURL: '',
  131. altText: '',
  132. titleText: ''};
  133. var images = this.getItemContent(item);
  134. var imageTag = this.findImageTag(images);
  135. if(imageTag !== undefined) {
  136. cartoonImage.imageURL = imageTag.attr("src");
  137. cartoonImage.altText = imageTag.attr("alt");
  138. cartoonImage.titleText = imageTag.attr("title");
  139. }
  140. if(cartoonImage.imageURL !== '' &&
  141. item.url.search(/\.(png|jpe?g|gif)/i) != -1) {
  142. cartoonImage.imageURL = item.url;
  143. }
  144. return cartoonImage;
  145. },
  146. getItemContent: function(item) {
  147. var images = $();
  148. try {
  149. images = $(item.description, document).filter("img");
  150. }
  151. catch(e) { /* Swallow exception */}
  152. if(images.length === 0) {
  153. try {
  154. images = $(item.content, document).find("img");
  155. }
  156. catch(e) { /* Swallow exception */}
  157. }
  158. if(images.length === 0) {
  159. try {
  160. images = $(item.description, document).find("img");
  161. }
  162. catch(e) { /* Swallow exception */}
  163. }
  164. return images;
  165. },
  166. findImageTag: function(images) {
  167. var imageTag = undefined;
  168. if(images.length > 0) {
  169. tempImageTag = $(images.get(0));
  170. if(tempImageTag.attr("src") !== undefined) {
  171. imageTag = tempImageTag;
  172. }
  173. }
  174. return imageTag;
  175. },
  176. forwardCartoons: function(cartoons) {
  177. var that = this.m_callbackObject.that;
  178. var callback = this.m_callbackObject.callback;
  179. callback.call(that, cartoons);
  180. },
  181. forwardError: function(url) {
  182. var that = this.m_callbackObject.that;
  183. var callback = this.m_callbackObject.errorCallback;
  184. callback.call(that, url, "Couldn't find cartoons from this URL. Check internet connectivity.");
  185. }
  186. };
  187. function MaemoHelper(window,
  188. jQueryEventProxy,
  189. dndHelper) {
  190. this.C_IMAGE_URL = "qrc:/images/maemo-task-switcher.png";
  191. this.m_window = window;
  192. this.m_jQueryEventProxy = jQueryEventProxy;
  193. this.m_dndHelper = dndHelper;
  194. }
  195. MaemoHelper.prototype = {
  196. createTaskSwitcher: function(to) {
  197. var element = this.createTaskSwitcherElement(this.C_IMAGE_URL,
  198. this.m_window.document);
  199. var clickHandler = {that: this,
  200. handler: this.taskSwitcherClicked};
  201. this.m_jQueryEventProxy.bind(element,
  202. "click",
  203. clickHandler);
  204. this.m_jQueryEventProxy.bind(to,
  205. "click",
  206. clickHandler);
  207. to.prepend(element);
  208. },
  209. createTaskSwitcherElement: function(imageURL,
  210. document) {
  211. var html = "<button id=\"maemoTaskSwitcher\">" +
  212. "<img id=\"maemoTaskSwitcherIcon\" src=\"\" />" +
  213. "</button>";
  214. var element = $(html, document);
  215. var image = element.find("#maemoTaskSwitcherIcon");
  216. this.m_dndHelper.disableDragging(image);
  217. image.attr("src", imageURL);
  218. return element;
  219. },
  220. taskSwitcherClicked: function(target, event) {
  221. this.m_window.minimize();
  222. },
  223. setFontSizeTo: function(elements, fontSize) {
  224. elements.css("font-size", fontSize);
  225. }
  226. };
  227. function CartoonSource(url,
  228. name,
  229. id,
  230. active) {
  231. this.setUrl(url);
  232. this.setName(name);
  233. this.setId(id);
  234. this.setActive(active);
  235. }
  236. CartoonSource.prototype = {
  237. setId: function(id) {
  238. this.m_id = id;
  239. },
  240. getId: function() {
  241. return this.m_id;
  242. },
  243. setUrl: function(url) {
  244. this.m_url = url;
  245. },
  246. getUrl: function() {
  247. return this.m_url;
  248. },
  249. setName: function(name) {
  250. this.m_name = name;
  251. },
  252. getName: function() {
  253. return this.m_name;
  254. },
  255. setActive: function(active) {
  256. if(!active) {
  257. active = false;
  258. }
  259. if(active === true ||
  260. active === 1) {
  261. this.m_active = 1;
  262. }
  263. if(active === false ||
  264. active === 0) {
  265. this.m_active = 0;
  266. }
  267. },
  268. getActive: function() {
  269. return this.m_active;
  270. },
  271. getActiveBoolean: function() {
  272. return (this.m_active ? true : false);
  273. }
  274. };
  275. function CartoonSourceResultFiller() {
  276. }
  277. CartoonSourceResultFiller.prototype = {
  278. createCartoonSource: function(row) {
  279. var cartoonSource = new CartoonSource();
  280. cartoonSource.setId(row['id']);
  281. cartoonSource.setUrl(row['url']);
  282. cartoonSource.setName(row['name']);
  283. cartoonSource.setActive(row['active']);
  284. return cartoonSource;
  285. }
  286. };
  287. function CartoonSourceResultAdapter(receiver) {
  288. this.m_receiver = receiver;
  289. this.m_cartoonSourceResultFiller = new CartoonSourceResultFiller();
  290. }
  291. CartoonSourceResultAdapter.prototype = {
  292. receiveResults: function(tx, results) {
  293. var cartoonSources = [];
  294. for (var i = 0; i < results.rows.length; ++i) {
  295. var row = results.rows.item(i);
  296. var cartoonSource = this.m_cartoonSourceResultFiller.createCartoonSource(row);
  297. cartoonSources.push(cartoonSource);
  298. }
  299. this.sendToReceiver(cartoonSources);
  300. },
  301. sendToReceiver: function(cartoonSources) {
  302. this.m_receiver.callback.call(this.m_receiver.that,
  303. cartoonSources);
  304. },
  305. getReceiver: function() {
  306. var callbackObject = { that: this,
  307. callback: this.receiveResults};
  308. return callbackObject;
  309. }
  310. };
  311. function CartoonAdditionAdapter(backend,
  312. receiver) {
  313. this.m_backend = backend;
  314. this.m_receiver = receiver;
  315. this.m_cartoonSourceResultFiller = new CartoonSourceResultFiller();
  316. }
  317. CartoonAdditionAdapter.prototype = {
  318. receiveIdResult: function(tx,
  319. results) {
  320. var id = results.insertId;
  321. this.m_backend.getCartoonSource(id,
  322. this.cartoonSourceReceiverCallback());
  323. },
  324. receiveCartoonSource: function(tx,
  325. results) {
  326. var row = results.rows.item(0);
  327. var cartoonSource = this.m_cartoonSourceResultFiller.createCartoonSource(row);
  328. this.sendToReceiver(cartoonSource);
  329. },
  330. sendToReceiver: function(cartoonSource) {
  331. this.m_receiver.callback.call(this.m_receiver.that,
  332. cartoonSource);
  333. },
  334. getReceiver: function() {
  335. var callbackObject = { that: this,
  336. callback: this.receiveIdResult};
  337. return callbackObject;
  338. },
  339. cartoonSourceReceiverCallback: function() {
  340. var callbackObject = { that: this,
  341. callback: this.receiveCartoonSource};
  342. return callbackObject;
  343. }
  344. };
  345. function CartoonDataFetcher(feedUpdateBroker,
  346. cartoonParser,
  347. feedResolver) {
  348. this.m_feedUpdateBroker = feedUpdateBroker;
  349. this.m_cartoonParser = cartoonParser;
  350. this.m_feedResolver = feedResolver;
  351. this.m_case = undefined;
  352. this.C_MAX_WAIT_TIME = 60000;
  353. }
  354. CartoonDataFetcher.prototype = {
  355. abort: function() {
  356. if(this.m_case !== undefined &&
  357. "xhr" in this.m_case) {
  358. this.m_case.xhr.abort();
  359. }
  360. },
  361. getDataFromURL: function(URL,
  362. receivers,
  363. feedDiscover) {
  364. if(feedDiscover === undefined) {
  365. feedDiscover = true;
  366. }
  367. this.m_case = this.createCase(URL,
  368. receivers,
  369. feedDiscover);
  370. this.createXHR(URL);
  371. },
  372. createCase: function(URL,
  373. receivers,
  374. feedDiscover) {
  375. var xhr = this.createXHR(this,
  376. URL,
  377. this.C_MAX_WAIT_TIME);
  378. var caseData = { URL: URL,
  379. receivers: receivers,
  380. feedDiscover: feedDiscover,
  381. xhr: xhr.xhr,
  382. timeoutID: xhr.timeoutID
  383. };
  384. return caseData;
  385. },
  386. createXHR: function(that,
  387. URL,
  388. timeout) {
  389. var receiver = that;
  390. var log = console;
  391. var xhr = new XMLHttpRequest();
  392. xhr.onreadystatechange = function() {
  393. log.debug(receiver);
  394. if(xhr.readyState === 4 &&
  395. receiver.receiveResponse) {
  396. receiver.receiveResponse(xhr,
  397. xhr.statusText);
  398. }
  399. };
  400. xhr.overrideMimeType("text/xml");
  401. xhr.open("GET", URL, true);
  402. xhr.send(null);
  403. var timeoutID = setTimeout(function() {xhr.abort();}, timeout);
  404. return { timeoutID: timeoutID, xhr: xhr };
  405. },
  406. receiveResponse: function(request,
  407. textStatus) {
  408. clearTimeout(this.m_case.timeoutID);
  409. var feedInfos = [];
  410. this.m_case.status = textStatus;
  411. if(this.m_case.feedDiscover &&
  412. this.m_feedResolver !== undefined) {
  413. feedInfos = this.m_feedResolver.findFeedInfos(request);
  414. }
  415. if(feedInfos.length > 0) {
  416. this.getDataFromURL(feedInfos[0].href,
  417. this.m_case.receivers,
  418. false);
  419. return;
  420. }
  421. else if(feedInfos.length == 0 &&
  422. request.responseXML) {
  423. this.processFeed(request,
  424. this.m_case.receivers.cartoonReceiver);
  425. }
  426. else {
  427. this.reportError(this.m_case);
  428. }
  429. },
  430. processFeed: function(request,
  431. receiver) {
  432. var feed = this.m_feedUpdateBroker.handleResponse(request,
  433. request.status,
  434. request.responseXML);
  435. this.m_cartoonParser.parseCartoonsFromFeed(feed, receiver);
  436. },
  437. reportError: function(errorCase) {
  438. try {
  439. var errorReceiver = errorCase.receivers.errorReceiver;
  440. errorReceiver.callback.call(errorReceiver.that,
  441. errorCase.URL,
  442. "Couldn't find cartoons for URL " +
  443. errorCase.URL +
  444. "(because of " + errorCase.status +
  445. ").");
  446. }
  447. catch(e) {
  448. alert("CartoonDataFetcher.reportError: Error callback threw an exception: " + e);
  449. }
  450. }
  451. };
  452. function FeedResolver() {
  453. /*
  454. * https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp
  455. * <link (whitespace|rel="alternate"|type="application/(atom|rss)+xml"|title="*"|href="*") />
  456. */
  457. this.LINK_MATCH_REGEX = /<link(?:\s+|(?:rel=[\"\']alternate[\"\']){1}|(?:(type)=[\"\']application\/(atom|rss)\+xml[\"\']){1}|(?:(title){1}=[\"\']([^<&\"]*)[\"\'])?|(href){1}=[\"\']([^<&\"]*)[\"\'])*\s*\/>/i;
  458. }
  459. FeedResolver.prototype = {
  460. findFeedInfos: function(response) {
  461. var feedInfos = [];
  462. if(response.responseXML) {
  463. feedInfos = this.findFeedInfosFromDOM(response.responseXML);
  464. }
  465. if(!response.responseXML &&
  466. response.responseText) {
  467. feedInfos = this.findFeedInfosFromText(response.responseText);
  468. }
  469. return feedInfos;
  470. },
  471. findFeedInfosFromDOM: function(xmlDoc) {
  472. var feedInfos = [];
  473. if(xmlDoc.getElementsByTagName("html").length > 0) {
  474. var elements = xmlDoc.getElementsByTagName("link");
  475. var baseURL = xmlDoc.baseURI;
  476. for(var i = 0; i < elements.length; i++) {
  477. var attributes = { rel: elements[i].rel.toLowerCase(),
  478. title: elements[i].title,
  479. type: elements[i].type.toLowerCase()
  480. .replace(/application\/([a-z]+)\+xml/g,
  481. "$1"),
  482. href: elements[i].href};
  483. if(attributes.rel === 'alternate' &&
  484. (attributes.type === 'atom' ||
  485. attributes.type === 'rss') &&
  486. attributes.href !== '') {
  487. delete attributes.rel;
  488. feedInfos.push(attributes);
  489. }
  490. }
  491. }
  492. return feedInfos;
  493. },
  494. findFeedInfosFromText: function(htmlText) {
  495. var feedInfos = [];
  496. if(htmlText.search(/<html.*?>/i) != -1) {
  497. var beforeHead = htmlText.split(/<\/head>/i)[0];
  498. var textArray = beforeHead.replace(/\/?>/g, "/>\n").split(/\n\r?/);
  499. for(var i=0; i<textArray.length; i++) {
  500. var feedInfo = this.findSingleFeedInfoFromText(textArray[i]);
  501. if(feedInfo) {
  502. feedInfos.push(feedInfo);
  503. }
  504. }
  505. }
  506. return feedInfos;
  507. },
  508. findSingleFeedInfoFromText: function(text) {
  509. var matches = this.LINK_MATCH_REGEX.exec(text);
  510. var feedInfo = undefined;
  511. if(matches) {
  512. feedInfo = {};
  513. for(var i=0; i<matches.length; i++) {
  514. if(matches[i] !== undefined &&
  515. (matches[i].toLowerCase() === 'type' ||
  516. matches[i].toLowerCase() === 'href' ||
  517. matches[i].toLowerCase() === 'title')) {
  518. feedInfo[matches[i]] = matches[i+1];
  519. i = i+2;
  520. continue;
  521. }
  522. }
  523. }
  524. return feedInfo;
  525. }
  526. };
  527. function CartoonManagerBackend(db) {
  528. this.m_db = db;
  529. this.m_txId = 0;
  530. this.m_resultReceivers = {};
  531. this.C_TABLE_NAME = "CartoonReaderSources";
  532. this.C_DEFAULT_FEED_NAME = "xkcd";
  533. this.C_DEFAULT_FEED = "http://xkcd.com/atom.xml";
  534. this.C_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS " + this.C_TABLE_NAME + " " +
  535. "(id INTEGER PRIMARY KEY AUTOINCREMENT," +
  536. " url TEXT, " +
  537. " name TEXT, " +
  538. " active INTEGER NOT NULL DEFAULT 0);";
  539. this.setup();
  540. }
  541. CartoonManagerBackend.prototype = {
  542. setup: function() {
  543. this.executeSQL(this.C_CREATE_TABLE_SQL,
  544. [],
  545. this.getEmptyHandler());
  546. },
  547. getEmptyHandler: function() {
  548. var handler = {that: this,
  549. callback: this.emptyHandler};
  550. return handler;
  551. },
  552. emptyHandler: function(tx, result) {
  553. console.log("CartoonManagerBackend.emptyHandler called.");
  554. },
  555. registerAddCartoonSourceAdapter: function(adapter) {
  556. this.m_addCartoonSourceAdapter = adapter;
  557. },
  558. registerGetCartoonSourcesAdapter: function(adapter) {
  559. this.m_getCartoonSourcesAdapter = adapter;
  560. },
  561. registerGetCartoonSourceAdapter: function(adapter) {
  562. this.m_getCartoonSourceAdapter = adapter;
  563. },
  564. registerUpdateCartoonSourceAdapter: function(adapter) {
  565. this.m_updateCartoonSourceAdapter = adapter;
  566. },
  567. getCartoonSources: function(receiver) {
  568. if(receiver === undefined &&
  569. this.m_getCartoonSourcesAdapter !== undefined) {
  570. receiver = this.m_getCartoonSourcesAdapter.getReceiver();
  571. }
  572. if(receiver === undefined) {
  573. receiver = this.getEmptyHandler();
  574. }
  575. var cartoonSourceSQL = "SELECT * FROM " + this.C_TABLE_NAME + ";";
  576. this.executeSQL(cartoonSourceSQL,
  577. [],
  578. receiver);
  579. },
  580. getCartoonSource: function(id,
  581. receiver) {
  582. if(receiver === undefined &&
  583. this.m_getCartoonSourceAdapter !== undefined) {
  584. receiver = this.m_getCartoonSourceAdapter.getReceiver();
  585. }
  586. if(receiver === undefined) {
  587. receiver = this.getEmptyHandler();
  588. }
  589. var cartoonSourceForIdSQL = "SELECT * FROM " + this.C_TABLE_NAME + " " +
  590. "WHERE id = ?;";
  591. this.executeSQL(cartoonSourceForIdSQL,
  592. [id],
  593. receiver);
  594. },
  595. getActiveCartoonSource: function(receiver) {
  596. if(receiver === undefined &&
  597. this.m_getCartoonSourceAdapter !== undefined) {
  598. receiver = this.m_getCartoonSourceAdapter.getReceiver();
  599. }
  600. if(receiver === undefined) {
  601. receiver = this.getEmptyHandler();
  602. }
  603. var activeCartoonSourceSQL = "SELECT * FROM " + this.C_TABLE_NAME + " " +
  604. "WHERE active = 1;";
  605. this.executeSQL(activeCartoonSourceSQL,
  606. [],
  607. receiver);
  608. },
  609. addCartoonSource: function(cartoonSource,
  610. receiver) {
  611. if(receiver === undefined &&
  612. this.m_addCartoonSourceAdapter !== undefined) {
  613. receiver = this.m_addCartoonSourceAdapter.getReceiver();
  614. }
  615. if(receiver === undefined) {
  616. receiver = this.getEmptyHandler();
  617. }
  618. var createSQL = "INSERT INTO " + this.C_TABLE_NAME + " " +
  619. "(url, name, active) VALUES (?, ?, 0);";
  620. this.executeSQL(createSQL,
  621. [cartoonSource.getUrl(),
  622. cartoonSource.getName()],
  623. receiver);
  624. },
  625. receiveModelChanges: function(changes) {
  626. if("toBeAdded" in changes) {
  627. this.handleAdded(changes.toBeAdded);
  628. }
  629. if("updated" in changes) {
  630. this.handleUpdated(changes.updated);
  631. }
  632. if("removed" in changes) {
  633. this.handleRemoved(changes.removed);
  634. }
  635. },
  636. handleAdded: function(added) {
  637. this.addCartoonSource(added.cartoonSource);
  638. },
  639. handleUpdated: function(updated) {
  640. if("cartoonSources" in updated) {
  641. for(var i = 0; i < updated.cartoonSources.length; i++) {
  642. this.updateCartoonSource(updated.cartoonSources[i]);
  643. }
  644. }
  645. },
  646. updateCartoonSource: function(cartoonSource) {
  647. var receiver = this.getEmptyHandler();
  648. if(this.m_updateCartoonSourceAdapter !== undefined) {
  649. receiver = this.m_updateCartoonSourceAdapter.getReceiver();
  650. }
  651. var updateSQL = "UPDATE " + this.C_TABLE_NAME + " " +
  652. "SET url = ?, " +
  653. "name = ?, " +
  654. "active = ? " +
  655. "WHERE id = ?;";
  656. this.executeSQL(updateSQL,
  657. [cartoonSource.getUrl(),
  658. cartoonSource.getName(),
  659. cartoonSource.getActive(),
  660. cartoonSource.getId()],
  661. receiver);
  662. },
  663. handleRemoved: function(removed) {
  664. var removeSQL = "DELETE FROM " + this.C_TABLE_NAME + " "+
  665. "WHERE id = ?;";
  666. this.executeSQL(removeSQL,
  667. [removed.getId()],
  668. this.getEmptyHandler());
  669. },
  670. executeSQL: function(SQL,
  671. params,
  672. resultReceiver) {
  673. var txId = this.m_txId;
  674. this.m_txId++;
  675. var self = this;
  676. this.m_resultReceivers[txId] = resultReceiver;
  677. this.m_db.transaction(function(tx) {
  678. tx.txId = txId;
  679. tx.SQL = SQL;
  680. tx.executeSql(SQL,
  681. params,
  682. function(tx, result) {self.generalResultReceiver(tx, result);},
  683. function(tx, error) {self.generalErrorReceiver(tx, error);});
  684. });
  685. },
  686. generalResultReceiver: function(tx, result) {
  687. /** Let's cheat a bit and insert default if none was
  688. was returned... */
  689. if(tx.SQL.search(/SELECT/) != -1 &&
  690. result.rows.length == 0) {
  691. // Insert default
  692. var insertDefault = "INSERT INTO " + this.C_TABLE_NAME + " " +
  693. "(url, name, active) VALUES(?, ?, ?);";
  694. this.executeSQL(insertDefault,
  695. [this.C_DEFAULT_FEED, this.C_DEFAULT_FEED_NAME, 1],
  696. this.getEmptyHandler());
  697. this.executeSQL(tx.SQL,
  698. [],
  699. this.m_resultReceivers[tx.txId]);
  700. delete this.m_resultReceivers[tx.txId];
  701. return;
  702. }
  703. var receiver = this.m_resultReceivers[tx.txId];
  704. try {
  705. receiver.callback.call(receiver.that, tx, result);
  706. }
  707. catch(e) {
  708. alert("CartoonManagerBackend failed to call the result receiver because: " + e);
  709. }
  710. },
  711. generalErrorReceiver: function(tx, error) {
  712. alert("CartoonManagerBackend received error when trying to execute SQL: " + error.message);
  713. }
  714. };
  715. function ObjectSpiller(recurse) {
  716. //var m_recursionDepth = 0;
  717. this.m_recurseOn = recurse;
  718. }
  719. ObjectSpiller.prototype = {
  720. getRecurseOn: function() {
  721. return this.m_recurseOn;
  722. },
  723. setRecurseOn: function(recurseOn) {
  724. this.m_recurseOn = recurseOn;
  725. },
  726. vomit: function(object) {
  727. for(var name in object) {
  728. alert(name + " : " + object[name]);
  729. if(typeof(object[name]) == "object" &&
  730. this.m_recurseOn) {
  731. alert("Recursing on " + name);
  732. this.vomit(object[name]);
  733. }
  734. }
  735. }
  736. };