跨电子书页面共享数据

时间:2018-08-24 07:28:27

标签: javascript html5 epub session-storage epub3

我想在固定版式的epub3电子书的一章末进行测验。该测验将跨越多个页面,并且本质上是多项选择。每个问题将由问题本身和四个选项组成,每个选项都有一个单选按钮。测验结束时,用户将单击一个按钮以显示其总体结果。为此,我将需要在页面之间共享信息。一种方法是将所有页面都放在一个XHTML文档中,然后将学生针对每个问题给出的答案存储在javascript变量中。但是,在同一个XHTML文件中包含多页固定版式的epub3书是否有效?如我在这里所做的那样:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<title>My Book</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>

<style>

p.pagebreak {
    page-break-after:always;
} 

</style>
</head>

<body> 

    <p>
        Text on Page 1
    </p>

    <p class="pagebreak"></p>

    <p>
        Text on Page 2
    </p>

    <p class="pagebreak"></p>

    <p>
        Text on Page 3
    </p>
</body>
</html> 

在iBooks中看起来还不错。

或者,如果使用多个页面,我可以使用window.sessionStorage存储学生的答案。但是,我不知道有多少读者支持存储。我希望该测验适用于iBooks,也适用于Android,Windows Tablets和台式机。

您如何建议我实施测验?

3 个答案:

答案 0 :(得分:8)

我认为您不太了解使用ePub实施和支持这一切的复杂性。我建议您阅读about ePub file format。另请参见ePub format规范的最新版本。

ePub发布(包括ePub3)作为单个文件提供。该文件是未加密的压缩归档文件,其中包含一组相互关联的资源。

示例ePub文件结构:

--ZIP Container--
mimetype
META-INF/
  container.xml
OEBPS/
  content.opf
  chapter1.xhtml
  ch1-pic.png
  css/
    style.css
    myfont.otf
  toc.ncx
  

引用您的问题: 我希望该测验适用于iBooks以及Android,Windows Tablets和台式机。

浏览器本身不支持从此类文件进行读取和显示。如果您真的想要这个,那么就必须对所有这些进行编程。对您来说,这不是真正必要的,因为我们已经有了JavaScript库:

  • Epub.js-用于在浏览器中呈现ePub文档的JavaScript库;
  • Readium-js-用Java编写的EPUB处理引擎

但是请不要忘记:在这两种情况下,它们都必须具有NodeJS服务器。

然后,您必须考虑此过程的所有资源-确实太多了!太多的开发工作,太多的资源和太多的能源浪费!

因为所有这些,没人会这样做。

  

引用您的问题: 您如何建议我实施测验?

我推荐的解决方案

您可以在一个HTML文件中回答所有测验问题,并将所有答案保存在数组中。我为您准备了示威示例:

var activePage = 0,
    pages = document.querySelectorAll('.quiz-page'),
    answers = [];

function goToNext(buttonObj)
{
    var questions = document.getElementsByName('question' + activePage),
        value = -1;

    for(var i = 0; i < questions.length; i++)
        if(questions[i].checked)
            value = questions[i].value;

    if(value < 0)
    {
        alert('Please choose one value!');
        return;
    }
    else
        // save the answer in array
        answers[activePage] = value;

    activePage++;

    for(var i = 0; i < pages.length; i++)
        pages[i].style.display = 'none';
    
    if(activePage < pages.length)
        pages[activePage].style.display = 'block';
    else
    {
        buttonObj.style.display = 'none';
        sendResultsToServer();
    }

    if(activePage == pages.length - 1)
        buttonObj.value = 'Get Results';
}

function sendResultsToServer()
{
    var strAllAnswers = answers.join(',');
    console.log('Answers indexes (one on each page): ' + strAllAnswers);

    //TODO: Send results to server using AJAX
    //... your AJAX code ...

    // Following example of code is for server side checking of results.
    // If you want you could do this checking of results on the
    // client side, but somebody could know all the correct
    // results if you do it on the client side. Be careful!

    var questions =
    [
        {
            question: 'True or false: 3 + 3 = 6?',
            answers: ['False','True'],
            correctAnswer: 1
        },
        {
            question: 'What sound does a dog make?',
            answers: ['Meow','Mooo','Woof'],
            correctAnswer: 2
        },
        {
            question: 'Which from movie names below is a science fiction movie?',
            answers: ['Star Wars','Planet of the Apes','Lion King','Shrek'],
            correctAnswer: 1
        },
    ];

    var arAllAnswers = strAllAnswers.split(',');
    var result = '<h3>Results</h3>';

    for(var i = 0; i < questions.length; i++)
    {
        result += '<p><b>' + questions[i].question + '</b></p>';
        result += 'Your answer was: ' + questions[i].answers[arAllAnswers[i]] + '<br>';
        result += 'Correct answer is: ' + questions[i].answers[questions[i].correctAnswer];
    }

    var resultPage = document.querySelector('#result');
    resultPage.innerHTML = result;
    resultPage.style.display = 'block';
}
label{cursor:pointer}
<div class="quiz-page">
    <p><b>Question 1 of 3.</b> True or false: 3 + 3 = 6?</p>
    <label><input type="radio" name="question0" value="0">False</label><br>
    <label><input type="radio" name="question0" value="1">True</label> 
</div>
<div class="quiz-page" style="display:none">
    <p><b>Question 2 of 3.</b> What sound does a dog make?</p>
    <label><input type="radio" name="question1" value="0">Meow</label><br>
    <label><input type="radio" name="question1" value="1">Mooo</label><br>
    <label><input type="radio" name="question1" value="2">Woof</label>
</div>
<div class="quiz-page" style="display:none">
    <p><b>Question 3 of 3.</b> Which from movie names below is a science fiction movie?</p>
    <label><input type="radio" name="question2" value="0">Star Wars</label><br>
    <label><input type="radio" name="question2" value="1">Planet of the Apes</label><br>
    <label><input type="radio" name="question2" value="2">Lion King</label><br>
    <label><input type="radio" name="question2" value="3">Shrek</label>
</div>
<div id="result" style="display:none"></div>
<br>
<input type="button" value="Next" onclick="goToNext(this)">

此代码应适用于iBooks,Android,Windows Tablets和台式机。

答案 1 :(得分:3)

根据specification,当rendition:layout设置为pre-paginated时:

  

给定的渲染是预先分页的。呈现时,阅读系统必须为每个书脊itemref恰好产生一页。

我的理解是,不,在同一个文件中包含多个页面是无效的(如果我没记错的话,只有可以在spine / manifest中引用的文件)。但是,从本质上来说,对于<nav>而言,它可能是无效的……可以随意进行广泛的测试,但是恕我直言,这是不值得的,因为...

...关于存储数据,IDPF将a lot of rules设置为符合读者的要求。但是,我严重怀疑拒绝脚本的阅读系统是否会取得成功,因为任何交互行为都需要脚本。特别是由于这种格式主要用于教育目的,因此交互是一个很好的补充。另外,用户可能会禁用脚本(根据文档),请确保:浏览器也有该脚本,谁在使用?因此,localStorage。 ;)

最后,如上所述,它确实不是浏览器呈现的,但是上下文确实接近Web浏览器,但有一些限制。实际上,可以(应该?)假定读者一种浏览器,只是局限于其application/oebps-package+xml包文件(带有奇特的MIME类型)所描述的世界。

答案 2 :(得分:0)

  

我希望该测验适用于iBooks,也适用于Android和Windows平板电脑和台式机。

看看Superbooks是Web / HTML应用程序,而不是驻留在网络之外的“基于文件”的书本系统。我认为这会有所帮助,因为您正在寻找可在所有设备和浏览器(平板电脑,移动设备和台式机)上使用的功能,并且希望在本书中添加一个交互式测验。 Bookiza是可用于创建超级本的工具。

完全公开:我是Bubblin和Bookiza的创造者。

相关问题