1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/lib/object", 5 "firebug/lib/locale", 6 "firebug/firebug", 7 "firebug/lib/dom", 8 "firebug/chrome/menu", 9 ], 10 function(Obj, Locale, Firebug, Dom, Menu) { 11 12 // ************************************************************************************************ 13 // Constants 14 15 const Cc = Components.classes; 16 const Ci = Components.interfaces; 17 18 const MAX_HISTORY_MENU_ITEMS = 15; 19 20 // ************************************************************************************************ 21 22 /** 23 * @class Support for back and forward pattern for navigating within Firebug UI (panels). 24 */ 25 Firebug.NavigationHistory = Obj.extend(Firebug.Module, 26 { 27 dispatchName: "navigationHistory", 28 29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 30 // Extending Module 31 32 initContext: function(context, persistedState) 33 { 34 Firebug.Module.initContext.apply(this, arguments); 35 36 // Initialize context members. 37 context.navigationHistory = []; 38 context.navigationHistoryIndex = 0; 39 40 if (persistedState && persistedState.navigationHistory) 41 { 42 context.navigationHistory = persistedState.navigationHistory; 43 context.navigationHistoryIndex = persistedState.navigationHistoryIndex; 44 } 45 }, 46 47 destroyContext: function(context, persistedState) 48 { 49 Firebug.Module.destroyContext.apply(this, arguments); 50 51 if (persistedState) 52 { 53 persistedState.navigationHistory = context.navigationHistory; 54 persistedState.navigationHistoryIndex = context.navigationHistoryIndex; 55 } 56 }, 57 58 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 59 // History popup menu 60 61 onPopupShowing: function(popup, context) 62 { 63 var currIndex = this.getCurrentIndex(context); 64 65 if (FBTrace.DBG_HISTORY) 66 FBTrace.sysout("history.onPopupShowing; " + currIndex + ", " + context.getName(), context); 67 68 Dom.eraseNode(popup); 69 70 var list = this.getHistory(context); 71 72 // Don't display the popup for a single item. 73 var count = list.length; 74 if (count <= 1) 75 return false; 76 77 var maxItems = MAX_HISTORY_MENU_ITEMS; 78 var half = Math.floor(maxItems / 2); 79 var start = Math.max(currIndex - half, 0); 80 var end = Math.min(start == 0 ? maxItems : currIndex + half + 1, count); 81 82 if (end == count) 83 start = Math.max(count - maxItems, 0); 84 85 var tooltipBack = Locale.$STR("firebug.history.Go back to this panel"); 86 var tooltipCurrent = Locale.$STR("firebug.history.Stay on this panel"); 87 var tooltipForward = Locale.$STR("firebug.history.Go forward to this panel"); 88 89 for (var i=end-1; i>=start; i--) 90 { 91 var historyItem = list[i]; 92 var panelType = Firebug.getPanelType(historyItem.panelName); 93 var label = Firebug.getPanelTitle(panelType); 94 if (historyItem.location && historyItem.location.url) 95 label += " - " + historyItem.location.url; 96 97 var menuInfo = { 98 label: label, 99 nol10n: true, 100 className: "menuitem-iconic fbURLMenuItem", 101 }; 102 103 if (i < currIndex) 104 { 105 menuInfo.className += " navigationHistoryMenuItemBack"; 106 menuInfo.tooltiptext = tooltipBack; 107 } 108 else if (i == currIndex) 109 { 110 menuInfo.type = "radio"; 111 menuInfo.checked = "true"; 112 menuInfo.className = "navigationHistoryMenuItemCurrent"; 113 menuInfo.tooltiptext = tooltipCurrent; 114 } 115 else 116 { 117 menuInfo.className += " navigationHistoryMenuItemForward"; 118 menuInfo.tooltiptext = tooltipForward; 119 } 120 121 var menuItem = Menu.createMenuItem(popup, menuInfo); 122 menuItem.repObject = location; 123 menuItem.setAttribute("index", i); 124 } 125 126 return true; 127 }, 128 129 onHistoryCommand: function(event, context) 130 { 131 var menuItem = event.target; 132 var index = menuItem.getAttribute("index"); 133 if (!index) 134 return false; 135 136 this.gotoHistoryIndex(context, index); 137 return true; 138 }, 139 140 goBack: function(context) 141 { 142 var currIndex = this.getCurrentIndex(context); 143 144 if (FBTrace.DBG_HISTORY) 145 FBTrace.sysout("history.goBack; " + currIndex + ", " + context.getName(), context); 146 147 this.gotoHistoryIndex(context, currIndex - 1); 148 }, 149 150 goForward: function(context) 151 { 152 var currIndex = this.getCurrentIndex(context); 153 154 if (FBTrace.DBG_HISTORY) 155 FBTrace.sysout("history.goForward; " + currIndex + ", " + context.getName(), context); 156 157 this.gotoHistoryIndex(context, currIndex + 1); 158 }, 159 160 gotoHistoryIndex: function(context, index) 161 { 162 var list = this.getHistory(context); 163 if (index < 0 || index >= list.length) 164 return; 165 166 var historyItem = list[index]; 167 168 try 169 { 170 this.navInProgress = true; 171 Firebug.chrome.navigate(historyItem.location, historyItem.panelName); 172 context.navigationHistoryIndex = index; 173 } 174 catch (e) 175 { 176 } 177 finally 178 { 179 this.navInProgress = false; 180 } 181 182 this.updateButtons(context); 183 }, 184 185 186 updateButtons: function(context) 187 { 188 var list = this.getHistory(context); 189 190 var backButton = Firebug.chrome.$("fbNavigateBackButton"); 191 var forwardButton = Firebug.chrome.$("fbNavigateForwardButton"); 192 193 backButton.setAttribute("disabled", "true"); 194 forwardButton.setAttribute("disabled", "true"); 195 196 if (list.length <= 1) 197 return; 198 199 var currIndex = this.getCurrentIndex(context); 200 201 if (currIndex > 0) 202 backButton.removeAttribute("disabled"); 203 204 if (currIndex < list.length-1) 205 forwardButton.removeAttribute("disabled"); 206 }, 207 208 getHistory: function(context) 209 { 210 if (!context.navigationHistory) 211 context.navigationHistory = []; 212 213 return context.navigationHistory; 214 }, 215 216 getCurrentIndex: function(context) 217 { 218 if (typeof(context.navigationHistoryIndex) == "undefined") 219 context.navigationHistoryIndex = 0; 220 221 return context.navigationHistoryIndex; 222 }, 223 224 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 225 // UI Listener 226 227 onPanelNavigate: function(location, panel) 228 { 229 var context = panel.context; 230 var currIndex = this.getCurrentIndex(context); 231 232 if (FBTrace.DBG_HISTORY) 233 FBTrace.sysout("history.onPanelNavigate; " + currIndex + ", " + 234 "Panel: " + (panel ? panel.name : "Unknown Panel") + ", " + 235 "Location: " + (location ? location.url : "No Location") + ", " + 236 context.getName()); 237 238 // The panel must be always there 239 if (!panel) 240 return; 241 242 // Ignore side panel navigation. 243 if (panel.parentPanel) 244 return; 245 246 // The user is navigating using the history UI, this action doesn't affect 247 // the history list. 248 if (this.navInProgress) 249 return; 250 251 var list = this.getHistory(context); 252 253 // If the last item in the history is the same bail out. 254 var lastHistoryItem = list.length ? list[list.length-1] : null; 255 if (lastHistoryItem && lastHistoryItem.panelName == panel.name && 256 lastHistoryItem.location == location) 257 return; 258 259 if (lastHistoryItem && lastHistoryItem.location && location && 260 lastHistoryItem.location.url == location.url) 261 return; 262 263 // If the panel is the same, bail out. 264 var currHistoryItem = list.length ? list[currIndex] : null; 265 if (currHistoryItem && currHistoryItem.panelName == panel.name && 266 currHistoryItem.location == location) 267 return; 268 269 // Remove forward history. 270 list.splice(currIndex+1, list.length-(currIndex+1)); 271 272 // New back history record. 273 list.push({panelName: panel.name, location: location}); 274 context.navigationHistoryIndex = list.length-1; 275 276 if (FBTrace.DBG_HISTORY) 277 FBTrace.sysout("history.onPanelNavigate; New history record created " + currIndex + 278 ", " + panel.name + ", " + (location ? location.url : "No Location"), list); 279 280 // Update back and forward buttons in the UI. 281 this.updateButtons(context); 282 } 283 }); 284 285 // ************************************************************************************************ 286 // Registration 287 288 Firebug.registerModule(Firebug.NavigationHistory); 289 Firebug.registerUIListener(Firebug.NavigationHistory); 290 291 return Firebug.NavigationHistory; 292 293 // ************************************************************************************************ 294 }); 295