[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/console-filters/ -> console-filters-debug.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('console-filters', function (Y, NAME) {
   9  
  10  /**
  11   * <p>Provides Plugin.ConsoleFilters plugin class.</p>
  12   *
  13   * <p>This plugin adds the ability to control which Console entries display by filtering on category and source. Two groups of checkboxes are added to the Console footer, one for categories and the other for sources.  Only those messages that match a checked category or source are displayed.</p>
  14   *
  15   * @module console-filters
  16   * @namespace Plugin
  17   * @class ConsoleFilters
  18   */
  19  
  20  // Some common strings and functions
  21  var getCN = Y.ClassNameManager.getClassName,
  22      CONSOLE = 'console',
  23      FILTERS = 'filters',
  24      FILTER  = 'filter',
  25      CATEGORY = 'category',
  26      SOURCE   = 'source',
  27      CATEGORY_DOT = 'category.',
  28      SOURCE_DOT   = 'source.',
  29  
  30      HOST     = 'host',
  31      CHECKED  = 'checked',
  32      DEF_VISIBILITY = 'defaultVisibility',
  33  
  34      DOT = '.',
  35      EMPTY   = '',
  36  
  37      C_BODY       = DOT + Y.Console.CHROME_CLASSES.console_bd_class,
  38      C_FOOT       = DOT + Y.Console.CHROME_CLASSES.console_ft_class,
  39  
  40      SEL_CHECK    = 'input[type=checkbox].',
  41  
  42      isString = Y.Lang.isString;
  43  
  44  function ConsoleFilters() {
  45      ConsoleFilters.superclass.constructor.apply(this,arguments);
  46  }
  47  
  48  Y.namespace('Plugin').ConsoleFilters = Y.extend(ConsoleFilters, Y.Plugin.Base,
  49  
  50  // Y.Plugin.ConsoleFilters prototype
  51  {
  52      /**
  53       * Collection of all log messages passed through since the plugin's
  54       * instantiation.  This holds all messages regardless of filter status.
  55       * Used as a single source of truth for repopulating the Console body when
  56       * filters are changed.
  57       *
  58       * @property _entries
  59       * @type Array
  60       * @protected
  61       */
  62      _entries : null,
  63  
  64      /**
  65       * Maximum number of entries to store in the message cache.
  66       *
  67       * @property _cacheLimit
  68       * @type {Number}
  69       * @default Infinity
  70       * @protected
  71       */
  72      _cacheLimit : Number.POSITIVE_INFINITY,
  73  
  74      /**
  75       * The container node created to house the category filters.
  76       *
  77       * @property _categories
  78       * @type Node
  79       * @protected
  80       */
  81      _categories : null,
  82  
  83      /**
  84       * The container node created to house the source filters.
  85       *
  86       * @property _sources
  87       * @type Node
  88       * @protected
  89       */
  90      _sources : null,
  91  
  92      /**
  93       * Initialize entries collection and attach listeners to host events and
  94       * methods.
  95       *
  96       * @method initializer
  97       * @protected
  98       */
  99      initializer : function () {
 100          this._entries = [];
 101  
 102          this.get(HOST).on("entry", this._onEntry, this);
 103  
 104          this.doAfter("renderUI", this.renderUI);
 105          this.doAfter("syncUI", this.syncUI);
 106          this.doAfter("bindUI", this.bindUI);
 107  
 108          this.doAfter("clearConsole", this._afterClearConsole);
 109  
 110          if (this.get(HOST).get('rendered')) {
 111              this.renderUI();
 112              this.syncUI();
 113              this.bindUI();
 114          }
 115  
 116          this.after("cacheLimitChange", this._afterCacheLimitChange);
 117      },
 118  
 119      /**
 120       * Removes the plugin UI and unwires events.
 121       *
 122       * @method destructor
 123       * @protected
 124       */
 125      destructor : function () {
 126          //TODO: grab last {consoleLimit} entries and update the console with
 127          //them (no filtering)
 128          this._entries = [];
 129  
 130          if (this._categories) {
 131              this._categories.remove();
 132          }
 133          if (this._sources) {
 134              this._sources.remove();
 135          }
 136      },
 137  
 138      /**
 139       * Adds the category and source filter sections to the Console footer.
 140       *
 141       * @method renderUI
 142       * @protected
 143       */
 144      renderUI : function () {
 145          var foot = this.get(HOST).get('contentBox').one(C_FOOT),
 146              html;
 147  
 148          if (foot) {
 149              html = Y.Lang.sub(
 150                          ConsoleFilters.CATEGORIES_TEMPLATE,
 151                          ConsoleFilters.CHROME_CLASSES);
 152  
 153              this._categories = foot.appendChild(Y.Node.create(html));
 154  
 155              html = Y.Lang.sub(
 156                          ConsoleFilters.SOURCES_TEMPLATE,
 157                          ConsoleFilters.CHROME_CLASSES);
 158  
 159              this._sources = foot.appendChild(Y.Node.create(html));
 160          }
 161      },
 162  
 163      /**
 164       * Binds to checkbox click events and internal attribute change events to
 165       * maintain the UI state.
 166       *
 167       * @method bindUI
 168       * @protected
 169       */
 170      bindUI : function () {
 171          this._categories.on('click', Y.bind(this._onCategoryCheckboxClick, this));
 172  
 173          this._sources.on('click', Y.bind(this._onSourceCheckboxClick, this));
 174  
 175          this.after('categoryChange',this._afterCategoryChange);
 176          this.after('sourceChange',  this._afterSourceChange);
 177      },
 178  
 179      /**
 180       * Updates the UI to be in accordance with the current state of the plugin.
 181       *
 182       * @method syncUI
 183       */
 184      syncUI : function () {
 185          Y.each(this.get(CATEGORY), function (v, k) {
 186              this._uiSetCheckbox(CATEGORY, k, v);
 187          }, this);
 188  
 189          Y.each(this.get(SOURCE), function (v, k) {
 190              this._uiSetCheckbox(SOURCE, k, v);
 191          }, this);
 192  
 193          this.refreshConsole();
 194      },
 195  
 196      /**
 197       * Ensures a filter is set up for any new categories or sources and
 198       * collects the messages in _entries.  If the message is stamped with a
 199       * category or source that is currently being filtered out, the message
 200       * will not pass to the Console's print buffer.
 201       *
 202       * @method _onEntry
 203       * @param e {Event} the custom event object
 204       * @protected
 205       */
 206      _onEntry : function (e) {
 207          this._entries.push(e.message);
 208  
 209          var cat = CATEGORY_DOT + e.message.category,
 210              src = SOURCE_DOT + e.message.source,
 211              cat_filter = this.get(cat),
 212              src_filter = this.get(src),
 213              overLimit  = this._entries.length - this._cacheLimit,
 214              visible;
 215  
 216          if (overLimit > 0) {
 217              this._entries.splice(0, overLimit);
 218          }
 219  
 220          if (cat_filter === undefined) {
 221              visible = this.get(DEF_VISIBILITY);
 222              this.set(cat, visible);
 223              cat_filter = visible;
 224          }
 225  
 226          if (src_filter === undefined) {
 227              visible = this.get(DEF_VISIBILITY);
 228              this.set(src, visible);
 229              src_filter = visible;
 230          }
 231  
 232          if (!cat_filter || !src_filter) {
 233              e.preventDefault();
 234          }
 235      },
 236  
 237      /**
 238       * Flushes the cached entries after a call to the Console's clearConsole().
 239       *
 240       * @method _afterClearConsole
 241       * @protected
 242       */
 243      _afterClearConsole : function () {
 244          this._entries = [];
 245      },
 246  
 247      /**
 248       * Triggers the Console to update if a known category filter
 249       * changes value (e.g. visible => hidden).  Updates the appropriate
 250       * checkbox's checked state if necessary.
 251       *
 252       * @method _afterCategoryChange
 253       * @param e {Event} the attribute change event object
 254       * @protected
 255       */
 256      _afterCategoryChange : function (e) {
 257          var cat    = e.subAttrName.replace(/category\./, EMPTY),
 258              before = e.prevVal,
 259              after  = e.newVal;
 260  
 261          // Don't update the console for new categories
 262          if (!cat || before[cat] !== undefined) {
 263              this.refreshConsole();
 264  
 265              this._filterBuffer();
 266          }
 267  
 268          if (cat && !e.fromUI) {
 269              this._uiSetCheckbox(CATEGORY, cat, after[cat]);
 270          }
 271      },
 272  
 273      /**
 274       * Triggers the Console to update if a known source filter
 275       * changes value (e.g. visible => hidden).  Updates the appropriate
 276       * checkbox's checked state if necessary.
 277       *
 278       * @method _afterSourceChange
 279       * @param e {Event} the attribute change event object
 280       * @protected
 281       */
 282      _afterSourceChange : function (e) {
 283          var src     = e.subAttrName.replace(/source\./, EMPTY),
 284              before = e.prevVal,
 285              after  = e.newVal;
 286  
 287          // Don't update the console for new sources
 288          if (!src || before[src] !== undefined) {
 289              this.refreshConsole();
 290  
 291              this._filterBuffer();
 292          }
 293  
 294          if (src && !e.fromUI) {
 295              this._uiSetCheckbox(SOURCE, src, after[src]);
 296          }
 297      },
 298  
 299      /**
 300       * Flushes the Console's print buffer of any entries that have a category
 301       * or source that is currently being excluded.
 302       *
 303       * @method _filterBuffer
 304       * @protected
 305       */
 306      _filterBuffer : function () {
 307          var cats = this.get(CATEGORY),
 308              srcs = this.get(SOURCE),
 309              buffer = this.get(HOST).buffer,
 310              start = null,
 311              i;
 312  
 313          for (i = buffer.length - 1; i >= 0; --i) {
 314              if (!cats[buffer[i].category] || !srcs[buffer[i].source]) {
 315                  start = start || i;
 316              } else if (start) {
 317                  buffer.splice(i,(start - i));
 318                  start = null;
 319              }
 320          }
 321          if (start) {
 322              buffer.splice(0,start + 1);
 323          }
 324      },
 325  
 326      /**
 327       * Trims the cache of entries to the appropriate new length.
 328       *
 329       * @method _afterCacheLimitChange
 330       * @param e {Event} the attribute change event object
 331       * @protected
 332       */
 333      _afterCacheLimitChange : function (e) {
 334          if (isFinite(e.newVal)) {
 335              var delta = this._entries.length - e.newVal;
 336  
 337              if (delta > 0) {
 338                  this._entries.splice(0,delta);
 339              }
 340          }
 341      },
 342  
 343      /**
 344       * Repopulates the Console with entries appropriate to the current filter
 345       * settings.
 346       *
 347       * @method refreshConsole
 348       */
 349      refreshConsole : function () {
 350          var entries   = this._entries,
 351              host      = this.get(HOST),
 352              body      = host.get('contentBox').one(C_BODY),
 353              remaining = host.get('consoleLimit'),
 354              cats      = this.get(CATEGORY),
 355              srcs      = this.get(SOURCE),
 356              buffer    = [],
 357              i,e;
 358  
 359          if (body) {
 360              host._cancelPrintLoop();
 361  
 362              // Evaluate all entries from latest to oldest
 363              for (i = entries.length - 1; i >= 0 && remaining >= 0; --i) {
 364                  e = entries[i];
 365                  if (cats[e.category] && srcs[e.source]) {
 366                      buffer.unshift(e);
 367                      --remaining;
 368                  }
 369              }
 370  
 371              body.setHTML(EMPTY);
 372              host.buffer = buffer;
 373              host.printBuffer();
 374          }
 375      },
 376  
 377      /**
 378       * Updates the checked property of a filter checkbox of the specified type.
 379       * If no checkbox is found for the input params, one is created.
 380       *
 381       * @method _uiSetCheckbox
 382       * @param type {String} 'category' or 'source'
 383       * @param item {String} the name of the filter (e.g. 'info', 'event')
 384       * @param checked {Boolean} value to set the checkbox's checked property
 385       * @protected
 386       */
 387      _uiSetCheckbox : function (type, item, checked) {
 388          if (type && item) {
 389              var container = type === CATEGORY ?
 390                                  this._categories :
 391                                  this._sources,
 392                  sel      = SEL_CHECK + getCN(CONSOLE,FILTER,item),
 393                  checkbox = container.one(sel),
 394                  host;
 395  
 396              if (!checkbox) {
 397                  host = this.get(HOST);
 398  
 399                  this._createCheckbox(container, item);
 400  
 401                  checkbox = container.one(sel);
 402  
 403                  host._uiSetHeight(host.get('height'));
 404              }
 405  
 406              checkbox.set(CHECKED, checked);
 407          }
 408      },
 409  
 410      /**
 411       * Passes checkbox clicks on to the category attribute.
 412       *
 413       * @method _onCategoryCheckboxClick
 414       * @param e {Event} the DOM event
 415       * @protected
 416       */
 417      _onCategoryCheckboxClick : function (e) {
 418          var t = e.target, cat;
 419  
 420          if (t.hasClass(ConsoleFilters.CHROME_CLASSES.filter)) {
 421              cat = t.get('value');
 422              if (cat && cat in this.get(CATEGORY)) {
 423                  this.set(CATEGORY_DOT + cat, t.get(CHECKED), { fromUI: true });
 424              }
 425          }
 426      },
 427  
 428      /**
 429       * Passes checkbox clicks on to the source attribute.
 430       *
 431       * @method _onSourceCheckboxClick
 432       * @param e {Event} the DOM event
 433       * @protected
 434       */
 435      _onSourceCheckboxClick : function (e) {
 436          var t = e.target, src;
 437  
 438          if (t.hasClass(ConsoleFilters.CHROME_CLASSES.filter)) {
 439              src = t.get('value');
 440              if (src && src in this.get(SOURCE)) {
 441                  this.set(SOURCE_DOT + src, t.get(CHECKED), { fromUI: true });
 442              }
 443          }
 444      },
 445  
 446      /**
 447       * Hides any number of categories from the UI.  Convenience method for
 448       * myConsole.filter.set('category.foo', false); set('category.bar', false);
 449       * and so on.
 450       *
 451       * @method hideCategory
 452       * @param cat* {String} 1..n categories to filter out of the UI
 453       */
 454      hideCategory : function (cat, multiple) {
 455          if (isString(multiple)) {
 456              Y.Array.each(arguments, this.hideCategory, this);
 457          } else {
 458              this.set(CATEGORY_DOT + cat, false);
 459          }
 460      },
 461  
 462      /**
 463       * Shows any number of categories in the UI.  Convenience method for
 464       * myConsole.filter.set('category.foo', true); set('category.bar', true);
 465       * and so on.
 466       *
 467       * @method showCategory
 468       * @param cat* {String} 1..n categories to allow to display in the UI
 469       */
 470      showCategory : function (cat, multiple) {
 471          if (isString(multiple)) {
 472              Y.Array.each(arguments, this.showCategory, this);
 473          } else {
 474              this.set(CATEGORY_DOT + cat, true);
 475          }
 476      },
 477  
 478      /**
 479       * Hides any number of sources from the UI.  Convenience method for
 480       * myConsole.filter.set('source.foo', false); set('source.bar', false);
 481       * and so on.
 482       *
 483       * @method hideSource
 484       * @param src* {String} 1..n sources to filter out of the UI
 485       */
 486      hideSource : function (src, multiple) {
 487          if (isString(multiple)) {
 488              Y.Array.each(arguments, this.hideSource, this);
 489          } else {
 490              this.set(SOURCE_DOT + src, false);
 491          }
 492      },
 493  
 494      /**
 495       * Shows any number of sources in the UI.  Convenience method for
 496       * myConsole.filter.set('source.foo', true); set('source.bar', true);
 497       * and so on.
 498       *
 499       * @method showSource
 500       * @param src* {String} 1..n sources to allow to display in the UI
 501       */
 502      showSource : function (src, multiple) {
 503          if (isString(multiple)) {
 504              Y.Array.each(arguments, this.showSource, this);
 505          } else {
 506              this.set(SOURCE_DOT + src, true);
 507          }
 508      },
 509  
 510      /**
 511       * Creates a checkbox and label from the ConsoleFilters.FILTER_TEMPLATE for
 512       * the provided type and name.  The checkbox and label are appended to the
 513       * container node passes as the first arg.
 514       *
 515       * @method _createCheckbox
 516       * @param container {Node} the parentNode of the new checkbox and label
 517       * @param name {String} the identifier of the filter
 518       * @protected
 519       */
 520      _createCheckbox : function (container, name) {
 521          var info = Y.merge(ConsoleFilters.CHROME_CLASSES, {
 522                          filter_name  : name,
 523                          filter_class : getCN(CONSOLE, FILTER, name)
 524                     }),
 525              node = Y.Node.create(
 526                          Y.Lang.sub(ConsoleFilters.FILTER_TEMPLATE, info));
 527  
 528          container.appendChild(node);
 529      },
 530  
 531      /**
 532       * Validates category updates are objects and the subattribute is not too
 533       * deep.
 534       *
 535       * @method _validateCategory
 536       * @param cat {String} the new category:visibility map
 537       * @param v {String} the subattribute path updated
 538       * @return Boolean
 539       * @protected
 540       */
 541      _validateCategory : function (cat, v) {
 542          return Y.Lang.isObject(v,true) && cat.split(/\./).length < 3;
 543      },
 544  
 545      /**
 546       * Validates source updates are objects and the subattribute is not too
 547       * deep.
 548       *
 549       * @method _validateSource
 550       * @param cat {String} the new source:visibility map
 551       * @param v {String} the subattribute path updated
 552       * @return Boolean
 553       * @protected
 554       */
 555      _validateSource : function (src, v) {
 556          return Y.Lang.isObject(v,true) && src.split(/\./).length < 3;
 557      },
 558  
 559      /**
 560       * Setter method for cacheLimit attribute.  Basically a validator to ensure
 561       * numeric input.
 562       *
 563       * @method _setCacheLimit
 564       * @param v {Number} Maximum number of entries
 565       * @return {Number}
 566       * @protected
 567       */
 568      _setCacheLimit: function (v) {
 569          if (Y.Lang.isNumber(v)) {
 570              this._cacheLimit = v;
 571              return v;
 572          } else {
 573              return Y.Attribute.INVALID_VALUE;
 574          }
 575      }
 576  },
 577  
 578  // Y.Plugin.ConsoleFilters static properties
 579  {
 580      /**
 581       * Plugin name.
 582       *
 583       * @property NAME
 584       * @type String
 585       * @static
 586       * @default 'consoleFilters'
 587       */
 588      NAME : 'consoleFilters',
 589  
 590      /**
 591       * The namespace hung off the host object that this plugin will inhabit.
 592       *
 593       * @property NS
 594       * @type String
 595       * @static
 596       * @default 'filter'
 597       */
 598      NS : FILTER,
 599  
 600      /**
 601       * Markup template used to create the container for the category filters.
 602       *
 603       * @property CATEGORIES_TEMPLATE
 604       * @type String
 605       * @static
 606       */
 607      CATEGORIES_TEMPLATE :
 608          '<div class="{categories}"></div>',
 609  
 610      /**
 611       * Markup template used to create the container for the source filters.
 612       *
 613       * @property SOURCES_TEMPLATE
 614       * @type String
 615       * @static
 616       */
 617      SOURCES_TEMPLATE :
 618          '<div class="{sources}"></div>',
 619  
 620      /**
 621       * Markup template used to create the category and source filter checkboxes.
 622       *
 623       * @property FILTER_TEMPLATE
 624       * @type String
 625       * @static
 626       */
 627      FILTER_TEMPLATE :
 628          // IE8 and FF3 don't permit breaking _between_ nowrap elements.  IE8
 629          // doesn't understand (non spec) wbr tag, nor does it create text nodes
 630          // for spaces in innerHTML strings.  The thin-space entity suffices to
 631          // create a breakable point.
 632          '<label class="{filter_label}">'+
 633              '<input type="checkbox" value="{filter_name}" '+
 634                  'class="{filter} {filter_class}"> {filter_name}'+
 635          '</label>&#8201;',
 636  
 637      /**
 638       * Classnames used by the templates when creating nodes.
 639       *
 640       * @property CHROME_CLASSES
 641       * @type Object
 642       * @static
 643       * @protected
 644       */
 645      CHROME_CLASSES : {
 646          categories   : getCN(CONSOLE,FILTERS,'categories'),
 647          sources      : getCN(CONSOLE,FILTERS,'sources'),
 648          category     : getCN(CONSOLE,FILTER,CATEGORY),
 649          source       : getCN(CONSOLE,FILTER,SOURCE),
 650          filter       : getCN(CONSOLE,FILTER),
 651          filter_label : getCN(CONSOLE,FILTER,'label')
 652      },
 653  
 654      ATTRS : {
 655          /**
 656           * Default visibility applied to new categories and sources.
 657           *
 658           * @attribute defaultVisibility
 659           * @type {Boolean}
 660           * @default true
 661           */
 662          defaultVisibility : {
 663              value : true,
 664              validator : Y.Lang.isBoolean
 665          },
 666  
 667          /**
 668           * <p>Map of entry categories to their visibility status.  Update a
 669           * particular category's visibility by setting the subattribute to true
 670           * (visible) or false (hidden).</p>
 671           *
 672           * <p>For example, yconsole.filter.set('category.info', false) to hide
 673           * log entries with the category/logLevel of 'info'.</p>
 674           *
 675           * <p>Similarly, yconsole.filter.get('category.warn') will return a
 676           * boolean indicating whether that category is currently being included
 677           * in the UI.</p>
 678           *
 679           * <p>Unlike the YUI instance configuration's logInclude and logExclude
 680           * properties, filtered entries are only hidden from the UI, but
 681           * can be made visible again.</p>
 682           *
 683           * @attribute category
 684           * @type Object
 685           */
 686          category : {
 687              value : {},
 688              validator : function (v,k) {
 689                  return this._validateCategory(k,v);
 690              }
 691          },
 692  
 693          /**
 694           * <p>Map of entry sources to their visibility status.  Update a
 695           * particular sources's visibility by setting the subattribute to true
 696           * (visible) or false (hidden).</p>
 697           *
 698           * <p>For example, yconsole.filter.set('sources.slider', false) to hide
 699           * log entries originating from Y.Slider.</p>
 700           *
 701           * @attribute source
 702           * @type Object
 703           */
 704          source : {
 705              value : {},
 706              validator : function (v,k) {
 707                  return this._validateSource(k,v);
 708              }
 709          },
 710  
 711          /**
 712           * Maximum number of entries to store in the message cache.  Use this to
 713           * limit the memory footprint in environments with heavy log usage.
 714           * By default, there is no limit (Number.POSITIVE_INFINITY).
 715           *
 716           * @attribute cacheLimit
 717           * @type {Number}
 718           * @default Number.POSITIVE_INFINITY
 719           */
 720          cacheLimit : {
 721              value : Number.POSITIVE_INFINITY,
 722              setter : function (v) {
 723                  return this._setCacheLimit(v);
 724              }
 725          }
 726      }
 727  });
 728  
 729  
 730  }, '3.17.2', {"requires": ["plugin", "console"], "skinnable": true});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1