| CODENOTIFIER | HelpYou are not signed inSign in |
Project: Firebug
Revision: 57
Author: joehewitt
Date: 01 Jul 2007 19:54:49
Changes:* Firebug for iPhone 0.1
Files:| ... | ...@@ -0,0 +1,261 @@ | |
| 1 | ||
| 2 | html, body { | |
| 3 | margin: 0; | |
| 4 | background: #FFFFFF; | |
| 5 | font-family: Lucida Grande, Tahoma, sans-serif; | |
| 6 | font-size: 11px; | |
| 7 | overflow: hidden; | |
| 8 | } | |
| 9 | ||
| 10 | a { | |
| 11 | text-decoration: none; | |
| 12 | } | |
| 13 | ||
| 14 | a:hover { | |
| 15 | text-decoration: underline; | |
| 16 | } | |
| 17 | ||
| 18 | h1 { | |
| 19 | margin: 0; | |
| 20 | font-size: 12px; | |
| 21 | } | |
| 22 | ||
| 23 | .toolbar { | |
| 24 | height: 16px; | |
| 25 | border-top: 1px solid ThreeDHighlight; | |
| 26 | border-bottom: 1px solid ThreeDShadow; | |
| 27 | padding: 2px 6px; | |
| 28 | background: ThreeDFace; | |
| 29 | } | |
| 30 | ||
| 31 | .toolbarRight { | |
| 32 | position: absolute; | |
| 33 | top: 4px; | |
| 34 | right: 6px; | |
| 35 | } | |
| 36 | ||
| 37 | #inner { | |
| 38 | position: absolute; | |
| 39 | width: 100%; | |
| 40 | height: 100%; | |
| 41 | } | |
| 42 | ||
| 43 | #log { | |
| 44 | overflow: auto; | |
| 45 | position: absolute; | |
| 46 | left: 0; | |
| 47 | width: 100%; | |
| 48 | } | |
| 49 | ||
| 50 | #commandLineBox { | |
| 51 | position: absolute; | |
| 52 | left: 0; | |
| 53 | width: 100%; | |
| 54 | height: 18px; | |
| 55 | border-top: 1px solid #CCCCCC; | |
| 56 | padding-top: 2px; | |
| 57 | } | |
| 58 | ||
| 59 | #commandPrefix { | |
| 60 | margin-left: 4px; | |
| 61 | font-family: Monaco, monospace; | |
| 62 | color: blue; | |
| 63 | } | |
| 64 | ||
| 65 | #commandLine { | |
| 66 | position: absolute; | |
| 67 | margin-left: 5px; | |
| 68 | width: 100%; | |
| 69 | height: 100%; | |
| 70 | border: none; | |
| 71 | font-family: Monaco, monospace; | |
| 72 | } | |
| 73 | ||
| 74 | /************************************************************************************************/ | |
| 75 | ||
| 76 | .logRow { | |
| 77 | position: relative; | |
| 78 | border-bottom: 1px solid #D7D7D7; | |
| 79 | padding: 2px 4px 1px 6px; | |
| 80 | background-color: #FFFFFF; | |
| 81 | } | |
| 82 | ||
| 83 | .logRow-command { | |
| 84 | font-family: Monaco, monospace; | |
| 85 | color: blue; | |
| 86 | } | |
| 87 | ||
| 88 | .logRow-text { | |
| 89 | font-family: Monaco, monospace; | |
| 90 | white-space: -moz-pre-wrap; | |
| 91 | } | |
| 92 | ||
| 93 | .objectBox-null { | |
| 94 | padding: 0 2px; | |
| 95 | border: 1px solid #666666; | |
| 96 | background-color: #888888; | |
| 97 | color: #FFFFFF; | |
| 98 | } | |
| 99 | ||
| 100 | .objectBox-string { | |
| 101 | font-family: Monaco, monospace; | |
| 102 | color: red; | |
| 103 | white-space: pre; | |
| 104 | } | |
| 105 | ||
| 106 | .objectBox-number { | |
| 107 | color: #000088; | |
| 108 | } | |
| 109 | ||
| 110 | .objectBox-function { | |
| 111 | font-family: Monaco, monospace; | |
| 112 | color: DarkGreen; | |
| 113 | } | |
| 114 | ||
| 115 | .objectBox-object { | |
| 116 | color: DarkGreen; | |
| 117 | font-weight: bold; | |
| 118 | } | |
| 119 | ||
| 120 | /************************************************************************************************/ | |
| 121 | ||
| 122 | .logRow-info, | |
| 123 | .logRow-error, | |
| 124 | .logRow-warning { | |
| 125 | background: #FFFFFF no-repeat 2px 2px; | |
| 126 | padding-left: 20px; | |
| 127 | padding-bottom: 3px; | |
| 128 | } | |
| 129 | ||
| 130 | .logRow-info { | |
| 131 | background-image: url(infoIcon.png); | |
| 132 | } | |
| 133 | ||
| 134 | .logRow-warning { | |
| 135 | background-color: cyan; | |
| 136 | background-image: url(warningIcon.png); | |
| 137 | } | |
| 138 | ||
| 139 | .logRow-error { | |
| 140 | background-color: LightYellow; | |
| 141 | background-image: url(errorIcon.png); | |
| 142 | } | |
| 143 | ||
| 144 | .errorMessage { | |
| 145 | vertical-align: top; | |
| 146 | color: #FF0000; | |
| 147 | } | |
| 148 | ||
| 149 | .objectBox-sourceLink { | |
| 150 | position: absolute; | |
| 151 | right: 4px; | |
| 152 | top: 2px; | |
| 153 | padding-left: 8px; | |
| 154 | font-family: Lucida Grande, sans-serif; | |
| 155 | font-weight: bold; | |
| 156 | color: #0000FF; | |
| 157 | } | |
| 158 | ||
| 159 | /************************************************************************************************/ | |
| 160 | ||
| 161 | .logRow-group { | |
| 162 | background: #EEEEEE; | |
| 163 | border-bottom: none; | |
| 164 | } | |
| 165 | ||
| 166 | .logGroup { | |
| 167 | background: #EEEEEE; | |
| 168 | } | |
| 169 | ||
| 170 | .logGroupBox { | |
| 171 | margin-left: 24px; | |
| 172 | border-top: 1px solid #D7D7D7; | |
| 173 | border-left: 1px solid #D7D7D7; | |
| 174 | } | |
| 175 | ||
| 176 | /************************************************************************************************/ | |
| 177 | ||
| 178 | .selectorTag, | |
| 179 | .selectorId, | |
| 180 | .selectorClass { | |
| 181 | font-family: Monaco, monospace; | |
| 182 | font-weight: normal; | |
| 183 | } | |
| 184 | ||
| 185 | .selectorTag { | |
| 186 | color: #0000FF; | |
| 187 | } | |
| 188 | ||
| 189 | .selectorId { | |
| 190 | color: DarkBlue; | |
| 191 | } | |
| 192 | ||
| 193 | .selectorClass { | |
| 194 | color: red; | |
| 195 | } | |
| 196 | ||
| 197 | /************************************************************************************************/ | |
| 198 | ||
| 199 | .objectBox-element { | |
| 200 | font-family: Monaco, monospace; | |
| 201 | color: #000088; | |
| 202 | } | |
| 203 | ||
| 204 | .nodeChildren { | |
| 205 | margin-left: 16px; | |
| 206 | } | |
| 207 | ||
| 208 | .nodeTag { | |
| 209 | color: blue; | |
| 210 | } | |
| 211 | ||
| 212 | .nodeValue { | |
| 213 | color: #FF0000; | |
| 214 | font-weight: normal; | |
| 215 | } | |
| 216 | ||
| 217 | .nodeText, | |
| 218 | .nodeComment { | |
| 219 | margin: 0 2px; | |
| 220 | vertical-align: top; | |
| 221 | } | |
| 222 | ||
| 223 | .nodeText { | |
| 224 | color: #333333; | |
| 225 | } | |
| 226 | ||
| 227 | .nodeComment { | |
| 228 | color: DarkGreen; | |
| 229 | } | |
| 230 | ||
| 231 | /************************************************************************************************/ | |
| 232 | ||
| 233 | .propertyNameCell { | |
| 234 | vertical-align: top; | |
| 235 | } | |
| 236 | ||
| 237 | .propertyName { | |
| 238 | font-weight: bold; | |
| 239 | } | |
| 240 | ||
| 241 | /************************************************************************************************/ | |
| 242 | ||
| 243 | .arrayLeftBracket, | |
| 244 | .arrayRightBracket, | |
| 245 | .arrayComma { | |
| 246 | font-family: Monaco, monospace; | |
| 247 | } | |
| 248 | ||
| 249 | .arrayLeftBracket, | |
| 250 | .arrayRightBracket { | |
| 251 | font-weight: bold; | |
| 252 | } | |
| 253 | ||
| 254 | .arrayLeftBracket { | |
| 255 | margin-right: 4px; | |
| 256 | } | |
| 257 | ||
| 258 | .arrayRightBracket { | |
| 259 | margin-left: 4px; | |
| 260 | } | |
| 261 |
| ... | ...@@ -0,0 +1,27 @@ | |
| 1 | <html> | |
| 2 | <head></head> | |
| 3 | <body> | |
| 4 | <script type="application/x-javascript"> | |
| 5 | ||
| 6 | var host = window.location.host; | |
| 7 | ||
| 8 | function command(text) | |
| 9 | { | |
| 10 | parent.console.command(text); | |
| 11 | } | |
| 12 | ||
| 13 | function respond(text) | |
| 14 | { | |
| 15 | // Send the message using an img instead of XMLHttpRequest to avoid cross-domain security | |
| 16 | var img = document.createElement("img"); | |
| 17 | img.style.visibility = "hidden"; | |
| 18 | document.body.appendChild(img); | |
| 19 | img.onerror = function() { img.parentNode.removeChild(img); } | |
| 20 | ||
| 21 | var message = escape(text); | |
| 22 | img.src = "http://" + host + "/response?message=" + message; | |
| 23 | } | |
| 24 | ||
| 25 | parent.console.respond = respond; | |
| 26 | ||
| 27 | </script> |
| ... | ...@@ -0,0 +1,187 @@ | |
| 1 | ||
| 2 | from urlparse import urlparse | |
| 3 | from cgi import parse_qs | |
| 4 | from urllib import unquote | |
| 5 | import signal, thread, threading, time | |
| 6 | import BaseHTTPServer, SocketServer, mimetypes | |
| 7 | ||
| 8 | # ************************************************************************************************** | |
| 9 | # Globals | |
| 10 | ||
| 11 | global done, server, consoleCommand, phoneResponse | |
| 12 | ||
| 13 | done = False | |
| 14 | server = None | |
| 15 | phoneResponseEvent = threading.Event() | |
| 16 | consoleEvent = threading.Event() | |
| 17 | ||
| 18 | webPort = 1840 | |
| 19 | ||
| 20 | # ************************************************************************************************** | |
| 21 | ||
| 22 | class WebServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): | |
| 23 | pass | |
| 24 | ||
| 25 | class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | |
| 26 | def do_GET(self): | |
| 27 | #print "%s" % self.path | |
| 28 | ||
| 29 | host, path, params, query = parseURL(self.path) | |
| 30 | ||
| 31 | if path == "/command": | |
| 32 | postConsoleCommand(query.get("message")) | |
| 33 | response = waitForPhoneResponse() | |
| 34 | ||
| 35 | self.respond(200, "application/x-javascript") | |
| 36 | self << response | |
| 37 | ||
| 38 | elif path == "/response": | |
| 39 | postPhoneResponse(query.get("message")) | |
| 40 | ||
| 41 | elif path == "/browser": | |
| 42 | self.respond(200, "text/html") | |
| 43 | self << getFormattedFile("browser.html") | |
| 44 | self.wfile.flush() | |
| 45 | ||
| 46 | while 1: | |
| 47 | message = waitForPhoneResponse() | |
| 48 | self << "<script>command('%s')</script>" % escapeJavaScript(message) | |
| 49 | self.wfile.flush() | |
| 50 | ||
| 51 | elif path == "/phone": | |
| 52 | self.respond(200, "text/html") | |
| 53 | self << getFormattedFile("phone.html") | |
| 54 | self.wfile.flush() | |
| 55 | ||
| 56 | while 1: | |
| 57 | message = waitForConsoleCommand() | |
| 58 | self << "<script>command('%s')</script>" % escapeJavaScript(message) | |
| 59 | self.wfile.flush() | |
| 60 | ||
| 61 | elif path == "/ibug.js": | |
| 62 | header = "var ibugHost = '%(hostName)s:%(port)s';" % getHostInfo() | |
| 63 | self.sendFile("ibug.js", header=header) | |
| 64 | ||
| 65 | else: | |
| 66 | self.sendFile(path[1:]) | |
| 67 | ||
| 68 | def respond(self, code=200, mimeType="text/plain"): | |
| 69 | self << "HTTP/1.1 %s %s\n" % (code, "OK") | |
| 70 | self << "Content-Type: %s\n" % mimeType | |
| 71 | self << "\n" | |
| 72 | ||
| 73 | def sendFile(self, path, mimeType=None, header=None): | |
| 74 | if not mimeType: | |
| 75 | mimeType = mimetypes.guess_type(path)[0] | |
| 76 | ||
| 77 | self.respond(200, mimeType) | |
| 78 | if header: | |
| 79 | self << header | |
| 80 | self << file(path).read() | |
| 81 | ||
| 82 | def __lshift__(self, text): | |
| 83 | self.wfile.write(text) | |
| 84 | ||
| 85 | # ************************************************************************************************** | |
| 86 | ||
| 87 | def serve(): | |
| 88 | print "Paste this code into the <head> of all HTML that will run on your iPhone:" | |
| 89 | print getFormattedFile("embed.html", getHostInfo()) | |
| 90 | ||
| 91 | url = "http://%(hostName)s:%(port)s/firebug.html" % getHostInfo() | |
| 92 | print "Load this page in your browser:\n" | |
| 93 | print " %s" % url | |
| 94 | ||
| 95 | print "\nFirebug server is running..." | |
| 96 | ||
| 97 | signal.signal(signal.SIGINT, terminate) | |
| 98 | ||
| 99 | # Run the server on a separate thread | |
| 100 | thread.start_new_thread(runServer, ()) | |
| 101 | ||
| 102 | global done | |
| 103 | while not done: | |
| 104 | try: | |
| 105 | time.sleep(0.3) | |
| 106 | except IOError: | |
| 107 | pass | |
| 108 | ||
| 109 | global server | |
| 110 | server.server_close() | |
| 111 | ||
| 112 | def runServer(): | |
| 113 | global server | |
| 114 | server = WebServer(("", webPort), WebRequestHandler) | |
| 115 | server.allow_reuse_address = True | |
| 116 | server.serve_forever() | |
| 117 | ||
| 118 | def terminate(sig_num, frame): | |
| 119 | global done | |
| 120 | done = True | |
| 121 | ||
| 122 | # ************************************************************************************************** | |
| 123 | ||
| 124 | def postConsoleCommand(message): | |
| 125 | global consoleCommand | |
| 126 | consoleCommand = message | |
| 127 | consoleEvent.set() | |
| 128 | ||
| 129 | def waitForConsoleCommand(): | |
| 130 | consoleEvent.wait() | |
| 131 | consoleEvent.clear() | |
| 132 | ||
| 133 | global consoleCommand | |
| 134 | return consoleCommand | |
| 135 | ||
| 136 | def postPhoneResponse(message): | |
| 137 | global phoneResponse | |
| 138 | phoneResponse = message | |
| 139 | phoneResponseEvent.set() | |
| 140 | ||
| 141 | def waitForPhoneResponse(): | |
| 142 | phoneResponseEvent.wait() | |
| 143 | phoneResponseEvent.clear() | |
| 144 | ||
| 145 | global phoneResponse | |
| 146 | return phoneResponse | |
| 147 | ||
| 148 | # ************************************************************************************************** | |
| 149 | ||
| 150 | def parseURL(url): | |
| 151 | """ Parses a URL into a tuple (host, path, args) where args is a dictionary.""" | |
| 152 | ||
| 153 | scheme, host, path, params, query, hash = urlparse(url) | |
| 154 | if not path: path = "/" | |
| 155 | ||
| 156 | args = parse_qs(query) | |
| 157 | ||
| 158 | escapedArgs = {} | |
| 159 | for name in args: | |
| 160 | if len(args[name]) == 1: | |
| 161 | escapedArgs[unquote(name)] = unquote(args[name][0]) | |
| 162 | else: | |
| 163 | escapedArgs[unquote(name)] = escapedSet = [] | |
| 164 | for item in args[name]: | |
| 165 | escapedSet.append(unquote(item)) | |
| 166 | ||
| 167 | return host, path, params, escapedArgs | |
| 168 | ||
| 169 | def escapeJavaScript(text): | |
| 170 | return text.replace("'", "\\'").replace("\n", "\\n").replace("\r", "") | |
| 171 | ||
| 172 | def getFormattedFile(path, args={}): | |
| 173 | return file(path).read() % args | |
| 174 | ||
| 175 | def getHostInfo(): | |
| 176 | import socket | |
| 177 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
| 178 | s.connect(("getfirebug.com", 80)) | |
| 179 | hostName = s.getsockname()[0] | |
| 180 | s.close() | |
| 181 | ||
| 182 | return {"hostName": hostName, "port": webPort} | |
| 183 | ||
| 184 | # ************************************************************************************************** | |
| 185 | ||
| 186 | if __name__ == "__main__": | |
| 187 | serve() |
| ... | ...@@ -0,0 +1,266 @@ | |
| 1 | ||
| 2 | //if (!("console" in window) || !("firebug" in console)) { | |
| 3 | (function() | |
| 4 | { | |
| 5 | var consoleFrame = null; | |
| 6 | var consoleBody = null; | |
| 7 | var commandLine = null; | |
| 8 | ||
| 9 | var commandHistory = [""]; | |
| 10 | var commandPointer = 0; | |
| 11 | var commandInsertPointer = -1; | |
| 12 | var commandHistoryMax = 1000; | |
| 13 | ||
| 14 | var frameVisible = false; | |
| 15 | var messageQueue = []; | |
| 16 | var groupStack = []; | |
| 17 | var timeMap = {}; | |
| 18 | ||
| 19 | var clPrefix = ">>> "; | |
| 20 | ||
| 21 | var isFirefox = navigator.userAgent.indexOf("Firefox") != -1; | |
| 22 | var isIE = navigator.userAgent.indexOf("MSIE") != -1; | |
| 23 | var isOpera = navigator.userAgent.indexOf("Opera") != -1; | |
| 24 | var isSafari = navigator.userAgent.indexOf("AppleWebKit") != -1; | |
| 25 | ||
| 26 | // ******************************************************************************************** | |
| 27 | ||
| 28 | function init() | |
| 29 | { | |
| 30 | consoleFrame = document.getElementById("inner"); | |
| 31 | consoleBody = document.getElementById("log"); | |
| 32 | ||
| 33 | commandLine = document.getElementById("commandLine"); | |
| 34 | addEvent(commandLine, "keydown", onCommandLineKeyDown); | |
| 35 | ||
| 36 | layout(); | |
| 37 | ||
| 38 | commandLine.focus(); | |
| 39 | commandLine.select(); | |
| 40 | ||
| 41 | window.onload = function init() | |
| 42 | { | |
| 43 | var iframe = document.createElement("iframe"); | |
| 44 | document.body.appendChild(iframe); | |
| 45 | iframe.style.display = "none"; | |
| 46 | iframe.src = "/browser"; | |
| 47 | } | |
| 48 | } | |
| 49 | ||
| 50 | function focusCommandLine() | |
| 51 | { | |
| 52 | toggleConsole(true); | |
| 53 | if (commandLine) | |
| 54 | commandLine.focus(); | |
| 55 | } | |
| 56 | ||
| 57 | function evalCommandLine() | |
| 58 | { | |
| 59 | var text = commandLine.value; | |
| 60 | commandLine.value = ""; | |
| 61 | ||
| 62 | appendToHistory(text); | |
| 63 | logRow([clPrefix, text], "command"); | |
| 64 | ||
| 65 | sendCommand(text); | |
| 66 | } | |
| 67 | ||
| 68 | function sendCommand(text) | |
| 69 | { | |
| 70 | var message = escape(text).replace("+", "%2B") | |
| 71 | var request = new XMLHttpRequest(); | |
| 72 | request.open("GET", "command?message=" + message, true); | |
| 73 | request.send(null); | |
| 74 | } | |
| 75 | ||
| 76 | function appendToHistory(command, unique) | |
| 77 | { | |
| 78 | if (unique && commandHistory[commandInsertPointer] == command) | |
| 79 | return; | |
| 80 | ||
| 81 | ++commandInsertPointer; | |
| 82 | if (commandInsertPointer >= commandHistoryMax) | |
| 83 | commandInsertPointer = 0; | |
| 84 | ||
| 85 | commandPointer = commandInsertPointer+1; | |
| 86 | commandHistory[commandInsertPointer] = command; | |
| 87 | } | |
| 88 | ||
| 89 | function cycleCommandHistory(dir) | |
| 90 | { | |
| 91 | commandHistory[commandPointer] = commandLine.value; | |
| 92 | ||
| 93 | if (dir < 0) | |
| 94 | { | |
| 95 | --commandPointer; | |
| 96 | if (commandPointer < 0) | |
| 97 | commandPointer = 0; | |
| 98 | } | |
| 99 | else | |
| 100 | { | |
| 101 | ++commandPointer; | |
| 102 | if (commandPointer > commandInsertPointer+1) | |
| 103 | commandPointer = commandInsertPointer+1; | |
| 104 | } | |
| 105 | ||
| 106 | var command = commandHistory[commandPointer]; | |
| 107 | ||
| 108 | commandLine.value = command; | |
| 109 | commandLine.setSelectionRange(command.length, command.length); | |
| 110 | } | |
| 111 | ||
| 112 | function layout() | |
| 113 | { | |
| 114 | var toolbar = consoleBody.ownerDocument.getElementById("toolbar"); | |
| 115 | var height = consoleFrame.offsetHeight - (toolbar.offsetHeight + commandLine.offsetHeight); | |
| 116 | consoleBody.style.top = toolbar.offsetHeight + "px"; | |
| 117 | consoleBody.style.height = height + "px"; | |
| 118 | ||
| 119 | var commandLineBox = consoleBody.ownerDocument.getElementById("commandLineBox"); | |
| 120 | commandLineBox.style.top = (consoleFrame.offsetHeight - commandLine.offsetHeight) + "px"; | |
| 121 | } | |
| 122 | ||
| 123 | // ******************************************************************************************** | |
| 124 | ||
| 125 | function logRow(message, className, handler) | |
| 126 | { | |
| 127 | var isScrolledToBottom = | |
| 128 | consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight; | |
| 129 | ||
| 130 | if (!handler) | |
| 131 | handler = writeRow; | |
| 132 | ||
| 133 | handler(message, className); | |
| 134 | ||
| 135 | if (isScrolledToBottom) | |
| 136 | consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight; | |
| 137 | } | |
| 138 | ||
| 139 | function logFormatted(objects, className) | |
| 140 | { | |
| 141 | var html = []; | |
| 142 | ||
| 143 | var format = objects[0]; | |
| 144 | var objIndex = 0; | |
| 145 | ||
| 146 | if (typeof(format) != "string") | |
| 147 | { | |
| 148 | format = ""; | |
| 149 | objIndex = -1; | |
| 150 | } | |
| 151 | ||
| 152 | var parts = parseFormat(format); | |
| 153 | for (var i = 0; i < parts.length; ++i) | |
| 154 | { | |
| 155 | var part = parts[i]; | |
| 156 | if (part && typeof(part) == "object") | |
| 157 | { | |
| 158 | var object = objects[++objIndex]; | |
| 159 | part.appender(object, html); | |
| 160 | } | |
| 161 | else | |
| 162 | appendText(part, html); | |
| 163 | } | |
| 164 | ||
| 165 | for (var i = objIndex+1; i < objects.length; ++i) | |
| 166 | { | |
| 167 | appendText(" ", html); | |
| 168 | ||
| 169 | var object = objects[i]; | |
| 170 | if (typeof(object) == "string") | |
| 171 | appendText(object, html); | |
| 172 | else | |
| 173 | appendObject(object, html); | |
| 174 | } | |
| 175 | ||
| 176 | logRow(html, className); | |
| 177 | } | |
| 178 | ||
| 179 | function writeRow(message, className) | |
| 180 | { | |
| 181 | var row = consoleBody.ownerDocument.createElement("div"); | |
| 182 | row.className = "logRow" + (className ? " logRow-"+className : ""); | |
| 183 | row.innerHTML = message.join(""); | |
| 184 | appendRow(row); | |
| 185 | } | |
| 186 | ||
| 187 | function appendRow(row) | |
| 188 | { | |
| 189 | var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody; | |
| 190 | container.appendChild(row); | |
| 191 | } | |
| 192 | ||
| 193 | function parseFormat(format) | |
| 194 | { | |
| 195 | var parts = []; | |
| 196 | ||
| 197 | var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/; | |
| 198 | var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat}; | |
| 199 | ||
| 200 | for (var m = reg.exec(format); m; m = reg.exec(format)) | |
| 201 | { | |
| 202 | var type = m[8] ? m[8] : m[5]; | |
| 203 | var appender = type in appenderMap ? appenderMap[type] : appendObject; | |
| 204 | var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0); | |
| 205 | ||
| 206 | parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1)); | |
| 207 | parts.push({appender: appender, precision: precision}); | |
| 208 | ||
| 209 | format = format.substr(m.index+m[0].length); | |
| 210 | } | |
| 211 | ||
| 212 | parts.push(format); | |
| 213 | ||
| 214 | return parts; | |
| 215 | } | |
| 216 | ||
| 217 | // ******************************************************************************************** | |
| 218 | ||
| 219 | function addEvent(object, name, handler) | |
| 220 | { | |
| 221 | if (document.all) | |
| 222 | object.attachEvent("on"+name, handler); | |
| 223 | else | |
| 224 | object.addEventListener(name, handler, false); | |
| 225 | } | |
| 226 | ||
| 227 | function removeEvent(object, name, handler) | |
| 228 | { | |
| 229 | if (document.all) | |
| 230 | object.detachEvent("on"+name, handler); | |
| 231 | else | |
| 232 | object.removeEventListener(name, handler, false); | |
| 233 | } | |
| 234 | ||
| 235 | function cancelEvent(event) | |
| 236 | { | |
| 237 | if (document.all) | |
| 238 | event.cancelBubble = true; | |
| 239 | else | |
| 240 | event.stopPropagation(); | |
| 241 | } | |
| 242 | ||
| 243 | function onCommandLineKeyDown(event) | |
| 244 | { | |
| 245 | if (event.keyCode == 13) | |
| 246 | evalCommandLine();//evalCommandLine(); | |
| 247 | else if (event.keyCode == 27) | |
| 248 | commandLine.value = ""; | |
| 249 | else if (event.keyCode == 38) | |
| 250 | cycleCommandHistory(-1); | |
| 251 | else if (event.keyCode == 40) | |
| 252 | cycleCommandHistory(1); | |
| 253 | } | |
| 254 | ||
| 255 | window.command = function(text) | |
| 256 | { | |
| 257 | var lines = text.split("\0"); | |
| 258 | var className = lines[0]; | |
| 259 | var html = lines[1]; | |
| 260 | logRow([html], className); | |
| 261 | } | |
| 262 | ||
| 263 | init(); | |
| 264 | ||
| 265 | })(); | |
| 266 | //} |
| ... | ...@@ -0,0 +1,2 @@ | |
| 1 | ||
| 2 | <script type="application/x-javascript" src="http://%(hostName)s:%(port)s/ibug.js"></script> |
| ... | ...@@ -0,0 +1,438 @@ | |
| 1 | ||
| 2 | if (!("console" in window) || !("firebug" in console)) { | |
| 3 | (function() | |
| 4 | { | |
| 5 | window.console = | |
| 6 | { | |
| 7 | firebug: "ibug0.1", | |
| 8 | ||
| 9 | log: function() | |
| 10 | { | |
| 11 | logFormatted(arguments, ""); | |
| 12 | }, | |
| 13 | ||
| 14 | debug: function() | |
| 15 | { | |
| 16 | logFormatted(arguments, "debug"); | |
| 17 | }, | |
| 18 | ||
| 19 | info: function() | |
| 20 | { | |
| 21 | logFormatted(arguments, "info"); | |
| 22 | }, | |
| 23 | ||
| 24 | warn: function() | |
| 25 | { | |
| 26 | logFormatted(arguments, "warning"); | |
| 27 | }, | |
| 28 | ||
| 29 | error: function() | |
| 30 | { | |
| 31 | logFormatted(arguments, "error"); | |
| 32 | }, | |
| 33 | ||
| 34 | assert: function(truth, message) | |
| 35 | { | |
| 36 | if (!truth) | |
| 37 | { | |
| 38 | var args = []; | |
| 39 | for (var i = 1; i < arguments.length; ++i) | |
| 40 | args.push(arguments[i]); | |
| 41 | ||
| 42 | logFormatted(args.length ? args : ["Assertion Failure"], "error"); | |
| 43 | throw message ? message : "Assertion Failure"; | |
| 44 | } | |
| 45 | }, | |
| 46 | ||
| 47 | dir: function(object) | |
| 48 | { | |
| 49 | var html = []; | |
| 50 | ||
| 51 | var pairs = []; | |
| 52 | for (var name in object) | |
| 53 | { | |
| 54 | try | |
| 55 | { | |
| 56 | pairs.push([name, object[name]]); | |
| 57 | } | |
| 58 | catch (exc) | |
| 59 | { | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | pairs.sort(function(a, b) { return a[0] < b[0] ? -1 : 1; }); | |
| 64 | ||
| 65 | html.push('<table>'); | |
| 66 | for (var i = 0; i < pairs.length; ++i) | |
| 67 | { | |
| 68 | var name = pairs[i][0], value = pairs[i][1]; | |
| 69 | ||
| 70 | html.push('<tr>', | |
| 71 | '<td class="propertyNameCell"><span class="propertyName">', | |
| 72 | escapeHTML(name), '</span></td>', '<td><span class="propertyValue">'); | |
| 73 | appendObject(value, html); | |
| 74 | html.push('</span></td></tr>'); | |
| 75 | } | |
| 76 | html.push('</table>'); | |
| 77 | ||
| 78 | logRow(html, "dir"); | |
| 79 | }, | |
| 80 | ||
| 81 | dirxml: function(node) | |
| 82 | { | |
| 83 | var html = []; | |
| 84 | ||
| 85 | appendNode(node, html); | |
| 86 | logRow(html, "dirxml"); | |
| 87 | }, | |
| 88 | ||
| 89 | group: function() | |
| 90 | { | |
| 91 | logRow(arguments, "group", pushGroup); | |
| 92 | }, | |
| 93 | ||
| 94 | groupEnd: function() | |
| 95 | { | |
| 96 | logRow(arguments, "", popGroup); | |
| 97 | }, | |
| 98 | ||
| 99 | time: function(name) | |
| 100 | { | |
| 101 | timeMap[name] = (new Date()).getTime(); | |
| 102 | }, | |
| 103 | ||
| 104 | timeEnd: function(name) | |
| 105 | { | |
| 106 | if (name in timeMap) | |
| 107 | { | |
| 108 | var delta = (new Date()).getTime() - timeMap[name]; | |
| 109 | logFormatted([name+ ":", delta+"ms"]); | |
| 110 | delete timeMap[name]; | |
| 111 | } | |
| 112 | }, | |
| 113 | ||
| 114 | count: function() | |
| 115 | { | |
| 116 | this.warn(["count() not supported."]); | |
| 117 | }, | |
| 118 | ||
| 119 | trace: function() | |
| 120 | { | |
| 121 | this.warn(["trace() not supported."]); | |
| 122 | }, | |
| 123 | ||
| 124 | profile: function() | |
| 125 | { | |
| 126 | this.warn(["profile() not supported."]); | |
| 127 | }, | |
| 128 | ||
| 129 | profileEnd: function() | |
| 130 | { | |
| 131 | }, | |
| 132 | ||
| 133 | // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
| 134 | ||
| 135 | $: function(id) | |
| 136 | { | |
| 137 | return document.getElementById(id); | |
| 138 | }, | |
| 139 | ||
| 140 | $$: function(selector) | |
| 141 | { | |
| 142 | // XXXjoe Make this into getElementsBySelector | |
| 143 | return document.getElementsByTagName(selector); | |
| 144 | }, | |
| 145 | ||
| 146 | // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
| 147 | ||
| 148 | onError: function(msg, href, lineNo) | |
| 149 | { | |
| 150 | var html = []; | |
| 151 | ||
| 152 | var lastSlash = href.lastIndexOf("/"); | |
| 153 | var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1); | |
| 154 | ||
| 155 | html.push( | |
| 156 | '<span class="errorMessage">', msg, '</span>', | |
| 157 | '<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>' | |
| 158 | ); | |
| 159 | ||
| 160 | logRow(html, "error"); | |
| 161 | }, | |
| 162 | ||
| 163 | command: function(text) | |
| 164 | { | |
| 165 | with (console) | |
| 166 | { | |
| 167 | try { | |
| 168 | var result = eval(text); | |
| 169 | if (result !== undefined) | |
| 170 | console.log(result); | |
| 171 | } | |
| 172 | catch (exc) | |
| 173 | { | |
| 174 | console.onError(exc.message, exc.sourceId+"", exc.line); | |
| 175 | } | |
| 176 | } | |
| 177 | } | |
| 178 | }; | |
| 179 | ||
| 180 | // ******************************************************************************************** | |
| 181 | ||
| 182 | var timeMap = {}; | |
| 183 | ||
| 184 | // ******************************************************************************************** | |
| 185 | ||
| 186 | function appendText(object, html) | |