Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('console', function (Y, NAME) {
2
 
3
/**
4
 * Console creates a visualization for messages logged through calls to a YUI
5
 * instance's <code>Y.log( message, category, source )</code> method.  The
6
 * debug versions of YUI modules will include logging statements to offer some
7
 * insight into the steps executed during that module's operation.  Including
8
 * log statements in your code will cause those messages to also appear in the
9
 * Console.  Use Console to aid in developing your page or application.
10
 *
11
 * Entry categories &quot;info&quot;, &quot;warn&quot;, and &quot;error&quot;
12
 * are also referred to as the log level, and entries are filtered against the
13
 * configured logLevel.
14
 *
15
 * @module console
16
 */
17
var getCN = Y.ClassNameManager.getClassName,
18
    CHECKED        = 'checked',
19
    CLEAR          = 'clear',
20
    CLICK          = 'click',
21
    COLLAPSED      = 'collapsed',
22
    CONSOLE        = 'console',
23
    CONTENT_BOX    = 'contentBox',
24
    DISABLED       = 'disabled',
25
    ENTRY          = 'entry',
26
    ERROR          = 'error',
27
    HEIGHT         = 'height',
28
    INFO           = 'info',
29
    LAST_TIME      = 'lastTime',
30
    PAUSE          = 'pause',
31
    PAUSED         = 'paused',
32
    RESET          = 'reset',
33
    START_TIME     = 'startTime',
34
    TITLE          = 'title',
35
    WARN           = 'warn',
36
 
37
    DOT = '.',
38
 
39
    C_BUTTON           = getCN(CONSOLE,'button'),
40
    C_CHECKBOX         = getCN(CONSOLE,'checkbox'),
41
    C_CLEAR            = getCN(CONSOLE,CLEAR),
42
    C_COLLAPSE         = getCN(CONSOLE,'collapse'),
43
    C_COLLAPSED        = getCN(CONSOLE,COLLAPSED),
44
    C_CONSOLE_CONTROLS = getCN(CONSOLE,'controls'),
45
    C_CONSOLE_HD       = getCN(CONSOLE,'hd'),
46
    C_CONSOLE_BD       = getCN(CONSOLE,'bd'),
47
    C_CONSOLE_FT       = getCN(CONSOLE,'ft'),
48
    C_CONSOLE_TITLE    = getCN(CONSOLE,TITLE),
49
    C_ENTRY            = getCN(CONSOLE,ENTRY),
50
    C_ENTRY_CAT        = getCN(CONSOLE,ENTRY,'cat'),
51
    C_ENTRY_CONTENT    = getCN(CONSOLE,ENTRY,'content'),
52
    C_ENTRY_META       = getCN(CONSOLE,ENTRY,'meta'),
53
    C_ENTRY_SRC        = getCN(CONSOLE,ENTRY,'src'),
54
    C_ENTRY_TIME       = getCN(CONSOLE,ENTRY,'time'),
55
    C_PAUSE            = getCN(CONSOLE,PAUSE),
56
    C_PAUSE_LABEL      = getCN(CONSOLE,PAUSE,'label'),
57
 
58
    RE_INLINE_SOURCE = /^(\S+)\s/,
59
    RE_AMP = /&(?!#?[a-z0-9]+;)/g,
60
    RE_GT  = />/g,
61
    RE_LT  = /</g,
62
 
63
    ESC_AMP = '&#38;',
64
    ESC_GT  = '&#62;',
65
    ESC_LT  = '&#60;',
66
 
67
    ENTRY_TEMPLATE_STR =
68
        '<div class="{entry_class} {cat_class} {src_class}">'+
69
            '<p class="{entry_meta_class}">'+
70
                '<span class="{entry_src_class}">'+
71
                    '{sourceAndDetail}'+
72
                '</span>'+
73
                '<span class="{entry_cat_class}">'+
74
                    '{category}</span>'+
75
                '<span class="{entry_time_class}">'+
76
                    ' {totalTime}ms (+{elapsedTime}) {localTime}'+
77
                '</span>'+
78
            '</p>'+
79
            '<pre class="{entry_content_class}">{message}</pre>'+
80
        '</div>',
81
 
82
    L = Y.Lang,
83
    create     = Y.Node.create,
84
    isNumber   = L.isNumber,
85
    isString   = L.isString,
86
    merge      = Y.merge,
87
    substitute = Y.Lang.sub;
88
 
89
/**
90
A basic console that displays messages logged throughout your application.
91
 
92
@class Console
93
@constructor
94
@extends Widget
95
@param [config] {Object} Object literal specifying widget configuration properties.
96
**/
97
function Console() {
98
    Console.superclass.constructor.apply(this,arguments);
99
}
100
 
101
Y.Console = Y.extend(Console, Y.Widget,
102
 
103
// Y.Console prototype
104
{
105
    /**
106
     * Category to prefix all event subscriptions to allow for ease of detach
107
     * during destroy.
108
     *
109
     * @property _evtCat
110
     * @type string
111
     * @protected
112
     */
113
    _evtCat : null,
114
 
115
    /**
116
     * Reference to the Node instance containing the header contents.
117
     *
118
     * @property _head
119
     * @type Node
120
     * @default null
121
     * @protected
122
     */
123
    _head    : null,
124
 
125
    /**
126
     * Reference to the Node instance that will house the console messages.
127
     *
128
     * @property _body
129
     * @type Node
130
     * @default null
131
     * @protected
132
     */
133
    _body    : null,
134
 
135
    /**
136
     * Reference to the Node instance containing the footer contents.
137
     *
138
     * @property _foot
139
     * @type Node
140
     * @default null
141
     * @protected
142
     */
143
    _foot    : null,
144
 
145
    /**
146
     * Holds the object API returned from <code>Y.later</code> for the print
147
     * loop interval.
148
     *
149
     * @property _printLoop
150
     * @type Object
151
     * @default null
152
     * @protected
153
     */
154
    _printLoop : null,
155
 
156
    /**
157
     * Array of normalized message objects awaiting printing.
158
     *
159
     * @property buffer
160
     * @type Array
161
     * @default null
162
     * @protected
163
     */
164
    buffer   : null,
165
 
166
    /**
167
     * Wrapper for <code>Y.log</code>.
168
     *
169
     * @method log
170
     * @param arg* {MIXED} (all arguments passed through to <code>Y.log</code>)
171
     * @chainable
172
     */
173
    log : function () {
174
        Y.log.apply(Y,arguments);
175
 
176
        return this;
177
    },
178
 
179
    /**
180
     * Clear the console of messages and flush the buffer of pending messages.
181
     *
182
     * @method clearConsole
183
     * @chainable
184
     */
185
    clearConsole : function () {
186
        // TODO: clear event listeners from console contents
187
        this._body.empty();
188
 
189
        this._cancelPrintLoop();
190
 
191
        this.buffer = [];
192
 
193
        return this;
194
    },
195
 
196
    /**
197
     * Clears the console and resets internal timers.
198
     *
199
     * @method reset
200
     * @chainable
201
     */
202
    reset : function () {
203
        this.fire(RESET);
204
 
205
        return this;
206
    },
207
 
208
    /**
209
     * Collapses the body and footer.
210
     *
211
     * @method collapse
212
     * @chainable
213
     */
214
    collapse : function () {
215
        this.set(COLLAPSED, true);
216
 
217
        return this;
218
    },
219
 
220
    /**
221
     * Expands the body and footer if collapsed.
222
     *
223
     * @method expand
224
     * @chainable
225
     */
226
    expand : function () {
227
        this.set(COLLAPSED, false);
228
 
229
        return this;
230
    },
231
 
232
    /**
233
     * Outputs buffered messages to the console UI.  This is typically called
234
     * from a scheduled interval until the buffer is empty (referred to as the
235
     * print loop).  The number of buffered messages output to the Console is
236
     * limited to the number provided as an argument.  If no limit is passed,
237
     * all buffered messages are rendered.
238
     *
239
     * @method printBuffer
240
     * @param limit {Number} (optional) max number of buffered entries to write
241
     * @chainable
242
     */
243
    printBuffer: function (limit) {
244
        var messages    = this.buffer,
245
            debug       = Y.config.debug,
246
            entries     = [],
247
            consoleLimit= this.get('consoleLimit'),
248
            newestOnTop = this.get('newestOnTop'),
249
            anchor      = newestOnTop ? this._body.get('firstChild') : null,
250
            i;
251
 
252
        if (messages.length > consoleLimit) {
253
            messages.splice(0, messages.length - consoleLimit);
254
        }
255
 
256
        limit = Math.min(messages.length, (limit || messages.length));
257
 
258
        // turn off logging system
259
        Y.config.debug = false;
260
 
261
        if (!this.get(PAUSED) && this.get('rendered')) {
262
 
263
            for (i = 0; i < limit && messages.length; ++i) {
264
                entries[i] = this._createEntryHTML(messages.shift());
265
            }
266
 
267
            if (!messages.length) {
268
                this._cancelPrintLoop();
269
            }
270
 
271
            if (entries.length) {
272
                if (newestOnTop) {
273
                    entries.reverse();
274
                }
275
 
276
                this._body.insertBefore(create(entries.join('')), anchor);
277
 
278
                if (this.get('scrollIntoView')) {
279
                    this.scrollToLatest();
280
                }
281
 
282
                this._trimOldEntries();
283
            }
284
        }
285
 
286
        // restore logging system
287
        Y.config.debug = debug;
288
 
289
        return this;
290
    },
291
 
292
 
293
    /**
294
     * Constructor code.  Set up the buffer and entry template, publish
295
     * internal events, and subscribe to the configured logEvent.
296
     *
297
     * @method initializer
298
     * @protected
299
     */
300
    initializer : function () {
301
        this._evtCat = Y.stamp(this) + '|';
302
 
303
        this.buffer = [];
304
 
305
        this.get('logSource').on(this._evtCat +
306
            this.get('logEvent'),Y.bind("_onLogEvent",this));
307
 
308
        /**
309
         * Transfers a received message to the print loop buffer.  Default
310
         * behavior defined in _defEntryFn.
311
         *
312
         * @event entry
313
         * @param event {EventFacade} An Event Facade object with the following attribute specific properties added:
314
         *  <dl>
315
         *      <dt>message</dt>
316
         *          <dd>The message data normalized into an object literal (see _normalizeMessage)</dd>
317
         *  </dl>
318
         * @preventable _defEntryFn
319
         */
320
        this.publish(ENTRY, { defaultFn: this._defEntryFn });
321
 
322
        /**
323
         * Triggers the reset behavior via the default logic in _defResetFn.
324
         *
325
         * @event reset
326
         * @param event {EventFacade} Event Facade object
327
         * @preventable _defResetFn
328
         */
329
        this.publish(RESET, { defaultFn: this._defResetFn });
330
 
331
        this.after('rendered', this._schedulePrint);
332
    },
333
 
334
    /**
335
     * Tears down the instance, flushing event subscriptions and purging the UI.
336
     *
337
     * @method destructor
338
     * @protected
339
     */
340
    destructor : function () {
341
        var bb = this.get('boundingBox');
342
 
343
        this._cancelPrintLoop();
344
 
345
        this.get('logSource').detach(this._evtCat + '*');
346
 
347
        bb.purge(true);
348
    },
349
 
350
    /**
351
     * Generate the Console UI.
352
     *
353
     * @method renderUI
354
     * @protected
355
     */
356
    renderUI : function () {
357
        this._initHead();
358
        this._initBody();
359
        this._initFoot();
360
 
361
        // Apply positioning to the bounding box if appropriate
362
        var style = this.get('style');
363
        if (style !== 'block') {
364
            this.get('boundingBox').addClass(this.getClassName(style));
365
        }
366
    },
367
 
368
    /**
369
     * Sync the UI state to the current attribute state.
370
     *
371
     * @method syncUI
372
     */
373
    syncUI : function () {
374
        this._uiUpdatePaused(this.get(PAUSED));
375
        this._uiUpdateCollapsed(this.get(COLLAPSED));
376
        this._uiSetHeight(this.get(HEIGHT));
377
    },
378
 
379
    /**
380
     * Set up event listeners to wire up the UI to the internal state.
381
     *
382
     * @method bindUI
383
     * @protected
384
     */
385
    bindUI : function () {
386
        this.get(CONTENT_BOX).one('button.'+C_COLLAPSE).
387
            on(CLICK,this._onCollapseClick,this);
388
 
389
        this.get(CONTENT_BOX).one('input[type=checkbox].'+C_PAUSE).
390
            on(CLICK,this._onPauseClick,this);
391
 
392
        this.get(CONTENT_BOX).one('button.'+C_CLEAR).
393
            on(CLICK,this._onClearClick,this);
394
 
395
        // Attribute changes
396
        this.after(this._evtCat + 'stringsChange',
397
            this._afterStringsChange);
398
        this.after(this._evtCat + 'pausedChange',
399
            this._afterPausedChange);
400
        this.after(this._evtCat + 'consoleLimitChange',
401
            this._afterConsoleLimitChange);
402
        this.after(this._evtCat + 'collapsedChange',
403
            this._afterCollapsedChange);
404
    },
405
 
406
 
407
    /**
408
     * Create the DOM structure for the header elements.
409
     *
410
     * @method _initHead
411
     * @protected
412
     */
413
    _initHead : function () {
414
        var cb   = this.get(CONTENT_BOX),
415
            info = merge(Console.CHROME_CLASSES, {
416
                        str_collapse : this.get('strings.collapse'),
417
                        str_title : this.get('strings.title')
418
                    });
419
 
420
        this._head = create(substitute(Console.HEADER_TEMPLATE,info));
421
 
422
        cb.insertBefore(this._head,cb.get('firstChild'));
423
    },
424
 
425
    /**
426
     * Create the DOM structure for the console body&#8212;where messages are
427
     * rendered.
428
     *
429
     * @method _initBody
430
     * @protected
431
     */
432
    _initBody : function () {
433
        this._body = create(substitute(
434
                            Console.BODY_TEMPLATE,
435
                            Console.CHROME_CLASSES));
436
 
437
        this.get(CONTENT_BOX).appendChild(this._body);
438
    },
439
 
440
    /**
441
     * Create the DOM structure for the footer elements.
442
     *
443
     * @method _initFoot
444
     * @protected
445
     */
446
    _initFoot : function () {
447
        var info = merge(Console.CHROME_CLASSES, {
448
                id_guid   : Y.guid(),
449
                str_pause : this.get('strings.pause'),
450
                str_clear : this.get('strings.clear')
451
            });
452
 
453
        this._foot = create(substitute(Console.FOOTER_TEMPLATE,info));
454
 
455
        this.get(CONTENT_BOX).appendChild(this._foot);
456
    },
457
 
458
    /**
459
     * Determine if incoming log messages are within the configured logLevel
460
     * to be buffered for printing.
461
     *
462
     * @method _isInLogLevel
463
     * @protected
464
     */
465
    _isInLogLevel : function (e) {
466
        var cat = e.cat, lvl = this.get('logLevel');
467
 
468
        if (lvl !== INFO) {
469
            cat = cat || INFO;
470
 
471
            if (isString(cat)) {
472
                cat = cat.toLowerCase();
473
            }
474
 
475
            if ((cat === WARN && lvl === ERROR) ||
476
                (cat === INFO && lvl !== INFO)) {
477
                return false;
478
            }
479
        }
480
 
481
        return true;
482
    },
483
 
484
    /**
485
     * Create a log entry message from the inputs including the following keys:
486
     * <ul>
487
     *     <li>time - this moment</li>
488
     *     <li>message - leg message</li>
489
     *     <li>category - logLevel or custom category for the message</li>
490
     *     <li>source - when provided, the widget or util calling Y.log</li>
491
     *     <li>sourceAndDetail - same as source but can include instance info</li>
492
     *     <li>localTime - readable version of time</li>
493
     *     <li>elapsedTime - ms since last entry</li>
494
     *     <li>totalTime - ms since Console was instantiated or reset</li>
495
     * </ul>
496
     *
497
     * @method _normalizeMessage
498
     * @param e {Event} custom event containing the log message
499
     * @return Object the message object
500
     * @protected
501
     */
502
    _normalizeMessage : function (e) {
503
 
504
        var msg = e.msg,
505
            cat = e.cat,
506
            src = e.src,
507
 
508
            m = {
509
                time            : new Date(),
510
                message         : msg,
511
                category        : cat || this.get('defaultCategory'),
512
                sourceAndDetail : src || this.get('defaultSource'),
513
                source          : null,
514
                localTime       : null,
515
                elapsedTime     : null,
516
                totalTime       : null
517
            };
518
 
519
        // Extract m.source "Foo" from m.sourceAndDetail "Foo bar baz"
520
        m.source          = RE_INLINE_SOURCE.test(m.sourceAndDetail) ?
521
                                RegExp.$1 : m.sourceAndDetail;
522
        m.localTime       = m.time.toLocaleTimeString ?
523
                            m.time.toLocaleTimeString() : (m.time + '');
524
        m.elapsedTime     = m.time - this.get(LAST_TIME);
525
        m.totalTime       = m.time - this.get(START_TIME);
526
 
527
        this._set(LAST_TIME,m.time);
528
 
529
        return m;
530
    },
531
 
532
    /**
533
     * Sets an interval for buffered messages to be output to the console.
534
     *
535
     * @method _schedulePrint
536
     * @protected
537
     */
538
    _schedulePrint : function () {
539
        if (!this._printLoop && !this.get(PAUSED) && this.get('rendered')) {
540
            this._printLoop = Y.later(
541
                                this.get('printTimeout'),
542
                                this, this.printBuffer,
543
                                this.get('printLimit'), true);
544
        }
545
    },
546
 
547
    /**
548
     * Translates message meta into the markup for a console entry.
549
     *
550
     * @method _createEntryHTML
551
     * @param m {Object} object literal containing normalized message metadata
552
     * @return String
553
     * @protected
554
     */
555
    _createEntryHTML : function (m) {
556
        m = merge(
557
                this._htmlEscapeMessage(m),
558
                Console.ENTRY_CLASSES,
559
                {
560
                    cat_class : this.getClassName(ENTRY,m.category),
561
                    src_class : this.getClassName(ENTRY,m.source)
562
                });
563
 
564
        return this.get('entryTemplate').replace(/\{(\w+)\}/g,
565
            function (_,token) {
566
                return token in m ? m[token] : '';
567
            });
568
    },
569
 
570
    /**
571
     * Scrolls to the most recent entry
572
     *
573
     * @method scrollToLatest
574
     * @chainable
575
     */
576
    scrollToLatest : function () {
577
        var scrollTop = this.get('newestOnTop') ?
578
 
579
                            this._body.get('scrollHeight');
580
 
581
        this._body.set('scrollTop', scrollTop);
582
    },
583
 
584
    /**
585
     * Performs HTML escaping on strings in the message object.
586
     *
587
     * @method _htmlEscapeMessage
588
     * @param m {Object} the normalized message object
589
     * @return Object the message object with proper escapement
590
     * @protected
591
     */
592
    _htmlEscapeMessage : function (m) {
593
        m.message         = this._encodeHTML(m.message);
594
        m.source          = this._encodeHTML(m.source);
595
        m.sourceAndDetail = this._encodeHTML(m.sourceAndDetail);
596
        m.category        = this._encodeHTML(m.category);
597
 
598
        return m;
599
    },
600
 
601
    /**
602
     * Removes the oldest message entries from the UI to maintain the limit
603
     * specified in the consoleLimit configuration.
604
     *
605
     * @method _trimOldEntries
606
     * @protected
607
     */
608
    _trimOldEntries : function () {
609
        // Turn off the logging system for the duration of this operation
610
        // to prevent an infinite loop
611
        Y.config.debug = false;
612
 
613
        var bd = this._body,
614
            limit = this.get('consoleLimit'),
615
            debug = Y.config.debug,
616
            entries,e,i,l;
617
 
618
        if (bd) {
619
            entries = bd.all(DOT+C_ENTRY);
620
            l = entries.size() - limit;
621
 
622
            if (l > 0) {
623
                if (this.get('newestOnTop')) {
624
                    i = limit;
625
                    l = entries.size();
626
                } else {
627
                    i = 0;
628
                }
629
 
630
                this._body.setStyle('display','none');
631
 
632
                for (;i < l; ++i) {
633
                    e = entries.item(i);
634
                    if (e) {
635
                        e.remove();
636
                    }
637
                }
638
 
639
                this._body.setStyle('display','');
640
            }
641
 
642
        }
643
 
644
        Y.config.debug = debug;
645
    },
646
 
647
    /**
648
     * Returns the input string with ampersands (&amp;), &lt, and &gt; encoded
649
     * as HTML entities.
650
     *
651
     * @method _encodeHTML
652
     * @param s {String} the raw string
653
     * @return String the encoded string
654
     * @protected
655
     */
656
    _encodeHTML : function (s) {
657
        return isString(s) ?
658
            s.replace(RE_AMP,ESC_AMP).
659
              replace(RE_LT, ESC_LT).
660
              replace(RE_GT, ESC_GT) :
661
            s;
662
    },
663
 
664
    /**
665
     * Clears the timeout for printing buffered messages.
666
     *
667
     * @method _cancelPrintLoop
668
     * @protected
669
     */
670
    _cancelPrintLoop : function () {
671
        if (this._printLoop) {
672
            this._printLoop.cancel();
673
            this._printLoop = null;
674
        }
675
    },
676
 
677
    /**
678
     * Validates input value for style attribute.  Accepts only values 'inline',
679
     * 'block', and 'separate'.
680
     *
681
     * @method _validateStyle
682
     * @param style {String} the proposed value
683
     * @return {Boolean} pass/fail
684
     * @protected
685
     */
686
    _validateStyle : function (style) {
687
        return style === 'inline' || style === 'block' || style === 'separate';
688
    },
689
 
690
    /**
691
     * Event handler for clicking on the Pause checkbox to update the paused
692
     * attribute.
693
     *
694
     * @method _onPauseClick
695
     * @param e {Event} DOM event facade for the click event
696
     * @protected
697
     */
698
    _onPauseClick : function (e) {
699
        this.set(PAUSED,e.target.get(CHECKED));
700
    },
701
 
702
    /**
703
     * Event handler for clicking on the Clear button.  Pass-through to
704
     * <code>this.clearConsole()</code>.
705
     *
706
     * @method _onClearClick
707
     * @param e {Event} DOM event facade for the click event
708
     * @protected
709
     */
710
    _onClearClick : function (e) {
711
        this.clearConsole();
712
    },
713
 
714
    /**
715
     * Event handler for clicking on the Collapse/Expand button. Sets the
716
     * &quot;collapsed&quot; attribute accordingly.
717
     *
718
     * @method _onCollapseClick
719
     * @param e {Event} DOM event facade for the click event
720
     * @protected
721
     */
722
    _onCollapseClick : function (e) {
723
        this.set(COLLAPSED, !this.get(COLLAPSED));
724
    },
725
 
726
 
727
    /**
728
     * Validator for logSource attribute.
729
     *
730
     * @method _validateLogSource
731
     * @param v {Object} the desired logSource
732
     * @return {Boolean} true if the input is an object with an <code>on</code>
733
     *                   method
734
     * @protected
735
     */
736
    _validateLogSource: function (v) {
737
        return v && Y.Lang.isFunction(v.on);
738
    },
739
 
740
    /**
741
     * Setter method for logLevel attribute.  Acceptable values are
742
     * &quot;error&quot, &quot;warn&quot, and &quot;info&quot (case
743
     * insensitive).  Other values are treated as &quot;info&quot;.
744
     *
745
     * @method _setLogLevel
746
     * @param v {String} the desired log level
747
     * @return String One of Console.LOG_LEVEL_INFO, _WARN, or _ERROR
748
     * @protected
749
     */
750
    _setLogLevel : function (v) {
751
        if (isString(v)) {
752
            v = v.toLowerCase();
753
        }
754
 
755
        return (v === WARN || v === ERROR) ? v : INFO;
756
    },
757
 
758
    /**
759
     * Getter method for useBrowserConsole attribute.  Just a pass through to
760
     * the YUI instance configuration setting.
761
     *
762
     * @method _getUseBrowserConsole
763
     * @return {Boolean} or null if logSource is not a YUI instance
764
     * @protected
765
     */
766
    _getUseBrowserConsole: function () {
767
        var logSource = this.get('logSource');
768
        return logSource instanceof YUI ?
769
            logSource.config.useBrowserConsole : null;
770
    },
771
 
772
    /**
773
     * Setter method for useBrowserConsole attributes.  Only functional if the
774
     * logSource attribute points to a YUI instance.  Passes the value down to
775
     * the YUI instance.  NOTE: multiple Console instances cannot maintain
776
     * independent useBrowserConsole values, since it is just a pass through to
777
     * the YUI instance configuration.
778
     *
779
     * @method _setUseBrowserConsole
780
     * @param v {Boolean} false to disable browser console printing (default)
781
     * @return {Boolean} true|false if logSource is a YUI instance
782
     * @protected
783
     */
784
    _setUseBrowserConsole: function (v) {
785
        var logSource = this.get('logSource');
786
        if (logSource instanceof YUI) {
787
            v = !!v;
788
            logSource.config.useBrowserConsole = v;
789
            return v;
790
        } else {
791
            return Y.Attribute.INVALID_VALUE;
792
        }
793
    },
794
 
795
    /**
796
     * Set the height of the Console container.  Set the body height to the
797
     * difference between the configured height and the calculated heights of
798
     * the header and footer.
799
     * Overrides Widget.prototype._uiSetHeight.
800
     *
801
     * @method _uiSetHeight
802
     * @param v {String|Number} the new height
803
     * @protected
804
     */
805
    _uiSetHeight : function (v) {
806
        Console.superclass._uiSetHeight.apply(this,arguments);
807
 
808
        if (this._head && this._foot) {
809
            var h = this.get('boundingBox').get('offsetHeight') -
810
                    this._head.get('offsetHeight') -
811
                    this._foot.get('offsetHeight');
812
 
813
            this._body.setStyle(HEIGHT,h+'px');
814
        }
815
    },
816
 
817
    /**
818
     * Over-ride default content box sizing to do nothing, since we're sizing
819
     * the body section to fill out height ourselves.
820
     *
821
     * @method _uiSizeCB
822
     * @protected
823
     */
824
    _uiSizeCB : function() {
825
        // Do Nothing. Ideally want to move to Widget-StdMod, which accounts for
826
        // _uiSizeCB
827
    },
828
 
829
    /**
830
     * Updates the UI if changes are made to any of the strings in the strings
831
     * attribute.
832
     *
833
     * @method _afterStringsChange
834
     * @param e {Event} Custom event for the attribute change
835
     * @protected
836
     */
837
    _afterStringsChange : function (e) {
838
        var prop   = e.subAttrName ? e.subAttrName.split(DOT)[1] : null,
839
            cb     = this.get(CONTENT_BOX),
840
            before = e.prevVal,
841
            after  = e.newVal;
842
 
843
        if ((!prop || prop === TITLE) && before.title !== after.title) {
844
            cb.all(DOT+C_CONSOLE_TITLE).setHTML(after.title);
845
        }
846
 
847
        if ((!prop || prop === PAUSE) && before.pause !== after.pause) {
848
            cb.all(DOT+C_PAUSE_LABEL).setHTML(after.pause);
849
        }
850
 
851
        if ((!prop || prop === CLEAR) && before.clear !== after.clear) {
852
            cb.all(DOT+C_CLEAR).set('value',after.clear);
853
        }
854
    },
855
 
856
    /**
857
     * Updates the UI and schedules or cancels the print loop.
858
     *
859
     * @method _afterPausedChange
860
     * @param e {Event} Custom event for the attribute change
861
     * @protected
862
     */
863
    _afterPausedChange : function (e) {
864
        var paused = e.newVal;
865
 
866
        if (e.src !== Y.Widget.SRC_UI) {
867
            this._uiUpdatePaused(paused);
868
        }
869
 
870
        if (!paused) {
871
            this._schedulePrint();
872
        } else if (this._printLoop) {
873
            this._cancelPrintLoop();
874
        }
875
    },
876
 
877
    /**
878
     * Checks or unchecks the paused checkbox
879
     *
880
     * @method _uiUpdatePaused
881
     * @param on {Boolean} the new checked state
882
     * @protected
883
     */
884
    _uiUpdatePaused : function (on) {
885
        var node = this._foot.all('input[type=checkbox].'+C_PAUSE);
886
 
887
        if (node) {
888
            node.set(CHECKED,on);
889
        }
890
    },
891
 
892
    /**
893
     * Calls this._trimOldEntries() in response to changes in the configured
894
     * consoleLimit attribute.
895
     *
896
     * @method _afterConsoleLimitChange
897
     * @param e {Event} Custom event for the attribute change
898
     * @protected
899
     */
900
    _afterConsoleLimitChange : function () {
901
        this._trimOldEntries();
902
    },
903
 
904
 
905
    /**
906
     * Updates the className of the contentBox, which should trigger CSS to
907
     * hide or show the body and footer sections depending on the new value.
908
     *
909
     * @method _afterCollapsedChange
910
     * @param e {Event} Custom event for the attribute change
911
     * @protected
912
     */
913
    _afterCollapsedChange : function (e) {
914
        this._uiUpdateCollapsed(e.newVal);
915
    },
916
 
917
    /**
918
     * Updates the UI to reflect the new Collapsed state
919
     *
920
     * @method _uiUpdateCollapsed
921
     * @param v {Boolean} true for collapsed, false for expanded
922
     * @protected
923
     */
924
    _uiUpdateCollapsed : function (v) {
925
        var bb     = this.get('boundingBox'),
926
            button = bb.all('button.'+C_COLLAPSE),
927
            method = v ? 'addClass' : 'removeClass',
928
            str    = this.get('strings.'+(v ? 'expand' : 'collapse'));
929
 
930
        bb[method](C_COLLAPSED);
931
 
932
        if (button) {
933
            button.setHTML(str);
934
        }
935
 
936
        this._uiSetHeight(v ? this._head.get('offsetHeight'): this.get(HEIGHT));
937
    },
938
 
939
    /**
940
     * Makes adjustments to the UI if needed when the Console is hidden or shown
941
     *
942
     * @method _afterVisibleChange
943
     * @param e {Event} the visibleChange event
944
     * @protected
945
     */
946
    _afterVisibleChange : function (e) {
947
        Console.superclass._afterVisibleChange.apply(this,arguments);
948
 
949
        this._uiUpdateFromHideShow(e.newVal);
950
    },
951
 
952
    /**
953
     * Recalculates dimensions and updates appropriately when shown
954
     *
955
     * @method _uiUpdateFromHideShow
956
     * @param v {Boolean} true for visible, false for hidden
957
     * @protected
958
     */
959
    _uiUpdateFromHideShow : function (v) {
960
        if (v) {
961
            this._uiSetHeight(this.get(HEIGHT));
962
        }
963
    },
964
 
965
    /**
966
     * Responds to log events by normalizing qualifying messages and passing
967
     * them along through the entry event for buffering etc.
968
     *
969
     * @method _onLogEvent
970
     * @param msg {String} the log message
971
     * @param cat {String} OPTIONAL the category or logLevel of the message
972
     * @param src {String} OPTIONAL the source of the message (e.g. widget name)
973
     * @protected
974
     */
975
    _onLogEvent : function (e) {
976
 
977
        if (!this.get(DISABLED) && this._isInLogLevel(e)) {
978
 
979
            var debug = Y.config.debug;
980
 
981
            /* TODO: needed? */
982
            Y.config.debug = false;
983
 
984
            this.fire(ENTRY, {
985
                message : this._normalizeMessage(e)
986
            });
987
 
988
            Y.config.debug = debug;
989
        }
990
    },
991
 
992
    /**
993
     * Clears the console, resets the startTime attribute, enables and
994
     * unpauses the widget.
995
     *
996
     * @method _defResetFn
997
     * @protected
998
     */
999
    _defResetFn : function () {
1000
        this.clearConsole();
1001
        this.set(START_TIME,new Date());
1002
        this.set(DISABLED,false);
1003
        this.set(PAUSED,false);
1004
    },
1005
 
1006
    /**
1007
     * Buffers incoming message objects and schedules the printing.
1008
     *
1009
     * @method _defEntryFn
1010
     * @param e {Event} The Custom event carrying the message in its payload
1011
     * @protected
1012
     */
1013
    _defEntryFn : function (e) {
1014
        if (e.message) {
1015
            this.buffer.push(e.message);
1016
            this._schedulePrint();
1017
        }
1018
    }
1019
 
1020
},
1021
 
1022
// Y.Console static properties
1023
{
1024
    /**
1025
     * The identity of the widget.
1026
     *
1027
     * @property NAME
1028
     * @type String
1029
     * @static
1030
     */
1031
    NAME : CONSOLE,
1032
 
1033
    /**
1034
     * Static identifier for logLevel configuration setting to allow all
1035
     * incoming messages to generate Console entries.
1036
     *
1037
     * @property LOG_LEVEL_INFO
1038
     * @type String
1039
     * @static
1040
     */
1041
    LOG_LEVEL_INFO  : INFO,
1042
 
1043
    /**
1044
     * Static identifier for logLevel configuration setting to allow only
1045
     * incoming messages of logLevel &quot;warn&quot; or &quot;error&quot;
1046
     * to generate Console entries.
1047
     *
1048
     * @property LOG_LEVEL_WARN
1049
     * @type String
1050
     * @static
1051
     */
1052
    LOG_LEVEL_WARN  : WARN,
1053
 
1054
    /**
1055
     * Static identifier for logLevel configuration setting to allow only
1056
     * incoming messages of logLevel &quot;error&quot; to generate
1057
     * Console entries.
1058
     *
1059
     * @property LOG_LEVEL_ERROR
1060
     * @type String
1061
     * @static
1062
     */
1063
    LOG_LEVEL_ERROR : ERROR,
1064
 
1065
    /**
1066
     * Map (object) of classNames used to populate the placeholders in the
1067
     * Console.ENTRY_TEMPLATE markup when rendering a new Console entry.
1068
     *
1069
     * <p>By default, the keys contained in the object are:</p>
1070
     * <ul>
1071
     *    <li>entry_class</li>
1072
     *    <li>entry_meta_class</li>
1073
     *    <li>entry_cat_class</li>
1074
     *    <li>entry_src_class</li>
1075
     *    <li>entry_time_class</li>
1076
     *    <li>entry_content_class</li>
1077
     * </ul>
1078
     *
1079
     * @property ENTRY_CLASSES
1080
     * @type Object
1081
     * @static
1082
     */
1083
    ENTRY_CLASSES   : {
1084
        entry_class         : C_ENTRY,
1085
        entry_meta_class    : C_ENTRY_META,
1086
        entry_cat_class     : C_ENTRY_CAT,
1087
        entry_src_class     : C_ENTRY_SRC,
1088
        entry_time_class    : C_ENTRY_TIME,
1089
        entry_content_class : C_ENTRY_CONTENT
1090
    },
1091
 
1092
    /**
1093
     * Map (object) of classNames used to populate the placeholders in the
1094
     * Console.HEADER_TEMPLATE, Console.BODY_TEMPLATE, and
1095
     * Console.FOOTER_TEMPLATE markup when rendering the Console UI.
1096
     *
1097
     * <p>By default, the keys contained in the object are:</p>
1098
     * <ul>
1099
     *   <li>console_hd_class</li>
1100
     *   <li>console_bd_class</li>
1101
     *   <li>console_ft_class</li>
1102
     *   <li>console_controls_class</li>
1103
     *   <li>console_checkbox_class</li>
1104
     *   <li>console_pause_class</li>
1105
     *   <li>console_pause_label_class</li>
1106
     *   <li>console_button_class</li>
1107
     *   <li>console_clear_class</li>
1108
     *   <li>console_collapse_class</li>
1109
     *   <li>console_title_class</li>
1110
     * </ul>
1111
     *
1112
     * @property CHROME_CLASSES
1113
     * @type Object
1114
     * @static
1115
     */
1116
    CHROME_CLASSES  : {
1117
        console_hd_class       : C_CONSOLE_HD,
1118
        console_bd_class       : C_CONSOLE_BD,
1119
        console_ft_class       : C_CONSOLE_FT,
1120
        console_controls_class : C_CONSOLE_CONTROLS,
1121
        console_checkbox_class : C_CHECKBOX,
1122
        console_pause_class    : C_PAUSE,
1123
        console_pause_label_class : C_PAUSE_LABEL,
1124
        console_button_class   : C_BUTTON,
1125
        console_clear_class    : C_CLEAR,
1126
        console_collapse_class : C_COLLAPSE,
1127
        console_title_class    : C_CONSOLE_TITLE
1128
    },
1129
 
1130
    /**
1131
     * Markup template used to generate the DOM structure for the header
1132
     * section of the Console when it is rendered.  The template includes
1133
     * these {placeholder}s:
1134
     *
1135
     * <ul>
1136
     *   <li>console_button_class - contributed by Console.CHROME_CLASSES</li>
1137
     *   <li>console_collapse_class - contributed by Console.CHROME_CLASSES</li>
1138
     *   <li>console_hd_class - contributed by Console.CHROME_CLASSES</li>
1139
     *   <li>console_title_class - contributed by Console.CHROME_CLASSES</li>
1140
     *   <li>str_collapse - pulled from attribute strings.collapse</li>
1141
     *   <li>str_title - pulled from attribute strings.title</li>
1142
     * </ul>
1143
     *
1144
     * @property HEADER_TEMPLATE
1145
     * @type String
1146
     * @static
1147
     */
1148
    HEADER_TEMPLATE :
1149
        '<div class="{console_hd_class}">'+
1150
            '<h4 class="{console_title_class}">{str_title}</h4>'+
1151
            '<button type="button" class="'+
1152
                '{console_button_class} {console_collapse_class}">{str_collapse}'+
1153
            '</button>'+
1154
        '</div>',
1155
 
1156
    /**
1157
     * Markup template used to generate the DOM structure for the Console body
1158
     * (where the messages are inserted) when it is rendered.  The template
1159
     * includes only the {placeholder} &quot;console_bd_class&quot;, which is
1160
     * constributed by Console.CHROME_CLASSES.
1161
     *
1162
     * @property BODY_TEMPLATE
1163
     * @type String
1164
     * @static
1165
     */
1166
    BODY_TEMPLATE : '<div class="{console_bd_class}"></div>',
1167
 
1168
    /**
1169
     * Markup template used to generate the DOM structure for the footer
1170
     * section of the Console when it is rendered.  The template includes
1171
     * many of the {placeholder}s from Console.CHROME_CLASSES as well as:
1172
     *
1173
     * <ul>
1174
     *   <li>id_guid - generated unique id, relates the label and checkbox</li>
1175
     *   <li>str_pause - pulled from attribute strings.pause</li>
1176
     *   <li>str_clear - pulled from attribute strings.clear</li>
1177
     * </ul>
1178
     *
1179
     * @property FOOTER_TEMPLATE
1180
     * @type String
1181
     * @static
1182
     */
1183
    FOOTER_TEMPLATE :
1184
        '<div class="{console_ft_class}">'+
1185
            '<div class="{console_controls_class}">'+
1186
                '<label class="{console_pause_label_class}"><input type="checkbox" class="{console_checkbox_class} {console_pause_class}" value="1" id="{id_guid}"> {str_pause}</label>' +
1187
                '<button type="button" class="'+
1188
                    '{console_button_class} {console_clear_class}">{str_clear}'+
1189
                '</button>'+
1190
            '</div>'+
1191
        '</div>',
1192
 
1193
    /**
1194
     * Default markup template used to create the DOM structure for Console
1195
     * entries. The markup contains {placeholder}s for content and classes
1196
     * that are replaced via Y.Lang.sub.  The default template contains
1197
     * the {placeholder}s identified in Console.ENTRY_CLASSES as well as the
1198
     * following placeholders that will be populated by the log entry data:
1199
     *
1200
     * <ul>
1201
     *   <li>cat_class</li>
1202
     *   <li>src_class</li>
1203
     *   <li>totalTime</li>
1204
     *   <li>elapsedTime</li>
1205
     *   <li>localTime</li>
1206
     *   <li>sourceAndDetail</li>
1207
     *   <li>message</li>
1208
     * </ul>
1209
     *
1210
     * @property ENTRY_TEMPLATE
1211
     * @type String
1212
     * @static
1213
     */
1214
    ENTRY_TEMPLATE : ENTRY_TEMPLATE_STR,
1215
 
1216
    /**
1217
     * Static property used to define the default attribute configuration of
1218
     * the Widget.
1219
     *
1220
     * @property ATTRS
1221
     * @Type Object
1222
     * @static
1223
     */
1224
    ATTRS : {
1225
 
1226
        /**
1227
         * Name of the custom event that will communicate log messages.
1228
         *
1229
         * @attribute logEvent
1230
         * @type String
1231
         * @default "yui:log"
1232
         */
1233
        logEvent : {
1234
            value : 'yui:log',
1235
            writeOnce : true,
1236
            validator : isString
1237
        },
1238
 
1239
        /**
1240
         * Object that will emit the log events.  By default the YUI instance.
1241
         * To have a single Console capture events from all YUI instances, set
1242
         * this to the Y.Global object.
1243
         *
1244
         * @attribute logSource
1245
         * @type EventTarget
1246
         * @default Y
1247
         */
1248
        logSource : {
1249
            value : Y,
1250
            writeOnce : true,
1251
            validator : function (v) {
1252
                return this._validateLogSource(v);
1253
            }
1254
        },
1255
 
1256
        /**
1257
         * Collection of strings used to label elements in the Console UI.
1258
         * Default collection contains the following name:value pairs:
1259
         *
1260
         * <ul>
1261
         *   <li>title : &quot;Log Console&quot;</li>
1262
         *   <li>pause : &quot;Pause&quot;</li>
1263
         *   <li>clear : &quot;Clear&quot;</li>
1264
         *   <li>collapse : &quot;Collapse&quot;</li>
1265
         *   <li>expand : &quot;Expand&quot;</li>
1266
         * </ul>
1267
         *
1268
         * @attribute strings
1269
         * @type Object
1270
         */
1271
        strings : {
1272
            valueFn: function() { return Y.Intl.get("console"); }
1273
        },
1274
 
1275
        /**
1276
         * Boolean to pause the outputting of new messages to the console.
1277
         * When paused, messages will accumulate in the buffer.
1278
         *
1279
         * @attribute paused
1280
         * @type boolean
1281
         * @default false
1282
         */
1283
        paused : {
1284
            value : false,
1285
            validator : L.isBoolean
1286
        },
1287
 
1288
        /**
1289
         * If a category is not specified in the Y.log(..) statement, this
1290
         * category will be used. Categories &quot;info&quot;,
1291
         * &quot;warn&quot;, and &quot;error&quot; are also called log level.
1292
         *
1293
         * @attribute defaultCategory
1294
         * @type String
1295
         * @default "info"
1296
         */
1297
        defaultCategory : {
1298
            value : INFO,
1299
            validator : isString
1300
        },
1301
 
1302
        /**
1303
         * If a source is not specified in the Y.log(..) statement, this
1304
         * source will be used.
1305
         *
1306
         * @attribute defaultSource
1307
         * @type String
1308
         * @default "global"
1309
         */
1310
        defaultSource   : {
1311
            value : 'global',
1312
            validator : isString
1313
        },
1314
 
1315
        /**
1316
         * Markup template used to create the DOM structure for Console entries.
1317
         *
1318
         * @attribute entryTemplate
1319
         * @type String
1320
         * @default Console.ENTRY_TEMPLATE
1321
         */
1322
        entryTemplate : {
1323
            value : ENTRY_TEMPLATE_STR,
1324
            validator : isString
1325
        },
1326
 
1327
        /**
1328
         * Minimum entry log level to render into the Console.  The initial
1329
         * logLevel value for all Console instances defaults from the
1330
         * Y.config.logLevel YUI configuration, or Console.LOG_LEVEL_INFO if
1331
         * that configuration is not set.
1332
         *
1333
         * Possible values are &quot;info&quot;, &quot;warn&quot;,
1334
         * &quot;error&quot; (case insensitive), or their corresponding statics
1335
         * Console.LOG_LEVEL_INFO and so on.
1336
         *
1337
         * @attribute logLevel
1338
         * @type String
1339
         * @default Y.config.logLevel or Console.LOG_LEVEL_INFO
1340
         */
1341
        logLevel : {
1342
            value : Y.config.logLevel || INFO,
1343
            setter : function (v) {
1344
                return this._setLogLevel(v);
1345
            }
1346
        },
1347
 
1348
        /**
1349
         * Millisecond timeout between iterations of the print loop, moving
1350
         * entries from the buffer to the UI.
1351
         *
1352
         * @attribute printTimeout
1353
         * @type Number
1354
         * @default 100
1355
         */
1356
        printTimeout : {
1357
            value : 100,
1358
            validator : isNumber
1359
        },
1360
 
1361
        /**
1362
         * Maximum number of entries printed in each iteration of the print
1363
         * loop. This is used to prevent excessive logging locking the page UI.
1364
         *
1365
         * @attribute printLimit
1366
         * @type Number
1367
         * @default 50
1368
         */
1369
        printLimit : {
1370
            value : 50,
1371
            validator : isNumber
1372
        },
1373
 
1374
        /**
1375
         * Maximum number of Console entries allowed in the Console body at one
1376
         * time.  This is used to keep acquired messages from exploding the
1377
         * DOM tree and impacting page performance.
1378
         *
1379
         * @attribute consoleLimit
1380
         * @type Number
1381
         * @default 300
1382
         */
1383
        consoleLimit : {
1384
            value : 300,
1385
            validator : isNumber
1386
        },
1387
 
1388
        /**
1389
         * New entries should display at the top of the Console or the bottom?
1390
         *
1391
         * @attribute newestOnTop
1392
         * @type Boolean
1393
         * @default true
1394
         */
1395
        newestOnTop : {
1396
            value : true
1397
        },
1398
 
1399
        /**
1400
         * When new entries are added to the Console UI, should they be
1401
         * scrolled into view?
1402
         *
1403
         * @attribute scrollIntoView
1404
         * @type Boolean
1405
         * @default true
1406
         */
1407
        scrollIntoView : {
1408
            value : true
1409
        },
1410
 
1411
        /**
1412
         * The baseline time for this Console instance, used to measure elapsed
1413
         * time from the moment the console module is <code>use</code>d to the
1414
         * moment each new entry is logged (not rendered).
1415
         *
1416
         * This value is reset by the instance method myConsole.reset().
1417
         *
1418
         * @attribute startTime
1419
         * @type Date
1420
         * @default The moment the console module is <code>use</code>d
1421
         */
1422
        startTime : {
1423
            value : new Date()
1424
        },
1425
 
1426
        /**
1427
         * The precise time the last entry was logged.  Used to measure elapsed
1428
         * time between log messages.
1429
         *
1430
         * @attribute lastTime
1431
         * @type Date
1432
         * @default The moment the console module is <code>use</code>d
1433
         */
1434
        lastTime : {
1435
            value : new Date(),
1436
            readOnly: true
1437
        },
1438
 
1439
        /**
1440
         * Controls the collapsed state of the Console
1441
         *
1442
         * @attribute collapsed
1443
         * @type Boolean
1444
         * @default false
1445
         */
1446
        collapsed : {
1447
            value : false
1448
        },
1449
 
1450
        /**
1451
        * String with units, or number, representing the height of the Console,
1452
        * inclusive of header and footer. If a number is provided, the default
1453
        * unit, defined by Widget's DEF_UNIT, property is used.
1454
        *
1455
        * @attribute height
1456
        * @default "300px"
1457
        * @type {String | Number}
1458
        */
1459
        height: {
1460
            value: "300px"
1461
        },
1462
 
1463
        /**
1464
        * String with units, or number, representing the width of the Console.
1465
        * If a number is provided, the default unit, defined by Widget's
1466
        * DEF_UNIT, property is used.
1467
        *
1468
        * @attribute width
1469
        * @default "300px"
1470
        * @type {String | Number}
1471
        */
1472
        width: {
1473
            value: "300px"
1474
        },
1475
 
1476
        /**
1477
         * Pass through to the YUI instance useBrowserConsole configuration.
1478
         * By default this is set to false, which will disable logging to the
1479
         * browser console when a Console instance is created.  If the
1480
         * logSource is not a YUI instance, this has no effect.
1481
         *
1482
         * @attribute useBrowserConsole
1483
         * @type {Boolean}
1484
         * @default false
1485
         */
1486
         useBrowserConsole : {
1487
            lazyAdd: false,
1488
            value: false,
1489
            getter : function () {
1490
                return this._getUseBrowserConsole();
1491
            },
1492
            setter : function (v) {
1493
                return this._setUseBrowserConsole(v);
1494
            }
1495
         },
1496
 
1497
         /**
1498
          * Allows the Console to flow in the document.  Available values are
1499
          * 'inline', 'block', and 'separate' (the default).
1500
          *
1501
          * @attribute style
1502
          * @type {String}
1503
          * @default 'separate'
1504
          */
1505
         style : {
1506
            value : 'separate',
1507
            writeOnce : true,
1508
            validator : function (v) {
1509
                return this._validateStyle(v);
1510
            }
1511
         }
1512
    }
1513
 
1514
});
1515
 
1516
 
1517
}, '3.18.1', {"requires": ["yui-log", "widget"], "skinnable": true, "lang": ["en", "es", "hu", "it", "ja"]});