Avoid returning hard-wired HTML strings from the C code.
Generate the HTML from the JSON in the viewer code for more flexibility.
mupdf.countPages = Module.cwrap('countPages', 'number', ['number']);
mupdf.pageWidth = Module.cwrap('pageWidth', 'number', ['number', 'number', 'number']);
mupdf.pageHeight = Module.cwrap('pageHeight', 'number', ['number', 'number', 'number']);
- mupdf.pageLinks = Module.cwrap('pageLinks', 'string', ['number', 'number', 'number']);
mupdf.drawPageAsPNG = Module.cwrap('drawPageAsPNG', 'string', ['number', 'number', 'number']);
+ mupdf.pageLinksJSON = Module.cwrap('pageLinks', 'string', ['number', 'number', 'number']);
mupdf.drawPageAsHTML = Module.cwrap('drawPageAsHTML', 'string', ['number', 'number']);
mupdf.drawPageAsSVG = Module.cwrap('drawPageAsSVG', 'string', ['number', 'number']);
mupdf.loadOutline = Module.cwrap('loadOutline', 'number', ['number']);
return list;
}
+mupdf.pageLinks = function (doc, page, dpi) {
+ return JSON.parse(mupdf.pageLinksJSON(doc, page, dpi));
+}
+
onmessage = function (event) {
let [ func, args, id ] = event.data;
if (!ready) {
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<style>
+
#outline, #outline ul { margin:0; padding-left:1.2em; }
#outline a { text-decoration:none; color: black; }
#outline a:hover { text-decoration:underline; }
-#pages img {
- display:block;
-}
-
-#pages div {
+div.page {
display:block;
background-color:white;
margin:16px auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
+ position:relative;
+}
+
+div.page img {
+ display:block;
+ position:absolute;
+ user-select:none;
+}
+
+div.links {
+ position:absolute;
+}
+
+div.links a {
+ display:block;
+ position:absolute;
+}
+
+div.links a:hover {
+ border: 1px dotted blue;
}
/* GRID */
let doc, pageCount;
let dirty = [];
let pageDIV = [];
-let pageIMG = [];
-let pageMAP = [];
let pageW = [];
let pageH = [];
let zoom = 96;
doc = 0;
pageCount = 0;
pageDIV = [];
- pageIMG = [];
- pageMAP = [];
dirty = [];
emptyNode(document.getElementById("pages"));
emptyNode(document.getElementById("outline"));
pagesDiv.scrollTo(0, 0);
for (let i = 1; i <= pageCount; ++i) {
let div = pageDIV[i] = document.createElement("div");
+ div.classList.add("page");
div.id = "page" + i;
div.style.width = defaultW + 'px';
div.style.height = defaultH + 'px';
pageDIV[i].style.width = defaultW + 'px';
pageDIV[i].style.height = defaultH + 'px';
emptyNode(pageDIV[i]);
- pageIMG[i] = null;
- pageMAP[i] = null;
}
if (current)
pageDIV[current].scrollIntoView();
if (dirty[i] && isVisible(pageDIV[i], 1000)) {
console.log("mupdf: drawing page", i);
let pageNumber = i;
- dirty[i] = false;
- let div = pageDIV[i];
+ dirty[pageNumber] = false;
+ let div = pageDIV[pageNumber];
emptyNode(div);
- let img = pageIMG[i] = new Image();
- img.useMap = "#map" + i;
+
+ let img = new Image();
img.draggable = false;
+ // user-select:none disables image.draggable, and we want
+ // to keep pointer-events for the link image-map
+ img.ondragstart = function () { return false; }
img.onload = function () {
pageDIV[pageNumber].style.width = 'min-content';
pageDIV[pageNumber].style.height = 'auto';
}
div.appendChild(img);
- let map = pageMAP[i] = document.createElement("map");
- map.name = "map" + i;
+
+ let map = document.createElement("div");
+ map.classList.add("links");
div.appendChild(map);
- mupdf.drawPageAsPNG(doc, i, zoom).then(data => pageIMG[pageNumber].src = data);
- mupdf.pageLinks(doc, i, zoom).then(data => pageMAP[pageNumber].innerHTML = data);
+ mupdf.drawPageAsPNG(doc, i, zoom).then(data => img.src = data);
+
+ mupdf.pageLinks(doc, pageNumber, zoom).then(data => {
+ for (let link of data) {
+ let a = document.createElement("a");
+ a.href = link.href;
+ a.style.left = link.x + 'px';
+ a.style.top = link.y + 'px';
+ a.style.width = link.w + 'px';
+ a.style.height = link.h + 'px';
+ map.appendChild(a);
+ }
+ });
}
};
}
buf = fz_new_buffer(ctx, 0);
{
+ fz_append_string(ctx, buf, "[");
links = fz_load_links(ctx, lastPage);
{
for (link = links; link; link = link->next)
{
fz_irect bbox = fz_round_rect(fz_transform_rect(link->rect, fz_scale(dpi/72, dpi/72)));
- fz_append_printf(ctx, buf, "<area shape=\"rect\" coords=\"%d,%d,%d,%d\"",
- bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+ fz_append_string(ctx, buf, "{");
+ fz_append_printf(ctx, buf, "%q:%d,", "x", bbox.x0);
+ fz_append_printf(ctx, buf, "%q:%d,", "y", bbox.y0);
+ fz_append_printf(ctx, buf, "%q:%d,", "w", bbox.x1 - bbox.x0);
+ fz_append_printf(ctx, buf, "%q:%d,", "h", bbox.y1 - bbox.y0);
if (fz_is_external_link(ctx, link->uri))
- fz_append_printf(ctx, buf, " href=\"%s\">\n", link->uri);
+ {
+ fz_append_printf(ctx, buf, "%q:%q", "href", link->uri);
+ }
else
{
- fz_location linkLoc = fz_resolve_link(ctx, doc, link->uri, NULL, NULL);
- int linkNumber = fz_page_number_from_location(ctx, doc, linkLoc);
- fz_append_printf(ctx, buf, " href=\"#page%d\">\n", linkNumber+1);
+ fz_location link_loc = fz_resolve_link(ctx, doc, link->uri, NULL, NULL);
+ int link_page = fz_page_number_from_location(ctx, doc, link_loc);
+ fz_append_printf(ctx, buf, "%q:\"#page%d\"", "href", link_page+1);
}
+ fz_append_string(ctx, buf, "}");
+ if (link->next)
+ fz_append_string(ctx, buf, ",");
}
}
- fz_append_byte(ctx, buf, 0);
+ fz_append_string(ctx, buf, "]");
fz_drop_link(ctx, links);
}
+
+ fz_terminate_buffer(ctx, buf);
fz_buffer_extract(ctx, buf, &data);
fz_drop_buffer(ctx, buf);