2016/07/12

[JavaScript]Indexed Database APIで容量チェック

Indexed Database APIは、端末のローカルディスクを使うため必然的に容量が決まっています。

そこで、トランザクションが発生した場合に、容量いっぱいで登録できなかった場合はどうすればいいのだろうか?

モダンブラウザのストレージ容量まとめ
によると、以下のように組めばおkみたいです。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
  db = e.target.result;
  /*
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.count();
  request.onsuccess = function(e){
    var count = e.target.result;
    console.log(count)
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };
  */

  
  var transaction = db.transaction([storeName],'readwrite');
  var store = transaction.objectStore(storeName);
  var request = store.put({
    hoge : 'bar'
  });
  request.onsuccess = function(e){
  };
  request.onerror = function(e){
  };
  request.onabort = function(e){
    var error = e.target.error;
    if(error.name == 'QuotaExceededError'){
      console.log("容量エラーです")
    }
  };
  transaction.oncomplete = function(){
  };
  

  /*
  var localKeys = [];
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.openCursor();
  request.onsuccess = function(e){
    var cursor = e.target.result;
    if(cursor == null){
      return;
    }
    var data = cursor.value;
    var localKey = cursor.key;
    localKeys[localKeys.length] = localKey;
    console.log (localKey)
    console.log (data.hoge)
    cursor.continue();
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
    //実際は、oncompleteで繰り返し削除を行う必要性がある。
    var transaction = db.transaction([storeName],'readwrite');
    var store = transaction.objectStore(storeName);
    var request = store.delete(localKeys[0]);
    request.onsuccess = function(e){
    };
    request.onerror = function(e){
    };
    transaction.oncomplete = function(){
    };
  };
  */
};
openRequest.onerror = function(e) {
};

参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2
モダンブラウザのストレージ容量まとめ

2016/07/11

[JavaScript]Indexed Database APIでデータを削除

ObjectStoreからデータを取得するところまではできたので、次は、データを削除する方法について。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
  db = e.target.result;
  /*
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.count();
  request.onsuccess = function(e){
    var count = e.target.result;
    console.log(count)
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };
  */

  /*
  var transaction = db.transaction([storeName],'readwrite');
  var store = transaction.objectStore(storeName);
  var request = store.put({
    hoge : 'bar'
  });
  request.onsuccess = function(e){
  };
  request.onerror = function(e){
  };
  request.onabort = function(e){
  };
  transaction.oncomplete = function(){
  };
  */

  var localKeys = [];
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.openCursor();
  request.onsuccess = function(e){
    var cursor = e.target.result;
    if(cursor == null){
      return;
    }
    var data = cursor.value;
    var localKey = cursor.key;
    localKeys[localKeys.length] = localKey;
    console.log (localKey)
    console.log (data.hoge)
    cursor.continue();
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
    //実際は、oncompleteで繰り返し削除を行う必要性がある。
    var transaction = db.transaction([storeName],'readwrite');
    var store = transaction.objectStore(storeName);
    var request = store.delete(localKeys[0]);
    request.onsuccess = function(e){
    };
    request.onerror = function(e){
    };
    transaction.oncomplete = function(){
    };
  };

};
openRequest.onerror = function(e) {
};

で、実行したら、確かにデータ削除できた。

参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2

2016/07/10

[JavaScript]Indexed Database APIでデータを取得

ObjectStoreにデータを登録するところまではできたので、次は、実際にデータを取得する方法について。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
  db = e.target.result;
  /*
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.count();
  request.onsuccess = function(e){
    var count = e.target.result;
    console.log(count)
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };
  */

  /*
  var transaction = db.transaction([storeName],'readwrite');
  var store = transaction.objectStore(storeName);
  var request = store.put({
    hoge : 'bar'
  });
  request.onsuccess = function(e){
  };
  request.onerror = function(e){
  };
  request.onabort = function(e){
  };
  transaction.oncomplete = function(){
  };
  */

  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.openCursor();
  request.onsuccess = function(e){
    var cursor = e.target.result;
    if(cursor == null){
      return;
    }
    var data = cursor.value;
    var localKey = cursor.key;
    console.log (localKey)
    console.log (data.hoge)
    cursor.continue();
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };

};
openRequest.onerror = function(e) {
};

で、実行したら、確かにデータ取得できた。

参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2

2016/07/09

[JavaScript]Indexed Database APIでObjectStoreにデータを保存

先日、ObjectStoreに登録されているデータ数を取得するところまではできたので、次は、実際にデータを保存する方法について。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
  db = e.target.result;
  /*
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.count();
  request.onsuccess = function(e){
    var count = e.target.result;
    console.log(count)
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };
  */
  var transaction = db.transaction([storeName],'readwrite');
  var store = transaction.objectStore(storeName);
  var request = store.put({
    hoge : 'bar'
  });
  request.onsuccess = function(e){
  };
  request.onerror = function(e){
  };
  request.onabort = function(e){
  };
  transaction.oncomplete = function(){
  };
};
openRequest.onerror = function(e) {
};

で、実行したら、確かにデータ登録できた。

参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2

2016/07/08

[jQuery]複数selectorでdomを選択

いつもdomを選択する場合は、ならべくkey-valueっぽく、1keyで済ませるようにしているのですが、複数同時に指定したい場合があって、かつ、それが属性だった場合について調べました。

$('._hoge').filter('[data-foo][data-bar]')
めっちゃ単純だった。

2016/07/07

[JavaScript]Indexed Database APIでObjectStoreのデータ数を取得

ObjectStoreを作成するところまではできたので、次は、保存されているデータ数を取得する方法について。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
  db = e.target.result;
  var transaction = db.transaction([storeName],'readonly');
  var store = transaction.objectStore(storeName);
  var request = store.count();
  request.onsuccess = function(e){
    var count = e.target.result;
    console.log(count)
  };
  request.onerror = function(e){
  };
  transaction.oncomplete = function(){
  };
};
openRequest.onerror = function(e) {
};

という形でデータベースがオープンしてからトランザクションしないとエラーになってしまいます。

この辺、coffeeでもっと簡単に書けないかなー、かつ、かっこよく。


参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2
IndexedDB概要

2016/07/06

[JavaScript]Indexed Database APIでObjectStoreを作成

データベースを作成するところまではできたので、次は、オブジェクトを実際に保存するObjectStoreの作成方法について。

var db;
var indexedDBName = 'localDB';
var storeName = 'localStore';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;

//var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
  db = e.target.result;
  db.createObjectStore(storeName,{
    keyPath:'id',
    autoIncrement:true
  });
};
openRequest.onsuccess = function(e) {
 
};
openRequest.onerror = function(e) {
};

上を実行したら、確かにObjectStoreの作成ができた。

autoIncrementをtrueにするとデータが登録される度に、自動インクリメントしてくれるので便利ですね。

参考
【HTML5】Indexed Database API を真面目に勉強してみる
[HTML5] Indexed DBで検索結果をキャッシュする #2

2016/07/05

[JavaScript]Indexed Database APIでDatabaseを削除

昨日書いたエントリーではDatabaseを作成する方法について書いたので、今日は、削除する方法について。

var indexedDBName = 'localDB';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
/*
var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
};
openRequest.onsuccess = function(e) {
 
};
openRequest.onerror = function(e) {
};
*/
上を実行したら、確かにDBの削除ができた。

さらにコメントアウトをはずすと、毎回、アクセスする度に、新規のデータベースが作成される形になります。

参考
【HTML5】Indexed Database API を真面目に勉強してみる

2016/07/04

[JavaScript]Indexed Database APIでDatabaseを作成

今、作っているwebサービスでIndexed Database APIを使おうかなと思っているのだが、そもそも使い方がわからないので、調査してみた。

まずは、Databaseをオープンさせる必要があるので、下記のようなコードを書く必要がある。

var indexedDBName = 'localDB';
var version = 1;
var indexedDB;
indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
var openRequest = indexedDB.open(indexedDBName,version);
openRequest.onupgradeneeded = function(e) {
};
openRequest.onsuccess = function(e) {
 
};
openRequest.onerror = function(e) {
};
上を実行したら、確かにDBの作成はできた。

参考
【HTML5】Indexed Database API を真面目に勉強してみる

2016/07/03

[JavaScript]スロットの実装その2

昨日のエントリーでスロットを実装するプログラムの紹介をしましたが、それを編集して掲載さいているサイトがあったので、紹介。

jQuery + jQuery Easing Plugin

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8" />
  <title>Sample Slot:jQuery+jQuery Easing Plugin</title>
  <script src="libs/jquery-1.8.3.min.js" type="text/javascript"></script>
  <script src="libs/jquery.easing.1.3.js" type="text/javascript"></script>
  <script src="slots.js" type="text/javascript"></script>
  <link href="slots.css" rel="stylesheet" type="text/css" />
 </head>
 <body>
  <p align="center">
   回転スタートから停止までの時間:
   <input id="txt_duration" type="text" value="3" size="3" maxlength="3" />
   [秒]
  </p>
  <p align="center">
   アニメーション(回転)方式:
   <select id="sel_easing" size="1">
    <option selected>jswing</option>
    <option>easeInQuad</option>
    <option>easeOutQuad</option>
    <option>easeInOutQuad</option>
    <option>easeInCubic</option>
    <option>easeOutCubic</option>
    <option>easeInOutCubic</option>
    <option>easeInQuart</option>
    <option>easeOutQuart</option>
    <option>easeInOutQuart</option>
    <option>easeInQuint</option>
    <option>easeOutQuint</option>
    <option>easeInOutQuint</option>
    <option>easeInSine</option>
    <option>easeOutSine</option>
    <option>easeInOutSine</option>
    <option>easeInExpo</option>
    <option>easeOutExpo</option>
    <option>easeInOutExpo</option>
    <option>easeInCirc</option>
    <option>easeOutCirc</option>
    <option>easeInOutCirc</option>
    <option>easeInElastic</option>
    <option>easeOutElastic</option>
    <option>easeInOutElastic</option>
    <option>easeInBack</option>
    <option>easeOutBack</option>
    <option>easeInOutBack</option>
    <option>easeInBounce</option>
    <option>easeOutBounce</option>
    <option>easeInOutBounce</option>
   </select>
  </p>
  <div align="center">
   <div style="width:306px;" align="center">
    <div class="slots" id="slots_a">
     <div class="wrapper" style="margin-top: -200px;"></div>
    </div>
    <div class="slots" id="slots_b">
     <div class="wrapper" style="margin-top: -200px;"></div>
    </div>
    <div class="slots" id="slots_c">
     <div class="wrapper" style="margin-top: -200px;"></div>
    </div>
    <div style="text-align:center;clear:both;">
     <input id="btn_start" type="button" value="Start" onClick="go();" style="margin-top:4px;">
     <input id="btn_reset" type="button" value="Reset" onClick="reset();" style="margin-top:4px;" disabled>
    </div>
    <p id="result" style="text-align:center;color:red;font-size:42px;margin-top:0px"></p>
   </div>
  </div>
 </body>
</html>
body {
 background-color: white;
 padding: 0px;
 margin: 0px;
 font-size: 12px;
}

.slots {
 font-size: 100px;
 font-family: arial, helvetica, sans-serif;
 overflow: hidden;
 width: 100px;
 height: 100px;
 border: 1px solid black;
 float: left;
}

.slots .wrapper {
 margin-top: 3px;
 width: 100px;
}

.slots .slot {
 width: 100px;
 height: 100px;
 text-align: center;
}
var opts = ['1357464992_github.png', '1357465001_ffffound.png', '1357465007_live-journal.png', '1357465012_bebo.png', '1357465021_icon-dock.png', '1357465029_metacafe.png', '1357465036_newsvine.png'];
var results = new Array(3);
var time;
var select;
var columns;

$(document).ready(function() {
 onload();
});

function onload() {
 // initialize drawed this html page.
 columns = 0;
 addSlots($("#slots_a .wrapper"));
 addSlots($("#slots_b .wrapper"));
 addSlots($("#slots_c .wrapper"));
}

function go() {
 // initialize after pushed Start button.
 time = parseInt($("#txt_duration").val()) * 1000;
 select = document.getElementById('sel_easing');
 $("#btn_start").attr("disabled", "disabled");

 // addSlots($("#slots_a .wrapper"));
 moveSlots($("#slots_a .wrapper"));
 // addSlots($("#slots_b .wrapper"));
 moveSlots($("#slots_b .wrapper"));
 // addSlots($("#slots_c .wrapper"));
 moveSlots($("#slots_c .wrapper"));

 // refee.
 $(this).delay(time + 1000).queue(function() {
  if (results[0] == results[1] && results[1] == results[2]) {
   $("#result").text("当たり!");
  } else {
   $("#result").text("はずれ~");
  }
  $("#btn_reset").removeAttr("disabled");
  $(this).dequeue();
 })
}

function reset() {
 $("#slots_a .wrapper").children().remove();
 $("#slots_a .wrapper").css({
  "margin-top" : "-200px"
 });
 $("#slots_b .wrapper").children().remove();
 $("#slots_b .wrapper").css({
  "margin-top" : "-200px"
 });
 $("#slots_c .wrapper").children().remove();
 $("#slots_c .wrapper").css({
  "margin-top" : "-200px"
 });

 $("#btn_start").removeAttr("disabled");
 $("#btn_reset").attr("disabled", "disabled");
 $("#result").text("");
 onload();
}

function addSlots(jqo) {
 for (var i = 0; i < 15; i++) {
  var ctr = Math.floor(Math.random() * opts.length);
  jqo.append("<div class='slot'><img border='0' src='../images/" + opts[ctr] + "' /></div>");
  if (i == 12) {
   results[columns] = ctr;
   columns++;
  }
 }
}

function moveSlots(jqo) {
 time += Math.round(Math.random() * 1000);

 var marginTop = parseInt(jqo.css("margin-top"), 10)
 marginTop -= (10 * 100)

 jqo.stop(true, true);
 jqo.animate({
  "margin-top" : marginTop + "px"
 }, {
  'duration' : time,
  'easing' : select.options[select.selectedIndex].text
 });
}