// -*- c++ -*- // // debugwindow.js - Show debug information using small debug window. // // Copyright (C) 2005 Kouichirou Eto, // All rights reserved. // This is free software with ABSOLUTELY NO WARRANTY. // // You can redistribute it and/or modify it under the terms of // the GNU General Public License version 2. // // // * Usage // init() : called from onload. // open() : open window. // print(str) : print message. // puts(str) : print message with new line. // clear() : clear window. // p(obj) : print the result of inspecting the object. // inspect(obj) : inspect object. // // // * Interface for the debug window // [x] - close window. // [v] - make console bigger. // [-] - close console. // [+] - open console. // // // * History // // ** 2005-04-05 DebugWindow 0.5 // - Do not open window by default. // // ** 2005-03-31 DebugWindow 0.4 // - Set default position to right top corner. // - Set default to close console. // // ** 2005-03-30 DebugWindow 0.3 // - Add a lines button and a close button. // - Add a test case. // // ** 2005-03-30 DebugWindow 0.2 // - Now works in IE same as Firefox. // // ** 2005-03-29 DebugWindow 0.1 // - The initial release. // // // * Special Thanks to // // - debug.js // -- http://homepage1.nifty.com/kuraman/js/debug.html // // - wema // -- http://wema.sourceforge.jp/ // // - ArekorePopup.js // -- http://www.remus.dti.ne.jp/~a-satomi/bunsyorou/ArekorePopup.html // // - bobchin // -- http://d.hatena.ne.jp/bobchin/20050304 // function DebugWindow() { // setting. this.showConsole = true; //this.showConsole = false; this.width = "320px"; this.height = "240px"; // height unit must be "px". // variables. this.win = null; this.toggleButton = null; this.console = null; this.buffer = ""; this.dragging = false; } DebugWindow.prototype = { init : function() { this.open(); }, open : function() { var obj = document.getElementById("debugwindow"); if (obj) return; // already opened. // create window var w = document.createElement("div"); w.setAttribute("id", "debugwindow"); with(w.style) { zIndex = "1"; position = "absolute"; right = "0px"; top = "0px"; width = this.width; margin = "0"; padding = "0"; border = "2px outset"; fontFamily = "Verdana,Arial,sans-serif"; fontSize = "small"; } w.show = function() { this.style.display = "block"; }; w.hide = function() { this.style.display = "none"; }; document.body.appendChild(w); this.win = w; // titlebar var titlebar = document.createElement("div"); titlebar.setAttribute("id", "debugwindowtitlebar"); with(titlebar.style) { margin = "0"; padding = "0"; borderBottom = "1px solid #ccc"; background = "#999"; color = "#fff"; } w.appendChild(titlebar); // console var console = document.createElement("div"); console.setAttribute("id", "debugwindowconsole"); console.contentEditable = "true"; // contentEditable only works in IE. with(console.style) { height = this.height; overflow = "scroll"; margin = "0"; padding = "0"; border = "1px inset"; background = "#eee"; color = "#000"; fontFamily = "Verdana,Arial,sans-serif"; fontSize = "small"; } console.makeBigger = function() { var s = this.style; var h = parseInt(s.height.replace("px", "")); h += 24; s.height = h+"px"; }; console.show = function() { this.style.display = "block"; }; console.hide = function() { this.style.display = "none"; }; console.visible = function() { return this.style.display == "block"; }; console.show(); // console is visible. w.appendChild(console); this.console = console; // title var span = document.createElement("span"); with(span.style) { display = "block"; margin = "0"; padding = "0 0 0 10px"; fontSize = "xx-small"; } span.innerHTML = "debug window"; span.onmousedown = function(e) { // onmousedown g_debug.startDragging(e); }; span.ondblclick = function() { g_debug.consoleToggle(); }; titlebar.appendChild(span); // close button var span = this.createButton("debugwindowclosebutton"); span.setPos(0, 0); span.innerHTML = "x"; span.onmousedown = function() { g_debug.win.hide(); }; titlebar.appendChild(span); // make bigger button var span = this.createButton("debugwindowbiggerbutton"); span.setPos(18, 0); span.innerHTML = "v"; var proc = function() { g_debug.console.makeBigger(); }; span.onclick = proc; span.ondblclick = proc; titlebar.appendChild(span); // console toggle button var span = this.createButton("debugwindowtogglebutton"); span.setPos(32, 0); var proc = function() { g_debug.consoleToggle(); }; span.onclick = proc; span.ondblclick = proc; titlebar.appendChild(span); this.toggleButton = span; // set document event document.onmousemove = function(e) { g_debug.nowDragging(e); }; document.onmouseup = function(e) { g_debug.endDragging(); } if (! this.showConsole) { this.consoleToggle(); // hide at the first. } }, createButton : function(id) { // private var span = document.createElement("span"); span.setAttribute("id", id); with(span.style) { width = "12px"; height = "10px"; margin = "0"; padding = "0"; background = "#ccc"; color = "#000"; fontSize = "xx-small"; fontWeight = "bold"; textAlign = "center"; display = "block"; border = "1px outset"; } span.setPos = function(x, y) { with(this.style) { position = "absolute"; right = x+"px"; top = y+"px"; } } return span; }, consoleToggle : function(e) { var con = this.console; var but = this.toggleButton; if (con.visible()) { con.hide(); but.innerHTML = "+"; } else { con.show(); but.innerHTML = "-"; } }, startDragging : function(e) { if (typeof e == "undefined") { e = window.event; } var w = this.win; if (!w) return; var pos = this.getMousePos(e); var divpos = this.getDivPos(w); var x = pos.mouseX - divpos.x; var y = pos.mouseY - divpos.y this.offset = { x : x, y : y }; this.dragging = true; }, nowDragging : function(e) { if (typeof e == "undefined") { e = window.event; } if (!this.alerted) { //g_debug.p(e); this.alerted = true; } var w = this.win; if (!w) return; if (!this.dragging) return; var pos = this.getMousePos(e); var offset = this.offset; var x = pos.mouseX - offset.x; var y = pos.mouseY - offset.y; w.style.left = x+"px"; w.style.top = y+"px"; }, endDragging : function() { g_debug.dragging = false; }, // ref. ArekorePopup.js getMousePos : function(e) { var d = document.documentElement; var body = document.body; var isSafari = navigator.userAgent.match('AppleWebKit'); var scrollX = (window.scrollX) ? window.scrollX : (d.scrollLeft) ? d.scrollLeft : body.scrollLeft; var scrollY = (window.scrollY) ? window.scrollY : (d.scrollTop) ? d.scrollTop : body.scrollTop; var windowW = (window.innerWidth) ? window.innerWidth : d.offsetWidth; var windowH = (window.innerHeight) ? window.innerHeight : d.offsetHeight; var windowX = e.clientX - (( isSafari) ? scrollX : 0); var windowY = e.clientY - (( isSafari) ? scrollY : 0); var mouseX = e.clientX + ((!isSafari) ? scrollX : 0); var mouseY = e.clientY + ((!isSafari) ? scrollY : 0); var pos = { scrollX : scrollX, scrollY : scrollY, windowW : windowW, windowH : windowH, windowX : windowX, windowY : windowY, mouseX : mouseX, mouseY : mouseY }; return pos; }, getDivPos : function(o) { var s = o.style; var x = (s.left) ? s.left : (s.posLeft) ? s.posLeft : o.offsetLeft+"px"; var y = (s.top) ? s.top : (s.posTop) ? s.posTop : o.offsetTop+"px"; divx = parseInt(x.replace("px", "")); divy = parseInt(y.replace("px", "")); if (divx == 0) divx = 1; // IE BUGFIX. if (divy == 0) divy = 1; var pos = { x : divx, y : divy }; return pos; }, // ref. ArekorePopup.js addEventListener : function(obj, type, listener) { if (obj.addEventListener) { // Std DOM Events obj.addEventListener(type, listener, false); } else if (obj.attachEvent) { // IE //g_debug.pa("addEvent hi"); var e = { //type : window.event.type, //target : window.event.srcElement, //currentTarget : obj, //clientX : window.event.clientX, //clientY : window.event.clientY, //pageY : document.body.scrollTop + window.event.clientY, //shiftKey : window.event.shiftKey, //stopPropagation : function() { window.event.cancelBubble = true } }; //g_debug.pa(e); obj.attachEvent('on' + type, function() { listener( e ) } ); } }, destroy : function() { // private var div = this.win; if (!div) return; document.body.removeChild(div); this.win = null; }, bufferPrint : function(str) { str = this.escapeHTML(str); this.buffer += str; }, bufferPrintTag : function(str) { this.buffer += str; }, print : function(str) { this.bufferPrintTag(""); this.bufferPrint(str) this.bufferPrintTag(""); }, puts : function(str) { this.print(str); this.bufferPrintTag(""); this.flush(); }, clear : function() { this.buffer = ""; this.flush(); }, p : function(obj) { var str = this.inspect(obj) this.puts(str); }, flush : function() { if (!this.win) this.open(); if (this.win.style.display == "none") { this.win.style.display = "block"; } var div = this.console; if (!div) return; // error div.innerHTML = this.buffer; }, pa : function(obj) { // to test DebugWindow. var str = this.inspect(obj) alert(str); }, inspect : function(obj) { if (typeof obj == "number") { return ""+obj; } else if (typeof obj == "string") { return "\""+obj+"\""; } else if (typeof obj == "function") { return ""+obj; } else if (typeof obj == "object") { //var delimiter = ",
"; var delimiter = ",\n"; var str = "{"; var added = false; for (key in obj) { var value = obj[key]; if (value) { if (added) str += delimiter; added = true; if (typeof value == "number") { str += ""+key+"=>"+value+""; } else if (typeof value == "string") { str += ""+key+"=>\""+value+"\""; } else if (typeof value == "function") { str += ""+key+"()"; } else if (typeof value == "object") { str += ""+key+"=>"+value+""; } else { str += ""+key+"=><"+(typeof value)+":"+value+">"; } } } return str+"}"; } else { return "<"+(typeof obj)+":"+obj+">"; } }, escapeHTML : function(str) { str = str.replace(/&/g, "&"); str = str.replace(//g, ">"); str = str.replace(/\"/g, """); // " //str = str.replace(/\n/g, ""); return str; }, dummy : function() { } // no "," here }; if (typeof g_debug == 'undefined') { var g_debug = new DebugWindow(); //var proc = function() { // g_debug.init(); //} //window.onload = proc; //g_debug.addEventListener(window, "load", proc); }