1 /* See license.txt for terms of usage */ 2 3 FBL.ns(function() { with (FBL) { 4 5 // ************************************************************************************************ 6 // Constants 7 8 const searchDelay = 150; 9 10 // ************************************************************************************************ 11 12 /** 13 * @module Implements basic search box functionality. The box is displayed on the right side 14 * of the Firebug's toolbar. Specific search capabilities depends on the current panel 15 * and implemented in <code>panel.search</code> method. The search-box is automatically 16 * available for panels that have <code>searchable<code> property set to true (set to 17 * false by default). 18 */ 19 Firebug.Search = extend(Firebug.Module, 20 { 21 dispatchName: "search", 22 search: function(text, context) 23 { 24 var searchBox = Firebug.chrome.$("fbSearchBox"); 25 searchBox.value = text; 26 this.update(context); 27 }, 28 searchNext: function(context) { 29 this.update(context, true, false); 30 }, 31 searchPrev: function(context) { 32 this.update(context, true, true); 33 }, 34 35 displayOnly: function(text, context) 36 { 37 var searchBox = Firebug.chrome.$("fbSearchBox"); 38 39 if (text && text.length > 0) 40 setClass(searchBox, "fbSearchBox-attention"); 41 else 42 removeClass(searchBox, "fbSearchBox-attention"); 43 44 searchBox.value = text; 45 }, 46 47 focus: function(context) 48 { 49 if (Firebug.isDetached()) 50 Firebug.chrome.focus(); 51 else 52 Firebug.toggleBar(true); 53 54 var searchBox = Firebug.chrome.$("fbSearchBox"); 55 searchBox.focus(); 56 searchBox.select(); 57 }, 58 59 update: function(context, immediate, reverse) 60 { 61 var panel = Firebug.chrome.getSelectedPanel(); 62 if (!panel.searchable) 63 return; 64 65 var searchBox = Firebug.chrome.$("fbSearchBox"); 66 var panelNode = panel.panelNode; 67 68 var value = searchBox.value; 69 70 // This sucks, but the find service won't match nodes that are invisible, so we 71 // have to make sure to make them all visible unless the user is appending to the 72 // last string, in which case it's ok to just search the set of visible nodes 73 if (!panel.searchText || value.indexOf(panel.searchText) != 0) 74 removeClass(panelNode, "searching"); 75 76 // Cancel the previous search to keep typing smooth 77 clearTimeout(panelNode.searchTimeout); 78 79 if (immediate) 80 { 81 var found = panel.search(value, reverse); 82 if (!found && value) 83 beep(); 84 85 if (value) 86 { 87 // Hides all nodes that didn't pass the filter 88 setClass(panelNode, "searching"); 89 } 90 else 91 { 92 // Makes all nodes visible again 93 removeClass(panelNode, "searching"); 94 } 95 96 panel.searchText = value; 97 } 98 else 99 { 100 // After a delay, perform the search 101 panelNode.searchTimeout = setTimeout(function() 102 { 103 var found = panel.search(value, reverse); 104 if (!found && value) 105 Firebug.Search.onNotFound(value); 106 107 if (value) 108 { 109 // Hides all nodes that didn't pass the filter 110 setClass(panelNode, "searching"); 111 } 112 else 113 { 114 // Makes all nodes visible again 115 removeClass(panelNode, "searching"); 116 } 117 118 panel.searchText = value; 119 }, searchDelay); 120 } 121 }, 122 123 onNotFound: function() 124 { 125 beep(); 126 }, 127 128 isCaseSensitive: function(text) 129 { 130 return !!Firebug.searchCaseSensitive || text.toLowerCase() != text; 131 }, 132 getTestingRegex: function(text) 133 { 134 var caseSensitive = Firebug.Search.isCaseSensitive(text); 135 try 136 { 137 return new RegExp(text, caseSensitive ? "g" : "gi"); 138 } 139 catch (err) 140 { 141 // The user entered an invalid regex. Duck type the regex object 142 // to support literal searches when an invalid regex is entered 143 return new LiteralRegExp(text, false, caseSensitive); 144 } 145 }, 146 147 searchOptionMenu: function(label, option) 148 { 149 return { label: label, checked: Firebug[option], option: option, 150 command: bindFixed(this.onToggleSearchOption, this, option) }; 151 }, 152 onToggleSearchOption: function(option) 153 { 154 Firebug.setPref(Firebug.prefDomain, option, !Firebug[option]); 155 }, 156 157 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 158 // extends Module 159 160 initializeUI: function() 161 { 162 }, 163 164 shutdown: function() 165 { 166 }, 167 168 showPanel: function(browser, panel) 169 { 170 // Manage visibility of the search-box according to the searchable flag. 171 var searchBox = Firebug.chrome.$("fbSearchBox"); 172 searchBox.value = ""; 173 removeClass(searchBox, "fbSearchBox-attention"); 174 175 if (panel) 176 { 177 searchBox.collapsed = !panel.searchable; 178 searchBox.updateOptions(panel.getSearchOptionsMenuItems()); 179 } 180 else 181 searchBox.collapsed = false; 182 } 183 }); 184 185 // ************************************************************************************************ 186 187 Firebug.registerModule(Firebug.Search); 188 189 // ************************************************************************************************ 190 }}); 191