1 /* See license.txt for terms of usage */ 2 3 define([ 4 "firebug/firebug", 5 "firebug/lib/events", 6 "firebug/lib/wrapper", 7 "firebug/lib/css", 8 "firebug/lib/dom", 9 "firebug/lib/string", 10 "firebug/console/autoCompleter" 11 ], 12 function(Firebug, Events, Wrapper, Css, Dom, Str) { 13 14 // ********************************************************************************************* // 15 // Constants 16 17 const Cc = Components.classes; 18 const Ci = Components.interfaces; 19 20 // ********************************************************************************************* // 21 22 Firebug.CommandHistory = function() 23 { 24 const commandHistoryMax = 1000; 25 26 var commandsPopup = Firebug.chrome.$("fbCommandHistory"); 27 var commands = this.commands = []; 28 var commandPointer = 0; 29 var commandInsertPointer = -1; 30 31 this.getLastCommand = function() 32 { 33 var command = commands[commandInsertPointer]; 34 if (!command) 35 return ""; 36 37 return command; 38 }; 39 40 this.appendToHistory = function(command) 41 { 42 if (commands[commandInsertPointer] != command) 43 { 44 commandInsertPointer++; 45 if (commandInsertPointer >= commandHistoryMax) 46 commandInsertPointer = 0; 47 48 commands[commandInsertPointer] = command; 49 } 50 51 commandPointer = commandInsertPointer + 1; 52 53 if (Firebug.chrome.$("fbCommandLineHistoryButton").hasAttribute("disabled")) 54 { 55 Firebug.chrome.$("fbCommandLineHistoryButton").removeAttribute("disabled"); 56 Firebug.chrome.$("fbCommandEditorHistoryButton").removeAttribute("disabled"); 57 58 this.attachListeners(); 59 } 60 }; 61 62 this.attachListeners = function() 63 { 64 Events.addEventListener(commandsPopup, "mouseover", this.onMouseOver, true); 65 Events.addEventListener(commandsPopup, "mouseup", this.onMouseUp, true); 66 Events.addEventListener(commandsPopup, "popuphidden", this.onPopupHidden, true); 67 }; 68 69 this.detachListeners = function() 70 { 71 Events.removeEventListener(commandsPopup, "mouseover", this.onMouseOver, true); 72 Events.removeEventListener(commandsPopup, "mouseup", this.onMouseUp, true); 73 Events.removeEventListener(commandsPopup, "popuphidden", this.onPopupHidden, true); 74 }; 75 76 this.cycleCommands = function(context, dir) 77 { 78 var command; 79 var commandLine = Firebug.CommandLine.getCommandLine(context); 80 81 commandPointer += dir; 82 if (commandPointer < 0) 83 commandPointer = 0; 84 else if (commandPointer > commands.length) 85 commandPointer = commands.length; 86 87 if (commandPointer < commands.length) 88 { 89 command = commands[commandPointer]; 90 if (commandsPopup.state == "open") 91 { 92 var commandElement = commandsPopup.children[commandPointer]; 93 this.selectCommand(commandElement); 94 95 Dom.scrollMenupopup(commandsPopup, commandElement); 96 } 97 } 98 else 99 { 100 command = ""; 101 this.removeCommandSelection(); 102 } 103 104 commandLine.value = command; 105 Firebug.CommandLine.autoCompleter.hide(); 106 Firebug.CommandLine.update(context); 107 setCursorToEOL(commandLine); 108 }; 109 110 this.isShown = function() 111 { 112 return commandsPopup.state == "open"; 113 }; 114 115 this.show = function(element) 116 { 117 if (this.isShown()) 118 return this.hide(); 119 120 Dom.eraseNode(commandsPopup); 121 122 if(commands.length == 0) 123 return; 124 125 var doc = commandsPopup.ownerDocument; 126 127 for (var i = 0; i < commands.length; i++) 128 { 129 var hbox = doc.createElementNS("http://www.w3.org/1999/xhtml", "div"); 130 131 hbox.classList.add("commandHistoryItem"); 132 var shortExpr = Str.cropString(Str.stripNewLines(commands[i]), 50); 133 hbox.innerHTML = Str.escapeForTextNode(shortExpr); 134 hbox.value = i; 135 commandsPopup.appendChild(hbox); 136 137 if (i === commandPointer) 138 this.selectCommand(hbox); 139 } 140 141 commandsPopup.openPopup(element, "before_start", 0, 0, false, false); 142 143 // make sure last element is visible 144 setTimeout(Dom.scrollMenupopup, 10, commandsPopup, hbox); 145 this.isOpen = true; 146 147 return true; 148 }; 149 150 this.hide = function() 151 { 152 commandsPopup.hidePopup(); 153 this.isOpen = false; 154 return true; 155 }; 156 157 this.toggle = function(element) 158 { 159 this.isShown() ? this.hide() : this.show(element); 160 }; 161 162 this.removeCommandSelection = function() 163 { 164 var selected = commandsPopup.ownerDocument.getElementsByClassName("selected")[0]; 165 Css.removeClass(selected, "selected"); 166 }; 167 168 this.selectCommand = function(element) 169 { 170 this.removeCommandSelection(); 171 172 Css.setClass(element, "selected"); 173 }; 174 175 this.onMouseOver = function(event) 176 { 177 var hovered = event.target; 178 179 if (hovered.localName == "vbox") 180 return; 181 182 Firebug.CommandLine.commandHistory.selectCommand(hovered); 183 }; 184 185 this.onMouseUp = function(event) 186 { 187 var i = event.target.value; 188 if (i == undefined) 189 return; 190 191 var commandLine = Firebug.CommandLine.getCommandLine(Firebug.currentContext); 192 193 commandLine.value = commands[i]; 194 commandPointer = event.target.value; 195 196 Firebug.CommandLine.commandHistory.hide(); 197 }; 198 199 this.onPopupHidden = function(event) 200 { 201 Firebug.chrome.setGlobalAttribute("fbCommandLineHistoryButton", "checked", "false"); 202 Firebug.chrome.setGlobalAttribute("fbCommandEditorHistoryButton", "checked", "false"); 203 this.isOpen = false; 204 }; 205 }; 206 207 // ********************************************************************************************* // 208 // Helpers 209 210 //xxxHonza: duplicated in console/autoCompleter.js 211 function setCursorToEOL(input) 212 { 213 // textbox version, https://developer.mozilla.org/en/XUL/Property/inputField 214 // input.inputField.setSelectionRange(len, len); 215 input.setSelectionRange(input.value.length, input.value.length); 216 } 217 218 // ********************************************************************************************* // 219 // Registration 220 221 return Firebug.CommandHistory; 222 223 // ********************************************************************************************* // 224 }); 225