mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge branch 'master' of github.com:sharelatex/web-sharelatex
This commit is contained in:
commit
811859a4a1
10 changed files with 246 additions and 6 deletions
|
@ -35,6 +35,9 @@ module.exports = CompileController =
|
|||
getFileFromClsi: (req, res, next = (error) ->) ->
|
||||
CompileController.proxyToClsi("/project/#{req.params.Project_id}/output/#{req.params.file}", req, res, next)
|
||||
|
||||
proxySync: (req, res, next = (error) ->) ->
|
||||
CompileController.proxyToClsi(req.url, req, res, next)
|
||||
|
||||
proxyToClsi: (url, req, res, next = (error) ->) ->
|
||||
logger.log url: url, "proxying to CLSI"
|
||||
url = "#{Settings.apis.clsi.url}#{url}"
|
||||
|
|
|
@ -109,6 +109,9 @@ module.exports = class Router
|
|||
next()
|
||||
), SecurityManager.requestCanAccessProject, CompileController.getFileFromClsi
|
||||
app.del "/project/:Project_id/output", SecurityManager.requestCanAccessProject, CompileController.deleteAuxFiles
|
||||
app.get "/project/:Project_id/sync/code", SecurityManager.requestCanAccessProject, CompileController.proxySync
|
||||
app.get "/project/:Project_id/sync/pdf", SecurityManager.requestCanAccessProject, CompileController.proxySync
|
||||
|
||||
|
||||
app.del '/Project/:Project_id', SecurityManager.requestIsOwner, ProjectController.deleteProject
|
||||
app.post '/Project/:Project_id/clone', SecurityManager.requestCanAccessProject, ProjectController.cloneProject
|
||||
|
|
|
@ -304,6 +304,12 @@ define [
|
|||
gotoLine: (line) ->
|
||||
@aceEditor.gotoLine(line)
|
||||
|
||||
getCurrentLine: () ->
|
||||
@aceEditor.selection?.getCursor()?.row
|
||||
|
||||
getCurrentColumn: () ->
|
||||
@aceEditor.selection?.getCursor()?.column
|
||||
|
||||
getLines: (from, to) ->
|
||||
if from? and to?
|
||||
@getSession().doc.getLines(from, to)
|
||||
|
|
|
@ -64,6 +64,7 @@ define [
|
|||
PdfView = PdfjsView
|
||||
@pdfjs = true
|
||||
@pdfView = new PdfView(manager: @)
|
||||
@pdfView.on "dblclick", (e) => @trigger "dblclick", e
|
||||
|
||||
render: () ->
|
||||
@setElement(@templates.pdfPanel)
|
||||
|
@ -214,4 +215,7 @@ define [
|
|||
Backbone.View::undelegateEvents.apply(this, arguments)
|
||||
@pdfView.undelegateEvents()
|
||||
|
||||
highlightInPdf: (args...) ->
|
||||
@pdfView.highlightInPdf?(args...)
|
||||
|
||||
|
||||
|
|
|
@ -2,16 +2,18 @@ define [
|
|||
"libs/pdfListView/PdfListView"
|
||||
"libs/pdfListView/TextLayerBuilder"
|
||||
"libs/pdfListView/AnnotationsLayerBuilder"
|
||||
"libs/pdfListView/HighlightsLayerBuilder"
|
||||
"text!libs/pdfListView/TextLayer.css"
|
||||
"text!libs/pdfListView/AnnotationsLayer.css"
|
||||
"text!libs/pdfListView/HighlightsLayer.css"
|
||||
"libs/backbone"
|
||||
"libs/jquery.storage"
|
||||
], (PDFListView, TextLayerBuilder, AnnotationsLayerBuilder, textLayerCss, annotationsLayerCss) ->
|
||||
], (PDFListView, TextLayerBuilder, AnnotationsLayerBuilder, HighlightsLayerBuilder, textLayerCss, annotationsLayerCss, highlightsLayerCss) ->
|
||||
if PDFJS?
|
||||
PDFJS.workerSrc = "#{window.sharelatex.pdfJsWorkerPath}"
|
||||
|
||||
style = $("<style/>")
|
||||
style.text(textLayerCss + "\n" + annotationsLayerCss)
|
||||
style.text(textLayerCss + "\n" + annotationsLayerCss + "\n" + highlightsLayerCss)
|
||||
$("body").append(style)
|
||||
|
||||
PDFjsView = Backbone.View.extend
|
||||
|
@ -33,6 +35,9 @@ define [
|
|||
@pdfListView = new PDFListView @$(".pdfjs-list-view")[0],
|
||||
textLayerBuilder: TextLayerBuilder
|
||||
annotationsLayerBuilder: AnnotationsLayerBuilder
|
||||
highlightsLayerBuilder: HighlightsLayerBuilder
|
||||
ondblclick: (e) =>
|
||||
@trigger "dblclick", e
|
||||
#logLevel: PDFListView.Logger.DEBUG
|
||||
@pdfListView.listView.pageWidthOffset = 20
|
||||
@pdfListView.listView.pageHeightOffset = 20
|
||||
|
@ -121,3 +126,35 @@ define [
|
|||
onResize: () ->
|
||||
@pdfListView.onResize()
|
||||
|
||||
highlightInPdf: (areas) ->
|
||||
highlights = for area in (areas or [])
|
||||
{
|
||||
page: area.page - 1
|
||||
highlight:
|
||||
left: area.h
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ define [
|
|||
|
||||
createPdfPanel: () ->
|
||||
@view = new CompiledView manager: @, ide: @ide
|
||||
@view.on "dblclick", (e) => @syncToCode(e)
|
||||
@view.render()
|
||||
if $.localStorage("layout.pdf") == "flat"
|
||||
@switchToFlatView()
|
||||
|
@ -210,3 +211,37 @@ define [
|
|||
})
|
||||
|
||||
}]
|
||||
|
||||
syncToCode: (e) ->
|
||||
$.ajax {
|
||||
url: "/project/#{@ide.project_id}/sync/pdf"
|
||||
data:
|
||||
page: e.page + 1
|
||||
h: e.x.toFixed(2)
|
||||
v: e.y.toFixed(2)
|
||||
type: "GET"
|
||||
success: (response) =>
|
||||
data = JSON.parse(response)
|
||||
if data.code and data.code.length > 0
|
||||
file = data.code[0].file
|
||||
line = data.code[0].line
|
||||
@ide.fileTreeManager.openDocByPath(file, line)
|
||||
}
|
||||
|
||||
syncToPdf: () ->
|
||||
entity_id = @ide.editor.getCurrentDocId()
|
||||
file = @ide.fileTreeManager.getPathOfEntityId(entity_id)
|
||||
line = @ide.editor.getCurrentLine()
|
||||
column = @ide.editor.getCurrentColumn()
|
||||
|
||||
$.ajax {
|
||||
url: "/project/#{@ide.project_id}/sync/code"
|
||||
data:
|
||||
file: file
|
||||
line: line + 1
|
||||
column: column
|
||||
type: "GET"
|
||||
success: (response) =>
|
||||
data = JSON.parse(response)
|
||||
@view.highlightInPdf(data.pdf or [])
|
||||
}
|
||||
|
|
16
services/web/public/js/libs/pdfListView/HighlightsLayer.css
Normal file
16
services/web/public/js/libs/pdfListView/HighlightsLayer.css
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
});
|
|
@ -215,6 +215,16 @@ ListView.prototype = {
|
|||
// per pageContainer.
|
||||
this.pdfDoc.pages.map(function(page) {
|
||||
var pageView = new PageView(page, this);
|
||||
|
||||
// TODO: Switch over to a proper event handler
|
||||
var that = this;
|
||||
var index = that.pageViews.length;
|
||||
pageView.ondblclick = function(e) {
|
||||
e.page = index;
|
||||
if (that.ondblclick) {
|
||||
that.ondblclick.call(that, e);
|
||||
}
|
||||
}
|
||||
this.pageViews.push(pageView);
|
||||
|
||||
var container = new PageContainerView(this);
|
||||
|
@ -378,14 +388,31 @@ ListView.prototype = {
|
|||
return pdfPosition;
|
||||
},
|
||||
|
||||
setPdfPosition: function(pdfPosition) {
|
||||
setPdfPosition: function(pdfPosition, fromTop) {
|
||||
if (typeof pdfPosition !== "undefined" && pdfPosition != null) {
|
||||
var offset = pdfPosition.offset;
|
||||
var page_index = pdfPosition.page;
|
||||
var pageView = this.pageViews[page_index];
|
||||
if (fromTop) {
|
||||
offset.top = pageView.normalHeight - offset.top;
|
||||
}
|
||||
var position = pageView.getPdfPositionInViewer(offset.left, offset.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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -462,6 +489,27 @@ function PageView(page, listView) {
|
|||
|
||||
var dom = this.dom = document.createElement('div');
|
||||
dom.className = "plv-page-view page-view";
|
||||
var that = this;
|
||||
dom.ondblclick = function(e) {
|
||||
var layerX = e.layerX;
|
||||
var layerY = e.layerY;
|
||||
var element = e.target;
|
||||
while (element.offsetParent && element.offsetParent !== dom) {
|
||||
layerX = layerX + element.offsetLeft;
|
||||
layerY = layerY + element.offsetTop;
|
||||
element = element.offsetParent;
|
||||
}
|
||||
|
||||
var pdfPoint = that.viewport.convertToPdfPoint(layerX, layerY);
|
||||
var event = {
|
||||
x: pdfPoint[0],
|
||||
y: that.normalHeight - pdfPoint[1]
|
||||
};
|
||||
|
||||
if (that.ondblclick) {
|
||||
that.ondblclick.call(that.listView, event)
|
||||
}
|
||||
}
|
||||
this.createNewCanvas();
|
||||
}
|
||||
|
||||
|
@ -560,6 +608,7 @@ PageView.prototype = {
|
|||
scaled: pixelRatio != 1
|
||||
};
|
||||
},
|
||||
|
||||
createNewCanvas: function() {
|
||||
if (this.canvas) {
|
||||
this.dom.removeChild(this.canvas);
|
||||
|
@ -628,6 +677,25 @@ PageView.prototype = {
|
|||
}
|
||||
var pdfOffset = this.viewport.convertToPdfPoint(0, canvasOffset);
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -716,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 = {
|
||||
canvasContext: pageView.getCanvasContext(),
|
||||
viewport: viewport,
|
||||
|
@ -766,13 +842,19 @@ function PDFListView(mainDiv, options) {
|
|||
}
|
||||
logger.logLevel = options.logLevel;
|
||||
|
||||
var self = this;
|
||||
|
||||
this.listView = new ListView(mainDiv, options);
|
||||
this.listView.ondblclick = function(e) {
|
||||
if (options.ondblclick) {
|
||||
options.ondblclick.call(self, e);
|
||||
}
|
||||
}
|
||||
|
||||
this.renderController = new RenderController();
|
||||
this.renderController.addListView(this.listView);
|
||||
this.renderController.updateRenderList();
|
||||
|
||||
var self = this;
|
||||
|
||||
mainDiv.addEventListener('scroll', function() {
|
||||
// This will update the list AND start rendering if needed.
|
||||
|
@ -844,8 +926,16 @@ PDFListView.prototype = {
|
|||
return this.listView.getPdfPosition();
|
||||
},
|
||||
|
||||
setPdfPosition: function(pdfPosition) {
|
||||
this.listView.setPdfPosition(pdfPosition)
|
||||
setPdfPosition: function(pdfPosition, fromTop) {
|
||||
this.listView.setPdfPosition(pdfPosition, fromTop);
|
||||
},
|
||||
|
||||
setHighlights: function(highlights, fromTop) {
|
||||
this.listView.setHighlights(highlights, fromTop);
|
||||
},
|
||||
|
||||
clearHighlights: function() {
|
||||
this.listView.clearHighlights();
|
||||
}
|
||||
};
|
||||
PDFListView.Logger = Logger;
|
||||
|
|
|
@ -84,6 +84,13 @@ TextLayerBuilder.prototype = {
|
|||
textDiv.style.left = geom.x + 'px';
|
||||
textDiv.style.top = (geom.y - fontHeight) + 'px';
|
||||
|
||||
textDiv.ondblclick = function(e) {
|
||||
if (window.getSelection)
|
||||
window.getSelection().removeAllRanges();
|
||||
else if (document.selection)
|
||||
document.selection.empty();
|
||||
}
|
||||
|
||||
// The content of the div is set in the `setTextContent` function.
|
||||
|
||||
this.textDivs.push(textDiv);
|
||||
|
|
Loading…
Reference in a new issue