Reviewed by Tim H.
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Oct 2006 04:35:41 +0000 (04:35 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Oct 2006 04:35:41 +0000 (04:35 +0000)
        Bug 9778: http://bugs.webkit.org/show_bug.cgi?id=9778

        * ChangeLog:
        * Drosera/Drosera.xcodeproj/project.pbxproj: Added files
        * Drosera/English.lproj/Debugger.nib/info.nib: Resized the main window and WebView
        * Drosera/English.lproj/Debugger.nib/keyedobjects.nib: Resized the main window and WebView
        * Drosera/Images/SourceArrowOpen.png: Added.
        * Drosera/Images/fileIcon.jpg: Added.
        * Drosera/Images/siteCollapsed.tif: Added.
        * Drosera/Images/siteExpanded.tif: Added.
        * Drosera/Images/siteIcon.tif: Added.
        * Drosera/debugger.css: Added File Browser styles
        * Drosera/debugger.html: Added File Browser UI
        * Drosera/debugger.js: Added File Browser functionality

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16984 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
WebKitTools/ChangeLog
WebKitTools/Drosera/Drosera.xcodeproj/project.pbxproj
WebKitTools/Drosera/English.lproj/Debugger.nib/info.nib
WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib
WebKitTools/Drosera/Images/SourceArrowOpen.png [new file with mode: 0644]
WebKitTools/Drosera/Images/fileIcon.jpg [new file with mode: 0644]
WebKitTools/Drosera/Images/siteCollapsed.tif [new file with mode: 0644]
WebKitTools/Drosera/Images/siteExpanded.tif [new file with mode: 0644]
WebKitTools/Drosera/Images/siteIcon.tif [new file with mode: 0644]
WebKitTools/Drosera/debugger.css
WebKitTools/Drosera/debugger.html
WebKitTools/Drosera/debugger.js

index 4489934cad341c4660b3b25a7e29b7d9eb7897d1..4ae160e2ff736402fd7feb64e1a73ef2c7ad3f76 100644 (file)
@@ -1,3 +1,22 @@
+2006-10-10  Vladimir Olexa  <vladimir.olexa@gmail.com>
+
+        Reviewed by Tim H.
+
+        Bug 9778: http://bugs.webkit.org/show_bug.cgi?id=9778 
+
+        * ChangeLog:
+        * Drosera/Drosera.xcodeproj/project.pbxproj: Added files
+        * Drosera/English.lproj/Debugger.nib/info.nib: Resized the main window and WebView
+        * Drosera/English.lproj/Debugger.nib/keyedobjects.nib: Resized the main window and WebView
+        * Drosera/Images/SourceArrowOpen.png: Added.
+        * Drosera/Images/fileIcon.jpg: Added.
+        * Drosera/Images/siteCollapsed.tif: Added.
+        * Drosera/Images/siteExpanded.tif: Added.
+        * Drosera/Images/siteIcon.tif: Added.
+        * Drosera/debugger.css: Added File Browser styles
+        * Drosera/debugger.html: Added File Browser UI
+        * Drosera/debugger.js: Added File Browser functionality
+
 2006-10-10  Darin Adler  <darin@apple.com>
 
         * Scripts/do-file-rename: Added.
index f22bd1082a0112c26302341809ad7e5197a109f7..e7791fb7de63f366feccab8d850866699e1dbbfc 100644 (file)
@@ -7,6 +7,11 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               15CE85540ADBEA620078A734 /* fileIcon.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 15CE854F0ADBEA610078A734 /* fileIcon.jpg */; };
+               15CE85550ADBEA620078A734 /* siteCollapsed.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85500ADBEA610078A734 /* siteCollapsed.tif */; };
+               15CE85560ADBEA620078A734 /* siteExpanded.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85510ADBEA610078A734 /* siteExpanded.tif */; };
+               15CE85570ADBEA620078A734 /* siteIcon.tif in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85520ADBEA610078A734 /* siteIcon.tif */; };
+               15CE85580ADBEA620078A734 /* SourceArrowOpen.png in Resources */ = {isa = PBXBuildFile; fileRef = 15CE85530ADBEA610078A734 /* SourceArrowOpen.png */; };
                1C2632D30A4AF0A800EA7CD8 /* verticalSplitterBar.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D10A4AF0A800EA7CD8 /* verticalSplitterBar.tiff */; };
                1C2632D40A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D20A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff */; };
                1C2632D70A4AF0B800EA7CD8 /* SourceArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 1C2632D50A4AF0B800EA7CD8 /* SourceArrow.png */; };
 /* Begin PBXFileReference section */
                1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
                13E42FBA07B3F13500E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+               15CE854F0ADBEA610078A734 /* fileIcon.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = fileIcon.jpg; sourceTree = "<group>"; };
+               15CE85500ADBEA610078A734 /* siteCollapsed.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = siteCollapsed.tif; sourceTree = "<group>"; };
+               15CE85510ADBEA610078A734 /* siteExpanded.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = siteExpanded.tif; sourceTree = "<group>"; };
+               15CE85520ADBEA610078A734 /* siteIcon.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = siteIcon.tif; sourceTree = "<group>"; };
+               15CE85530ADBEA610078A734 /* SourceArrowOpen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SourceArrowOpen.png; sourceTree = "<group>"; };
                1C2632D10A4AF0A800EA7CD8 /* verticalSplitterBar.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = verticalSplitterBar.tiff; sourceTree = "<group>"; };
                1C2632D20A4AF0A800EA7CD8 /* verticalSplitterDimple.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = verticalSplitterDimple.tiff; sourceTree = "<group>"; };
                1C2632D50A4AF0B800EA7CD8 /* SourceArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = SourceArrow.png; sourceTree = "<group>"; };
                1CC058B70A44A210006FE533 /* Images */ = {
                        isa = PBXGroup;
                        children = (
+                               15CE854F0ADBEA610078A734 /* fileIcon.jpg */,
+                               15CE85500ADBEA610078A734 /* siteCollapsed.tif */,
+                               15CE85510ADBEA610078A734 /* siteExpanded.tif */,
+                               15CE85520ADBEA610078A734 /* siteIcon.tif */,
+                               15CE85530ADBEA610078A734 /* SourceArrowOpen.png */,
                                1C6F84510A58EDFE004FCD89 /* console.png */,
                                1C4FF7530A44F6320000D05D /* gutter.png */,
                                1C4FF91F0A45F3520000D05D /* glossyHeader.png */,
                2A37F4A9FDCFA73011CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = C05733CB08A9546B00998B17 /* Build configuration list for PBXProject "Drosera" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        mainGroup = 2A37F4AAFDCFA73011CA2CEA /* SafariBug */;
                        projectDirPath = "";
+                       projectRoot = "";
+                       shouldCheckCompatibility = 1;
                        targets = (
                                8D15AC270486D014006FF6A4 /* Drosera */,
                                1CD8D54C0A4902B000E5677B /* Drosera (Nightly Launcher) */,
                                63A9E23F0AD4869300C079EE /* breakpointEditor.css in Resources */,
                                63A9E2400AD4869400C079EE /* breakpointEditor.html in Resources */,
                                63A9E2410AD4869400C079EE /* breakpointEditor.js in Resources */,
+                               15CE85540ADBEA620078A734 /* fileIcon.jpg in Resources */,
+                               15CE85550ADBEA620078A734 /* siteCollapsed.tif in Resources */,
+                               15CE85560ADBEA620078A734 /* siteExpanded.tif in Resources */,
+                               15CE85570ADBEA620078A734 /* siteIcon.tif in Resources */,
+                               15CE85580ADBEA620078A734 /* SourceArrowOpen.png in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 6d07d217914a7abebe7727cab2a875fa438eb78b..7564e3ec8e8bb238f6157365aec4e83a7c9ab443 100644 (file)
@@ -3,7 +3,7 @@
 <plist version="1.0">
 <dict>
        <key>IBDocumentLocation</key>
-       <string>751 149 356 240 0 0 1440 878 </string>
+       <string>907 177 356 240 0 0 1280 832 </string>
        <key>IBFramework Version</key>
        <string>446.1</string>
        <key>IBOpenObjects</key>
@@ -11,6 +11,6 @@
                <integer>5</integer>
        </array>
        <key>IBSystem Version</key>
-       <string>8I1119</string>
+       <string>8L127</string>
 </dict>
 </plist>
index 72c961a6afcbfaad46fc14811dae86498fa4448f..3978af2de91e2fe60fb39428d1ea66479369b1c8 100644 (file)
Binary files a/WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib and b/WebKitTools/Drosera/English.lproj/Debugger.nib/keyedobjects.nib differ
diff --git a/WebKitTools/Drosera/Images/SourceArrowOpen.png b/WebKitTools/Drosera/Images/SourceArrowOpen.png
new file mode 100644 (file)
index 0000000..4016402
Binary files /dev/null and b/WebKitTools/Drosera/Images/SourceArrowOpen.png differ
diff --git a/WebKitTools/Drosera/Images/fileIcon.jpg b/WebKitTools/Drosera/Images/fileIcon.jpg
new file mode 100644 (file)
index 0000000..c651a78
Binary files /dev/null and b/WebKitTools/Drosera/Images/fileIcon.jpg differ
diff --git a/WebKitTools/Drosera/Images/siteCollapsed.tif b/WebKitTools/Drosera/Images/siteCollapsed.tif
new file mode 100644 (file)
index 0000000..07d8a12
Binary files /dev/null and b/WebKitTools/Drosera/Images/siteCollapsed.tif differ
diff --git a/WebKitTools/Drosera/Images/siteExpanded.tif b/WebKitTools/Drosera/Images/siteExpanded.tif
new file mode 100644 (file)
index 0000000..8044385
Binary files /dev/null and b/WebKitTools/Drosera/Images/siteExpanded.tif differ
diff --git a/WebKitTools/Drosera/Images/siteIcon.tif b/WebKitTools/Drosera/Images/siteIcon.tif
new file mode 100644 (file)
index 0000000..d32654f
Binary files /dev/null and b/WebKitTools/Drosera/Images/siteIcon.tif differ
index 2469943af9f410bbb9b98c8a3935b6c1707bc723..0b511a62f4a885d1d6e81f9f9b7598342cc0a546 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2006 Vladimir Olexa (vladimir.olexa@gmail.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 img { padding: 0; margin: 0; }
 body { margin: 0; padding: 0; overflow: hidden; }
 
-#main { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
+#fileBrowser { position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 220px;}
+#fileList { position: absolute; top: 0; bottom: 0; left: 0; right: 10px; padding: 0; margin: 0; }
+#filesDivider { position: absolute; z-index: 10; right: 0px; bottom: 0px; top: 0; width: 10px; cursor: col-resize; background: url(verticalSplitterDimple.tiff) 50% no-repeat, url(verticalSplitterBar.tiff) repeat-y; width: 10px; }
+#masterMain { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
+#main { position: absolute; top: 0; bottom: 0; left: 220px; right: 0; }
 #info { position: absolute; top: 0; height: 175px; left: 0; right: 0; }
 #divider { cursor: row-resize; position: absolute; bottom: 0; left: 0; right: 0; background: url(splitterDimple.tif) 50% no-repeat, url(splitterBar.tif) repeat-x; height: 10px }
 #body { position: absolute; top: 175px; left: 0; right: 0; bottom: 0; }
@@ -37,9 +42,66 @@ body { margin: 0; padding: 0; overflow: hidden; }
 #sources { width: 100%; height: 100% }
 #header { vertical-align: top; height: 16px; box-sizing: border-box; border-bottom: 1px solid #aaa; background: url(glossyHeader.png) repeat-x; position: absolute; top: 0; left: 0; right: 0; }
 #header > * { vertical-align: top; }
-#footer { height: 21px; box-sizing: border-box; border-top: 1px solid #aaa; background: url(glossyFooterFill.tif) repeat-x; position: absolute; bottom: 0; left: 0; right: 0; }
+.footer { height: 21px; box-sizing: border-box; border-top: 1px solid #aaa; background: url(glossyFooterFill.tif) repeat-x; position: absolute; bottom: 0; left: 0; right: 0; }
 #infoDivider { position: absolute; z-index: 10; right: 0; left: 0; top: 0; bottom: 9px; width: 10px; cursor: col-resize; background: url(verticalSplitterDimple.tiff) 50% no-repeat, url(verticalSplitterBar.tiff) repeat-y; width: 10px; }
 
+#filesBrowserSites {
+    position: absolute;
+    font-family: "Lucida Grande", sans-serif;
+    font-size: 11px;
+    padding: 2px;
+    overflow-x: hidden;
+    overflow-y: auto;
+    top: 16px;
+    left: 0;
+    right: 0;
+    bottom: 21px;
+    background-color: white;
+}
+
+#filesBrowserSites div {
+    font-weight: normal;
+    overflow: hidden;
+    white-space: nowrap;
+    padding-left: 26px;
+    background: url(siteExpanded.tif) no-repeat 0px 0px;
+    cursor: default;
+    margin-bottom: 2px;
+}
+
+#filesBrowserSites div.expanded {
+    background: url(siteExpanded.tif) no-repeat 0px 0px;
+}
+#filesBrowserSites div.collapsed {
+    background: url(siteCollapsed.tif) no-repeat 0px 0px;
+}
+
+#filesBrowserSites div ul {
+    margin: 0;
+    padding: 0;
+    list-style-type: none;
+    font-weight: normal;
+}
+
+#filesBrowserSites div ul li {
+    margin-left: -25px;
+    height: 15px;
+    padding-left: 38px;
+    margin-top: 1px;
+    margin-bottom: 1px;
+    background: url(fileIcon.jpg) no-repeat 26px 0%;
+    cursor: default;
+    overflow: hidden;    
+}
+
+#filesBrowserSites div ul li.active {
+    background-color: #ccc;
+}
+
+#filesBrowserSites div ul li.passive {
+    background-color: white;
+}
+
 #files {
     opacity: 0;
     position: absolute;
@@ -247,4 +309,4 @@ tr.current {
     padding: 0 8px;
     text-align: left;
     -webkit-user-select: none;
-}
+}
\ No newline at end of file
index c998a928ffd84f7c6e75d00a8818fe6261a44860..195a9df14ea89ef0734bb16bb483c0163aad13bc 100644 (file)
@@ -1,5 +1,6 @@
 <!--
 Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+Copyright (C) 2006 Vladimir Olexa (vladimir.olexa@gmail.com)
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
@@ -36,6 +37,18 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     </style>
 </head>
 <body onload="loaded()">
+<div id="masterMain">
+<div id="fileBrowser">
+<div id="fileList">
+<table id="fileListTableHeader">
+<tr class="column"><th onmousedown="headerMouseDown(this);" onmouseup="headerMouseUp(this);" onmouseout="headerMouseOut(this);">Files</th><th class="scrollCorner"></th></tr>
+</table>
+<div id="filesBrowserSites">
+</div>
+<div class="footer"></div>
+</div>
+<div id="filesDivider"></div>
+</div>
 <div id="main">
 <div id="info">
 <div id="leftPane">
@@ -70,8 +83,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 <button class="popup"><select size="1" id="files" onchange="switchFile()"></select><div id="filesPopupButtonContent"><span class="placeholder">no files loaded</span></div></button>
 </div>
 <div id="sourcesContainer"><iframe id="sources" src="viewer.html"></iframe></div>
-<div id="footer"></div>
+<div class="footer"></div>
+</div>
 </div>
 </div>
 </body>
-</html>
+</html>
\ No newline at end of file
index 0ed00d189f85c4c5b5a3887767b476913377a41c..01b0c03913128ff784b6ca9bbf225c622808ee18 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
  * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2006 Vladimir Olexa (vladimir.olexa@gmail.com)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -108,6 +109,34 @@ function headerMouseOut(element) {
     element.style.background = "url(glossyHeader.png) repeat-x";
 }
 
+function filesDividerDragStart(event) 
+{
+    dividerDragStart(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event, "col-resize");
+}
+
+function filesDividerDragEnd(event) 
+{
+    dividerDragEnd(document.getElementById("filesDivider"), filesDividerDrag, filesDividerDragEnd, event);
+}
+
+function filesDividerDrag(event) 
+{
+    var element = document.getElementById("filesDivider");
+    if (document.getElementById("filesDivider").dragging == true) {
+        var masterMain = document.getElementById("masterMain");
+        var main = document.getElementById("main");
+        var fileBrowser = document.getElementById("fileBrowser");
+        var x = event.clientX + window.scrollX;
+        var delta = element.dragLastX - x;
+        var newWidth = constrainedWidthFromElement(fileBrowser.clientWidth - delta, masterMain, 0.1, 0.9);
+        if ((fileBrowser.clientWidth - delta) == newWidth) // the width wasn't constrained
+            element.dragLastX = x;
+        fileBrowser.style.width = newWidth + "px";
+        main.style.left = newWidth + "px";
+        event.preventDefault();
+    }
+}
+
 function dividerDragStart(element, dividerDrag, dividerDragEnd, event, cursor) {
     element.dragging = true;
     element.dragLastY = event.clientY + window.scrollY;
@@ -118,14 +147,63 @@ function dividerDragStart(element, dividerDrag, dividerDragEnd, event, cursor) {
     event.preventDefault();
 }
 
+function dividerDragEnd(element, dividerDrag, dividerDragEnd, event) {
+    element.dragging = false;
+    document.removeEventListener("mousemove", dividerDrag, true);
+    document.removeEventListener("mouseup", dividerDragEnd, true);
+    document.body.style.cursor = null;
+}
+
+function dividerDrag(event) {
+    var element = document.getElementById("divider");
+    if (document.getElementById("divider").dragging == true) {
+        var main = document.getElementById("main");
+        var top = document.getElementById("info");
+        var bottom = document.getElementById("body");
+        var y = event.clientY + window.scrollY;
+        var delta = element.dragLastY - y;
+        var newHeight = constrainedHeightFromElement(top.clientHeight - delta, main);
+        if ((top.clientHeight - delta) == newHeight) // the height wasn't constrained
+            element.dragLastY = y;
+        top.style.height = newHeight + "px";
+        bottom.style.top = newHeight + "px";
+        event.preventDefault();
+    }
+}
+
 function sourceDividerDragStart(event) {
     dividerDragStart(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event, "row-resize");
 }
 
+function sourceDividerDragEnd(event) {
+    dividerDragEnd(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event);
+}
+
 function infoDividerDragStart(event) {
     dividerDragStart(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event, "col-resize");
 }
 
+function infoDividerDragEnd(event) {
+    dividerDragEnd(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event);
+}
+
+function infoDividerDrag(event) {
+    var element = document.getElementById("infoDivider");
+    if (document.getElementById("infoDivider").dragging == true) {
+        var main = document.getElementById("main");
+        var leftPane = document.getElementById("leftPane");
+        var rightPane = document.getElementById("rightPane");
+        var x = event.clientX + window.scrollX;
+        var delta = element.dragLastX - x;
+        var newWidth = constrainedWidthFromElement(leftPane.clientWidth - delta, main);
+        if ((leftPane.clientWidth - delta) == newWidth) // the width wasn't constrained
+            element.dragLastX = x;
+        leftPane.style.width = newWidth + "px";
+        rightPane.style.left = newWidth + "px";
+        event.preventDefault();
+    }
+}
+
 function columnResizerDragStart(event) {
     isResizingColumn = true;
     dividerDragStart(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event, "col-resize");
@@ -136,21 +214,6 @@ function columnResizerDragEnd(event) {
     dividerDragEnd(document.getElementById("variableColumnResizer"), columnResizerDrag, columnResizerDragEnd, event);
 }
 
-function infoDividerDragEnd(event) {
-    dividerDragEnd(document.getElementById("infoDivider"), infoDividerDrag, infoDividerDragEnd, event);
-}
-
-function sourceDividerDragEnd(event) {
-    dividerDragEnd(document.getElementById("divider"), dividerDrag, sourceDividerDragEnd, event);
-}
-
-function dividerDragEnd(element, dividerDrag, dividerDragEnd, event) {
-    element.dragging = false;
-    document.removeEventListener("mousemove", dividerDrag, true);
-    document.removeEventListener("mouseup", dividerDragEnd, true);
-    document.body.style.cursor = null;
-}
-
 function columnResizerDrag(event) {
     var element = document.getElementById("variableColumnResizer");
     if (element.dragging == true) {
@@ -175,11 +238,14 @@ function columnResizerDrag(event) {
     }
 }
 
-function constrainedWidthFromElement(width, element) {
-    if (width < element.clientWidth * 0.25)
-        width = element.clientWidth * 0.25;
-    else if (width > element.clientWidth * 0.75)
-        width = element.clientWidth * 0.75;
+function constrainedWidthFromElement(width, element, constrainLeft, constrainRight) {
+    if (constrainLeft === undefined) constrainLeft = 0.25;
+    if (constrainRight === undefined) constrainRight = 0.75;
+    
+    if (width < element.clientWidth * constrainLeft)
+        width = element.clientWidth * constrainLeft;
+    else if (width > element.clientWidth * constrainRight)
+        width = element.clientWidth * constrainRight;
     return width;
 }
 
@@ -191,43 +257,10 @@ function constrainedHeightFromElement(height, element) {
     return height;
 }
 
-function infoDividerDrag(event) {
-    var element = document.getElementById("infoDivider");
-    if (document.getElementById("infoDivider").dragging == true) {
-        var main = document.getElementById("main");
-        var leftPane = document.getElementById("leftPane");
-        var rightPane = document.getElementById("rightPane");
-        var x = event.clientX + window.scrollX;
-        var delta = element.dragLastX - x;
-        var newWidth = constrainedWidthFromElement(leftPane.clientWidth - delta, main);
-        if ((leftPane.clientWidth - delta) == newWidth) // the width wasn't constrained
-            element.dragLastX = x;
-        leftPane.style.width = newWidth + "px";
-        rightPane.style.left = newWidth + "px";
-        event.preventDefault();
-    }
-}
-
-function dividerDrag(event) {
-    var element = document.getElementById("divider");
-    if (document.getElementById("divider").dragging == true) {
-        var main = document.getElementById("main");
-        var top = document.getElementById("info");
-        var bottom = document.getElementById("body");
-        var y = event.clientY + window.scrollY;
-        var delta = element.dragLastY - y;
-        var newHeight = constrainedHeightFromElement(top.clientHeight - delta, main);
-        if ((top.clientHeight - delta) == newHeight) // the height wasn't constrained
-            element.dragLastY = y;
-        top.style.height = newHeight + "px";
-        bottom.style.top = newHeight + "px";
-        event.preventDefault();
-    }
-}
-
 function loaded() {
     document.getElementById("divider").addEventListener("mousedown", sourceDividerDragStart, false);
     document.getElementById("infoDivider").addEventListener("mousedown", infoDividerDragStart, false);
+    document.getElementById("filesDivider").addEventListener("mousedown", filesDividerDragStart, false);
     document.getElementById("variableColumnResizer").addEventListener("mousedown", columnResizerDragStart, false);
 }
 
@@ -495,6 +528,7 @@ function totalOffsetTop(element, stop)
 function switchFile()
 {
     var filesSelect = document.getElementById("files");
+    fileClicked(filesSelect.options[filesSelect.selectedIndex].value, false);
     loadFile(filesSelect.options[filesSelect.selectedIndex].value, true);
 }
 
@@ -768,7 +802,8 @@ function loadFile(fileIndex, manageNavLists)
             break;
         }
     }
-
+    
+    
     if (manageNavLists) {
         nextFiles = new Array();
         if (currentFile != -1)
@@ -802,6 +837,124 @@ function updateFileSource(source, url, force)
     }
 }
 
+/**
+* ParsedURL - this object chops up full URL into two parts: 
+ * 1) The domain: everything from http:// to the end of the domain name
+ * 2) The relative path: everything after the domain
+ *
+ * @param string url URL to be processed
+ */
+function ParsedURL(url)
+{
+    // Since we're getting the URL from the browser, we're safe to assume the URL is already well formatted
+    // and so there is no need for more sophisticated regular expression here
+    var url_parts = url.match(/(http[s]?:\/\/(www)?\.?(\w|\.|-)+\w(:\d{1,5})?)\/?(.*)/);
+    
+    // the domain here is considered the whole http://www.example.org:8000 string for display purposes
+    this.domain = url_parts[1];
+    // the relative path is everything following the domain
+    this.relativePath = "/" + url_parts[5];
+}
+
+/**
+* SiteBrowser - modifies the file tree via DOM as new files are being open
+ *
+ */
+function SiteBrowser()
+{
+    var fileBrowser = document.getElementById("filesBrowserSites");
+    
+    this.addURL = function add(url, fileIndex)
+    {
+        var parsedURL = new ParsedURL(url);
+        var divs = fileBrowser.getElementsByTagName("div");
+        
+        if (divs.length == 0) { 
+            addNewDomain(parsedURL, fileIndex);
+        } else {
+            var isNew = true;
+            for (var i = 0; i < divs.length; i++) {
+                if (divs[i].id == parsedURL.domain) {
+                    var uls = divs[i].getElementsByTagName("ul");
+                    var ul = (uls.length > 0) ? uls[0] : document.createElement("ul");
+                    var li = document.createElement("li");
+                    
+                    li.id = fileIndex;
+                    li.addEventListener("click", fileBrowserMouseEvents, false);
+                    li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/";
+                    ul.appendChild(li);
+                    isNew = false;
+                    break;
+                }
+            }
+            if (isNew) {
+                addNewDomain(parsedURL, fileIndex);
+            }
+        }
+    }
+    
+    this.selectInitialFile = function sf()
+    {
+        if (currentFile == -1)
+            document.getElementById("1").className = "active";
+    }
+    
+    function addNewDomain(parsedURL, fileIndex)
+    {
+        var div = document.createElement("div");
+        var ul = document.createElement("ul");
+        var li = document.createElement("li");
+        
+        div.id = div.innerText = div.title = parsedURL.domain;
+        div.addEventListener("click", fileBrowserMouseEvents, false);
+        // Maybe we can add some roll-overs here...
+        //div.addEventListener("mouseover", fileBrowserMouseEvents, false);
+        //div.addEventListener("mouseout", fileBrowserMouseEvents, false);
+        li.id = fileIndex;
+        li.addEventListener("click", fileBrowserMouseEvents, false);
+        li.title = li.innerText = parsedURL.relativePath ? parsedURL.relativePath : "/";
+        ul.appendChild(li);
+        div.appendChild(ul);
+        fileBrowser.appendChild(div);        
+    }
+}
+
+function fileBrowserMouseEvents(event)
+{
+    switch (event.type)
+    {
+        case "click":
+            // If we clicked on a site, collapse/expand it, if on a file, display it. Since we're only capturing this
+            // event from either a DIV or LI element, we don't have to worry about any ambiguity
+            (event.target.nodeName.toUpperCase() == "DIV") ? toggleCollapseSite(event) : fileClicked(event.target.id);
+            break;
+    }
+}
+
+function fileClicked(fileId, shouldLoadFile)
+{
+    if (shouldLoadFile === undefined) shouldLoadFile = true;
+    
+    document.getElementById(currentFile).className  = "passive";
+    document.getElementById(fileId).className       = "active";
+    if (shouldLoadFile) 
+        loadFile(fileId, false);
+}
+
+function toggleCollapseSite(event)
+{
+    var thisSite = document.getElementById(event.target.id);
+    var siteFiles = thisSite.getElementsByTagName("ul");
+    
+    if (siteFiles[0].style.display == "block" || !siteFiles[0].style.display) {
+        siteFiles[0].style.display = "none";
+        thisSite.className = "collapsed"; 
+    } else {
+        siteFiles[0].style.display = "block";
+        thisSite.className = "expanded";
+    }
+}
+
 function didParseScript(source, fileSource, url, sourceId, baseLineNumber)
 {
     var fileIndex = filesLookup[url];
@@ -830,6 +983,11 @@ function didParseScript(source, fileSource, url, sourceId, baseLineNumber)
         option.value = fileIndex;
         option.text = (file.url ? file.url : "(unknown script)");
         filesSelect.appendChild(option);
+
+        var siteBrowser = new SiteBrowser();
+        siteBrowser.addURL(file.url, fileIndex);
+        siteBrowser.selectInitialFile();        
+        
         firstLoad = true;
     }
 
@@ -843,7 +1001,7 @@ function didParseScript(source, fileSource, url, sourceId, baseLineNumber)
         updateFileSource((fileSource.length ? fileSource : source), url, false);
 
     if (currentFile == -1)
-        loadFile(fileIndex, true);
+        loadFile(fileIndex, false);
 }
 
 function jumpToLine(sourceId, line)