Add highlighting when syncing from code to pdf

This commit is contained in:
James Allen 2014-04-08 18:21:44 +01:00
parent 1444db4fd6
commit ef7a3788b4
6 changed files with 144 additions and 17 deletions

View file

@ -215,7 +215,7 @@ define [
Backbone.View::undelegateEvents.apply(this, arguments) Backbone.View::undelegateEvents.apply(this, arguments)
@pdfView.undelegateEvents() @pdfView.undelegateEvents()
setPdfPosition: (args...) -> highlightInPdf: (args...) ->
@pdfView.setPdfPosition?(args...) @pdfView.highlightInPdf?(args...)

View file

@ -2,16 +2,18 @@ define [
"libs/pdfListView/PdfListView" "libs/pdfListView/PdfListView"
"libs/pdfListView/TextLayerBuilder" "libs/pdfListView/TextLayerBuilder"
"libs/pdfListView/AnnotationsLayerBuilder" "libs/pdfListView/AnnotationsLayerBuilder"
"libs/pdfListView/HighlightsLayerBuilder"
"text!libs/pdfListView/TextLayer.css" "text!libs/pdfListView/TextLayer.css"
"text!libs/pdfListView/AnnotationsLayer.css" "text!libs/pdfListView/AnnotationsLayer.css"
"text!libs/pdfListView/HighlightsLayer.css"
"libs/backbone" "libs/backbone"
"libs/jquery.storage" "libs/jquery.storage"
], (PDFListView, TextLayerBuilder, AnnotationsLayerBuilder, textLayerCss, annotationsLayerCss) -> ], (PDFListView, TextLayerBuilder, AnnotationsLayerBuilder, HighlightsLayerBuilder, textLayerCss, annotationsLayerCss, highlightsLayerCss) ->
if PDFJS? if PDFJS?
PDFJS.workerSrc = "#{window.sharelatex.pdfJsWorkerPath}" PDFJS.workerSrc = "#{window.sharelatex.pdfJsWorkerPath}"
style = $("<style/>") style = $("<style/>")
style.text(textLayerCss + "\n" + annotationsLayerCss) style.text(textLayerCss + "\n" + annotationsLayerCss + "\n" + highlightsLayerCss)
$("body").append(style) $("body").append(style)
PDFjsView = Backbone.View.extend PDFjsView = Backbone.View.extend
@ -33,6 +35,7 @@ define [
@pdfListView = new PDFListView @$(".pdfjs-list-view")[0], @pdfListView = new PDFListView @$(".pdfjs-list-view")[0],
textLayerBuilder: TextLayerBuilder textLayerBuilder: TextLayerBuilder
annotationsLayerBuilder: AnnotationsLayerBuilder annotationsLayerBuilder: AnnotationsLayerBuilder
highlightsLayerBuilder: HighlightsLayerBuilder
ondblclick: (e) => ondblclick: (e) =>
@trigger "dblclick", e @trigger "dblclick", e
#logLevel: PDFListView.Logger.DEBUG #logLevel: PDFListView.Logger.DEBUG
@ -123,11 +126,35 @@ define [
onResize: () -> onResize: () ->
@pdfListView.onResize() @pdfListView.onResize()
setPdfPosition: (page, top, left) -> highlightInPdf: (areas) ->
@pdfListView.setPdfPosition({ highlights = for area in (areas or [])
page: page {
offset: page: area.page - 1
left: left highlight:
top: top left: area.h
}, true) top: area.v
height: area.height
width: area.width
}
if highlights.length > 0
first = highlights[0]
@pdfListView.setPdfPosition({
page: first.page
offset:
left: first.highlight.left
top: first.highlight.top - 100
}, true)
@pdfListView.clearHighlights()
@pdfListView.setHighlights(highlights, true)
setTimeout () =>
@$(".pdfjs-list-view .plv-highlights-layer > div").fadeOut "slow", () =>
@pdfListView.clearHighlights()
, 1000

View file

@ -243,9 +243,5 @@ define [
type: "GET" type: "GET"
success: (response) => success: (response) =>
data = JSON.parse(response) data = JSON.parse(response)
if data.pdf and data.pdf.length > 0 @view.highlightInPdf(data.pdf or [])
page = data.pdf[0].page - 1
h = data.pdf[0].h
v = data.pdf[0].v
@view.setPdfPosition page, v - 100, h
} }

View file

@ -0,0 +1,16 @@
.plv-highlights-layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
}
.plv-highlights-layer > div {
display: block;
position: absolute;
pointer-events: auto;
background-color: yellow;
opacity: 0.4;
}

View file

@ -0,0 +1,39 @@
(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else context[name] = definition()
})('HighlightsLayerBuilder', this, function (name, context) {
function HighlightsLayerBuilder(pageView, highlightsLayerDiv) {
this.highlightsLayerDiv = highlightsLayerDiv;
this.pageView = pageView;
this.highlightElements = [];
};
HighlightsLayerBuilder.EXTERNAL_LINK_TARGET = "_blank";
HighlightsLayerBuilder.prototype = {
addHighlight: function(left, top, width, height) {
rect = this.pageView.viewport.convertToViewportRectangle([left, top, left + width, top + height]);
rect = PDFJS.Util.normalizeRect(rect);
var element = document.createElement("div");
element.style.left = Math.floor(rect[0]) + 'px';
element.style.top = Math.floor(rect[1]) + 'px';
element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
this.highlightElements.push(element);
this.highlightsLayerDiv.appendChild(element);
return element;
},
clearHighlights: function() {
for (var i = 0; i < this.highlightElements.length; i++) {
this.highlightElements[i].remove();
}
this.highlightElements = [];
}
}
return HighlightsLayerBuilder;
});

View file

@ -399,6 +399,20 @@ ListView.prototype = {
var position = pageView.getPdfPositionInViewer(offset.left, offset.top); var position = pageView.getPdfPositionInViewer(offset.left, offset.top);
this.dom.scrollTop = position.top; this.dom.scrollTop = position.top;
} }
},
setHighlights: function(highlights, fromTop) {
for (i = 0; i < highlights.length; i++) {
var pageIndex = highlights[i].page;
var pageView = this.pageViews[pageIndex];
pageView.addHighlight(highlights[i].highlight, fromTop);
}
},
clearHighlights: function() {
for (var i = 0; i < this.pageViews.length; i++) {
var pageView = this.pageViews[i].clearHighlights();
}
} }
}; };
@ -663,6 +677,25 @@ PageView.prototype = {
} }
var pdfOffset = this.viewport.convertToPdfPoint(0, canvasOffset); var pdfOffset = this.viewport.convertToPdfPoint(0, canvasOffset);
return pdfOffset[1]; return pdfOffset[1];
},
clearHighlights: function() {
if (this.highlightsLayer) {
this.highlightsLayer.clearHighlights();
}
},
addHighlight: function(highlight, fromTop) {
if (this.highlightsLayer) {
var top = highlight.top;
var left = highlight.left;
var width = highlight.width;
var height = highlight.height;
if (fromTop) {
top = this.normalHeight - top;
}
this.highlightsLayer.addHighlight(left, top, width, height);
}
} }
}; };
@ -751,6 +784,14 @@ Page.prototype = {
); );
} }
var highlightsLayerBuilder = pageView.listView.options.highlightsLayerBuilder;
if (highlightsLayerBuilder) {
var highlightsLayerDiv = pageView.highlightsLayerDiv = document.createElement("div");
highlightsLayerDiv.className = 'plv-highlights-layer highlights-layer';
pageView.dom.appendChild(highlightsLayerDiv);
pageView.highlightsLayer = new highlightsLayerBuilder(pageView, highlightsLayerDiv);
}
renderContext = { renderContext = {
canvasContext: pageView.getCanvasContext(), canvasContext: pageView.getCanvasContext(),
viewport: viewport, viewport: viewport,
@ -886,7 +927,15 @@ PDFListView.prototype = {
}, },
setPdfPosition: function(pdfPosition, fromTop) { setPdfPosition: function(pdfPosition, fromTop) {
this.listView.setPdfPosition(pdfPosition, fromTop) this.listView.setPdfPosition(pdfPosition, fromTop);
},
setHighlights: function(highlights, fromTop) {
this.listView.setHighlights(highlights, fromTop);
},
clearHighlights: function() {
this.listView.clearHighlights();
} }
}; };
PDFListView.Logger = Logger; PDFListView.Logger = Logger;