我有一个带有2页的Epub3书以及一个目录页面。我正在Mac OSX上的苹果书中查看这本书。这两个页面并排出现。第一页如下:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=500, height=600"/>
</head>
<body>
<p id="result"></p>
<script>
//<![CDATA[
var current_page = "1";
var other_page = "2";
var t = 0;
setInterval(function() {
var d = new Date();
var storage = localStorage;
storage.setItem("t"+ current_page, d.toLocaleString());
document.getElementById("result").innerHTML = storage.getItem("t"+ current_page) +" "+storage.getItem("t"+ other_page);
}, 1000);
//]]>
</script>
</body>
</html>
,第二页中唯一不同的是:
var current_page = "2";
var other_page = "1";
因此,每一秒钟,第1页将当前时间保存到本地存储为t1
,而第2页对于值t2
的作用相同。同时,在将其值显示为屏幕之前,这两个页面都从本地存储中读取t1
和t2
。但是,在iBooks中,第1页仅设法在重新加载页面时显示t2
的当前值 - 就像当我翻转到目录时,然后再次返回第1页和第2页。对于t1
,第2页发生了类似的事情。
所以在时间21:10:00,第1页可能显示:
08/09/19,21:09:18 08/09/19,21:08:58
和第2页:
08/09/19,21:09:22 08/09/19,21:08:01
我也尝试使用会话数据,但是第1页无法读取t2
,并且第2页无法读取t1
。因此,这将显示为:
08/09/19,21:09:18 null
我可以想到几个应用程序,对于页面而言,相互通信非常有用。
例如,如果视频在一个页面上播放,则如果启动了另一个页面上的视频,则将其停止将很有用。通常,这是使用会话存储进行的。这与我自己的用例以及我开始探索此问题的原因有关。
同样,如果在第1页上要求用户输入故事的主字符的名称,则该条目在输入后应立即出现在第2页上。
除本地或会话存储以外,还有其他方法可以在EPUB3中相互通信吗?
我不知道epub3
,没有Mac可以测试,但是以下是我想到的四个可能的解决方案:
cookie
对于该用例,它的性能不如localStorage
,但是如果您没有很多选择,那么它比没有更好。
函数可以创建,读取和删除cookie(信用https://stackoverflow.com/a/a/28230846/9150652(:
function setCookie(name,value,days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999;';
}
用法用于您的示例:
<script>
//<![CDATA[
var current_page = "1";
var other_page = "2";
var t = 0;
setInterval(function() {
var d = new Date();
setCookie("t"+ current_page, d.toLocaleString(), 100); // 100 days
document.getElementById("result").innerHTML = getCookie("t"+ current_page) +" "+getCookie("t"+ other_page);
}, 1000);
//]]>
</script>
广播channel
BroadCastChannel是一个非常新的功能,因此"书籍"应用程序可能不会支持它。但这是一个概念:
<script>
//<![CDATA[
var broadcaster = new BroadcastChannel('test');
var current_page = "1";
var other_page = "2";
var t = 0;
setInterval(function() {
var d = new Date();
// Send message to all other tabs with BroadcastChannel('test')
bc.postMessage({
senderPage: "t"+ current_page,
date: d.toLocaleString()
});
}, 1000);
broadcaster.onmessage = (result) => {
if(result.senderPage == "t"+ other_page) { // If the message is from the other page
// Set HTML to current date + sent Date from other page
var d = new Date();
document.getElementById("result").innerHTML = d.toLocaleString() +" "+result.date;
}
};
//]]>
</script>
某种后端
如果以上都没有作用,则您可能没有其他选择,只能使用某种后端来提供和保存数据
如果仅适合您,我建议您使用免费的firebase或mongodb地图集,因为它们都可以为自己的免费层提供一些价值。
如果您使用后端进行操作,则可以使用类似的事情来完成:
<script>
//<![CDATA[
var current_page = "1";
var other_page = "2";
var lastLocalDate = new Date();
const serverUrl = "http://someUrl.com/endpoint/"
// Gets the latest date of the other page via ajax
function getUpdate() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
// If successful, update HTML
if (xmlhttp.status == 200) {
document.getElementById("result").innerHTML = lastLocalDate.toLocaleString() +" "+xhr.responseText;
}
// Update the date of this page anyways
sendUpdate();
}
};
// GET request with parameter requestingPage, which is the other page
xmlhttp.open("GET", serverUrl, true);
xmlhttp.send(`requestingPage=${other_page}`);
}
// Sends the current date of this page to the webserver
function sendUpdate() {
var xmlhttp = new XMLHttpRequest();
// No need to check if successful, just update the page again
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
getUpdate();
}
};
lastLocalDate = new Date();
// POST request with parameters page and date
xmlhttp.open("POST", serverUrl, true);
xmlhttp.send(`sendingPage=${current_page}&data=${lastLocalDate.toLocaleString()}`);
}
// Start with sending an update (so that lastLocalDate is at least sent once to the server)
sendUpdate();
//]]>
</script>
和后端中的某些方法需要看起来像这样(请注意,这不是任何语言中的有效代码(:
@GET
function getDate(requestingPageId)
find latest entry with page.id == requestingPageId
return page.date
@POST
function saveDate(savingPage, savingDate)
store new page element with
page.id = savingPage
page.date = savingDate
和数据库中的一个收集看起来像这样:
[
{
id: 1,
date: "date"
},{
id: 2,
date: "date"
},{
id: 2,
date: "date"
},{
id: 1,
date: "date"
},
// ...
]
窗口参考
如果书籍应用程序从第一个选项卡打开第二个选项卡,则可能值得研究:
- window.postmessage((
- 及其功能:
- window.open(( 打开第二个选项卡并获取对它的引用
- 和窗口。开放器获取对开瓶器的引用