1 /* See license.txt for terms of usage */
  2 
  3 // ************************************************************************************************
  4 // Globals
  5 
  6 const Cc = Components.classes;
  7 const Ci = Components.interfaces;
  8 
  9 var item;
 10 var FBL;
 11 var internalFilefieldTextbox;
 12 var browseButton;
 13 
 14 // browsing for a new file modifies image and label only if they are autogenereted from filename
 15 var origLabel = "";
 16 var origImage = null;
 17 
 18 function onLoad()
 19 {
 20     var args = window.arguments[0];
 21     item = args.item;
 22     FBL = args.FBL;
 23 
 24     browseButton = document.getElementById("browse-button");
 25 
 26     document.getElementById("name").value = item.label;
 27     if (item.executable)
 28     {
 29         origImage = FBL.getIconURLForFile(item.executable);
 30         try
 31         {
 32             var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
 33             file.initWithPath(item.executable);
 34             document.getElementById("executable").file = file;
 35             origLabel = file.leafName.replace(".exe","");
 36         }
 37         catch(exc) {}
 38     }
 39 
 40     if (item.cmdline)
 41         document.getElementById("cmdline").value = item.cmdline;
 42 
 43     onChange();
 44 
 45     // Localization
 46     internationalizeUI(document);
 47 
 48     window.sizeToContent();
 49 
 50     if (document.getAnonymousElementByAttribute && !document.getElementById("executable").file)
 51     {
 52         setTimeout(function()
 53         {
 54             internalFilefieldTextbox = document.getAnonymousElementByAttribute(
 55                 document.getElementById("executable"), "class", "fileFieldLabel");
 56 
 57             if (internalFilefieldTextbox)
 58             {
 59                 internalFilefieldTextbox.readOnly = false;
 60                 internalFilefieldTextbox.addEventListener("input", function(e) {
 61                     browseButton.disabled = (this.value != "");
 62                     onChange();
 63                 }, false);
 64             }
 65         }, 100);
 66     }
 67 }
 68 
 69 function internationalizeUI(doc)
 70 {
 71     var elements = doc.getElementsByClassName("fbInternational");
 72     var attributes = ["title", "label", "value"];
 73     for (var i=0; i<elements.length; i++)
 74     {
 75         if (elements[i].nodeName == "description")
 76         {
 77             var localized = FBL.$STR(elements[i].textContent);
 78             var parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
 79             var doc = parser.parseFromString("<vbox>" + localized + "</vbox>", "text/xml");
 80             var root = doc.documentElement;
 81 
 82             while(elements[i].firstChild)
 83                 elements[i].removeChild(elements[i].firstChild);
 84 
 85             for(var j=0; j<root.childNodes.length; j++)
 86             {
 87                 // ToDo: Show labels correctly
 88                 // Namespaces are not inherited from doc, so labels 
 89                 // are not shown as links
 90                 node = doc.importNode(root.childNodes[j], true);
 91                 elements[i].appendChild(node);
 92             }
 93         }
 94         else
 95         {
 96             for(var j=0; j<attributes.length; j++)
 97             {
 98                 if (elements[i].hasAttribute(attributes[j]))
 99                     FBL.internationalize(elements[i], attributes[j]);
100             }
101         }
102     }
103 }
104 
105 function onAccept()
106 {
107     item.label = document.getElementById("name").value;
108     if (!browseButton.disabled)
109     {
110         var file = document.getElementById("executable").file;
111         item.executable = "";
112         if (file)
113             item.executable = file.path;
114     }
115     else
116     {
117         item.executable = internalFilefieldTextbox.value.replace(/^\s+|\s+$/g, '');
118     }
119 
120     item.cmdline = document.getElementById("cmdline").value;
121     if (item.image == origImage)
122         item.image = FBL.getIconURLForFile(item.executable);
123 
124     try
125     {
126         var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
127         file.initWithPath(item.executable);
128         if (!file.isExecutable())
129            throw "NotAnExecutable";
130 
131         window.arguments[1].saveChanges = true;
132         return true;
133     }
134     catch (exc)
135     {
136         if (FBTrace.DBG_ERRORS)
137             FBTrace.sysout("changeEditor.onAccept; EXCEPTION " + exc, exc);
138 
139         var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].createInstance(
140             Ci.nsIPromptService);
141 
142         if (exc == "NotAnExecutable")
143         {
144             promptService.alert(null, FBL.$STR("changeEditor.Invalid_Application_Path"),
145                 FBL.$STR("changeEditor.Path_is_not_an_executable"));
146         }
147         else
148         {
149             promptService.alert(null, FBL.$STR("changeEditor.Invalid_Application_Path"),
150                 FBL.$STR("changeEditor.Application_does_not_exist"));
151         }
152 
153         return false;
154     }
155 }
156 
157 function onChange()
158 {
159     document.documentElement.getButton("accept").disabled = !(
160         document.getElementById("name").value && (
161             (browseButton.disabled && internalFilefieldTextbox &&
162                 internalFilefieldTextbox.value &&
163                 internalFilefieldTextbox.value.replace(/^\s+|\s+$/g, '')) ||
164             (!browseButton.disabled && document.getElementById("executable").file)
165         )
166     );
167 }
168 
169 function onBrowse()
170 {
171     const Ci = Components.interfaces;
172     const nsIFilePicker = Ci.nsIFilePicker;
173     var picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
174     picker.init(window, "", nsIFilePicker.modeOpen);
175     picker.appendFilters(nsIFilePicker.filterApps);
176 
177     if (picker.show() == nsIFilePicker.returnOK && picker.file)
178     {
179         var nameField = document.getElementById("name");
180         var execField = document.getElementById("executable");
181         execField.file = picker.file;
182 
183         if (internalFilefieldTextbox)
184             internalFilefieldTextbox.readOnly = true;
185 
186         if (nameField.value == origLabel || nameField.value == "")
187             origLabel = nameField.value = execField.file.leafName.replace(".exe","");
188 
189         onChange();
190         return true;
191     }
192 
193     return false;
194 }
195 
196 function insertText(text, whole)
197 {
198     var textbox = document.getElementById("cmdline")
199     if(whole)
200         textbox.select();
201 
202     textbox.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor).insertText(text);
203     textbox.focus()
204 }
205 
206 // ************************************************************************************************
207 
208 // would be good to have autosuggest for popular editors
209 var defaultCommandLines =
210 {
211     "emacs/vim/gedit/nano/geany":     "+%line %file",
212     "sublimetext":                    "%file:%line:%col",
213     "notepad++":                      "-n%line %file",
214     "emeditor":                       "/l %line %file",
215     "IntelliJ IDEA":                  "%{--line %line%} %file",
216     "browser":                        "%url",
217     "explorer":                       "/select,%file",
218     "wget/curl":                      "%url",
219     "firefox":                        "http://validator.w3.org/check?uri=%url"
220 }
221 
222 function suggestionPopupShowing(popup)
223 {
224     FBL.eraseNode(popup);
225 
226     for (var i in defaultCommandLines)
227     {
228         var box = document.createElement('hbox');
229         var label = document.createElement('label');
230         label.setAttribute('value', i + ': ');
231         box.appendChild(label);
232 
233         var spacer = document.createElement('spacer');
234         spacer.setAttribute('flex', 1);
235         box.appendChild(spacer);
236 
237         label = document.createElement('label');
238         label.setAttribute('value', defaultCommandLines[i]);
239         label.className = 'text-link'
240         box.appendChild(label);
241 
242         popup.appendChild(box)
243     }
244 }
245 
246 // ************************************************************************************************
247 // TODO: suggestions for application?
248 /*
249 var paths = []
250 var handlers = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
251     .getService(Ci.nsIMIMEService).getFromTypeAndExtension("", "js").possibleLocalHandlers;
252 for (var i = handlers.length - 1; i >= 0; i--)
253     paths.unshift(handlers.queryElementAt(i, Ci.nsILocalHandlerApp).executable.path);
254 
255 paths
256 */
257 
258 // ************************************************************************************************
259 var testEditor = function()
260 {
261     var tmpItem = {};
262     var file = document.getElementById("executable").file;
263     if (file)
264         tmpItem.executable = file.path;
265     tmpItem.cmdline = document.getElementById("cmdline").value;
266 
267     var Firebug = opener.opener.Firebug;
268     Firebug.ExternalEditors.open(Firebug.Firefox.getCurrentBrowser().currentURI.spec, 5, tmpItem);
269 }
270 
271 
272