5 мая 2010 в 22:55

Разработка с использованием WEB SQL DB и Local Storage

Совсем недавно на хабре был пост, посвященный работе с WEB SQL DB. Одно из полезных применений локальных баз данных – работа в оффлайн режиме. Кроме этого, я покажу еще один вариант работы, когда вместо sql используется local storage, который поддерживается уже большим количеством браузеров.

Определение offline режима


Для начала определим, что мы работаем в offline режиме. Способов несколько. Во-первых, мы можем послать запрос, и в случае неудачи начинать работать в нужном режиме. Но HTML5 позволяет определить это более простым способом, а именно вот так
navigator.onLine

К сожалению, это будет работать только в Opera и Firefox (www.html5demos.com/ хороший сайт, показывающий поддержку той или иной фичи браузерами).
Определив, что мы в оффлайне, мы можем переходить к дальнейшей работе. Важно помнить, что к этому моменту, все необходимые нам ресурсы должны быть закешированы. Подробнее о создании кэша для оффлайн приложений можно прочитать тут. А на StackOverflow можно почитать дискуссию о том, какой же метод все таки удобнее.

Работаем с WEB SQL DB



Работать с базой достаточно просто

Вначале создадим ее
db = openDatabase("TestDB", "1.0", "HTML5 Database", 200000);.

В функцию создания базы данных передаются следующие параметры:
  • Название базы данных
  • Ее версия
  • Отображаемое имя
  • Размер в байтах

Далее открываем транзакцию и выполняем нужные нам действия
db.transaction(function(tx)
    {
      tx.executeSql("DELETE FROM tbl_test WHERE id = ?", [item.id]);
    });


И далее все в таком духе. Я бы хотел предложить альтернативный вариант, а именно библиотеку jQT Database
Вот тут можно прочитать как работает данный плагин. А скачать можно тут, если попытаться скачать его по ссылке, данной в первом источнике ничего не выйдет.
Вкратце, как оно работает.

Инициализируем базу:
jQT.dbOpen(“name”, “version”,”descriptione”, size);

Создаем таблицу:
jQT.dbCreateTables(json);

Вставляем строки:
jQT.dbInsertRows(json);

Селектим строки:
jQT.dbSelectAll(“table”, callback(result));

Удаляем строки:
jQT.dbDeleteRow(“table”,”key”,”value”);

Удаляем таблицу:
jQT.dbDropTable(“table”);

Выполнить запрос:
jQT.dbExecuteQuery(“Query”,”Debug text”, callback(result));


Имхо, очень удобно.
Пара комментариев. Переменная jQT создается при работе с jQTouch. Если не хотите использовать лишние библиотеки, то проще всего залезть в исходники и выдрать нужный код для себя, благо написано он очень грамотно.

Работаем с Local storage



Теперь проведем всю ту же работу, но только с использованием local storage. Сначала заведем само хранилище

var storage = window.localStorage;


Теперь чтобы завести пустую переменную достаточно написать следующий код.

storage.operations = ""


Теперь перед нами стоит вопрос, в том как организовать хранение данных. Моим решением стало хранение текстового варианта xml и его последующее преобразование. (На самом деле в моем случае решение было достаточно очевидным и, наверное, единственным, так как веб-сервис возвращал мне именно xml)

Выполняем запрос на сервер (я использую jQuery и, думаю, использовать этот код в остальных фреймворках будет несложно).

 $.ajax({
    url: '/operations/get/',
    type: 'POST',
    success: function(res) {
      var successful = $(res).find("successful").text();
      if (successful == "true") {        
        storage.operations = "<result>";
        var jobz = $(res).find("return").children();
        jobz.each(function() {
          var nodName = $(this)[0].nodeName;          
          if (nodName == "OPERATIONS") {
            var operation = $(this);
            storage.operations += "<operations>" + operation.html() + "</operations>";
          }
        });       
        storage.operations += "</result>";

      } else {        
        storage.operations += "<?xml version='1.0' encoding='utf-8'?><result></result>";
      }      
    }
  });


Итак, мы выполнили запрос. Так как результат у нас xml, то для того, чтобы работать с ним как с DOM объектом в jQuery достаточно просто обернуть его $(). К сожалению это не работает в Internet Explorer, где для перевода текста в DOM объект необходим следующий код

function getXml(text) {
  try {
    var xmlDocument = new ActiveXObject("Microsoft.XMLDOM");
    xmlDocument.async = "false";
    xmlDocument.loadXML(text);
    return xmlDocument;
  } catch(e) {
    alert(e.description);
  }
  return null;
}


Почитать про работу с веб-сервисами в IE можно тут.

Если запрос прошел удачно, то мы выбираем всех потомков корневого узла (в моем случае они могут быть нескольких типов) и оборачиваем его нужными тегами. Замечу, что вызов .html() вернет нам именно код с тегами, в то время как .text() вернет только содержимое внутри тегов.

Теперь чтобы получить, то что мы сохранили делаем следующую функцию

function getOperationsFromStorage() {
  return $(storage.operations).find('operations');
}


Работать с ней можно следующим образом

getOperationsFromStorage().each(function() {
  var id = $(this).find('id').text();
  alert("Find entitie with id "+id);      
});


Как видно, мы каждый раз оборачиваем this $() и вызываем у него метод .find(). Если у нас имеется вложенные сущности, то добраться до них можно следующим образом

$(this).find("otherInfo").each(function() {
   var name = $(this).find("name").text();
   alert(“Found inline tag value ”+name);
});


Остался еще один вопрос, как обновлять наш объект. Я делаю это следующим образом.

var s = "<operations>";
s += "<id>" + someId+ "</id>";
s += "<type>"+type+"</type>";
s += "</operations>";
var text = storage. operations;
text = text.substring(0, text.length - 9);
text += s + "</result>";
storage. operations = text;


Как видно, я отрезаю закрывающий тег, дописываю новый объект и в конце опять закрываю все оборачивающим тегом.

Надеюсь, что теперь работа по созданию оффлайн приложений станет проще.

P.S.: В завершении хотелось бы рассказать о библиотеке Modernizr, которая позволяет определять поддержку той или иной фичи браузером.
Андрей Ребров @mythmaker
карма
153,0
рейтинг 0,0
Похожие публикации
Самое читаемое Разработка

Комментарии (8)

  • +3
    Во-первых, зачем тут SQL? SQL как язык запросов к базе.

    Имхо, все это намного красивее пишется, если вся страница проектируется в стиле event-driven development. Надо достать определенную сущность? Не вопрос! Генерируем соответствующее событие, а JS реагирующий на событие уже сам понимает нужен ли запрос к серверу или нет. Благодаря этому и синхронизация, и очистка по TTL клиентского кеша, и куча других вещей будут писаться очень просто.
  • +3
    navigator.onLine

    К сожалению, это будет работать только в Opera и Firefox
    У меня в IE8 работает.
  • 0
    нда, наворотили фигни на ровном месте с этими фичами…
  • 0
    Подробнее о создании кэша для оффлайн приложений можно прочитать тут. А на StackOverflow можно почитать дискуссию о том, какой же метод все таки удобнее.

    Не могли бы вы припомнить 2 ссылки, упомянутые в этих предложениях?

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.