今天看了JavaScript权威指南中的15章节,15.8:在document中添加内容,该代码综合了不同的DOM编程内容,其编程的结构也值得我们学习。那么首先先给个log.js的基本解释。
log()中有3个参数:
1.category: message的类型,根据message的类型选择性的对其启动或者使其无效.
2.message: 就是log中的text, 也可以是空;
3.object: log中的对象,该参数是选择性的,如果传送object,则object中的属性记录在表中,任何属性的值是它本身的,则可以用递归记录(这点会在后面说明)。
实用功能(Utility Functions):
log.debug() 和 log.warn() ,还有alert();debug()和warn()是用赋值messge的类型---category和object; alert是跳出一个警告;
启动日志记录(Enabling logging):
如果message是缺省值将不会显示,有两种启用的方式,第一个是创建<div>或者别的容器元素,用id"<category>_log".如<debug>_log或者<warn>_log等。这种情况下,所有的message会经过规定附加在容器中(如<div>),或者任何你喜欢的style。
第二种情况,可定义一个适当的日志记录选项--log.options.debugEnabled,在程序中写成log.options[category+"Enabled"],则可以更加灵活了,只要对log.options.debugEnabled进行判定,是true则设置<div>中的属性。反之,则不启动该功能。貌似该判断在程序中没有具体设置,我认为应该在log.options = {debugEnabled: log.options.debugEnabled, debugDisabled:log.options.debugIsabled}这样。
设计Log Messages
用CSS去设计每个log messages的显示。每个log message放置在<div>中,再付一个css class即可,用<category>_message表示则可对应到css文件中的名称,如:debug_message.
log Options
log.options.timestamp: 当是true时,添加日期和时间在消息中。
log.options.maxRecursion:定义最大的嵌套表格数目。
log.options.filter: 过滤器???
log.js源代码:
// log函数:
function log(category, message, object) {
// If this category is explicitly disabled, do nothing
if (log.options[category + "Disabled"]) return;
// Find the container
var id = category + "_log";
var c = document.getElementById(id);
// If there is no container, but logging in this category is enabled,
// create the container.
if (!c && log.options[category + "Enabled"]) {
c = document.createElement("div");
c.id = id;
c.className = "log";
document.body.appendChild(c);
}
// If still no container, we ignore the message
if (!c) return;
// If timestamping is enabled, add the timestamp
if (log.options.timestamp)
message = new Date() + ": " + (message?message:"");
// Create a <div> element to hold the log entry
var entry = document.createElement("div");
entry.className = category + "_message";
if (message) {
// Add the message to it
entry.appendChild(document.createTextNode(message));
}
if (object && typeof object == "object") {
entry.appendChild(log.makeTable(object, 0)); //makeTable函数在下面解释
}
// Finally, add the entry to the logging container(往DIV中添加子节点:<table>)
c.appendChild(entry);
}
//log.makeTable
log.makeTable = function(object, level) {
// If we've reached maximum recursion, return a Text node instead.
if (level > log.options.maxRecursion)
return document.createTextNode(object.toString());
// Create the table we'll be returning
var table = document.createElement("table");
table.border = 1;
// Add a Name|Type|Value header to the table(还是往其中添加节点,制定表格的标题)
var header = document.createElement("tr");
var headerName = document.createElement("th");
var headerType = document.createElement("th");
var headerValue = document.createElement("th");
headerName.appendChild(document.createTextNode("Name"));
headerType.appendChild(document.createTextNode("Type"));
headerValue.appendChild(document.createTextNode("Value"));
header.appendChild(headerName);
header.appendChild(headerType);
header.appendChild(headerValue);
table.appendChild(header);
// Get property names of the object and sort them alphabetically(数组存储object 中的内容,按字母排序)
var names = [];
for(var name in object) names.push(name);
names.sort();
// Now loop through those properties
for(var i = 0; i < names.length; i++) {
var name, value, type;
name = names[i];
try {
value = object[name];
type = typeof value;
}
catch(e) { // This should not happen, but it can in Firefox
value = "<unknown value>";
type = "unknown";
};
// Skip this property if it is rejected by a filter
if (log.options.filter && !log.options.filter(name, value)) continue;
// Never display function source code: it takes up too much room
if (type == "function") value = "{/*source code suppressed*/}";
// Create a table row to display property name, type and value (添加节点,显示表格中的内容)
var row = document.createElement("tr");
row.vAlign = "top";
var rowName = document.createElement("td");
var rowType = document.createElement("td");
var rowValue = document.createElement("td");
rowName.appendChild(document.createTextNode(name));
rowType.appendChild(document.createTextNode(type));
// For objects, recurse to display them as tables
if (type == "object")
rowValue.appendChild(log.makeTable(value, level+1));
else
rowValue.appendChild(document.createTextNode(value));
// Add the cells to the row, and add the row to the table
row.appendChild(rowName);
row.appendChild(rowType);
row.appendChild(rowValue);
table.appendChild(row);
}
// Finally, return the table.
return table;
}
// Create an empty options object
log.options = {};
// Utility versions of the function with hardcoded categories (这里再封装函数)
log.debug = function(message, object) { log("debug", message, object); };
log.warn = function(message, object) { log("warning", message, object); };
// Uncomment the following line to convert alert() dialogs to log messages
// function alert(msg) { log("alert", msg); }
//CSS代码:
body {
}
#debug_log {
background-color: #aaa;
border: solid black 2px;
overflow: auto;
width: 75%;
height: 300px;
}
#debug_log:before {
content: "Debugging Messages";
display: block;
text-align: center;
font: bold 18pt sans-serif;
}
.debug_message {
border-bottom: solid black 1px;
}
//HTML代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<script src = "Untitled JS 3.js"></script>
<link rel = "stylesheet" type="text/css" href="Untitled CSS 7.css">
</head>
<body>
<script>
function makeRectangle(x,y,w,h){
log.debug("entering makeRectangle");
var r ={x:x, y:y, size:{w:w, h:h}};
//这里可以看到r[size]也是object对象,需要用table来保存,所以要用递归。对应上面同样颜色部分
log.debug("New rectangle", r);
log.debug("exiting makeRectangle");
return r;
}
</script>
<button οnclick="makeRectangle(1,2,3,4);">Make Rectangle</button>
<div id = "debug_log" class = "log"></div>
</body>
</html>
其实感觉代码第一没写完全,书中有些地方没解释清楚,但我觉得该代码还是包含了很多知识点,其中有些地方我也有些是懂非懂的感觉,希望大家看完后有什么想法的也一起讨论讨论!
运行效果图: