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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to js/reader.js.

     1      1   //
     2      2   // reader.js
     3      3   //      Support functions for reading a chapter on a web page
     4      4   //
            5  +"use strict";
     5      6   
     6      7   // User name
     7      8   var who = null;
     8      9   
     9     10   // Document path
    10     11   var docname = null;
    11     12   
................................................................................
    14     15   
    15     16   // Web element with text content which scrolls
    16     17   var pane = null;
    17     18   
    18     19   // Current font size
    19     20   var curSize = 14;
    20     21   
           22  +// Target ms to scroll to new page
           23  +const SmoothTime = 750,
           24  +    Steps = 20,
           25  +    Interval = SmoothTime/Steps;
           26  +
    21     27   // Wrappers for XMLHttpRequest
    22     28   function xhr_get(url, fn) {
    23         -    var req = new XMLHttpRequest();
           29  +    const req = new XMLHttpRequest();
    24     30       req.open("GET", url);
    25     31       req.onreadystatechange = function() {
    26     32           // Ignore progress/errors
    27     33           if ((req.readyState != 4) || (req.status != 200)) {
    28     34               return;
    29     35           }
    30     36   
................................................................................
    32     38           if (fn != null) {
    33     39               fn(req.responseText);
    34     40           }
    35     41       }
    36     42       req.send();
    37     43   }
    38     44   function xhr_put_json(url, buf, fn) {
    39         -    var req = new XMLHttpRequest();
           45  +    const req = new XMLHttpRequest();
    40     46       req.open("PUT", url);
    41     47       req.setRequestHeader("Content-type", "application/json");
    42         -    req.setRequestHeader("Content-length", buf.length);
    43     48       req.onreadystatechange = function() {
    44     49           // Ignore progress/errors
    45     50           if ((req.readyState != 4) || (req.status != 200)) {
    46     51               return;
    47     52           }
    48     53   
    49     54           // Response (or ignore)
................................................................................
    52     57           }
    53     58       }
    54     59       req.send(buf);
    55     60   }
    56     61   
    57     62   // Saved state for this user on this document
    58     63   function start_state(txt) {
    59         -    var resp = JSON.parse(txt);
           64  +    const resp = JSON.parse(txt);
    60     65   
    61         -    // See if there's a position for our section
    62         -    if (!(secnum in resp)) {
    63         -        // Just leave us at top
    64         -        return;
           66  +    // Set a font size?  (Font size is global to document,
           67  +    //  hopefully a feature.)
           68  +    if ("fontSize" in resp) {
           69  +        curSize = resp.fontSize;
           70  +        pane.style.fontSize = curSize.toString() + "px";
    65     71       }
    66     72   
    67     73       // Position is saved as a float percentage 0..1, so
    68     74       //  scale fractional position against overall scroll
    69     75       //  height to set position.
    70         -    var d = document.scrollingElement;
    71         -    if (d != null) {
    72         -        d.scrollTop = d.scrollHeight * resp[secnum];
           76  +    if (secnum in resp) {
           77  +        const d = document.scrollingElement;
           78  +        if (d != null) {
           79  +            d.scrollTop = d.scrollHeight * resp[secnum];
           80  +        }
    73     81       }
    74         -
    75         -    // TBD, styling to patch into CSS?
    76     82   }
    77     83   
    78     84   // Push our position
    79     85   function save_state() {
    80         -    var st = {};
    81         -    var d = document.scrollingElement;
           86  +    const d = document.scrollingElement;
    82     87       if (d != null) {
           88  +        const st = {};
           89  +
    83     90           // Which section?  Each chapter has its own position.
    84     91           st.secnum = secnum;
    85     92   
    86     93           // Record URL we're using
    87     94           st.url = document.URL;
    88     95   
    89     96           // Percentage position on scroll bar
    90     97           st.pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);
    91     98   
           99  +        // Current font size
          100  +        st.fontSize = curSize;
          101  +
    92    102           // Send it over
    93    103           xhr_put_json("/state.json?doc=" + encodeURIComponent(docname),
    94    104               JSON.stringify(st), null);
    95    105       }
    96    106   }
          107  +
          108  +// Next step of scrolling
          109  +function smooth_scroll(d, incr, step) {
          110  +
          111  +    // Reached target
          112  +    if (step == 0) {
          113  +        return;
          114  +    }
          115  +
          116  +    // Next increment of motion
          117  +    d.scrollTop += incr;
          118  +    setTimeout(function () {
          119  +        smooth_scroll(d, incr, step-1);
          120  +    }, Interval);
          121  +}
          122  +
          123  +// Smoothly move @d's scrollTop to the new value @targ
          124  +function smoothly(d, targ) {
          125  +    const dx = targ - d.scrollTop;
          126  +    const incr = parseFloat(dx)/Steps;
          127  +
          128  +    // Walk steps until we reach @targ
          129  +    smooth_scroll(d, incr, Steps);
          130  +}
    97    131   
    98    132   // They tapped the screen.
    99    133   //
   100    134   // First pass, upper half shrinks text, lower grows.
   101    135   function tapped(ev) {
   102    136       // When we changed font size, our scroll position has to be refreshed
   103    137       //  to be the same portion of the new scrollable size.
   104         -    var d = document.scrollingElement;
   105         -    var pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);
          138  +    const d = document.scrollingElement;
          139  +    const pos = parseFloat(d.scrollTop) / parseFloat(d.scrollHeight);
          140  +
          141  +    // Short names for geometry
          142  +    const h = window.innerHeight, w = window.innerWidth;
          143  +
          144  +    // Top quarter, previous page, bottom quarter, next page
          145  +    // 10% overlap
          146  +    // We delay the scroll to "break" the finger contact which
          147  +    //  otherwise can look like a drag across the scrolled text.
          148  +    const evY = ev.screenY;
          149  +    let nd = null;
          150  +    if (evY < (h/4)) {
          151  +        nd = d.scrollTop - (9 * d.clientHeight) / 10;
          152  +    }
          153  +    if (evY > ((h*3)/4)) {
          154  +        nd = d.scrollTop + (9 * d.clientHeight) / 10;
          155  +    }
          156  +    if (nd != null) {
          157  +        smoothly(d, nd);
          158  +        return;
          159  +    }
          160  +
          161  +    // Font adjustment only happend in middle third of screen
          162  +    const evX = ev.screenX;
          163  +    if ((evX < w/3) || (evX > ((w*2)/3))) {
          164  +        return;
          165  +    }
   106    166   
   107    167       // Shrink for upper tap, grow for lower
   108         -    var coord = ev.screenY;
   109         -    if (coord < window.innerHeight/2) {
          168  +    if (evY < h/2) {
   110    169           if (curSize > 4) {
   111    170               curSize -= 2;
   112    171           }
   113    172       } else {
   114    173           curSize += 2;
   115    174       }
   116    175       pane.style.fontSize = curSize.toString() + "px";
................................................................................
   128    187       docname = arg_doc;
   129    188       pane = document.getElementById(arg_pane);
   130    189   
   131    190       // Tap handler
   132    191       pane.onclick = tapped;
   133    192   
   134    193       // Calculate section number
   135         -    var url = document.URL;
   136         -    var slidx = url.lastIndexOf('/');
          194  +    const url = document.URL;
          195  +    const slidx = url.lastIndexOf('/');
   137    196       if (slidx > 0) {
   138    197           secnum = parseInt(url.slice(slidx+1));
   139    198       }
   140    199   
   141    200       // By default, start at top of document
   142         -    var d = document.scrollingElement;
          201  +    const d = document.scrollingElement;
   143    202       if (d != null) {
   144    203           d.scrollTop = 0;
          204  +        d.style.userSelect = "none";
   145    205       }
   146    206   
   147    207       // Snapshot our reading position when we switch away
   148    208       document.addEventListener("blur", save_state);
   149    209       document.addEventListener("mouseleave", save_state);
   150    210       document.addEventListener("visibilitychange", function () {
   151    211           if (document.hidden) {

Changes to put.py.

    34     34               f.close()
    35     35           except:
    36     36               ovals = {}
    37     37   
    38     38           # Update with this state
    39     39           newvals = json.loads(buf)
    40     40           ovals["url"] = str(newvals["url"])
           41  +        ovals["fontSize"] = int(newvals["fontSize"])
    41     42           ovals[int(newvals["secnum"])] = float(newvals["pos"])
    42     43   
    43     44           # Try and save back
    44     45           try:
    45     46               f = open(statepath, "w")
    46     47               f.write(json.dumps(ovals))
    47     48               f.close()
    48     49           except:
    49     50               sys.stderr.write("Can't save state to %s\n" % (statepath,))
    50     51   
    51     52           return True,self.send_result("", "text/html")