wepub

Check-in [5d74a2880e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add UI for font size up/down, smooth scroll, save font size for book.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | master | trunk
Files: files | file ages | folders
SHA3-256:5d74a2880ee0abc55d21464b06d1e3f1b1a2ceb9a1c81649823be9e83b4b6ab2
User & Date: ajv-899-334-8894@vsta.org 2017-06-24 04:32:14
Context
2018-04-26
00:55
Tidy up display and styling. Fix (again) bug with chapter numbering. check-in: cb7f4d4130 user: vandyswa@gmail.com tags: master, trunk
2017-06-24
04:32
Add UI for font size up/down, smooth scroll, save font size for book. check-in: 5d74a2880e user: ajv-899-334-8894@vsta.org tags: master, trunk
2017-04-06
04:01
Tap to adjust font size. check-in: 3f780220b4 user: ajv-899-334-8894@vsta.org tags: master, trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to js/reader.js.

1
2
3
4

5
6
7
8
9
10
11
..
14
15
16
17
18
19
20





21
22
23
24
25
26
27
28
29
30
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82


83
84
85
86
87
88
89
90
91



92
93
94
95
96
























97
98
99
100
101
102
103
104
105
106


























107
108
109

110
111
112
113
114
115
116
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
//
// reader.js
//      Support functions for reading a chapter on a web page
//


// User name
var who = null;

// Document path
var docname = null;

................................................................................

// Web element with text content which scrolls
var pane = null;

// Current font size
var curSize = 14;






// Wrappers for XMLHttpRequest
function xhr_get(url, fn) {
    var req = new XMLHttpRequest();
    req.open("GET", url);
    req.onreadystatechange = function() {
        // Ignore progress/errors
        if ((req.readyState != 4) || (req.status != 200)) {
            return;
        }

................................................................................
        if (fn != null) {
            fn(req.responseText);
        }
    }
    req.send();
}
function xhr_put_json(url, buf, fn) {
    var req = new XMLHttpRequest();
    req.open("PUT", url);
    req.setRequestHeader("Content-type", "application/json");
    req.setRequestHeader("Content-length", buf.length);
    req.onreadystatechange = function() {
        // Ignore progress/errors
        if ((req.readyState != 4) || (req.status != 200)) {
            return;
        }

        // Response (or ignore)
................................................................................
        }
    }
    req.send(buf);
}

// Saved state for this user on this document
function start_state(txt) {
    var resp = JSON.parse(txt);

    // See if there's a position for our section
    if (!(secnum in resp)) {
        // Just leave us at top
        return;

    }

    // Position is saved as a float percentage 0..1, so
    //  scale fractional position against overall scroll
    //  height to set position.

    var d = document.scrollingElement;
    if (d != null) {
        d.scrollTop = d.scrollHeight * resp[secnum];
    }

    // TBD, styling to patch into CSS?
}

// Push our position
function save_state() {
    var st = {};
    var d = document.scrollingElement;
    if (d != null) {


        // Which section?  Each chapter has its own position.
        st.secnum = secnum;

        // Record URL we're using
        st.url = document.URL;

        // Percentage position on scroll bar
        st.pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);




        // Send it over
        xhr_put_json("/state.json?doc=" + encodeURIComponent(docname),
            JSON.stringify(st), null);
    }
}

























// They tapped the screen.
//
// First pass, upper half shrinks text, lower grows.
function tapped(ev) {
    // When we changed font size, our scroll position has to be refreshed
    //  to be the same portion of the new scrollable size.
    var d = document.scrollingElement;
    var pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);



























    // Shrink for upper tap, grow for lower
    var coord = ev.screenY;
    if (coord < window.innerHeight/2) {

        if (curSize > 4) {
            curSize -= 2;
        }
    } else {
        curSize += 2;
    }
    pane.style.fontSize = curSize.toString() + "px";
................................................................................
    docname = arg_doc;
    pane = document.getElementById(arg_pane);

    // Tap handler
    pane.onclick = tapped;

    // Calculate section number
    var url = document.URL;
    var slidx = url.lastIndexOf('/');
    if (slidx > 0) {
        secnum = parseInt(url.slice(slidx+1));
    }

    // By default, start at top of document
    var d = document.scrollingElement;
    if (d != null) {
        d.scrollTop = 0;

    }

    // Snapshot our reading position when we switch away
    document.addEventListener("blur", save_state);
    document.addEventListener("mouseleave", save_state);
    document.addEventListener("visibilitychange", function () {
        if (document.hidden) {




>







 







>
>
>
>
>


|







 







|


<







 







|

|
|
|
|
>





>
|
|
|
|
|
<




<
|

>
>









>
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
>







 







|
|





|


>







1
2
3
4
5
6
7
8
9
10
11
12
..
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
..
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167


168
169
170
171
172
173
174
175
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//
// reader.js
//      Support functions for reading a chapter on a web page
//
"use strict";

// User name
var who = null;

// Document path
var docname = null;

................................................................................

// Web element with text content which scrolls
var pane = null;

// Current font size
var curSize = 14;

// Target ms to scroll to new page
const SmoothTime = 750,
    Steps = 20,
    Interval = SmoothTime/Steps;

// Wrappers for XMLHttpRequest
function xhr_get(url, fn) {
    const req = new XMLHttpRequest();
    req.open("GET", url);
    req.onreadystatechange = function() {
        // Ignore progress/errors
        if ((req.readyState != 4) || (req.status != 200)) {
            return;
        }

................................................................................
        if (fn != null) {
            fn(req.responseText);
        }
    }
    req.send();
}
function xhr_put_json(url, buf, fn) {
    const req = new XMLHttpRequest();
    req.open("PUT", url);
    req.setRequestHeader("Content-type", "application/json");

    req.onreadystatechange = function() {
        // Ignore progress/errors
        if ((req.readyState != 4) || (req.status != 200)) {
            return;
        }

        // Response (or ignore)
................................................................................
        }
    }
    req.send(buf);
}

// Saved state for this user on this document
function start_state(txt) {
    const resp = JSON.parse(txt);

    // Set a font size?  (Font size is global to document,
    //  hopefully a feature.)
    if ("fontSize" in resp) {
        curSize = resp.fontSize;
        pane.style.fontSize = curSize.toString() + "px";
    }

    // Position is saved as a float percentage 0..1, so
    //  scale fractional position against overall scroll
    //  height to set position.
    if (secnum in resp) {
        const d = document.scrollingElement;
        if (d != null) {
            d.scrollTop = d.scrollHeight * resp[secnum];
        }
    }

}

// Push our position
function save_state() {

    const d = document.scrollingElement;
    if (d != null) {
        const st = {};

        // Which section?  Each chapter has its own position.
        st.secnum = secnum;

        // Record URL we're using
        st.url = document.URL;

        // Percentage position on scroll bar
        st.pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);

        // Current font size
        st.fontSize = curSize;

        // Send it over
        xhr_put_json("/state.json?doc=" + encodeURIComponent(docname),
            JSON.stringify(st), null);
    }
}

// Next step of scrolling
function smooth_scroll(d, incr, step) {

    // Reached target
    if (step == 0) {
        return;
    }

    // Next increment of motion
    d.scrollTop += incr;
    setTimeout(function () {
        smooth_scroll(d, incr, step-1);
    }, Interval);
}

// Smoothly move @d's scrollTop to the new value @targ
function smoothly(d, targ) {
    const dx = targ - d.scrollTop;
    const incr = parseFloat(dx)/Steps;

    // Walk steps until we reach @targ
    smooth_scroll(d, incr, Steps);
}

// They tapped the screen.
//
// First pass, upper half shrinks text, lower grows.
function tapped(ev) {
    // When we changed font size, our scroll position has to be refreshed
    //  to be the same portion of the new scrollable size.
    const d = document.scrollingElement;
    const pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);

    // Short names for geometry
    const h = window.innerHeight, w = window.innerWidth;

    // Top quarter, previous page, bottom quarter, next page
    // 10% overlap
    // We delay the scroll to "break" the finger contact which
    //  otherwise can look like a drag across the scrolled text.
    const evY = ev.screenY;
    let nd = null;
    if (evY < (h/4)) {
        nd = d.scrollTop - (9 * d.clientHeight) / 10;
    }
    if (evY > ((h*3)/4)) {
        nd = d.scrollTop + (9 * d.clientHeight) / 10;
    }
    if (nd != null) {
        smoothly(d, nd);
        return;
    }

    // Font adjustment only happend in middle third of screen
    const evX = ev.screenX;
    if ((evX < w/3) || (evX > ((w*2)/3))) {
        return;
    }

    // Shrink for upper tap, grow for lower


    if (evY < h/2) {
        if (curSize > 4) {
            curSize -= 2;
        }
    } else {
        curSize += 2;
    }
    pane.style.fontSize = curSize.toString() + "px";
................................................................................
    docname = arg_doc;
    pane = document.getElementById(arg_pane);

    // Tap handler
    pane.onclick = tapped;

    // Calculate section number
    const url = document.URL;
    const slidx = url.lastIndexOf('/');
    if (slidx > 0) {
        secnum = parseInt(url.slice(slidx+1));
    }

    // By default, start at top of document
    const d = document.scrollingElement;
    if (d != null) {
        d.scrollTop = 0;
        d.style.userSelect = "none";
    }

    // Snapshot our reading position when we switch away
    document.addEventListener("blur", save_state);
    document.addEventListener("mouseleave", save_state);
    document.addEventListener("visibilitychange", function () {
        if (document.hidden) {

Changes to put.py.

34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
            f.close()
        except:
            ovals = {}

        # Update with this state
        newvals = json.loads(buf)
        ovals["url"] = str(newvals["url"])

        ovals[int(newvals["secnum"])] = float(newvals["pos"])

        # Try and save back
        try:
            f = open(statepath, "w")
            f.write(json.dumps(ovals))
            f.close()
        except:
            sys.stderr.write("Can't save state to %s\n" % (statepath,))

        return True,self.send_result("", "text/html")







>











34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
            f.close()
        except:
            ovals = {}

        # Update with this state
        newvals = json.loads(buf)
        ovals["url"] = str(newvals["url"])
        ovals["fontSize"] = int(newvals["fontSize"])
        ovals[int(newvals["secnum"])] = float(newvals["pos"])

        # Try and save back
        try:
            f = open(statepath, "w")
            f.write(json.dumps(ovals))
            f.close()
        except:
            sys.stderr.write("Can't save state to %s\n" % (statepath,))

        return True,self.send_result("", "text/html")