Closed Bug 104383 Opened 23 years ago Closed 22 years ago

Ability to go to specific line number in View Source window

Categories

(Core Graveyard :: View Source, enhancement)

enhancement
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: schapel, Assigned: bugzilla.mozilla.org-3)

References

Details

(Whiteboard: [geekweb-fixed])

Attachments

(2 files, 12 obsolete files)

1.18 KB, image/png
Details
12.55 KB, patch
neil
: review+
bzbarsky
: superreview+
Details | Diff | Splinter Review
The View Source window needs the capability to go to a specific line number in the source. Here is how such a feature might work: 1. The user selects Edit | Go to Line #... 2. The user types a line number in a field and clicks the Go button or presses the Enter key 3. The line is displayed and highlighted, with the window scrolled all the way to the left side so the beginning of the line can be seen, and perhaps the dialog is dismissed
Great idea. I couldn't find another request for this, so confirming. Also see bug 15364.
Status: UNCONFIRMED → NEW
Ever confirmed: true
Depends on: 15364
doron, I'll love you if you do this.
Assignee: blakeross → doronr
ui wise we can have a input box in the menubar. There is a window.scrollByLines() function (http://developer.netscape.com/evangelism/docs/technotes/xref/window-object/) which might work. bz even suggest if we have a view-source:url#45 to jump to line 45. Will look at it after sleep
Status: NEW → ASSIGNED
I have this working, we need to decide for how to do the UI (I currently have it in the menubar).
Notepad [w2k] uses Edit>Goto which is fine by me, assuming we have no Search menu.
i need to bring back the search menu for viewsource since the naviagor search remocal was futured. can you take a screenshot of the noteapd goto dialog? win98 goto has none
In the windows 2k notepad the shortcut for goto line is ctrl-G and when the dialog opens up, the line number displayed in the textbox is the line number that you are currently on.
0.9.7 it is
Target Milestone: --- → mozilla0.9.7
future. I have this working, but it depends on 110506 getting fully fixed by me.
Target Milestone: mozilla0.9.7 → Future
Depends on: 110506
mass moving open bugs pertaining to view source to pmac@netscape.com as qa contact. to find all bugspam pertaining to this, set your search string to "ItsSharkeysNight".
QA Contact: sairuh → pmac
Keywords: mozilla1.1
Component: XP Apps: GUI Features → ViewSource
do we want to call this "jump to line" or goto? Have this working, attaching what I have in a sec
Attached patch patch which needs work (obsolete) — Splinter Review
How do we want to call it? Go to or jump to line? Patch hardcodes some text still.
> + * The Original Code is Jumo To Line Code. Who's "Jumo" ? :) Why is the little jump-to-line dialog a dialog=no? Why is it even a separate dialog, instead of being a textfield in the viewsource window (like the typein field in the JS console)? Also, I thought the idea was to pass a default line number to the view-source window and have it scroll to that line number onload... are we still planning to do that?
I've always seen this called Go to. I believe Win2K's Edit | Go To... menu makes sense. HomeSite 5 uses Edit | Go to Position... and gives you the option to indicate both the line number and the character position on the line. Of course it's an editor and not a viewer. One nice thing about the HomeSite dialog is that it gives you the valid range: Choose a line number (1-789) [ ]
I copied the find code :) For the default line number, that isn't yet done as I need to modify the js console, don't worry. If I could figure form js the number of lines, that would be cool and solve some issues. I think I have a rough idea of a possible way, but need to do more research on that.
I would say that if there was a way to display line numbers (see bug 15364), this functionality would not necessarily be needed. I would say that line numbers should be added to the source viewer before the "go to line" is added.
Doron, how does this patch deal with the "wrap long lines" mode? Mike, getting this to work is a _lot_ easier than displaying line numbers. We have two proposed fixes for this bug, none for that one yet...
I don't do any development on Mozilla, so I certainly can't argue what would be the easiest solution. If "jump to line" is added (without a display of line numbers on the left), how does the user identify the line once the window has scrolled to it. Is it supposed to be obvious that it is the line at the top of the source window (assuming that the window scrolls to the top of the indicated line)? Does the line become highlighted? There's no cursor to indicate the line in the manner that most editors might. What happens if you "jump to" the last line of the source, or a line near the end? The scrollbar for the viewer only scrolls down enough for the last line to appear at the bottom of the window. On my screen, that leaves close to 40 lines. If I were to "jump to" line 396 of 400 in a particular file, will I only see the last 5 lines in the window (with blank space below)? Or will there be some other way to indicate the line that I was searching for? I'm not trying to argue, I am just pointing out why I was thinking that displaying the line numbers on the left might help make the "jump to" feature a little more usable.
I haven't had time to log into linux and check, and won't till next week probably. As for wrapping, it doesn't know that lines were wrapped, so it will scroll to the nth line displayed. As for line numbers, venkman does it, need to look at that code
*** Bug 160209 has been marked as a duplicate of this bug. ***
setting to 1.2alpha btw, I am very inclined to replace the new->brower/mail/etc with just a "New Browser" menuitem, or even removing that totally As for wrapping, I'm using window.scrollto, so it has no idea about wrapping, so this might cause some issues when I get a jsconsole -> viewsource to linenumber patch (which I had, but lost).
Keywords: mozilla1.1
Target Milestone: Future → mozilla1.2alpha
> As for wrapping, I'm using window.scrollto, so it has no idea about wrapping Then maybe it's the wrong thing to use? If the line numbers in view source are going to have no resemblance to the line numbers in the JS console, what's the point of this patch?
I could always turn off wrapping :) reseting, as this is a valid concern.
Status: ASSIGNED → NEW
Target Milestone: mozilla1.2alpha → ---
Keywords: mozilla1.2
so, would turning off wrapping if the caller is js console be evil?
Keywords: mozilla1.2
Somewhat, yes. There's also the approach taken in bug 79612. We _could_ try to minimize the speed hit there...
it's not worth it for this feature to hack c++
That's a matter of your opinion, not fact.... I think it's perfectly worth it.
current patch doesn't select that line, but it's a start
Whiteboard: [geekweb-fixed]
Now using Mozilla 1.2 Javascript Console gives me this (just an example): Error: xxx is not defined Source File: http://localhost/file.asp Line: 86 I can click the link and the "Source of" window opens the file at the top. IMHO it would be a great start if the "Source of" window had the ability to move to line x and then highlight it (is there a bug for that). Leave the Goto Menu/Dialog stuff for later. (Ctrl-A, Ctrl-C, "open editor", Ctrl-V, Ctrl-G, is not fun)
> is there a bug for that Yes. This is the bug for that.
*** Bug 185572 has been marked as a duplicate of this bug. ***
... lot of bugs were marked as duplicate of this one, but there is NO RESULT. There is still no "GoToLine" or "JumToLine" in ViewSource ... so is there finally a possibility to add thes SIMPLY feature?
If it's so simple, add it. Maybe it's not as simple as you think, eh?
It was totally useless comentary because Mozilla-team solve this problem since Mozilla 0.9 and now we have 1.3a ...
Where exactly have we solved this problem?
future. to make this really work, we need line numbers, which would mean slowing down viewsource. Might have an idea how to speed viewsource a bit to hide the perf hit of line numbers, but I don't have time now to do that.
Target Milestone: --- → Future
This patch finds the specified line the hard way by counting newlines. When the line (e.g. line 34) is found, it is enclosed in a <span class="selected-line" id="line-34"> element. If necessary, span elements that span several lines including the specified are split into two. The line can be styled by inserting some suitable CSS in /res/viewsource.css, e.g. .selected-line { border: 1px dotted black; } Currently it only searches for \n. I am not sure if \r should be handled as a newline as well. When syntax highlighting is on, the performance isn't impressing. With syntax highlighting turned on, however, there is no noticeable delay. The UI is still pretty rudimentary. It still needs localization and some kind of feedback when the line number entered is out of range. Currently the line number is entered in a regular JS prompt(). Personally I prefer a popup dialog, but another possibility is a fixed textfield in the viewsource window as suggested in comment 14. Comments?
> I am not sure if \r should be handled as a newline as well. \r is not a valid character in the DOM; there will never be \r in #text nodes unless someone sticks it in there via DOM methods (as in, the parser will never produce such text nodes). Would it possibly be faster to select all the #text nodes in the document with a treewalker and then stop iterating when you hit the n-th newline? Also, what sort of speed are we talking about here in the highlighted case? Would we be better off just using the patch in bug 79612 (perf hit opening view source every time) or the patch in this bug (per hit on every traversal to a line)? (This is a question about what we think the primary usage patter of such a function would be, really...) Thanks for picking this one up, Christian!
>Would it possibly be faster to select all the #text nodes in the document with >a treewalker and then stop iterating when you hit the n-th newline? I doesn't seem so. Infact is seems considerably (> +50%) slower. And it doesn't make the code easier to read either, because we still need to know which pre and span (if any) each text node is in (disclaimer: I have never worked with the treewalker before so I might have used it in a less-than-optimal way). >Also, what sort of speed are we talking about here in the highlighted case? I have changed the code so it now uses offsetHeight-calculations to count the number of lines when word wrap is off. Also the number of lines in each pre element is now cached, so when the user jumps to a line for the second time it is usually much faster. The following results show approximately how long time it takes to jump to line 2000 of a document on my old Pentium Celeron 300 MHz: word wrap OFF, syntax highlighting OFF < 1 sec word wrap OFF, syntax highlighting ON < 1 sec word wrap ON, syntax highlighting OFF ~ 3 sec word wrap ON, syntax highlighting ON ~15 sec >Would we be better off just using the patch in bug 79612 (perf hit opening view >source every time) or the patch in this bug (per hit on every traversal to a >line)? (This is a question about what we think the primary usage patter of >such a function would be, really...) Personally I'd use the go-to-line feature a lot, but I usually have word wrapping turned off, so I would probably prefer the patch in this bug. Judging from the number of votes and duplicates, this feature (surprisingly) doesn't seem that popular. However, I think the best solution would be a combination of the two patches. If the patch in bug 79612 is changed, so it doesn't insert nodes for every line but just one for every, say, 50 lines (perhaps it could just add an id attribute on each pre element indicating the line number of the last line in the pre), then the perf hit on window open probably wouldn't be that big. The patch in this bug can then find and highlight the exact line by counting newlines from the nearest of these target nodes. Unfortunately I don't really hack C++, so I can't change the patch to bug 79612 myself.
Attachment #120398 - Attachment is obsolete: true
> (perhaps it could just add an id attribute on each pre element indicating the > line number of the last line in the pre) That is an interesting thought, now... Do you build Mozilla, by any chance? If I changed the patch in bug 79612 to do that, would you be able to test?
Yes, I build (on Linux). I tried applying the existing patch, but it seems to have bitrotted. But if you update and change it, I will try again and work from there.
Attached patch Updated patch.... (obsolete) — Splinter Review
This adds an id to all but the first "pre" element (I could add it to the first one too, if you really want, of course). The id has the form "lineXXX" where XXX is the line number of the first line in that pre. So: <pre> Text </pre> <pre id="line2"> text2 text3 </pre> <pre id="line4"> ... I've not done any perf testing on how long it takes to open viewsource with or without this patch; if someone has the time to do that, it would be much appreciated. I _think_ this one shouldn't really affect perf much...
Oh, and I did first line instead of last, because it's a _lot_ easier to do in the current setup... if having the last line number would be much much better, I'll try to look into doing that instead...
Attached patch Patch v 1.2 (obsolete) — Splinter Review
It now highlights the line in < 1 sec, independently of word wrapping and syntax highlighting. >Oh, and I did first line instead of last, because it's a _lot_ easier to do That's fine with me. Now, I am not sure how to move this further (this is my first real Mozilla hacking): - is regular JS prompt() and alert() calls the way to go, should I create a XUL dialog for entering the line number, or should the UI be totally different? - element.scrollIntoView() doesn't do what I expect (I can't find any authorative information about how it is supposed to react). When called on an span element containing a lot of lines down in a pre element, only the top of the pre element is scrolled into view, leaving the span element way below the viewport. This is particularly a problem when viewing source of documents containing a lot of inline Javascript, because a <script> block appears not to be split into seperate pre elements. Is this a bug in scrollIntoView()?
Attachment #120501 - Attachment is obsolete: true
> is regular JS prompt() and alert() calls the way to go Not really, you should use nsIPromptService. see http://lxr.mozilla.org/seamonkey/source/embedding/components/windowwatcher/public/nsIPromptService.idl
> element.scrollIntoView() doesn't do what I expect One possibility here is to use <a id="line-xxx" name="line-xxx"> </a> to enclose the line, to scroll to it by calling loadURI("#line-xxx") on the content webnavigation, and to style it by using the :target selector.... That said, is the problem that scrollIntoView is just scrolling to the top of the parent span that the span you added is in or something? Regular prompt() or alert() should not be called from chrome. You could use the ones on nsIWindowWatcher instead.... I think just having a line number toolbar thingy would be best, myself.... but I'm not a good person to ask about UI. In any case, it's be good to get the code itself working and landed; that can happen even without real UI for it (note that it would be trivial to at least make links from the JS console scroll to the right line, per patch in bug 79612). Two more questions: 1) Why the relative positioning instead of just using a negative margin? 2) What page are you using as your testcase for how long the "go to line" takes? Could you possibly test it on http://www.w3.org/TR/DOM-Level-2-HTML/html.html just so we have a baseline for a fairly large heterogeneous page?
Er, biesi is right. nsIPromptService, not nsIWindowWatcher. I just thought of something else. Sicking, could the splitting and such done in this patch be more easily done using surroundContents on a range or something?
it looks like you should be able to just set the start and endpoint of a range and then use the range to do all the splitting and cloning. However you will not be able to call .surroundContents because that doesn't like splitting non-textnodes (i.e splitting a parent <span>). This is a very stupid limitation in .surroundContents and I poked them about it before the spec went into recommendation, but aparently it is by design (don't ask me why though, it doesn't make sense to me) http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Surrounding However what you still can do is to use the range and call selectedLine.appendChild(range.extractContents()); range.insertNode(selectedLine); That should split any spans as necessary.
Attached patch Patch v. 1.3 (obsolete) — Splinter Review
>> element.scrollIntoView() doesn't do what I expect > >That said, is the problem that scrollIntoView is just scrolling to the top of >the parent span that the span you added is in or something? It scrolls to the top of the parent pre. This is a problem, because a pre containing Javascript can easily contain more than a screenful of lines. >One possibility here is to use <a id="line-xxx" name="line-xxx"> This appears to behave exactly like scrollIntoView(). I found out that scrollIntoView() is actually broken for dynamically created elements (bug 186149), and this is probably also affecting <a id="line-xxx" name="line-xxx">. However, using setTimeout('element.scrollIntoView()', 1) appears to be working for now. >1) Why the relative positioning instead of just using a negative margin? I was tired :-) Now fixed. >2) What page are you using as your testcase for how long the "go to line" >takes? Could you possibly test it on >http://www.w3.org/TR/DOM-Level-2-HTML/html.html It works in < 1 sec even on a long page like this. However, you have to wait for the line to display before searching (not the whole document, just the line your are looking for). Especially with syntax highlighting turned on, this may take quite a while. But once it is loaded, "go to line" works "instantly". >However what you still can do is to use the range and call >selectedLine.appendChild(range.extractContents()); >range.insertNode(selectedLine); Wow, that definately made the code a lot simpler. Also, it now makes sense to use a treewalker to find the text nodes, making the code even more simple. However, due to bug 135922 I cannot use range.insertNode(), so instead I use a slightly more complicated workaround. >Not really, you should use nsIPromptService. Done. Also, the strings are now localizable. >I think just having a line number toolbar thingy would be best, myself.... but >I'm not a good person to ask about UI. In any case, it's be good to get the >code itself working and landed; that can happen even without real UI for it This patch uses the dialog approach. I can easily change it to a toolbar thingy or completely remove the UI (who decides this?), but at least for testing some kind of UI is probably necessary. >(note that it would be trivial to at least make links from the JS console >scroll to the right line, per patch in bug 79612). It's not completely trivial (for me, at least :-), because the "go to line" function has to wait until the line has been displayed (loaded?). That could probably be done using window.setInterval(), but I don't know how to detect when the page has finished displaying (I cannot find an appropriate onload event).
Attachment #121229 - Attachment is obsolete: true
Depends on: 186149
Assigning to Christian, since he's doing all the work... ;) > I found out that scrollIntoView() is actually broken for dynamically created > elements (bug 186149), and this is probably also affecting <a id="line-xxx" > name="line-xxx"> Yep. Try the patch in that bug? If that makes the <a name="xxx"> approach work, I'd sorta like to go with it, since if/when we implement smart scrolling behavior on resize we'd be more likely to keep the right place... That, and it makes the code simpler again -- no need for keeping track of the class. If one approach works and the other does not, of course, we use the one that works. ;) > However, due to bug 135922 I cannot use range.insertNode() Try the patch in that bug too? I've always loved how the use of DOM in our UI forces our DOM impl to suck less.... ;) I hope that all the methods involved keep the selected line properly highlighted, btw.... (I'm not too familiar with ranges, as you can tell.... ;)). In particular, using the "pre" as the thing to append to instead of using the range start container in the case when the container is not a #text node looks odd... (but I've not really put much thought about what the range looks like at that point yet). > but I don't know how to detect when the page has finished displaying Hm... You _may_ be able to attach an onload event to _content. That has to be done after you start the load, however... Perhaps a better way is to, before you start the load, getBrowser().webNavigation.GetInterface(Components.interfaces.nsIWebProgress), then use a small nsIWebProgressListener impl to watch for the STATE_STOP state change? The set an interval and keep trying to scroll and cancel when you manage to scroll or the stop event comes in.... I haven't really done a thorough nitpicking review yet, since this is sort of in-progress so far.. but there are some places where things don't really line up; dunno if those are tabs or just bad whitespacing. This is looking really good, btw. Thanks a ton for working on it.
Assignee: doron → christian
Target Milestone: Future → ---
Depends on: 135922
>> I found out that scrollIntoView() is actually broken for dynamically created >> elements (bug 186149), [...] > >Yep. Try the patch in that bug? >> However, due to bug 135922 I cannot use range.insertNode() > >Try the patch in that bug too? I've always loved how the use of DOM in our UI >forces our DOM impl to suck less.... ;) Boris, you rock! Both your patches work perfectly and made the patch for this bug even cleaner. >Hm... You _may_ be able to attach an onload event to _content. That has to be >done after you start the load, however... Perhaps a better way is to, before >you start the load, >getBrowser().webNavigation.GetInterface(Components.interfaces.nsIWebProgress), >then use a small nsIWebProgressListener impl to watch for the STATE_STOP state >change? The set an interval and keep trying to scroll and cancel when you >manage to scroll or the stop event comes in.... Appearently STATE_STOP is reached way before the whole document is displayed and accessible via the DOM API. If I understand nsViewSourceHTML.cpp correctly it just adds elements to an existing document, so waiting for onload/STATE_STOP wont work. Is it possible for nsViewSourceHTML.cpp to trigger an event, or perhaps close the element with a magic element, e.g. <span id="the-end">? Or is there another way to detect when nsViewSourceHTML.cpp is done? Or did I miss something about nsIWebProgressListener?
OK, maybe we should just do this the stupid way. ;) Sometime before you actually start the load (say at the top of onLoadViewSource() or viewSource(), do: getBrowser().addEventListener("load", foo, true); and add function foo (event) { // we are loaded } (with a better function name and all). Just make sure to use a capturing listener, since load events don't bubble... (and yes, I should have thought of this before suggesting the other stuff; I've been working on necko/docshell too much lately.... ;) )
Attached patch Patch v. 1.4 (obsolete) — Splinter Review
Now I managed to get hold of the onload event (using getBrowser().addEventListener). Included in the patch is now also a change to the JS console that makes the links to the view source window also go to the line in question. The line number is supplied via window.arguments as recommended in bug 79612. The argument must be of type "number" to work. I changed window._content.document.getElementById('viewsource') to window._content.document.body, because when view source is called without a page descripter (e.g. from the JS console) the body element for some reason does not have id="viewsource". I don't know why this is the case, but using document.body is probably just as good as using document.getElementById("viewsource"). I jump to the line using webNavigation.loadURI(), but I looks as if I have to supply an absolute URL instead of just |#line-1234|. I don't know a way to find this absolute URL except by doing simple string searches and concatenations (I tried getBrowser().webNavigation.currentURI.resolve(...) and ioService.newURI(...) without luck).
Attachment #121580 - Attachment is obsolete: true
Gack. You're right; loadURI does not take an anchor name.... I should consider fixing that or adding a scrollToAnchor on that API.... Anyway, that works for now. I'm not sure why there is no "viewsource" id -- nsViewSourceHTML.cpp always adds it to the <body>... Please give global variables names like gLineFound? If you use the :target pseudo-class instead of a class, you shouldn't need to keep track of the selected line globally, right? This is looking really excellent. ;)
Attached patch Patch v. 1.5 (obsolete) — Splinter Review
I now use the :target selector, so selectedLine no longer have to be global. The global variables have been prefixed with |g|.
Attachment #121867 - Attachment is obsolete: true
Comment on attachment 120593 [details] [diff] [review] Updated patch.... rbs, would you sr the back end part of this?
Attachment #120593 - Flags: superreview?(rbs)
Attachment #120593 - Flags: review?(rbs)
Comment on attachment 121923 [details] [diff] [review] Patch v. 1.5 + textNodes: for (var textNode = treewalker.firstChild(); + textNode != null; + textNode = treewalker.nextNode()) { Indent the sub-clauses of the if to line up? No need for a new patch with that change till after Neil's review. sr=me, and looking forward to having this in the tree. ;)
Attachment #121923 - Flags: superreview+
Attachment #121923 - Flags: review?(neil)
Comment on attachment 121923 [details] [diff] [review] Patch v. 1.5 + var selectedLine = window._content.document.getElementById('line-' + line); always null here due to 'line-'
rbs, that's not looking for the pre blocks. See + selectedLine.id = 'line-' + line;
Might be best to settle on a uniform nomenclature then. It is confusion otherwise. Other comments comming up...
Comment on attachment 121923 [details] [diff] [review] Patch v. 1.5 + if (typeof(arg) == "number" && !isNaN(arg)) { + window.setTimeout(waitForLine, 200, arg); + getBrowser().addEventListener("load", function() { contentLoaded = true; }, true); + } + } [...] +function waitForLine(line) { + var found = goToLine(line); + // + // If the line was not found and the page has not finished + // loading, then try again after a short while. + // + if (!found && !contentLoaded) { + window.setTimeout(waitForLine, 200, line); + } +} Do you need all these genuflections? BTW, I experienced similar troubles with View Selection Source where I had to wait until the DOM is built before highligthing the selected area. (It is until you set out to do these stuff that difficulties show up :-) It would have save you some hassle to look over there. Your code can be simplified in these ways: 1) to wait until the view-source DOM is there, you can for example do the following (i.e., no need for setTimeout): disable_the_goto_line_menu_item_by_default(); window.document.getElementById("appcontent") .addEventListener("load", waitForLine, true); function waitForLine() { removeListener(waitForLine) ... enable_the_goto_line_menu_item(); } 2) no much point for CSS rules with :target. Just re-use the selection infrastructure to select the line (like in View Selection Source). function gotoLine() { // get the selection controller var contentWindow = getBrowser().contentDocument.defaultView; var selection = contentWindow.getSelection(); // figure out the range of interest, say |myRange| // (it is possible to avoid modifying the view-source DOM by // defining the parameters of range appropriately) myRange = ... if (invalid) return, of course selection.removeAllRanges(); selection.addRange(myRange); // this will automatically scroll // the selection/line into view... // (i.e. no need to re-load) // ======= // FYI, the default behavior of the selection is to scroll at the // end of the selection. For wrapped lines, to ensure that the // selection is scrolled at the beginning, you might want to override // the default behavior with this little voodoo: (this is what // View Selection Source does, BTW) try { getBrowser().docShell .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsISelectionDisplay) .QueryInterface(Components.interfaces.nsISelectionController) .scrollSelectionIntoView( Components.interfaces.nsISelectionController.SELECTION_NORMAL, Components.interfaces.nsISelectionController.SELECTION_ANCHOR_REGION, true); } catch(e) { } }
Comment on attachment 120593 [details] [diff] [review] Updated patch.... r+sr=rbs. (With the freeze, I wouldn't have bothered doing the cleanup since it makes the patch unnecessarily big when requesting the a=)
Attachment #120593 - Flags: superreview?(rbs)
Attachment #120593 - Flags: superreview+
Attachment #120593 - Flags: review?(rbs)
Attachment #120593 - Flags: review+
>1) to wait until the view-source DOM is there, you can for >example do the following (i.e., no need for setTimeout): The thing is that the line may be accessible before the whole document has loaded and the load event occurs. setTimeout allows us to highlight the line almost as soon as it has been loaded. Thanks for the review. An updated patch coming up later today.
Comment on attachment 121923 [details] [diff] [review] Patch v. 1.5 >+ getBrowser().addEventListener("load", function() { gContentLoaded = true; }, true); I agree that you should be trying to find the line here. >+ var viewSourceBundle = document.getElementById('viewSourceBundle'); Pity you forgot to include the bundle in the XUL... >+ for (;;) { I'm doubtful you want this in a loop... >+ if (isNaN(line)) { >+ promptService.alert(window, >+ viewSourceBundle.getString("invalidInputTitle"), >+ viewSourceBundle.getString("invalidInputText")); >+ } else { >+ break; >+ } if (!isNan(line)) break; promptService.alert(...); IMHO looks neater. Actually, you might want to check for if (line > 0) break; >+ if (selectedLine == null) { Do we do this or !selectedLine? (Can't remember "house" style) >+ for (var lbound = 0, ubound = viewsource.childNodes.length - 1; ; ) { >+ var middle = lbound + Math.ceil((ubound - lbound) / 2); var middle = Math.ceil((ubound + lbound) / 2); Aside: I prefer to have ubound start at .length and adjust the code accordingly e.g. middle = (ubound + lbound) >> 1 >+ textNodes: A label! Is this to be the first JS label in Mozilla? (OK I haven't searched the rest of the code). >+ // Count newlines; Try splitting the data into lines, that gives you an instant count. i.e. var lineArray = textNode.data.split(/\n/); (you might need to adjust for a trailing newline though) >+ selectedLine = window._content.document.createElement('SPAN'); Interesting this. When word wrap is on the border looks awful. I tried using -moz-outline which outlines each row of the wrapped line. I also tried using a DIV instead of a SPAN, which forces a 100% width block which looks good for short and wrapped lines, but not for long unwrapped lines (i.e. more than 100% width). You could of course try pre[wrap] :target { display: block; } (or whatever). Or you could forget the border and put both a DIV and a SPAN in... >+ if (selectedLine != null) { >+ selectedLine.className = 'selected-line'; A leftover from some code that you might need to resurrect? >+ getBrowser().webNavigation.loadURI(viewSrcUrl, loadFlags, null, null, null); Note that getBrowser() also has a .loadURI method which passes some default values to .webNavigation.loadURI >+<!ENTITY goToLineCmd.label "Go to line ..."> No space before the ...
Attachment #121923 - Flags: review?(neil) → review-
neil, thanks for the review. I have a few clarifying questions: >>+ getBrowser().addEventListener("load", function() { gContentLoaded = true; }, true); >I agree that you should be trying to find the line here. I am not sure I understand you correctly. Do you suggest that I should wait for the whole DOM to load before looking for the line? This will make looking for a line in the beginning of the document take significantly longer - especially when syntax highlighting is on. >>+ for (;;) { >I'm doubtful you want this in a loop... If I get you right, you think that I should just show the alert(invalidInput) and then terminate without prompting for a line again? Notepad, UltraEdit and others keep prompting for a line until a valid integer has been entered. >Interesting this. When word wrap is on the border looks awful. I will probably just use a selection as suggested by rbs to be in sync with View Selection Source (if people agreee).
Yeah, using the selection sounds fine.
re: comment #64 > >1) to wait until the view-source DOM is there, you can for > >example do the following (i.e., no need for setTimeout): > > The thing is that the line may be accessible before the whole document has > loaded and the load event occurs. setTimeout allows us to highlight the line > almost as soon as it has been loaded. With the selection approach, you wouldn't be using a view-source(url#line) anymore. Hence there is no (re)load. Rather, the gotoLine kicks in after the user mouses clumsily to Edit -> Goto Line -> input. By then, a rather long time would have elapsed and the single load (first time) would have completed in most cases. [In an earlier implementation of View Selection Source, it used a setTimeout. It was not worth the trouble. Plus the sr didn't like it. Also, optionally disabling the menu item (if you deem necessary) provides a safeguard until that first load is done. As you experiment with the selection, you will get a clearer picture of where things stand.]
> Rather, the gotoLine kicks in after the user mouses clumsily to Edit -> Goto > Line -> input. Except in the common case of source being opened from the JS console. Then the gotoLine() is called programmatically. We could indeed delay that till the onload, but if there is a JS error on line 143 of a 5000-line HTML file, it'd be good to scroll to it asap after the user clicks the link in the JS console.
Adding dependency to bug 79612 which I hadn't read before and which is the scenario that you describe. So, the fix is intended to subsume two cases: Normal: view-source(url) + Edit -> Goto line -> input JS Console: view-source(url#line), jump to line. ==== From my recollection, I couldn't get a meaningful document pointer from the script until the document onload was fired (paint supression/zombie, perhaps). There is a difference between: /* this one tells that the chrome is ready */ + getBrowser().addEventListener("load", function() { gContentLoaded = true; }, true); /* this one tells that the content document is ready, same as <body onload> */ window.document.getElementById("appcontent") .addEventListener("load", waitForLine, true); Are you really observing a jump to the line asap with the other one, while the document is still sluggishly loading?
Blocks: 79612
> There is a difference between: There is? The first sets a capturing load listener on the XUL <browser> node. The second sets a load listener on the parent of said node. Both will fire at the same point -- when the onload() of the document loading withing the browser fires. I'm assuming that Christian tested the scrolling to line while the document is loading, of course.
> There is? Indeed. It took me a while to discover & get what I wanted because of that difference. In fact, come to think of it, if there wasn't a difference the setTimeout would be meaningless. Since <body onload> would mean that the DOM is there, and so gotoLine will succeed. Whereas <chrome onload> means that the chrome is done and is about to load the document, and so attaching the waitLine for the document means something. This brings to what I was most wondering about: whether what is exposed to the script is indeed a meaningful at that stage, which is why I am curious to know how the testing goes.
> This brings to what I was most wondering about: whether what is exposed to the > script is indeed a meaningful at that stage, which is why I am curious to know > how the testing goes. I do not know whether the DOM exposed to the script is meaningful during load, but if the text nodes are added sequentially in the order they will appear in the tree, then I assume that if the script thinks it has found the line then it in fact is the right line (because text nodes cannot be inserted before it in the tree). But I am just guessing. Judging by my testing it looks as if the setTimeout version always (?) succeeds in finding the line, but sometimes the scrollSelectionIntoView fails, i.e. the line is highlighted but the window does not scroll at all. Perhaps the text is somehow present in the DOM a short while before it is displayed on the screen. If people prefer the conservative approach that waits for the whole document to load before looking for the line, I will use that.
Status: NEW → ASSIGNED
> the setTimeout version always (?) succeeds in finding the line Indeed, since you are looping. But it could be that the loop is succeeding at the very end, i.e., when the document has already loaded anyway. Another thing to double-check is that the line that is seemingly found may actually belong to the old document (the so-called "zombie" document). I am a bit cautious in this muddy area because it took me a while to get out of it. Once you are happy with a reliable version, feel free to show us.
Attached patch Patch v. 1.6 (obsolete) — Splinter Review
This patch waits for the load event before looking for the line. This appears to work in all cases contrary to the setTimeout solution that sometimes failed to scroll the line into view. The specified line is highlighted using a selection. If the line happens to be blank, the selection is invisible. This might change if the linefeed characters are made visible in a selection as proposed in bug 156175. I don't know if we need a workaround for this, e.g. reverting to highlighting via CSS, but since empty lines in general aren't of much interest this probably isn't a big issue. It looks like there is a problem with scrollSelectionIntoView being off by one line, so I filed bug 205006.
Attachment #121923 - Attachment is obsolete: true
Comment on attachment 122940 [details] [diff] [review] Patch v. 1.6 Looking good to me, just a few sanity check comments: + // arg[3] - Line number to go to. // if ("arguments" in window) { var arg; @@ -78,6 +104,16 @@ } } // + // Wait for the specified line to load. + // + if (window.arguments.length >= 4) { + arg = window.arguments[3]; + + if (typeof(arg) == "number" && arg > 0) { + gGoToLine = arg; + } + } + // This is for bug 79612, view-source(url#line), right? I don't see the parsing of #line. Needs to hook properly now? + getBrowser().addEventListener( + "load", + function() { + if (gGoToLine) { + goToLine(gGoToLine); + gGoToLine = false; + } You mean |if (gGoToLine > 0)| and |gGoToLine = -1| since it isn't a boolean.
> This is for bug 79612, view-source(url#line), right? I don't see the parsing > of #line. It is indeed a hook for the JS console, but the line number is sent from the JS console (consoleBindings.xml) via window.arguments instead of url#line (as suggested in bug 79612), i.e. no parsing needs to be done: window.openDialog( "chrome://navigator/content/viewSource.xul", "_blank", "scrollbars,resizable,chrome,dialog=no", url, null, null, line);
I applied the patch for experimentation and could fix/work-around the remaining issues: 1) If the selected line happens to be blank, the selection is invisible. -> show a blinking caret on the line... 2) scrollSelectionIntoView off by one line -> use a "hint" to orientate the selection. This one was subtle because range indices are delicate. With your code, the selection start's offset is after the "\n" at the end of the previous line. By using an interline hint ("hintright"), I forced the needed line to come into view. Also, -> moved the bundle to the viewsource overlay -> placed the Goto line menu item before the Finds. It looked akward to be in-between them. (I guess some UI people might comment later on the wordings anyway.) Back to you. Good job. It works great and the ice on the cake is that it kills bug 79612, as well as CSS errors (when the line number is given properly). Re: bz, you might want to sync the line's id in DUMP_TO_FILE. Also, it looked like you could have set id="line1" on the first <pre> to save the special-case in the JS.
Yeah, I should sync the DUMP_TO_FILE stuff, and it looks like I need to add some IF_FREE() calls as well (the body token is the only one we do it for now)... those are not real leaks, since it's an arena, but still.... Oh, and yes; I'll add an id to the first <pre>.
Want to drive things in, then? It is low risk with high reward. Click on a warning/error in the JavaScript console and it jumps to the precise line in the source and highlights it... JavaScript'ers in particular will like this a lot.
Attachment #81425 - Attachment is obsolete: true
Attachment #120593 - Attachment is obsolete: true
Attachment #122940 - Attachment is obsolete: true
Comment on attachment 123360 [details] [diff] [review] Patch for back end updated to comment 78 I was wrong about IF_FREE. Parser nodes free their tokens, so we should NOT, in fact, be freeing them. This is the same as the previous patch except I added id="line1" to the first <pre> and fixed the DUMP_TO_FILE sections. I agree that it would be great to take this for 1.4, drivers willing (I agree that this is quite low-risk). What we need is r= on the front end section from a front-end person (eg Neil).
Attachment #123360 - Flags: superreview?(rbs)
Attachment #123360 - Flags: review?(rbs)
Comment on attachment 123251 [details] [diff] [review] v1.7 - correct remaining issues from using the selection sr=me on this (modulo whatever you guys decide to do with that first pre). Neil, would you review?
Attachment #123251 - Flags: superreview+
Attachment #123251 - Flags: review?(neil.parkwaycc.co.uk)
Comment on attachment 123360 [details] [diff] [review] Patch for back end updated to comment 78 r+sr=rbs on this updated back-end.
Attachment #123360 - Flags: superreview?(rbs)
Attachment #123360 - Flags: superreview+
Attachment #123360 - Flags: review?(rbs)
Attachment #123360 - Flags: review+
Comment on attachment 123251 [details] [diff] [review] v1.7 - correct remaining issues from using the selection >+ locale/en-US/navigator/viewSource.properties (resources/locale/en-US/viewSource.properties) Sadly the file itself is missing from the patch :-/ >+ // >+ // Disable "go to line" while reloading due to e.g. change of charset >+ // or toggling of syntax highlighting. >+ // >+ getBrowser().addEventListener( >+ "unload", >+ function() { >+ document.getElementById('cmd_goToLine').setAttribute('disabled', 'true'); >+ }, >+ true); >+ >+ getBrowser().addEventListener( >+ "load", >+ function() { >+ if (gGoToLine) { >+ goToLine(gGoToLine); >+ gGoToLine = 0; >+ } >+ document.getElementById('cmd_goToLine').removeAttribute('disabled'); >+ }, >+ true); I'm not a fan of big inline functions... >+ arg = window.arguments[3]; >+ >+ if (typeof(arg) == "number" && arg > 0) { >+ gGoToLine = arg; >+ } Probably neater to do the parseInt here instead of in consoleBindings.xml i.e. arg = parseInt(window.arguments[3]); if (arg > 0) { gGoToLine = arg; } Actaully, gGoToLine = parseInt(window.arguments[3]); would work becuause your load handler already checks for > 0. >+ promptService.alert(window, >+ viewSourceBundle.getString("invalidInputTitle"), >+ viewSourceBundle.getString("invalidInputText")); The subtle difference is that Notepad et al don't close the prompt for the input while displaying the invalid input alert... in fact, Notepad doesn't close it for the out of range alert either, so I think you should be consistent too, whichever way around, either always prompt after an error or never prompt after an error. >+ gLastLineFound = line; >+ var found = goToLine(line); You haven't found the line yet... please set gLastLineFound in goToLine() instead. >+ if (curLine == line) {// && !range) { Still setting the end of the range every time? >+ if (!range) { >+ range = document.createRange(); >+ range.setStart(textNode, curPos); >+ } >+ >+ // >+ // This will always be overridden later, except when we look for >+ // the very last line in the file (this is the only line that does >+ // not end with \n). >+ // >+ range.setEndAfter(pre.lastChild); >+ var selection = window._content.getSelection(); >+ selection.removeAllRanges(); I think you should use if (!range) return false; before here (also change the last return to return true;). >+ var url = this.getAttribute("url"); >+ var line = this.hasAttribute("line") ? parseInt(this.getAttribute("line")) : null; > window.openDialog( > "chrome://navigator/content/viewSource.xul", "_blank", >- "scrollbars,resizable,chrome,dialog=no", this.getAttribute("url")); >+ "scrollbars,resizable,chrome,dialog=no", url, null, null, line); With the parseInt in viewsource.js you can just use two inline getAttribute calls instead now.
Attachment #123251 - Flags: review?(neil.parkwaycc.co.uk) → review-
Comment on attachment 123360 [details] [diff] [review] Patch for back end updated to comment 78 Requesting 1.4 approval for the back end part. This is a very safe change that just adds line number information to the markup view-source generates; this should enable front-end code to be added (in the other patch, or via an XPI) that will enable users to "go to line" in view-source.
Attachment #123360 - Flags: approval1.4?
Attached patch v1.8 - updated to comment 85 (obsolete) — Splinter Review
> The subtle difference is that Notepad et al don't close the prompt for the > input while displaying the invalid input alert... [...] so I think you should > be consistent too, whichever way around, either always prompt after an error > or never prompt after an error. I decided to always prompt after an error. This allows the user to see and possible change what he typed.
Attachment #123251 - Attachment is obsolete: true
+ // the first line in the pre element is number 123 (except the first + // pre that does not have an id attribute). Now that the first pre isn't a special-case, the "except" bit is not necessary anymore, you might want update the comment at check-in.
Attachment #123452 - Flags: review?(neil.parkwaycc.co.uk)
Comment on attachment 123452 [details] [diff] [review] v1.8 - updated to comment 85 >+ if (gGoToLine) { I think gGoToLine > 0 would be better here. >+ goToLine(gGoToLine); >+ gGoToLine = 0; >+ } >+ var selection = window._content.getSelection(); >+ selection.removeAllRanges(); >+ >+ if (!range) { >+ return false; >+ } I think you should swap these around, otherwise the previous selection will be lost if the line was not found.
Attachment #123452 - Flags: review?(neil.parkwaycc.co.uk) → review+
I am not sure whether this update needs new reviews. I do not have CVS access so I need help getting this checked in when it's time - thanks.
Attachment #123452 - Attachment is obsolete: true
Comment on attachment 123502 [details] [diff] [review] v1.9 that addresses comment 88 and 89 Neil, one last look, please? ;) sr=me
Attachment #123502 - Flags: superreview+
Attachment #123502 - Flags: review?(neil.parkwaycc.co.uk)
Comment on attachment 123360 [details] [diff] [review] Patch for back end updated to comment 78 a=asa (on behalf of drivers) for checkin to 1.4
Attachment #123360 - Flags: approval1.4? → approval1.4+
Comment on attachment 123360 [details] [diff] [review] Patch for back end updated to comment 78 Back end patch checked in.
Attachment #123360 - Attachment is obsolete: true
Attachment #123502 - Flags: review?(neil.parkwaycc.co.uk) → review+
Attachment #123502 - Flags: approval1.4?
Comment on attachment 123502 [details] [diff] [review] v1.9 that addresses comment 88 and 89 a=asa (on behalf of drivers) for checkin to 1.4
Attachment #123502 - Flags: approval1.4? → approval1.4+
Patch checked in. Christian, thank you once again (I just noticed that this plays perfectly with the debug-only CSS error reporting, so life got that much happier).
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
*** Bug 239211 has been marked as a duplicate of this bug. ***
Product: Browser → Seamonkey
Blocks: 239211
Product: SeaMonkey → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: