!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Mozilla Communicator client code, released
15 * March 31, 1998.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-1999
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Pete Collins
24 * Brian King
25 * Daniel Glazman <glazman@netscape.com>
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 /**** NAMESPACES ****/
42 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
43
44 // Each editor window must include this file
45 // Variables shared by all dialogs:
46
47 // Object to attach commonly-used widgets (all dialogs should use this)
48 var gDialog = {};
49
50 const kOutputEncodeBasicEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeBasicEntities;
51 const kOutputEncodeHTMLEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeHTMLEntities;
52 const kOutputEncodeLatin1Entities = Components.interfaces.nsIDocumentEncoder.OutputEncodeLatin1Entities;
53 const kOutputEncodeW3CEntities = Components.interfaces.nsIDocumentEncoder.OutputEncodeW3CEntities;
54 const kOutputFormatted = Components.interfaces.nsIDocumentEncoder.OutputFormatted;
55 const kOutputLFLineBreak = Components.interfaces.nsIDocumentEncoder.OutputLFLineBreak;
56 const kOutputSelectionOnly = Components.interfaces.nsIDocumentEncoder.OutputSelectionOnly;
57 const kOutputWrap = Components.interfaces.nsIDocumentEncoder.OutputWrap;
58
59 var gStringBundle;
60 var gIOService;
61 var gPrefsService;
62 var gPrefsBranch;
63 var gFilePickerDirectory;
64
65 var gOS = "";
66 const gWin = "Win";
67 const gUNIX = "UNIX";
68 const gMac = "Mac";
69
70 const kWebComposerWindowID = "editorWindow";
71 const kMailComposerWindowID = "msgcomposeWindow";
72
73 var gIsHTMLEditor;
74 /************* Message dialogs ***************/
75
AlertWithTitle
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
76 function AlertWithTitle(title, message, parentWindow)
77 {
78 if (!parentWindow)
79 parentWindow = window;
80
81 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
82 promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
83
84 if (promptService)
85 {
86 if (!title)
87 title = GetString("Alert");
88
89 // "window" is the calling dialog window
90 promptService.alert(parentWindow, title, message);
91 }
92 }
93
94 // Optional: Caller may supply text to substitue for "Ok" and/or "Cancel"
ConfirmWithTitle
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
95 function ConfirmWithTitle(title, message, okButtonText, cancelButtonText)
96 {
97 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
98 promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
99
100 if (promptService)
101 {
102 var okFlag = okButtonText ? promptService.BUTTON_TITLE_IS_STRING : promptService.BUTTON_TITLE_OK;
103 var cancelFlag = cancelButtonText ? promptService.BUTTON_TITLE_IS_STRING : promptService.BUTTON_TITLE_CANCEL;
104
105 return promptService.confirmEx(window, title, message,
106 (okFlag * promptService.BUTTON_POS_0) +
107 (cancelFlag * promptService.BUTTON_POS_1),
108 okButtonText, cancelButtonText, null, null, {value:0}) == 0;
109 }
110 return false;
111 }
112
113 /************* String Utilities ***************/
114
GetString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
115 function GetString(name)
116 {
117 if (!gStringBundle)
118 {
119 try {
120 var strBundleService =
121 Components.classes["@mozilla.org/intl/stringbundle;1"].getService();
122 strBundleService =
123 strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService);
124
125 gStringBundle = strBundleService.createBundle("chrome://editor/locale/editor.properties");
126
127 } catch (ex) {}
128 }
129 if (gStringBundle)
130 {
131 try {
132 return gStringBundle.GetStringFromName(name);
133 } catch (e) {}
134 }
135 return null;
136 }
137
TrimStringLeft
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
138 function TrimStringLeft(string)
139 {
140 if(!string) return "";
141 return string.replace(/^\s+/, "");
142 }
143
TrimStringRight
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
144 function TrimStringRight(string)
145 {
146 if (!string) return "";
147 return string.replace(/\s+$/, '');
148 }
149
150 // Remove whitespace from both ends of a string
TrimString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
151 function TrimString(string)
152 {
153 if (!string) return "";
154 return string.replace(/(^\s+)|(\s+$)/g, '')
155 }
156
IsWhitespace
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
157 function IsWhitespace(string)
158 {
159 return /^\s/.test(string);
160 }
161
TruncateStringAtWordEnd
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
162 function TruncateStringAtWordEnd(string, maxLength, addEllipses)
163 {
164 // Return empty if string is null, undefined, or the empty string
165 if (!string)
166 return "";
167
168 // We assume they probably don't want whitespace at the beginning
169 string = string.replace(/^\s+/, '');
170 if (string.length <= maxLength)
171 return string;
172
173 // We need to truncate the string to maxLength or fewer chars
174 if (addEllipses)
175 maxLength -= 3;
176 string = string.replace(RegExp("(.{0," + maxLength + "})\\s.*"), "$1")
177
178 if (string.length > maxLength)
179 string = string.slice(0, maxLength);
180
181 if (addEllipses)
182 string += "...";
183 return string;
184 }
185
186 // Replace all whitespace characters with supplied character
187 // E.g.: Use charReplace = " ", to "unwrap" the string by removing line-end chars
188 // Use charReplace = "_" when you don't want spaces (like in a URL)
ReplaceWhitespace
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
189 function ReplaceWhitespace(string, charReplace)
190 {
191 return string.replace(/(^\s+)|(\s+$)/g,'').replace(/\s+/g,charReplace)
192 }
193
194 // Replace whitespace with "_" and allow only HTML CDATA
195 // characters: "a"-"z","A"-"Z","0"-"9", "_", ":", "-", ".",
196 // and characters above ASCII 127
ConvertToCDATAString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
197 function ConvertToCDATAString(string)
198 {
199 return string.replace(/\s+/g,"_").replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g,'');
200 }
201
GetSelectionAsText
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
202 function GetSelectionAsText()
203 {
204 try {
205 return GetCurrentEditor().outputToString("text/plain", kOutputSelectionOnly);
206 } catch (e) {}
207
208 return "";
209 }
210
211
212 /************* Get Current Editor and associated interfaces or info ***************/
213 const nsIPlaintextEditor = Components.interfaces.nsIPlaintextEditor;
214 const nsIHTMLEditor = Components.interfaces.nsIHTMLEditor;
215 const nsITableEditor = Components.interfaces.nsITableEditor;
216 const nsIEditorStyleSheets = Components.interfaces.nsIEditorStyleSheets;
217 const nsIEditingSession = Components.interfaces.nsIEditingSession;
218
GetCurrentEditor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
219 function GetCurrentEditor()
220 {
221 // Get the active editor from the <editor> tag
222 // XXX This will probably change if we support > 1 editor in main Composer window
223 // (e.g. a plaintext editor for HTMLSource)
224
225 // For dialogs: Search up parent chain to find top window with editor
226 var editor;
227 try {
228 var editorElement = GetCurrentEditorElement();
229 editor = editorElement.getEditor(editorElement.contentWindow);
230
231 // Do QIs now so editor users won't have to figure out which interface to use
232 // Using "instanceof" does the QI for us.
233 editor instanceof Components.interfaces.nsIPlaintextEditor;
234 editor instanceof Components.interfaces.nsIHTMLEditor;
235 } catch (e) { dump (e)+"\n"; }
236
237 return editor;
238 }
239
GetCurrentTableEditor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
240 function GetCurrentTableEditor()
241 {
242 var editor = GetCurrentEditor();
243 return (editor && (editor instanceof nsITableEditor)) ? editor : null;
244 }
245
GetCurrentEditorElement
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
246 function GetCurrentEditorElement()
247 {
248 var tmpWindow = window;
249
250 do {
251 // Get the <editor> element(s)
252 var editorList = tmpWindow.document.getElementsByTagName("editor");
253
254 // This will change if we support > 1 editor element
255 if (editorList.item(0))
256 return editorList.item(0);
257
258 tmpWindow = tmpWindow.opener;
259 }
260 while (tmpWindow);
261
262 return null;
263 }
264
GetCurrentCommandManager
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
265 function GetCurrentCommandManager()
266 {
267 try {
268 return GetCurrentEditorElement().commandManager;
269 } catch (e) { dump (e)+"\n"; }
270
271 return null;
272 }
273
GetCurrentEditorType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
274 function GetCurrentEditorType()
275 {
276 try {
277 return GetCurrentEditorElement().editortype;
278 } catch (e) { dump (e)+"\n"; }
279
280 return "";
281 }
282
IsHTMLEditor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
283 function IsHTMLEditor()
284 {
285 // We don't have an editorElement, just return false
286 if (!GetCurrentEditorElement())
287 return false;
288
289 var editortype = GetCurrentEditorType();
290 switch (editortype)
291 {
292 case "html":
293 case "htmlmail":
294 return true;
295
296 case "text":
297 case "textmail":
298 return false
299
300 default:
301 dump("INVALID EDITOR TYPE: " + editortype + "\n");
302 break;
303 }
304 return false;
305 }
306
PageIsEmptyAndUntouched
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
307 function PageIsEmptyAndUntouched()
308 {
309 return IsDocumentEmpty() && !IsDocumentModified() && !IsHTMLSourceChanged();
310 }
311
IsInHTMLSourceMode
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
312 function IsInHTMLSourceMode()
313 {
314 return (gEditorDisplayMode == kDisplayModeSource);
315 }
316
317 // are we editing HTML (i.e. neither in HTML source mode, nor editing a text file)
IsEditingRenderedHTML
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
318 function IsEditingRenderedHTML()
319 {
320 return IsHTMLEditor() && !IsInHTMLSourceMode();
321 }
322
IsWebComposer
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
323 function IsWebComposer()
324 {
325 return document.documentElement.id == "editorWindow";
326 }
327
IsDocumentEditable
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
328 function IsDocumentEditable()
329 {
330 try {
331 return GetCurrentEditor().isDocumentEditable;
332 } catch (e) {}
333 return false;
334 }
335
IsDocumentEmpty
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
336 function IsDocumentEmpty()
337 {
338 try {
339 return GetCurrentEditor().documentIsEmpty;
340 } catch (e) {}
341 return false;
342 }
343
IsDocumentModified
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
344 function IsDocumentModified()
345 {
346 try {
347 return GetCurrentEditor().documentModified;
348 } catch (e) {}
349 return false;
350 }
351
IsHTMLSourceChanged
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
352 function IsHTMLSourceChanged()
353 {
354 return gSourceTextEditor.documentModified;
355 }
356
newCommandParams
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
357 function newCommandParams()
358 {
359 try {
360 return Components.classes["@mozilla.org/embedcomp/command-params;1"].createInstance(Components.interfaces.nsICommandParams);
361 }
362 catch(e) { dump("error thrown in newCommandParams: "+e+"\n"); }
363 return null;
364 }
365
366 /************* General editing command utilities ***************/
367
GetDocumentTitle
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
368 function GetDocumentTitle()
369 {
370 try {
371 return new XPCNativeWrapper(GetCurrentEditor().document, "title").title;
372 } catch (e) {}
373
374 return "";
375 }
376
SetDocumentTitle
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
377 function SetDocumentTitle(title)
378 {
379
380 try {
381 GetCurrentEditor().setDocumentTitle(title);
382
383 // Update window title (doesn't work if called from a dialog)
384 if ("UpdateWindowTitle" in window)
385 window.UpdateWindowTitle();
386 } catch (e) {}
387 }
388
389 var gAtomService;
GetAtomService
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
390 function GetAtomService()
391 {
392 gAtomService = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService);
393 }
394
EditorGetTextProperty
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
395 function EditorGetTextProperty(property, attribute, value, firstHas, anyHas, allHas)
396 {
397 try {
398 if (!gAtomService) GetAtomService();
399 var propAtom = gAtomService.getAtom(property);
400
401 GetCurrentEditor().getInlineProperty(propAtom, attribute, value,
402 firstHas, anyHas, allHas);
403 }
404 catch(e) {}
405 }
406
EditorSetTextProperty
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
407 function EditorSetTextProperty(property, attribute, value)
408 {
409 try {
410 if (!gAtomService) GetAtomService();
411 var propAtom = gAtomService.getAtom(property);
412
413 GetCurrentEditor().setInlineProperty(propAtom, attribute, value);
414 if ("gContentWindow" in window)
415 window.gContentWindow.focus();
416 }
417 catch(e) {}
418 }
419
EditorRemoveTextProperty
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
420 function EditorRemoveTextProperty(property, attribute)
421 {
422 try {
423 if (!gAtomService) GetAtomService();
424 var propAtom = gAtomService.getAtom(property);
425
426 GetCurrentEditor().removeInlineProperty(propAtom, attribute);
427 if ("gContentWindow" in window)
428 window.gContentWindow.focus();
429 }
430 catch(e) {}
431 }
432
433 /************* Element enbabling/disabling ***************/
434
435 // this function takes an elementID and a flag
436 // if the element can be found by ID, then it is either enabled (by removing "disabled" attr)
437 // or disabled (setAttribute) as specified in the "doEnable" parameter
SetElementEnabledById
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
438 function SetElementEnabledById(elementID, doEnable)
439 {
440 SetElementEnabled(document.getElementById(elementID), doEnable);
441 }
442
SetElementEnabled
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
443 function SetElementEnabled(element, doEnable)
444 {
445 if ( element )
446 {
447 if ( doEnable )
448 element.removeAttribute("disabled");
449 else
450 element.setAttribute("disabled", "true");
451 }
452 else
453 {
454 dump("Element not found in SetElementEnabled\n");
455 }
456 }
457
458 /************* Services / Prefs ***************/
459
GetIOService
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
460 function GetIOService()
461 {
462 if (gIOService)
463 return gIOService;
464
465 gIOService = Components.classes["@mozilla.org/network/io-service;1"]
466 .getService(Components.interfaces.nsIIOService);
467
468 return gIOService;
469 }
470
GetFileProtocolHandler
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
471 function GetFileProtocolHandler()
472 {
473 var ios = GetIOService();
474 var handler = ios.getProtocolHandler("file");
475 return handler.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
476 }
477
GetPrefsService
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
478 function GetPrefsService()
479 {
480 if (gPrefsService)
481 return gPrefsService;
482
483 try {
484 gPrefsService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
485 }
486 catch(ex) {
487 dump("failed to get prefs service!\n");
488 }
489
490 return gPrefsService;
491 }
492
GetPrefs
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
493 function GetPrefs()
494 {
495 if (gPrefsBranch)
496 return gPrefsBranch;
497
498 try {
499 var prefService = GetPrefsService();
500 if (prefService)
501 gPrefsBranch = prefService.getBranch(null);
502
503 if (gPrefsBranch)
504 return gPrefsBranch;
505 else
506 dump("failed to get root prefs!\n");
507 }
508 catch(ex) {
509 dump("failed to get root prefs!\n");
510 }
511 return null;
512 }
513
GetStringPref
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
514 function GetStringPref(name)
515 {
516 try {
517 return GetPrefs().getComplexValue(name, Components.interfaces.nsISupportsString).data;
518 } catch (e) {}
519 return "";
520 }
521
GetBoolPref
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
522 function GetBoolPref(name)
523 {
524 try {
525 return GetPrefs().getBoolPref(name);
526 } catch (e) {}
527 return false;
528 }
529
SetUnicharPref
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
530 function SetUnicharPref(aPrefName, aPrefValue)
531 {
532 var prefs = GetPrefs();
533 if (prefs)
534 {
535 try {
536 var str = Components.classes["@mozilla.org/supports-string;1"]
537 .createInstance(Components.interfaces.nsISupportsString);
538 str.data = aPrefValue;
539 prefs.setComplexValue(aPrefName, Components.interfaces.nsISupportsString, str);
540 }
541 catch(e) {}
542 }
543 }
544
GetUnicharPref
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
545 function GetUnicharPref(aPrefName, aDefVal)
546 {
547 var prefs = GetPrefs();
548 if (prefs)
549 {
550 try {
551 return prefs.getComplexValue(aPrefName, Components.interfaces.nsISupportsString).data;
552 }
553 catch(e) {}
554 }
555 return "";
556 }
557
558 // Set initial directory for a filepicker from URLs saved in prefs
SetFilePickerDirectory
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
559 function SetFilePickerDirectory(filePicker, fileType)
560 {
561 if (filePicker)
562 {
563 try {
564 var prefBranch = GetPrefs();
565 if (prefBranch)
566 {
567 // Save current directory so we can reset it in SaveFilePickerDirectory
568 gFilePickerDirectory = filePicker.displayDirectory;
569
570 var location = prefBranch.getComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile);
571 if (location)
572 filePicker.displayDirectory = location;
573 }
574 }
575 catch(e) {}
576 }
577 }
578
579 // Save the directory of the selected file to prefs
SaveFilePickerDirectory
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
580 function SaveFilePickerDirectory(filePicker, fileType)
581 {
582 if (filePicker && filePicker.file)
583 {
584 try {
585 var prefBranch = GetPrefs();
586
587 var fileDir;
588 if (filePicker.file.parent)
589 fileDir = filePicker.file.parent.QueryInterface(Components.interfaces.nsILocalFile);
590
591 if (prefBranch)
592 prefBranch.setComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile, fileDir);
593
594 var prefsService = GetPrefsService();
595 prefsService.savePrefFile(null);
596 } catch (e) {}
597 }
598
599 // Restore the directory used before SetFilePickerDirectory was called;
600 // This reduces interference with Browser and other module directory defaults
601 if (gFilePickerDirectory)
602 filePicker.displayDirectory = gFilePickerDirectory;
603
604 gFilePickerDirectory = null;
605 }
606
GetDefaultBrowserColors
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
607 function GetDefaultBrowserColors()
608 {
609 var prefs = GetPrefs();
610 var colors = { TextColor:0, BackgroundColor:0, LinkColor:0, ActiveLinkColor:0 , VisitedLinkColor:0 };
611 var useSysColors = false;
612 try { useSysColors = prefs.getBoolPref("browser.display.use_system_colors"); } catch (e) {}
613
614 if (!useSysColors)
615 {
616 try { colors.TextColor = prefs.getCharPref("browser.display.foreground_color"); } catch (e) {}
617
618 try { colors.BackgroundColor = prefs.getCharPref("browser.display.background_color"); } catch (e) {}
619 }
620 // Use OS colors for text and background if explicitly asked or pref is not set
621 if (!colors.TextColor)
622 colors.TextColor = "windowtext";
623
624 if (!colors.BackgroundColor)
625 colors.BackgroundColor = "window";
626
627 colors.LinkColor = prefs.getCharPref("browser.anchor_color");
628 colors.ActiveLinkColor = prefs.getCharPref("browser.active_color");
629 colors.VisitedLinkColor = prefs.getCharPref("browser.visited_color");
630
631 return colors;
632 }
633
634 /************* URL handling ***************/
635
TextIsURI
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
636 function TextIsURI(selectedText)
637 {
638 return selectedText && /^http:\/\/|^https:\/\/|^file:\/\/|'\
639 ' ^ftp:\/\/|^about:|^mailto:|^news:|^snews:|^telnet:|^ldap:|'\
640 ' ^ldaps:|^gopher:|^finger:|^javascript:/i.test(selectedText);
641 }
642
IsUrlAboutBlank
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
643 function IsUrlAboutBlank(urlString)
644 {
645 return (urlString == "about:blank");
646 }
647
MakeRelativeUrl
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
648 function MakeRelativeUrl(url)
649 {
650 var inputUrl = TrimString(url);
651 if (!inputUrl)
652 return inputUrl;
653
654 // Get the filespec relative to current document's location
655 // NOTE: Can't do this if file isn't saved yet!
656 var docUrl = GetDocumentBaseUrl();
657 var docScheme = GetScheme(docUrl);
658
659 // Can't relativize if no doc scheme (page hasn't been saved)
660 if (!docScheme)
661 return inputUrl;
662
663 var urlScheme = GetScheme(inputUrl);
664
665 // Do nothing if not the same scheme or url is already relativized
666 if (docScheme != urlScheme)
667 return inputUrl;
668
669 var IOService = GetIOService();
670 if (!IOService)
671 return inputUrl;
672
673 // Host must be the same
674 var docHost = GetHost(docUrl);
675 var urlHost = GetHost(inputUrl);
676 if (docHost != urlHost)
677 return inputUrl;
678
679
680 // Get just the file path part of the urls
681 // XXX Should we use GetCurrentEditor().documentCharacterSet for 2nd param ?
682 var docPath = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null).path;
683 var urlPath = IOService.newURI(inputUrl, GetCurrentEditor().documentCharacterSet, null).path;
684
685 // We only return "urlPath", so we can convert
686 // the entire docPath for case-insensitive comparisons
687 var os = GetOS();
688 var doCaseInsensitive = (docScheme == "file" && os == gWin);
689 if (doCaseInsensitive)
690 docPath = docPath.toLowerCase();
691
692 // Get document filename before we start chopping up the docPath
693 var docFilename = GetFilename(docPath);
694
695 // Both url and doc paths now begin with "/"
696 // Look for shared dirs starting after that
697 urlPath = urlPath.slice(1);
698 docPath = docPath.slice(1);
699
700 var firstDirTest = true;
701 var nextDocSlash = 0;
702 var done = false;
703
704 // Remove all matching subdirs common to both doc and input urls
705 do {
706 nextDocSlash = docPath.indexOf("\/");
707 var nextUrlSlash = urlPath.indexOf("\/");
708
709 if (nextUrlSlash == -1)
710 {
711 // We're done matching and all dirs in url
712 // what's left is the filename
713 done = true;
714
715 // Remove filename for named anchors in the same file
716 if (nextDocSlash == -1 && docFilename)
717 {
718 var anchorIndex = urlPath.indexOf("#");
719 if (anchorIndex > 0)
720 {
721 var urlFilename = doCaseInsensitive ? urlPath.toLowerCase() : urlPath;
722
723 if (urlFilename.indexOf(docFilename) == 0)
724 urlPath = urlPath.slice(anchorIndex);
725 }
726 }
727 }
728 else if (nextDocSlash >= 0)
729 {
730 // Test for matching subdir
731 var docDir = docPath.slice(0, nextDocSlash);
732 var urlDir = urlPath.slice(0, nextUrlSlash);
733 if (doCaseInsensitive)
734 urlDir = urlDir.toLowerCase();
735
736 if (urlDir == docDir)
737 {
738
739 // Remove matching dir+"/" from each path
740 // and continue to next dir
741 docPath = docPath.slice(nextDocSlash+1);
742 urlPath = urlPath.slice(nextUrlSlash+1);
743 }
744 else
745 {
746 // No match, we're done
747 done = true;
748
749 // Be sure we are on the same local drive or volume
750 // (the first "dir" in the path) because we can't
751 // relativize to different drives/volumes.
752 // UNIX doesn't have volumes, so we must not do this else
753 // the first directory will be misinterpreted as a volume name
754 if (firstDirTest && docScheme == "file" && os != gUNIX)
755 return inputUrl;
756 }
757 }
758 else // No more doc dirs left, we're done
759 done = true;
760
761 firstDirTest = false;
762 }
763 while (!done);
764
765 // Add "../" for each dir left in docPath
766 while (nextDocSlash > 0)
767 {
768 urlPath = "../" + urlPath;
769 nextDocSlash = docPath.indexOf("\/", nextDocSlash+1);
770 }
771 return urlPath;
772 }
773
MakeAbsoluteUrl
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
774 function MakeAbsoluteUrl(url)
775 {
776 var resultUrl = TrimString(url);
777 if (!resultUrl)
778 return resultUrl;
779
780 // Check if URL is already absolute, i.e., it has a scheme
781 var urlScheme = GetScheme(resultUrl);
782
783 if (urlScheme)
784 return resultUrl;
785
786 var docUrl = GetDocumentBaseUrl();
787 var docScheme = GetScheme(docUrl);
788
789 // Can't relativize if no doc scheme (page hasn't been saved)
790 if (!docScheme)
791 return resultUrl;
792
793 var IOService = GetIOService();
794 if (!IOService)
795 return resultUrl;
796
797 // Make a URI object to use its "resolve" method
798 var absoluteUrl = resultUrl;
799 var docUri = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null);
800
801 try {
802 absoluteUrl = docUri.resolve(resultUrl);
803 // This is deprecated and buggy!
804 // If used, we must make it a path for the parent directory (remove filename)
805 //absoluteUrl = IOService.resolveRelativePath(resultUrl, docUrl);
806 } catch (e) {}
807
808 return absoluteUrl;
809 }
810
811 // Get the HREF of the page's <base> tag or the document location
812 // returns empty string if no base href and document hasn't been saved yet
GetDocumentBaseUrl
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
813 function GetDocumentBaseUrl()
814 {
815 try {
816 var docUrl;
817
818 // if document supplies a <base> tag, use that URL instead
819 var baseList = GetCurrentEditor().document.getElementsByTagName("base");
820 if (baseList)
821 {
822 var base = baseList.item(0);
823 if (base)
824 docUrl = base.getAttribute("href");
825 }
826 if (!docUrl)
827 docUrl = GetDocumentUrl();
828
829 if (!IsUrlAboutBlank(docUrl))
830 return docUrl;
831 } catch (e) {}
832 return "";
833 }
834
GetDocumentUrl
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
835 function GetDocumentUrl()
836 {
837 try {
838 var aDOMHTMLDoc = GetCurrentEditor().document.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
839 return aDOMHTMLDoc.URL;
840 }
841 catch (e) {}
842 return "";
843 }
844
845 // Extract the scheme (e.g., 'file', 'http') from a URL string
GetScheme
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
846 function GetScheme(urlspec)
847 {
848 var resultUrl = TrimString(urlspec);
849 // Unsaved document URL has no acceptable scheme yet
850 if (!resultUrl || IsUrlAboutBlank(resultUrl))
851 return "";
852
853 var IOService = GetIOService();
854 if (!IOService)
855 return "";
856
857 var scheme = "";
858 try {
859 // This fails if there's no scheme
860 scheme = IOService.extractScheme(resultUrl);
861 } catch (e) {}
862
863 return scheme ? scheme.toLowerCase() : "";
864 }
865
GetHost
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
866 function GetHost(urlspec)
867 {
868 if (!urlspec)
869 return "";
870
871 var IOService = GetIOService();
872 if (!IOService)
873 return "";
874
875 var host = "";
876 try {
877 host = IOService.newURI(urlspec, null, null).host;
878 } catch (e) {}
879
880 return host;
881 }
882
GetUsername
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
883 function GetUsername(urlspec)
884 {
885 if (!urlspec)
886 return "";
887
888 var IOService = GetIOService();
889 if (!IOService)
890 return "";
891
892 var username = "";
893 try {
894 username = IOService.newURI(urlspec, null, null).username;
895 } catch (e) {}
896
897 return username;
898 }
899
GetFilename
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
900 function GetFilename(urlspec)
901 {
902 if (!urlspec || IsUrlAboutBlank(urlspec))
903 return "";
904
905 var IOService = GetIOService();
906 if (!IOService)
907 return "";
908
909 var filename;
910
911 try {
912 var uri = IOService.newURI(urlspec, null, null);
913 if (uri)
914 {
915 var url = uri.QueryInterface(Components.interfaces.nsIURL);
916 if (url)
917 filename = url.fileName;
918 }
919 } catch (e) {}
920
921 return filename ? filename : "";
922 }
923
924 // Return the url without username and password
925 // Optional output objects return extracted username and password strings
926 // This uses just string routines via nsIIOServices
StripUsernamePassword
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
927 function StripUsernamePassword(urlspec, usernameObj, passwordObj)
928 {
929 urlspec = TrimString(urlspec);
930 if (!urlspec || IsUrlAboutBlank(urlspec))
931 return urlspec;
932
933 if (usernameObj)
934 usernameObj.value = "";
935 if (passwordObj)
936 passwordObj.value = "";
937
938 // "@" must exist else we will never detect username or password
939 var atIndex = urlspec.indexOf("@");
940 if (atIndex > 0)
941 {
942 try {
943 var IOService = GetIOService();
944 if (!IOService)
945 return urlspec;
946
947 var uri = IOService.newURI(urlspec, null, null);
948 var username = uri.username;
949 var password = uri.password;
950
951 if (usernameObj && username)
952 usernameObj.value = username;
953 if (passwordObj && password)
954 passwordObj.value = password;
955 if (username)
956 {
957 var usernameStart = urlspec.indexOf(username);
958 if (usernameStart != -1)
959 return urlspec.slice(0, usernameStart) + urlspec.slice(atIndex+1);
960 }
961 } catch (e) {}
962 }
963 return urlspec;
964 }
965
StripPassword
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
966 function StripPassword(urlspec, passwordObj)
967 {
968 urlspec = TrimString(urlspec);
969 if (!urlspec || IsUrlAboutBlank(urlspec))
970 return urlspec;
971
972 if (passwordObj)
973 passwordObj.value = "";
974
975 // "@" must exist else we will never detect password
976 var atIndex = urlspec.indexOf("@");
977 if (atIndex > 0)
978 {
979 try {
980 var IOService = GetIOService();
981 if (!IOService)
982 return urlspec;
983
984 var password = IOService.newURI(urlspec, null, null).password;
985
986 if (passwordObj && password)
987 passwordObj.value = password;
988 if (password)
989 {
990 // Find last ":" before "@"
991 var colon = urlspec.lastIndexOf(":", atIndex);
992 if (colon != -1)
993 {
994 // Include the "@"
995 return urlspec.slice(0, colon) + urlspec.slice(atIndex);
996 }
997 }
998 } catch (e) {}
999 }
1000 return urlspec;
1001 }
1002
1003 // Version to use when you have an nsIURI object
StripUsernamePasswordFromURI
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1004 function StripUsernamePasswordFromURI(uri)
1005 {
1006 var urlspec = "";
1007 if (uri)
1008 {
1009 try {
1010 urlspec = uri.spec;
1011 var userPass = uri.userPass;
1012 if (userPass)
1013 {
1014 start = urlspec.indexOf(userPass);
1015 urlspec = urlspec.slice(0, start) + urlspec.slice(start+userPass.length+1);
1016 }
1017 } catch (e) {}
1018 }
1019 return urlspec;
1020 }
1021
InsertUsernameIntoUrl
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1022 function InsertUsernameIntoUrl(urlspec, username)
1023 {
1024 if (!urlspec || !username)
1025 return urlspec;
1026
1027 try {
1028 var ioService = GetIOService();
1029 var URI = ioService.newURI(urlspec, GetCurrentEditor().documentCharacterSet, null);
1030 URI.username = username;
1031 return URI.spec;
1032 } catch (e) {}
1033
1034 return urlspec;
1035 }
1036
GetOS
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1037 function GetOS()
1038 {
1039 if (gOS)
1040 return gOS;
1041
1042 var platform = navigator.platform.toLowerCase();
1043
1044 if (platform.indexOf("win") != -1)
1045 gOS = gWin;
1046 else if (platform.indexOf("mac") != -1)
1047 gOS = gMac;
1048 else if (platform.indexOf("unix") != -1 || platform.indexOf("linux") != -1 || platform.indexOf("sun") != -1)
1049 gOS = gUNIX;
1050 else
1051 gOS = "";
1052 // Add other tests?
1053
1054 return gOS;
1055 }
1056
ConvertRGBColorIntoHEXColor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1057 function ConvertRGBColorIntoHEXColor(color)
1058 {
1059 if ( /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.test(color) ) {
1060 var r = Number(RegExp.$1).toString(16);
1061 if (r.length == 1) r = "0"+r;
1062 var g = Number(RegExp.$2).toString(16);
1063 if (g.length == 1) g = "0"+g;
1064 var b = Number(RegExp.$3).toString(16);
1065 if (b.length == 1) b = "0"+b;
1066 return "#"+r+g+b;
1067 }
1068 else
1069 {
1070 return color;
1071 }
1072 }
1073
1074 /************* CSS ***************/
1075
GetHTMLOrCSSStyleValue
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1076 function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
1077 {
1078 var prefs = GetPrefs();
1079 var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
1080 var value;
1081 if (IsCSSPrefChecked && IsHTMLEditor())
1082 value = element.style.getPropertyValue(cssPropertyName);
1083
1084 if (!value)
1085 value = element.getAttribute(attrName);
1086
1087 if (!value)
1088 return "";
1089
1090 return value;
1091 }
1092
1093 /************* Miscellaneous ***************/
1094 // Clone simple JS objects
Clone
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1095 function Clone(obj)
1096 {
1097 var clone = {};
1098 for (var i in obj)
1099 {
1100 if( typeof obj[i] == 'object')
1101 clone[i] = Clone(obj[i]);
1102 else
1103 clone[i] = obj[i];
1104 }
1105 return clone;
1106 }