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 {
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";
let bookRoot;
let pageContainer;
let inBookNavContainer;
let fontSettingDiv;
let bookCurrentId;
let pageCurrentId;
function summaryOnOrOff () {
if (bookRoot.classList.contains(WITH_SUMMARY_CLASS)) {
@ -19,6 +24,8 @@ function summaryOnOrOff () {
window.onload = function () {
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];
@ -28,16 +35,17 @@ window.onload = function () {
};
for (let node of document.getElementsByClassName("fold")) {
function bindFolderClickEvent () {
for (let node of document.getElementsByClassName("fold")) {
node.childNodes[0].addEventListener("click", function () {
if (node.classList.contains("on")) {
node.classList.remove("on");
} else node.classList.add("on");
});
}
}
} bindFolderClickEvent();
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.getElementsByClassName("summary-container-icon")[0].addEventListener("click", function () {
if (node.classList.contains("on")) {
@ -46,7 +54,6 @@ for (const node of document.getElementsByClassName("summary-container")) {
node.classList.add("on")
}
})
}
function openOrCloseFontSettings () {
@ -114,3 +121,70 @@ function setCookie(name, value) {
const expires = "expires=" + d.toGMTString()
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();
// 检查是否为 ajax 请求
$rawContent = $_GET['raw']=="true";
$rawWithNav = $_GET['nav']=="true";
// 格式化所给链接,并将链接转化为路径字符串数组
$req = $_GET['p'];
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";
?>
@ -123,11 +133,12 @@ try {
</div>
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a><?= PageMeta::$book->getName() ?></a>
<a id="page-title"><?= PageMeta::$book->getName() ?></a>
</h1>
</div>
<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 class="search-noresults">
<section class="normal markdown-section">
@ -136,6 +147,7 @@ try {
</section>
</div>
</div>
<?php if (!$rawContent) : ?>
</div>
</div>
</div>
@ -145,6 +157,8 @@ try {
require "./template/footer.php";
endif;
} catch (Exception $e) {
echo "<h1>ERROR</h1><p>" . $e->getMessage() . "</p>";

View File

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

View File

@ -73,7 +73,7 @@ class Page {
public function getSummaryHtml (): string {
$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":"") .
"'><a class='page-contented' " .
(

View File

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