Home | History | Annotate | Download | only in components
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @extends {WebInspector.Object}
     34  */
     35 WebInspector.FilterBar = function()
     36 {
     37     this._filtersShown = false;
     38     this._element = document.createElement("div");
     39     this._element.className = "hbox";
     40 
     41     this._filterButton = new WebInspector.StatusBarButton(WebInspector.UIString("Filter"), "filters-toggle", 3);
     42     this._filterButton.element.addEventListener("click", this._handleFilterButtonClick.bind(this), false);
     43 
     44     this._filters = [];
     45 }
     46 
     47 WebInspector.FilterBar.Events = {
     48     FiltersToggled: "FiltersToggled"
     49 }
     50 
     51 WebInspector.FilterBar.FilterBarState = {
     52     Inactive : "inactive",
     53     Active : "active",
     54     Shown : "shown"
     55 };
     56 
     57 WebInspector.FilterBar.prototype = {
     58     /**
     59      * @param {string} name
     60      */
     61     setName: function(name)
     62     {
     63         this._stateSetting = WebInspector.settings.createSetting("filterBar-" + name + "-toggled", false);
     64         this._setState(this._stateSetting.get());
     65     },
     66 
     67     /**
     68      * @return {!WebInspector.StatusBarButton}
     69      */
     70     filterButton: function()
     71     {
     72         return this._filterButton;
     73     },
     74 
     75     /**
     76      * @return {!Element}
     77      */
     78     filtersElement: function()
     79     {
     80         return this._element;
     81     },
     82 
     83     /**
     84      * @return {boolean}
     85      */
     86     filtersToggled: function()
     87     {
     88         return this._filtersShown;
     89     },
     90 
     91     /**
     92      * @param {!WebInspector.FilterUI} filter
     93      */
     94     addFilter: function(filter)
     95     {
     96         this._filters.push(filter);
     97         this._element.appendChild(filter.element());
     98         filter.addEventListener(WebInspector.FilterUI.Events.FilterChanged, this._filterChanged, this);
     99         this._updateFilterButton();
    100     },
    101 
    102     /**
    103      * @param {!WebInspector.Event} event
    104      */
    105     _filterChanged: function(event)
    106     {
    107         this._updateFilterButton();
    108     },
    109 
    110     /**
    111      * @return {string}
    112      */
    113     _filterBarState: function()
    114     {
    115         if (this._filtersShown)
    116             return WebInspector.FilterBar.FilterBarState.Shown;
    117         var isActive = false;
    118         for (var i = 0; i < this._filters.length; ++i) {
    119             if (this._filters[i].isActive())
    120                 return WebInspector.FilterBar.FilterBarState.Active;
    121         }
    122         return WebInspector.FilterBar.FilterBarState.Inactive;
    123     },
    124 
    125     _updateFilterButton: function()
    126     {
    127         this._filterButton.state = this._filterBarState();
    128     },
    129 
    130     /**
    131      * @param {!Event} event
    132      */
    133     _handleFilterButtonClick: function(event)
    134     {
    135         this._setState(!this._filtersShown);
    136     },
    137 
    138     /**
    139      * @param {boolean} filtersShown
    140      */
    141     _setState: function(filtersShown)
    142     {
    143         if (this._filtersShown === filtersShown)
    144             return;
    145 
    146         this._filtersShown = filtersShown;
    147         if (this._stateSetting)
    148             this._stateSetting.set(filtersShown);
    149 
    150         this._updateFilterButton();
    151         this.dispatchEventToListeners(WebInspector.FilterBar.Events.FiltersToggled, this._filtersShown);
    152         if (this._filtersShown) {
    153             for (var i = 0; i < this._filters.length; ++i) {
    154                 if (this._filters[i] instanceof WebInspector.TextFilterUI) {
    155                     var textFilterUI = /** @type {!WebInspector.TextFilterUI} */ (this._filters[i]);
    156                     textFilterUI.focus();
    157                 }
    158             }
    159         }
    160     },
    161 
    162     clear: function()
    163     {
    164         this._element.removeChildren();
    165         this._filters = [];
    166         this._updateFilterButton();
    167     },
    168 
    169     __proto__: WebInspector.Object.prototype
    170 }
    171 
    172 /**
    173  * @interface
    174  * @extends {WebInspector.EventTarget}
    175  */
    176 WebInspector.FilterUI = function()
    177 {
    178 }
    179 
    180 WebInspector.FilterUI.Events = {
    181     FilterChanged: "FilterChanged"
    182 }
    183 
    184 WebInspector.FilterUI.prototype = {
    185     /**
    186      * @return {boolean}
    187      */
    188     isActive: function() { },
    189 
    190     /**
    191      * @return {!Element}
    192      */
    193     element: function() { }
    194 }
    195 
    196 /**
    197  * @constructor
    198  * @extends {WebInspector.Object}
    199  * @implements {WebInspector.FilterUI}
    200  * @implements {WebInspector.SuggestBoxDelegate}
    201  * @param {boolean=} supportRegex
    202  */
    203 WebInspector.TextFilterUI = function(supportRegex)
    204 {
    205     this._supportRegex = !!supportRegex;
    206     this._regex = null;
    207 
    208     this._filterElement = document.createElement("div");
    209     this._filterElement.className = "filter-text-filter";
    210 
    211     this._filterInputElement = /** @type {!HTMLInputElement} */ (this._filterElement.createChild("input", "search-replace toolbar-replace-control"));
    212     this._filterInputElement.placeholder = WebInspector.UIString("Filter");
    213     this._filterInputElement.id = "filter-input-field";
    214     this._filterInputElement.addEventListener("mousedown", this._onFilterFieldManualFocus.bind(this), false); // when the search field is manually selected
    215     this._filterInputElement.addEventListener("input", this._onInput.bind(this), false);
    216     this._filterInputElement.addEventListener("change", this._onChange.bind(this), false);
    217     this._filterInputElement.addEventListener("keydown", this._onInputKeyDown.bind(this), true);
    218     this._filterInputElement.addEventListener("blur", this._onBlur.bind(this), true);
    219 
    220     /** @type {?WebInspector.TextFilterUI.SuggestionBuilder} */
    221     this._suggestionBuilder = null;
    222 
    223     this._suggestBox = new WebInspector.SuggestBox(this);
    224 
    225     if (this._supportRegex) {
    226         this._filterElement.classList.add("supports-regex");
    227         this._regexCheckBox = this._filterElement.createChild("input");
    228         this._regexCheckBox.type = "checkbox";
    229         this._regexCheckBox.id = "text-filter-regex";
    230         this._regexCheckBox.addEventListener("change", this._onInput.bind(this), false);
    231 
    232         this._regexLabel = this._filterElement.createChild("label");
    233         this._regexLabel.htmlFor = "text-filter-regex";
    234         this._regexLabel.textContent = WebInspector.UIString("Regex");
    235     }
    236 }
    237 
    238 WebInspector.TextFilterUI.prototype = {
    239     /**
    240      * @return {boolean}
    241      */
    242     isActive: function()
    243     {
    244         return !!this._filterInputElement.value;
    245     },
    246 
    247     /**
    248      * @return {!Element}
    249      */
    250     element: function()
    251     {
    252         return this._filterElement;
    253     },
    254 
    255     /**
    256      * @return {string}
    257      */
    258     value: function()
    259     {
    260         return this._filterInputElement.value;
    261     },
    262 
    263     /**
    264      * @param {string} value
    265      */
    266     setValue: function(value)
    267     {
    268         this._filterInputElement.value = value;
    269         this._valueChanged(false);
    270     },
    271 
    272     /**
    273      * @return {?RegExp}
    274      */
    275     regex: function()
    276     {
    277         return this._regex;
    278     },
    279 
    280     /**
    281      * @param {!Event} event
    282      */
    283     _onFilterFieldManualFocus: function(event)
    284     {
    285         WebInspector.setCurrentFocusElement(event.target);
    286     },
    287 
    288     /**
    289      * @param {!Event} event
    290      */
    291     _onBlur: function(event)
    292     {
    293         this._cancelSuggestion();
    294     },
    295 
    296     _cancelSuggestion: function()
    297     {
    298         if (this._suggestionBuilder && this._suggestBox.visible) {
    299             this._suggestionBuilder.unapplySuggestion(this._filterInputElement);
    300             this._suggestBox.hide();
    301         }
    302     },
    303 
    304     _onInput: function()
    305     {
    306         this._valueChanged(true);
    307     },
    308 
    309     _onChange: function()
    310     {
    311         this._valueChanged(false);
    312     },
    313 
    314     focus: function()
    315     {
    316         this._filterInputElement.focus();
    317     },
    318 
    319     /**
    320      * @param {?WebInspector.TextFilterUI.SuggestionBuilder} suggestionBuilder
    321      */
    322     setSuggestionBuilder: function(suggestionBuilder)
    323     {
    324         this._cancelSuggestion();
    325         this._suggestionBuilder = suggestionBuilder;
    326     },
    327 
    328     _updateSuggestions: function()
    329     {
    330         if (!this._suggestionBuilder)
    331             return;
    332         var suggestions = this._suggestionBuilder.buildSuggestions(this._filterInputElement);
    333         if (suggestions && suggestions.length) {
    334             if (this._suppressSuggestion)
    335                 delete this._suppressSuggestion;
    336             else
    337                 this._suggestionBuilder.applySuggestion(this._filterInputElement, suggestions[0], true);
    338             var anchorBox = this._filterInputElement.boxInWindow().relativeTo(new AnchorBox(-3, 0));
    339             this._suggestBox.updateSuggestions(anchorBox, suggestions, 0, true, "");
    340         } else {
    341             this._suggestBox.hide();
    342         }
    343     },
    344 
    345     /**
    346      * @param {boolean} showSuggestions
    347      */
    348     _valueChanged: function(showSuggestions)
    349     {
    350         if (showSuggestions)
    351             this._updateSuggestions();
    352         else
    353             this._suggestBox.hide();
    354 
    355         var filterQuery = this.value();
    356 
    357         this._regex = null;
    358         this._filterInputElement.classList.remove("filter-text-invalid");
    359         if (filterQuery) {
    360             if (this._supportRegex && this._regexCheckBox.checked) {
    361                 try {
    362                     this._regex = new RegExp(filterQuery, "i");
    363                 } catch (e) {
    364                     this._filterInputElement.classList.add("filter-text-invalid");
    365                 }
    366             } else {
    367                 this._regex = createPlainTextSearchRegex(filterQuery, "i");
    368             }
    369         }
    370 
    371         this._dispatchFilterChanged();
    372     },
    373 
    374     _dispatchFilterChanged: function()
    375     {
    376         this.dispatchEventToListeners(WebInspector.FilterUI.Events.FilterChanged, null);
    377     },
    378 
    379     /**
    380      * @param {!Event} event
    381      * @return {boolean}
    382      */
    383     _onInputKeyDown: function(event)
    384     {
    385         var handled = false;
    386         if (event.keyIdentifier === "U+0008") { // Backspace
    387             this._suppressSuggestion = true;
    388         } else if (this._suggestBox.visible()) {
    389             if (event.keyIdentifier === "U+001B") { // Esc
    390                 this._cancelSuggestion();
    391                 handled = true;
    392             } else if (event.keyIdentifier === "U+0009") { // Tab
    393                 this._suggestBox.acceptSuggestion();
    394                 this._valueChanged(true);
    395                 handled = true;
    396             } else {
    397                 handled = this._suggestBox.keyPressed(/** @type {!KeyboardEvent} */ (event));
    398             }
    399         }
    400         if (handled)
    401             event.consume(true);
    402         return handled;
    403     },
    404 
    405     /**
    406      * @override
    407      * @param {string} suggestion
    408      * @param {boolean=} isIntermediateSuggestion
    409      */
    410     applySuggestion: function(suggestion, isIntermediateSuggestion)
    411     {
    412         if (!this._suggestionBuilder)
    413             return;
    414         this._suggestionBuilder.applySuggestion(this._filterInputElement, suggestion, !!isIntermediateSuggestion);
    415         if (isIntermediateSuggestion)
    416             this._dispatchFilterChanged();
    417     },
    418 
    419     /** @override */
    420     acceptSuggestion: function()
    421     {
    422         this._filterInputElement.scrollLeft = this._filterInputElement.scrollWidth;
    423         this._valueChanged(true);
    424     },
    425 
    426     __proto__: WebInspector.Object.prototype
    427 }
    428 
    429 /**
    430  * @interface
    431  */
    432 WebInspector.TextFilterUI.SuggestionBuilder = function()
    433 {
    434 }
    435 
    436 WebInspector.TextFilterUI.SuggestionBuilder.prototype = {
    437     /**
    438      * @param {!HTMLInputElement} input
    439      * @return {?Array.<string>}
    440      */
    441     buildSuggestions: function(input) { },
    442 
    443     /**
    444      * @param {!HTMLInputElement} input
    445      * @param {string} suggestion
    446      * @param {boolean} isIntermediate
    447      */
    448     applySuggestion: function(input, suggestion, isIntermediate) { },
    449 
    450     /**
    451      * @param {!HTMLInputElement} input
    452      */
    453     unapplySuggestion: function(input) { }
    454 }
    455 
    456 /**
    457  * @constructor
    458  * @extends {WebInspector.Object}
    459  * @implements {WebInspector.FilterUI}
    460  * @param {!Array.<!WebInspector.NamedBitSetFilterUI.Item>} items
    461  * @param {!WebInspector.Setting=} setting
    462  */
    463 WebInspector.NamedBitSetFilterUI = function(items, setting)
    464 {
    465     this._filtersElement = document.createElement("div");
    466     this._filtersElement.className = "filter-bitset-filter status-bar-item";
    467     this._filtersElement.title = WebInspector.UIString("Use %s Click to select multiple types.", WebInspector.KeyboardShortcut.shortcutToString("", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta));
    468 
    469     this._allowedTypes = {};
    470     this._typeFilterElements = {};
    471     this._addBit(WebInspector.NamedBitSetFilterUI.ALL_TYPES, WebInspector.UIString("All"));
    472     this._filtersElement.createChild("div", "filter-bitset-filter-divider");
    473 
    474     for (var i = 0; i < items.length; ++i)
    475         this._addBit(items[i].name, items[i].label);
    476 
    477     if (setting) {
    478         this._setting = setting;
    479         setting.addChangeListener(this._settingChanged.bind(this));
    480         this._settingChanged();
    481     } else {
    482         this._toggleTypeFilter(WebInspector.NamedBitSetFilterUI.ALL_TYPES, false);
    483     }
    484 }
    485 
    486 /** @typedef {{name: string, label: string}} */
    487 WebInspector.NamedBitSetFilterUI.Item;
    488 
    489 WebInspector.NamedBitSetFilterUI.ALL_TYPES = "all";
    490 
    491 WebInspector.NamedBitSetFilterUI.prototype = {
    492     /**
    493      * @return {boolean}
    494      */
    495     isActive: function()
    496     {
    497         return !this._allowedTypes[WebInspector.NamedBitSetFilterUI.ALL_TYPES];
    498     },
    499 
    500     /**
    501      * @return {!Element}
    502      */
    503     element: function()
    504     {
    505         return this._filtersElement;
    506     },
    507 
    508     /**
    509      * @param {string} typeName
    510      * @return {boolean}
    511      */
    512     accept: function(typeName)
    513     {
    514         return !!this._allowedTypes[WebInspector.NamedBitSetFilterUI.ALL_TYPES] || !!this._allowedTypes[typeName];
    515     },
    516 
    517     _settingChanged: function()
    518     {
    519         var allowedTypes = this._setting.get();
    520         this._allowedTypes = {};
    521         for (var typeName in this._typeFilterElements) {
    522             if (allowedTypes[typeName])
    523                 this._allowedTypes[typeName] = true;
    524         }
    525         this._update();
    526     },
    527 
    528     _update: function()
    529     {
    530         if ((Object.keys(this._allowedTypes).length === 0) || this._allowedTypes[WebInspector.NamedBitSetFilterUI.ALL_TYPES]) {
    531             this._allowedTypes = {};
    532             this._allowedTypes[WebInspector.NamedBitSetFilterUI.ALL_TYPES] = true;
    533         }
    534         for (var typeName in this._typeFilterElements)
    535             this._typeFilterElements[typeName].classList.toggle("selected", this._allowedTypes[typeName]);
    536         this.dispatchEventToListeners(WebInspector.FilterUI.Events.FilterChanged, null);
    537     },
    538 
    539     /**
    540      * @param {string} name
    541      * @param {string} label
    542      */
    543     _addBit: function(name, label)
    544     {
    545         var typeFilterElement = this._filtersElement.createChild("li", name);
    546         typeFilterElement.typeName = name;
    547         typeFilterElement.createTextChild(label);
    548         typeFilterElement.addEventListener("click", this._onTypeFilterClicked.bind(this), false);
    549         this._typeFilterElements[name] = typeFilterElement;
    550     },
    551 
    552     /**
    553      * @param {!Event} e
    554      */
    555     _onTypeFilterClicked: function(e)
    556     {
    557         var toggle;
    558         if (WebInspector.isMac())
    559             toggle = e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey;
    560         else
    561             toggle = e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey;
    562         this._toggleTypeFilter(e.target.typeName, toggle);
    563     },
    564 
    565     /**
    566      * @param {string} typeName
    567      * @param {boolean} allowMultiSelect
    568      */
    569     _toggleTypeFilter: function(typeName, allowMultiSelect)
    570     {
    571         if (allowMultiSelect && typeName !== WebInspector.NamedBitSetFilterUI.ALL_TYPES)
    572             this._allowedTypes[WebInspector.NamedBitSetFilterUI.ALL_TYPES] = false;
    573         else
    574             this._allowedTypes = {};
    575 
    576         this._allowedTypes[typeName] = !this._allowedTypes[typeName];
    577 
    578         if (this._setting)
    579             this._setting.set(this._allowedTypes);
    580         else
    581             this._update();
    582     },
    583 
    584     __proto__: WebInspector.Object.prototype
    585 }
    586 
    587 /**
    588  * @constructor
    589  * @implements {WebInspector.FilterUI}
    590  * @extends {WebInspector.Object}
    591  * @param {!Array.<!{value: *, label: string, title: string}>} options
    592  */
    593 WebInspector.ComboBoxFilterUI = function(options)
    594 {
    595     this._filterElement = document.createElement("div");
    596     this._filterElement.className = "filter-combobox-filter";
    597 
    598     this._options = options;
    599     this._filterComboBox = new WebInspector.StatusBarComboBox(this._filterChanged.bind(this));
    600     for (var i = 0; i < options.length; ++i) {
    601         var filterOption = options[i];
    602         var option = document.createElement("option");
    603         option.text = filterOption.label;
    604         option.title = filterOption.title;
    605         this._filterComboBox.addOption(option);
    606         this._filterComboBox.element.title = this._filterComboBox.selectedOption().title;
    607     }
    608     this._filterElement.appendChild(this._filterComboBox.element);
    609 }
    610 
    611 WebInspector.ComboBoxFilterUI.prototype = {
    612     /**
    613      * @return {boolean}
    614      */
    615     isActive: function()
    616     {
    617         return this._filterComboBox.selectedIndex() !== 0;
    618     },
    619 
    620     /**
    621      * @return {!Element}
    622      */
    623     element: function()
    624     {
    625         return this._filterElement;
    626     },
    627 
    628     /**
    629      * @param {string} typeName
    630      * @return {*}
    631      */
    632     value: function(typeName)
    633     {
    634         var option = this._options[this._filterComboBox.selectedIndex()];
    635         return option.value;
    636     },
    637 
    638     /**
    639      * @param {number} index
    640      */
    641     setSelectedIndex: function(index)
    642     {
    643         this._filterComboBox.setSelectedIndex(index);
    644     },
    645 
    646     /**
    647      * @return {number}
    648      */
    649     selectedIndex: function(index)
    650     {
    651         return this._filterComboBox.selectedIndex();
    652     },
    653 
    654     /**
    655      * @param {!Event} event
    656      */
    657     _filterChanged: function(event)
    658     {
    659         var option = this._options[this._filterComboBox.selectedIndex()];
    660         this._filterComboBox.element.title = option.title;
    661         this.dispatchEventToListeners(WebInspector.FilterUI.Events.FilterChanged, null);
    662     },
    663 
    664     __proto__: WebInspector.Object.prototype
    665 }
    666 
    667 /**
    668  * @constructor
    669  * @implements {WebInspector.FilterUI}
    670  * @extends {WebInspector.Object}
    671  * @param {string} className
    672  * @param {string} title
    673  * @param {boolean=} activeWhenChecked
    674  * @param {!WebInspector.Setting=} setting
    675  */
    676 WebInspector.CheckboxFilterUI = function(className, title, activeWhenChecked, setting)
    677 {
    678     this._filterElement = document.createElement("div");
    679     this._filterElement.classList.add("filter-checkbox-filter", "filter-checkbox-filter-" + className);
    680     this._activeWhenChecked = !!activeWhenChecked;
    681     this._createCheckbox(title);
    682 
    683     if (setting) {
    684         this._setting = setting;
    685         setting.addChangeListener(this._settingChanged.bind(this));
    686         this._settingChanged();
    687     } else {
    688         this._checked = !this._activeWhenChecked;
    689         this._update();
    690     }
    691 }
    692 
    693 WebInspector.CheckboxFilterUI.prototype = {
    694     /**
    695      * @return {boolean}
    696      */
    697     isActive: function()
    698     {
    699         return this._activeWhenChecked === this._checked;
    700     },
    701 
    702     /**
    703      * @return {!Element}
    704      */
    705     element: function()
    706     {
    707         return this._filterElement;
    708     },
    709 
    710     /**
    711      * @return {boolean}
    712      */
    713     checked: function()
    714     {
    715         return this._checked;
    716     },
    717 
    718     /**
    719      * @param {boolean} state
    720      */
    721     setState: function(state)
    722     {
    723         this._checked = state;
    724         this._update();
    725     },
    726 
    727     _update: function()
    728     {
    729         this._checkElement.classList.toggle("checkbox-filter-checkbox-checked", this._checked);
    730         this.dispatchEventToListeners(WebInspector.FilterUI.Events.FilterChanged, null);
    731     },
    732 
    733     _settingChanged: function()
    734     {
    735         this._checked = this._setting.get();
    736         this._update();
    737     },
    738 
    739     /**
    740      * @param {!Event} event
    741      */
    742     _onClick: function(event)
    743     {
    744         this._checked = !this._checked;
    745         if (this._setting)
    746             this._setting.set(this._checked);
    747         else
    748             this._update();
    749     },
    750 
    751     /**
    752      * @param {string} title
    753      */
    754     _createCheckbox: function(title)
    755     {
    756         var label = this._filterElement.createChild("label");
    757         var checkBorder = label.createChild("div", "checkbox-filter-checkbox");
    758         this._checkElement = checkBorder.createChild("div", "checkbox-filter-checkbox-check");
    759         this._filterElement.addEventListener("click", this._onClick.bind(this), false);
    760         var typeElement = label.createChild("span", "type");
    761         typeElement.textContent = title;
    762     },
    763 
    764     __proto__: WebInspector.Object.prototype
    765 }
    766