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