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"use strict"; 6 7class CodeView extends View { 8 constructor(divID, PR, sourceText, sourcePosition, broker) { 9 super(divID, broker, null, false); 10 let view = this; 11 view.PR = PR; 12 view.mouseDown = false; 13 view.broker = broker; 14 view.allSpans = []; 15 16 var selectionHandler = { 17 clear: function() { broker.clear(selectionHandler); }, 18 select: function(items, selected) { 19 var handler = this; 20 var broker = view.broker; 21 for (let span of items) { 22 if (selected) { 23 span.classList.add("selected"); 24 } else { 25 span.classList.remove("selected"); 26 } 27 } 28 var locations = []; 29 for (var span of items) { 30 locations.push({pos_start: span.start, pos_end: span.end}); 31 } 32 broker.clear(selectionHandler); 33 broker.select(selectionHandler, locations, 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.divNode.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 || 46 (inclusive1 && currentSpan.start == pos1)) { 47 if (currentSpan.start < pos2 || 48 (inclusive2 && currentSpan.start == pos2)) { 49 result.push(currentSpan); 50 } 51 } 52 } 53 } 54 return result; 55 }, 56 brokeredSelect: function(locations, selected) { 57 let firstSelect = view.selection.isEmpty(); 58 for (let location of locations) { 59 let start = location.pos_start; 60 let end = location.pos_end; 61 if (start && end) { 62 let lower = 0; 63 let upper = view.allSpans.length; 64 if (upper > 0) { 65 while ((upper - lower) > 1) { 66 var middle = Math.floor((upper + lower) / 2); 67 var lineStart = view.allSpans[middle].start; 68 if (lineStart < start) { 69 lower = middle; 70 } else if (lineStart > start) { 71 upper = middle; 72 } else { 73 lower = middle; 74 break; 75 } 76 } 77 var currentSpan = view.allSpans[lower]; 78 var currentLineElement = currentSpan.parentNode; 79 if ((currentSpan.start <= start && start < currentSpan.end) || 80 (currentSpan.start <= end && end < currentSpan.end)) { 81 if (firstSelect) { 82 makeContainerPosVisible( 83 view.divNode, currentLineElement.offsetTop); 84 firstSelect = false; 85 } 86 view.selection.select(currentSpan, selected); 87 } 88 } 89 } 90 } 91 }, 92 brokeredClear: function() { view.selection.clear(); }, 93 }; 94 view.selection = new Selection(selectionHandler); 95 broker.addSelectionHandler(selectionHandler); 96 97 view.handleSpanMouseDown = function(e) { 98 e.stopPropagation(); 99 if (!e.shiftKey) { 100 view.selection.clear(); 101 } 102 view.selection.select(this, true); 103 view.mouseDown = true; 104 } 105 106 view.handleSpanMouseMove = function(e) { 107 if (view.mouseDown) { 108 view.selection.extendTo(this); 109 } 110 } 111 112 view.handleCodeMouseDown = function(e) { view.selection.clear(); } 113 114 document.addEventListener('mouseup', function(e) { 115 view.mouseDown = false; 116 }, false); 117 118 view.initializeCode(sourceText, sourcePosition); 119 } 120 121 initializeContent(data, rememberedSelection) { this.data = data; } 122 123 initializeCode(sourceText, sourcePosition) { 124 var view = this; 125 if (sourceText == "") { 126 var newHtml = "<pre class=\"prettyprint\"</pre>"; 127 view.divNode.innerHTML = newHtml; 128 } else { 129 var newHtml = 130 "<pre class=\"prettyprint linenums\">" + sourceText + "</pre>"; 131 view.divNode.innerHTML = newHtml; 132 try { 133 // Wrap in try to work when offline. 134 view.PR.prettyPrint(); 135 } catch (e) { 136 } 137 138 view.divNode.onmousedown = this.handleCodeMouseDown; 139 140 var base = sourcePosition; 141 var current = 0; 142 var lineListDiv = view.divNode.firstChild.firstChild.childNodes; 143 for (let 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 (let 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' || sourceText[current] == '\r')) { 163 ++current; 164 } 165 } 166 } 167 168 view.resizeToParent(); 169 } 170 171 deleteContent() {} 172} 173