home *** CD-ROM | disk | FTP | other *** search
/ Computer Active 2010 July / CA07.iso / Multimedija / QuickTimeInstaller.exe / AppleApplicationSupport.msi / WebKit.resources_inspector_SourceView.js < prev    next >
Encoding:
Text File  |  2010-03-15  |  11.2 KB  |  309 lines

  1. /*
  2.  * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1.  Redistributions of source code must retain the above copyright
  9.  *     notice, this list of conditions and the following disclaimer.
  10.  * 2.  Redistributions in binary form must reproduce the above copyright
  11.  *     notice, this list of conditions and the following disclaimer in the
  12.  *     documentation and/or other materials provided with the distribution.
  13.  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14.  *     its contributors may be used to endorse or promote products derived
  15.  *     from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20.  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. WebInspector.SourceView = function(resource)
  30. {
  31.     // Set the sourceFrame first since WebInspector.ResourceView will set headersVisible
  32.     // and our override of headersVisible needs the sourceFrame.
  33.     this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
  34.  
  35.     WebInspector.ResourceView.call(this, resource);
  36.  
  37.     resource.addEventListener("finished", this._resourceLoadingFinished, this);
  38.  
  39.     this.element.addStyleClass("source");
  40.  
  41.     this._frameNeedsSetup = true;
  42.  
  43.     this.contentElement.appendChild(this.sourceFrame.element);
  44.  
  45.     var gutterElement = document.createElement("div");
  46.     gutterElement.className = "webkit-line-gutter-backdrop";
  47.     this.element.appendChild(gutterElement);
  48. }
  49.  
  50. WebInspector.SourceView.prototype = {
  51.     set headersVisible(x)
  52.     {
  53.         if (x === this._headersVisible)
  54.             return;
  55.  
  56.         var superSetter = WebInspector.ResourceView.prototype.__lookupSetter__("headersVisible");
  57.         if (superSetter)
  58.             superSetter.call(this, x);
  59.  
  60.         this.sourceFrame.autoSizesToFitContentHeight = x;
  61.     },
  62.  
  63.     show: function(parentElement)
  64.     {
  65.         WebInspector.ResourceView.prototype.show.call(this, parentElement);
  66.         this.setupSourceFrameIfNeeded();
  67.     },
  68.  
  69.     hide: function()
  70.     {
  71.         WebInspector.View.prototype.hide.call(this);
  72.         this._currentSearchResultIndex = -1;
  73.     },
  74.  
  75.     resize: function()
  76.     {
  77.         if (this.sourceFrame.autoSizesToFitContentHeight)
  78.             this.sourceFrame.sizeToFitContentHeight();
  79.     },
  80.  
  81.     detach: function()
  82.     {
  83.         WebInspector.ResourceView.prototype.detach.call(this);
  84.  
  85.         // FIXME: We need to mark the frame for setup on detach because the frame DOM is cleared
  86.         // when it is removed from the document. Is this a bug?
  87.         this._frameNeedsSetup = true;
  88.         this._sourceFrameSetup = false;
  89.     },
  90.  
  91.     setupSourceFrameIfNeeded: function()
  92.     {
  93.         if (!this._frameNeedsSetup)
  94.             return;
  95.  
  96.         this.attach();
  97.  
  98.         delete this._frameNeedsSetup;
  99.         this.sourceFrame.addEventListener("content loaded", this._contentLoaded, this);
  100.         InspectorController.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element);
  101.     },
  102.     
  103.     _contentLoaded: function()
  104.     {
  105.         delete this._frameNeedsSetup;
  106.         this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
  107.  
  108.         if (this.resource.type === WebInspector.Resource.Type.Script) {
  109.             this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
  110.             this.sourceFrame.syntaxHighlightJavascript();
  111.         } else
  112.             this._sourceFrameSetupFinished();
  113.     },
  114.  
  115.     _resourceLoadingFinished: function(event)
  116.     {
  117.         this._frameNeedsSetup = true;
  118.         this._sourceFrameSetup = false;
  119.         if (this.visible)
  120.             this.setupSourceFrameIfNeeded();
  121.         this.resource.removeEventListener("finished", this._resourceLoadingFinished, this);
  122.     },
  123.  
  124.     _addBreakpoint: function(line)
  125.     {
  126.         var sourceID = null;
  127.         var closestStartingLine = 0;
  128.         var scripts = this.resource.scripts;
  129.         for (var i = 0; i < scripts.length; ++i) {
  130.             var script = scripts[i];
  131.             if (script.startingLine <= line && script.startingLine >= closestStartingLine) {
  132.                 closestStartingLine = script.startingLine;
  133.                 sourceID = script.sourceID;
  134.             }
  135.         }
  136.  
  137.         if (WebInspector.panels.scripts) {
  138.             var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID);
  139.             WebInspector.panels.scripts.addBreakpoint(breakpoint);
  140.         }
  141.     },
  142.  
  143.     // The rest of the methods in this prototype need to be generic enough to work with a ScriptView.
  144.     // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code.
  145.  
  146.     searchCanceled: function()
  147.     {
  148.         this._currentSearchResultIndex = -1;
  149.         this._searchResults = [];
  150.         delete this._delayedFindSearchMatches;
  151.     },
  152.  
  153.     performSearch: function(query, finishedCallback)
  154.     {
  155.         // Call searchCanceled since it will reset everything we need before doing a new search.
  156.         this.searchCanceled();
  157.  
  158.         var lineQueryRegex = /(^|\s)(?:#|line:\s*)(\d+)(\s|$)/i;
  159.         var lineQueryMatch = query.match(lineQueryRegex);
  160.         if (lineQueryMatch) {
  161.             var lineToSearch = parseInt(lineQueryMatch[2]);
  162.  
  163.             // If there was a space before and after the line query part, replace with a space.
  164.             // Otherwise replace with an empty string to eat the prefix or postfix space.
  165.             var lineQueryReplacement = (lineQueryMatch[1] && lineQueryMatch[3] ? " " : "");
  166.             var filterlessQuery = query.replace(lineQueryRegex, lineQueryReplacement);
  167.         }
  168.  
  169.         this._searchFinishedCallback = finishedCallback;
  170.  
  171.         function findSearchMatches(query, finishedCallback)
  172.         {
  173.             if (isNaN(lineToSearch)) {
  174.                 // Search the whole document since there was no line to search.
  175.                 this._searchResults = (InspectorController.search(this.sourceFrame.element.contentDocument, query) || []);
  176.             } else {
  177.                 var sourceRow = this.sourceFrame.sourceRow(lineToSearch);
  178.                 if (sourceRow) {
  179.                     if (filterlessQuery) {
  180.                         // There is still a query string, so search for that string in the line.
  181.                         this._searchResults = (InspectorController.search(sourceRow, filterlessQuery) || []);
  182.                     } else {
  183.                         // Match the whole line, since there was no remaining query string to match.
  184.                         var rowRange = this.sourceFrame.element.contentDocument.createRange();
  185.                         rowRange.selectNodeContents(sourceRow);
  186.                         this._searchResults = [rowRange];
  187.                     }
  188.                 }
  189.  
  190.                 // Attempt to search for the whole query, just incase it matches a color like "#333".
  191.                 var wholeQueryMatches = InspectorController.search(this.sourceFrame.element.contentDocument, query);
  192.                 if (wholeQueryMatches)
  193.                     this._searchResults = this._searchResults.concat(wholeQueryMatches);
  194.             }
  195.  
  196.             if (this._searchResults)
  197.                 finishedCallback(this, this._searchResults.length);
  198.         }
  199.  
  200.         if (!this._sourceFrameSetup) {
  201.             // The search is performed in _sourceFrameSetupFinished by calling _delayedFindSearchMatches.
  202.             this._delayedFindSearchMatches = findSearchMatches.bind(this, query, finishedCallback);
  203.             this.setupSourceFrameIfNeeded();
  204.             return;
  205.         }
  206.  
  207.         findSearchMatches.call(this, query, finishedCallback);
  208.     },
  209.  
  210.     jumpToFirstSearchResult: function()
  211.     {
  212.         if (!this._searchResults || !this._searchResults.length)
  213.             return;
  214.         this._currentSearchResultIndex = 0;
  215.         this._jumpToSearchResult(this._currentSearchResultIndex);
  216.     },
  217.  
  218.     jumpToLastSearchResult: function()
  219.     {
  220.         if (!this._searchResults || !this._searchResults.length)
  221.             return;
  222.         this._currentSearchResultIndex = (this._searchResults.length - 1);
  223.         this._jumpToSearchResult(this._currentSearchResultIndex);
  224.     },
  225.  
  226.     jumpToNextSearchResult: function()
  227.     {
  228.         if (!this._searchResults || !this._searchResults.length)
  229.             return;
  230.         if (++this._currentSearchResultIndex >= this._searchResults.length)
  231.             this._currentSearchResultIndex = 0;
  232.         this._jumpToSearchResult(this._currentSearchResultIndex);
  233.     },
  234.  
  235.     jumpToPreviousSearchResult: function()
  236.     {
  237.         if (!this._searchResults || !this._searchResults.length)
  238.             return;
  239.         if (--this._currentSearchResultIndex < 0)
  240.             this._currentSearchResultIndex = (this._searchResults.length - 1);
  241.         this._jumpToSearchResult(this._currentSearchResultIndex);
  242.     },
  243.  
  244.     showingFirstSearchResult: function()
  245.     {
  246.         return (this._currentSearchResultIndex === 0);
  247.     },
  248.  
  249.     showingLastSearchResult: function()
  250.     {
  251.         return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
  252.     },
  253.  
  254.     revealLine: function(lineNumber)
  255.     {
  256.         this.setupSourceFrameIfNeeded();
  257.         this.sourceFrame.revealLine(lineNumber);
  258.     },
  259.  
  260.     highlightLine: function(lineNumber)
  261.     {
  262.         this.setupSourceFrameIfNeeded();
  263.         this.sourceFrame.highlightLine(lineNumber);
  264.     },
  265.  
  266.     addMessage: function(msg)
  267.     {
  268.         this.sourceFrame.addMessage(msg);
  269.     },
  270.  
  271.     clearMessages: function()
  272.     {
  273.         this.sourceFrame.clearMessages();
  274.     },
  275.  
  276.     _jumpToSearchResult: function(index)
  277.     {
  278.         var foundRange = this._searchResults[index];
  279.         if (!foundRange)
  280.             return;
  281.  
  282.         var selection = this.sourceFrame.element.contentWindow.getSelection();
  283.         selection.removeAllRanges();
  284.         selection.addRange(foundRange);
  285.  
  286.         if (foundRange.startContainer.scrollIntoViewIfNeeded)
  287.             foundRange.startContainer.scrollIntoViewIfNeeded(true);
  288.         else if (foundRange.startContainer.parentNode)
  289.             foundRange.startContainer.parentNode.scrollIntoViewIfNeeded(true);
  290.     },
  291.  
  292.     _sourceFrameSetupFinished: function()
  293.     {
  294.         this._sourceFrameSetup = true;
  295.         if (this._delayedFindSearchMatches) {
  296.             this._delayedFindSearchMatches();
  297.             delete this._delayedFindSearchMatches;
  298.         }
  299.     },
  300.  
  301.     _syntaxHighlightingComplete: function(event)
  302.     {
  303.         this._sourceFrameSetupFinished();
  304.         this.sourceFrame.removeEventListener("syntax highlighting complete", null, this);
  305.     }
  306. }
  307.  
  308. WebInspector.SourceView.prototype.__proto__ = WebInspector.ResourceView.prototype;
  309.