@internetarchive/bookreader 5.0.0-61 → 5.0.0-62
Sign up to get free protection for your applications and to get access to all the features.
- package/BookReader/BookReader.css +63 -14
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReaderDemo/BookReaderDemo.css +2 -0
- package/BookReaderDemo/demo-internetarchive.html +91 -0
- package/CHANGELOG.md +5 -0
- package/package.json +2 -2
- package/src/BookReader/BookModel.js +2 -2
- package/src/BookReader/ModeThumb.js +1 -1
- package/src/BookReader/PageContainer.js +12 -0
- package/src/BookReader/events.js +0 -2
- package/src/BookReader/utils/SelectionObserver.js +43 -0
- package/src/BookReader.js +0 -264
- package/src/css/_BRpages.scss +2 -0
- package/src/css/_TextSelection.scss +84 -23
- package/src/plugins/plugin.text_selection.js +437 -112
- package/src/plugins/search/view.js +0 -9
- package/tests/jest/BookReader/BookModel.test.js +15 -0
- package/tests/jest/BookReader/utils/SelectionObserver.test.js +43 -0
- package/tests/jest/plugins/plugin.text_selection.test.js +166 -44
- package/src/BookReader/utils/SelectionStartedObserver.js +0 -46
- package/tests/jest/BookReader/utils/SelectionStartedObserver.test.js +0 -73
@@ -2,11 +2,13 @@
|
|
2
2
|
* Custom overrides for BookReader Demo.
|
3
3
|
*/
|
4
4
|
html {
|
5
|
+
/** This must be set because the nav menu uses rem and sets the fonts really big? */
|
5
6
|
font-size: 10px;
|
6
7
|
font-family: sans-serif;
|
7
8
|
}
|
8
9
|
|
9
10
|
body {
|
11
|
+
font-size: 16px;
|
10
12
|
background-color: #939598;
|
11
13
|
margin: 0px;
|
12
14
|
}
|
@@ -72,6 +72,97 @@
|
|
72
72
|
}
|
73
73
|
</style>
|
74
74
|
<section class="demos">
|
75
|
+
<details class="demo">
|
76
|
+
<summary>Test books</summary>
|
77
|
+
<ul>
|
78
|
+
<li>
|
79
|
+
Misc English book
|
80
|
+
<ul>
|
81
|
+
<li>
|
82
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=countofmontecris00duma_7">
|
83
|
+
<i>The Count of Monte-Cristo</i> by Alexandre Dumas
|
84
|
+
</a>
|
85
|
+
</li>
|
86
|
+
<li>
|
87
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=driitaleofdaring00bachuoft">
|
88
|
+
<i>D’ri and I</i> by Irving Bacheller
|
89
|
+
</a>
|
90
|
+
</li>
|
91
|
+
</ul>
|
92
|
+
</li>
|
93
|
+
<li>
|
94
|
+
Misc non-English book (<a href="https://archive.org/search?query=%21language%3Aeng&sort=-week&and%5B%5D=lending%3A%22is_readable%22&and%5B%5D=mediatype%3A%22texts%22">Search for more</a>)
|
95
|
+
<ul>
|
96
|
+
<li>
|
97
|
+
French: <a href="/BookReaderDemo/demo-internetarchive.html?ocaid=lecomtedemontecr01dumauoft">
|
98
|
+
<i>Le Comte de Monte-Cristo</i> by Alexandre Dumas
|
99
|
+
</a>
|
100
|
+
</li>
|
101
|
+
</ul>
|
102
|
+
</li>
|
103
|
+
<li>
|
104
|
+
Right-to-left book (<a href="https://archive.org/search?query=page-progression%3Arl&sort=-week&and%5B%5D=lending%3A%22is_readable%22&and%5B%5D=mediatype%3A%22texts%22">Search for more</a>)
|
105
|
+
<ul>
|
106
|
+
<li>
|
107
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=gendaitankashu00meijuoft">
|
108
|
+
<i>Gendai tanka shu</i> by Meiji, Emperor of Japan
|
109
|
+
</a>
|
110
|
+
</li>
|
111
|
+
</ul>
|
112
|
+
</li>
|
113
|
+
<li>
|
114
|
+
Newspaper with columns
|
115
|
+
<ul>
|
116
|
+
<li>
|
117
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=Crusader-Vol_28_Nos_1-20_Sept_1986-April_1987">
|
118
|
+
Crusader-Vol_28_Nos_1-20_Sept_1986-April_1987
|
119
|
+
</a>
|
120
|
+
</li>
|
121
|
+
</ul>
|
122
|
+
</li>
|
123
|
+
<li>
|
124
|
+
Text Selection
|
125
|
+
<ul>
|
126
|
+
<li>
|
127
|
+
OCR with spaces inside each <code><WORD></code> element
|
128
|
+
<ul>
|
129
|
+
<li><a href="/BookReaderDemo/demo-internetarchive.html?ocaid=theworksofplato01platiala">
|
130
|
+
<i>The Works of Plato</i> by Plato
|
131
|
+
</a></li>
|
132
|
+
</ul>
|
133
|
+
</li>
|
134
|
+
<li>
|
135
|
+
Weird font-sizes/indents
|
136
|
+
<ul>
|
137
|
+
<li><a href="/BookReaderDemo/demo-internetarchive.html?ocaid=cihm_58393#page/n3">
|
138
|
+
Microfilm poster thing
|
139
|
+
</a></li>
|
140
|
+
</ul>
|
141
|
+
</li>
|
142
|
+
<li>
|
143
|
+
Book with short lines
|
144
|
+
<ul>
|
145
|
+
<li>
|
146
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=countofmontecris00duma_7#page/261/mode/2up">
|
147
|
+
<i>The Count of Monte-Cristo</i>, p.261, second last line
|
148
|
+
</a>
|
149
|
+
</li>
|
150
|
+
</ul>
|
151
|
+
</li>
|
152
|
+
<li>
|
153
|
+
Book with double-spaced lines
|
154
|
+
<ul>
|
155
|
+
<li>
|
156
|
+
<a href="/BookReaderDemo/demo-internetarchive.html?ocaid=calnevpipelineex02unit#page/n93/mode/2up">
|
157
|
+
calnevpipelineex02unit
|
158
|
+
</a>
|
159
|
+
</li>
|
160
|
+
</ul>
|
161
|
+
</li>
|
162
|
+
</ul>
|
163
|
+
</li>
|
164
|
+
</ul>
|
165
|
+
</details>
|
75
166
|
<div class="demo">
|
76
167
|
<button id="toggle-loggedin">Toggle Logged in view</button>
|
77
168
|
<p>Features behind signed in gate: Bookmarks</p>
|
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# 5.0.0-62
|
2
|
+
- Fix: Make text selection work in Safari 15.4+ @cdrini
|
3
|
+
- Fix: Rewrite/improvements to text selection UX @cdrini
|
4
|
+
- Switches from SVG text layer to HTML text layer
|
5
|
+
|
1
6
|
# 5.0.0-61
|
2
7
|
- Fix: Mode2up preview pages hanging on first click @cdrini
|
3
8
|
- Dev: Add analytics event for text layer page selection @cdrini
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@internetarchive/bookreader",
|
3
|
-
"version": "5.0.0-
|
3
|
+
"version": "5.0.0-62",
|
4
4
|
"description": "The Internet Archive BookReader.",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -46,7 +46,7 @@
|
|
46
46
|
"@babel/plugin-proposal-class-properties": "7.16.7",
|
47
47
|
"@babel/plugin-proposal-decorators": "7.17.9",
|
48
48
|
"@babel/preset-env": "7.16.11",
|
49
|
-
"@open-wc/testing-helpers": "^2.2.
|
49
|
+
"@open-wc/testing-helpers": "^2.2.1",
|
50
50
|
"@types/jest": "^29.5.0",
|
51
51
|
"@webcomponents/webcomponentsjs": "^2.6.0",
|
52
52
|
"babel-loader": "8.2.5",
|
@@ -132,7 +132,7 @@ export class ModeThumb {
|
|
132
132
|
for (let i = 1; i < this.br.thumbRowBuffer; i++) {
|
133
133
|
if (firstRow - i >= 0) { rowsToDisplay.push(firstRow - i); }
|
134
134
|
}
|
135
|
-
rowsToDisplay.sort();
|
135
|
+
rowsToDisplay.sort((a, b) => a - b);
|
136
136
|
|
137
137
|
// Create the thumbnail divs and images (lazy loaded)
|
138
138
|
for (const row of rowsToDisplay) {
|
@@ -94,6 +94,18 @@ export function createSVGPageLayer(page, className) {
|
|
94
94
|
return svg;
|
95
95
|
}
|
96
96
|
|
97
|
+
/**
|
98
|
+
* @param {PageModel} page
|
99
|
+
* @param {string} className
|
100
|
+
*/
|
101
|
+
export function createDIVPageLayer(page, className) {
|
102
|
+
const div = document.createElement("div");
|
103
|
+
div.style.width = `${page.width}px`;
|
104
|
+
div.style.height = `${page.height}px`;
|
105
|
+
div.setAttribute('class', `BRPageLayer ${className}`);
|
106
|
+
return div;
|
107
|
+
}
|
108
|
+
|
97
109
|
/**
|
98
110
|
* @param {{ l: number, r: number, b: number, t: number }} box
|
99
111
|
*/
|
package/src/BookReader/events.js
CHANGED
@@ -8,8 +8,6 @@ export const EVENTS = {
|
|
8
8
|
stop: 'stop',
|
9
9
|
resize: 'resize',
|
10
10
|
userAction: 'userAction', // event to know if user is actively reading
|
11
|
-
// nav events:
|
12
|
-
navToggled: 'navToggled',
|
13
11
|
// menu click events
|
14
12
|
fullscreenToggled: 'fullscreenToggled',
|
15
13
|
zoomOut: 'zoomOut',
|
@@ -0,0 +1,43 @@
|
|
1
|
+
// @ts-check
|
2
|
+
export class SelectionObserver {
|
3
|
+
selecting = false;
|
4
|
+
startedInSelector = false;
|
5
|
+
/** @type {HTMLElement} */
|
6
|
+
target = null;
|
7
|
+
|
8
|
+
/**
|
9
|
+
* @param {string} selector
|
10
|
+
* @param {function('started' | 'cleared', HTMLElement): any} handler
|
11
|
+
*/
|
12
|
+
constructor(selector, handler) {
|
13
|
+
this.selector = selector;
|
14
|
+
this.handler = handler;
|
15
|
+
}
|
16
|
+
|
17
|
+
attach() {
|
18
|
+
// We can't just use selectstart, because safari on iOS just
|
19
|
+
// randomly decides when to fire it 😤
|
20
|
+
// document.addEventListener("selectstart", this._onSelectStart);
|
21
|
+
// This has to be on document :/
|
22
|
+
document.addEventListener("selectionchange", this._onSelectionChange);
|
23
|
+
}
|
24
|
+
|
25
|
+
detach() {
|
26
|
+
document.removeEventListener("selectionchange", this._onSelectionChange);
|
27
|
+
}
|
28
|
+
|
29
|
+
_onSelectionChange = () => {
|
30
|
+
const sel = window.getSelection();
|
31
|
+
|
32
|
+
if (!this.selecting && sel.toString()) {
|
33
|
+
this.selecting = true;
|
34
|
+
this.target = $(sel.anchorNode).closest(this.selector)[0];
|
35
|
+
this.handler('started', this.target);
|
36
|
+
}
|
37
|
+
|
38
|
+
if (this.selecting && (sel.isCollapsed || !sel.toString() || !$(sel.anchorNode).closest(this.selector)[0])) {
|
39
|
+
this.selecting = false;
|
40
|
+
this.handler('cleared', this.target);
|
41
|
+
}
|
42
|
+
};
|
43
|
+
}
|
package/src/BookReader.js
CHANGED
@@ -1412,10 +1412,6 @@ BookReader.prototype.bindNavigationHandlers = function() {
|
|
1412
1412
|
this.trigger(BookReader.eventNames.userAction);
|
1413
1413
|
});
|
1414
1414
|
|
1415
|
-
jIcons.filter('.fit').bind('fit', function() {
|
1416
|
-
// XXXmang implement autofit zoom
|
1417
|
-
});
|
1418
|
-
|
1419
1415
|
for (const control in navigationControls) {
|
1420
1416
|
jIcons.filter(`.${control}`).on('click.bindNavigationHandlers', () => {
|
1421
1417
|
navigationControls[control]();
|
@@ -1488,268 +1484,8 @@ BookReader.prototype.bindNavigationHandlers = function() {
|
|
1488
1484
|
self.$('.BRnavCntl').animate({opacity:.75},250);
|
1489
1485
|
}
|
1490
1486
|
});
|
1491
|
-
|
1492
|
-
this.initSwipeData();
|
1493
|
-
|
1494
|
-
$(document).off('mousemove.navigation', this.el);
|
1495
|
-
$(document).on(
|
1496
|
-
'mousemove.navigation',
|
1497
|
-
this.el,
|
1498
|
-
{ 'br': this },
|
1499
|
-
this.navigationMousemoveHandler
|
1500
|
-
);
|
1501
|
-
|
1502
|
-
$(document).off('mousedown.swipe', '.BRpageimage');
|
1503
|
-
$(document).on(
|
1504
|
-
'mousedown.swipe',
|
1505
|
-
'.BRpageimage',
|
1506
|
-
{ 'br': this },
|
1507
|
-
this.swipeMousedownHandler
|
1508
|
-
);
|
1509
|
-
|
1510
|
-
this.bindMozTouchHandlers();
|
1511
|
-
};
|
1512
|
-
|
1513
|
-
/**
|
1514
|
-
* Unbind navigation handlers
|
1515
|
-
*/
|
1516
|
-
BookReader.prototype.unbindNavigationHandlers = function() {
|
1517
|
-
$(document).off('mousemove.navigation', this.el);
|
1518
|
-
};
|
1519
|
-
|
1520
|
-
/**
|
1521
|
-
* Handle mousemove related to navigation. Bind at #BookReader level to allow autohide.
|
1522
|
-
*/
|
1523
|
-
BookReader.prototype.navigationMousemoveHandler = function(event) {
|
1524
|
-
// $$$ possibly not great to be calling this for every mousemove
|
1525
|
-
if (event.data['br'].uiAutoHide) {
|
1526
|
-
// 77px is an approximate height of the Internet Archive Top Nav
|
1527
|
-
// 75 & 76 (pixels) provide used in this context is checked against the IA top nav height
|
1528
|
-
const navkey = $(document).height() - 75;
|
1529
|
-
if ((event.pageY < 76) || (event.pageY > navkey)) {
|
1530
|
-
// inside or near navigation elements
|
1531
|
-
event.data['br'].hideNavigation();
|
1532
|
-
} else {
|
1533
|
-
event.data['br'].showNavigation();
|
1534
|
-
}
|
1535
|
-
}
|
1536
|
-
};
|
1537
|
-
|
1538
|
-
BookReader.prototype.initSwipeData = function(clientX, clientY) {
|
1539
|
-
/*
|
1540
|
-
* Based on the really quite awesome "Today's Guardian" at http://guardian.gyford.com/
|
1541
|
-
*/
|
1542
|
-
this._swipe = {
|
1543
|
-
mightBeSwiping: false,
|
1544
|
-
didSwipe: false,
|
1545
|
-
mightBeDraggin: false,
|
1546
|
-
didDrag: false,
|
1547
|
-
startTime: (new Date).getTime(),
|
1548
|
-
startX: clientX,
|
1549
|
-
startY: clientY,
|
1550
|
-
lastX: clientX,
|
1551
|
-
lastY: clientY,
|
1552
|
-
deltaX: 0,
|
1553
|
-
deltaY: 0,
|
1554
|
-
deltaT: 0
|
1555
|
-
};
|
1556
|
-
};
|
1557
|
-
|
1558
|
-
BookReader.prototype.swipeMousedownHandler = function(event) {
|
1559
|
-
const self = event.data['br'];
|
1560
|
-
|
1561
|
-
// We should be the last bubble point for the page images
|
1562
|
-
// Disable image drag and select, but keep right-click
|
1563
|
-
if (event.which == 3) {
|
1564
|
-
return !self.protected;
|
1565
|
-
}
|
1566
|
-
|
1567
|
-
$(event.target).on('mouseout.swipe',
|
1568
|
-
{ 'br': self},
|
1569
|
-
self.swipeMouseupHandler
|
1570
|
-
).on('mouseup.swipe',
|
1571
|
-
{ 'br': self},
|
1572
|
-
self.swipeMouseupHandler
|
1573
|
-
).on('mousemove.swipe',
|
1574
|
-
{ 'br': self },
|
1575
|
-
self.swipeMousemoveHandler
|
1576
|
-
);
|
1577
|
-
|
1578
|
-
self.initSwipeData(event.clientX, event.clientY);
|
1579
|
-
self._swipe.mightBeSwiping = true;
|
1580
|
-
self._swipe.mightBeDragging = true;
|
1581
|
-
|
1582
|
-
event.preventDefault();
|
1583
|
-
event.returnValue = false;
|
1584
|
-
event.cancelBubble = true;
|
1585
|
-
return false;
|
1586
|
-
};
|
1587
|
-
|
1588
|
-
BookReader.prototype.swipeMousemoveHandler = function(event) {
|
1589
|
-
const self = event.data['br'];
|
1590
|
-
const _swipe = self._swipe;
|
1591
|
-
if (! _swipe.mightBeSwiping) {
|
1592
|
-
return;
|
1593
|
-
}
|
1594
|
-
|
1595
|
-
// Update swipe data
|
1596
|
-
_swipe.deltaX = event.clientX - _swipe.startX;
|
1597
|
-
_swipe.deltaY = event.clientY - _swipe.startY;
|
1598
|
-
_swipe.deltaT = (new Date).getTime() - _swipe.startTime;
|
1599
|
-
|
1600
|
-
const absX = Math.abs(_swipe.deltaX);
|
1601
|
-
const absY = Math.abs(_swipe.deltaY);
|
1602
|
-
|
1603
|
-
// Minimum distance in the amount of tim to trigger the swipe
|
1604
|
-
const minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
|
1605
|
-
const maxSwipeTime = 400;
|
1606
|
-
|
1607
|
-
// Check for horizontal swipe
|
1608
|
-
if (absX > absY && (absX > minSwipeLength) && _swipe.deltaT < maxSwipeTime) {
|
1609
|
-
_swipe.mightBeSwiping = false; // only trigger once
|
1610
|
-
_swipe.didSwipe = true;
|
1611
|
-
if (self.mode == self.constMode2up) {
|
1612
|
-
if (_swipe.deltaX < 0) {
|
1613
|
-
self.right();
|
1614
|
-
} else {
|
1615
|
-
self.left();
|
1616
|
-
}
|
1617
|
-
}
|
1618
|
-
}
|
1619
|
-
|
1620
|
-
if ( _swipe.deltaT > maxSwipeTime && !_swipe.didSwipe) {
|
1621
|
-
if (_swipe.mightBeDragging) {
|
1622
|
-
// Dragging
|
1623
|
-
_swipe.didDrag = true;
|
1624
|
-
self.refs.$brContainer
|
1625
|
-
.scrollTop(self.refs.$brContainer.scrollTop() - event.clientY + _swipe.lastY)
|
1626
|
-
.scrollLeft(self.refs.$brContainer.scrollLeft() - event.clientX + _swipe.lastX);
|
1627
|
-
}
|
1628
|
-
}
|
1629
|
-
_swipe.lastX = event.clientX;
|
1630
|
-
_swipe.lastY = event.clientY;
|
1631
|
-
|
1632
|
-
event.preventDefault();
|
1633
|
-
event.returnValue = false;
|
1634
|
-
event.cancelBubble = true;
|
1635
|
-
return false;
|
1636
|
-
};
|
1637
|
-
|
1638
|
-
BookReader.prototype.swipeMouseupHandler = function(event) {
|
1639
|
-
const _swipe = event.data['br']._swipe;
|
1640
|
-
_swipe.mightBeSwiping = false;
|
1641
|
-
_swipe.mightBeDragging = false;
|
1642
|
-
|
1643
|
-
$(event.target).off('mouseout.swipe').off('mouseup.swipe').off('mousemove.swipe');
|
1644
|
-
|
1645
|
-
if (_swipe.didSwipe || _swipe.didDrag) {
|
1646
|
-
// Swallow event if completed swipe gesture
|
1647
|
-
event.preventDefault();
|
1648
|
-
event.returnValue = false;
|
1649
|
-
event.cancelBubble = true;
|
1650
|
-
return false;
|
1651
|
-
}
|
1652
|
-
return true;
|
1653
|
-
};
|
1654
|
-
|
1655
|
-
BookReader.prototype.bindMozTouchHandlers = function() {
|
1656
|
-
const self = this;
|
1657
|
-
|
1658
|
-
// Currently only want touch handlers in 2up
|
1659
|
-
this.refs.$br
|
1660
|
-
.on('MozTouchDown', function(event) {
|
1661
|
-
if (this.mode == self.constMode2up) {
|
1662
|
-
event.preventDefault();
|
1663
|
-
}
|
1664
|
-
})
|
1665
|
-
.on('MozTouchMove', function(event) {
|
1666
|
-
if (this.mode == self.constMode2up) {
|
1667
|
-
event.preventDefault();
|
1668
|
-
}
|
1669
|
-
})
|
1670
|
-
.on('MozTouchUp', function(event) {
|
1671
|
-
if (this.mode == self.constMode2up) {
|
1672
|
-
event.preventDefault();
|
1673
|
-
}
|
1674
|
-
});
|
1675
|
-
};
|
1676
|
-
|
1677
|
-
/**
|
1678
|
-
* Returns true if the navigation elements are currently visible
|
1679
|
-
* @return {boolean}
|
1680
|
-
*/
|
1681
|
-
BookReader.prototype.navigationIsVisible = function() {
|
1682
|
-
// $$$ doesn't account for transitioning states, nav must be fully visible to return true
|
1683
|
-
const toolpos = this.refs.$BRtoolbar.position();
|
1684
|
-
const tooltop = toolpos.top;
|
1685
|
-
return tooltop == 0;
|
1686
1487
|
};
|
1687
1488
|
|
1688
|
-
/**
|
1689
|
-
* Main controller that sets navigation into view.
|
1690
|
-
* Defaults to SHOW the navigation chrome
|
1691
|
-
*/
|
1692
|
-
BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
|
1693
|
-
const animationLength = this.constNavAnimationDuration;
|
1694
|
-
const animationType = 'linear';
|
1695
|
-
const resizePageContainer = function resizePageContainer () {
|
1696
|
-
/* main page container fills whole container */
|
1697
|
-
if (this.constMode2up !== this.mode) {
|
1698
|
-
const animate = true;
|
1699
|
-
this.resizeBRcontainer(animate);
|
1700
|
-
}
|
1701
|
-
this.trigger(BookReader.eventNames.navToggled);
|
1702
|
-
}.bind(this);
|
1703
|
-
|
1704
|
-
let toolbarHeight = 0;
|
1705
|
-
let navbarHeight = 0;
|
1706
|
-
if (hide) {
|
1707
|
-
toolbarHeight = this.getToolBarHeight() * -1;
|
1708
|
-
navbarHeight = this.getFooterHeight() * -1;
|
1709
|
-
|
1710
|
-
this.refs.$BRtoolbar.addClass('js-menu-hide');
|
1711
|
-
this.refs.$BRfooter.addClass('js-menu-hide');
|
1712
|
-
} else {
|
1713
|
-
this.refs.$BRtoolbar.removeClass('js-menu-hide');
|
1714
|
-
this.refs.$BRfooter.removeClass('js-menu-hide');
|
1715
|
-
}
|
1716
|
-
|
1717
|
-
this.refs.$BRtoolbar.animate(
|
1718
|
-
{ top: toolbarHeight },
|
1719
|
-
animationLength,
|
1720
|
-
animationType,
|
1721
|
-
resizePageContainer
|
1722
|
-
);
|
1723
|
-
this.refs.$BRfooter.animate(
|
1724
|
-
{ bottom: navbarHeight },
|
1725
|
-
animationLength,
|
1726
|
-
animationType,
|
1727
|
-
resizePageContainer
|
1728
|
-
);
|
1729
|
-
};
|
1730
|
-
/**
|
1731
|
-
* Hide navigation elements, if visible
|
1732
|
-
*/
|
1733
|
-
BookReader.prototype.hideNavigation = function() {
|
1734
|
-
// Check if navigation is showing
|
1735
|
-
if (this.navigationIsVisible()) {
|
1736
|
-
const hide = true;
|
1737
|
-
this.setNavigationView(hide);
|
1738
|
-
}
|
1739
|
-
};
|
1740
|
-
|
1741
|
-
/**
|
1742
|
-
* Show navigation elements
|
1743
|
-
*/
|
1744
|
-
BookReader.prototype.showNavigation = function() {
|
1745
|
-
// Check if navigation is hidden
|
1746
|
-
if (!this.navigationIsVisible()) {
|
1747
|
-
this.setNavigationView();
|
1748
|
-
}
|
1749
|
-
};
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
1489
|
/**************************/
|
1754
1490
|
/** BookModel extensions **/
|
1755
1491
|
/**************************/
|
package/src/css/_BRpages.scss
CHANGED
@@ -1,41 +1,70 @@
|
|
1
|
-
.
|
1
|
+
.BRtextLayer {
|
2
2
|
z-index: 2;
|
3
|
-
|
4
|
-
|
3
|
+
position: absolute;
|
4
|
+
top: 0;
|
5
|
+
left: 0;
|
6
|
+
color: transparent;
|
7
|
+
transform-origin: 0 0;
|
8
|
+
// Make it so right-clicking on "blank" part of text layer sends events to the image (for saving)
|
5
9
|
pointer-events: none;
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
cursor: text;
|
11
|
+
}
|
12
|
+
|
13
|
+
.BRparagraphElement {
|
14
|
+
margin: 0;
|
15
|
+
cursor: text;
|
16
|
+
font-family: Georgia, serif;
|
17
|
+
line-height: 0;
|
18
|
+
}
|
19
|
+
|
20
|
+
.BRlineElement {
|
21
|
+
pointer-events: all;
|
22
|
+
white-space: nowrap;
|
23
|
+
display: inline-block;
|
24
|
+
|
25
|
+
// We use display: inline-block, otherwise this causes every line
|
26
|
+
// to have newlines at the end in safari. BUT, since they're inline,
|
27
|
+
// if the OCR has to short line in the same paragraph, they can wrap
|
28
|
+
// and one can go onto the other. This adds an arbitrary margin to
|
29
|
+
// the right of each line, forcing things to wrap.
|
30
|
+
// See eg https://www-drini.archive.org/details/countofmontecris00duma_7/page/261/mode/2up
|
31
|
+
// Page 261, second last line on the page.
|
32
|
+
.BRtextLayer[dir=ltr] & { margin-right: 100%; }
|
33
|
+
.BRtextLayer[dir=rtl] & { margin-left: 100%; }
|
34
|
+
}
|
35
|
+
|
36
|
+
// Highlight colors for text selection layer
|
37
|
+
.BRwordElement, .BRspace, .BRparagraphElement, .BRparagraphElement br {
|
38
|
+
// these 2 properties do not work if joined
|
39
|
+
&::selection {
|
14
40
|
background: hsla(210, 74%, 62%, 0.4);
|
15
41
|
}
|
16
|
-
|
42
|
+
|
43
|
+
&::-moz-selection {
|
17
44
|
background: hsla(210, 74%, 62%, 0.4);
|
18
|
-
color:
|
45
|
+
color:transparent;
|
19
46
|
}
|
47
|
+
}
|
20
48
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
49
|
+
.BRparagraphElement br {
|
50
|
+
visibility: hidden;
|
51
|
+
}
|
52
|
+
|
53
|
+
// Use CSS pseudo-elements to render the hyphens. This makes them
|
54
|
+
// not selectable, so copy/pasting text doesn't include them.
|
55
|
+
.BRwordElement--hyphen::after {
|
56
|
+
content: "-";
|
27
57
|
}
|
28
58
|
|
29
59
|
// Hide text layer for performance during zooming & scrolling
|
30
60
|
.BRsmooth-zooming, .BRscrolling-active {
|
31
|
-
.
|
61
|
+
.BRpagecontainer:not(.BRpagecontainer--hasSelection) .BRtextLayer {
|
32
62
|
display: none;
|
33
63
|
}
|
34
64
|
}
|
35
65
|
|
36
|
-
// Hide text selection layers of off-screen pages
|
37
|
-
|
38
|
-
.BRmode1up .BRpagecontainer:not(.BRpage-visible) .textSelectionSVG {
|
66
|
+
// Hide text selection layers of off-screen pages
|
67
|
+
.BRmode1up .BRpagecontainer:not(.BRpage-visible) .BRtextLayer {
|
39
68
|
display: none;
|
40
69
|
}
|
41
70
|
|
@@ -45,3 +74,35 @@
|
|
45
74
|
-moz-user-select: none;
|
46
75
|
user-select: none;
|
47
76
|
}
|
77
|
+
|
78
|
+
|
79
|
+
// These are Microsoft Edge specific fixed to make some of the
|
80
|
+
// browsers features work well. These are for the in-place
|
81
|
+
// translation.
|
82
|
+
.BRwordElement, .BRspace {
|
83
|
+
&[_istranslated="1"], &[_msttexthash] {
|
84
|
+
background-color: #e4dccd;
|
85
|
+
color: black;
|
86
|
+
letter-spacing: unset !important;
|
87
|
+
background: #ccbfa7;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
.BRlineElement font[_mstmutation="1"] {
|
92
|
+
background: #ccbfa7;
|
93
|
+
}
|
94
|
+
|
95
|
+
.BRlineElement:has([_istranslated="1"], [_msttexthash]) {
|
96
|
+
background-color: #e4dccd;
|
97
|
+
color: black;
|
98
|
+
text-align: justify;
|
99
|
+
width: inherit;
|
100
|
+
&:not(:nth-last-child(2)) {
|
101
|
+
text-align-last: justify;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
.BRlineElement[_msttexthash] {
|
106
|
+
background: #ccbfa7;
|
107
|
+
word-spacing: unset !important;
|
108
|
+
}
|