Skip to content

Commit 9afa4a3

Browse files
committed
Migration ResumePlugin to BookReaderPlugin format
1 parent 32b10df commit 9afa4a3

6 files changed

Lines changed: 90 additions & 94 deletions

File tree

src/BookReader.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ BookReader.PLUGINS = {
7070
archiveAnalytics: null,
7171
/** @type {typeof import('./plugins/plugin.autoplay.js').AutoplayPlugin | null}*/
7272
autoplay: null,
73+
/** @type {typeof import('./plugins/plugin.resume.js').ResumePlugin | null}*/
74+
resume: null,
7375
/** @type {typeof import('./plugins/plugin.text_selection.js').TextSelectionPlugin | null}*/
7476
textSelection: null,
7577
};
@@ -260,6 +262,7 @@ BookReader.prototype.setup = function(options) {
260262
this._plugins = {
261263
archiveAnalytics: BookReader.PLUGINS.archiveAnalytics ? new BookReader.PLUGINS.archiveAnalytics(this) : null,
262264
autoplay: BookReader.PLUGINS.autoplay ? new BookReader.PLUGINS.autoplay(this) : null,
265+
resume: BookReader.PLUGINS.resume ? new BookReader.PLUGINS.resume(this) : null,
263266
textSelection: BookReader.PLUGINS.textSelection ? new BookReader.PLUGINS.textSelection(this) : null,
264267
};
265268

@@ -400,7 +403,7 @@ BookReader.prototype.initParams = function() {
400403
// Check for Resume plugin
401404
if (this.options.enablePageResume) {
402405
// Check cookies
403-
const val = this.getResumeValue();
406+
const val = this._plugins.resume.getResumeValue();
404407
if (val !== null) {
405408
// If page index different from default
406409
if (params.index !== val) {

src/BookReader/options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ export const DEFAULT_OPTIONS = {
145145
archiveAnalytics: null,
146146
/** @type {import('../plugins/plugin.autoplay.js').AutoplayPlugin['options']}*/
147147
autoplay: null,
148+
/** @type {import('../plugins/plugin.resume.js').ResumePlugin['options']} */
149+
resume: null,
148150
/** @type {import('../plugins/plugin.text_selection.js').TextSelectionPlugin['options']} */
149151
textSelection: null,
150152
},

src/plugins/plugin.resume.js

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { EVENTS } from '../BookReader/events.js';
2+
import { BookReaderPlugin } from '../BookReaderPlugin.js';
13
import * as docCookies from '../util/docCookies.js';
24

35
/* global BookReader */
@@ -8,61 +10,62 @@ BookReader.docCookies = docCookies;
810
/**
911
* Plugin to remember the current page number in a cookie
1012
*/
11-
jQuery.extend(BookReader.defaultOptions, {
12-
enablePageResume: true,
13-
/** @type {string|null} eg '/', '/details/id' */
14-
resumeCookiePath: null,
15-
});
13+
export class ResumePlugin extends BookReaderPlugin {
14+
options = {
15+
enablePageResume: true,
16+
/** @type {string|null} eg '/', '/details/id' */
17+
resumeCookiePath: null,
18+
}
1619

17-
/** @override */
18-
BookReader.prototype.init = (function(super_) {
19-
return function() {
20-
super_.call(this);
20+
/** @override */
21+
init() {
2122
if (this.options.enablePageResume) {
22-
this.bind(BookReader.eventNames.fragmentChange, () => {
23-
const params = this.paramsFromCurrent();
23+
this.br.bind(EVENTS.fragmentChange, () => {
24+
const params = this.br.paramsFromCurrent();
2425
this.updateResumeValue(params.index);
2526
});
2627
}
27-
};
28-
})(BookReader.prototype.init);
28+
}
2929

30-
/**
31-
* Gets page resume value, for remembering reader's page
32-
* Can be overridden for different implementation
33-
*
34-
* @return {number|null}
35-
*/
36-
BookReader.prototype.getResumeValue = function() {
37-
const val = BookReader.docCookies.getItem('br-resume');
38-
if (val !== null) return parseInt(val);
39-
else return null;
40-
};
30+
/**
31+
* Gets page resume value, for remembering reader's page
32+
* Can be overridden for different implementation
33+
*
34+
* @return {number|null}
35+
*/
36+
getResumeValue() {
37+
const val = BookReader.docCookies.getItem('br-resume');
38+
if (val !== null) return parseInt(val);
39+
else return null;
40+
}
4141

42-
/**
43-
* Return cookie path using pathname up to /page/... or /mode/...
44-
* using window.location.pathname for urlPathPart:
45-
* - matches encoding
46-
* - ignores querystring part
47-
* - ignores fragment part (after #)
48-
* @param {string} urlPathPart - window.location.pathname
49-
*/
50-
BookReader.prototype.getCookiePath = function(urlPathPart) {
51-
return urlPathPart.match('.+?(?=/page/|/mode/|$)')[0];
52-
};
42+
/**
43+
* Return cookie path using pathname up to /page/... or /mode/...
44+
* using window.location.pathname for urlPathPart:
45+
* - matches encoding
46+
* - ignores querystring part
47+
* - ignores fragment part (after #)
48+
* @param {string} urlPathPart - window.location.pathname
49+
*/
50+
getCookiePath(urlPathPart) {
51+
return urlPathPart.match('.+?(?=/page/|/mode/|$)')[0];
52+
}
5353

54-
/**
55-
* Sets page resume value, for remembering reader's page
56-
* Can be overridden for different implementation
57-
*
58-
* @param {Number} index leaf index
59-
* @param {string} [cookieName]
60-
*/
61-
BookReader.prototype.updateResumeValue = function(index, cookieName) {
62-
const ttl = new Date(+new Date + 12096e5); // 2 weeks
63-
// For multiple files in item, leave resumeCookiePath blank
64-
// It's likely we can remove resumeCookiePath using getCookiePath()
65-
const path = this.options.resumeCookiePath
66-
|| this.getCookiePath(window.location.pathname);
67-
BookReader.docCookies.setItem(cookieName || 'br-resume', index, ttl, path, null, false);
68-
};
54+
/**
55+
* Sets page resume value, for remembering reader's page
56+
* Can be overridden for different implementation
57+
*
58+
* @param {Number} index leaf index
59+
* @param {string} [cookieName]
60+
*/
61+
updateResumeValue(index, cookieName) {
62+
const ttl = new Date(+new Date + 12096e5); // 2 weeks
63+
// For multiple files in item, leave resumeCookiePath blank
64+
// It's likely we can remove resumeCookiePath using getCookiePath()
65+
const path = this.options.resumeCookiePath
66+
|| this.getCookiePath(window.location.pathname);
67+
BookReader.docCookies.setItem(cookieName || 'br-resume', index, ttl, path, null, false);
68+
}
69+
}
70+
71+
BookReader?.registerPlugin('resume', ResumePlugin);

tests/e2e/helpers/base.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ export function runBaseTests (br) {
7878

7979
// Check if uses plugin.resume.js
8080
const usesResume = ClientFunction(() => {
81-
const hasResumePlugin = typeof(br.getResumeValue) !== "undefined";
82-
const hasResumeValue = hasResumePlugin ? br.getResumeValue() : false;
81+
const hasResumePlugin = typeof(br._plugins.resume) !== "undefined";
82+
const hasResumeValue = hasResumePlugin ? br._plugins.resume.getResumeValue() : false;
8383
return hasResumeValue;
8484
});
8585

tests/jest/BookReader.test.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import BookReader, {_modeStringToNumber} from '@/src/BookReader.js';
33
import '@/src/plugins/plugin.resume.js';
44
import '@/src/plugins/url/plugin.url.js';
55

6+
/** @type {import('@/src/BookReader.js').default} */
67
let br;
78
beforeAll(() => {
89
document.body.innerHTML = '<div id="BookReader">';
@@ -33,35 +34,35 @@ test('has registered fullscreen toggle event', () => {
3334
});
3435

3536
test('checks cookie when initParams called', () => {
36-
br.getResumeValue = jest.fn(() => 15);
37+
br._plugins.resume.getResumeValue = jest.fn(() => 15);
3738
br.urlReadFragment = jest.fn(() => '');
3839

3940
const params = br.initParams();
40-
expect(br.getResumeValue).toHaveBeenCalledTimes(1);
41+
expect(br._plugins.resume.getResumeValue).toHaveBeenCalledTimes(1);
4142
expect(params.init).toBe(true);
4243
expect(params.index).toBe(15);
4344
expect(params.fragmentChange).toBe(true);
4445
});
4546

4647
test('does not check cookie when initParams called', () => {
47-
br.getResumeValue = jest.fn(() => null);
48+
br._plugins.resume.getResumeValue = jest.fn(() => null);
4849
br.urlReadFragment = jest.fn(() => '');
4950
br.options.enablePageResume = false;
5051

5152
const params = br.initParams();
52-
expect(br.getResumeValue).toHaveBeenCalledTimes(0);
53+
expect(br._plugins.resume.getResumeValue).toHaveBeenCalledTimes(0);
5354
expect(params.init).toBe(true);
5455
expect(params.index).toBe(0);
5556
expect(params.fragmentChange).toBe(false);
5657
});
5758

5859
test('gets index from fragment when both fragment and cookie when InitParams called', () => {
59-
br.getResumeValue = jest.fn(() => 15);
60+
br._plugins.resume.getResumeValue = jest.fn(() => 15);
6061
br.urlReadFragment = jest.fn(() => 'page/n4');
6162
br.options.enablePageResume = true;
6263

6364
const params = br.initParams();
64-
expect(br.getResumeValue).toHaveBeenCalledTimes(1);
65+
expect(br._plugins.resume.getResumeValue).toHaveBeenCalledTimes(1);
6566
expect(params.init).toBe(true);
6667
expect(params.index).toBe(4);
6768
expect(params.fragmentChange).toBe(true);
@@ -91,7 +92,7 @@ test('calls switchMode with init option when init called', () => {
9192
});
9293

9394
test('has suppressFragmentChange true when init with no input', () => {
94-
br.getResumeValue = jest.fn(() => null);
95+
br._plugins.resume.getResumeValue = jest.fn(() => null);
9596
br.urlReadFragment = jest.fn(() => '');
9697
br.urlReadHashFragment = jest.fn(() => '');
9798
br.switchMode = jest.fn();
@@ -102,7 +103,7 @@ test('has suppressFragmentChange true when init with no input', () => {
102103
});
103104

104105
test('has suppressFragmentChange false when init with cookie', () => {
105-
br.getResumeValue = jest.fn(() => 5);
106+
br._plugins.resume.getResumeValue = jest.fn(() => 5);
106107
br.urlReadFragment = jest.fn(() => '');
107108
br.switchMode = jest.fn();
108109

@@ -112,7 +113,7 @@ test('has suppressFragmentChange false when init with cookie', () => {
112113
});
113114

114115
test('has suppressFragmentChange false when init with fragment', () => {
115-
br.getResumeValue = jest.fn(() => null);
116+
br._plugins.resume.getResumeValue = jest.fn(() => null);
116117
br.urlReadFragment = jest.fn(() => 'mode/1up');
117118
br.switchMode = jest.fn();
118119

@@ -122,7 +123,7 @@ test('has suppressFragmentChange false when init with fragment', () => {
122123
});
123124

124125
test('has suppressFragmentChange false when init with hash fragment', () => {
125-
br.getResumeValue = jest.fn(() => null);
126+
br._plugins.resume.getResumeValue = jest.fn(() => null);
126127
br.urlReadFragment = jest.fn(() => '');
127128
br.urlReadHashFragment = jest.fn(() => 'mode/1up');
128129
br.switchMode = jest.fn();

tests/jest/plugins/plugin.resume.test.js

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import '@/src/plugins/plugin.resume.js';
33

44
import sinon from 'sinon';
55
import * as docCookies from '@/src/util/docCookies.js';
6+
import { ResumePlugin } from '@/src/plugins/plugin.resume.js';
67

8+
/** @type {import('@/src/BookReader.js').default} */
79
let br;
810
beforeAll(() => {
911
document.body.innerHTML = '<div id="BookReader">';
@@ -16,21 +18,6 @@ afterEach(() => {
1618
sinon.restore();
1719
});
1820

19-
describe('Plugin: Remember Current Page in Cookies', () => {
20-
test('has default option flag', () => {
21-
expect(BookReader.defaultOptions.enablePageResume).toEqual(true);
22-
expect(BookReader.defaultOptions.resumeCookiePath).toEqual(null);
23-
});
24-
25-
test('has added BR property: getResumeValue', () => {
26-
expect(br).toHaveProperty('getResumeValue');
27-
});
28-
29-
test('has added BR property: updateResumeValue', () => {
30-
expect(br).toHaveProperty('updateResumeValue');
31-
});
32-
});
33-
3421
describe('updateResumeValue', () => {
3522
/* Mark 2020-05-02
3623
Skipping while confirming with Neeraj
@@ -42,17 +29,17 @@ describe('updateResumeValue', () => {
4229
In this branch .toHaveBeenCalledTimes() === 1
4330
*/
4431
test.skip('starts when BookReaderInit is called', () => {
45-
br.updateResumeValue = jest.fn();
32+
br._plugins.resume.updateResumeValue = jest.fn();
4633
br.init();
47-
expect(br.updateResumeValue).toHaveBeenCalledTimes(2);
34+
expect(br._plugins.resume.updateResumeValue).toHaveBeenCalledTimes(2);
4835
});
4936

5037
test('handles cookieName=null', () => {
51-
const { updateResumeValue } = BookReader.prototype;
38+
const p = new ResumePlugin(null);
39+
p.setup({ resumeCookiePath: '/details/goody' });
5240
const setItemSpy = sinon.spy(docCookies, 'setItem');
53-
const fakeBr = { options: { resumeCookiePath: '/details/goody' } };
5441

55-
updateResumeValue.call(fakeBr, 16);
42+
p.updateResumeValue(16);
5643
expect(setItemSpy.callCount).toBe(1);
5744
expect(setItemSpy.args[0].slice(0, 2)).toEqual(['br-resume', 16]);
5845
expect(setItemSpy.args[0][3]).toEqual('/details/goody');
@@ -61,38 +48,38 @@ describe('updateResumeValue', () => {
6148
test('handles resumeCookiePath not set', () => {
6249
const setItemSpy = sinon.spy(docCookies, 'setItem');
6350
// Save function
64-
const saveFn = br.getCookiePath;
65-
br.getCookiePath = jest.fn(() => '/details/foo');
66-
br.updateResumeValue(16);
51+
const saveFn = br._plugins.resume.getCookiePath;
52+
br._plugins.resume.getCookiePath = jest.fn(() => '/details/foo');
53+
br._plugins.resume.updateResumeValue(16);
6754
expect(setItemSpy.args[0][3]).toEqual('/details/foo');
6855
// Restore function
69-
br.getCookiePath = saveFn;
56+
br._plugins.resume.getCookiePath = saveFn;
7057
});
7158

7259
test('handles cookie path from URL with decoration', () => {
7360
const complexPathWithPage = '/details/2008ELMValidityStudyFinalReportRevised/Executive%20Summary%20for%20the%20EPT%26ELM%20Validity%20Studie_20100603%20-%20Copy/page/n1/mode/2up';
7461
const complexPath = '/details/2008ELMValidityStudyFinalReportRevised/Executive%20Summary%20for%20the%20EPT%26ELM%20Validity%20Studie_20100603%20-%20Copy';
75-
expect(br.getCookiePath(complexPathWithPage))
62+
expect(br._plugins.resume.getCookiePath(complexPathWithPage))
7663
.toEqual(complexPath);
7764

78-
expect(br.getCookiePath('/details/item/mode/1up'))
65+
expect(br._plugins.resume.getCookiePath('/details/item/mode/1up'))
7966
.toEqual('/details/item');
8067

81-
expect(br.getCookiePath('/details/item/inside/a/long/path/model/is/used'))
68+
expect(br._plugins.resume.getCookiePath('/details/item/inside/a/long/path/model/is/used'))
8269
.toEqual('/details/item/inside/a/long/path/model/is/used');
8370

84-
expect(br.getCookiePath('/details/item/inside/a/long/path/mode/is/used'))
71+
expect(br._plugins.resume.getCookiePath('/details/item/inside/a/long/path/mode/is/used'))
8572
.toEqual('/details/item/inside/a/long/path');
8673
});
8774

8875
test('handles cookie path from URL with no decoration', () => {
89-
expect(br.getCookiePath('/details/item'))
76+
expect(br._plugins.resume.getCookiePath('/details/item'))
9077
.toEqual('/details/item');
9178

92-
expect(br.getCookiePath('/details/item/'))
79+
expect(br._plugins.resume.getCookiePath('/details/item/'))
9380
.toEqual('/details/item/');
9481

95-
expect(br.getCookiePath('/details/item/almost/any/kind/of/long/path'))
82+
expect(br._plugins.resume.getCookiePath('/details/item/almost/any/kind/of/long/path'))
9683
.toEqual('/details/item/almost/any/kind/of/long/path');
9784
});
9885
});

0 commit comments

Comments
 (0)