178 lines
5.4 KiB
JavaScript
178 lines
5.4 KiB
JavaScript
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
var CodeView = function(divID, PR, sourceText, sourcePosition, broker) {
|
||
|
"use strict";
|
||
|
var view = this;
|
||
|
|
||
|
view.divElement = document.getElementById(divID);
|
||
|
view.broker = broker;
|
||
|
view.codeSelection = null;
|
||
|
view.allSpans = [];
|
||
|
|
||
|
var selectionHandler = {
|
||
|
clear: function() {
|
||
|
broker.clear(selectionHandler);
|
||
|
},
|
||
|
select: function(items, selected) {
|
||
|
var handler = this;
|
||
|
var divElement = view.divElement;
|
||
|
var broker = view.broker;
|
||
|
for (let span of items) {
|
||
|
if (selected) {
|
||
|
span.classList.add("selected");
|
||
|
} else {
|
||
|
span.classList.remove("selected");
|
||
|
}
|
||
|
}
|
||
|
var ranges = [];
|
||
|
for (var span of items) {
|
||
|
ranges.push([span.start, span.end, null]);
|
||
|
}
|
||
|
broker.select(selectionHandler, ranges, selected);
|
||
|
},
|
||
|
selectionDifference: function(span1, inclusive1, span2, inclusive2) {
|
||
|
var pos1 = span1.start;
|
||
|
var pos2 = span2.start;
|
||
|
var result = [];
|
||
|
var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
|
||
|
for (var i=0; i < lineListDiv.length; i++) {
|
||
|
var currentLineElement = lineListDiv[i];
|
||
|
var spans = currentLineElement.childNodes;
|
||
|
for (var j=0; j < spans.length; ++j) {
|
||
|
var currentSpan = spans[j];
|
||
|
if (currentSpan.start > pos1 || (inclusive1 && currentSpan.start == pos1)) {
|
||
|
if (currentSpan.start < pos2 || (inclusive2 && currentSpan.start == pos2)) {
|
||
|
result.push(currentSpan);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
},
|
||
|
brokeredSelect: function(ranges, selected) {
|
||
|
var firstSelect = view.codeSelection.isEmpty();
|
||
|
for (var range of ranges) {
|
||
|
var start = range[0];
|
||
|
var end = range[1];
|
||
|
var lower = 0;
|
||
|
var upper = view.allSpans.length;
|
||
|
if (upper > 0) {
|
||
|
while ((upper - lower) > 1) {
|
||
|
var middle = Math.floor((upper + lower) / 2);
|
||
|
var lineStart = view.allSpans[middle].start;
|
||
|
if (lineStart < start) {
|
||
|
lower = middle;
|
||
|
} else if (lineStart > start) {
|
||
|
upper = middle;
|
||
|
} else {
|
||
|
lower = middle;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
var currentSpan = view.allSpans[lower];
|
||
|
var currentLineElement = currentSpan.parentNode;
|
||
|
if ((currentSpan.start <= start && start < currentSpan.end) ||
|
||
|
(currentSpan.start <= end && end < currentSpan.end)) {
|
||
|
if (firstSelect) {
|
||
|
makeContainerPosVisible(view.divElement, currentLineElement.offsetTop);
|
||
|
firstSelect = false;
|
||
|
}
|
||
|
view.codeSelection.select(currentSpan, selected);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
brokeredClear: function() {
|
||
|
view.codeSelection.clear();
|
||
|
},
|
||
|
};
|
||
|
|
||
|
view.codeSelection = new Selection(selectionHandler);
|
||
|
broker.addSelectionHandler(selectionHandler);
|
||
|
|
||
|
var mouseDown = false;
|
||
|
|
||
|
this.handleSpanMouseDown = function(e) {
|
||
|
e.stopPropagation();
|
||
|
if (!e.shiftKey) {
|
||
|
view.codeSelection.clear();
|
||
|
}
|
||
|
view.codeSelection.select(this, true);
|
||
|
mouseDown = true;
|
||
|
}
|
||
|
|
||
|
this.handleSpanMouseMove = function(e) {
|
||
|
if (mouseDown) {
|
||
|
view.codeSelection.extendTo(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.handleCodeMouseDown = function(e) {
|
||
|
view.codeSelection.clear();
|
||
|
}
|
||
|
|
||
|
document.addEventListener('mouseup', function(e){
|
||
|
mouseDown = false;
|
||
|
}, false);
|
||
|
|
||
|
this.initializeCode(sourceText, sourcePosition);
|
||
|
}
|
||
|
|
||
|
CodeView.prototype.initializeCode = function(sourceText, sourcePosition) {
|
||
|
var view = this;
|
||
|
if (sourceText == "") {
|
||
|
var newHtml = "<pre class=\"prettyprint\"</pre>";
|
||
|
view.divElement.innerHTML = newHtml;
|
||
|
} else {
|
||
|
var newHtml = "<pre class=\"prettyprint linenums\">"
|
||
|
+ sourceText + "</pre>";
|
||
|
view.divElement.innerHTML = newHtml;
|
||
|
try {
|
||
|
// Wrap in try to work when offline.
|
||
|
PR.prettyPrint();
|
||
|
} catch (e) {
|
||
|
}
|
||
|
|
||
|
view.divElement.onmousedown = this.handleCodeMouseDown;
|
||
|
|
||
|
var base = sourcePosition;
|
||
|
var current = 0;
|
||
|
var lineListDiv = view.divElement.firstChild.firstChild.childNodes;
|
||
|
for (i=0; i < lineListDiv.length; i++) {
|
||
|
var currentLineElement = lineListDiv[i];
|
||
|
currentLineElement.id = "li" + i;
|
||
|
var pos = base + current;
|
||
|
currentLineElement.pos = pos;
|
||
|
var spans = currentLineElement.childNodes;
|
||
|
for (j=0; j < spans.length; ++j) {
|
||
|
var currentSpan = spans[j];
|
||
|
if (currentSpan.nodeType == 1) {
|
||
|
currentSpan.start = pos;
|
||
|
currentSpan.end = pos + currentSpan.textContent.length;
|
||
|
currentSpan.onmousedown = this.handleSpanMouseDown;
|
||
|
currentSpan.onmousemove = this.handleSpanMouseMove;
|
||
|
view.allSpans.push(currentSpan);
|
||
|
}
|
||
|
current += currentSpan.textContent.length;
|
||
|
pos = base + current;
|
||
|
}
|
||
|
while ((current < sourceText.length) && (
|
||
|
sourceText[current] == '\n' ||
|
||
|
sourceText[current] == '\r')) {
|
||
|
++current;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.resizeToParent();
|
||
|
}
|
||
|
|
||
|
CodeView.prototype.resizeToParent = function() {
|
||
|
var view = this;
|
||
|
var documentElement = document.documentElement;
|
||
|
var y = view.divElement.parentNode.clientHeight || documentElement.clientHeight;
|
||
|
view.divElement.style.height = y + "px";
|
||
|
}
|