HTML5 のデータベース機能とオフライン機能を使用する: 第 1 回 オフラインのデータ編集機能とデータ同期機能を提供する

HTML5 は Web エクスペリエンスや LOB (Line of Business) アプリケーションを変える可能性があります。オフライン機能、そしてローカルに永続化可能なストレージ機能により、従来は専用のデスクトップ・アプリケーション開発フレームワークを使用しない限り実現できなかったリッチなユーザー・エクスペリエンスをオンラインでもオフラインでも実現することができます。この記事では HTML5 のオフライン機能とローカル・ストレージ機能を活用する方法について説明します。またサンプル・アプリケーションを示しながら、一般的な問題を回避するための方法についても説明します。

Brian J Stewart, Principal Consultant, Aqua Data Technologies, Inc.

Photo of Brian StewartBrian J. Stewart は、Aqua Data Technologies で主任コンサルタントを務めています。彼が設立したこの会社は、コンテンツ・マネージメント、XML 技術、そしてエンタープライズ・クライアント/サーバーおよび Web システムを専門としています。彼は Java EE および Microsoft .NET プラットフォームをベースとしてエンタープライズ・ソリューションを設計、開発しています。



2012年 8月 23日

はじめに

HTML バージョン 5 (HTML5) は 2014 年まで W3C (World Wide Web Consortium) の勧告にはならない見通しです。HTML5 は正式な標準ではありませんが、Web ブラウザーのベンダーは HTML5 の機能をブラウザーに追加したり、宣伝したりしています。HTML5 は既にインターネットの Web サイトや LOB (Line Of Business) アプリケーションの Web エクスペリエンスを変えつつあります。Amazon Kindle Cloud Reader など、多くの Web サイトは既に HTML5 を利用しています。HTML5 の機能のうち、LOB アプリケーションを大幅に変えるであろう 2 つの重要な機能がオフライン・アプリケーションのサポート機能とローカル永続ストレージ機能です。HTML5 は正式な標準ではないため、どのブラウザーでも必ず同じように HTML5 がサポートされているわけではありません。

この記事では、提案されている HTML5 標準によるオフライン・アプリケーションのサポート機能と、さまざまな永続ストレージ機能について説明します。これらの機能の説明は、サンプル・アプリケーションを利用して行います。


サンプル・アプリケーション

この記事で取り上げる Contact Manager というサンプル・アプリケーションは、連絡先情報 (氏名、住所、電話番号) を管理する機能を提供するアプリケーションです。このアプリケーションには、オンライン・モードとオフライン・モード、そして単純なデータ同期機能があります。オンライン・モードに切り換えると、ローカルで行われたデータの変更はサーバーと同期されます。オフラインの場合には、データはローカルの永続ストレージに保存されています。このアプリケーションは永続ストレージのための 4 つの基本機能、つまり CRUD (Create, Read, Update, Delete) をオンライン・モードでもオフライン・モードでもサポートしています。

アーキテクチャー

図 1 は、この Contact Manager アプリケーションのアーキテクチャーの概要です。サーバーのアーキテクチャーは 2 つのサーブレット、2 つのビジネス・サービス、2 つのデータ・プロバイダーで構成されています。ユーザー・インターフェース (UI) は、1 つの HTML ファイルと 4 つの JavaScript モジュール、そして最新バージョンの jQuery ライブラリーへの外部参照で構成されています。

図 1. アプリケーションのアーキテクチャーの概要
アプリケーションのアーキテクチャーの概要

データ・モデル

データ・モデルは、図 2 のように contact と state という 2 つのデータ・エンティティーで構成されています。contact テーブルには実際の連絡先データが含まれ、state テーブルには状態選択リスト用の辞書の値が含まれています。

図 2. データ・モデル
データ・モデル

サーバー・インターフェース

サーバー・インターフェースは、連絡先サーブレット (ContactServlet) と辞書サーブレット (DictionaryServlet) という 2 つのサーブレットで構成されています。表 1 は 2 つのサーブレットの概要です (サーブレットの実装と、それに対応するビジネス・サービスおよびデータ・プロバイダーの実装については、この記事では説明しません)。

表 1. サーブレットの概要
サーブレット名操作パラメーター説明
DictionaryServletgetstatesなし状態の配列を JSON (JavaScript Object Notation) フォーマットで返します。
ContactServletgetallcontactsなし連絡先レコードの配列を JSON フォーマットで返します。
ContactServletdeletecontactId - 削除対象の連絡先の ID指定された連絡先レコードを削除し、削除操作が成功したかどうかを示すブール値のフラグを含む JSON オブジェクトを返します。
{"result": <true/false>}
ContactServletsave
  • contactId - 保存対象の連絡先の ID (ゼロより大きい場合は更新操作を表します)
  • firstName - 「first name (名)」フィールドの値
  • lastName - 「last name (姓)」フィールドの値
  • street1 - 「street 1 (住所 1)」フィールドの値
  • street2 - 「street 2 (住所 2)」フィールドの値
  • city - 「city (市町村)」フィールドの値
  • state - 「state (州)」フィールドの値
  • zipCode - 「zip code (郵便番号)」フィールドの値
新規または更新された連絡先の ID と、保存操作が成功したかどうかを示すブール値のフラグとを含む JSON オブジェクトを返します。
{"contactId": <id>, "result": <true/false>"}

サーバー・インターフェースを呼び出す

リスト 1 のコードは、連絡先サーブレットを非同期で呼び出し、オンライン・データベースに保存された連絡先を取得する方法を示しています。このコードは jQuery の getJSON 関数を使用して連絡先サーブレットを呼び出しています。

リスト 1. サーバーから連絡先を取得する
function loadOnlineContacts() 
{
	$('#contactList').empty();
	$('#contactList').append('Loading contact data...');
	
	var url = '/html5app/contact?operation=getallcontacts';
	
	$.getJSON(url, function(data) {
		saveOfflineContactData(data);
		displayContactData(data);		
	});
}

リスト 2 のコードは新規または更新された連絡先をサーバーに保存する方法を示しています。このコードは jQuery の ajax 関数を使用して、HTTP の POST によって連絡先サーブレットにデータを送信しています。

リスト 2. サーバーに連絡先を保存する
function postEditedContact(dataString) {
	postEditedContact(dataString, false);	
}

function postEditedContact(dataString, suppressAlert) {
var contactId = $('input[name="contactId"]')[0].value;

$.ajax({  
type: "POST",  
url: "/html5app/contact",  
data: dataString,  
cache: false,
dataType: "json",
success: function(data) {
	var result = data.result;
	
	if (result) 
	{
		if (contactId > 0)
		{
		if (!suppressAlert) {
		alert("Contact was successfully updated.");
		}
		var lastModifyDate = data.lastModifyDate;
		$('input[name="lastModifyDate"]')[0].value = lastModifyDate;
		}
		else 
		{
		if (!suppressAlert) {
			alert("Contact was successfully created.");
		}
		
		var lastModifyDate = data.lastModifyDate;
		$('input[name="lastModifyDate"]')[0].value = lastModifyDate;
		$('input[name="contactId"]')[0].value = data.contactId;
		}
		
		loadOnlineContacts();

		hideEditForm();
	}
	else 
	{
		alert('An error occurred saving contact ' + contactId + '.');
	}
}
});  
}

最後に紹介する関数はオンライン・データベースからレコードを削除するための関数です。サーバーからレコードを削除する方法をリスト 3 に示します。このコードは jQuery の getJSON 関数を使用して連絡先サーブレットを呼び出しています。

リスト 3. サーバーから連絡先を削除する
function deleteOnlineContact(contactId, suppressAlert){
	var url = '/html5app/contact?operation=delete&contactId=' + contactId;
	
	$.getJSON(url, function(data) {
		var result = data.result;
		if (result) {
			if (!suppressAlert) {
				alert('Contact deleted');
			}
			loadOnlineContacts();
		}
		else {
			alert('Contact ' + contactId + 'not deleted');
		}
	});		
}

ローカル・データ・プロバイダーを作成する

ローカル・データ・プロバイダーはすべての選択リストと連絡先データをローカルに永続化します。HTML5 仕様には永続ストレージの選択肢がいくつかあります。どの技術を使用するかの選択は、データ・ストレージとブラウザーに対するサポート要件に依存します。以下のセクションでは、永続ストレージの 3 つの技術について、また主要な Web ブラウザーのすべてがサポートする永続ストレージ技術を使用したローカル・データ・プロバイダーの実装について説明します。

HTML5 に関連する永続ストレージ技術としては、以下の 3 つがあります。

  • localStorage ― localStorage はフラットなキー・バリュー・ストアを使用して単純にデータを保存します。主要なブラウザー (Apple Safari、Google Chrome、Microsoft Windows Internet Explorer、Mozilla Firefox、Opera など) はすべて、localStorage をサポートしています。HTML5 の localStorage は同期型であり、現状では主要なプラットフォームおよびブラウザーのすべてでサポートされている唯一のデータベース・ストレージ・メカニズムです。
  • WebSQL ― WebSQL は元々、Transact-SQL ベースのデータベースを Web ブラウザーで実現するためのものでした。WebSQL は一般的なリレーショナル・データベース (IBM DB2、Microsoft SQL Server、Oracle MySQL Server、Oracle Database など) と似ているため、容易に習得することができます。WebSQL は、Safari、Chrome、Opera など、いくつかのブラウザーでサポートされていますが、Firefox と Internet Explorer ではサポートされていません。WebSQL に関して提案された仕様はもはや開発されていないため、WebSQL はおそらく徐々に消えていくものと思われます。
  • IndexedDB (Indexed database) ― IndexedDB は、商用のクラウド・サービスとして提供されている多くのデータ・ストレージと似た、インデックスが使える階層型のキー・バリュー・ストアです。WebSQL 仕様の開発が行われなくなった一方で支持されるようになった IndexedDB は、現在 Firefox と Chrome でサポートされており、将来は Internet Explorer 10 でもサポートされる予定です。IndexedDB の API (Application Programming Interface) は非同期型であり、インデックス機能、クエリー機能、トランザクション機能をサポートしています。

多くのブラウザーで localStorage がサポートされていることから、この記事のサンプル・ソリューションでは JSON と localStorage を使用して永続ストレージを作成します。

ローカル・データ・プロバイダー

localStorage の方式では、連絡先データと辞書データを JSON の文字列としてシリアライズし、その文字列を localStorage に保存することでデータを永続化します。データを取得する場合には、JSON オブジェクトの配列としてデータをデシリアライズして処理します。

ローカルにデータを保存する

リスト 4 に連絡先データを localStorage に保存する方法を示します。ここでは、サーバーが返す JSON データを 1 つの文字列へとシリアライズするために、JavaScript 関数 JSON.stringify を使用しています。これにより、連絡先データを localStorage に保存することができます。

リスト 4. localStorage にデータを保存する
// fetch data from server
...
			
// convert JSON data to a string
var contactDataString = JSON.stringify(data);

// persist contact data to localstorage
localStorage.setItem("contactData", contactDataString);

ローカルでデータを取得する

リスト 5 に localStorage からデータを取得する方法を示します。まず、localStorage から JSON の文字列を取得します。取得した文字列は、文字列を JSON オブジェクトの配列にデシリアライズする JavaScript 関数 eval を使用して JSON オブジェクトに変換します。変換後のデータは、カスタムの JavaScript 関数 displayContactData を使用して表示します。

リスト 5. localStorage からデータを読み取る
function loadOfflineContacts() 
{
	$('#contactList').empty();
	$('#contactList').append('Loading contact data...');
	
	var dataStr = localStorage.getItem("contactData");
	var data = eval('(' + dataStr + ')');
	
	displayContactData(data);
}

ローカルでレコードを削除する

リスト 6 に localStorage からレコードを削除する方法を示します。

リスト 6. localStorage からレコードを削除する
function deleteOfflineContact(contactId) {
	var dataStr = localStorage.getItem("contactData");
	var data = eval('(' + dataStr + ')');
	
	var recordUpdated = false;
	$.each(data, function(i,item){
		if (item.id == contactId) {
			item.isDeleted=true;
			recordUpdated = true;
			return false;
		}	
	});
	
	if (recordUpdated) {
		dataStr = JSON.stringify(data);
		localStorage.setItem("contactData", dataStr);
		alert("Contact was successfully deleted.");
		
		loadOfflineContacts();
	}
}

このコードは以下の内容を実行します。

  • ローカル・ストレージからデータベースを読み取り、デシリアライズします。
  • contactId レコードが見つかるまで、レコードに対して繰り返し処理を行います。
  • isDeleted フラグを true にセットします。
  • データ同期関数の中で isDeleted フラグを使用します。(「データの同期」セクションを参照。)
  • localStorage にデータを永続化します。するとデータ・グリッドが更新されます。

ローカルでレコードを更新または作成する

リスト 7 に localStorage でレコードを更新または作成する方法を示します。

リスト 7. localStorage でレコードを更新する
function updateLocalContact() {
	var dataStr = localStorage.getItem("contactData");
	var data = eval('(' + dataStr + ')');
	
	var contactId = $('input[name="contactId"]')[0].value;
	
	var recordUpdated = false;
	if (contactId > 0) {
		$.each(data, function(i,item){
			if (item.id == contactId) {
				item.isDirty=true;
				item.firstName = $('input[name="firstName"]')[0].value;
				item.lastName = $('input[name="lastName"]')[0].value;
				item.street1 = $('input[name="street1"]')[0].value;
				item.street2 = $('input[name="street2"]')[0].value;
				item.city = $('input[name="city"]')[0].value;
				item.state = $('select[name="state"]')[0].value;
				item.zipCode = $('input[name="zipCode"]')[0].value;	
				recordUpdated = true;
				return false;
			}	
		});
	}
	else {		
		var newContactId = 0;
		var nextId = 0;
		while(newContactId == 0) {
			var found = false;

			nextId = nextId - 1;
			$.each(data, function(i,item){
				if (item.id == nextId) {
					found = true;
					return false;
				}
			});
			if (!found) {
				newContactId = nextId;
			}
		}
		var lastModifyDate = "";
		var newContact = {"street2": $('input[name="street2"]')[0].value,
				"id":newContactId,
				"street1":$('input[name="street1"]')[0].value,
				"lastName":$('input[name="lastName"]')[0].value,
				"isDirty":true,
				"zipCode":$('input[name="zipCode"]')[0].value,
				"state":$('select[name="state"]')[0].value,
				"lastModifyDate": lastModifyDate,
				"isDeleted":false,
				"firstName":$('input[name="firstName"]')[0].value,
				"city":$('input[name="city"]')[0].value};
		var nextIndex = data.length;
		data[nextIndex] = newContact;
		recordUpdated=true;
	} 
	
	if (recordUpdated) {
		dataStr = JSON.stringify(data);
		localStorage.setItem("contactData", dataStr);
		alert("Contact was successfully updated.");
	}
	
	hideEditForm();
}

リスト 7 を見るとわかるように、ここでは以下の内容を実行しています。

  • localStorage からデータベースを読み取り、デシリアライズします。
  • 保存対象のレコードの contactId がゼロより大きい場合 (更新が発生した場合) には、その contactId を id に持つレコードが見つかるまで順にレコードが調べられ、該当するレコードが見つかったら、そのレコードが更新されます。
  • それ以外の場合として、レコードが新規の場合 (contactId はゼロではありません) には、使用されていない負の contactId のなかで最も大きい値 (絶対値が最も小さい値) の contactId を検索します。
  • その contactId を新しいレコードに割り当てます。
  • 新しいレコードをデータベースに追加します。

そしてそのデータは JSON の文字列としてシリアライズされ、localStorage に保存されます。サーバーと同期する際に、有効な (ゼロより大きな) contactId が割り当てられます。負の ID はレコードが新規であることを示すための一時的な ID です。

localStorage に関して以下の点を理解しておくことが重要です。

  • 5MB までに制限されています (さらに大きなデータ・ストレージが必要な場合には IndexedDB を使用する必要があります)。
  • すべての主要な Web ブラウザーでサポートされています。
  • 文字列の値以外では動作しません。

次に、HTML5 を使用して UI を作成します。


HTML5 を使用して UI を作成する

このサンプル・アプリケーション Contact Manager には、1 つのページで構成される単純な UI があります。この UI では各レコードを編集、削除することができ、また新しいレコードを作成することができます。CSS (Cascading Style Sheets) と、(jQuery による) 動的 HTML を使用することで、作成と編集のためのサブフォームを必要に応じて表示したり非表示にしたりすることができます。

一貫性のあるユーザー・エクスペリエンスを実現するために、オンラインでもオフラインでも同じページを使用します。唯一の違いは、ある操作を実行した時にどちらのデータ・プロバイダーを呼び出すか、という点です。このアプリケーションを図 3 に示します。

図 3. Contact Manager アプリケーション
Contact Manager アプリケーション

JavaScript モジュール

このアプリケーションは以下の 4 つのカスタム JavaScript モジュールで構成されています。

  • core.js は一般的な JavaScript 関数を提供し、他のモジュールで使用されます。
  • formEvents.js はフォームとボタンのイベント・ハンドラーを提供します。formEvents.js はオンライン状態であるかオフライン状態であるかに応じて、適切なデータ・プロバイダーにデータベースの操作を委ねます。
  • onlinedb.js はオンラインの場合にサーバーと通信するための機能を提供します。
  • offlinedb.js はローカルのデータ・ストレージ機能を提供します。

また、すべてのモジュールは最新バージョンの jQuery ライブラリーを使用してデータのトラバース、非同期の Web リクエスト、動的 HTML の処理を行います。クライアントは JSON を使用してサーバーと通信します。

オフライン・アプリケーションのマニフェスト

HTML5 のオフライン機能では、静的なファイルやリソースをキャッシュすることができます。オフライン・アプリケーションのマニフェスト・ファイル (.appcache) は Web アプリケーションのオフライン機能を実現するための重要なファイルです。このマニフェスト・ファイルで以下の情報を定義します。

  • オフラインの間に利用できるリソースとページはどれか
  • オンラインの場合にのみ利用できるリソースはどれか
  • オフラインでは利用できないリソースに関して表示されるフォールバック・ページ

マニフェスト・ファイルは、CACHENETWORKFALLBACK という 3 つのセクションで構成されます。CACHE の下にあるページとリソースはローカルにキャッシュされます。NETWORK の下にあるページとリソースはキャッシュされず、オンラインの場合にのみ利用可能です。要求されたページがオフラインで利用できない場合、FALLBACK で指定されるページが表示されます。NETWORK セクションのアスタリスク (*) により、他のすべてのページとサーブレットはオンラインの場合にのみ利用可能であることが確実になります。この「*」がない場合には、(たとえオンラインの場合でも) サーブレットの呼び出しは失敗します。リスト 8 に Contact Manager のマニフェスト・ファイルを示します。

リスト 8. オフライン・アプリケーションのマニフェスト
CACHE MANIFEST
# Revision 1
CACHE:
default.html
list.html
scripts/core.js
scripts/localdb.js
scripts/onlinedb.js
scripts/formEvents.js
http://code.jquery.com/jquery-1.7.2.min.js
NETWORK:
*
FALLBACK:
/ offline.html

オフライン・アプリケーションを扱う場合には以下の点を理解することが重要です。

  • オフライン・アプリケーションのマニフェスト・ファイルの拡張子 .appcache を text/cache-manifest という MIME (Multipurpose Internet Mail Extension) タイプにマッピングする必要があります。Apache Tomcat の場合、そのためにはサーバーの web.xml ファイルに (Web アプリケーションの web.xml ファイルではありません) mime-mapping エントリーを追加します。ほとんどのブラウザーは MIME タイプが不適切な場合はオフライン・アプリケーションのマニフェストを暗黙的に無視します。
  • オフライン・アプリケーションのマニフェスト・ファイルがある場合には、(オンラインの場合であっても) ローカルにキャッシュされたリソースが必ず使用されます。
  • ローカル・リソースが更新されるのはオフライン・アプリケーションのマニフェスト・ファイルが変更された場合のみであり、通常はマニフェスト・ファイルのコメント内にあるリビジョン番号を変更することでローカル・リソースが更新されます。HTML リソースや CSS リソースへの変更はアプリケーションのマニフェスト・ファイルが変更されるまで Web ブラウザーには反映されません。
  • オフラインで使用可能なページには必ず <html lang="en" manifest="app.appcache"> という記述を含める必要があります。

オンラインかオフラインか

navigator.onLine というブール値と JavaScript を使用することで、アプリケーションがオンラインかオフラインかを検出することができます。アプリケーションがオンラインの場合には navigator.onLine は True を返します。

フォーム・イベント (オンラインまたはオフラインの処理)

Contact Manager では、オンライでもオフラインでも同じフォームを使用します。このソリューションを実現するためのカギはボタンとフォームのイベント・ハンドラーにあります。navigator.onLine を調べることで、(ローカルまたはオンラインの) どちらの操作を呼び出すかを判断します。リスト 9 に連絡先データをロードする例を示します。

リスト 9. (HTML BODY の onLoad イベントで) データをロードする
if (navigator.onLine) 
{	
	// selection list needs to be populated prior to synchronizing data
	// the list is updated from the online dictionary later
	populateOfflineStates(); 
	
	setStatusText("Synchronizing contact data with server...");
	synchronizeContacts();

	setStatusText("Loading dictionary data from server...");		
	populateOnlineStates();
	
	setStatusText("Loading contact data from server...");
	loadOnlineContacts();
}
else 
{
	alert('You are currently offline.');
	populateOfflineStates();
	setStatusText("Loading contact data from local storage...");
	loadOfflineContacts();
}

データの同期

オンラインの場合、すべての CRUD 操作にサーブレットを使用し、作成、変更、削除の操作を行います。オンライン・データベースが変更されるとローカル・キャッシュも更新されます。

オフラインの場合、すべての CRUD 操作にローカル・データ・プロバイダーを使用して変更を永続化します。再度サーバーに接続されると、以下の動作が実行されます。

  • ローカルで作成されたレコードはすべてサーバーに永続化されます。
  • ローカルで変更されたレコードはすべてサーバーでも更新されます。
  • ローカルで削除されたレコードはすべてサーバーから削除されます。

リスト 10 は完全な同期方法を示しています。同期の際には同じオンライン機能を使用して作成、更新、削除の操作が実行されます。最初のステップとして、jQuery の $.each 関数を使用してローカル・レコードに対して繰り返し処理を実行します。

ローカルで更新または作成されたレコードには、isDirty プロパティーを使用してフラグが立てられます。save 操作では一意のレコード ID が負の場合 (つまり MySQL データベースによってレコードが割り当てられていない場合)、その save 操作は新規とみなされます。ローカルで削除されたレコードには isDeleted プロパティーを使用してフラグが立てられます。

リスト 10. オフラインでの変更にサーバーを同期させる
var recordsUpdated = 0;
var recordsCreated = 0;
var recordsDeleted = 0;

$.each(data, function(i,item){
	if (item.isDeleted) {
		deleteOnlineContact(item.id, true);
		recordsDeleted++;
	}		
	else if (item.isDirty && !item.isDeleted) {
		$('input[name="contactId"]')[0].value = item.id;
		$('input[name="firstName"]')[0].value = item.firstName;
		$('input[name="lastName"]')[0].value = item.lastName;
		$('input[name="street1"]')[0].value = item.street1;
		$('input[name="street2"]')[0].value = item.street2;
		$('input[name="city"]')[0].value = item.city;
		$('select[name="state"]')[0].value = item.state;
		$('input[name="zipCode"]')[0].value = item.zipCode;
		
		var dataString = $("#editContactForm").serialize();
		postEditedContact(dataString, true);
		if (item.id > 0) {
			recordsUpdated++;
		}
		else {
			recordsCreated++;
		}			
	}
});

var msg = "Synchronization Summary\n\tRecords Updated: " + recordsUpdated + 
"\n\tRecords Created: " + recordsCreated +"\n\tRecords Deleted: " + recordsDeleted;
alert(msg);

最新のデータは、getcontacts 操作を使用してデータベースから取得されて表示されます。他のユーザーが行った変更もすべてサーバーに反映され、最新に更新されたデータはオフラインの場合でも使用できるように、ローカルに永続化されます。


まとめ

この記事ではサンプル・アプリケーションを示しながら、オンラインとオフラインをサポートするための適切なパターンについて説明しました。一貫したユーザー・エクスペリエンスを維持するために、オンライン・モードにもオフライン・モードにも 1 つの HTML ページを使用し、さらにオンライン、オフラインの状態に応じてオンラインまたはオフラインのデータ・プロバイダーをフォーム・イベント・ハンドラーの中で呼び出しています。

ここで紹介したデータ同期アルゴリズムは適切な同期の基本操作を提供しており、オフラインで行われたレコードの作成、削除、変更といった操作と同期させることができます。ただし、このコードは本番に使用できるものではなく、例えば、ローカルで変更されたのと同じレコードが別のユーザーによってサーバー上でも変更されたような場合の競合には対処することができません。

参考文献

学ぶために

  • JSON: この軽量なデータ交換フォーマットについて学んでください。
  • jQuery のドキュメント: Getting Started、Plugins、Support、API、UI などのセクションを含め、このドキュメントを読んでください。
  • HTML5 Tutorial: 新しい要素や属性、CSS3 のサポート、ローカル・ストレージ、ローカル SQL データベース、等々について学んでください。
  • developerWorks の Web development ゾーン: Web ベースのさまざまなソリューションを解説した記事が豊富に用意されています。Web development 技術文書一覧に用意された、さまざまな技術記事やヒント、チュートリアル、技術標準、IBM Redbooks をご覧ください。
  • developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。
  • developerWorks Live! briefings: IBM の製品およびツールについての情報や IT 業界の動向についての情報を迅速に把握してください。
  • developerWorks on-demand demos: 初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。
  • developerWorks は Twitter を利用しています: 今すぐ developerWorks のツイートをフォローしてください。

製品や技術を入手するために

  • IBM 製品の評価版: IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2、Lotus、Rational、Tivoli、WebSphere などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=829932
ArticleTitle=HTML5 のデータベース機能とオフライン機能を使用する: 第 1 回 オフラインのデータ編集機能とデータ同期機能を提供する
publish-date=08232012