diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/api/history_api | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/ja/web/api/history_api')
-rw-r--r-- | files/ja/web/api/history_api/example/index.html | 412 | ||||
-rw-r--r-- | files/ja/web/api/history_api/index.html | 130 | ||||
-rw-r--r-- | files/ja/web/api/history_api/working_with_the_history_api/index.html | 110 |
3 files changed, 652 insertions, 0 deletions
diff --git a/files/ja/web/api/history_api/example/index.html b/files/ja/web/api/history_api/example/index.html new file mode 100644 index 0000000000..544a38894e --- /dev/null +++ b/files/ja/web/api/history_api/example/index.html @@ -0,0 +1,412 @@ +--- +title: Ajax ナビゲーションの例 +slug: Web/API/History_API/Example +translation_of: Web/API/History_API/Example +--- +<p>これは3ページ (first_page.php、second_page.php、third_page.php) で構成された AJAX Web サイトの例です。どのように動作するかを確認するには、以下のファイル (またはgit clone <a href="https://github.com/giabao/mdn-ajax-nav-example" title="/en-US/docs/">https://github.com/giabao/mdn-ajax-nav-example.git</a>) を作成してください:</p> + +<div class="note" id="const_compatibility"><strong>メモ:</strong> このメカニズム内の {{HTMLElement("form")}} 要素を完全に統合するには、<a href="/ja/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files">フォームの送信とファイルのアップロード</a>の段落を見てください。</div> + +<p><strong>first_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "First page"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>first_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>second_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "Second page"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>second_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>third_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "Third page"; + $page_content = "<p>This is the content of <strong>third_page.php</strong>. This content is stored into a php variable.</p>"; + + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + echo json_encode(array("page" => $page_title, "content" => $page_content)); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<div id="ajax-content"> +<?php echo $page_content; ?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>css/style.css</strong>:</p> + +<pre class="brush: css">#ajax-loader { + position: fixed; + display: table; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +#ajax-loader > div { + display: table-cell; + width: 100%; + height: 100%; + vertical-align: middle; + text-align: center; + background-color: #000000; + opacity: 0.65; +} +</pre> + +<p><strong>include/after_content.php</strong>:</p> + +<pre class="brush: php"><p>This is the footer. It is shared between all ajax pages.</p> +</pre> + +<p><strong>include/before_content.php</strong>:</p> + +<pre class="brush: php"><p> +[ <a class="ajax-nav" href="first_page.php">First example</a> +| <a class="ajax-nav" href="second_page.php">Second example</a> +| <a class="ajax-nav" href="third_page.php">Third example</a> +| <a class="ajax-nav" href="unexisting.php">Unexisting page</a> ] +</p> + +</pre> + +<p><strong>include/header.php</strong>:</p> + +<pre class="brush: php"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<script type="text/javascript" src="js/ajax_nav.js"></script> +<link rel="stylesheet" href="css/style.css" /> +</pre> + +<p><strong>js/ajax_nav.js</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: js">"use strict"; + +const ajaxRequest = new (function () { + + function closeReq () { + oLoadingBox.parentNode && document.body.removeChild(oLoadingBox); + bIsLoading = false; + } + + function abortReq () { + if (!bIsLoading) { return; } + oReq.abort(); + closeReq(); + } + + function ajaxError () { + alert("Unknown error."); + } + + function ajaxLoad () { + var vMsg, nStatus = this.status; + switch (nStatus) { + case 200: + vMsg = JSON.parse(this.responseText); + document.title = oPageInfo.title = vMsg.page; + document.getElementById(sTargetId).innerHTML = vMsg.content; + if (bUpdateURL) { + history.pushState(oPageInfo, oPageInfo.title, oPageInfo.url); + bUpdateURL = false; + } + break; + default: + vMsg = nStatus + ": " + (oHTTPStatus[nStatus] || "Unknown"); + switch (Math.floor(nStatus / 100)) { + /* + case 1: + // Informational 1xx + console.log("Information code " + vMsg); + break; + case 2: + // Successful 2xx + console.log("Successful code " + vMsg); + break; + case 3: + // Redirection 3xx + console.log("Redirection code " + vMsg); + break; + */ + case 4: + /* Client Error 4xx */ + alert("Client Error #" + vMsg); + break; + case 5: + /* Server Error 5xx */ + alert("Server Error #" + vMsg); + break; + default: + /* Unknown status */ + ajaxError(); + } + } + closeReq(); + } + + function filterURL (sURL, sViewMode) { + return sURL.replace(rSearch, "") + ("?" + sURL.replace(rHost, "&").replace(rView, sViewMode ? "&" + sViewKey + "=" + sViewMode : "").slice(1)).replace(rEndQstMark, ""); + } + + function getPage (sPage) { + if (bIsLoading) { return; } + oReq = new XMLHttpRequest(); + bIsLoading = true; + oReq.onload = ajaxLoad; + oReq.onerror = ajaxError; + if (sPage) { oPageInfo.url = filterURL(sPage, null); } + oReq.open("get", filterURL(oPageInfo.url, "json"), true); + oReq.send(); + oLoadingBox.parentNode || document.body.appendChild(oLoadingBox); + } + + function requestPage (sURL) { + if (history.pushState) { + bUpdateURL = true; + getPage(sURL); + } else { + /* Ajax navigation is not supported */ + location.assign(sURL); + } + } + + function processLink () { + if (this.className === sAjaxClass) { + requestPage(this.href); + return false; + } + return true; + } + + function init () { + oPageInfo.title = document.title; + history.replaceState(oPageInfo, oPageInfo.title, oPageInfo.url); + for (var oLink, nIdx = 0, nLen = document.links.length; nIdx < nLen; document.links[nIdx++].onclick = processLink); + } + + const + + /* customizable constants */ + sTargetId = "ajax-content", sViewKey = "view_as", sAjaxClass = "ajax-nav", + + /* not customizable constants */ + rSearch = /\?.*$/, rHost = /^[^\?]*\?*&*/, rView = new RegExp("&" + sViewKey + "\\=[^&]*|&*$", "i"), rEndQstMark = /\?$/, + oLoadingBox = document.createElement("div"), oCover = document.createElement("div"), oLoadingImg = new Image(), + oPageInfo = { + title: null, + url: location.href + }, oHTTPStatus = /* http://www.iana.org/assignments/http-status-codes/http-status-codes.xml */ { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 208: "Already Reported", + 226: "IM Used", + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Reserved", + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Unassigned", + 426: "Upgrade Required", + 427: "Unassigned", + 428: "Precondition Required", + 429: "Too Many Requests", + 430: "Unassigned", + 431: "Request Header Fields Too Large", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates (Experimental)", + 507: "Insufficient Storage", + 508: "Loop Detected", + 509: "Unassigned", + 510: "Not Extended", + 511: "Network Authentication Required" + }; + + var + + oReq, bIsLoading = false, bUpdateURL = false; + + oLoadingBox.id = "ajax-loader"; + oCover.onclick = abortReq; + oLoadingImg.src = "data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="; + oCover.appendChild(oLoadingImg); + oLoadingBox.appendChild(oCover); + + onpopstate = function (oEvent) { + bUpdateURL = false; + oPageInfo.title = oEvent.state.title; + oPageInfo.url = oEvent.state.url; + getPage(); + }; + + window.addEventListener ? addEventListener("load", init, false) : window.attachEvent ? attachEvent("onload", init) : (onload = init); + + // Public methods + + this.open = requestPage; + this.stop = abortReq; + this.rebuildLinks = init; + +})(); +</pre> +</div> + +<p>詳細は、<a href="/ja/docs/Web/API/History_API">ブラウザの履歴を操作する</a>を参照してください。</p> + +<h2 id="あわせて参照">あわせて参照</h2> + +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> diff --git a/files/ja/web/api/history_api/index.html b/files/ja/web/api/history_api/index.html new file mode 100644 index 0000000000..c317686348 --- /dev/null +++ b/files/ja/web/api/history_api/index.html @@ -0,0 +1,130 @@ +--- +title: History API +slug: Web/API/History_API +tags: + - API + - Advanced + - DOM + - HTML5 + - History + - 履歴 +translation_of: Web/API/History_API +--- +<div>{{DefaultAPISidebar("History API")}}</div> + +<p>DOM の {{DOMxRef("Window")}} オブジェクトは、ブラウザーのセッション履歴 (<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history">WebExtensions history</a> と混同しないように) へのアクセスを {{DOMxRef("Window.history","history")}} オブジェクトを介して提供しています。このオブジェクトは、ユーザーの履歴の中を前のページや後のページへ移動したり、履歴スタックの中を称さしたりするのに便利なメソッドやプロパティが提供されています。</p> + +<h2 id="Concepts_and_usage" name="Concepts_and_usage">概念と使用方法</h2> + +<p>ユーザーの履歴の中を前のページや次のページへ移動するには、 {{DOMxRef("History.back","back()")}}, {{DOMxRef("History.forward","forward()")}}, {{DOMxRef("History.go","go()")}} の各メソッドを使用します。</p> + +<h3 id="Moving_forward_and_backward" name="Moving_forward_and_backward">前のページや次のページへの移動</h3> + +<p>履歴を前に遡るには、次のようにします。</p> + +<pre class="brush: js notranslate">window.history.back() +</pre> + +<p>これは、ちょうどユーザーがブラウザーのツールバーの<kbd><strong>前のページへ戻る</strong></kbd>ボタンをクリックしたときのような動作です。</p> + +<p>同様に、次のようにして (ユーザーが<kbd><strong>次のページへ進む</strong></kbd>ボタンをクリックしたときのように) 次のページへ進むこともできます。</p> + +<pre class="brush: js notranslate">window.history.forward() +</pre> + +<h3 id="Moving_to_a_specific_point_in_history" name="Moving_to_a_specific_point_in_history">履歴内の特定の位置まで移動</h3> + +<p>{{DOMxRef("History.go","go()")}} メソッドを使うと、セッション履歴において現在のページから相対的な位置を指定して特定のページを読み込むことができます。 (現在のページの相対位置は <code>0</code> となります。)</p> + +<p>ひとつ前のページへと戻る例です ({{DOMxRef("History.back","back()")}} と同様の動き)。</p> + +<pre class="brush: js notranslate">window.history.go(-1) +</pre> + +<p>ページを進める例で、 {{DOMxRef("History.forward","forward()")}} を呼び出すのと同様です。</p> + +<pre class="brush: js notranslate">window.history.go(1) +</pre> + +<p>同様に、 <code>2</code> を渡すことで2ページ分を進めることができます。</p> + +<p><code>go()</code> メソッドの他の使い方として、 <code>0</code> を渡すか、引数なしで呼び出すことで、現在のページを再読み込みすることができます。</p> + +<pre class="brush: js notranslate">// 以下の文は、 +// どちらもページを再読み込みする +// 効果があります。 +window.history.go(0) +window.history.go() +</pre> + +<p><code>length</code> プロパティの値を参照することにより、履歴スタック中のページの数を知ることができます。</p> + +<pre class="brush: js notranslate">let numberOfEntries = window.history.length +</pre> + +<h2 id="Interfaces" name="Interfaces">インターフェイス</h2> + +<dl> + <dt>{{domxref("History")}}</dt> + <dd>ブラウザーの<em>セッション履歴</em> (すなわち、現在のページが読み込まれているタブやフレームで表示したことがあるページ群) の操作ができます。</dd> +</dl> + +<h2 id="Examples" name="Examples">例</h2> + +<p>以下の例では <code>onpopstate</code> プロパティにリスナーを割り当てています。そして、 history オブジェクトのメソッドで現在のタブのブラウザー履歴の追加、置換、移動など、いくつかの操作を説明しています。</p> + +<pre class="brush:js line-numbers language-js notranslate">window.onpopstate = function(event) { + alert(`location: ${document.location}, state: ${JSON.stringify(event.state)}`) +} + +history.pushState({page: 1}, "title 1", "?page=1") +history.pushState({page: 2}, "title 2", "?page=2") +history.replaceState({page: 3}, "title 3", "?page=3") +history.back() // alerts "location: http://example.com/example.html?page=1, state: {"page":1}" +history.back() // alerts "location: http://example.com/example.html, state: null" +history.go(2) // alerts "location: http://example.com/example.html?page=3, state: {"page":3}"</pre> + +<h2 id="Specifications" name="Specifications">仕様書</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">仕様書</th> + <th scope="col">状態</th> + <th scope="col">備考</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName("HTML WHATWG", "browsers.html#history", "History")}}</td> + <td>{{Spec2("HTML WHATWG")}}</td> + <td>{{SpecName("HTML5 W3C")}} から変更なし</td> + </tr> + <tr> + <td>{{SpecName("HTML5 W3C", "browsers.html#history", "History")}}</td> + <td>{{Spec2("HTML5 W3C")}}</td> + <td>初回定義</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> + +<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div> + +<p>{{Compat("api.History")}}</p> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<h3 id="References" name="References">リファレンス</h3> + +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> + +<h3 id="Guides" name="Guides">ガイド</h3> + +<ul> + <li><a href="/ja/docs/Web/API/History_API/Working_with_the_History_API">History API の操作</a></li> +</ul> diff --git a/files/ja/web/api/history_api/working_with_the_history_api/index.html b/files/ja/web/api/history_api/working_with_the_history_api/index.html new file mode 100644 index 0000000000..c7b71399b2 --- /dev/null +++ b/files/ja/web/api/history_api/working_with_the_history_api/index.html @@ -0,0 +1,110 @@ +--- +title: History API を取り扱う +slug: Web/API/History_API/Working_with_the_History_API +tags: + - DOM + - History API + - History API Tutorial +translation_of: Web/API/History_API/Working_with_the_History_API +--- +<p>HTML5 では {{DOMxRef("History.pushState","pushState()")}} および {{DOMxRef("History.replaceState","replaceState()")}} メソッドが導入され、それぞれにより履歴エントリの追加と修正が可能となりました。 これらのメソッドは {{ domxref("window.onpopstate") }}イベントと連動して動作します。</p> + +<h2 id="履歴エントリの追加と修正">履歴エントリの追加と修正</h2> + +<p>{{ gecko_minversion_header("2") }}</p> + +<p>{{DOMxRef("History.pushState","pushState()")}} を使うことで、履歴の状態を変更した後に生成される {{domxref("XMLHttpRequest")}} オブジェクトの HTTP ヘッダー中のリファラも変更されます。リファラは {{domxref("XMLHttpRequest")}} オブジェクトが生成された時点での <code>this</code> となるウィンドウの持つドキュメントの URL となります。</p> + +<h3 id="pushState_の例">pushState() の例</h3> + +<p>以下の JavaScript は <span class="nowiki">http://mozilla.org/foo.html</span> において実行されると仮定します:</p> + +<pre class="brush: js">let stateObj = { + foo: "bar", +}; + +history.pushState(stateObj, "page 2", "bar.html"); +</pre> + +<p>これにより URL バーには <span class="nowiki">http://mozilla.org/bar.html</span> と表示されますが、ブラウザは <code>bar.html</code> をロードすることはなくまたその存在をチェックすることはありません。</p> + +<p>ユーザが http://google.com に移動し、それから戻るボタンをクリックしたとします。このとき、URL バーは http://mozilla.org/bar.html を表示し、<code>history.state</code> は <code>stateObj</code> になります。popstate イベントはページがリロードされたために発火しません。ページそれ自体は bar.html のように見えます。</p> + +<p>再び戻るボタンをクリックすると、URL は <span class="nowiki">http://mozilla.org/foo.html</span> へ変化し、 <code>popstate</code> イベントが発火され、state は null オブジェクトとなります。ここでもまた、<code>popstate</code> イベントを受け取って手動でコンテンツを変更することは可能ですが、戻るという操作によって戻る前のコンテンツが変更されるわけではありません。</p> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> Although <code>history.back()</code> normally behaves the same way as clicking the Back button, the <code>history.back()</code> method acts differently from the browser Back button after using <code>history.pushState()</code>. Calling <code>history.back()</code> after <code>history.pushState()</code> does not raise a <code>popstate</code> event while clicking on the browser's Back button does raise the event.</p> +</div> + +<h3 id="pushState_メソッド">pushState() メソッド</h3> + +<p><code>pushState()</code> は、state オブジェクト、タイトル(現在のところ無視されます)、そしてURL(任意)の3つのパラメータを使用します。これら3つのパラメータについて詳細に見ていきましょう:</p> + +<ul> + <li> + <p><strong>state オブジェクト</strong> — state オブジェクトは <code>pushState()</code> によって作成される新しい履歴エントリに関連付けられる JavaScript オブジェクトです。ユーザーが新しいエントリに移動すればいつでも、<code>popstate</code> イベントが発火して、履歴エントリの state オブジェクトのコピーがイベントの <code>state</code> プロパティへと含まれることとなります。</p> + + <p>state オブジェクトは何であってもシリアライズされます。Firefox はユーザーのディスクに state オブジェクトを保存し、ユーザーがブラウザを再起動した際に state オブジェクトを復元するため、シリアライズされた状態での state オブジェクトの最大文字数は640000文字と、サイズの制限がされています。シリアライズ後にこの最大文字数を上回ることになる state オブジェクトを <code>pushState()</code> に渡した場合、<code>pushState()</code>は例外を投げます。これを上回るスペースが必要な場合、<code>sessionStorage</code> または <code>localStorage</code> の使用を推奨します。</p> + </li> + <li> + <p><strong>タイトル</strong> — <a href="https://github.com/whatwg/html/issues/2174">Safari 以外のブラウザはこのパラメータを無視します</a>。しかし将来的には使えるようになるかもしれません。将来的な変更に備えて、空の文字列を渡しておくべきでしょう。あるいは、移動しようとしている先の状態を示す短いタイトルを渡しておくこともできます。</p> + </li> + <li> + <p><strong>URL</strong> — このパラメーターは、新しい履歴エントリの URL が指定します。<code>pushState()</code> の呼び出しの後、ブラウザはこの URL のロードを行わないと注記しておきますが、ユーザーがブラウザを再起動させた後などでは、新しく指定された URL をロードすることがあります。新しい URL は絶対パスである必要は無く、相対パスであった場合は、現在のURLとの相対関係が解決されます。新しい URL は現在の URLと same origin でなければなりません。でなければ <code>pushState()</code> は例外を発生させるでしょう。このパラメータは任意であり、指定されなかった場合は現在のドキュメントの URL が設定されます。</p> + </li> +</ul> + +<div class="note"><strong>注:</strong> Gecko 2.0 {{ geckoRelease("2.0") }} より Gecko 5.0 {{ geckoRelease("5.0") }} に於いては、渡されたオブジェクトは JSON を使用してシリアライズされます。Gecko 6.0 {{ geckoRelease("6.0") }} より、オブジェクトは <a href="/ja/DOM/The_structured_clone_algorithm" title="ja/DOM/The structured clone algorithm">the structured clone algorithm</a> を使用してシリアライズされます。これにより多種多様なオブジェクトを安全に渡せるようになります。</div> + +<p>ある意味では、<code>pushState()</code> の呼び出しは <code>window.location = "#foo";</code> と設定するのと似ています。どちらも、現在のドキュメントに関連する別の履歴エントリの生成とアクティベートを行います。ですが <code>pushState()</code> にはいくらかの利点があります:</p> + +<ul> + <li>新しい URL は、現在の URL と同じドメインであればどの URL にもなることができます。対照的に、<code>window.location</code> では hash の変更しかできず、同じ {{ domxref("document") }} のままとなります。</li> + <li>必ずしも URL を変更する必要はありません。対照的に、<code>window.location = "#foo";</code> では、現在の hash が <code>#foo</code> でない場合、新しい履歴エントリの作成以外のことはできません。</li> + <li>新しい履歴エントリに任意のデータを関連付けることができます。hash を基にしたアプローチでは、関連するデータを含めた短い文字列を全てエンコードする必要があります。</li> + <li>If <code>title </code>is subsequently used by browsers, this data can be utilized (independent of, say, the hash).</li> +</ul> + +<p>新しい URLが、変更前のURLから hash のみを変更した URL である場合であっても、 <code>pushState()</code> は <code>hashchange</code> イベントを発火させることはないと注記しておきます。</p> + +<p>In a <a href="/en-US/docs/Mozilla/Tech/XUL">XUL</a> document, it creates the specified XUL element.</p> + +<p>In other documents, it creates an element with a <code>null</code> namespace URI.</p> + +<h3 id="replaceState_メソッド">replaceState() メソッド</h3> + +<p><code>history.replaceState()</code> は丁度 <code>history.pushState()</code> のように動作しますが、<code>pushState()</code> と異なる点として、 <code>replaceState()</code> は新しく履歴エントリを作成する代わりに現在の履歴エントリを修正します。Note that this doesn't prevent the creation of a new entry in the global browser history.</p> + +<p>具体的には、何らかのユーザーのアクションを受け、現在の履歴エントリの URL または state オブジェクトを更新したい場合に <code>replaceState()</code> が役立ちます。</p> + +<div class="note"><strong>注:</strong> Gecko 2.0 {{ geckoRelease("2.0") }} より Gecko 5.0 {{ geckoRelease("5.0") }} に於いては、渡されたオブジェクトは JSON を使用してシリアライズされます。Gecko 6.0 {{ geckoRelease("6.0") }} より、オブジェクトは <a href="/ja/DOM/The_structured_clone_algorithm" title="ja/DOM/The structured clone algorithm">the structured clone algorithm</a> を使用してシリアライズされます。これにより多種多様なオブジェクトを安全に渡せるようになります。</div> + +<h3 id="replaceState_の例">replaceState() の例</h3> + +<p><span class="nowiki">仮に <code>http://mozilla.org/foo.html</code></span> は次の JavaScript を実行するものとします。</p> + +<pre class="brush: js">var stateObj = { foo: "bar" }; +history.pushState(stateObj, "page 2", "bar.html");</pre> + +<p>この2行のコードの説明は <a href="ja/docs/Web/API/History_API/Working_with_the_History_API$edit#Example_of_pushState_method">pushState()の例 </a><em>のセクションで見ることができます。次に、</em><code>http://mozilla.org/bar.html</code> が次の JavaScript を実行するものとします。</p> + +<pre class="brush: js">history.replaceState(stateObj, "page 3", "bar2.html");</pre> + +<p>これによってアドレスバーには <code><span class="nowiki">http://mozilla.org/bar2.html</span></code> が表示されますが、ブラウザは <code>bar2.html</code> の読み込みを行わず、<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">bar2.html</span></font> が存在するかどうかもチェックしません。</p> + +<p>仮に今、ユーザーが <code><span class="nowiki">http://www.microsoft.com</span></code> に移動し、<strong>戻る</strong>ボタンを押したとします。この時点でアドレスバーには <code><span class="nowiki">http://mozilla.org/bar2.html</span></code> が表示されています。もしユーザーが再び<strong>戻る</strong>ボタンを押すと、アドレスバーには <code><span class="nowiki">http://mozilla.org/foo.html</span></code> が表示され、<code>bar.html</code> を完全に回避します。</p> + +<h3 id="popstate_イベント">popstate イベント</h3> + +<p>アクティブな履歴エントリが変更される度にウィンドウへと <code>popstate</code> イベントが発行されます。<code>pushState</code> の呼び出しまたは <code>replaceState</code> の呼び出しの影響によって、アクティベートされた履歴エントリが作成された場合、<code>popstate</code> イベントの <code>state</code> プロパティは履歴エントリの state オブジェクトのコピーを含みます。</p> + +<p>使い方のサンプルは {{ domxref("window.onpopstate") }} を参照してください。</p> + +<h3 id="現在の状態を読み取る">現在の状態を読み取る</h3> + +<p>ページが読み込まれたとき、 ページは null ではない state オブジェクトを持っているかもしれません。これは例えば、({{DOMxRef("History.pushState","pushState()")}} または {{DOMxRef("History.replaceState","replaceState()")}}) の使用によって)ページに state オブジェクトが設定されており、ユーザーがブラウザを再起動した場合に起こりえます。ページを再読み込みした際にページは <code>onload</code> イベントを受け取りますが <code>popstate</code> イベントは受け取られません。しかしながら <code>history.state</code> プロパティを読み取った場合、<code>popstate</code> が発火した際に取得できるであろう state オブジェクトを得ることができるでしょう。</p> + +<p>このように <code>history.state</code> プロパティを用いることで、 <code>popstate</code> イベントを待つことなく現在の履歴エントリの state を読み取ることができます:</p> + +<pre class="brush: js">let currentState = history.state; +</pre> |