1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
var debug = operator(); |
18 |
var info = operator(); |
19 |
var warn = operator(); |
20 |
var error = operator(); |
21 |
var childLogger = operator(); |
22 |
var log = operator(); |
23 |
var threshold = operator(); |
24 |
var enable = operator(); |
25 |
var disable = operator(); |
26 |
var toggle = operator(); |
27 |
|
28 |
function Logger(category, handler) { |
29 |
return object(function(method) { |
30 |
each([debug, info, warn, error], function(priorityOperator) { |
31 |
method(priorityOperator, function(self, message, exception) { |
32 |
log(handler, priorityOperator, category, message, exception); |
33 |
}); |
34 |
}); |
35 |
|
36 |
method(childLogger, function(self, categoryName, newHandler) { |
37 |
return Logger(append(copy(category), categoryName), newHandler || handler); |
38 |
}); |
39 |
|
40 |
method(asString, function(self) { |
41 |
return 'Logger[' + join(category, '.') + ']'; |
42 |
}); |
43 |
}); |
44 |
} |
45 |
|
46 |
function ConsoleLogHandler(priority) { |
47 |
function formatOutput(category, message) { |
48 |
var timestamp = (new Date()).toUTCString(); |
49 |
return join(['[', join(category, '.'), '] [', timestamp, '] ', message], ''); |
50 |
} |
51 |
|
52 |
var ieConsole = !window.console.debug; |
53 |
|
54 |
var debugPrimitive = ieConsole ? |
55 |
function(self, category, message, exception) { |
56 |
exception ? console.log(formatOutput(category, message), '\n', exception) : console.log(formatOutput(category, message)); |
57 |
} : |
58 |
function(self, category, message, exception) { |
59 |
exception ? console.debug(formatOutput(category, message), exception) : console.debug(formatOutput(category, message)); |
60 |
}; |
61 |
var infoPrimitive = ieConsole ? |
62 |
function(self, category, message, exception) { |
63 |
exception ? console.info(formatOutput(category, message), '\n', exception) : console.info(formatOutput(category, message)); |
64 |
} : |
65 |
function(self, category, message, exception) { |
66 |
exception ? console.info(formatOutput(category, message), exception) : console.info(formatOutput(category, message)); |
67 |
}; |
68 |
var warnPrimitive = ieConsole ? |
69 |
function(self, category, message, exception) { |
70 |
exception ? console.warn(formatOutput(category, message), '\n', exception) : console.warn(formatOutput(category, message)); |
71 |
} : |
72 |
function(self, category, message, exception) { |
73 |
exception ? console.warn(formatOutput(category, message), exception) : console.warn(formatOutput(category, message)); |
74 |
}; |
75 |
var errorPrimitive = ieConsole ? |
76 |
function(self, category, message, exception) { |
77 |
exception ? console.error(formatOutput(category, message), '\n', exception) : console.error(formatOutput(category, message)); |
78 |
} : |
79 |
function(self, category, message, exception) { |
80 |
exception ? console.error(formatOutput(category, message), exception) : console.error(formatOutput(category, message)); |
81 |
}; |
82 |
|
83 |
var handlers = [ |
84 |
Cell(debug, object(function(method) { |
85 |
method(debug, debugPrimitive); |
86 |
method(info, infoPrimitive); |
87 |
method(warn, warnPrimitive); |
88 |
method(error, errorPrimitive); |
89 |
})), |
90 |
Cell(info, object(function(method) { |
91 |
method(debug, noop); |
92 |
method(info, infoPrimitive); |
93 |
method(warn, warnPrimitive); |
94 |
method(error, errorPrimitive); |
95 |
})), |
96 |
Cell(warn, object(function(method) { |
97 |
method(debug, noop); |
98 |
method(info, noop); |
99 |
method(warn, warnPrimitive); |
100 |
method(error, errorPrimitive); |
101 |
})), |
102 |
Cell(error, object(function(method) { |
103 |
method(debug, noop); |
104 |
method(info, noop); |
105 |
method(warn, noop); |
106 |
method(error, errorPrimitive); |
107 |
})) |
108 |
]; |
109 |
var handler; |
110 |
|
111 |
function selectHandler(p) { |
112 |
handler = value(detect(handlers, function(cell) { |
113 |
return key(cell) == p; |
114 |
})); |
115 |
} |
116 |
|
117 |
selectHandler(priority || debug); |
118 |
|
119 |
return object(function (method) { |
120 |
method(threshold, function(self, priority) { |
121 |
selectHandler(priority); |
122 |
}); |
123 |
|
124 |
method(log, function(self, operation, category, message, exception) { |
125 |
operation(handler, category, message, exception); |
126 |
}); |
127 |
}); |
128 |
} |
129 |
|
130 |
|
131 |
var FirebugLogHandler = ConsoleLogHandler; |
132 |
|
133 |
function WindowLogHandler(thresholdPriority, name) { |
134 |
var lineOptions = [25, 50, 100, 200, 400]; |
135 |
var numberOfLines = lineOptions[3]; |
136 |
var categoryMatcher = /.*/; |
137 |
var closeOnExit = true; |
138 |
var logContainer; |
139 |
var logEntry = noop; |
140 |
|
141 |
function trimLines() { |
142 |
var nodes = logContainer.childNodes; |
143 |
var trim = size(nodes) - numberOfLines; |
144 |
if (trim > 0) { |
145 |
each(copy(nodes), function(node, index) { |
146 |
if (index < trim) logContainer.removeChild(node); |
147 |
}); |
148 |
} |
149 |
} |
150 |
|
151 |
function trimAllLines() { |
152 |
each(copy(logContainer.childNodes), function(node) { |
153 |
logContainer.removeChild(node); |
154 |
}); |
155 |
} |
156 |
|
157 |
function toggle() { |
158 |
var disabled = logEntry == noop; |
159 |
logEntry = disabled ? displayEntry : noop; |
160 |
return !disabled; |
161 |
} |
162 |
|
163 |
function displayEntry(priorityName, colorName, category, message, exception) { |
164 |
var categoryName = join(category, '.'); |
165 |
|
166 |
if (categoryMatcher.test(categoryName)) { |
167 |
var elementDocument = logContainer.ownerDocument; |
168 |
var timestamp = new Date(); |
169 |
var completeMessage = join(['[', categoryName, '] : ', message, (exception ? join(['\n', exception.name, ' <', exception.message, '>'], '') : '')], ''); |
170 |
each(split(completeMessage, '\n'), function(line) { |
171 |
if (/(\w+)/.test(line)) { |
172 |
var eventNode = elementDocument.createElement('div'); |
173 |
eventNode.style.padding = '3px'; |
174 |
eventNode.style.color = colorName; |
175 |
eventNode.setAttribute("title", timestamp + ' | ' + priorityName) |
176 |
logContainer.appendChild(eventNode).appendChild(elementDocument.createTextNode(line)); |
177 |
} |
178 |
}); |
179 |
logContainer.scrollTop = logContainer.scrollHeight; |
180 |
} |
181 |
trimLines(); |
182 |
} |
183 |
|
184 |
function showWindow() { |
185 |
var logWindow = window.open('', '_blank', 'scrollbars=1,width=800,height=680'); |
186 |
try { |
187 |
var windowDocument = logWindow.document; |
188 |
var documentBody = windowDocument.body; |
189 |
|
190 |
each(copy(documentBody.childNodes), function(e) { |
191 |
windowDocument.body.removeChild(e); |
192 |
}); |
193 |
|
194 |
documentBody.appendChild(windowDocument.createTextNode(' Close on exit ')); |
195 |
var closeOnExitCheckbox = windowDocument.createElement('input'); |
196 |
closeOnExitCheckbox.style.margin = '2px'; |
197 |
closeOnExitCheckbox.setAttribute('type', 'checkbox'); |
198 |
closeOnExitCheckbox.defaultChecked = true; |
199 |
closeOnExitCheckbox.checked = true; |
200 |
closeOnExitCheckbox.onclick = function() { |
201 |
closeOnExit = closeOnExitCheckbox.checked; |
202 |
}; |
203 |
documentBody.appendChild(closeOnExitCheckbox); |
204 |
|
205 |
documentBody.appendChild(windowDocument.createTextNode(' Lines ')); |
206 |
var lineCountDropDown = windowDocument.createElement('select'); |
207 |
lineCountDropDown.style.margin = '2px'; |
208 |
each(lineOptions, function(count, index) { |
209 |
var option = lineCountDropDown.appendChild(windowDocument.createElement('option')); |
210 |
if (numberOfLines == count) lineCountDropDown.selectedIndex = index; |
211 |
option.appendChild(windowDocument.createTextNode(asString(count))); |
212 |
}); |
213 |
documentBody.appendChild(lineCountDropDown); |
214 |
|
215 |
documentBody.appendChild(windowDocument.createTextNode(' Category ')); |
216 |
var categoryInputText = windowDocument.createElement('input'); |
217 |
categoryInputText.style.margin = '2px'; |
218 |
categoryInputText.setAttribute('type', 'text'); |
219 |
categoryInputText.setAttribute('value', categoryMatcher.source); |
220 |
categoryInputText.onchange = function() { |
221 |
categoryMatcher = new RegExp(categoryInputText.value); |
222 |
}; |
223 |
documentBody.appendChild(categoryInputText); |
224 |
|
225 |
documentBody.appendChild(windowDocument.createTextNode(' Level ')); |
226 |
var levelDropDown = windowDocument.createElement('select'); |
227 |
levelDropDown.style.margin = '2px'; |
228 |
var levels = [Cell('debug', debug), Cell('info', info), Cell('warn', warn), Cell('error', error)]; |
229 |
each(levels, function(priority, index) { |
230 |
var option = levelDropDown.appendChild(windowDocument.createElement('option')); |
231 |
if (thresholdPriority == value(priority)) levelDropDown.selectedIndex = index; |
232 |
option.appendChild(windowDocument.createTextNode(key(priority))); |
233 |
}); |
234 |
levelDropDown.onchange = function(event) { |
235 |
thresholdPriority = value(levels[levelDropDown.selectedIndex]); |
236 |
}; |
237 |
documentBody.appendChild(levelDropDown); |
238 |
|
239 |
var startStopButton = windowDocument.createElement('input'); |
240 |
startStopButton.style.margin = '2px'; |
241 |
startStopButton.setAttribute('type', 'button'); |
242 |
startStopButton.setAttribute('value', 'Stop'); |
243 |
startStopButton.onclick = function() { |
244 |
startStopButton.setAttribute('value', toggle() ? 'Stop' : 'Start'); |
245 |
}; |
246 |
documentBody.appendChild(startStopButton); |
247 |
|
248 |
var clearButton = windowDocument.createElement('input'); |
249 |
clearButton.style.margin = '2px'; |
250 |
clearButton.setAttribute('type', 'button'); |
251 |
clearButton.setAttribute('value', 'Clear'); |
252 |
documentBody.appendChild(clearButton); |
253 |
|
254 |
logContainer = documentBody.appendChild(windowDocument.createElement('pre')); |
255 |
logContainer.id = 'log-window'; |
256 |
var logContainerStyle = logContainer.style; |
257 |
logContainerStyle.width = '100%'; |
258 |
logContainerStyle.minHeight = '0'; |
259 |
logContainerStyle.maxHeight = '550px'; |
260 |
logContainerStyle.borderWidth = '1px'; |
261 |
logContainerStyle.borderStyle = 'solid'; |
262 |
logContainerStyle.borderColor = '#999'; |
263 |
logContainerStyle.backgroundColor = '#ddd'; |
264 |
logContainerStyle.overflow = 'scroll'; |
265 |
|
266 |
lineCountDropDown.onchange = function(event) { |
267 |
numberOfLines = lineOptions[lineCountDropDown.selectedIndex]; |
268 |
trimLines(); |
269 |
}; |
270 |
clearButton.onclick = trimAllLines; |
271 |
|
272 |
onUnload(window, function() { |
273 |
if (closeOnExit) { |
274 |
logEntry = noop; |
275 |
logWindow.close(); |
276 |
} |
277 |
}); |
278 |
} catch (e) { |
279 |
logWindow.close(); |
280 |
} |
281 |
} |
282 |
|
283 |
onKeyUp(document, function(evt) { |
284 |
var event = $event(evt, document.documentElement); |
285 |
if (keyCode(event) == 84 && isCtrlPressed(event) && isShiftPressed(event)) { |
286 |
showWindow(); |
287 |
logEntry = displayEntry; |
288 |
} |
289 |
}); |
290 |
|
291 |
return object(function(method) { |
292 |
method(threshold, function(self, priority) { |
293 |
thresholdPriority = priority; |
294 |
}); |
295 |
|
296 |
method(log, function(self, operation, category, message, exception) { |
297 |
operation(self, category, message, exception); |
298 |
}); |
299 |
|
300 |
method(debug, function(self, category, message, exception) { |
301 |
logEntry('debug', '#333', category, message, exception); |
302 |
}); |
303 |
|
304 |
method(info, function(self, category, message, exception) { |
305 |
logEntry('info', 'green', category, message, exception); |
306 |
}); |
307 |
|
308 |
method(warn, function(self, category, message, exception) { |
309 |
logEntry('warn', 'orange', category, message, exception); |
310 |
}); |
311 |
|
312 |
method(error, function(self, category, message, exception) { |
313 |
logEntry('error', 'red', category, message, exception); |
314 |
}); |
315 |
}); |
316 |
} |