1
0
mirror of https://github.com/suk-ws/ph-Bookshelf.git synced 2024-12-05 09:26:52 +08:00

使切换页面支持了(半个)pjax动态加载

- 现在在支持 javascript 的浏览器环境中,Book 和 Page 的链接将会采用异步局部更新的方式进行更新
  - 在进行更新时,内容区域的透明度会降为 20%
- 使 index 支持了请求部分页面内容
  - 在 raw=true 时,将会只输出内容容器内的内容
  - 在 nav=true 时,内容输出的前面会添加一行请求书籍的目录
- 给 page 和 book 链接添加了 'type/id' 格式的 id 和 'type-id' 的自定义属性
This commit is contained in:
A.C.Sukazyo Eyre 2021-05-31 16:05:45 +08:00
parent e4db1984b9
commit 6e5f71b96b
Signed by: Eyre_S
GPG Key ID: EFB47D98FE082FAD
7 changed files with 115 additions and 15 deletions

View File

@ -102,3 +102,11 @@
#book-search-input { #book-search-input {
background-color: var(--color-nav-background-base); background-color: var(--color-nav-background-base);
} }
#page-container {
transition-duration: 400ms;
}
#page-container.loading {
opacity: 0.2;
}

View File

@ -3,9 +3,14 @@ const WITH_SUMMARY_CLASS = "with-summary"
const DROPDOWN_OPEN_CLASS = "open"; const DROPDOWN_OPEN_CLASS = "open";
let bookRoot; let bookRoot;
let pageContainer;
let inBookNavContainer;
let fontSettingDiv; let fontSettingDiv;
let bookCurrentId;
let pageCurrentId;
function summaryOnOrOff () { function summaryOnOrOff () {
if (bookRoot.classList.contains(WITH_SUMMARY_CLASS)) { if (bookRoot.classList.contains(WITH_SUMMARY_CLASS)) {
@ -19,6 +24,8 @@ function summaryOnOrOff () {
window.onload = function () { window.onload = function () {
bookRoot = document.getElementsByClassName("book")[0]; bookRoot = document.getElementsByClassName("book")[0];
pageContainer = document.getElementById("page-container");
inBookNavContainer = document.getElementById("in-book-nav-container");
fontSettingDiv = document.getElementsByClassName("font-settings")[0].getElementsByClassName("dropdown-menu")[0]; fontSettingDiv = document.getElementsByClassName("font-settings")[0].getElementsByClassName("dropdown-menu")[0];
@ -28,16 +35,17 @@ window.onload = function () {
}; };
for (let node of document.getElementsByClassName("fold")) { function bindFolderClickEvent () {
node.childNodes[0].addEventListener("click", function () { for (let node of document.getElementsByClassName("fold")) {
if (node.classList.contains("on")) { node.childNodes[0].addEventListener("click", function () {
node.classList.remove("on"); if (node.classList.contains("on")) {
} else node.classList.add("on"); node.classList.remove("on");
}); } else node.classList.add("on");
} });
}
} bindFolderClickEvent();
for (const node of document.getElementsByClassName("summary-container")) { for (const node of document.getElementsByClassName("summary-container")) {
node.nextElementSibling.innerHTML = node.nextElementSibling.innerHTML + "<a class='summary-container-icon'><i class='fa'></i></a>"; node.nextElementSibling.innerHTML = node.nextElementSibling.innerHTML + "<a class='summary-container-icon'><i class='fa'></i></a>";
node.nextElementSibling.getElementsByClassName("summary-container-icon")[0].addEventListener("click", function () { node.nextElementSibling.getElementsByClassName("summary-container-icon")[0].addEventListener("click", function () {
if (node.classList.contains("on")) { if (node.classList.contains("on")) {
@ -46,7 +54,6 @@ for (const node of document.getElementsByClassName("summary-container")) {
node.classList.add("on") node.classList.add("on")
} }
}) })
} }
function openOrCloseFontSettings () { function openOrCloseFontSettings () {
@ -114,3 +121,70 @@ function setCookie(name, value) {
const expires = "expires=" + d.toGMTString() const expires = "expires=" + d.toGMTString()
document.cookie = name + "=" + value + "; " + expires; document.cookie = name + "=" + value + "; " + expires;
} }
function updatePage (bookId, pageId = "") {
const isNavRefresh = bookId !== bookCurrentId;
const request = new XMLHttpRequest();
const url = (
"/" + bookId + "/" + pageId
);
const urlParam = (
"?raw=true" +
((isNavRefresh)?("&nav=true"):(""))
)
request.open("GET", url + urlParam, true);
console.log(url + urlParam);
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
// data
const data = request.responseText.split("\n", 2);
const nav = isNavRefresh?data[0]:"";
const content = request.responseText.substr(nav.length);
console.log(nav);
console.log(content);
// content
pageContainer.innerHTML = content;
if (!isNavRefresh) document.getElementById("page/"+pageCurrentId).classList.remove("active");
if (!isNavRefresh) pageCurrentId = pageId;
if (!isNavRefresh) document.getElementById("page/"+pageId).classList.add("active");
// nav
if (isNavRefresh) {
inBookNavContainer.innerHTML = nav;
if (bookCurrentId !== "%root")
document.getElementById("book/"+bookCurrentId).classList.remove("active");
bookCurrentId = bookId;
pageCurrentId = inBookNavContainer.getElementsByClassName("active")[0].getAttribute("page-id");
document.getElementById("book/"+bookId).classList.add("active");
bindFolderClickEvent();
bindPageLinkClickEvent();
}
// history
window.history.pushState(document.documentElement.innerHTML, document.title, url);
pageContainer.classList.remove("loading");
}
}
request.send();
pageContainer.classList.add("loading");
}
function bindBookLinkClickEvent () {
for (let node of document.getElementsByClassName("link-book")) {
node.children[0].removeAttribute("href");
node.childNodes[0].addEventListener("click", function () {
updatePage(node.getAttribute("book-id"));
}, true);
}
} bindBookLinkClickEvent();
function bindPageLinkClickEvent () {
for (let node of document.getElementsByClassName("link-page")) {
node.children[0].removeAttribute("href");
node.childNodes[0].addEventListener("click", function () {
updatePage(bookCurrentId, node.getAttribute("page-id"));
}, true);
}
} bindPageLinkClickEvent();

View File

@ -17,6 +17,10 @@ try {
SiteMeta::load(); SiteMeta::load();
// 检查是否为 ajax 请求
$rawContent = $_GET['raw']=="true";
$rawWithNav = $_GET['nav']=="true";
// 格式化所给链接,并将链接转化为路径字符串数组 // 格式化所给链接,并将链接转化为路径字符串数组
$req = $_GET['p']; $req = $_GET['p'];
if (strlen($req) > 0 && $req[strlen($req) - 1] === '/') if (strlen($req) > 0 && $req[strlen($req) - 1] === '/')
@ -66,6 +70,12 @@ try {
} }
if ($rawContent && $rawWithNav) {
echo PageMeta::$book->getSummaryHtml() . "\n";
}
if (!$rawContent) :
require "./template/header.php"; require "./template/header.php";
?> ?>
@ -123,11 +133,12 @@ try {
</div> </div>
<h1> <h1>
<i class="fa fa-circle-o-notch fa-spin"></i> <i class="fa fa-circle-o-notch fa-spin"></i>
<a><?= PageMeta::$book->getName() ?></a> <a id="page-title"><?= PageMeta::$book->getName() ?></a>
</h1> </h1>
</div> </div>
<div class="page-wrapper" tabindex="-1" role="main"> <div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner"> <div id="page-container" class="page-inner">
<?php endif; ?>
<div id="book-search-results"> <div id="book-search-results">
<div class="search-noresults"> <div class="search-noresults">
<section class="normal markdown-section"> <section class="normal markdown-section">
@ -136,6 +147,7 @@ try {
</section> </section>
</div> </div>
</div> </div>
<?php if (!$rawContent) : ?>
</div> </div>
</div> </div>
</div> </div>
@ -145,6 +157,8 @@ try {
require "./template/footer.php"; require "./template/footer.php";
endif;
} catch (Exception $e) { } catch (Exception $e) {
echo "<h1>ERROR</h1><p>" . $e->getMessage() . "</p>"; echo "<h1>ERROR</h1><p>" . $e->getMessage() . "</p>";

View File

@ -54,7 +54,7 @@ class Book {
} }
public function getHtml (): string { public function getHtml (): string {
return "<li class='link" . (PageMeta::$book->getId()==$this->id?" active":"") . "'><a class='link' " . (PageMeta::$book->getId()==$this->id?"":" href='/$this->id'") . ">$this->name</a></li>"; return "<li id='book/$this->id' book-id='$this->id' class='link link-book" . (PageMeta::$book->getId()==$this->id?" active":"") . "'><a class='link' " . (PageMeta::$book->getId()==$this->id?"":" href='/$this->id'") . ">$this->name</a></li>";
} }
/** /**

View File

@ -64,7 +64,7 @@ class BookContented {
} }
public function getSummaryHtml (): string { public function getSummaryHtml (): string {
return $this->childs->getSummaryHtml(); return "<div id='in-book-nav-container'>" . $this->childs->getSummaryHtml() . "</div>";
} }
public function getPage (string $id): ?Page { public function getPage (string $id): ?Page {

View File

@ -73,7 +73,7 @@ class Page {
public function getSummaryHtml (): string { public function getSummaryHtml (): string {
$str = $str =
"<li class='page-contented chapter" . "<li id='page/$this->id' page-id='$this->id' class='page-contented chapter link-page " .
(PageMeta::$page->getId()==$this->id?" active":"") . (PageMeta::$page->getId()==$this->id?" active":"") .
"'><a class='page-contented' " . "'><a class='page-contented' " .
( (

View File

@ -11,7 +11,11 @@
} }
?> ?>
<script><?= SiteMeta::getCustomScriptContent("custom") ?></script> <script><?= SiteMeta::getCustomScriptContent("custom") ?></script>
<script>
bookCurrentId = "<?= PageMeta::$book->getId() ?>";
pageCurrentId = "<?= PageMeta::$page->getId() ?>";
</script>
</body> </body>
</html> </html>