pdfview: add basic pdfview

authorSamuel Trégouët <samuel.tregouet@logilab.fr>
changeset7c65356a52ff
branchdefault
phasedraft
hiddenyes
parent revision#aaa19ec3d16d xmosaicframe: add url and xhr on context for view
child revision#52fcdcae875a pdfview: state of a pdf-viewer should be on instance and not on prototype
files modified by this revision
components/pdfview/pdf-viewer/js/pdf/pdf.js
components/pdfview/pdf-viewer/js/pdf/pdf.worker.js
components/pdfview/pdf-viewer/pdf-viewer.html
components/pdfview/pdf-viewer/pdf-viewer.js
components/pdfview/pdfview.html
components/pdfview/pdfview.js
package.json
portfolios/_template.html
# HG changeset patch
# User Samuel Trégouët <samuel.tregouet@logilab.fr>
# Date 1427977554 -7200
# Thu Apr 02 14:25:54 2015 +0200
# Node ID 7c65356a52ff15b4716695514dc8005530d2585b
# Parent aaa19ec3d16da2b29fc522762335e1c75c6c1153
pdfview: add basic pdfview

diff --git a/components/pdfview/pdf-viewer/js/pdf/pdf.js b/components/pdfview/pdf-viewer/js/pdf/pdf.js
@@ -0,0 +1,1 @@
1 +../../../../../node_modules/pdfjs-dist/build/pdf.js
2 \ No newline at end of file
diff --git a/components/pdfview/pdf-viewer/js/pdf/pdf.worker.js b/components/pdfview/pdf-viewer/js/pdf/pdf.worker.js
@@ -0,0 +1,1 @@
3 +../../../../../node_modules/pdfjs-dist/build/pdf.worker.js
4 \ No newline at end of file
diff --git a/components/pdfview/pdf-viewer/pdf-viewer.html b/components/pdfview/pdf-viewer/pdf-viewer.html
@@ -0,0 +1,22 @@
5 +<!-- come from https://github.com/rahmathm1/pdf-viewer
6 +     with small changes:
7 +
8 +     - remove polymer-component tag since it is not necessary
9 +     - do not disable worker with disableWorker flag
10 +     - change PDFJS.workerSrc
11 +     - move js in its own file
12 +     - call renderBook in setPath method
13 +       (to have a chance to fill path attribute)
14 +     - run jshint on it:
15 +       - add missing `;`
16 +       - add `use strict`
17 +       - add comment to declare global
18 +  -->
19 +<template>
20 +  <canvas id="pdf-canvas"></canvas>
21 +</template>
22 +<script src="js/pdf/pdf.js"></script>
23 +<script src="js/pdf/pdf.worker.js"></script>
24 +<script src="pdf-viewer.js"></script>
25 +
26 +
diff --git a/components/pdfview/pdf-viewer/pdf-viewer.js b/components/pdfview/pdf-viewer/pdf-viewer.js
@@ -0,0 +1,121 @@
27 +/* global PDFJS */
28 +
29 +(function(window, document, undefined) {
30 +    'use strict';
31 +    // Refers to the "importer", which is index.html
32 +    var thatDoc = document;
33 +
34 +
35 +    // Refers to the "importee", which is src/hello-world.html
36 +    var thisDoc = (thatDoc._currentScript || thatDoc.currentScript).ownerDocument;
37 +
38 +    // Gets content from <template>
39 +    var template = thisDoc.querySelector('template').content;
40 +
41 +    // Creates an object based in the HTML Element prototype
42 +    var pdfProto = Object.create(HTMLElement.prototype);
43 +
44 +    // Fires when an instance of the element is created
45 +    pdfProto.createdCallback = function() {
46 +
47 +        // Creates the shadow root
48 +        var shadowRoot = this.createShadowRoot();
49 +
50 +        // Adds a template clone into shadow root
51 +        var clone = thatDoc.importNode(template, true);
52 +        shadowRoot.appendChild(clone);
53 +
54 +        // Caches <canvas> DOM query
55 +        pdfProto.canvas = shadowRoot.getElementById('pdf-canvas');
56 +
57 +        if (this.hasAttribute('path')) {
58 +            var path = this.getAttribute('path');
59 +            this.setPath(path);
60 +        }
61 +    };
62 +
63 +    pdfProto.renderBook = function() {
64 +        pdfProto.pageNumPending = null;
65 +        pdfProto.pageRendering = false;
66 +        pdfProto.pageNumPending = null;
67 +        pdfProto.ctx = pdfProto.canvas.getContext('2d');
68 +        pdfProto.scale = 2;
69 +        pdfProto.pageNum = 1;
70 +        pdfProto.isReady = false;
71 +
72 +        //PDFJS.disableWorker = true;
73 +        PDFJS.workerSrc = '/components/pdfview/pdf-viewer/js/pdf/pdf.worker.js';
74 +        PDFJS.getDocument(this.path).then(function(pdfDoc) {
75 +            pdfProto.pdf = pdfDoc;
76 +            pdfProto.renderPage(pdfProto.pageNum);
77 +        });
78 +    };
79 +
80 +    pdfProto.renderPage = function(num) {
81 +        pdfProto.pageRendering = true;
82 +        pdfProto.pdf.getPage(num).then(function(page) {
83 +            var viewport = page.getViewport(pdfProto.scale);
84 +            pdfProto.canvas.height = viewport.height;
85 +            pdfProto.canvas.width = viewport.width;
86 +
87 +            var renderContext = {
88 +                canvasContext: pdfProto.ctx,
89 +                viewport: viewport
90 +            };
91 +            var renderTask = page.render(renderContext);
92 +            pdfProto.isReady = true;
93 +
94 +            renderTask.promise.then(function() {
95 +                pdfProto.pageRendering = false;
96 +                if (pdfProto.pageNumPending !== null) {
97 +                    pdfProto.renderPage(pdfProto.pageNumPending);
98 +                    pdfProto.pageNumPending = null;
99 +                }
100 +            });
101 +        });
102 +    };
103 +
104 +    pdfProto.nextPage = function() {
105 +        if (pdfProto.pageNum >= pdfProto.pdf.numPages) {
106 +            return false;
107 +        }
108 +        pdfProto.pageNum++;
109 +        pdfProto.queueRenderPage(pdfProto.pageNum);
110 +        return true;
111 +    };
112 +
113 +    pdfProto.prevPage = function() {
114 +        if (pdfProto.pageNum <= 1) {
115 +            return false;
116 +        }
117 +        pdfProto.pageNum--;
118 +        pdfProto.queueRenderPage(pdfProto.pageNum);
119 +        return true;
120 +    };
121 +
122 +    pdfProto.queueRenderPage = function(num) {
123 +        if (pdfProto.pageRendering) {
124 +            pdfProto.pageNumPending = num;
125 +        } else {
126 +            pdfProto.renderPage(num);
127 +        }
128 +    };
129 +
130 +    // Fires when an attribute was added, removed, or updated
131 +    pdfProto.attributeChangedCallback = function(attr, oldVal, newVal) {
132 +        if (attr === 'path') {
133 +            this.setPath(newVal);
134 +        }
135 +    };
136 +
137 +    // Sets new value to "who" attribute
138 +    pdfProto.setPath = function(val) {
139 +        this.path = val;
140 +        this.renderBook();
141 +    };
142 +
143 +    // Registers <hello-world> in the main document
144 +    window.PdfViewer = thatDoc.registerElement('pdf-viewer', {
145 +        prototype: pdfProto
146 +    });
147 +})(window, document);
diff --git a/components/pdfview/pdfview.html b/components/pdfview/pdfview.html
@@ -0,0 +1,22 @@
148 +<link href="pdf-viewer/pdf-viewer.html" rel="import"/>
149 +
150 +<template>
151 +  <style>
152 +    @import url("/vendor.css"); /* XXX fix need for absolute path */
153 +  </style>
154 +  <nav class="navbar navbar-default">
155 +    <button id="prev-page" type="button" class="btn btn-default navbar-btn">
156 +      prev
157 +    </button>
158 +    <button id="next-page" type="button" class="btn btn-default navbar-btn">
159 +      next
160 +    </button>
161 +  </nav>
162 +  <pdf-viewer></pdf-viewer>
163 +  
164 +</template>
165 +
166 +
167 +<script src="pdfview.js"></script>
168 +
169 +
diff --git a/components/pdfview/pdfview.js b/components/pdfview/pdfview.js
@@ -0,0 +1,60 @@
170 +(function registerView(ownerDocument) {
171 +    'use strict';
172 +
173 +    // register html component
174 +    var proto = Object.create(HTMLDivElement.prototype);
175 +
176 +    proto.createdCallback = function() {
177 +        var template = ownerDocument.querySelector('template');
178 +        var clone = document.importNode(template.content, true);
179 +        var root = this.createShadowRoot();
180 +        root.appendChild(clone);
181 +        this.viewer = root.querySelector('pdf-viewer');
182 +        root.appendChild(this.viewer);
183 +
184 +        root.addEventListener('click', function(ev) {
185 +            if (!ev.target) {
186 +                return;
187 +            }
188 +            switch (ev.target.id) {
189 +                case 'next-page':
190 +                  this.viewer.nextPage();
191 +                  break;
192 +                case 'prev-page':
193 +                  this.viewer.prevPage();
194 +                  break;
195 +                default:
196 +                  break;
197 +            }
198 +        }.bind(this));
199 +
200 +    };
201 +    proto.setPath = function(newPath) {
202 +        this.viewer.setAttribute('path', newPath);
203 +    };
204 +    proto.attributeChangedCallback = function(attr, oldVal, newVal) {
205 +        if (attr === 'path') {
206 +            this.setPath(newVal);
207 +        }
208 +    };
209 +    document.registerElement('x-mosaic-pdfview', {
210 +        prototype: proto
211 +    });
212 +
213 +
214 +    // register view
215 +    function pdfView(ctx) {
216 +
217 +        var contentType = ctx.xhr.getResponseHeader('content-type');
218 +        if (contentType === 'application/pdf') {
219 +            var viewer = document.createElement('x-mosaic-pdfview');
220 +            viewer.setAttribute('path', ctx.reqUrl);
221 +            return viewer;
222 +        }
223 +
224 +    }
225 +
226 +    var registry = require('registry');
227 +    registry.registerView('http', 'pdf', pdfView);
228 +})(document._currentScript.ownerDocument);
229 +
diff --git a/package.json b/package.json
@@ -1,11 +1,13 @@
230  {
231    "name": "mosaic",
232    "version": "0.1.0",
233    "description": "mosaic knowledge browser",
234    "main": "index.js",
235 -  "dependencies": {},
236 +  "dependencies": {
237 +    "pdfjs-dist": "^1.1.28"
238 +  },
239    "devDependencies": {
240      "babel": "^4.7.16",
241      "babel-brunch": "^4.0.0",
242      "bootstrap": "^3.3.4",
243      "brunch": "^1.7.20",
diff --git a/portfolios/_template.html b/portfolios/_template.html
@@ -16,10 +16,11 @@
244      <link rel="import" href="/components/neotableview/neotableview.html" />
245      <link rel="import" href="/components/neolistview/neolistview.html" />
246      <link rel="import" href="/components/sparqltableview/sparqltableview.html" />
247      <link rel="import" href="/components/cwtableview/cwtableview.html" />
248      <link rel="import" href="/components/markdown-editable/markdown-editable.html" />
249 +    <link rel="import" href="/components/pdfview/pdfview.html" />
250    </head>
251    <body>
252      <div class="container">
253        <button id="save-portfolio" class="btn">save portfolio</button>
254        <x-markdown-editable>###Edit me</x-markdown-editable>