Changeset 156809 in webkit
- Timestamp:
- Oct 2, 2013 4:33:14 PM (11 years ago)
- Location:
- trunk/Source/WebInspectorUI
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebInspectorUI/ChangeLog
r156765 r156809 1 2013-10-02 Brian J. Burg <burg@cs.washington.edu> 2 3 Web Inspector: save and restore source positions in back/forward history 4 https://bugs.webkit.org/show_bug.cgi?id=122062 5 6 Reviewed by Timothy Hatcher. 7 8 Previously, the back/forward entries comprised of only the content 9 views, but not their positions if navigated via hyperlink (i.e., 10 handling script.js:42). When multiple instances of the same 11 content view appeared in the back/forward list, the most recent 12 navigation was displayed rather than the linked position. 13 14 We now store context necessary to re-navigate such hyperlinks by 15 storing view- specific data inside a cookie object, and invoke a 16 supplied callback to take any position initialization actions, 17 such as calling TextEditor.revealPosition. This state is 18 encapsulated into BackForwardEntry instances. 19 20 Functions that save and restore scroll positions inside content 21 views have been changed to store state in BackForwardEntry 22 instances, so multiple scroll positions can be saved for a content 23 view appearing in the navigation history more than once. 24 25 * UserInterface/BackForwardEntry.js: Added. 26 (WebInspector.BackForwardEntry): 27 (WebInspector.BackForwardEntry.prototype.get contentView): 28 (WebInspector.BackForwardEntry.prototype.get cookie): 29 (WebInspector.BackForwardEntry.prototype.prepareToShow): 30 (WebInspector.BackForwardEntry.prototype.prepareToHide): 31 (WebInspector.BackForwardEntry.prototype._restoreFromCookie): 32 (WebInspector.BackForwardEntry.prototype._restoreScrollPositions): 33 (WebInspector.BackForwardEntry.prototype._saveScrollPositions): 34 * UserInterface/ContentBrowser.js: 35 (WebInspector.ContentBrowser.prototype.showContentView): 36 (WebInspector.ContentBrowser.prototype._updateContentViewNavigationItems): 37 (WebInspector.ContentBrowser.prototype._updateFindBanner): 38 * UserInterface/ContentViewContainer.js: 39 (WebInspector.ContentViewContainer.prototype.get currentContentView): 40 (WebInspector.ContentViewContainer.prototype.get currentBackForwardEntry): 41 (WebInspector.ContentViewContainer.prototype.showContentView): 42 (WebInspector.ContentViewContainer.prototype.showBackForwardEntryForIndex): 43 (WebInspector.ContentViewContainer.prototype.replaceContentView): 44 (WebInspector.ContentViewContainer.prototype.closeAllContentViewsOfPrototype): 45 (WebInspector.ContentViewContainer.prototype.closeAllContentViews): 46 (WebInspector.ContentViewContainer.prototype.goBack): 47 (WebInspector.ContentViewContainer.prototype.goForward): 48 (WebInspector.ContentViewContainer.prototype.shown): 49 (WebInspector.ContentViewContainer.prototype.hidden): 50 (WebInspector.ContentViewContainer.prototype._showEntry): 51 (WebInspector.ContentViewContainer.prototype._hideEntry): 52 * UserInterface/Main.html: 53 * UserInterface/Main.js: 54 (WebInspector.openURL): 55 * UserInterface/ResourceSidebarPanel.js: 56 (WebInspector.ResourceSidebarPanel.prototype.restoreCallback): 57 (WebInspector.ResourceSidebarPanel.prototype.showSourceCode): 58 1 59 2013-10-02 Antoine Quint <graouts@apple.com> 2 60 -
trunk/Source/WebInspectorUI/UserInterface/ContentBrowser.js
r156198 r156809 158 158 }, 159 159 160 showContentView: function(contentView )161 { 162 return this._contentViewContainer.showContentView(contentView );160 showContentView: function(contentView, cookie, restoreCallback) 161 { 162 return this._contentViewContainer.showContentView(contentView, cookie, restoreCallback); 163 163 }, 164 164 … … 412 412 // Go through each of the items of the new content view and add a divider before them. 413 413 currentContentView.navigationItems.forEach(function(navigationItem, index) { 414 // Add dividers before items unless it's the first item and not a button. 414 // Add dividers before items unless it's the first item and not a button. 415 415 if (index !== 0 || navigationItem instanceof WebInspector.ButtonNavigationItem) { 416 416 var divider = new WebInspector.DividerNavigationItem; … … 434 434 return; 435 435 } 436 436 437 437 this._findBanner.targetElement = currentContentView.element; 438 438 this._findBanner.numberOfResults = currentContentView.hasPerformedSearch ? currentContentView.numberOfSearchResults : null; -
trunk/Source/WebInspectorUI/UserInterface/ContentViewContainer.js
r156727 r156809 65 65 if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1) 66 66 return null; 67 return this._backForwardList[this._currentIndex].contentView; 68 }, 69 70 get currentBackForwardEntry() 71 { 72 if (this._currentIndex < 0 || this._currentIndex > this._backForwardList.length - 1) 73 return null; 67 74 return this._backForwardList[this._currentIndex]; 68 75 }, … … 127 134 }, 128 135 129 showContentView: function(contentView )136 showContentView: function(contentView, cookie, restoreCallback) 130 137 { 131 138 console.assert(contentView instanceof WebInspector.ContentView); … … 139 146 return null; 140 147 141 // Don't do anything if the content view is already the current content view. 142 var currentContentView = this.currentContentView; 143 if (currentContentView === contentView) 144 return contentView; 148 var currentEntry = this.currentBackForwardEntry; 149 var provisionalEntry = new WebInspector.BackForwardEntry(contentView, cookie, restoreCallback); 150 // Don't do anything if we would have added an identical back/forward list entry. 151 if (currentEntry && currentEntry.contentView === contentView && Object.shallowEqual(provisionalEntry.cookie, currentEntry.cookie)) 152 return currentEntry.contentView; 145 153 146 154 // Showing a content view will truncate the back/forward list after the current index and insert the content view … … 151 159 152 160 // Insert the content view at the new index. This will remove any content views greater than or equal to the index. 153 var removed Items = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, contentView);161 var removedEntries = this._backForwardList.splice(newIndex, this._backForwardList.length - newIndex, provisionalEntry); 154 162 155 163 console.assert(newIndex === this._backForwardList.length - 1); 156 console.assert(this._backForwardList[newIndex] === contentView);164 console.assert(this._backForwardList[newIndex] === provisionalEntry); 157 165 158 166 // Disassociate with the removed content views. 159 for (var i = 0; i < removed Items.length; ++i) {167 for (var i = 0; i < removedEntries.length; ++i) { 160 168 // Skip disassociation if this content view is still in the back/forward list. 161 if (this._backForwardList.contains(removedItems[i])) 162 continue; 163 164 this._disassociateFromContentView(removedItems[i]); 169 var shouldDissociateContentView = this._backForwardList.some(function(existingEntry) { 170 return existingEntry.contentView === removedEntries[i].contentView; 171 }); 172 if (shouldDissociateContentView) 173 this._disassociateFromContentView(removedEntries[i]); 165 174 } 166 175 … … 168 177 contentView._parentContainer = this; 169 178 170 this.showBackForwardEntry (newIndex);179 this.showBackForwardEntryForIndex(newIndex); 171 180 172 181 return contentView; 173 182 }, 174 183 175 showBackForwardEntry : function(index)184 showBackForwardEntryForIndex: function(index) 176 185 { 177 186 console.assert(index >= 0 && index <= this._backForwardList.length - 1); … … 183 192 184 193 // Hide the currently visible content view. 185 var currentContentView = this.currentContentView;186 if ( currentContentView)187 this._hide ContentView(currentContentView);194 var previousEntry = this.currentBackForwardEntry; 195 if (previousEntry) 196 this._hideEntry(previousEntry); 188 197 189 198 this._currentIndex = index; 190 191 this._showContentView(this.currentContentView); 199 var currentEntry = this.currentBackForwardEntry; 200 console.assert(currentEntry); 201 202 this._showEntry(currentEntry); 192 203 193 204 this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange); … … 214 225 var currentlyShowing = (this.currentContentView === oldContentView); 215 226 if (currentlyShowing) 216 this._hide ContentView(oldContentView);227 this._hideEntry(this.currentBackForwardEntry); 217 228 218 229 // Disassociate with the old content view. … … 224 235 // Replace all occurrences of oldContentView with newContentView in the back/forward list. 225 236 for (var i = 0; i < this._backForwardList.length; ++i) { 226 if (this._backForwardList[i] === oldContentView) 227 this._backForwardList[i] = newContentView; 228 } 229 237 if (this._backForwardList[i].contentView === oldContentView) 238 this._backForwardList[i].contentView = newContentView; 239 } 240 241 // Re-show the current entry, because its content view instance was replaced. 230 242 if (currentlyShowing) { 231 this._show ContentView(newContentView);243 this._showEntry(this.currentBackForwardEntry); 232 244 this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange); 233 245 } … … 245 257 var allSamePrototype = true; 246 258 for (var i = this._backForwardList.length - 1; i >= 0; --i) { 247 if (!(this._backForwardList[i] instanceof constructor)) {259 if (!(this._backForwardList[i].contentView instanceof constructor)) { 248 260 allSamePrototype = false; 249 261 break; … … 261 273 // Hide and disassociate with all the content views that are instances of the constructor. 262 274 for (var i = this._backForwardList.length - 1; i >= 0; --i) { 263 var contentView= this._backForwardList[i];264 if (!( contentView instanceof constructor))275 var entry = this._backForwardList[i]; 276 if (!(entry.contentView instanceof constructor)) 265 277 continue; 266 278 267 if ( contentView === oldCurrentContentView)268 this._hide ContentView(contentView);279 if (entry.contentView === oldCurrentContentView) 280 this._hideEntry(entry); 269 281 270 282 if (this._currentIndex >= i) { … … 274 286 } 275 287 276 this._disassociateFromContentView( contentView);288 this._disassociateFromContentView(entry.contentView); 277 289 278 290 // Remove the item from the back/forward list. … … 281 293 } 282 294 283 var current ContentView = this.currentContentView;284 console.assert(current ContentView || (!currentContentView&& this._currentIndex === -1));285 286 if (current ContentView && (currentContentView !== oldCurrentContentView || backForwardListDidChange)) {287 this._show ContentView(currentContentView);295 var currentEntry = this.currentBackForwardEntry; 296 console.assert(currentEntry || (!currentEntry && this._currentIndex === -1)); 297 298 if (currentEntry && currentEntry.contentView !== oldCurrentContentView || backForwardListDidChange) { 299 this._showEntry(currentEntry); 288 300 this.dispatchEventToListeners(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange); 289 301 } … … 299 311 // Hide and disassociate with all the content views. 300 312 for (var i = 0; i < this._backForwardList.length; ++i) { 301 var contentView= this._backForwardList[i];313 var entry = this._backForwardList[i]; 302 314 if (i === this._currentIndex) 303 this._hide ContentView(contentView);304 this._disassociateFromContentView( contentView);315 this._hideEntry(entry); 316 this._disassociateFromContentView(entry.contentView); 305 317 } 306 318 … … 325 337 if (!this.canGoBack()) 326 338 return; 327 this.showBackForwardEntry (this._currentIndex - 1);339 this.showBackForwardEntryForIndex(this._currentIndex - 1); 328 340 }, 329 341 … … 332 344 if (!this.canGoForward()) 333 345 return; 334 this.showBackForwardEntry (this._currentIndex + 1);346 this.showBackForwardEntryForIndex(this._currentIndex + 1); 335 347 }, 336 348 337 349 shown: function() 338 350 { 339 var current ContentView = this.currentContentView;340 if (!current ContentView)341 return; 342 343 this._show ContentView(currentContentView);351 var currentEntry = this.currentBackForwardEntry; 352 if (!currentEntry) 353 return; 354 355 this._showEntry(currentEntry); 344 356 }, 345 357 346 358 hidden: function() 347 359 { 348 var current ContentView = this.currentContentView;349 if (!current ContentView)350 return; 351 352 this._hide ContentView(currentContentView);360 var currentEntry = this.currentBackForwardEntry; 361 if (!currentEntry) 362 return; 363 364 this._hideEntry(currentEntry); 353 365 }, 354 366 … … 382 394 }, 383 395 384 _saveScrollPositionsForContentView: function(contentView) 385 { 386 var scrollableElements = contentView.scrollableElements || []; 387 for (var i = 0; i < scrollableElements.length; ++i) { 388 var element = scrollableElements[i]; 389 if (!element) 390 continue; 391 if (contentView.shouldKeepElementsScrolledToBottom) 392 element._savedIsScrolledToBottom = element.isScrolledToBottom(); 393 element._savedScrollTop = element.scrollTop; 394 element._savedScrollLeft = element.scrollLeft; 395 } 396 }, 397 398 _restoreScrollPositionsForContentView: function(contentView) 399 { 400 var scrollableElements = contentView.scrollableElements || []; 401 for (var i = 0; i < scrollableElements.length; ++i) { 402 var element = scrollableElements[i]; 403 if (!element) 404 continue; 405 406 // Restore the top scroll position by either scrolling to the bottom or to the saved position. 407 element.scrollTop = element._savedIsScrolledToBottom ? element.scrollHeight : element._savedScrollTop; 408 409 // Don't restore the left scroll position when scrolled to the bottom. This way the when content changes 410 // the user won't be left in a weird horizontal position. 411 element.scrollLeft = element._savedIsScrolledToBottom ? 0 : element._savedScrollLeft; 412 } 413 }, 414 415 _showContentView: function(contentView) 416 { 417 if (contentView.visible) 418 return; 419 420 this._addContentViewElement(contentView); 421 422 this._prepareContentViewToShow(contentView); 423 }, 424 425 _prepareContentViewToShow: function(contentView) 426 { 427 this._restoreScrollPositionsForContentView(contentView); 428 429 contentView.visible = true; 430 contentView.shown(); 431 contentView.updateLayout(); 432 }, 433 434 _hideContentView: function(contentView) 435 { 436 if (!contentView.visible) 437 return; 438 439 this._prepareContentViewToHide(contentView); 440 441 this._removeContentViewElement(contentView); 442 }, 443 444 _prepareContentViewToHide: function(contentView) 445 { 446 contentView.visible = false; 447 contentView.hidden(); 448 449 this._saveScrollPositionsForContentView(contentView); 396 _showEntry: function(entry) 397 { 398 console.assert(entry instanceof WebInspector.BackForwardEntry); 399 400 this._addContentViewElement(entry.contentView); 401 entry.prepareToShow(); 402 }, 403 404 _hideEntry: function(entry) 405 { 406 console.assert(entry instanceof WebInspector.BackForwardEntry); 407 408 entry.prepareToHide(); 409 this._removeContentViewElement(entry.contentView); 450 410 } 451 411 }; -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r155134 r156809 240 240 <script src="EventHandler.js"></script> 241 241 <script src="SourceCodeTextEditor.js"></script> 242 <script src="BackForwardEntry.js"></script> 242 243 <script src="ContentViewContainer.js"></script> 243 244 <script src="ContentView.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Main.js
r156198 r156809 512 512 var resource = frame.url === url ? frame.mainResource : frame.resourceForURL(url, searchChildFrames); 513 513 if (resource) { 514 this.resourceSidebarPanel.showSourceCode(resource, lineNumber); 514 var position = new WebInspector.SourceCodePosition(lineNumber, 0); 515 this.resourceSidebarPanel.showSourceCode(resource, position); 515 516 return; 516 517 } -
trunk/Source/WebInspectorUI/UserInterface/ResourceSidebarPanel.js
r156198 r156809 249 249 showSourceCode: function(sourceCode, positionToReveal, textRangeToSelect, forceUnformatted) 250 250 { 251 console.assert(!positionToReveal || positionToReveal instanceof WebInspector.SourceCodePosition, positionToReveal); 251 252 var representedObject = sourceCode; 252 253 … … 260 261 representedObject = representedObject.parentFrame; 261 262 262 var contentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject); 263 264 if (contentView instanceof WebInspector.FrameContentView) 265 contentView.showSourceCode(positionToReveal, textRangeToSelect, forceUnformatted); 266 else if (contentView instanceof WebInspector.ResourceClusterContentView) 267 contentView.showResponse(positionToReveal, textRangeToSelect, forceUnformatted); 268 else if (contentView instanceof WebInspector.ScriptContentView) 269 contentView.revealPosition(positionToReveal, textRangeToSelect, forceUnformatted); 270 271 WebInspector.contentBrowser.showContentView(contentView); 263 var newContentView = WebInspector.contentBrowser.contentViewForRepresentedObject(representedObject); 264 var cookie = {lineNumber: positionToReveal.lineNumber, columnNumber: positionToReveal.columnNumber}; 265 266 var restoreCallback = function(contentView, savedCookie) { 267 var lineNumber = savedCookie.lineNumber; 268 var columnNumber = savedCookie.columnNumber; 269 var position = new WebInspector.SourceCodePosition(lineNumber, columnNumber); 270 271 if (contentView instanceof WebInspector.FrameContentView) 272 contentView.showSourceCode(position) 273 else if (contentView instanceof WebInspector.ResourceClusterContentView) 274 contentView.showResponse(position) 275 else if (contentView instanceof WebInspector.ScriptContentView) 276 contentView.revealPosition(position) 277 }; 278 279 WebInspector.contentBrowser.showContentView(newContentView, cookie, restoreCallback); 272 280 }, 273 281
Note: See TracChangeset
for help on using the changeset viewer.