//region離線檢測
//判斷設備是否能上網 navigator.onLine window事件online offline
//alert( navigator.onLine );html
//監測網絡變化
W.addHandler( window, "online", function () {
alert( "online" );
} );
W.addHandler( window, "offline", function () {
alert( "offline" );
} );
//endregionweb
//region應用緩存 描述文件 manifest file P627數據庫
//endregion數組
//region 數據存儲瀏覽器
//HTTP cookie
//該標準要求服務器對任意HTTP請求發送Set-Cookie HTTP頭做爲相應的一部分,其中包括會話信息緩存
//1.限制
//cookie在性質上是綁定在特定的域名下的。
// 當設定了一個cookie後,再給建立他的域名發送請求時,都會包含這個cookie。
// 這個限制確保了存儲在cookie中的信息只能讓批准的接受者訪問,而沒法被其餘域訪問
//cookie在客戶端計算機大小和數量都有限制 根據瀏覽器不一樣單個域下最多20-50個 整個cookie長度限制在2095b安全
//2.cookie的構成 只有名值對兒纔會被髮送到服務器 其餘參數都是服務器給瀏覽器的指示
// 名稱name 須要通過URL編碼
// 值value
// 域domain
// 路徑path
// 失效時間expires
// 安全標誌secure服務器
//設置了secure標誌的cookie只能經過SSL加密鏈接才能傳輸cookie
//設置在HTTP頭部分
// HTTP/1.1 200 OK
//Content-type:text/html
//Set-Cookie:name-value;expires=Mon,22-Jan-07 07:10:24 GMT;domain=.wrox.com;path=/;secure
//Other-header:other-header-value網絡
//3.JavaScript中的cookie
var CookieUtil = {
get : function ( name ) {
var cookieName = encodeURIComponent( name ) + "=",
cookieStart = document.cookie.indexOf( cookieName ),
cookieValue = null;
if ( cookieStart > -1 ) {
var cookieEnd = document.cookie.indexOf( ";", cookieStart );
if ( cookieEnd == -1 ) {
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent( document.cookie.substring( cookieStart + cookieName.length, cookieEnd ) );
}
return cookieValue;
},
set : function ( name, value, expires, path, domain, secure ) {
var cookieText = encodeURIComponent( name ) + "=" + encodeURIComponent( value );
if ( expires instanceof Date ) {
cookieText += ";expires=" + expires.toGMTString();
}
if ( path ) {
cookieText += ";path=" + path;
}
if ( domain ) {
cookieText += ";domain=" + domain;
}
if ( secure ) {
cookieText += ";secure";
}
document.cookie = cookieText; //並不會覆蓋原來的cookie 除非名稱已經存在
},
unset : function ( name, path, domain, secure ) {
this.set( name, "", new Date( 0 ), path, domain, secure );
}
};
CookieUtil.set( "name", "zodiac", new Date( "January 1,2020" ) );
//CookieUtil.unset("name");
//alert( CookieUtil.get( "name" ) );
//4.子cookie 爲了繞開瀏覽器對單域名下的cookie的限制,使用子cookie name=name1=value1=&name2=value2 自由操做 可是這樣會增長cookie的長度
var SubCookieUtil = {
get : function ( name, subName ) {
var subCookies = this.getAll( name );
if ( subCookies ) {
return subCookies[subName];
}
else {
return null;
}
},
getAll : function ( name ) {
var cookieName = encodeURIComponent( name ) + "=",
cookieStart = document.cookie.indexOf( cookieName ),
cookieValue = null,
cookieEnd,
subCookies,
i,
parts,
result = {};
if ( cookieStart > -1 ) {
cookieEnd = document.cookie.indexOf( ";", cookieStart );
if ( cookieEnd == -1 ) {
cookieEnd = document.cookie.length;
}
cookieValue = document.cookie.substring( cookieStart + cookieName.length, cookieEnd );
if ( cookieValue.length > 0 ) {
subCookies = cookieValue.split( "&" );
for ( i = 0, len = subCookies.length; i < len; i++ ) {
parts = subCookies[i].split( "=" );
result[decodeURIComponent( parts[0] )] = decodeURIComponent( parts[1] );
}
return result;
}
}
},
set : function ( name, subName, value, expires, path, domain, secure ) {
var subCookies = this.getAll( name ) || {};
subCookies[subName] = value;
this.setAll( name, subCookies, expires, path, domain, secure );
},
setAll : function ( name, subCookies, expires, path, domain, secure ) {
var cookieText = encodeURIComponent( name ) + "=",
subCookieParts = new Array(),
subName;
for ( subName in subCookies ) {
if ( subName.length > 0 && subCookies.hasOwnProperty( subName ) ) {
subCookieParts.push( encodeURIComponent( subName ) + "=" + encodeURIComponent( subCookies[subName] ) );
}
}
if ( subCookieParts.length > 0 ) {
cookieText += subCookieParts.join( "&" );
if ( expires instanceof Date ) {
cookieText += ";expires=" + expires.toGMTString();
}
if ( path ) {
cookieText += ";path=" + path;
}
if ( domain ) {
cookieText += ";domain=" + domain;
}
if ( secure ) {
cookieText += ";secure";
}
}
else {
cookieText += ";expires=" + (new Date( 0 )).toGMTString();
}
document.cookie = cookieText;
},
unset : function ( name, subName, path, domain, secure ) {
var subCookies = this.getAll( name );
if ( subCookies ) {
delete subCookies[subName];
this.setAll( name, subCookies, null, path, domain, secure );
}
},
unsetAll : function ( name, path, domain, secure ) {
this.setAll( name, null, new Date( 0 ), path, domain, secure );
}
};
//endregion
//region Web存儲機制
//Storage類型 HTML5 Storage類型都有公共方法setItem getItem removeItem key 大小限制根據瀏覽器2.5M--5M
//1.sessionStorage保持到會話結束,即保存到瀏覽器關閉 合適會話類的小段數據
sessionStorage.setItem( "name", "zodiac" );//使用方法存儲數據
sessionStorage.age = "22";//使用屬性存儲數據
var name = sessionStorage.getItem( "name" );//使用方法獲取數據
var age = sessionStorage.age;//使用屬性獲取數據
//sessionStorage.removeItem("name");
//delete sessionStorage.age 使用delete刪除一個值 在Webkit中無效
// W.log( sessionStorage.key( 0 ) );//逆序獲取指定位置上的名字
//2.localStorage HTML5標準 老版本使用globalStorage 跨會話第存儲數據,但有特定的訪問限制
// globalStorage須要指定那些域能夠訪問該數據
// 要訪問localStorage頁面必須來自同一域名(子域名無效),同一協議,同一端口上。至關於globalStorage[location.host]
//二者的數據都保存到經過JavaScript刪除或者用戶清除瀏覽器緩存爲止
//兼容
function getLocalStorage() {
if ( typeof localStorage == "object" ) {
return localStorage;
}
else if ( typeof globalStorage == "object" ) {
return globalStorage[location.host];
}
else {
throw new Error( "Local Storage not available" );
}
}
var localStorage = getLocalStorage();
localStorage.setItem( "name", "zodiac" );
//Storage事件 ie8和FireFox只實現了domain屬性 WebKit不支持此事件
// 爲Storage對象進行任何修改,都會在文檔上觸發storage事件 set get remove delete等都會觸發
W.addHandler( document, "storage", function ( event ) {
var domain = event.domain,
key = event.key,
newValue = event.newValue,
oldValue = event.oldValue;
} );
//endregion
//region IndexedDB
//IndexedDB思想是建立一套API,方便保存和讀取JavaScript對象,同時還支持查詢及搜索
//IndexedDB操做徹底是異步的,大多數操做會以請求進行,但這些操做會在後期執行,若是成功則返回數據,失敗則返回錯誤。
//差很少每次IndexedDB操做都須要註冊onerror和onsuccess事件處理程序,以確保適當地處理結果
//1.數據庫indexedDB本質是一個數據庫 和傳統數據庫不一樣在於使用對象保存數據,而不是使用表來保存數據。
//一個indexedDB數據庫,就是一組位於相同命名空間下的對象的集合
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;
function closeDB( db ) {
db.close();
}
function deleteDB( name ) {
debugger;
indexedDB.deleteDatabase( name );
}
function openDB( myDB, successHandler, upGradeHandler ) {
var version = myDB.version || 1,
request = indexedDB.open( myDB.name, version );
request.onerror = function ( e ) {
console.log( e.currentTarget.error.message );
};
request.onsuccess = function ( e ) {
myDB.db = e.target.result;
successHandler && successHandler();
};
request.onupgradeneeded = function ( e ) { //請求數據庫版本變化句柄
console.log( 'DB version changed to ' + version );
myDB.db = e.target.result;
upGradeHandler && upGradeHandler();
};
}
function addData( db, storeName, addData ) {
var transaction = db.transaction( storeName, 'readwrite' ),//打開一個事務,參數一能夠爲字符串或者數組, 參數二爲訪問數據的方式readony readwrite
store = transaction.objectStore( storeName );
for ( var i = 0; i < addData.length; i++ ) {
store.add( addData[i] );
}
}
function getDataByKey( db, storeName, value ) {
var transaction = db.transaction( storeName, 'readwrite' );
var store = transaction.objectStore( storeName );
var request = store.get( value );
request.onsuccess = function ( e ) {
var student = e.target.result;
console.log( student.name );
};
}
function updateDataByKey( db, storeName, value ) {
var transaction = db.transaction( storeName, 'readwrite' );
var store = transaction.objectStore( storeName );
var request = store.get( value );
request.onsuccess = function ( e ) {
var student = e.target.result;
student.age = 35;
store.put( student );
};
}
function deleteDataByKey( db, storeName, value ) {
var transaction = db.transaction( storeName, 'readwrite' );
var store = transaction.objectStore( storeName );
store.delete( value );
}
function clearObjectStore( db, storeName ) {
var transaction = db.transaction( storeName, 'readwrite' );
var store = transaction.objectStore( storeName );
store.clear();
}
function deleteStore( db, storeName ) {
db.objectStoreNames.contains( storeName ) && db.deleteObjectStore( storeName );
}
//索引是惟一的沒問題,若是索引不惟一也只會取到第一個匹配值,要想獲得全部符合條件的值就須要使用遊標了
function getDataByIndex( db, storeName, index ) {
var transaction = db.transaction( storeName );
var store = transaction.objectStore( storeName );
var index = store.index( "nameIndex" );
index.get( index ).onsuccess = function ( e ) {
var student = e.target.result;
console.log( student.id );
}
}
//遊標 cursor有屬性direction key value primaryKey 方法update() delete() continue() advance()
// cursor.continue(key)若是指定了key會移動打指定key值處 沒有則會使遊標下移直到沒有數據返回undefined。cursor.advance(count)向前移動多少
function fetchStoreByCursor( db, storeName ) {
var transaction = db.transaction( storeName );
var store = transaction.objectStore( storeName );
var request = store.openCursor();
request.onsuccess = function ( e ) {
var cursor = e.target.result;
if ( cursor ) {
console.log( cursor.key );
var currentStudent = cursor.value;
console.log( currentStudent.name );
cursor.continue();
}
};
}
//遊標+索引
function getMultipleData( db, storeName ) {
var transaction = db.transaction( storeName );
var store = transaction.objectStore( storeName );
var index = store.index( "ageIndex" );
var IDBKeyRange=window.IDBKeyRange||window.webkitIDBKeyRange;
var request = index.openCursor( IDBKeyRange.only( 26 ));
// index.openCursor()/index.openKeyCursor()方法在不傳遞參數的時候會獲取object store全部記錄,像上面例子同樣咱們能夠對搜索進行篩選
// 可使用key range 限制遊標中值的範圍,把它做爲第一個參數傳給 openCursor() 或是 openKeyCursor()
// 第二個可選參數表示遊標方向默認是向後
// 有:IDBCursor.NEXT向後 IDBCursor.NEXT_NO_DUPLICATE跳太重複向後 IDBCursor.PREV向前 IDBCursor.PREV_NO_DUPLICATE跳太重複向前
// IDBKeyRange.only(value):只獲取指定數據
// IDBKeyRange.lowerBound(value,isOpen):獲取最小是value的數據,第二個參數用來指示是否排除value值自己,也就是數學中的是不是開區間
// IDBKeyRange.upperBound(value,isOpen):和上面相似,用於獲取最大值是value的數據
// IDBKeyRange.bound(value1,value2,isOpen1,isOpen2):不用解釋了吧
request.onsuccess = function ( e ) {
var cursor = e.target.result;
if ( cursor ) {
var student = cursor.value;
console.log( student.id );
cursor.continue();
}
}
}
function getMultipleData( db, storeName ) {
var transaction = db.transaction( storeName );
var store = transaction.objectStore( storeName );
var index = store.index( "nameIndex" );
var request = index.openCursor( IDBKeyRange.bound( 'B', 'F', false,
true
) );
request.onsuccess = function ( e ) {
var cursor = e.target.result;
if ( cursor ) {
var student = cursor.value;
console.log( student.name );
cursor.continue();
}
}
}
var myDB = {
name : "zodiac",
version : 1,
db : null
};
function successHandler() {
//在對新數據庫作任何事情以前,須要開始一個事務。事務中須要指定該事務跨越哪些object store。
var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction,
transaction = myDB.db.transaction( ['students', 'teacher'], "readonly" ),
objectStore = transaction.objectStore( 'students' ); //獲取students object store objectStore至關於表
//開啓事務後插入數據
addData( myDB.db, 'students', students );
addData( myDB.db, 'teacher', teacher );
}
function upGradeHandler() {//跟新數據庫 建表 必須在數據庫版本變化後才能執行
if ( !myDB.db.objectStoreNames.contains( 'students' ) ) {
var store = myDB.db.createObjectStore( 'students', {keyPath : "id", autoIncrement : true} ); //keyPath主鍵 keyGenerator其餘參數 autoIncrement默認爲true
store.createIndex( 'ageIndex', 'age', {unique : false} ); //建立索引 索引名稱 索引屬性字段名 索引屬性值是否惟一
store.createIndex( 'nameIndex', 'name', {unique : true} );
}
if ( !myDB.db.objectStoreNames.contains( 'teacher' ) ) {
myDB.db.createObjectStore( 'teacher', {keyPath : "id", autoIncrement : true} );
}
}
var students = [
{
id : 1001,
name : "Byron",
age : 24
},
{
id : 1002,
name : "Frank",
age : 30
},
{
id : 1003,
name : "Aaron",
age : 26
}
];
var teacher = [
{
id : 1,
name : "aa",
age : 44
},
{
id : 2,
name : "bb",
age : 45
},
{
id : 3,
name : "cc",
age : 46
}
];
openDB( myDB, null, upGradeHandler );
openDB( myDB, successHandler );
// deleteDB("zodiac"); //endregion