+2007-11-24 Timothy Hatcher <timothy@apple.com>
+
+ Reviewed by Adam Roben.
+
+ Bug 16121: Web Inspector needs helper functions that pass a 'this' object to
+ addEventListener and setTimeout
+ http://bugs.webkit.org/show_bug.cgi?id=16121
+
+ Add Function.prototype.bind. This helper will return a wrapper function
+ that will call the original function with the supplied arguments
+ and using the supplied 'this' object.
+
+ * page/inspector/Database.js: Remove a use of setTimeout by
+ inheriting some common functions from Resource.
+ * page/inspector/DatabasePanel.js: Use the new bind function.
+ * page/inspector/ConsolePanel.js: Ditto.
+ * page/inspector/DocumentPanel.js: Ditto.
+ * page/inspector/NetworkPanel.js: Ditto.
+ * page/inspector/PropertiesSection.js: Ditto.
+ * page/inspector/Resource.js: Ditto.
+ * page/inspector/SidebarPane.js: Ditto.
+ * page/inspector/inspector.html: Moved Database.js after Resource.js,
+ now that Database.js uses it.
+ * page/inspector/inspector.js: Use the new bind function. Also
+ removed a setTimeout used for the localized strings code. There is
+ now a load event listener added to the localized strings script
+ element that will call WebInspector.loaded.
+ * page/inspector/utilities.js: Add Function.prototype.bind.
+
2007-11-24 Timothy Hatcher <timothy@apple.com>
Reviewed by Adam Roben.
this.messageList.className = "console-message-list";
this.element.appendChild(this.messageList);
- var console = this;
- this.messageList.addEventListener("click", function(event) { console.messageListClicked(event) }, true);
+ this.messageList.addEventListener("click", this.messageListClicked.bind(this), true);
this.consolePrompt = document.createElement("textarea");
this.consolePrompt.className = "console-prompt";
this.element.appendChild(this.consolePrompt);
- this.consolePrompt.addEventListener("keydown", function(event) { console.promptKeypress(event) }, false);
+ this.consolePrompt.addEventListener("keydown", this.promptKeypress.bind(this), false);
}
WebInspector.ConsolePanel.prototype = {
return WebInspector.resourceCategories.databases;
},
- updateTitleSoon: function()
- {
- if (this.updateTitleTimeout)
- return;
- var _self = this;
- this.updateTitleTimeout = setTimeout(function () { _self.updateTitle() }, 0);
- },
-
updateTitle: function()
{
delete this.updateTitleTimeout;
return this._panel;
},
- select: function()
- {
- WebInspector.navigateToResource(this);
- },
-
- deselect: function()
- {
- this.listItem.deselect(true);
- if (WebInspector.currentPanel === this._panel)
- WebInspector.currentPanel = null;
- },
-
- attach: function()
- {
- this.panel.attach();
- },
-
- detach: function()
- {
- if (this._panel)
- this.panel.detach();
- }
+ // Inherit the other functions from the Resource prototype.
+ updateTitleSoon: WebInspector.Resource.prototype.updateTitleSoon,
+ select: WebInspector.Resource.prototype.select,
+ deselect: WebInspector.Resource.prototype.deselect,
+ attach: WebInspector.Resource.prototype.attach,
+ detach: WebInspector.Resource.prototype.detach
}
this.queryPromptElement.className = "database-prompt";
this.element.appendChild(this.queryPromptElement);
- var panel = this;
- this.queryPromptElement.addEventListener("keydown", function(event) { panel.queryInputKeypress(event) }, false);
+ this.queryPromptElement.addEventListener("keydown", this.queryInputKeypress.bind(this), false);
this.queryPromptHistory = [];
this.queryPromptHistoryOffset = 0;
queryView.commandListElement.className = "database-command-list";
queryView.contentElement.appendChild(queryView.commandListElement);
+ var panel = this;
queryView.show = function()
{
panel.queryPromptElement.focus();
browseView.reloadTableElement.appendChild(document.createElement("img"));
browseView.reloadTableElement.className = "database-table-reload";
browseView.reloadTableElement.title = WebInspector.UIString("Reload");
- browseView.reloadTableElement.addEventListener("click", function() { panel.updateTableList(); panel.updateTableBrowser() }, false);
+ browseView.reloadTableElement.addEventListener("click", this.reloadClicked.bind(this), false);
browseView.show = function()
{
}
},
+ reloadClicked: function()
+ {
+ this.updateTableList();
+ this.updateTableBrowser();
+ },
+
updateTableList: function()
{
var browseView = this.views.browse;
var panel = this;
var changeTableFunction = function()
{
- var browseView = panel.views.browse;
var index = browseView.tableSelectElement.selectedIndex;
if (index != -1)
panel.currentTable = browseView.tableSelectElement.options[index].value;
domView.sidebarResizeElement = document.createElement("div");
domView.sidebarResizeElement.className = "sidebar-resizer-vertical sidebar-resizer-vertical-right";
- domView.sidebarResizeElement.addEventListener("mousedown", function(event) { panel.rightSidebarResizerDragStart(event) }, false);
+ domView.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);
domView.contentElement.appendChild(domView.sideContentElement);
domView.contentElement.appendChild(domView.sidebarElement);
if (document.body.offsetWidth <= 0) {
// The stylesheet hasn't loaded yet, so we need to update later.
- var panel = this;
- setTimeout(function() { panel.updateBreadcrumbSizes() }, 0);
+ setTimeout(this.updateBreadcrumbSizes.bind(this), 0);
return;
}
if (document.body.offsetWidth <= 0) {
// The stylesheet hasn't loaded yet, so we need to update later.
- var element = this;
- setTimeout(function() { element.updateSelection() }, 0);
+ setTimeout(this.updateSelection.bind(this), 0);
return;
}
onattach: function()
{
- var element = this;
- this.listItemElement.addEventListener("mousedown", function(event) { element.onmousedown(event) }, false);
+ this.listItemElement.addEventListener("mousedown", this.onmousedown.bind(this), false);
},
onpopulate: function()
this.resourcesElement = document.createElement("div");
this.resourcesElement.className = "network-resources";
- var panel = this;
- this.resourcesElement.addEventListener("click", function(event) { return panel.onClick(event) }, false);
+ this.resourcesElement.addEventListener("click", this.resourcesClicked.bind(this), false);
this.timelineElement.appendChild(this.resourcesElement);
var graphArea = document.createElement("div");
this.graphModeSelectElement = document.createElement("select");
this.graphModeSelectElement.className = "network-graph-mode";
- this.graphModeSelectElement.addEventListener("change", function(event) { return panel.onModeChange(event) }, false);
+ this.graphModeSelectElement.addEventListener("change", this.changeGraphMode.bind(this), false);
this.graphLabelElement.appendChild(this.graphModeSelectElement);
this.graphLabelElement.appendChild(document.createElement("br"));
this.updateTimelineDividersIfNeeded();
},
- onClick: function(event)
+ resourcesClicked: function(event)
{
// If the click wasn't inside a network resource row, ignore it.
var resourceElement = event.target.firstParentOrSelfWithClass("network-resource");
resourceElement.timelineEntry.toggleShowingInfo();
},
- onModeChange: function(event)
+ changeGraphMode: function(event)
{
this.updateSummaryGraph();
},
{
if ("sortTimelineEntriesTimeout" in this)
return;
-
- var _self = this;
- this.sortTimelineEntriesTimeout = setTimeout(function () { _self.sortTimelineEntriesIfNeeded() }, 500);
+ this.sortTimelineEntriesTimeout = setTimeout(this.sortTimelineEntriesIfNeeded.bind(this), 500);
},
sortTimelineEntriesIfNeeded: function()
{
if ("updateTimelineDividersTimeout" in this)
return;
-
- var _self = this;
- this.updateTimelineDividersTimeout = setTimeout(function () { _self.updateTimelineDividersIfNeeded() }, 500);
+ this.updateTimelineDividersTimeout = setTimeout(this.updateTimelineDividersIfNeeded.bind(this), 500);
},
updateTimelineDividersIfNeeded: function()
if (document.body.offsetWidth <= 0) {
// The stylesheet hasn't loaded yet, so we need to update later.
- var panel = this;
- setTimeout(function () { panel.updateTimelineDividersIfNeeded() }, 0);
+ setTimeout(this.updateTimelineDividersIfNeeded.bind(this), 0);
return;
}
{
if ("refreshAllTimelineEntriesTimeout" in this)
return;
-
- var _self = this;
- this.refreshAllTimelineEntriesTimeout = setTimeout(function () { _self.refreshAllTimelineEntries() }, 500, skipBoundryUpdate, skipTimelineSort, immediate);
+ this.refreshAllTimelineEntriesTimeout = setTimeout(this.refreshAllTimelineEntries.bind(this), 500, skipBoundryUpdate, skipTimelineSort, immediate);
},
refreshAllTimelineEntries: function(skipBoundryUpdate, skipTimelineSort, immediate)
{
if ("updateSummaryGraphTimeout" in this)
return;
-
- var _self = this;
- this.updateSummaryGraphTimeout = setTimeout(function () { _self.updateSummaryGraph() }, 500);
+ this.updateSummaryGraphTimeout = setTimeout(this.updateSummaryGraph.bind(this), 500);
},
updateSummaryGraph: function()
this.showingTipButton = this.resource.tips.length;
this.fileElement.insertBefore(this.tipButtonElement, this.fileElement.firstChild);
- var entry = this;
- this.tipButtonElement.addEventListener("click", function(event) { entry.toggleTipBalloon(event) }, false );
+ this.tipButtonElement.addEventListener("click", this.toggleTipBalloon.bind(this), false );
this.areaElement = document.createElement("div");
this.areaElement.className = "network-area";
this.headerElement.appendChild(this.titleElement);
this.headerElement.appendChild(this.subtitleElement);
-
- var section = this;
- this.headerElement.addEventListener("click", function() { section.expanded = !section.expanded; }, false);
+ this.headerElement.addEventListener("click", this.toggleExpanded.bind(this), false);
this.propertiesElement = document.createElement("ol");
this.propertiesElement.className = "properties";
return;
this._expanded = false;
this.element.removeStyleClass("expanded");
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
}
}
{
if (this.updateTitleTimeout)
return;
- var _self = this;
- this.updateTitleTimeout = setTimeout(function () { _self.updateTitle() }, 0);
+ this.updateTitleTimeout = setTimeout(this.updateTitle.bind(this), 0);
},
updateTitle: function()
this.titleElement = document.createElement("div");
this.titleElement.className = "title";
-
- var pane = this;
- this.titleElement.addEventListener("click", function() { pane.expanded = !pane.expanded; }, false);
+ this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false);
this.bodyElement = document.createElement("div");
this.bodyElement.className = "body";
this.element.removeStyleClass("expanded");
if (this.oncollapse)
this.oncollapse(this);
+ },
+
+ toggleExpanded: function()
+ {
+ this.expanded = !this.expanded;
}
}
<script type="text/javascript" src="utilities.js"></script>
<script type="text/javascript" src="treeoutline.js"></script>
<script type="text/javascript" src="inspector.js"></script>
- <script type="text/javascript" src="Database.js"></script>
<script type="text/javascript" src="Resource.js"></script>
<script type="text/javascript" src="ResourceCategory.js"></script>
+ <script type="text/javascript" src="Database.js"></script>
<script type="text/javascript" src="SidebarPane.js"></script>
<script type="text/javascript" src="PropertiesSection.js"></script>
<script type="text/javascript" src="MetricsSidebarPane.js"></script>
}
}
-WebInspector.setupLocalizedString = function(event)
-{
- var localizedStringsURL = InspectorController.localizedStringsURL();
- if (localizedStringsURL) {
- var localizedStringsScriptElement = document.createElement("script");
- localizedStringsScriptElement.type = "text/javascript";
- localizedStringsScriptElement.src = localizedStringsURL;
- document.getElementsByTagName("head").item(0).appendChild(localizedStringsScriptElement);
- }
-}
-
WebInspector.loaded = function()
{
this.fileOutline = new TreeOutline(document.getElementById("list"));
this.addMainEventListeners(document);
- window.addEventListener("unload", function(event) { WebInspector.windowUnload(event) }, true);
- window.addEventListener("resize", function(event) { WebInspector.windowResize(event) }, true);
+ window.addEventListener("unload", this.windowUnload.bind(this), true);
+ window.addEventListener("resize", this.windowResize.bind(this), true);
- document.addEventListener("mousedown", function(event) { WebInspector.changeFocus(event) }, true);
- document.addEventListener("focus", function(event) { WebInspector.changeFocus(event) }, true);
- document.addEventListener("keypress", function(event) { WebInspector.documentKeypress(event) }, true);
- document.addEventListener("beforecopy", function(event) { WebInspector.documentCanCopy(event) }, true);
- document.addEventListener("copy", function(event) { WebInspector.documentCopy(event) }, true);
+ document.addEventListener("mousedown", this.changeFocus.bind(this), true);
+ document.addEventListener("focus", this.changeFocus.bind(this), true);
+ document.addEventListener("keypress", this.documentKeypress.bind(this), true);
+ document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
+ document.addEventListener("copy", this.documentCopy.bind(this), true);
document.getElementById("back").title = WebInspector.UIString("Show previous panel.");
document.getElementById("forward").title = WebInspector.UIString("Show next panel.");
document.getElementById("search").setAttribute("placeholder", WebInspector.UIString("Search"));
- document.getElementById("back").addEventListener("click", function(event) { WebInspector.back() }, true);
- document.getElementById("forward").addEventListener("click", function(event) { WebInspector.forward() }, true);
+ document.getElementById("back").addEventListener("click", this.back.bind(this), true);
+ document.getElementById("forward").addEventListener("click", this.forward.bind(this), true);
this.updateBackForwardButtons();
- document.getElementById("attachToggle").addEventListener("click", function(event) { WebInspector.toggleAttach() }, true);
- document.getElementById("statusToggle").addEventListener("click", function(event) { WebInspector.toggleStatusArea() }, true);
- document.getElementById("sidebarResizeWidget").addEventListener("mousedown", WebInspector.sidebarResizerDragStart, true);
- document.getElementById("sidebarResizer").addEventListener("mousedown", WebInspector.sidebarResizerDragStart, true);
- document.getElementById("searchResultsResizer").addEventListener("mousedown", WebInspector.searchResultsResizerDragStart, false);
+ document.getElementById("attachToggle").addEventListener("click", this.toggleAttach.bind(this), true);
+ document.getElementById("statusToggle").addEventListener("click", this.toggleStatusArea.bind(this), true);
+
+ document.getElementById("sidebarResizeWidget").addEventListener("mousedown", this.sidebarResizerDragStart, true);
+ document.getElementById("sidebarResizer").addEventListener("mousedown", this.sidebarResizerDragStart, true);
+ document.getElementById("searchResultsResizer").addEventListener("mousedown", this.searchResultsResizerDragStart, true);
document.body.addStyleClass("detached");
var windowLoaded = function()
{
- WebInspector.setupLocalizedString(event);
-
- // Delay calling loaded to give time for the localized strings file to load.
- // Calling it too early will cause localized string lookups to fail.
- setTimeout(function() { WebInspector.loaded() }, 0);
+ var localizedStringsURL = InspectorController.localizedStringsURL();
+ if (localizedStringsURL) {
+ var localizedStringsScriptElement = document.createElement("script");
+ localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
+ localizedStringsScriptElement.type = "text/javascript";
+ localizedStringsScriptElement.src = localizedStringsURL;
+ document.getElementsByTagName("head").item(0).appendChild(localizedStringsScriptElement);
+ } else
+ WebInspector.loaded();
delete windowLoaded;
window.removeEventListener("load", windowLoaded, false);
Object.sortedProperties = function(obj)
{
var properties = [];
- for (var prop in obj) {
+ for (var prop in obj)
properties.push(prop);
- }
-
properties.sort();
return properties;
}
+Function.prototype.bind = function(thisObject)
+{
+ var func = this;
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) };
+}
+
Element.prototype.removeStyleClass = function(className)
{
// Test for the simple case before using a RegExp.
for (var node = this; node && (node !== document); node = node.parentNode)
if (node.nodeName.toLowerCase() === nodeName.toLowerCase())
return node;
-
return null;
}
for (var node = this; node && (node !== document); node = node.parentNode)
if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
return node;
-
return null;
}
{
if (!this.parentNode)
return null;
-
return this.parentNode.firstParentOrSelfWithClass(className);
}