~ubuntu-branches/ubuntu/lucid/loggerhead/lucid-security

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/console/console-debug.js

  • Committer: Bazaar Package Importer
  • Author(s): James Westby, Roland Mas, Jelmer Vernooij, James Westby
  • Date: 2009-08-26 13:18:03 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090826131803-0ce1fhaetci8b0c5
Tags: 1.17-0ubuntu1
[ Roland Mas ]
* Use the YUI library provided by libjs-yui. (Closes: #511286)

[ Jelmer Vernooij ]
* Use my debian.org address in Uploaders field.
* Add ${misc:Depends} to please lintian.
* Suggest recent version of paste, which doesn't expose internal port
  numbers in links. (Closes: #507000)
* Bump standards version to 3.8.1.

[ James Westby ]
* New upstream release.
* Drop get-orig-source rule in favour of debian/watch.
* Add python-pkg-resources and python-paste to Build-Depends,
  python-pkg-resources to Depends and python-simplejson to
  Recommends due to dependency changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
 
3
Code licensed under the BSD License:
 
4
http://developer.yahoo.net/yui/license.txt
 
5
version: 3.0.0pr2
 
6
*/
 
7
YUI.add('console', function(Y) {
 
8
 
 
9
/**
 
10
 * A user interface for viewing log messages.
 
11
 *
 
12
 * @module console
 
13
 */
 
14
 
 
15
var getCN = Y.ClassNameManager.getClassName,
 
16
    CONSOLE        = 'console',
 
17
    ENTRY          = 'entry',
 
18
    RESET          = 'reset',
 
19
    CHECKED        = 'checked',
 
20
    TITLE          = 'title',
 
21
    PAUSE          = 'pause',
 
22
    PAUSED         = 'paused',
 
23
    CLEAR          = 'clear',
 
24
    INFO           = 'info',
 
25
    WARN           = 'warn',
 
26
    ERROR          = 'error',
 
27
    INNER_HTML     = 'innerHTML',
 
28
    CLICK          = 'click',
 
29
    CONTENT_BOX    = 'contentBox',
 
30
    DISABLED       = 'disabled',
 
31
    START_TIME     = 'startTime',
 
32
    LAST_TIME      = 'lastTime',
 
33
    ENTRY_TEMPLATE = 'entryTemplate',
 
34
    RENDERED       = 'rendered',
 
35
 
 
36
    DOT = '.',
 
37
 
 
38
    C_ENTRY            = getCN(CONSOLE,ENTRY),
 
39
    C_PAUSE            = getCN(CONSOLE,PAUSE),
 
40
    C_CHECKBOX         = getCN(CONSOLE,'checkbox'),
 
41
    C_BUTTON           = getCN(CONSOLE,'button'),
 
42
    C_CLEAR            = getCN(CONSOLE,CLEAR),
 
43
    C_PAUSE_LABEL      = getCN(CONSOLE,PAUSE,'label'),
 
44
    C_ENTRY_META       = getCN(CONSOLE,ENTRY,'meta'),
 
45
    C_ENTRY_CAT        = getCN(CONSOLE,ENTRY,'cat'),
 
46
    C_ENTRY_SRC        = getCN(CONSOLE,ENTRY,'src'),
 
47
    C_ENTRY_TIME       = getCN(CONSOLE,ENTRY,'time'),
 
48
    C_ENTRY_CONTENT    = getCN(CONSOLE,ENTRY,'content'),
 
49
    C_CONSOLE_HD       = getCN(CONSOLE,'hd'),
 
50
    C_CONSOLE_BD       = getCN(CONSOLE,'bd'),
 
51
    C_CONSOLE_FT       = getCN(CONSOLE,'ft'),
 
52
    C_CONSOLE_CONTROLS = getCN(CONSOLE,'controls'),
 
53
    C_CONSOLE_TITLE    = getCN(CONSOLE,TITLE),
 
54
 
 
55
    RE_INLINE_SOURCE = /^(\S+)\s/,
 
56
    RE_AMP = /&/g,
 
57
    RE_LT  = /</g,
 
58
    RE_GT  = />/g,
 
59
 
 
60
    ESC_AMP = '&#38;',
 
61
    ESC_LT  = '&#60;',
 
62
    ESC_GT  = '&#62;',
 
63
    
 
64
    L = Y.Lang,
 
65
    isString   = L.isString,
 
66
    isNumber   = L.isNumber,
 
67
    isObject   = L.isObject,
 
68
    merge      = Y.merge,
 
69
    substitute = Y.substitute,
 
70
    create     = Y.Node.create;
 
71
    
 
72
/**
 
73
 * Console creates a visualization for messages logged through calls to a YUI
 
74
 * instance's <code>Y.log( message, category, source )</code> method.  The
 
75
 * debug versions of YUI modules will include logging statements to offer some
 
76
 * insight into the steps executed during that module's operation.  Including
 
77
 * log statements in your code will cause those messages to also appear in the
 
78
 * Console.  Use Console to aid in developing your page or application.
 
79
 *
 
80
 * Entry categories are also referred to as the log level, and entries are
 
81
 * filtered against the configured logLevel.
 
82
 *
 
83
 * @class Console
 
84
 * @extends Widget
 
85
 */
 
86
 
 
87
function Console() {
 
88
    Console.superclass.constructor.apply(this,arguments);
 
89
}
 
90
 
 
91
Y.mix(Console, {
 
92
 
 
93
    /**
 
94
     * The identity of the widget.
 
95
     *
 
96
     * @property Console.NAME
 
97
     * @type String
 
98
     * @static
 
99
     */
 
100
    NAME : CONSOLE,
 
101
 
 
102
    /**
 
103
     * Static identifier for logLevel configuration setting to allow all
 
104
     * incoming messages to generate Console entries.
 
105
     *
 
106
     * @property Console.LOG_LEVEL_INFO
 
107
     * @type Number
 
108
     * @static
 
109
     */
 
110
    LOG_LEVEL_INFO  : 3,
 
111
 
 
112
    /**
 
113
     * Static identifier for logLevel configuration setting to allow only
 
114
     * incoming messages of logLevel &quot;warn&quot; or &quot;error&quot;
 
115
     * to generate Console entries.
 
116
     *
 
117
     * @property Console.LOG_LEVEL_WARN
 
118
     * @type Number
 
119
     * @static
 
120
     */
 
121
    LOG_LEVEL_WARN  : 2,
 
122
 
 
123
    /**
 
124
     * Static identifier for logLevel configuration setting to allow only
 
125
     * incoming messages of logLevel &quot;error&quot; to generate
 
126
     * Console entries.
 
127
     *
 
128
     * @property Console.LOG_LEVEL_ERROR
 
129
     * @type Number
 
130
     * @static
 
131
     */
 
132
    LOG_LEVEL_ERROR : 1,
 
133
 
 
134
    /**
 
135
     * Map (object) of classNames used to populate the placeholders in the
 
136
     * Console.ENTRY_TEMPLATE markup when rendering a new Console entry.
 
137
     *
 
138
     * <p>By default, the keys contained in the object are:</p>
 
139
     * <ul>
 
140
     *    <li>entry_class</li>
 
141
     *    <li>entry_meta_class</li>
 
142
     *    <li>entry_cat_class</li>
 
143
     *    <li>entry_src_class</li>
 
144
     *    <li>entry_time_class</li>
 
145
     *    <li>entry_content_class</li>
 
146
     * </ul>
 
147
     *
 
148
     * @property Console.ENTRY_CLASSES
 
149
     * @type Object
 
150
     * @static
 
151
     */
 
152
    ENTRY_CLASSES   : {
 
153
        entry_class         : C_ENTRY,
 
154
        entry_meta_class    : C_ENTRY_META,
 
155
        entry_cat_class     : C_ENTRY_CAT,
 
156
        entry_src_class     : C_ENTRY_SRC,
 
157
        entry_time_class    : C_ENTRY_TIME,
 
158
        entry_content_class : C_ENTRY_CONTENT
 
159
    },
 
160
 
 
161
    /**
 
162
     * Map (object) of classNames used to populate the placeholders in the
 
163
     * Console.HEADER_TEMPLATE, Console.BODY_TEMPLATE, and
 
164
     * Console.FOOTER_TEMPLATE markup when rendering the Console UI.
 
165
     *
 
166
     * <p>By default, the keys contained in the object are:</p>
 
167
     * <ul>
 
168
     *   <li>console_hd_class</li>
 
169
     *   <li>console_bd_class</li>
 
170
     *   <li>console_ft_class</li>
 
171
     *   <li>console_controls_class</li>
 
172
     *   <li>console_checkbox_class</li>
 
173
     *   <li>console_pause_class</li>
 
174
     *   <li>console_pause_label_class</li>
 
175
     *   <li>console_button_class</li>
 
176
     *   <li>console_clear_class</li>
 
177
     *   <li>console_title_class</li>
 
178
     * </ul>
 
179
     *
 
180
     * @property Console.CHROME_CLASSES
 
181
     * @type Object
 
182
     * @static
 
183
     */
 
184
    CHROME_CLASSES  : {
 
185
        console_hd_class       : C_CONSOLE_HD,
 
186
        console_bd_class       : C_CONSOLE_BD,
 
187
        console_ft_class       : C_CONSOLE_FT,
 
188
        console_controls_class : C_CONSOLE_CONTROLS,
 
189
        console_checkbox_class : C_CHECKBOX,
 
190
        console_pause_class    : C_PAUSE,
 
191
        console_pause_label_class : C_PAUSE_LABEL,
 
192
        console_button_class   : C_BUTTON,
 
193
        console_clear_class    : C_CLEAR,
 
194
        console_title_class    : C_CONSOLE_TITLE
 
195
    },
 
196
 
 
197
    /**
 
198
     * Markup template used to generate the DOM structure for the header
 
199
     * section of the Console when it is rendered.  The template includes
 
200
     * these {placeholder}s:
 
201
     *
 
202
     * <ul>
 
203
     *   <li>console_hd_class - contributed by Console.CHROME_CLASSES</li>
 
204
     *   <li>console_title_class - contributed by Console.CHROME_CLASSES</li>
 
205
     *   <li>str_title - pulled from attribute strings.title</li>
 
206
     * </ul>
 
207
     *
 
208
     * @property Console.HEADER_TEMPLATE
 
209
     * @type String
 
210
     * @static
 
211
     */
 
212
    HEADER_TEMPLATE :
 
213
        '<div class="{console_hd_class}">'+
 
214
            '<h4 class="{console_title_class}">{str_title}</h4>'+
 
215
        '</div>',
 
216
 
 
217
    /**
 
218
     * Markup template used to generate the DOM structure for the Console body
 
219
     * (where the messages are inserted) when it is rendered.  The template
 
220
     * includes only the {placeholder} &quot;console_bd_class&quot;, which is
 
221
     * constributed by Console.CHROME_CLASSES.
 
222
     *
 
223
     * @property Console.BODY_TEMPLATE
 
224
     * @type String
 
225
     * @static
 
226
     */
 
227
    BODY_TEMPLATE : '<div class="{console_bd_class}"></div>',
 
228
 
 
229
    /**
 
230
     * Markup template used to generate the DOM structure for the footer
 
231
     * section of the Console when it is rendered.  The template includes
 
232
     * many of the {placeholder}s from Console.CHROME_CLASSES as well as:
 
233
     *
 
234
     * <ul>
 
235
     *   <li>id_guid - generated unique id, relates the label and checkbox</li>
 
236
     *   <li>str_pause - pulled from attribute strings.pause</li>
 
237
     *   <li>str_clear - pulled from attribute strings.clear</li>
 
238
     * </ul>
 
239
     *
 
240
     * @property Console.HEADER_TEMPLATE
 
241
     * @type String
 
242
     * @static
 
243
     */
 
244
    FOOTER_TEMPLATE :
 
245
        '<div class="{console_ft_class}">'+
 
246
            '<div class="{console_controls_class}">'+
 
247
                '<input type="checkbox" class="{console_checkbox_class} '+
 
248
                        '{console_pause_class}" value="1" id="{id_guid}"> '+
 
249
                '<label for="{id_guid}" class="{console_pause_label_class}">'+
 
250
                    '{str_pause}</label>' +
 
251
                '<input type="button" class="'+
 
252
                    '{console_button_class} {console_clear_class}" '+
 
253
                    'value="{str_clear}">'+
 
254
            '</div>'+
 
255
        '</div>',
 
256
 
 
257
    /**
 
258
     * Default markup template used to create the DOM structure for Console
 
259
     * entries. The markup contains {placeholder}s for content and classes
 
260
     * that are replaced via Y.substitute.  The default template contains
 
261
     * the {placeholder}s identified in Console.ENTRY_CLASSES as well as the
 
262
     * following placeholders that will be populated by the log entry data:
 
263
     *
 
264
     * <ul>
 
265
     *   <li>cat_class</li>
 
266
     *   <li>src_class</li>
 
267
     *   <li>label</li>
 
268
     *   <li>totalTime</li>
 
269
     *   <li>elapsedTime</li>
 
270
     *   <li>localTime</li>
 
271
     *   <li>sourceAndDetail</li>
 
272
     *   <li>message</li>
 
273
     * </ul>
 
274
     *
 
275
     * @property Console.ENTRY_TEMPLATE
 
276
     * @type String
 
277
     * @static
 
278
     */
 
279
    ENTRY_TEMPLATE :
 
280
        '<pre class="{entry_class} {cat_class} {src_class}">'+
 
281
            '<div class="{entry_meta_class}">'+
 
282
                '<p>'+
 
283
                    '<span class="{entry_cat_class}">'+
 
284
                        '{label}</span>'+
 
285
                    '<span class="{entry_time_class}">'+
 
286
                        ' {totalTime}ms (+{elapsedTime}) {localTime}:'+
 
287
                    '</span>'+
 
288
                '</p>'+
 
289
                '<p class="{entry_src_class}">'+
 
290
                    '{sourceAndDetail}'+
 
291
                '</p>'+
 
292
            '</div>'+
 
293
            '<p class="{entry_content_class}">{message}</p>'+
 
294
        '</pre>',
 
295
 
 
296
    /**
 
297
     * Static property used to define the default attribute configuration of
 
298
     * the Widget.
 
299
     *
 
300
     * @property Console.ATTRS
 
301
     * @Type Object
 
302
     * @static
 
303
     */
 
304
    ATTRS : {
 
305
 
 
306
        /**
 
307
         * Name of the custom event that will communicate log messages.
 
308
         *
 
309
         * @attribute logEvent
 
310
         * @type String
 
311
         * @default "yui:log"
 
312
         */
 
313
        logEvent : {
 
314
            value : 'yui:log',
 
315
            writeOnce : true,
 
316
            validator : isString
 
317
        },
 
318
 
 
319
        /**
 
320
         * Collection of strings used to label elements in the Console UI.
 
321
         * Default collection contains the following name:value pairs:
 
322
         *
 
323
         * <ul>
 
324
         *   <li>title : &quot;Log Console&quot;</li>
 
325
         *   <li>pause : &quot;Pause&quot;</li>
 
326
         *   <li>clear : &quot;Clear&quot;</li>
 
327
         * </ul>
 
328
         *
 
329
         * @attribute strings
 
330
         * @type Object
 
331
         */
 
332
        strings : {
 
333
            value : {
 
334
                title : "Log Console",
 
335
                pause : "Pause",
 
336
                clear : "Clear"
 
337
            }
 
338
        },
 
339
 
 
340
        /**
 
341
         * Boolean to pause the outputting of new messages to the console.
 
342
         * When paused, messages will accumulate in the buffer.
 
343
         *
 
344
         * @attribute paused
 
345
         * @type boolean
 
346
         * @default false
 
347
         */
 
348
        paused : {
 
349
            value : false,
 
350
            validator : L.isBoolean
 
351
        },
 
352
 
 
353
        /**
 
354
         * If a category is not specified in the Y.log(..) statement, this
 
355
         * category will be used. Category is also called &quot;log level&quot;.
 
356
         *
 
357
         * @attribute defaultCategory
 
358
         * @type String
 
359
         * @default "info"
 
360
         */
 
361
        defaultCategory : {
 
362
            value : INFO,
 
363
            validator : isString
 
364
        },
 
365
 
 
366
        /**
 
367
         * If a source is not specified in the Y.log(..) statement, this
 
368
         * source will be used.
 
369
         *
 
370
         * @attribute defaultSource
 
371
         * @type String
 
372
         * @default "global"
 
373
         */
 
374
        defaultSource   : {
 
375
            value : 'global',
 
376
            validator : isString
 
377
        },
 
378
 
 
379
        /**
 
380
         * Markup template used to create the DOM structure for Console entries.
 
381
         *
 
382
         * @attribute entryTemplate
 
383
         * @type String
 
384
         * @default (see Console.ENTRY_TEMPLATE)
 
385
         */
 
386
        entryTemplate : {
 
387
            value : '',
 
388
            validator : isString
 
389
        },
 
390
 
 
391
        /**
 
392
         * Minimum entry log level to render into the Console.  The initial
 
393
         * logLevel value for all Console instances defaults from the
 
394
         * Y.config.logLevel YUI configuration, or Console.LOG_LEVEL_INFO if
 
395
         * that configuration is not set.
 
396
         *
 
397
         * Possible values are &quot;info&quot;, &quot;warn&quot;,
 
398
         * &quot;error&quot; (case insensitive), or the corresponding statics
 
399
         * Console.LOG_LEVEL_INFO and so on.
 
400
         *
 
401
         * @attribute logLevel
 
402
         * @type String|Number
 
403
         * @default Y.config.logLevel or Console.LOG_LEVEL_INFO
 
404
         */
 
405
        logLevel : {
 
406
            value : Y.config.logLevel,
 
407
            validator : function (v) {
 
408
                return this._validateNewLogLevel(v);
 
409
            },
 
410
            set : function (v) {
 
411
                return this._setLogLevel(v);
 
412
            }
 
413
        },
 
414
 
 
415
        /**
 
416
         * Millisecond timeout to maintain before emptying buffer of Console
 
417
         * entries to the UI.
 
418
         *
 
419
         * @attribute printTimeout
 
420
         * @type Number
 
421
         * @default 100
 
422
         */
 
423
        printTimeout : {
 
424
            value : 100,
 
425
            validator : isNumber
 
426
        },
 
427
 
 
428
        /**
 
429
         * Maximum number of Console entries allowed in the Console body at one
 
430
         * time.  This is used to keep acquired messages from exploding the
 
431
         * DOM tree and impacting page performance.
 
432
         *
 
433
         * @attribute consoleLimit
 
434
         * @type Number
 
435
         * @default 500
 
436
         */
 
437
        consoleLimit : {
 
438
            value : 500,
 
439
            validator : isNumber
 
440
        },
 
441
 
 
442
        /**
 
443
         * New entries should display at the top of the Console or the bottom?
 
444
         *
 
445
         * @attribute newestOnTop
 
446
         * @type Boolean
 
447
         * @default true
 
448
         */
 
449
        newestOnTop : {
 
450
            value : true
 
451
        },
 
452
 
 
453
        /**
 
454
         * When new entries are added to the Console UI, should they be
 
455
         * scrolled into view?
 
456
         *
 
457
         * @attribute scrollIntoView
 
458
         * @type Boolean
 
459
         * @default true
 
460
         */
 
461
        scrollIntoView : {
 
462
            value : true
 
463
        },
 
464
 
 
465
        /**
 
466
         * The baseline time for this Console instance, used to measure elapsed
 
467
         * time from the moment the console module is <code>use</code>d to the
 
468
         * moment each new entry is logged (not rendered).
 
469
         *
 
470
         * This value is reset by the instance method myConsole.reset().
 
471
         *
 
472
         * @attribute startTime
 
473
         * @type Date
 
474
         * @default The moment the console module is <code>use</code>d
 
475
         */
 
476
        startTime : {
 
477
            value : new Date()
 
478
        },
 
479
 
 
480
        /**
 
481
         * The precise time the last entry was logged.  Used to measure elapsed
 
482
         * time between log messages.
 
483
         *
 
484
         * @attribute lastTime
 
485
         * @type Date
 
486
         * @default The moment the console module is <code>use</code>d
 
487
         */
 
488
        lastTime : {
 
489
            value : new Date(),
 
490
            readOnly: true
 
491
        }
 
492
 
 
493
    }
 
494
 
 
495
});
 
496
 
 
497
Y.extend(Console,Y.Widget,{
 
498
 
 
499
    /**
 
500
     * Reference to the Node instance containing the head contents.
 
501
     *
 
502
     * @property _head
 
503
     * @type Node
 
504
     * @default null
 
505
     * @protected
 
506
     */
 
507
    _head    : null,
 
508
 
 
509
    /**
 
510
     * Reference to the Node instance that will house the console messages.
 
511
     *
 
512
     * @property _body
 
513
     * @type Node
 
514
     * @default null
 
515
     * @protected
 
516
     */
 
517
    _body    : null,
 
518
 
 
519
    /**
 
520
     * Reference to the Node instance containing the footer contents.
 
521
     *
 
522
     * @property _head
 
523
     * @type Node
 
524
     * @default null
 
525
     * @protected
 
526
     */
 
527
    _foot    : null,
 
528
 
 
529
    /**
 
530
     * Object API returned from <code>Y.later</code>. Holds the timer id
 
531
     * returned by <code>setTimout</code> for scheduling of buffered messages.
 
532
     *
 
533
     * @property _timeout
 
534
     * @type Object
 
535
     * @default null
 
536
     * @protected
 
537
     */
 
538
    _timeout : null,
 
539
 
 
540
    /**
 
541
     * Array of normalized message objects awaiting printing.
 
542
     *
 
543
     * @property buffer
 
544
     * @type Array
 
545
     * @default null
 
546
     */
 
547
    buffer   : null,
 
548
 
 
549
    /**
 
550
     * Wrapper for <code>Y.log</code>.
 
551
     *
 
552
     * @method log
 
553
     * @param {Any*} * (all arguments passed through to <code>Y.log</code>)
 
554
     */
 
555
    log : function () {
 
556
        return Y.log.apply(Y,arguments);
 
557
    },
 
558
 
 
559
    /**
 
560
     * Clear the console of messages and flush the buffer of pending messages.
 
561
     *
 
562
     * @method clearConsole
 
563
     * @chainable
 
564
     */
 
565
    clearConsole : function () {
 
566
        // TODO: clear event listeners from console contents
 
567
        this._body.set(INNER_HTML,'');
 
568
 
 
569
        this._clearTimeout();
 
570
 
 
571
        this.buffer = [];
 
572
 
 
573
        return this;
 
574
    },
 
575
 
 
576
    /**
 
577
     * Clears the console and resets internal timers.
 
578
     *
 
579
     * @method reset
 
580
     * @chainable
 
581
     */
 
582
    reset : function () {
 
583
        this.fire(RESET);
 
584
        
 
585
        return this;
 
586
    },
 
587
 
 
588
    /**
 
589
     * Outputs all buffered messages to the console UI.
 
590
     * 
 
591
     * @method printBuffer
 
592
     * @chainable
 
593
     */
 
594
    printBuffer: function () {
 
595
        if (!this.get(PAUSED) && this.get('rendered')) {
 
596
 
 
597
            this._clearTimeout();
 
598
 
 
599
            var messages = this.buffer,
 
600
                i,len;
 
601
 
 
602
            this.buffer = [];
 
603
 
 
604
            // TODO: use doc frag
 
605
            for (i = 0, len = messages.length; i < len; ++i) {
 
606
                this.printLogEntry(messages[i]);
 
607
            }
 
608
 
 
609
            this._trimOldEntries();
 
610
        }
 
611
 
 
612
        return this;
 
613
    },
 
614
 
 
615
    /**
 
616
     * Prints the provided message to the console UI.
 
617
     *
 
618
     * @method printLogEntry
 
619
     * @param m {Object} Normalized message object
 
620
     * @chainable
 
621
     */
 
622
    printLogEntry : function (m) {
 
623
        m = merge(
 
624
                this._htmlEscapeMessage(m),
 
625
                Console.ENTRY_CLASSES,
 
626
                {
 
627
                    cat_class : this.getClassName(ENTRY,m.category),
 
628
                    src_class : this.getClassName(ENTRY,m.source)
 
629
                });
 
630
 
 
631
        var n = create(substitute(this.get('entryTemplate'),m));
 
632
 
 
633
        this._addToConsole(n);
 
634
 
 
635
        return this;
 
636
    },
 
637
 
 
638
    
 
639
    /**
 
640
     * Constructor code.  Set up the buffer and entry template, publish
 
641
     * internal events, and subscribe to the configured logEvent.
 
642
     * 
 
643
     * @method initializer
 
644
     * @protected
 
645
     */
 
646
    initializer : function () {
 
647
        this.buffer    = [];
 
648
 
 
649
        if (!this.get(ENTRY_TEMPLATE)) {
 
650
            this.set(ENTRY_TEMPLATE,Console.ENTRY_TEMPLATE);
 
651
        }
 
652
 
 
653
        Y.on(this.get('logEvent'),Y.bind(this._onLogEvent,this));
 
654
 
 
655
        /**
 
656
         * Triggers the processing of an incoming message via the default logic
 
657
         * in _defEntryFn.
 
658
         *
 
659
         * @event entry
 
660
         * @param event {Event.Facade} An Event Facade object with the following attribute specific properties added:
 
661
         *  <dl>
 
662
         *      <dt>message</dt>
 
663
         *          <dd>The message data normalized into an object literal (see _normalizeMessage)</dd>
 
664
         *  </dl>
 
665
         * @preventable _defEntryFn
 
666
         */
 
667
        this.publish(ENTRY, { defaultFn: this._defEntryFn });
 
668
 
 
669
        /**
 
670
         * Triggers the reset behavior via the default logic in _defResetFn.
 
671
         *
 
672
         * @event reset
 
673
         * @param event {Event.Facade} Event Facade object
 
674
         * @preventable _defResetFn
 
675
         */
 
676
        this.publish(RESET, { defaultFn: this._defResetFn });
 
677
    },
 
678
 
 
679
    /**
 
680
     * Generate the Console UI.
 
681
     *
 
682
     * @method renderUI
 
683
     * @protected
 
684
     */
 
685
    renderUI : function () {
 
686
        this._initHead();
 
687
        this._initConsole();
 
688
        this._initFoot();
 
689
    },
 
690
 
 
691
    /**
 
692
     * Sync the UI state to the current attribute state.
 
693
     *
 
694
     * @method syncUI
 
695
     */
 
696
    syncUI : function () {
 
697
        this.set(PAUSED,this.get(PAUSED));
 
698
    },
 
699
 
 
700
    /**
 
701
     * Set up event listeners to wire up the UI to the internal state.
 
702
     *
 
703
     * @method bindUI
 
704
     * @protected
 
705
     */
 
706
    bindUI : function () {
 
707
        this.get(CONTENT_BOX).query('input[type=checkbox].'+C_PAUSE).
 
708
            on(CLICK,this._onPauseClick,this);
 
709
 
 
710
        this.get(CONTENT_BOX).query('input[type=button].'+C_CLEAR).
 
711
            on(CLICK,this._onClearClick,this);
 
712
        
 
713
        // Attribute changes
 
714
        this.after('stringsChange',       this._afterStringsChange);
 
715
        this.after('pausedChange',        this._afterPausedChange);
 
716
        this.after('consoleLimitChange',  this._afterConsoleLimitChange);
 
717
    },
 
718
 
 
719
    
 
720
    /**
 
721
     * Create the DOM structure for the header elements.
 
722
     *
 
723
     * @method _initHead
 
724
     * @protected
 
725
     */
 
726
    _initHead : function () {
 
727
        var cb   = this.get(CONTENT_BOX),
 
728
            info = merge(Console.CHROME_CLASSES, {
 
729
                        str_title : this.get('strings.title')
 
730
                    });
 
731
 
 
732
        this._head = create(substitute(Console.HEADER_TEMPLATE,info));
 
733
 
 
734
        cb.insertBefore(this._head,cb.get('firstChild'));
 
735
    },
 
736
 
 
737
    /**
 
738
     * Create the DOM structure for the console body&#8212;where messages are
 
739
     * rendered.
 
740
     *
 
741
     * @method _initConsole
 
742
     * @protected
 
743
     */
 
744
    _initConsole : function () {
 
745
        this._body = create(substitute(
 
746
                            Console.BODY_TEMPLATE,
 
747
                            Console.CHROME_CLASSES));
 
748
 
 
749
        this.get(CONTENT_BOX).appendChild(this._body);
 
750
    },
 
751
 
 
752
    /**
 
753
     * Create the DOM structure for the footer elements.
 
754
     *
 
755
     * @method _initFoot
 
756
     * @protected
 
757
     */
 
758
    _initFoot : function () {
 
759
        var info = merge(Console.CHROME_CLASSES, {
 
760
                id_guid   : Y.guid(),
 
761
                str_pause : this.get('strings.pause'),
 
762
                str_clear : this.get('strings.clear')
 
763
            });
 
764
 
 
765
        this._foot = create(substitute(Console.FOOTER_TEMPLATE,info));
 
766
 
 
767
        this.get(CONTENT_BOX).appendChild(this._foot);
 
768
    },
 
769
 
 
770
    /**
 
771
     * Determine if incoming log messages are within the configured logLevel
 
772
     * to be buffered for printing.
 
773
     *
 
774
     * @method _isInLogLevel
 
775
     * @protected
 
776
     */
 
777
    _isInLogLevel : function (msg,cat) {
 
778
        var lvl = this.get('logLevel'),
 
779
            mlvl = cat === ERROR ? Console.LOG_LEVEL_ERROR :
 
780
                    cat === WARN ? Console.LOG_LEVEL_WARN  :
 
781
                                   Console.LOG_LEVEL_INFO;
 
782
 
 
783
        return lvl >= mlvl;
 
784
    },
 
785
 
 
786
    /**
 
787
     * Create a log entry message from the inputs including the following keys:
 
788
     * <ul>
 
789
     *     <li>time - this moment</li>
 
790
     *     <li>message - leg message</li>
 
791
     *     <li>category - aka logLevel</li>
 
792
     *     <li>source - when provided, the widget or util calling Y.log</li>
 
793
     *     <li>sourceAndDetail - same as source but can include instance info</li>
 
794
     *     <li>label - logLevel/category label for the entry</li>
 
795
     *     <li>localTime - readable version of time</li>
 
796
     *     <li>elapsedTime - ms since last entry</li>
 
797
     *     <li>totalTime - ms since Console was instantiated or reset</li>
 
798
     * </ul>
 
799
     *
 
800
     * @mehod _normalizeMessage
 
801
     * @param msg {String} the log message
 
802
     * @param cat {String} OPTIONAL the category or logLevel of the message
 
803
     * @param src {String} OPTIONAL the source widget or util of the message
 
804
     * @return Object the message object
 
805
     * @protected
 
806
     */
 
807
    _normalizeMessage : function (msg,cat,src) {
 
808
        var m = {
 
809
            time            : new Date(),
 
810
            message         : msg,
 
811
            category        : cat || this.get('defaultCategory'),
 
812
            sourceAndDetail : src || this.get('defaultSource'),
 
813
            source          : null,
 
814
            label           : null,
 
815
            localTime       : null,
 
816
            elapsedTime     : null,
 
817
            totalTime       : null
 
818
        };
 
819
 
 
820
        // Extract m.source "Foo" from m.sourceAndDetail "Foo bar baz"
 
821
        m.source          = RE_INLINE_SOURCE.test(m.sourceAndDetail) ?
 
822
                                RegExp.$1 : m.sourceAndDetail;
 
823
        m.label           = m.category;
 
824
        m.localTime       = m.time.toLocaleTimeString ? 
 
825
                            m.time.toLocaleTimeString() : (m.time + '');
 
826
        m.elapsedTime     = m.time - this.get(LAST_TIME);
 
827
        m.totalTime       = m.time - this.get(START_TIME);
 
828
 
 
829
        this._set(LAST_TIME,m.time);
 
830
 
 
831
        return m;
 
832
    },
 
833
 
 
834
    /**
 
835
     * Sets a timeout for buffered messages to be output to the console.
 
836
     *
 
837
     * @method _schedulePrint
 
838
     * @protected
 
839
     */
 
840
    _schedulePrint : function () {
 
841
        if (!this.get(PAUSED) && !this._timeout) {
 
842
            this._timeout = Y.later(
 
843
                                this.get('printTimeout'),
 
844
                                this,this.printBuffer);
 
845
        }
 
846
    },
 
847
 
 
848
    /**
 
849
     * Inserts a Node into the console body at the top or bottom depending on
 
850
     * the configuration value of newestOnTop.
 
851
     *
 
852
     * @method _addToConsole
 
853
     * @param node {Node} the node to insert into the console body
 
854
     * @protected
 
855
     */
 
856
    _addToConsole : function (node) {
 
857
        var toTop = this.get('newestOnTop'),
 
858
            bd    = this._body,
 
859
            scrollTop;
 
860
 
 
861
        bd.insertBefore(node,toTop ? bd.get('firstChild') : null);
 
862
 
 
863
        if (this.get('scrollIntoView')) {
 
864
            scrollTop = toTop ? 0 : bd.get('scrollHeight');
 
865
 
 
866
            bd.set('scrollTop', scrollTop);
 
867
        }
 
868
    },
 
869
 
 
870
    /**
 
871
     * Performs HTML escaping on strings in the message object.
 
872
     *
 
873
     * @method _htmlEscapeMessage
 
874
     * @param m {Object} the normalized message object
 
875
     * @return Object a clone of the message object with proper escapement
 
876
     * @protected
 
877
     */
 
878
    _htmlEscapeMessage : function (m) {
 
879
        m = Y.clone(m);
 
880
        m.message         = this._encodeHTML(m.message);
 
881
        m.label           = this._encodeHTML(m.label);
 
882
        m.source          = this._encodeHTML(m.source);
 
883
        m.sourceAndDetail = this._encodeHTML(m.sourceAndDetail);
 
884
        m.category        = this._encodeHTML(m.category);
 
885
 
 
886
        return m;
 
887
    },
 
888
 
 
889
    /**
 
890
     * Removes the oldest message entries from the UI to maintain the limit
 
891
     * specified in the consoleLimit configuration.
 
892
     *
 
893
     * @method _trimOldEntries
 
894
     * @protected
 
895
     */
 
896
    _trimOldEntries : function () {
 
897
        var bd = this._body;
 
898
 
 
899
        if (bd) {
 
900
            var entries = bd.queryAll(DOT+C_ENTRY),
 
901
                i = entries ? entries.size() - this.get('consoleLimit') : 0;
 
902
 
 
903
            if (i > 0) {
 
904
                if (this.get('newestOnTop')) {
 
905
                    for (var l = entries.size(); i<l; i++) {
 
906
                        bd.removeChild(entries.item(i));
 
907
                    }
 
908
                } else {
 
909
                    for (;i>=0;--i) {
 
910
                        bd.removeChild(entries.item(i));
 
911
                    }
 
912
                }
 
913
            }
 
914
        }
 
915
    },
 
916
 
 
917
    /**
 
918
     * Returns the input string with ampersands (&amp;), &lt, and &gt; encoded
 
919
     * as HTML entities.
 
920
     *
 
921
     * @method _encodeHTML
 
922
     * @param s {String} the raw string
 
923
     * @return String the encoded string
 
924
     * @protected
 
925
     */
 
926
    _encodeHTML : function (s) {
 
927
        return isString(s) ?
 
928
            s.replace(RE_AMP,ESC_AMP).
 
929
              replace(RE_LT, ESC_LT).
 
930
              replace(RE_GT, ESC_GT) :
 
931
            s;
 
932
    },
 
933
 
 
934
    /**
 
935
     * Clears the timeout for printing buffered messages.
 
936
     *
 
937
     * @method _clearTimeout
 
938
     * @protected
 
939
     */
 
940
    _clearTimeout : function () {
 
941
        if (this._timeout) {
 
942
            this._timeout.cancel();
 
943
            this._timeout = null;
 
944
        }
 
945
    },
 
946
 
 
947
    /**
 
948
     * Event handler for clicking on the Pause checkbox to update the paused
 
949
     * attribute.
 
950
     *
 
951
     * @method _onPauseClick
 
952
     * @param e {Event} DOM event facade for the click event
 
953
     * @protected
 
954
     */
 
955
    _onPauseClick : function (e) {
 
956
        var paused = e.target.get(CHECKED);
 
957
 
 
958
        this.set(PAUSED,paused,{ src: Y.Widget.UI_SRC });
 
959
    },
 
960
 
 
961
    /**
 
962
     * Event handler for clicking on the Clear button.  Pass-through to
 
963
     * <code>this.clearConsole()</code>.
 
964
     *
 
965
     * @method _onClearClick
 
966
     * @param e {Event} DOM event facade for the click event
 
967
     * @protected
 
968
     */
 
969
    _onClearClick : function (e) {
 
970
        this.clearConsole();
 
971
    },
 
972
 
 
973
 
 
974
    /**
 
975
     * Setter method for logLevel attribute.  Acceptable values are
 
976
     * &quot;error&quot, &quot;warn&quot, &quot;info&quot, and
 
977
     * Y.Console.LOG_LEVEL_ERROR, Y.Console.LOG_LEVEL_WARN, 
 
978
     * Y.Console.LOG_LEVEL_INFO.  Any other value becomes
 
979
     * Y.Console.LOG_LEVEL_INFO.
 
980
     *
 
981
     * @method _setLogLevel
 
982
     * @param v {String|Number} String or numeric alias for the desired logLevel
 
983
     * @return Number LOG_LEVEL_ERROR, _WARN, or _INFO
 
984
     * @protected
 
985
     */
 
986
    _setLogLevel : function (v) {
 
987
        if (isString(v)) {
 
988
            v = v.toLowerCase();
 
989
            v = v === ERROR ?
 
990
                        Console.LOG_LEVEL_ERROR :
 
991
                        v === WARN ?
 
992
                            Console.LOG_LEVEL_WARN :
 
993
                            Console.LOG_LEVEL_INFO;
 
994
        } else if (!isNumber(v)) {
 
995
            v = Console.LOG_LEVEL_INFO;
 
996
        }
 
997
 
 
998
        return v;
 
999
    },
 
1000
 
 
1001
    /**
 
1002
     * Verifies input logLevel is one of Y.Console.LOG_LEVEL_ERROR,
 
1003
     * Y.Console.LOG_LEVEL_WARN, or Y.Console.LOG_LEVEL_INFO.
 
1004
     *
 
1005
     * @method _validateNewLogLevel
 
1006
     * @param v {Number} requested logLevel
 
1007
     * @return Boolean
 
1008
     * @protected
 
1009
     */
 
1010
    _validateNewLogLevel : function (v) {
 
1011
        return v === Console.LOG_LEVEL_INFO ||
 
1012
               v === Console.LOG_LEVEL_WARN ||
 
1013
               v === Console.LOG_LEVEL_ERROR;
 
1014
    },
 
1015
 
 
1016
    /**
 
1017
     * Updates the UI if changes are made to any of the strings in the strings
 
1018
     * attribute.
 
1019
     *
 
1020
     * @method _afterStringsChange
 
1021
     * @param e {Event} Custom event for the attribute change
 
1022
     * @protected
 
1023
     */
 
1024
    _afterStringsChange : function (e) {
 
1025
        var prop   = e.subAttrName ? e.subAttrName.split(DOT)[1] : null,
 
1026
            cb     = this.get(CONTENT_BOX),
 
1027
            before = e.prevVal,
 
1028
            after  = e.newVal,
 
1029
            el;
 
1030
 
 
1031
        if ((!prop || prop === TITLE) && before.title !== after.title) {
 
1032
            el = cb.query(DOT+C_CONSOLE_TITLE);
 
1033
            if (el) {
 
1034
                el.set(INNER_HTML,after.title);
 
1035
            }
 
1036
        }
 
1037
 
 
1038
        if ((!prop || prop === PAUSE) && before.pause !== after.pause) {
 
1039
            el = cb.query(DOT+C_PAUSE_LABEL);
 
1040
            if (el) {
 
1041
                el.set(INNER_HTML,after.pause);
 
1042
            }
 
1043
        }
 
1044
 
 
1045
        if ((!prop || prop === CLEAR) && before.clear !== after.clear) {
 
1046
            el = cb.query(DOT+C_CLEAR);
 
1047
            if (el) {
 
1048
                el.set('value',after.clear);
 
1049
            }
 
1050
        }
 
1051
    },
 
1052
 
 
1053
    /**
 
1054
     * Updates the UI and schedules or cancels the scheduled buffer printing
 
1055
     * operation.
 
1056
     *
 
1057
     * @method _afterPausedChange
 
1058
     * @param e {Event} Custom event for the attribute change
 
1059
     * @protected
 
1060
     */
 
1061
    _afterPausedChange : function (e) {
 
1062
        var paused = e.newVal;
 
1063
 
 
1064
        if (e.src !== Y.Widget.SRC_UI) {
 
1065
            var node = this._foot.queryAll('input[type=checkbox].'+C_PAUSE);
 
1066
            if (node) {
 
1067
                node.set(CHECKED,paused);
 
1068
            }
 
1069
        }
 
1070
 
 
1071
        if (!paused) {
 
1072
            this._schedulePrint();
 
1073
        } else if (this._timeout) {
 
1074
            clearTimeout(this._timeout);
 
1075
            this._timeout = null;
 
1076
        }
 
1077
    },
 
1078
 
 
1079
    /**
 
1080
     * Calls this._trimOldEntries() in response to changes in the configured
 
1081
     * consoleLimit attribute.
 
1082
     * 
 
1083
     * @method _afterConsoleLimitChange
 
1084
     * @param e {Event} Custom event for the attribute change
 
1085
     * @protected
 
1086
     */
 
1087
    _afterConsoleLimitChange : function () {
 
1088
        this._trimOldEntries();
 
1089
    },
 
1090
 
 
1091
 
 
1092
    /**
 
1093
     * Responds to log events by normalizing qualifying messages and passing
 
1094
     * them along through the entry event for buffering etc.
 
1095
     * 
 
1096
     * @method _onLogEvent
 
1097
     * @param msg {String} the log message
 
1098
     * @param cat {String} OPTIONAL the category or logLevel of the message
 
1099
     * @param src {String} OPTIONAL the source of the message (e.g. widget name)
 
1100
     * @protected
 
1101
     */
 
1102
    _onLogEvent : function (msg,cat,src) {
 
1103
 
 
1104
        if (!this.get(DISABLED) && this._isInLogLevel(msg,cat,src)) {
 
1105
 
 
1106
            /* TODO: needed? */
 
1107
            var debug = Y.config.debug;
 
1108
            Y.config.debug = false;
 
1109
 
 
1110
            this.fire(ENTRY, {
 
1111
                message : this._normalizeMessage.apply(this,arguments)
 
1112
            });
 
1113
 
 
1114
            Y.config.debug = debug;
 
1115
        }
 
1116
    },
 
1117
 
 
1118
    /**
 
1119
     * Clears the console, resets the startTime attribute, enables and
 
1120
     * unpauses the widget.
 
1121
     *
 
1122
     * @method _defResetFn
 
1123
     * @protected
 
1124
     */
 
1125
    _defResetFn : function () {
 
1126
        this.clearConsole();
 
1127
        this.set(START_TIME,new Date());
 
1128
        this.set(DISABLED,false);
 
1129
        this.set(PAUSED,false);
 
1130
    },
 
1131
 
 
1132
    /**
 
1133
     * Buffers incoming message objects and schedules the printing.
 
1134
     *
 
1135
     * @method _defEntryFn
 
1136
     * @param e {Event} The Custom event carrying the message in its payload
 
1137
     * @protected
 
1138
     */
 
1139
    _defEntryFn : function (e) {
 
1140
        if (e.message) {
 
1141
            this.buffer.push(e.message);
 
1142
            this._schedulePrint();
 
1143
        }
 
1144
    }
 
1145
 
 
1146
});
 
1147
 
 
1148
Y.Console = Console;
 
1149
 
 
1150
 
 
1151
}, '3.0.0pr2' ,{requires:['substitute','widget']});