OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 var CodeView = function(divID, PR, sourceText, sourcePosition, broker) { |
| 6 "use strict"; |
| 7 var view = this; |
| 8 |
| 9 view.divElement = document.getElementById(divID); |
| 10 view.broker = broker; |
| 11 view.codeSelection = null; |
| 12 view.allSpans = []; |
| 13 |
| 14 var selectionHandler = { |
| 15 clear: function() { |
| 16 broker.clear(selectionHandler); |
| 17 }, |
| 18 select: function(items, selected) { |
| 19 var handler = this; |
| 20 var divElement = view.divElement; |
| 21 var broker = view.broker; |
| 22 for (let span of items) { |
| 23 if (selected) { |
| 24 span.classList.add("selected"); |
| 25 } else { |
| 26 span.classList.remove("selected"); |
| 27 } |
| 28 } |
| 29 var ranges = []; |
| 30 for (var span of items) { |
| 31 ranges.push([span.start, span.end, null]); |
| 32 } |
| 33 broker.select(selectionHandler, ranges, selected); |
| 34 }, |
| 35 selectionDifference: function(span1, inclusive1, span2, inclusive2) { |
| 36 var pos1 = span1.start; |
| 37 var pos2 = span2.start; |
| 38 var result = []; |
| 39 var lineListDiv = view.divElement.firstChild.firstChild.childNodes; |
| 40 for (var i=0; i < lineListDiv.length; i++) { |
| 41 var currentLineElement = lineListDiv[i]; |
| 42 var spans = currentLineElement.childNodes; |
| 43 for (var j=0; j < spans.length; ++j) { |
| 44 var currentSpan = spans[j]; |
| 45 if (currentSpan.start > pos1 || (inclusive1 && currentSpan.start == po
s1)) { |
| 46 if (currentSpan.start < pos2 || (inclusive2 && currentSpan.start ==
pos2)) { |
| 47 result.push(currentSpan); |
| 48 } |
| 49 } |
| 50 } |
| 51 } |
| 52 return result; |
| 53 }, |
| 54 brokeredSelect: function(ranges, selected) { |
| 55 var firstSelect = view.codeSelection.isEmpty(); |
| 56 for (var range of ranges) { |
| 57 var start = range[0]; |
| 58 var end = range[1]; |
| 59 var lower = 0; |
| 60 var upper = view.allSpans.length; |
| 61 if (upper > 0) { |
| 62 while ((upper - lower) > 1) { |
| 63 var middle = Math.floor((upper + lower) / 2); |
| 64 var lineStart = view.allSpans[middle].start; |
| 65 if (lineStart < start) { |
| 66 lower = middle; |
| 67 } else if (lineStart > start) { |
| 68 upper = middle; |
| 69 } else { |
| 70 lower = middle; |
| 71 break; |
| 72 } |
| 73 } |
| 74 var currentSpan = view.allSpans[lower]; |
| 75 var currentLineElement = currentSpan.parentNode; |
| 76 if ((currentSpan.start <= start && start < currentSpan.end) || |
| 77 (currentSpan.start <= end && end < currentSpan.end)) { |
| 78 if (firstSelect) { |
| 79 makeContainerPosVisible(view.divElement, currentLineElement.offset
Top); |
| 80 firstSelect = false; |
| 81 } |
| 82 view.codeSelection.select(currentSpan, selected); |
| 83 } |
| 84 } |
| 85 } |
| 86 }, |
| 87 brokeredClear: function() { |
| 88 view.codeSelection.clear(); |
| 89 }, |
| 90 }; |
| 91 |
| 92 view.codeSelection = new Selection(selectionHandler); |
| 93 broker.addSelectionHandler(selectionHandler); |
| 94 |
| 95 var mouseDown = false; |
| 96 |
| 97 this.handleSpanMouseDown = function(e) { |
| 98 e.stopPropagation(); |
| 99 if (!e.shiftKey) { |
| 100 view.codeSelection.clear(); |
| 101 } |
| 102 view.codeSelection.select(this, true); |
| 103 mouseDown = true; |
| 104 } |
| 105 |
| 106 this.handleSpanMouseMove = function(e) { |
| 107 if (mouseDown) { |
| 108 view.codeSelection.extendTo(this); |
| 109 } |
| 110 } |
| 111 |
| 112 this.handleCodeMouseDown = function(e) { |
| 113 view.codeSelection.clear(); |
| 114 } |
| 115 |
| 116 document.addEventListener('mouseup', function(e){ |
| 117 mouseDown = false; |
| 118 }, false); |
| 119 |
| 120 this.initializeCode(sourceText, sourcePosition); |
| 121 } |
| 122 |
| 123 CodeView.prototype.initializeCode = function(sourceText, sourcePosition) { |
| 124 var view = this; |
| 125 if (sourceText == "") { |
| 126 var newHtml = "<pre class=\"prettyprint\"</pre>"; |
| 127 view.divElement.innerHTML = newHtml; |
| 128 } else { |
| 129 var newHtml = "<pre class=\"prettyprint linenums\">" |
| 130 + sourceText + "</pre>"; |
| 131 view.divElement.innerHTML = newHtml; |
| 132 try { |
| 133 // Wrap in try to work when offline. |
| 134 PR.prettyPrint(); |
| 135 } catch (e) { |
| 136 } |
| 137 |
| 138 view.divElement.onmousedown = this.handleCodeMouseDown; |
| 139 |
| 140 var base = sourcePosition; |
| 141 var current = 0; |
| 142 var lineListDiv = view.divElement.firstChild.firstChild.childNodes; |
| 143 for (i=0; i < lineListDiv.length; i++) { |
| 144 var currentLineElement = lineListDiv[i]; |
| 145 currentLineElement.id = "li" + i; |
| 146 var pos = base + current; |
| 147 currentLineElement.pos = pos; |
| 148 var spans = currentLineElement.childNodes; |
| 149 for (j=0; j < spans.length; ++j) { |
| 150 var currentSpan = spans[j]; |
| 151 if (currentSpan.nodeType == 1) { |
| 152 currentSpan.start = pos; |
| 153 currentSpan.end = pos + currentSpan.textContent.length; |
| 154 currentSpan.onmousedown = this.handleSpanMouseDown; |
| 155 currentSpan.onmousemove = this.handleSpanMouseMove; |
| 156 view.allSpans.push(currentSpan); |
| 157 } |
| 158 current += currentSpan.textContent.length; |
| 159 pos = base + current; |
| 160 } |
| 161 while ((current < sourceText.length) && ( |
| 162 sourceText[current] == '\n' || |
| 163 sourceText[current] == '\r')) { |
| 164 ++current; |
| 165 } |
| 166 } |
| 167 } |
| 168 |
| 169 this.resizeToParent(); |
| 170 } |
| 171 |
| 172 CodeView.prototype.resizeToParent = function() { |
| 173 var view = this; |
| 174 var documentElement = document.documentElement; |
| 175 var y = view.divElement.parentNode.clientHeight || documentElement.clientHeigh
t; |
| 176 view.divElement.style.height = y + "px"; |
| 177 } |
OLD | NEW |