Home | History | Annotate | Download | only in turbolizer
      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 == pos1)) {
     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.offsetTop);
     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.clientHeight;
    176   view.divElement.style.height = y + "px";
    177 }
    178