element(s)
var editorList = tmpWindow.document.getElementsByTagName("editor");
// This will change if we support > 1 editor element
if (editorList.item(0))
return editorList.item(0);
tmpWindow = tmpWindow.opener;
}
while (tmpWindow);
return null;
}
function GetCurrentEditingSession()
{
try {
return GetCurrentEditorElement().editingSession;
} catch (e) { dump (e)+"\n"; }
return null;
}
function GetCurrentCommandManager()
{
try {
return GetCurrentEditorElement().commandManager;
} catch (e) { dump (e)+"\n"; }
return null;
}
function GetCurrentEditorType()
{
try {
return GetCurrentEditorElement().editortype;
} catch (e) { dump (e)+"\n"; }
return "";
}
function IsHTMLEditor()
{
// We don't have an editorElement, just return false
if (!GetCurrentEditorElement())
return false;
var editortype = GetCurrentEditorType();
switch (editortype)
{
case "html":
case "htmlmail":
return true;
case "text":
case "textmail":
return false
default:
dump("INVALID EDITOR TYPE: " + editortype + "\n");
break;
}
return false;
}
function PageIsEmptyAndUntouched()
{
return IsDocumentEmpty() && !IsDocumentModified() && !IsHTMLSourceChanged();
}
function IsInHTMLSourceMode()
{
return (gEditorDisplayMode == kDisplayModeSource);
}
// are we editing HTML (i.e. neither in HTML source mode, nor editing a text file)
function IsEditingRenderedHTML()
{
return IsHTMLEditor() && !IsInHTMLSourceMode();
}
function IsWebComposer()
{
return document.documentElement.id == "editorWindow";
}
function IsDocumentEditable()
{
try {
return GetCurrentEditor().isDocumentEditable;
} catch (e) {}
return false;
}
function IsDocumentEmpty()
{
try {
return GetCurrentEditor().documentIsEmpty;
} catch (e) {}
return false;
}
function IsDocumentModified()
{
try {
return GetCurrentEditor().documentModified;
} catch (e) {}
return false;
}
function IsHTMLSourceChanged()
{
return gSourceTextEditor.documentModified;
}
function newCommandParams()
{
try {
return Components.classes["@mozilla.org/embedcomp/command-params;1"].createInstance(Components.interfaces.nsICommandParams);
}
catch(e) { dump("error thrown in newCommandParams: "+e+"\n"); }
return null;
}
/************* General editing command utilities ***************/
function GetDocumentTitle()
{
try {
return new XPCNativeWrapper(GetCurrentEditor().document, "title").title;
} catch (e) {}
return "";
}
function SetDocumentTitle(title)
{
try {
GetCurrentEditor().setDocumentTitle(title);
// Update window title (doesn't work if called from a dialog)
if ("UpdateWindowTitle" in window)
window.UpdateWindowTitle();
} catch (e) {}
}
var gAtomService;
function GetAtomService()
{
gAtomService = Components.classes["@mozilla.org/atom-service;1"].getService(Components.interfaces.nsIAtomService);
}
function EditorGetTextProperty(property, attribute, value, firstHas, anyHas, allHas)
{
try {
if (!gAtomService) GetAtomService();
var propAtom = gAtomService.getAtom(property);
GetCurrentEditor().getInlineProperty(propAtom, attribute, value,
firstHas, anyHas, allHas);
}
catch(e) {}
}
function EditorSetTextProperty(property, attribute, value)
{
try {
if (!gAtomService) GetAtomService();
var propAtom = gAtomService.getAtom(property);
GetCurrentEditor().setInlineProperty(propAtom, attribute, value);
if ("gContentWindow" in window)
window.gContentWindow.focus();
}
catch(e) {}
}
function EditorRemoveTextProperty(property, attribute)
{
try {
if (!gAtomService) GetAtomService();
var propAtom = gAtomService.getAtom(property);
GetCurrentEditor().removeInlineProperty(propAtom, attribute);
if ("gContentWindow" in window)
window.gContentWindow.focus();
}
catch(e) {}
}
/************* Element enbabling/disabling ***************/
// this function takes an elementID and a flag
// if the element can be found by ID, then it is either enabled (by removing "disabled" attr)
// or disabled (setAttribute) as specified in the "doEnable" parameter
function SetElementEnabledById(elementID, doEnable)
{
SetElementEnabled(document.getElementById(elementID), doEnable);
}
function SetElementEnabled(element, doEnable)
{
if ( element )
{
if ( doEnable )
element.removeAttribute("disabled");
else
element.setAttribute("disabled", "true");
}
else
{
dump("Element not found in SetElementEnabled\n");
}
}
/************* Services / Prefs ***************/
function GetIOService()
{
if (gIOService)
return gIOService;
gIOService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
return gIOService;
}
function GetFileProtocolHandler()
{
var ios = GetIOService();
var handler = ios.getProtocolHandler("file");
return handler.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
}
function GetPrefsService()
{
if (gPrefsService)
return gPrefsService;
try {
gPrefsService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
}
catch(ex) {
dump("failed to get prefs service!\n");
}
return gPrefsService;
}
function GetPrefs()
{
if (gPrefsBranch)
return gPrefsBranch;
try {
var prefService = GetPrefsService();
if (prefService)
gPrefsBranch = prefService.getBranch(null);
if (gPrefsBranch)
return gPrefsBranch;
else
dump("failed to get root prefs!\n");
}
catch(ex) {
dump("failed to get root prefs!\n");
}
return null;
}
function GetStringPref(name)
{
try {
return GetPrefs().getComplexValue(name, Components.interfaces.nsISupportsString).data;
} catch (e) {}
return "";
}
function GetBoolPref(name)
{
try {
return GetPrefs().getBoolPref(name);
} catch (e) {}
return false;
}
function SetUnicharPref(aPrefName, aPrefValue)
{
var prefs = GetPrefs();
if (prefs)
{
try {
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
str.data = aPrefValue;
prefs.setComplexValue(aPrefName, Components.interfaces.nsISupportsString, str);
}
catch(e) {}
}
}
function GetUnicharPref(aPrefName, aDefVal)
{
var prefs = GetPrefs();
if (prefs)
{
try {
return prefs.getComplexValue(aPrefName, Components.interfaces.nsISupportsString).data;
}
catch(e) {}
}
return "";
}
// Set initial directory for a filepicker from URLs saved in prefs
function SetFilePickerDirectory(filePicker, fileType)
{
if (filePicker)
{
try {
var prefBranch = GetPrefs();
if (prefBranch)
{
// Save current directory so we can reset it in SaveFilePickerDirectory
gFilePickerDirectory = filePicker.displayDirectory;
var location = prefBranch.getComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile);
if (location)
filePicker.displayDirectory = location;
}
}
catch(e) {}
}
}
// Save the directory of the selected file to prefs
function SaveFilePickerDirectory(filePicker, fileType)
{
if (filePicker && filePicker.file)
{
try {
var prefBranch = GetPrefs();
var fileDir;
if (filePicker.file.parent)
fileDir = filePicker.file.parent.QueryInterface(Components.interfaces.nsILocalFile);
if (prefBranch)
prefBranch.setComplexValue("editor.lastFileLocation."+fileType, Components.interfaces.nsILocalFile, fileDir);
var prefsService = GetPrefsService();
prefsService.savePrefFile(null);
} catch (e) {}
}
// Restore the directory used before SetFilePickerDirectory was called;
// This reduces interference with Browser and other module directory defaults
if (gFilePickerDirectory)
filePicker.displayDirectory = gFilePickerDirectory;
gFilePickerDirectory = null;
}
function GetDefaultBrowserColors()
{
var prefs = GetPrefs();
var colors = { TextColor:0, BackgroundColor:0, LinkColor:0, ActiveLinkColor:0 , VisitedLinkColor:0 };
var useSysColors = false;
try { useSysColors = prefs.getBoolPref("browser.display.use_system_colors"); } catch (e) {}
if (!useSysColors)
{
try { colors.TextColor = prefs.getCharPref("browser.display.foreground_color"); } catch (e) {}
try { colors.BackgroundColor = prefs.getCharPref("browser.display.background_color"); } catch (e) {}
}
// Use OS colors for text and background if explicitly asked or pref is not set
if (!colors.TextColor)
colors.TextColor = "windowtext";
if (!colors.BackgroundColor)
colors.BackgroundColor = "window";
colors.LinkColor = prefs.getCharPref("browser.anchor_color");
colors.ActiveLinkColor = prefs.getCharPref("browser.active_color");
colors.VisitedLinkColor = prefs.getCharPref("browser.visited_color");
return colors;
}
/************* URL handling ***************/
function TextIsURI(selectedText)
{
return selectedText && /^http:\/\/|^https:\/\/|^file:\/\/|\
^ftp:\/\/|^about:|^mailto:|^news:|^snews:|^telnet:|^ldap:|\
^ldaps:|^gopher:|^finger:|^javascript:/i.test(selectedText);
}
function IsUrlAboutBlank(urlString)
{
return (urlString == "about:blank");
}
function MakeRelativeUrl(url)
{
var inputUrl = TrimString(url);
if (!inputUrl)
return inputUrl;
// Get the filespec relative to current document's location
// NOTE: Can't do this if file isn't saved yet!
var docUrl = GetDocumentBaseUrl();
var docScheme = GetScheme(docUrl);
// Can't relativize if no doc scheme (page hasn't been saved)
if (!docScheme)
return inputUrl;
var urlScheme = GetScheme(inputUrl);
// Do nothing if not the same scheme or url is already relativized
if (docScheme != urlScheme)
return inputUrl;
var IOService = GetIOService();
if (!IOService)
return inputUrl;
// Host must be the same
var docHost = GetHost(docUrl);
var urlHost = GetHost(inputUrl);
if (docHost != urlHost)
return inputUrl;
// Get just the file path part of the urls
// XXX Should we use GetCurrentEditor().documentCharacterSet for 2nd param ?
var docPath = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null).path;
var urlPath = IOService.newURI(inputUrl, GetCurrentEditor().documentCharacterSet, null).path;
// We only return "urlPath", so we can convert
// the entire docPath for case-insensitive comparisons
var os = GetOS();
var doCaseInsensitive = (docScheme == "file" && os == gWin);
if (doCaseInsensitive)
docPath = docPath.toLowerCase();
// Get document filename before we start chopping up the docPath
var docFilename = GetFilename(docPath);
// Both url and doc paths now begin with "/"
// Look for shared dirs starting after that
urlPath = urlPath.slice(1);
docPath = docPath.slice(1);
var firstDirTest = true;
var nextDocSlash = 0;
var done = false;
// Remove all matching subdirs common to both doc and input urls
do {
nextDocSlash = docPath.indexOf("\/");
var nextUrlSlash = urlPath.indexOf("\/");
if (nextUrlSlash == -1)
{
// We're done matching and all dirs in url
// what's left is the filename
done = true;
// Remove filename for named anchors in the same file
if (nextDocSlash == -1 && docFilename)
{
var anchorIndex = urlPath.indexOf("#");
if (anchorIndex > 0)
{
var urlFilename = doCaseInsensitive ? urlPath.toLowerCase() : urlPath;
if (urlFilename.indexOf(docFilename) == 0)
urlPath = urlPath.slice(anchorIndex);
}
}
}
else if (nextDocSlash >= 0)
{
// Test for matching subdir
var docDir = docPath.slice(0, nextDocSlash);
var urlDir = urlPath.slice(0, nextUrlSlash);
if (doCaseInsensitive)
urlDir = urlDir.toLowerCase();
if (urlDir == docDir)
{
// Remove matching dir+"/" from each path
// and continue to next dir
docPath = docPath.slice(nextDocSlash+1);
urlPath = urlPath.slice(nextUrlSlash+1);
}
else
{
// No match, we're done
done = true;
// Be sure we are on the same local drive or volume
// (the first "dir" in the path) because we can't
// relativize to different drives/volumes.
// UNIX doesn't have volumes, so we must not do this else
// the first directory will be misinterpreted as a volume name
if (firstDirTest && docScheme == "file" && os != gUNIX)
return inputUrl;
}
}
else // No more doc dirs left, we're done
done = true;
firstDirTest = false;
}
while (!done);
// Add "../" for each dir left in docPath
while (nextDocSlash > 0)
{
urlPath = "../" + urlPath;
nextDocSlash = docPath.indexOf("\/", nextDocSlash+1);
}
return urlPath;
}
function MakeAbsoluteUrl(url)
{
var resultUrl = TrimString(url);
if (!resultUrl)
return resultUrl;
// Check if URL is already absolute, i.e., it has a scheme
var urlScheme = GetScheme(resultUrl);
if (urlScheme)
return resultUrl;
var docUrl = GetDocumentBaseUrl();
var docScheme = GetScheme(docUrl);
// Can't relativize if no doc scheme (page hasn't been saved)
if (!docScheme)
return resultUrl;
var IOService = GetIOService();
if (!IOService)
return resultUrl;
// Make a URI object to use its "resolve" method
var absoluteUrl = resultUrl;
var docUri = IOService.newURI(docUrl, GetCurrentEditor().documentCharacterSet, null);
try {
absoluteUrl = docUri.resolve(resultUrl);
// This is deprecated and buggy!
// If used, we must make it a path for the parent directory (remove filename)
//absoluteUrl = IOService.resolveRelativePath(resultUrl, docUrl);
} catch (e) {}
return absoluteUrl;
}
// Get the HREF of the page's tag or the document location
// returns empty string if no base href and document hasn't been saved yet
function GetDocumentBaseUrl()
{
try {
var docUrl;
// if document supplies a tag, use that URL instead
var baseList = GetCurrentEditor().document.getElementsByTagName("base");
if (baseList)
{
var base = baseList.item(0);
if (base)
docUrl = base.getAttribute("href");
}
if (!docUrl)
docUrl = GetDocumentUrl();
if (!IsUrlAboutBlank(docUrl))
return docUrl;
} catch (e) {}
return "";
}
function GetDocumentUrl()
{
try {
var aDOMHTMLDoc = GetCurrentEditor().document.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
return aDOMHTMLDoc.URL;
}
catch (e) {}
return "";
}
// Extract the scheme (e.g., 'file', 'http') from a URL string
function GetScheme(urlspec)
{
var resultUrl = TrimString(urlspec);
// Unsaved document URL has no acceptable scheme yet
if (!resultUrl || IsUrlAboutBlank(resultUrl))
return "";
var IOService = GetIOService();
if (!IOService)
return "";
var scheme = "";
try {
// This fails if there's no scheme
scheme = IOService.extractScheme(resultUrl);
} catch (e) {}
return scheme ? scheme.toLowerCase() : "";
}
function GetHost(urlspec)
{
if (!urlspec)
return "";
var IOService = GetIOService();
if (!IOService)
return "";
var host = "";
try {
host = IOService.newURI(urlspec, null, null).host;
} catch (e) {}
return host;
}
function GetUsername(urlspec)
{
if (!urlspec)
return "";
var IOService = GetIOService();
if (!IOService)
return "";
var username = "";
try {
username = IOService.newURI(urlspec, null, null).username;
} catch (e) {}
return username;
}
function GetFilename(urlspec)
{
if (!urlspec || IsUrlAboutBlank(urlspec))
return "";
var IOService = GetIOService();
if (!IOService)
return "";
var filename;
try {
var uri = IOService.newURI(urlspec, null, null);
if (uri)
{
var url = uri.QueryInterface(Components.interfaces.nsIURL);
if (url)
filename = url.fileName;
}
} catch (e) {}
return filename ? filename : "";
}
// Return the url without username and password
// Optional output objects return extracted username and password strings
// This uses just string routines via nsIIOServices
function StripUsernamePassword(urlspec, usernameObj, passwordObj)
{
urlspec = TrimString(urlspec);
if (!urlspec || IsUrlAboutBlank(urlspec))
return urlspec;
if (usernameObj)
usernameObj.value = "";
if (passwordObj)
passwordObj.value = "";
// "@" must exist else we will never detect username or password
var atIndex = urlspec.indexOf("@");
if (atIndex > 0)
{
try {
var IOService = GetIOService();
if (!IOService)
return urlspec;
var uri = IOService.newURI(urlspec, null, null);
var username = uri.username;
var password = uri.password;
if (usernameObj && username)
usernameObj.value = username;
if (passwordObj && password)
passwordObj.value = password;
if (username)
{
var usernameStart = urlspec.indexOf(username);
if (usernameStart != -1)
return urlspec.slice(0, usernameStart) + urlspec.slice(atIndex+1);
}
} catch (e) {}
}
return urlspec;
}
function StripPassword(urlspec, passwordObj)
{
urlspec = TrimString(urlspec);
if (!urlspec || IsUrlAboutBlank(urlspec))
return urlspec;
if (passwordObj)
passwordObj.value = "";
// "@" must exist else we will never detect password
var atIndex = urlspec.indexOf("@");
if (atIndex > 0)
{
try {
var IOService = GetIOService();
if (!IOService)
return urlspec;
var password = IOService.newURI(urlspec, null, null).password;
if (passwordObj && password)
passwordObj.value = password;
if (password)
{
// Find last ":" before "@"
var colon = urlspec.lastIndexOf(":", atIndex);
if (colon != -1)
{
// Include the "@"
return urlspec.slice(0, colon) + urlspec.slice(atIndex);
}
}
} catch (e) {}
}
return urlspec;
}
// Version to use when you have an nsIURI object
function StripUsernamePasswordFromURI(uri)
{
var urlspec = "";
if (uri)
{
try {
urlspec = uri.spec;
var userPass = uri.userPass;
if (userPass)
{
start = urlspec.indexOf(userPass);
urlspec = urlspec.slice(0, start) + urlspec.slice(start+userPass.length+1);
}
} catch (e) {}
}
return urlspec;
}
function InsertUsernameIntoUrl(urlspec, username)
{
if (!urlspec || !username)
return urlspec;
try {
var ioService = GetIOService();
var URI = ioService.newURI(urlspec, GetCurrentEditor().documentCharacterSet, null);
URI.username = username;
return URI.spec;
} catch (e) {}
return urlspec;
}
function GetOS()
{
if (gOS)
return gOS;
var platform = navigator.platform.toLowerCase();
if (platform.indexOf("win") != -1)
gOS = gWin;
else if (platform.indexOf("mac") != -1)
gOS = gMac;
else if (platform.indexOf("unix") != -1 || platform.indexOf("linux") != -1 || platform.indexOf("sun") != -1)
gOS = gUNIX;
else
gOS = "";
// Add other tests?
return gOS;
}
function ConvertRGBColorIntoHEXColor(color)
{
if ( /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.test(color) ) {
var r = Number(RegExp.$1).toString(16);
if (r.length == 1) r = "0"+r;
var g = Number(RegExp.$2).toString(16);
if (g.length == 1) g = "0"+g;
var b = Number(RegExp.$3).toString(16);
if (b.length == 1) b = "0"+b;
return "#"+r+g+b;
}
else
{
return color;
}
}
/************* CSS ***************/
function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
{
var prefs = GetPrefs();
var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
var value;
if (IsCSSPrefChecked && IsHTMLEditor())
value = element.style.getPropertyValue(cssPropertyName);
if (!value)
value = element.getAttribute(attrName);
if (!value)
return "";
return value;
}
/************* Miscellaneous ***************/
// Clone simple JS objects
function Clone(obj)
{
var clone = {};
for (var i in obj)
{
if( typeof obj[i] == 'object')
clone[i] = Clone(obj[i]);
else
clone[i] = obj[i];
}
return clone;
}
PK
T0
" content/editor/ComposerCommands.jsUT 6@NDDUx /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser (sfraser@netscape.com)
* Ryan Cassin (rcassin@supernova.org)
* Kathleen Brade (brade@netscape.com)
* Daniel Glazman (glazman@netscape.com)
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Implementations of nsIControllerCommand for composer commands */
var gComposerJSCommandControllerID = 0;
//-----------------------------------------------------------------------------------
function SetupHTMLEditorCommands()
{
var commandTable = GetComposerCommandTable();
if (!commandTable)
return;
// Include everthing a text editor does
SetupTextEditorCommands();
//dump("Registering HTML editor commands\n");
commandTable.registerCommand("cmd_renderedHTMLEnabler", nsDummyHTMLCommand);
commandTable.registerCommand("cmd_grid", nsGridCommand);
commandTable.registerCommand("cmd_listProperties", nsListPropertiesCommand);
commandTable.registerCommand("cmd_pageProperties", nsPagePropertiesCommand);
commandTable.registerCommand("cmd_colorProperties", nsColorPropertiesCommand);
commandTable.registerCommand("cmd_advancedProperties", nsAdvancedPropertiesCommand);
commandTable.registerCommand("cmd_objectProperties", nsObjectPropertiesCommand);
commandTable.registerCommand("cmd_removeNamedAnchors", nsRemoveNamedAnchorsCommand);
commandTable.registerCommand("cmd_editLink", nsEditLinkCommand);
commandTable.registerCommand("cmd_form", nsFormCommand);
commandTable.registerCommand("cmd_inputtag", nsInputTagCommand);
commandTable.registerCommand("cmd_inputimage", nsInputImageCommand);
commandTable.registerCommand("cmd_textarea", nsTextAreaCommand);
commandTable.registerCommand("cmd_select", nsSelectCommand);
commandTable.registerCommand("cmd_button", nsButtonCommand);
commandTable.registerCommand("cmd_label", nsLabelCommand);
commandTable.registerCommand("cmd_fieldset", nsFieldSetCommand);
commandTable.registerCommand("cmd_isindex", nsIsIndexCommand);
commandTable.registerCommand("cmd_image", nsImageCommand);
commandTable.registerCommand("cmd_hline", nsHLineCommand);
commandTable.registerCommand("cmd_link", nsLinkCommand);
commandTable.registerCommand("cmd_anchor", nsAnchorCommand);
commandTable.registerCommand("cmd_insertHTMLWithDialog", nsInsertHTMLWithDialogCommand);
commandTable.registerCommand("cmd_insertBreak", nsInsertBreakCommand);
commandTable.registerCommand("cmd_insertBreakAll",nsInsertBreakAllCommand);
commandTable.registerCommand("cmd_table", nsInsertOrEditTableCommand);
commandTable.registerCommand("cmd_editTable", nsEditTableCommand);
commandTable.registerCommand("cmd_SelectTable", nsSelectTableCommand);
commandTable.registerCommand("cmd_SelectRow", nsSelectTableRowCommand);
commandTable.registerCommand("cmd_SelectColumn", nsSelectTableColumnCommand);
commandTable.registerCommand("cmd_SelectCell", nsSelectTableCellCommand);
commandTable.registerCommand("cmd_SelectAllCells", nsSelectAllTableCellsCommand);
commandTable.registerCommand("cmd_InsertTable", nsInsertTableCommand);
commandTable.registerCommand("cmd_InsertRowAbove", nsInsertTableRowAboveCommand);
commandTable.registerCommand("cmd_InsertRowBelow", nsInsertTableRowBelowCommand);
commandTable.registerCommand("cmd_InsertColumnBefore", nsInsertTableColumnBeforeCommand);
commandTable.registerCommand("cmd_InsertColumnAfter", nsInsertTableColumnAfterCommand);
commandTable.registerCommand("cmd_InsertCellBefore", nsInsertTableCellBeforeCommand);
commandTable.registerCommand("cmd_InsertCellAfter", nsInsertTableCellAfterCommand);
commandTable.registerCommand("cmd_DeleteTable", nsDeleteTableCommand);
commandTable.registerCommand("cmd_DeleteRow", nsDeleteTableRowCommand);
commandTable.registerCommand("cmd_DeleteColumn", nsDeleteTableColumnCommand);
commandTable.registerCommand("cmd_DeleteCell", nsDeleteTableCellCommand);
commandTable.registerCommand("cmd_DeleteCellContents", nsDeleteTableCellContentsCommand);
commandTable.registerCommand("cmd_JoinTableCells", nsJoinTableCellsCommand);
commandTable.registerCommand("cmd_SplitTableCell", nsSplitTableCellCommand);
commandTable.registerCommand("cmd_TableOrCellColor", nsTableOrCellColorCommand);
commandTable.registerCommand("cmd_NormalizeTable", nsNormalizeTableCommand);
commandTable.registerCommand("cmd_smiley", nsSetSmiley);
commandTable.registerCommand("cmd_ConvertToTable", nsConvertToTable);
}
function SetupTextEditorCommands()
{
var commandTable = GetComposerCommandTable();
if (!commandTable)
return;
//dump("Registering plain text editor commands\n");
commandTable.registerCommand("cmd_find", nsFindCommand);
commandTable.registerCommand("cmd_findNext", nsFindAgainCommand);
commandTable.registerCommand("cmd_findPrev", nsFindAgainCommand);
commandTable.registerCommand("cmd_rewrap", nsRewrapCommand);
commandTable.registerCommand("cmd_spelling", nsSpellingCommand);
commandTable.registerCommand("cmd_validate", nsValidateCommand);
commandTable.registerCommand("cmd_checkLinks", nsCheckLinksCommand);
commandTable.registerCommand("cmd_insertChars", nsInsertCharsCommand);
}
function SetupComposerWindowCommands()
{
// Don't need to do this if already done
if (gComposerWindowControllerID)
return;
// Create a command controller and register commands
// specific to Web Composer window (file-related commands, HTML Source...)
// We can't use the composer controller created on the content window else
// we can't process commands when in HTMLSource editor
// IMPORTANT: For each of these commands, the doCommand method
// must first call FinishHTMLSource()
// to go from HTML Source mode to any other edit mode
var windowControllers = window.controllers;
if (!windowControllers) return;
var commandTable;
var composerController;
var editorController;
try {
composerController = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
editorController = composerController.QueryInterface(Components.interfaces.nsIControllerContext);
editorController.init(null); // init it without passing in a command table
// Get the nsIControllerCommandTable interface we need to register commands
var interfaceRequestor = composerController.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
commandTable = interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
}
catch (e)
{
dump("Failed to create composerController\n");
return;
}
if (!commandTable)
{
dump("Failed to get interface for nsIControllerCommandManager\n");
return;
}
// File-related commands
commandTable.registerCommand("cmd_open", nsOpenCommand);
commandTable.registerCommand("cmd_save", nsSaveCommand);
commandTable.registerCommand("cmd_saveAs", nsSaveAsCommand);
commandTable.registerCommand("cmd_exportToText", nsExportToTextCommand);
commandTable.registerCommand("cmd_saveAndChangeEncoding", nsSaveAndChangeEncodingCommand);
commandTable.registerCommand("cmd_publish", nsPublishCommand);
commandTable.registerCommand("cmd_publishAs", nsPublishAsCommand);
commandTable.registerCommand("cmd_publishSettings",nsPublishSettingsCommand);
commandTable.registerCommand("cmd_revert", nsRevertCommand);
commandTable.registerCommand("cmd_openRemote", nsOpenRemoteCommand);
commandTable.registerCommand("cmd_preview", nsPreviewCommand);
commandTable.registerCommand("cmd_editSendPage", nsSendPageCommand);
commandTable.registerCommand("cmd_print", nsPrintCommand);
commandTable.registerCommand("cmd_printSetup", nsPrintSetupCommand);
commandTable.registerCommand("cmd_quit", nsQuitCommand);
commandTable.registerCommand("cmd_close", nsCloseCommand);
commandTable.registerCommand("cmd_preferences", nsPreferencesCommand);
// Edit Mode commands
if (GetCurrentEditorType() == "html")
{
commandTable.registerCommand("cmd_NormalMode", nsNormalModeCommand);
commandTable.registerCommand("cmd_AllTagsMode", nsAllTagsModeCommand);
commandTable.registerCommand("cmd_HTMLSourceMode", nsHTMLSourceModeCommand);
commandTable.registerCommand("cmd_PreviewMode", nsPreviewModeCommand);
commandTable.registerCommand("cmd_FinishHTMLSource", nsFinishHTMLSource);
commandTable.registerCommand("cmd_CancelHTMLSource", nsCancelHTMLSource);
commandTable.registerCommand("cmd_updateStructToolbar", nsUpdateStructToolbarCommand);
}
windowControllers.insertControllerAt(0, editorController);
// Store the controller ID so we can be sure to get the right one later
gComposerWindowControllerID = windowControllers.getControllerId(editorController);
}
//-----------------------------------------------------------------------------------
function GetComposerCommandTable()
{
var controller;
if (gComposerJSCommandControllerID)
{
try {
controller = window.content.controllers.getControllerById(gComposerJSCommandControllerID);
} catch (e) {}
}
if (!controller)
{
//create it
controller = Components.classes["@mozilla.org/embedcomp/base-command-controller;1"].createInstance();
var editorController = controller.QueryInterface(Components.interfaces.nsIControllerContext);
editorController.init(null);
editorController.setCommandContext(GetCurrentEditorElement());
window.content.controllers.insertControllerAt(0, controller);
// Store the controller ID so we can be sure to get the right one later
gComposerJSCommandControllerID = window.content.controllers.getControllerId(controller);
}
if (controller)
{
var interfaceRequestor = controller.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
return interfaceRequestor.getInterface(Components.interfaces.nsIControllerCommandTable);
}
return null;
}
//-----------------------------------------------------------------------------------
function goUpdateCommandState(command)
{
try
{
var controller = top.document.commandDispatcher.getControllerForCommand(command);
if (!(controller instanceof Components.interfaces.nsICommandController))
return;
var params = newCommandParams();
if (!params) return;
controller.getCommandStateWithParams(command, params);
switch (command)
{
case "cmd_bold":
case "cmd_italic":
case "cmd_underline":
case "cmd_var":
case "cmd_samp":
case "cmd_code":
case "cmd_acronym":
case "cmd_abbr":
case "cmd_cite":
case "cmd_strong":
case "cmd_em":
case "cmd_superscript":
case "cmd_subscript":
case "cmd_strikethrough":
case "cmd_tt":
case "cmd_nobreak":
case "cmd_ul":
case "cmd_ol":
pokeStyleUI(command, params.getBooleanValue("state_all"));
break;
case "cmd_paragraphState":
case "cmd_align":
case "cmd_highlight":
case "cmd_backgroundColor":
case "cmd_fontColor":
case "cmd_fontFace":
case "cmd_fontSize":
case "cmd_absPos":
pokeMultiStateUI(command, params);
break;
case "cmd_decreaseZIndex":
case "cmd_increaseZIndex":
case "cmd_indent":
case "cmd_outdent":
case "cmd_increaseFont":
case "cmd_decreaseFont":
case "cmd_removeStyles":
case "cmd_smiley":
break;
default: dump("no update for command: " +command+"\n");
}
}
catch (e) { dump("An error occurred updating the "+command+" command: \n"+e+"\n"); }
}
function goUpdateComposerMenuItems(commandset)
{
//dump("Updating commands for " + commandset.id + "\n");
for (var i = 0; i < commandset.childNodes.length; i++)
{
var commandNode = commandset.childNodes[i];
var commandID = commandNode.id;
if (commandID)
{
goUpdateCommand(commandID); // enable or disable
if (commandNode.hasAttribute("state"))
goUpdateCommandState(commandID);
}
}
}
//-----------------------------------------------------------------------------------
function goDoCommandParams(command, params)
{
try
{
var controller = top.document.commandDispatcher.getControllerForCommand(command);
if (controller && controller.isCommandEnabled(command))
{
if (controller instanceof Components.interfaces.nsICommandController)
{
controller.doCommandWithParams(command, params);
// the following two lines should be removed when we implement observers
if (params)
controller.getCommandStateWithParams(command, params);
}
else
{
controller.doCommand(command);
}
ResetStructToolbar();
}
}
catch (e)
{
dump("An error occurred executing the "+command+" command\n");
}
}
function pokeStyleUI(uiID, aDesiredState)
{
try {
var commandNode = top.document.getElementById(uiID);
if (!commandNode)
return;
var uiState = ("true" == commandNode.getAttribute("state"));
if (aDesiredState != uiState)
{
var newState;
if (aDesiredState)
newState = "true";
else
newState = "false";
commandNode.setAttribute("state", newState);
}
} catch(e) { dump("poking UI for "+uiID+" failed: "+e+"\n"); }
}
function doStyleUICommand(cmdStr)
{
try
{
var cmdParams = newCommandParams();
goDoCommandParams(cmdStr, cmdParams);
if (cmdParams)
pokeStyleUI(cmdStr, cmdParams.getBooleanValue("state_all"));
ResetStructToolbar();
} catch(e) {}
}
function pokeMultiStateUI(uiID, cmdParams)
{
try
{
var commandNode = document.getElementById(uiID);
if (!commandNode)
return;
var isMixed = cmdParams.getBooleanValue("state_mixed");
var desiredAttrib;
if (isMixed)
desiredAttrib = "mixed";
else
desiredAttrib = cmdParams.getCStringValue("state_attribute");
var uiState = commandNode.getAttribute("state");
if (desiredAttrib != uiState)
{
commandNode.setAttribute("state", desiredAttrib);
}
} catch(e) {}
}
function doStatefulCommand(commandID, newState)
{
var commandNode = document.getElementById(commandID);
if (commandNode)
commandNode.setAttribute("state", newState);
gContentWindow.focus(); // needed for command dispatch to work
try
{
var cmdParams = newCommandParams();
if (!cmdParams) return;
cmdParams.setCStringValue("state_attribute", newState);
goDoCommandParams(commandID, cmdParams);
pokeMultiStateUI(commandID, cmdParams);
ResetStructToolbar();
} catch(e) { dump("error thrown in doStatefulCommand: "+e+"\n"); }
}
//-----------------------------------------------------------------------------------
function PrintObject(obj)
{
dump("-----" + obj + "------\n");
var names = "";
for (var i in obj)
{
if (i == "value")
names += i + ": " + obj.value + "\n";
else if (i == "id")
names += i + ": " + obj.id + "\n";
else
names += i + "\n";
}
dump(names + "-----------\n");
}
//-----------------------------------------------------------------------------------
function PrintNodeID(id)
{
PrintObject(document.getElementById(id));
}
//-----------------------------------------------------------------------------------
var nsDummyHTMLCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// do nothing
dump("Hey, who's calling the dummy command?\n");
}
};
//-----------------------------------------------------------------------------------
var nsOpenCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; // we can always do this
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(window, GetString("OpenHTMLFile"), nsIFilePicker.modeOpen);
SetFilePickerDirectory(fp, "html");
// When loading into Composer, direct user to prefer HTML files and text files,
// so we call separately to control the order of the filter list
fp.appendFilters(nsIFilePicker.filterHTML);
fp.appendFilters(nsIFilePicker.filterText);
fp.appendFilters(nsIFilePicker.filterAll);
/* doesn't handle *.shtml files */
try {
fp.show();
/* need to handle cancel (uncaught exception at present) */
}
catch (ex) {
dump("filePicker.chooseInputFile threw an exception\n");
}
/* This checks for already open window and activates it...
* note that we have to test the native path length
* since file.URL will be "file:///" if no filename picked (Cancel button used)
*/
if (fp.file && fp.file.path.length > 0) {
SaveFilePickerDirectory(fp, "html");
editPage(fp.fileURL.spec, window, false);
}
}
};
// STRUCTURE TOOLBAR
//
var nsUpdateStructToolbarCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
UpdateStructToolbar();
return true;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand) {}
}
// ******* File output commands and utilities ******** //
//-----------------------------------------------------------------------------------
var nsSaveCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
// Always allow saving when editing a remote document,
// otherwise the document modified state would prevent that
// when you first open a remote file.
try {
var docUrl = GetDocumentUrl();
return IsDocumentEditable() &&
(IsDocumentModified() || IsHTMLSourceChanged() ||
IsUrlAboutBlank(docUrl) || GetScheme(docUrl) != "file");
} catch (e) {return false;}
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var result = false;
var editor = GetCurrentEditor();
if (editor)
{
FinishHTMLSource();
result = SaveDocument(IsUrlAboutBlank(GetDocumentUrl()), false, editor.contentsMIMEType);
window.content.focus();
}
return result;
}
}
var nsSaveAsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var editor = GetCurrentEditor();
if (editor)
{
FinishHTMLSource();
var result = SaveDocument(true, false, editor.contentsMIMEType);
window.content.focus();
return result;
}
return false;
}
}
var nsExportToTextCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (GetCurrentEditor())
{
FinishHTMLSource();
var result = SaveDocument(true, true, "text/plain");
window.content.focus();
return result;
}
return false;
}
}
var nsSaveAndChangeEncodingCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
FinishHTMLSource();
window.ok = false;
window.exportToText = false;
var oldTitle = GetDocumentTitle();
window.openDialog("chrome://editor/content/EditorSaveAsCharset.xul","_blank", "chrome,close,titlebar,modal,resizable=yes");
if (GetDocumentTitle() != oldTitle)
UpdateWindowTitle();
if (window.ok)
{
if (window.exportToText)
{
window.ok = SaveDocument(true, true, "text/plain");
}
else
{
var editor = GetCurrentEditor();
window.ok = SaveDocument(true, false, editor ? editor.contentsMIMEType : null);
}
}
window.content.focus();
return window.ok;
}
};
var nsPublishCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
if (IsDocumentEditable())
{
// Always allow publishing when editing a local document,
// otherwise the document modified state would prevent that
// when you first open any local file.
try {
var docUrl = GetDocumentUrl();
return IsDocumentModified() || IsHTMLSourceChanged()
|| IsUrlAboutBlank(docUrl) || GetScheme(docUrl) == "file";
} catch (e) {return false;}
}
return false;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (GetCurrentEditor())
{
var docUrl = GetDocumentUrl();
var filename = GetFilename(docUrl);
var publishData;
var showPublishDialog = false;
// First check pref to always show publish dialog
try {
var prefs = GetPrefs();
if (prefs)
showPublishDialog = prefs.getBoolPref("editor.always_show_publish_dialog");
} catch(e) {}
if (!showPublishDialog && filename)
{
// Try to get publish data from the document url
publishData = CreatePublishDataFromUrl(docUrl);
// If none, use default publishing site? Need a pref for this
//if (!publishData)
// publishData = GetPublishDataFromSiteName(GetDefaultPublishSiteName(), filename);
}
if (showPublishDialog || !publishData)
{
// Show the publish dialog
publishData = {};
window.ok = false;
var oldTitle = GetDocumentTitle();
window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
"chrome,close,titlebar,modal", "", "", publishData);
if (GetDocumentTitle() != oldTitle)
UpdateWindowTitle();
window.content.focus();
if (!window.ok)
return false;
}
if (publishData)
{
FinishHTMLSource();
return Publish(publishData);
}
}
return false;
}
}
var nsPublishAsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (GetCurrentEditor())
{
FinishHTMLSource();
window.ok = false;
var publishData = {};
var oldTitle = GetDocumentTitle();
window.openDialog("chrome://editor/content/EditorPublish.xul","_blank",
"chrome,close,titlebar,modal", "", "", publishData);
if (GetDocumentTitle() != oldTitle)
UpdateWindowTitle();
window.content.focus();
if (window.ok)
return Publish(publishData);
}
return false;
}
}
// ------- output utilites ----- //
// returns a fileExtension string
function GetExtensionBasedOnMimeType(aMIMEType)
{
try {
var mimeService = null;
mimeService = Components.classes["@mozilla.org/mime;1"].getService();
mimeService = mimeService.QueryInterface(Components.interfaces.nsIMIMEService);
var fileExtension = mimeService.getPrimaryExtension(aMIMEType, null);
// the MIME service likes to give back ".htm" for text/html files,
// so do a special-case fix here.
if (fileExtension == "htm")
fileExtension = "html";
return fileExtension;
}
catch (e) {}
return "";
}
function GetSuggestedFileName(aDocumentURLString, aMIMEType)
{
var extension = GetExtensionBasedOnMimeType(aMIMEType);
if (extension)
extension = "." + extension;
// check for existing file name we can use
if (aDocumentURLString.length >= 0 && !IsUrlAboutBlank(aDocumentURLString))
{
var docURI = null;
try {
var ioService = GetIOService();
docURI = ioService.newURI(aDocumentURLString, GetCurrentEditor().documentCharacterSet, null);
docURI = docURI.QueryInterface(Components.interfaces.nsIURL);
// grab the file name
var url = docURI.fileBaseName;
if (url)
return url+extension;
} catch(e) {}
}
// check if there is a title we can use
var title = GetDocumentTitle();
// generate a valid filename, if we can't just go with "untitled"
return GenerateValidFilename(title, extension) || GetString("untitled") + extension;
}
// returns file picker result
function PromptForSaveLocation(aDoSaveAsText, aEditorType, aMIMEType, aDocumentURLString)
{
var dialogResult = {};
dialogResult.filepickerClick = nsIFilePicker.returnCancel;
dialogResult.resultingURI = "";
dialogResult.resultingLocalFile = null;
var fp = null;
try {
fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
} catch (e) {}
if (!fp) return dialogResult;
// determine prompt string based on type of saving we'll do
var promptString;
if (aDoSaveAsText || aEditorType == "text")
promptString = GetString("ExportToText");
else
promptString = GetString("SaveDocumentAs")
fp.init(window, promptString, nsIFilePicker.modeSave);
// Set filters according to the type of output
if (aDoSaveAsText)
fp.appendFilters(nsIFilePicker.filterText);
else
fp.appendFilters(nsIFilePicker.filterHTML);
fp.appendFilters(nsIFilePicker.filterAll);
// now let's actually set the filepicker's suggested filename
var suggestedFileName = GetSuggestedFileName(aDocumentURLString, aMIMEType);
if (suggestedFileName)
fp.defaultString = suggestedFileName;
// set the file picker's current directory
// assuming we have information needed (like prior saved location)
try {
var ioService = GetIOService();
var fileHandler = GetFileProtocolHandler();
var isLocalFile = true;
try {
var docURI = ioService.newURI(aDocumentURLString, GetCurrentEditor().documentCharacterSet, null);
isLocalFile = docURI.schemeIs("file");
}
catch (e) {}
var parentLocation = null;
if (isLocalFile)
{
var fileLocation = fileHandler.getFileFromURLSpec(aDocumentURLString); // this asserts if url is not local
parentLocation = fileLocation.parent;
}
if (parentLocation)
{
// Save current filepicker's default location
if ("gFilePickerDirectory" in window)
gFilePickerDirectory = fp.displayDirectory;
fp.displayDirectory = parentLocation;
}
else
{
// Initialize to the last-used directory for the particular type (saved in prefs)
SetFilePickerDirectory(fp, aEditorType);
}
}
catch(e) {}
dialogResult.filepickerClick = fp.show();
if (dialogResult.filepickerClick != nsIFilePicker.returnCancel)
{
// reset urlstring to new save location
dialogResult.resultingURIString = fileHandler.getURLSpecFromFile(fp.file);
dialogResult.resultingLocalFile = fp.file;
SaveFilePickerDirectory(fp, aEditorType);
}
else if ("gFilePickerDirectory" in window && gFilePickerDirectory)
fp.displayDirectory = gFilePickerDirectory;
return dialogResult;
}
// returns a boolean (whether to continue (true) or not (false) because user canceled)
function PromptAndSetTitleIfNone()
{
if (GetDocumentTitle()) // we have a title; no need to prompt!
return true;
var promptService = GetPromptService();
if (!promptService) return false;
var result = {value:null};
var captionStr = GetString("DocumentTitle");
var msgStr = GetString("NeedDocTitle") + '\n' + GetString("DocTitleHelp");
var confirmed = promptService.prompt(window, captionStr, msgStr, result, null, {value:0});
if (confirmed)
SetDocumentTitle(TrimString(result.value));
return confirmed;
}
var gPersistObj;
// Don't forget to do these things after calling OutputFileWithPersistAPI:
// we need to update the uri before notifying listeners
// if (doUpdateURI)
// SetDocumentURI(docURI);
// UpdateWindowTitle();
// if (!aSaveCopy)
// editor.resetModificationCount();
// this should cause notification to listeners that document has changed
const webPersist = Components.interfaces.nsIWebBrowserPersist;
function OutputFileWithPersistAPI(editorDoc, aDestinationLocation, aRelatedFilesParentDir, aMimeType)
{
gPersistObj = null;
var editor = GetCurrentEditor();
try {
var imeEditor = editor.QueryInterface(Components.interfaces.nsIEditorIMESupport);
imeEditor.ForceCompositionEnd();
} catch (e) {}
var isLocalFile = false;
try {
var tmp1 = aDestinationLocation.QueryInterface(Components.interfaces.nsIFile);
isLocalFile = true;
}
catch (e) {
try {
var tmp = aDestinationLocation.QueryInterface(Components.interfaces.nsIURI);
isLocalFile = tmp.schemeIs("file");
}
catch (e) {}
}
try {
// we should supply a parent directory if/when we turn on functionality to save related documents
var persistObj = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(webPersist);
persistObj.progressListener = gEditorOutputProgressListener;
var wrapColumn = GetWrapColumn();
var outputFlags = GetOutputFlags(aMimeType, wrapColumn);
// for 4.x parity as well as improving readability of file locally on server
// this will always send crlf for upload (http/ftp)
if (!isLocalFile) // if we aren't saving locally then send both cr and lf
{
outputFlags |= webPersist.ENCODE_FLAGS_CR_LINEBREAKS | webPersist.ENCODE_FLAGS_LF_LINEBREAKS;
// we want to serialize the output for all remote publishing
// some servers can handle only one connection at a time
// some day perhaps we can make this user-configurable per site?
persistObj.persistFlags = persistObj.persistFlags | webPersist.PERSIST_FLAGS_SERIALIZE_OUTPUT;
}
// note: we always want to set the replace existing files flag since we have
// already given user the chance to not replace an existing file (file picker)
// or the user picked an option where the file is implicitly being replaced (save)
persistObj.persistFlags = persistObj.persistFlags
| webPersist.PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS
| webPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES
| webPersist.PERSIST_FLAGS_DONT_FIXUP_LINKS
| webPersist.PERSIST_FLAGS_DONT_CHANGE_FILENAMES
| webPersist.PERSIST_FLAGS_FIXUP_ORIGINAL_DOM;
persistObj.saveDocument(editorDoc, aDestinationLocation, aRelatedFilesParentDir,
aMimeType, outputFlags, wrapColumn);
gPersistObj = persistObj;
}
catch(e) { dump("caught an error, bail\n"); return false; }
return true;
}
// returns output flags based on mimetype, wrapCol and prefs
function GetOutputFlags(aMimeType, aWrapColumn)
{
var outputFlags = 0;
var editor = GetCurrentEditor();
var outputEntity = (editor && editor.documentCharacterSet == "ISO-8859-1")
? webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES
: webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES;
if (aMimeType == "text/plain")
{
// When saving in "text/plain" format, always do formatting
outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
}
else
{
try {
// Should we prettyprint? Check the pref
var prefs = GetPrefs();
if (prefs.getBoolPref("editor.prettyprint"))
outputFlags |= webPersist.ENCODE_FLAGS_FORMATTED;
// How much entity names should we output? Check the pref
var encodeEntity = prefs.getCharPref("editor.encode_entity");
switch (encodeEntity) {
case "basic" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES; break;
case "latin1" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_LATIN1_ENTITIES; break;
case "html" : outputEntity = webPersist.ENCODE_FLAGS_ENCODE_HTML_ENTITIES; break;
case "none" : outputEntity = 0; break;
}
}
catch (e) {}
}
outputFlags |= outputEntity;
if (aWrapColumn > 0)
outputFlags |= webPersist.ENCODE_FLAGS_WRAP;
return outputFlags;
}
// returns number of column where to wrap
const nsIWebBrowserPersist = Components.interfaces.nsIWebBrowserPersist;
function GetWrapColumn()
{
try {
return GetCurrentEditor().wrapWidth;
} catch (e) {}
return 0;
}
function GetPromptService()
{
var promptService;
try {
promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
}
catch (e) {}
return promptService;
}
const gShowDebugOutputStateChange = false;
const gShowDebugOutputProgress = false;
const gShowDebugOutputStatusChange = false;
const gShowDebugOutputLocationChange = false;
const gShowDebugOutputSecurityChange = false;
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
const nsIChannel = Components.interfaces.nsIChannel;
const kErrorBindingAborted = 2152398850;
const kErrorBindingRedirected = 2152398851;
const kFileNotFound = 2152857618;
var gEditorOutputProgressListener =
{
onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
{
var editor = GetCurrentEditor();
// Use this to access onStateChange flags
var requestSpec;
try {
var channel = aRequest.QueryInterface(nsIChannel);
requestSpec = StripUsernamePasswordFromURI(channel.URI);
} catch (e) {
if ( gShowDebugOutputStateChange)
dump("***** onStateChange; NO REQUEST CHANNEL\n");
}
var pubSpec;
if (gPublishData)
pubSpec = gPublishData.publishUrl + gPublishData.docDir + gPublishData.filename;
if (gShowDebugOutputStateChange)
{
dump("\n***** onStateChange request: " + requestSpec + "\n");
dump(" state flags: ");
if (aStateFlags & nsIWebProgressListener.STATE_START)
dump(" STATE_START, ");
if (aStateFlags & nsIWebProgressListener.STATE_STOP)
dump(" STATE_STOP, ");
if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK)
dump(" STATE_IS_NETWORK ");
dump("\n * requestSpec="+requestSpec+", pubSpec="+pubSpec+", aStatus="+aStatus+"\n");
DumpDebugStatus(aStatus);
}
// The rest only concerns publishing, so bail out if no dialog
if (!gProgressDialog)
return;
// Detect start of file upload of any file:
// (We ignore any START messages after gPersistObj says publishing is finished
if ((aStateFlags & nsIWebProgressListener.STATE_START)
&& gPersistObj && requestSpec
&& (gPersistObj.currentState != gPersistObj.PERSIST_STATE_FINISHED))
{
try {
// Add url to progress dialog's list showing each file uploading
gProgressDialog.SetProgressStatus(GetFilename(requestSpec), "busy");
} catch(e) {}
}
// Detect end of file upload of any file:
if (aStateFlags & nsIWebProgressListener.STATE_STOP)
{
// ignore aStatus == kErrorBindingAborted; check http response for possible errors
try {
// check http channel for response: 200 range is ok; other ranges are not
var httpChannel = aRequest.QueryInterface(Components.interfaces.nsIHttpChannel);
var httpResponse = httpChannel.responseStatus;
if (httpResponse < 200 || httpResponse >= 300)
aStatus = httpResponse; // not a real error but enough to pass check below
else if (aStatus == kErrorBindingAborted)
aStatus = 0;
if (gShowDebugOutputStateChange)
dump("http response is: "+httpResponse+"\n");
}
catch(e)
{
if (aStatus == kErrorBindingAborted)
aStatus = 0;
}
// We abort publishing for all errors except if image src file is not found
var abortPublishing = (aStatus != 0 && aStatus != kFileNotFound);
// Notify progress dialog when we receive the STOP
// notification for a file if there was an error
// or a successful finish
// (Check requestSpec to be sure message is for destination url)
if (aStatus != 0
|| (requestSpec && requestSpec.indexOf(GetScheme(gPublishData.publishUrl)) == 0))
{
try {
gProgressDialog.SetProgressFinished(GetFilename(requestSpec), aStatus);
} catch(e) {}
}
if (abortPublishing)
{
// Cancel publishing
gPersistObj.cancelSave();
// Don't do any commands after failure
gCommandAfterPublishing = null;
// Restore original document to undo image src url adjustments
if (gRestoreDocumentSource)
{
try {
editor.rebuildDocumentFromSource(gRestoreDocumentSource);
// Clear transaction cache since we just did a potentially
// very large insert and this will eat up memory
editor.transactionManager.clear();
}
catch (e) {}
}
// Notify progress dialog that we're finished
// and keep open to show error
gProgressDialog.SetProgressFinished(null, 0);
// We don't want to change location or reset mod count, etc.
return;
}
//XXX HACK: "file://" protocol is not supported in network code
// (bug 151867 filed to add this support, bug 151869 filed
// to remove this and other code in nsIWebBrowserPersist)
// nsIWebBrowserPersist *does* copy the file(s), but we don't
// get normal onStateChange messages.
// Case 1: If images are included, we get fairly normal
// STATE_START/STATE_STOP & STATE_IS_NETWORK messages associated with the image files,
// thus we must finish HTML file progress below
// Case 2: If just HTML file is uploaded, we get STATE_START and STATE_STOP
// notification with a null "requestSpec", and
// the gPersistObj is destroyed before we get here!
// So create an new object so we can flow through normal processing below
if (!requestSpec && GetScheme(gPublishData.publishUrl) == "file"
&& (!gPersistObj || gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED))
{
aStateFlags |= nsIWebProgressListener.STATE_IS_NETWORK;
if (!gPersistObj)
{
gPersistObj =
{
result : aStatus,
currentState : nsIWebBrowserPersist.PERSIST_STATE_FINISHED
}
}
}
// STATE_IS_NETWORK signals end of publishing, as does the gPersistObj.currentState
if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK
&& gPersistObj.currentState == nsIWebBrowserPersist.PERSIST_STATE_FINISHED)
{
if (GetScheme(gPublishData.publishUrl) == "file")
{
//XXX "file://" hack: We don't get notified about the HTML file, so end progress for it
// (This covers both "Case 1 and 2" described above)
gProgressDialog.SetProgressFinished(gPublishData.filename, gPersistObj.result);
}
if (gPersistObj.result == 0)
{
// All files are finished and publishing succeeded (some images may have failed)
try {
// Make a new docURI from the "browse location" in case "publish location" was FTP
// We need to set document uri before notifying listeners
var docUrl = GetDocUrlFromPublishData(gPublishData);
SetDocumentURI(GetIOService().newURI(docUrl, editor.documentCharacterSet, null));
UpdateWindowTitle();
// this should cause notification to listeners that doc has changed
editor.resetModificationCount();
// Set UI based on whether we're editing a remote or local url
SetSaveAndPublishUI(urlstring);
} catch (e) {}
// Save publishData to prefs
if (gPublishData)
{
if (gPublishData.savePublishData)
{
// We published successfully, so we can safely
// save docDir and otherDir to prefs
gPublishData.saveDirs = true;
SavePublishDataToPrefs(gPublishData);
}
else
SavePassword(gPublishData);
}
// Ask progress dialog to close, but it may not
// if user checked checkbox to keep it open
gProgressDialog.RequestCloseDialog();
}
else
{
// We previously aborted publishing because of error:
// Calling gPersistObj.cancelSave() resulted in a non-zero gPersistObj.result,
// so notify progress dialog we're finished
gProgressDialog.SetProgressFinished(null, 0);
}
}
}
},
onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress,
aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
{
if (!gPersistObj)
return;
if (gShowDebugOutputProgress)
{
dump("\n onProgressChange: gPersistObj.result="+gPersistObj.result+"\n");
try {
var channel = aRequest.QueryInterface(nsIChannel);
dump("***** onProgressChange request: " + channel.URI.spec + "\n");
}
catch (e) {}
dump("***** self: "+aCurSelfProgress+" / "+aMaxSelfProgress+"\n");
dump("***** total: "+aCurTotalProgress+" / "+aMaxTotalProgress+"\n\n");
if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
dump(" Persister is ready to save data\n\n");
else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
dump(" Persister is saving data.\n\n");
else if (gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
}
},
onLocationChange : function(aWebProgress, aRequest, aLocation)
{
if (gShowDebugOutputLocationChange)
{
dump("***** onLocationChange: "+aLocation.spec+"\n");
try {
var channel = aRequest.QueryInterface(nsIChannel);
dump("***** request: " + channel.URI.spec + "\n");
}
catch(e) {}
}
},
onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
{
if (gShowDebugOutputStatusChange)
{
dump("***** onStatusChange: "+aMessage+"\n");
try {
var channel = aRequest.QueryInterface(nsIChannel);
dump("***** request: " + channel.URI.spec + "\n");
}
catch (e) { dump(" couldn't get request\n"); }
DumpDebugStatus(aStatus);
if (gPersistObj)
{
if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_READY)
dump(" Persister is ready to save data\n\n");
else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_SAVING)
dump(" Persister is saving data.\n\n");
else if(gPersistObj.currentState == gPersistObj.PERSIST_STATE_FINISHED)
dump(" PERSISTER HAS FINISHED SAVING DATA\n\n\n");
}
}
},
onSecurityChange : function(aWebProgress, aRequest, state)
{
if (gShowDebugOutputSecurityChange)
{
try {
var channel = aRequest.QueryInterface(nsIChannel);
dump("***** onSecurityChange request: " + channel.URI.spec + "\n");
} catch (e) {}
}
},
QueryInterface : function(aIID)
{
if (aIID.equals(Components.interfaces.nsIWebProgressListener)
|| aIID.equals(Components.interfaces.nsISupports)
|| aIID.equals(Components.interfaces.nsISupportsWeakReference)
|| aIID.equals(Components.interfaces.nsIPrompt)
|| aIID.equals(Components.interfaces.nsIAuthPrompt))
return this;
throw Components.results.NS_NOINTERFACE;
},
// nsIPrompt
alert : function(dlgTitle, text)
{
AlertWithTitle(dlgTitle, text, gProgressDialog ? gProgressDialog : window);
},
alertCheck : function(dialogTitle, text, checkBoxLabel, checkObj)
{
AlertWithTitle(dialogTitle, text);
},
confirm : function(dlgTitle, text)
{
return ConfirmWithTitle(dlgTitle, text, null, null);
},
confirmCheck : function(dlgTitle, text, checkBoxLabel, checkObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return;
promptServ.confirmEx(window, dlgTitle, text, nsIPromptService.STD_OK_CANCEL_BUTTONS,
"", "", "", checkBoxLabel, checkObj);
},
confirmEx : function(dlgTitle, text, btnFlags, btn0Title, btn1Title, btn2Title, checkBoxLabel, checkVal)
{
var promptServ = GetPromptService();
if (!promptServ)
return 0;
return promptServ.confirmEx(window, dlgTitle, text, btnFlags,
btn0Title, btn1Title, btn2Title,
checkBoxLabel, checkVal);
},
prompt : function(dlgTitle, text, inoutText, checkBoxLabel, checkObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
return promptServ.prompt(window, dlgTitle, text, inoutText, checkBoxLabel, checkObj);
},
promptPassword : function(dlgTitle, text, pwObj, checkBoxLabel, savePWObj)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
var ret = false;
try {
// Note difference with nsIAuthPrompt::promptPassword, which has
// just "in" savePassword param, while nsIPrompt is "inout"
// Initialize with user's previous preference for this site
if (gPublishData)
savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, checkBoxLabel, savePWObj);
if (!ret)
setTimeout(CancelPublishing, 0);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {}
return ret;
},
promptUsernameAndPassword : function(dlgTitle, text, userObj, pwObj, checkBoxLabel, savePWObj)
{
var ret = PromptUsernameAndPassword(dlgTitle, text, savePWObj.value, userObj, pwObj);
if (!ret)
setTimeout(CancelPublishing, 0);
return ret;
},
select : function(dlgTitle, text, count, selectList, outSelection)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
return promptServ.select(window, dlgTitle, text, count, selectList, outSelection);
},
// nsIAuthPrompt
prompt : function(dlgTitle, text, pwrealm, savePW, defaultText, result)
{
var promptServ = GetPromptService();
if (!promptServ)
return false;
var savePWObj = {value:savePW};
var ret = promptServ.prompt(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, defaultText, pwrealm, savePWObj);
if (!ret)
setTimeout(CancelPublishing, 0);
return ret;
},
promptUsernameAndPassword : function(dlgTitle, text, pwrealm, savePW, userObj, pwObj)
{
var ret = PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj);
if (!ret)
setTimeout(CancelPublishing, 0);
return ret;
},
promptPassword : function(dlgTitle, text, pwrealm, savePW, pwObj)
{
var ret = false;
try {
var promptServ = GetPromptService();
if (!promptServ)
return false;
// Note difference with nsIPrompt::promptPassword, which has
// "inout" savePassword param, while nsIAuthPrompt is just "in"
// Also nsIAuth doesn't supply "checkBoxLabel"
// Initialize with user's previous preference for this site
var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site
if (gPublishData)
savePWObj.value = gPublishData.savePassword;
ret = promptServ.promptPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, pwObj, GetString("SavePassword"), savePWObj);
if (!ret)
setTimeout(CancelPublishing, 0);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, gPublishData.username, pwObj.value, savePWObj.value);
} catch(e) {}
return ret;
}
}
function PromptUsernameAndPassword(dlgTitle, text, savePW, userObj, pwObj)
{
// HTTP prompts us twice even if user Cancels from 1st attempt!
// So never put up dialog if there's no publish data
if (!gPublishData)
return false
var ret = false;
try {
var promptServ = GetPromptService();
if (!promptServ)
return false;
var savePWObj = {value:savePW};
// Initialize with user's previous preference for this site
if (gPublishData)
{
// HTTP put uses this dialog if either username or password is bad,
// so prefill username input field with the previous value for modification
savePWObj.value = gPublishData.savePassword;
if (!userObj.value)
userObj.value = gPublishData.username;
}
ret = promptServ.promptUsernameAndPassword(gProgressDialog ? gProgressDialog : window,
dlgTitle, text, userObj, pwObj,
GetString("SavePassword"), savePWObj);
if (ret && gPublishData)
UpdateUsernamePasswordFromPrompt(gPublishData, userObj.value, pwObj.value, savePWObj.value);
} catch (e) {}
return ret;
}
function DumpDebugStatus(aStatus)
{
// see nsError.h and netCore.h and ftpCore.h
if (aStatus == kErrorBindingAborted)
dump("***** status is NS_BINDING_ABORTED\n");
else if (aStatus == kErrorBindingRedirected)
dump("***** status is NS_BINDING_REDIRECTED\n");
else if (aStatus == 2152398859) // in netCore.h 11
dump("***** status is ALREADY_CONNECTED\n");
else if (aStatus == 2152398860) // in netCore.h 12
dump("***** status is NOT_CONNECTED\n");
else if (aStatus == 2152398861) // in nsISocketTransportService.idl 13
dump("***** status is CONNECTION_REFUSED\n");
else if (aStatus == 2152398862) // in nsISocketTransportService.idl 14
dump("***** status is NET_TIMEOUT\n");
else if (aStatus == 2152398863) // in netCore.h 15
dump("***** status is IN_PROGRESS\n");
else if (aStatus == 2152398864) // 0x804b0010 in netCore.h 16
dump("***** status is OFFLINE\n");
else if (aStatus == 2152398865) // in netCore.h 17
dump("***** status is NO_CONTENT\n");
else if (aStatus == 2152398866) // in netCore.h 18
dump("***** status is UNKNOWN_PROTOCOL\n");
else if (aStatus == 2152398867) // in netCore.h 19
dump("***** status is PORT_ACCESS_NOT_ALLOWED\n");
else if (aStatus == 2152398868) // in nsISocketTransportService.idl 20
dump("***** status is NET_RESET\n");
else if (aStatus == 2152398869) // in ftpCore.h 21
dump("***** status is FTP_LOGIN\n");
else if (aStatus == 2152398870) // in ftpCore.h 22
dump("***** status is FTP_CWD\n");
else if (aStatus == 2152398871) // in ftpCore.h 23
dump("***** status is FTP_PASV\n");
else if (aStatus == 2152398872) // in ftpCore.h 24
dump("***** status is FTP_PWD\n");
else if (aStatus == 2152857601)
dump("***** status is UNRECOGNIZED_PATH\n");
else if (aStatus == 2152857602)
dump("***** status is UNRESOLABLE SYMLINK\n");
else if (aStatus == 2152857604)
dump("***** status is UNKNOWN_TYPE\n");
else if (aStatus == 2152857605)
dump("***** status is DESTINATION_NOT_DIR\n");
else if (aStatus == 2152857606)
dump("***** status is TARGET_DOES_NOT_EXIST\n");
else if (aStatus == 2152857608)
dump("***** status is ALREADY_EXISTS\n");
else if (aStatus == 2152857609)
dump("***** status is INVALID_PATH\n");
else if (aStatus == 2152857610)
dump("***** status is DISK_FULL\n");
else if (aStatus == 2152857612)
dump("***** status is NOT_DIRECTORY\n");
else if (aStatus == 2152857613)
dump("***** status is IS_DIRECTORY\n");
else if (aStatus == 2152857614)
dump("***** status is IS_LOCKED\n");
else if (aStatus == 2152857615)
dump("***** status is TOO_BIG\n");
else if (aStatus == 2152857616)
dump("***** status is NO_DEVICE_SPACE\n");
else if (aStatus == 2152857617)
dump("***** status is NAME_TOO_LONG\n");
else if (aStatus == 2152857618) // 80520012
dump("***** status is FILE_NOT_FOUND\n");
else if (aStatus == 2152857619)
dump("***** status is READ_ONLY\n");
else if (aStatus == 2152857620)
dump("***** status is DIR_NOT_EMPTY\n");
else if (aStatus == 2152857621)
dump("***** status is ACCESS_DENIED\n");
else if (aStatus == 2152398878)
dump("***** status is ? (No connection or time out?)\n");
else
dump("***** status is " + aStatus + "\n");
}
// Update any data that the user supplied in a prompt dialog
function UpdateUsernamePasswordFromPrompt(publishData, username, password, savePassword)
{
if (!publishData)
return;
// Set flag to save publish data after publishing if it changed in dialog
// and the "SavePassword" checkbox was checked
// or we already had site data for this site
// (Thus we don't automatically create a site until user brings up Publish As dialog)
publishData.savePublishData = (gPublishData.username != username || gPublishData.password != password)
&& (savePassword || !publishData.notInSiteData);
publishData.username = username;
publishData.password = password;
publishData.savePassword = savePassword;
}
const kSupportedTextMimeTypes =
[
"text/plain",
"text/css",
"text/rdf",
"text/xsl",
"text/javascript",
"application/x-javascript",
"text/xul",
"application/vnd.mozilla.xul+xml"
];
function IsSupportedTextMimeType(aMimeType)
{
for (var i = 0; i < kSupportedTextMimeTypes.length; i++)
{
if (kSupportedTextMimeTypes[i] == aMimeType)
return true;
}
return false;
}
// throws an error or returns true if user attempted save; false if user canceled save
function SaveDocument(aSaveAs, aSaveCopy, aMimeType)
{
var editor = GetCurrentEditor();
if (!aMimeType || aMimeType == "" || !editor)
throw NS_ERROR_NOT_INITIALIZED;
var editorDoc = editor.document;
if (!editorDoc)
throw NS_ERROR_NOT_INITIALIZED;
// if we don't have the right editor type bail (we handle text and html)
var editorType = GetCurrentEditorType();
if (editorType != "text" && editorType != "html"
&& editorType != "htmlmail" && editorType != "textmail")
throw NS_ERROR_NOT_IMPLEMENTED;
var saveAsTextFile = IsSupportedTextMimeType(aMimeType);
// check if the file is to be saved is a format we don't understand; if so, bail
if (aMimeType != "text/html" && !saveAsTextFile)
throw NS_ERROR_NOT_IMPLEMENTED;
if (saveAsTextFile)
aMimeType = "text/plain";
var urlstring = GetDocumentUrl();
var mustShowFileDialog = (aSaveAs || IsUrlAboutBlank(urlstring) || (urlstring == ""));
// If editing a remote URL, force SaveAs dialog
if (!mustShowFileDialog && GetScheme(urlstring) != "file")
mustShowFileDialog = true;
var replacing = !aSaveAs;
var titleChanged = false;
var doUpdateURI = false;
var tempLocalFile = null;
if (mustShowFileDialog)
{
try {
// Prompt for title if we are saving to HTML
if (!saveAsTextFile && (editorType == "html"))
{
var userContinuing = PromptAndSetTitleIfNone(); // not cancel
if (!userContinuing)
return false;
}
var dialogResult = PromptForSaveLocation(saveAsTextFile, editorType, aMimeType, urlstring);
if (dialogResult.filepickerClick == nsIFilePicker.returnCancel)
return false;
replacing = (dialogResult.filepickerClick == nsIFilePicker.returnReplace);
urlstring = dialogResult.resultingURIString;
tempLocalFile = dialogResult.resultingLocalFile;
// update the new URL for the webshell unless we are saving a copy
if (!aSaveCopy)
doUpdateURI = true;
} catch (e) { return false; }
} // mustShowFileDialog
var success = true;
var ioService;
try {
// if somehow we didn't get a local file but we did get a uri,
// attempt to create the localfile if it's a "file" url
var docURI;
if (!tempLocalFile)
{
ioService = GetIOService();
docURI = ioService.newURI(urlstring, editor.documentCharacterSet, null);
if (docURI.schemeIs("file"))
{
var fileHandler = GetFileProtocolHandler();
tempLocalFile = fileHandler.getFileFromURLSpec(urlstring).QueryInterface(Components.interfaces.nsILocalFile);
}
}
// this is the location where the related files will go
var relatedFilesDir = null;
// First check pref for saving associated files
var saveAssociatedFiles = false;
try {
var prefs = GetPrefs();
saveAssociatedFiles = prefs.getBoolPref("editor.save_associated_files");
} catch (e) {}
// Only change links or move files if pref is set
// and we are saving to a new location
if (saveAssociatedFiles && aSaveAs)
{
try {
if (tempLocalFile)
{
// if we are saving to the same parent directory, don't set relatedFilesDir
// grab old location, chop off file
// grab new location, chop off file, compare
var oldLocation = GetDocumentUrl();
var oldLocationLastSlash = oldLocation.lastIndexOf("\/");
if (oldLocationLastSlash != -1)
oldLocation = oldLocation.slice(0, oldLocationLastSlash);
var relatedFilesDirStr = urlstring;
var newLocationLastSlash = relatedFilesDirStr.lastIndexOf("\/");
if (newLocationLastSlash != -1)
relatedFilesDirStr = relatedFilesDirStr.slice(0, newLocationLastSlash);
if (oldLocation == relatedFilesDirStr || IsUrlAboutBlank(oldLocation))
relatedFilesDir = null;
else
relatedFilesDir = tempLocalFile.parent;
}
else
{
var lastSlash = urlstring.lastIndexOf("\/");
if (lastSlash != -1)
{
var relatedFilesDirString = urlstring.slice(0, lastSlash + 1); // include last slash
ioService = GetIOService();
relatedFilesDir = ioService.newURI(relatedFilesDirString, editor.documentCharacterSet, null);
}
}
} catch(e) { relatedFilesDir = null; }
}
var destinationLocation;
if (tempLocalFile)
destinationLocation = tempLocalFile;
else
destinationLocation = docURI;
success = OutputFileWithPersistAPI(editorDoc, destinationLocation, relatedFilesDir, aMimeType);
}
catch (e)
{
success = false;
}
if (success)
{
try {
if (doUpdateURI)
{
// If a local file, we must create a new uri from nsILocalFile
if (tempLocalFile)
docURI = GetFileProtocolHandler().newFileURI(tempLocalFile);
// We need to set new document uri before notifying listeners
SetDocumentURI(docURI);
}
// Update window title to show possibly different filename
// This also covers problem that after undoing a title change,
// window title loses the extra [filename] part that this adds
UpdateWindowTitle();
if (!aSaveCopy)
editor.resetModificationCount();
// this should cause notification to listeners that document has changed
// Set UI based on whether we're editing a remote or local url
SetSaveAndPublishUI(urlstring);
} catch (e) {}
}
else
{
var saveDocStr = GetString("SaveDocument");
var failedStr = GetString("SaveFileFailed");
AlertWithTitle(saveDocStr, failedStr);
}
return success;
}
function SetDocumentURI(uri)
{
try {
// XXX WE'LL NEED TO GET "CURRENT" CONTENT FRAME ONCE MULTIPLE EDITORS ARE ALLOWED
GetCurrentEditorElement().docShell.setCurrentURI(uri);
} catch (e) { dump("SetDocumentURI:\n"+e +"\n"); }
}
//------------------------------- Publishing
var gPublishData;
var gProgressDialog;
var gCommandAfterPublishing = null;
var gRestoreDocumentSource;
function Publish(publishData)
{
if (!publishData)
return false;
// Set data in global for username password requests
// and to do "post saving" actions after monitoring nsIWebProgressListener messages
// and we are sure file transfer was successful
gPublishData = publishData;
gPublishData.docURI = CreateURIFromPublishData(publishData, true);
if (!gPublishData.docURI)
{
AlertWithTitle(GetString("Publish"), GetString("PublishFailed"));
return false;
}
if (gPublishData.publishOtherFiles)
gPublishData.otherFilesURI = CreateURIFromPublishData(publishData, false);
else
gPublishData.otherFilesURI = null;
if (gShowDebugOutputStateChange)
{
dump("\n *** publishData: PublishUrl="+publishData.publishUrl+", BrowseUrl="+publishData.browseUrl+
", Username="+publishData.username+", Dir="+publishData.docDir+
", Filename="+publishData.filename+"\n");
dump(" * gPublishData.docURI.spec w/o pass="+StripPassword(gPublishData.docURI.spec)+", PublishOtherFiles="+gPublishData.publishOtherFiles+"\n");
}
// XXX Missing username will make FTP fail
// and it won't call us for prompt dialog (bug 132320)
// (It does prompt if just password is missing)
// So we should do the prompt ourselves before trying to publish
if (GetScheme(publishData.publishUrl) == "ftp" && !publishData.username)
{
var message = GetString("PromptFTPUsernamePassword").replace(/%host%/, GetHost(publishData.publishUrl));
var savePWobj = {value:publishData.savePassword};
var userObj = {value:publishData.username};
var pwObj = {value:publishData.password};
if (!PromptUsernameAndPassword(GetString("Prompt"), message, savePWobj, userObj, pwObj))
return false; // User canceled out of dialog
// Reset data in URI objects
gPublishData.docURI.username = publishData.username;
gPublishData.docURI.password = publishData.password;
if (gPublishData.otherFilesURI)
{
gPublishData.otherFilesURI.username = publishData.username;
gPublishData.otherFilesURI.password = publishData.password;
}
}
try {
// We launch dialog as a dependent
// Don't allow editing document!
SetDocumentEditable(false);
// Start progress monitoring
gProgressDialog =
window.openDialog("chrome://editor/content/EditorPublishProgress.xul", "_blank",
"chrome,dependent,titlebar", gPublishData, gPersistObj);
} catch (e) {}
// Network transfer is often too quick for the progress dialog to be initialized
// and we can completely miss messages for quickly-terminated bad URLs,
// so we can't call OutputFileWithPersistAPI right away.
// StartPublishing() is called at the end of the dialog's onload method
return true;
}
function StartPublishing()
{
var editor = GetCurrentEditor();
if (editor && gPublishData && gPublishData.docURI && gProgressDialog)
{
gRestoreDocumentSource = null;
// Save backup document since nsIWebBrowserPersist changes image src urls
// but we only need to do this if publishing images and other related files
if (gPublishData.otherFilesURI)
{
try {
// (256 = Output encoded entities)
gRestoreDocumentSource =
editor.outputToString(editor.contentsMIMEType, 256);
} catch (e) {}
}
OutputFileWithPersistAPI(editor.document,
gPublishData.docURI, gPublishData.otherFilesURI,
editor.contentsMIMEType);
return gPersistObj;
}
return null;
}
function CancelPublishing()
{
try {
gPersistObj.cancelSave();
gProgressDialog.SetProgressStatusCancel();
} catch (e) {}
// If canceling publishing do not do any commands after this
gCommandAfterPublishing = null;
if (gProgressDialog)
{
// Close Progress dialog
// (this will call FinishPublishing())
gProgressDialog.CloseDialog();
}
else
FinishPublishing();
}
function FinishPublishing()
{
SetDocumentEditable(true);
gProgressDialog = null;
gPublishData = null;
gRestoreDocumentSource = null;
if (gCommandAfterPublishing)
{
// Be sure to null out the global now incase of trouble when executing command
var command = gCommandAfterPublishing;
gCommandAfterPublishing = null;
goDoCommand(command);
}
}
// Create a nsIURI object filled in with all required publishing info
function CreateURIFromPublishData(publishData, doDocUri)
{
if (!publishData || !publishData.publishUrl)
return null;
var URI;
try {
var spec = publishData.publishUrl;
if (doDocUri)
spec += FormatDirForPublishing(publishData.docDir) + publishData.filename;
else
spec += FormatDirForPublishing(publishData.otherDir);
var ioService = GetIOService();
URI = ioService.newURI(spec, GetCurrentEditor().documentCharacterSet, null);
if (publishData.username)
URI.username = publishData.username;
if (publishData.password)
URI.password = publishData.password;
}
catch (e) {}
return URI;
}
// Resolve the correct "http:" document URL when publishing via ftp
function GetDocUrlFromPublishData(publishData)
{
if (!publishData || !publishData.filename || !publishData.publishUrl)
return "";
// If user was previously editing an "ftp" url, then keep that as the new scheme
var url;
var docScheme = GetScheme(GetDocumentUrl());
// Always use the "HTTP" address if available
// XXX Should we do some more validation here for bad urls???
// Let's at least check for a scheme!
if (!GetScheme(publishData.browseUrl))
url = publishData.publishUrl;
else
url = publishData.browseUrl;
url += FormatDirForPublishing(publishData.docDir) + publishData.filename;
if (GetScheme(url) == "ftp")
url = InsertUsernameIntoUrl(url, publishData.username);
return url;
}
function SetSaveAndPublishUI(urlstring)
{
// Be sure enabled state of toolbar buttons are correct
goUpdateCommand("cmd_save");
goUpdateCommand("cmd_publish");
}
function SetDocumentEditable(isDocEditable)
{
var editor = GetCurrentEditor();
if (editor && editor.document)
{
try {
var flags = editor.flags;
editor.flags = isDocEditable ?
flags &= ~nsIPlaintextEditor.eEditorReadonlyMask :
flags | nsIPlaintextEditor.eEditorReadonlyMask;
} catch(e) {}
// update all commands
window.updateCommands("create");
}
}
// ****** end of save / publish **********//
//-----------------------------------------------------------------------------------
var nsPublishSettingsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (GetCurrentEditor())
{
// Launch Publish Settings dialog
window.ok = window.openDialog("chrome://editor/content/EditorPublishSettings.xul","_blank", "chrome,close,titlebar,modal", "");
window.content.focus();
return window.ok;
}
return false;
}
}
//-----------------------------------------------------------------------------------
var nsRevertCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() &&
IsDocumentModified() &&
!IsUrlAboutBlank(GetDocumentUrl()));
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Confirm with the user to abandon current changes
var promptService = GetPromptService();
if (promptService)
{
// Put the page title in the message string
var title = GetDocumentTitle();
if (!title)
title = GetString("untitled");
var msg = GetString("AbandonChanges").replace(/%title%/,title);
var result = promptService.confirmEx(window, GetString("RevertCaption"), msg,
(promptService.BUTTON_TITLE_REVERT * promptService.BUTTON_POS_0) +
(promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
null, null, null, null, {value:0});
// Reload page if first button (Revert) was pressed
if(result == 0)
{
CancelHTMLSource();
EditorLoadUrl(GetDocumentUrl());
}
}
}
};
//-----------------------------------------------------------------------------------
var nsCloseCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return GetCurrentEditor() != null;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
CloseWindow();
}
};
function CloseWindow()
{
// Check to make sure document is saved. "true" means allow "Don't Save" button,
// so user can choose to close without saving
if (CheckAndSaveDocument("cmd_close", true))
{
if (window.InsertCharWindow)
SwitchInsertCharToAnotherEditorOrClose();
try {
var basewin = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIBaseWindow);
basewin.destroy();
} catch (e) {}
}
}
//-----------------------------------------------------------------------------------
var nsOpenRemoteCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; // we can always do this
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
/* The last parameter is the current browser window.
Use 0 and the default checkbox will be to load into an editor
and loading into existing browser option is removed
*/
window.openDialog( "chrome://communicator/content/openLocation.xul", "_blank", "chrome,modal,titlebar", 0);
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsPreviewCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() &&
IsHTMLEditor() &&
(DocumentHasBeenSaved() || IsDocumentModified()));
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument("cmd_preview", DocumentHasBeenSaved()))
return;
// Check if we saved again just in case?
if (DocumentHasBeenSaved())
{
var browser;
try {
// Find a browser with this URL
var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator("navigator:browser");
var documentURI = GetDocumentUrl();
while ( enumerator.hasMoreElements() )
{
browser = enumerator.getNext().QueryInterface(Components.interfaces.nsIDOMWindowInternal);
if ( browser && (documentURI == browser.getBrowser().currentURI.spec))
break;
browser = null;
}
}
catch (ex) {}
// If none found, open a new browser
if (!browser)
{
browser = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", documentURI);
}
else
{
try {
browser.BrowserReloadSkipCache();
browser.focus();
} catch (ex) {}
}
}
}
};
//-----------------------------------------------------------------------------------
var nsSendPageCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() &&
(DocumentHasBeenSaved() || IsDocumentModified()));
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Don't continue if user canceled during prompt for saving
// DocumentHasBeenSaved will test if we have a URL and suppress "Don't Save" button if not
if (!CheckAndSaveDocument("cmd_editSendPage", DocumentHasBeenSaved()))
return;
// Check if we saved again just in case?
if (DocumentHasBeenSaved())
{
// Launch Messenger Composer window with current page as contents
try
{
openComposeWindow(GetDocumentUrl(), GetDocumentTitle());
} catch (ex) { dump("Cannot Send Page: " + ex + "\n"); }
}
}
};
//-----------------------------------------------------------------------------------
var nsPrintCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; // we can always do this
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// In editor.js
FinishHTMLSource();
try {
NSPrint();
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsPrintSetupCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; // we can always do this
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// In editor.js
FinishHTMLSource();
NSPrintSetup();
}
};
//-----------------------------------------------------------------------------------
var nsQuitCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true; // we can always do this
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {}
/* The doCommand is not used, since cmd_quit's oncommand="goQuitApplication()" in platformCommunicatorOverlay.xul
doCommand: function(aCommand)
{
// In editor.js
FinishHTMLSource();
goQuitApplication();
}
*/
};
//-----------------------------------------------------------------------------------
var nsFindCommand =
{
isCommandEnabled: function(aCommand, editorElement)
{
return editorElement.getEditor(editorElement.contentWindow) != null;
},
getCommandStateParams: function(aCommand, aParams, editorElement) {},
doCommandParams: function(aCommand, aParams, editorElement) {},
doCommand: function(aCommand, editorElement)
{
try {
window.openDialog("chrome://editor/content/EdReplace.xul", "_blank",
"chrome,modal,titlebar", editorElement);
}
catch(ex) {
dump("*** Exception: couldn't open Replace Dialog\n");
}
//window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsFindAgainCommand =
{
isCommandEnabled: function(aCommand, editorElement)
{
// we can only do this if the search pattern is non-empty. Not sure how
// to get that from here
return editorElement.getEditor(editorElement.contentWindow) != null;
},
getCommandStateParams: function(aCommand, aParams, editorElement) {},
doCommandParams: function(aCommand, aParams, editorElement) {},
doCommand: function(aCommand, editorElement)
{
try {
var findPrev = aCommand == "cmd_findPrev";
var findInst = editorElement.webBrowserFind;
var findService = Components.classes["@mozilla.org/find/find_service;1"]
.getService(Components.interfaces.nsIFindService);
findInst.findBackwards = findService.findBackwards ^ findPrev;
findInst.findNext();
// reset to what it was in dialog, otherwise dialog setting can get reversed
findInst.findBackwards = findService.findBackwards;
}
catch (ex) {}
}
};
//-----------------------------------------------------------------------------------
var nsRewrapCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && !IsInHTMLSourceMode() &&
GetCurrentEditor() instanceof Components.interfaces.nsIEditorMailSupport);
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorMailSupport).rewrap(false);
}
};
//-----------------------------------------------------------------------------------
var nsSpellingCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() &&
!IsInHTMLSourceMode() && IsSpellCheckerInstalled());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.cancelSendMessage = false;
try {
var skipBlockQuotes = (window.document.firstChild.getAttribute("windowtype") == "msgcompose");
window.openDialog("chrome://editor/content/EdSpellCheck.xul", "_blank",
"chrome,close,titlebar,modal", false, skipBlockQuotes, true);
}
catch(ex) {}
window.content.focus();
}
};
// Validate using http://validator.w3.org/file-upload.html
var URL2Validate;
var nsValidateCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return GetCurrentEditor() != null;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// If the document hasn't been modified,
// then just validate the current url.
if (IsDocumentModified() || IsHTMLSourceChanged())
{
if (!CheckAndSaveDocument("cmd_validate", false))
return;
// Check if we saved again just in case?
if (!DocumentHasBeenSaved()) // user hit cancel?
return;
}
URL2Validate = GetDocumentUrl();
// See if it's a file:
var ifile;
try {
var fileHandler = GetFileProtocolHandler();
ifile = fileHandler.getFileFromURLSpec(URL2Validate);
// nsIFile throws an exception if it's not a file url
} catch (e) { ifile = null; }
if (ifile)
{
URL2Validate = ifile.path;
var vwin = window.open("http://validator.w3.org/file-upload.html",
"EditorValidate");
// Window loads asynchronously, so pass control to the load listener:
vwin.addEventListener("load", this.validateFilePageLoaded, false);
}
else
{
var vwin2 = window.open("http://validator.w3.org/check?uri="
+ URL2Validate
+ "&doctype=Inline",
"EditorValidate");
// This does the validation, no need to wait for page loaded.
}
},
validateFilePageLoaded: function(event)
{
event.target.forms[0].uploaded_file.value = URL2Validate;
}
};
var nsCheckLinksCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdLinkChecker.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsFormCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdFormProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsInputTagCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdInputProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsInputImageCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdInputImage.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsTextAreaCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdTextAreaProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsSelectCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdSelectProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsButtonCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdButtonProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsLabelCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var tagName = "label";
try {
var editor = GetCurrentEditor();
// Find selected label or if start/end of selection is in label
var labelElement = editor.getSelectedElement(tagName);
if (!labelElement)
labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.anchorNode);
if (!labelElement)
labelElement = editor.getElementOrParentByTagName(tagName, editor.selection.focusNode);
if (labelElement) {
// We only open the dialog for an existing label
window.openDialog("chrome://editor/content/EdLabelProps.xul", "_blank", "chrome,close,titlebar,modal", labelElement);
window.content.focus();
} else {
EditorSetTextProperty(tagName, "", "");
}
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsFieldSetCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdFieldSetProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsIsIndexCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
var editor = GetCurrentEditor();
var isindexElement = editor.createElementWithDefaults("isindex");
isindexElement.setAttribute("prompt", editor.outputToString("text/plain", 1)); // OutputSelectionOnly
editor.insertElementAtSelection(isindexElement, true);
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsImageCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsHLineCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Inserting an HLine is different in that we don't use properties dialog
// unless we are editing an existing line's attributes
// We get the last-used attributes from the prefs and insert immediately
var tagName = "hr";
var editor = GetCurrentEditor();
var hLine;
try {
hLine = editor.getSelectedElement(tagName);
} catch (e) {return;}
if (hLine)
{
// We only open the dialog for an existing HRule
window.openDialog("chrome://editor/content/EdHLineProps.xul", "_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
else
{
try {
hLine = editor.createElementWithDefaults(tagName);
// We change the default attributes to those saved in the user prefs
var prefs = GetPrefs();
var align = prefs.getIntPref("editor.hrule.align");
if (align == 0)
editor.setAttributeOrEquivalent(hLine, "align", "left", true);
else if (align == 2)
editor.setAttributeOrEquivalent(hLine, "align", "right", true);
//Note: Default is center (don't write attribute)
var width = prefs.getIntPref("editor.hrule.width");
var percent = prefs.getBoolPref("editor.hrule.width_percent");
if (percent)
width = width +"%";
editor.setAttributeOrEquivalent(hLine, "width", width, true);
var height = prefs.getIntPref("editor.hrule.height");
editor.setAttributeOrEquivalent(hLine, "size", String(height), true);
var shading = prefs.getBoolPref("editor.hrule.shading");
if (shading)
hLine.removeAttribute("noshade");
else
hLine.setAttribute("noshade", "noshade");
editor.insertElementAtSelection(hLine, true);
} catch (e) {}
}
}
};
//-----------------------------------------------------------------------------------
var nsLinkCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// If selected element is an image, launch that dialog instead
// since last tab panel handles link around an image
var element = GetObjectForProperties();
if (element && element.nodeName.toLowerCase() == "img")
window.openDialog("chrome://editor/content/EdImageProps.xul","_blank", "chrome,close,titlebar,modal", null, true);
else
window.openDialog("chrome://editor/content/EdLinkProps.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsAnchorCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdNamedAnchorProps.xul", "_blank", "chrome,close,titlebar,modal", "");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsInsertHTMLWithDialogCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdInsSrc.xul","_blank", "chrome,close,titlebar,modal,resizable", "");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsInsertCharsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
EditorFindOrCreateInsertCharWindow();
}
};
//-----------------------------------------------------------------------------------
var nsInsertBreakCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentEditor().insertHTML("
");
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsInsertBreakAllCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentEditor().insertHTML("
");
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsGridCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdSnapToGrid.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsListPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdListProps.xul","_blank", "chrome,close,titlebar,modal");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsPagePropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var oldTitle = GetDocumentTitle();
window.openDialog("chrome://editor/content/EdPageProps.xul","_blank", "chrome,close,titlebar,modal", "");
// Update main window title and
// recent menu data in prefs if doc title changed
if (GetDocumentTitle() != oldTitle)
UpdateWindowTitle();
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsObjectPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
var isEnabled = false;
if (IsDocumentEditable() && IsEditingRenderedHTML())
{
isEnabled = (GetObjectForProperties() != null ||
GetCurrentEditor().getSelectedElement("href") != null);
}
return isEnabled;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Launch Object properties for appropriate selected element
var element = GetObjectForProperties();
if (element)
{
var name = element.nodeName.toLowerCase();
switch (name)
{
case 'img':
goDoCommand("cmd_image");
break;
case 'hr':
goDoCommand("cmd_hline");
break;
case 'form':
goDoCommand("cmd_form");
break;
case 'input':
var type = element.getAttribute("type");
if (type && type.toLowerCase() == "image")
goDoCommand("cmd_inputimage");
else
goDoCommand("cmd_inputtag");
break;
case 'textarea':
goDoCommand("cmd_textarea");
break;
case 'select':
goDoCommand("cmd_select");
break;
case 'button':
goDoCommand("cmd_button");
break;
case 'label':
goDoCommand("cmd_label");
break;
case 'fieldset':
goDoCommand("cmd_fieldset");
break;
case 'table':
EditorInsertOrEditTable(false);
break;
case 'td':
case 'th':
EditorTableCellProperties();
break;
case 'ol':
case 'ul':
case 'dl':
case 'li':
goDoCommand("cmd_listProperties");
break;
case 'a':
if (element.name)
{
goDoCommand("cmd_anchor");
}
else if(element.href)
{
goDoCommand("cmd_link");
}
break;
default:
doAdvancedProperties(element);
break;
}
} else {
// We get a partially-selected link if asked for specifically
try {
element = GetCurrentEditor().getSelectedElement("href");
} catch (e) {}
if (element)
goDoCommand("cmd_link");
}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsSetSmiley =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon)
{
var smileyCode = aParams.getCStringValue("state_attribute");
var strSml;
switch(smileyCode)
{
case ":-)": strSml="s1";
break;
case ":-(": strSml="s2";
break;
case ";-)": strSml="s3";
break;
case ":-P":
case ":-p":
case ":-b": strSml="s4";
break;
case ":-D": strSml="s5";
break;
case ":-[": strSml="s6";
break;
case ":-\\":
case ":\\": strSml="s7";
break;
case "=-O":
case "=-o": strSml="s8";
break;
case ":-*": strSml="s9";
break;
case ">:o":
case ">:-o": strSml="s10";
break;
case "8-)": strSml="s11";
break;
case ":-$": strSml="s12";
break;
case ":-!": strSml="s13";
break;
case "O:-)":
case "o:-)": strSml="s14";
break;
case ":'(": strSml="s15";
break;
case ":-X":
case ":-x": strSml="s16";
break;
default: strSml="";
break;
}
try
{
var editor = GetCurrentEditor();
var selection = editor.selection;
var extElement = editor.createElementWithDefaults("span");
extElement.setAttribute("class", "moz-smiley-" + strSml);
var intElement = editor.createElementWithDefaults("span");
if (!intElement)
return;
//just for mailnews, because of the way it removes HTML
var smileButMenu = document.getElementById('smileButtonMenu');
if (smileButMenu.getAttribute("padwithspace"))
smileyCode = " " + smileyCode + " ";
var txtElement = editor.document.createTextNode(smileyCode);
if (!txtElement)
return;
intElement.appendChild (txtElement);
extElement.appendChild (intElement);
editor.insertElementAtSelection(extElement,true);
window.content.focus();
}
catch (e)
{
dump("Exception occured in smiley InsertElementAtSelection\n");
}
},
// This is now deprecated in favor of "doCommandParams"
doCommand: function(aCommand) {}
};
function doAdvancedProperties(element)
{
if (element)
{
window.openDialog("chrome://editor/content/EdAdvancedEdit.xul", "_blank", "chrome,close,titlebar,modal,resizable=yes", "", element);
window.content.focus();
}
}
var nsAdvancedPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Launch AdvancedEdit dialog for the selected element
try {
var element = GetCurrentEditor().getSelectedElement("");
doAdvancedProperties(element);
} catch (e) {}
}
};
//-----------------------------------------------------------------------------------
var nsColorPropertiesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
window.openDialog("chrome://editor/content/EdColorProps.xul","_blank", "chrome,close,titlebar,modal", "");
UpdateDefaultColors();
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsRemoveNamedAnchorsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
// We could see if there's any link in selection, but it doesn't seem worth the work!
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
EditorRemoveTextProperty("name", "");
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsEditLinkCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
// Not really used -- this command is only in context menu, and we do enabling there
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
var element = GetCurrentEditor().getSelectedElement("href");
if (element)
editPage(element.href, window, false);
} catch (e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsNormalModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsHTMLEditor() && IsDocumentEditable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
SetEditMode(kDisplayModeNormal);
}
};
var nsAllTagsModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsHTMLEditor());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
SetEditMode(kDisplayModeAllTags);
}
};
var nsHTMLSourceModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsHTMLEditor());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
SetEditMode(kDisplayModeSource);
}
};
var nsPreviewModeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsHTMLEditor());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
SetEditMode(kDisplayModePreview);
}
};
//-----------------------------------------------------------------------------------
var nsInsertOrEditTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return (IsDocumentEditable() && IsEditingRenderedHTML());
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (IsInTableCell())
EditorTableCellProperties();
else
EditorInsertOrEditTable(true);
}
};
//-----------------------------------------------------------------------------------
var nsEditTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
EditorInsertOrEditTable(false);
}
};
//-----------------------------------------------------------------------------------
var nsSelectTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().selectTable();
} catch(e) {}
window.content.focus();
}
};
var nsSelectTableRowCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().selectTableRow();
} catch(e) {}
window.content.focus();
}
};
var nsSelectTableColumnCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().selectTableColumn();
} catch(e) {}
window.content.focus();
}
};
var nsSelectTableCellCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().selectTableCell();
} catch(e) {}
window.content.focus();
}
};
var nsSelectAllTableCellsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().selectAllTableCells();
} catch(e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsInsertTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsDocumentEditable() && IsEditingRenderedHTML();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
EditorInsertTable();
}
};
var nsInsertTableRowAboveCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableRow(1, false);
} catch(e) {}
window.content.focus();
}
};
var nsInsertTableRowBelowCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableRow(1, true);
} catch(e) {}
window.content.focus();
}
};
var nsInsertTableColumnBeforeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableColumn(1, false);
} catch(e) {}
window.content.focus();
}
};
var nsInsertTableColumnAfterCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableColumn(1, true);
} catch(e) {}
window.content.focus();
}
};
var nsInsertTableCellBeforeCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableCell(1, false);
} catch(e) {}
window.content.focus();
}
};
var nsInsertTableCellAfterCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().insertTableCell(1, true);
} catch(e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsDeleteTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().deleteTable();
} catch(e) {}
window.content.focus();
}
};
var nsDeleteTableRowCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var rows = GetNumberOfContiguousSelectedRows();
// Delete at least one row
if (rows == 0)
rows = 1;
try {
var editor = GetCurrentTableEditor();
editor.beginTransaction();
// Loop to delete all blocks of contiguous, selected rows
while (rows)
{
editor.deleteTableRow(rows);
rows = GetNumberOfContiguousSelectedRows();
}
} finally { editor.endTransaction(); }
window.content.focus();
}
};
var nsDeleteTableColumnCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
var columns = GetNumberOfContiguousSelectedColumns();
// Delete at least one column
if (columns == 0)
columns = 1;
try {
var editor = GetCurrentTableEditor();
editor.beginTransaction();
// Loop to delete all blocks of contiguous, selected columns
while (columns)
{
editor.deleteTableColumn(columns);
columns = GetNumberOfContiguousSelectedColumns();
}
} finally { editor.endTransaction(); }
window.content.focus();
}
};
var nsDeleteTableCellCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().deleteTableCell(1);
} catch (e) {}
window.content.focus();
}
};
var nsDeleteTableCellContentsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTableCell();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().deleteTableCellContents();
} catch (e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsNormalizeTableCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Use nsnull to let editor find table enclosing current selection
try {
GetCurrentTableEditor().normalizeTable(null);
} catch (e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsJoinTableCellsCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
if (IsDocumentEditable() && IsEditingRenderedHTML())
{
try {
var editor = GetCurrentTableEditor();
var tagNameObj = { value: "" };
var countObj = { value: 0 };
var cell = editor.getSelectedOrParentTableElement(tagNameObj, countObj);
// We need a cell and either > 1 selected cell or a cell to the right
// (this cell may originate in a row spanned from above current row)
// Note that editor returns "td" for "th" also.
// (this is a pain! Editor and gecko use lowercase tagNames, JS uses uppercase!)
if( cell && (tagNameObj.value == "td"))
{
// Selected cells
if (countObj.value > 1) return true;
var colSpan = cell.getAttribute("colspan");
// getAttribute returns string, we need number
// no attribute means colspan = 1
if (!colSpan)
colSpan = Number(1);
else
colSpan = Number(colSpan);
var rowObj = { value: 0 };
var colObj = { value: 0 };
editor.getCellIndexes(cell, rowObj, colObj);
// Test if cell exists to the right of current cell
// (cells with 0 span should never have cells to the right
// if there is, user can select the 2 cells to join them)
return (colSpan && editor.getCellAt(null, rowObj.value,
colObj.value + colSpan));
}
} catch (e) {}
}
return false;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// Param: Don't merge non-contiguous cells
try {
GetCurrentTableEditor().joinTableCells(false);
} catch (e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsSplitTableCellCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
if (IsDocumentEditable() && IsEditingRenderedHTML())
{
var tagNameObj = { value: "" };
var countObj = { value: 0 };
var cell;
try {
cell = GetCurrentTableEditor().getSelectedOrParentTableElement(tagNameObj, countObj);
} catch (e) {}
// We need a cell parent and there's just 1 selected cell
// or selection is entirely inside 1 cell
if ( cell && (tagNameObj.value == "td") &&
countObj.value <= 1 &&
IsSelectionInOneCell() )
{
var colSpan = cell.getAttribute("colspan");
var rowSpan = cell.getAttribute("rowspan");
if (!colSpan) colSpan = 1;
if (!rowSpan) rowSpan = 1;
return (colSpan > 1 || rowSpan > 1 ||
colSpan == 0 || rowSpan == 0);
}
}
return false;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
try {
GetCurrentTableEditor().splitTableCell();
} catch (e) {}
window.content.focus();
}
};
//-----------------------------------------------------------------------------------
var nsTableOrCellColorCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return IsInTable();
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
EditorSelectColor("TableOrCell");
}
};
//-----------------------------------------------------------------------------------
var nsPreferencesCommand =
{
isCommandEnabled: function(aCommand, dummy)
{
return true;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
goPreferences('editor', 'chrome://editor/content/pref-composer.xul','editor');
window.content.focus();
}
};
var nsFinishHTMLSource =
{
isCommandEnabled: function(aCommand, dummy)
{
return true;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// In editor.js
FinishHTMLSource();
}
};
var nsCancelHTMLSource =
{
isCommandEnabled: function(aCommand, dummy)
{
return true;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
// In editor.js
CancelHTMLSource();
}
};
var nsConvertToTable =
{
isCommandEnabled: function(aCommand, dummy)
{
if (IsDocumentEditable() && IsEditingRenderedHTML())
{
var selection;
try {
selection = GetCurrentEditor().selection;
} catch (e) {}
if (selection && !selection.isCollapsed)
{
// Don't allow if table or cell is the selection
var element;
try {
element = GetCurrentEditor().getSelectedElement("");
} catch (e) {}
if (element)
{
var name = element.nodeName.toLowerCase();
if (name == "td" ||
name == "th" ||
name == "caption" ||
name == "table")
return false;
}
// Selection start and end must be in the same cell
// in same cell or both are NOT in a cell
if ( GetParentTableCell(selection.focusNode) !=
GetParentTableCell(selection.anchorNode) )
return false
return true;
}
}
return false;
},
getCommandStateParams: function(aCommand, aParams, aRefCon) {},
doCommandParams: function(aCommand, aParams, aRefCon) {},
doCommand: function(aCommand)
{
if (this.isCommandEnabled())
{
window.openDialog("chrome://editor/content/EdConvertToTable.xul","_blank", "chrome,close,titlebar,modal")
}
window.content.focus();
}
};
PK
Lf.>? >? % content/editor/EditorCommandsDebug.jsUT >NDDUx /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Main Composer window debug menu functions */
// --------------------------- Output ---------------------------
function EditorGetText()
{
try {
dump("Getting text\n");
var outputText = GetCurrentEditor().outputToString("text/plain", 2);
dump("<<" + outputText + ">>\n");
} catch (e) {}
}
function EditorGetHTML()
{
try {
dump("Getting HTML\n");
var outputHTML = GetCurrentEditor().outputToString("text/html", 256);
dump(outputHTML + "\n");
} catch (e) {}
}
function EditorDumpContent()
{
dump("============== Content Tree: ================\n");
GetCurrentEditor().dumpContentTree();
}
function EditorInsertText(textToInsert)
{
GetCurrentEditor().insertText(textToInsert);
}
function EditorTestSelection()
{
dump("Testing selection\n");
var selection = GetCurrentEditor().selection;
if (!selection)
{
dump("No selection!\n");
return;
}
dump("Selection contains:\n");
// 3rd param = column to wrap
dump(selection.QueryInterface(Components.interfaces.nsISelectionPrivate)
.toStringWithFormat("text/plain",
3, // OutputFormatted & gOutputSelectionOnly
0) + "\n");
var output, i;
dump("====== Selection as node and offsets==========\n");
dump("rangeCount = " + selection.rangeCount + "\n");
for (i = 0; i < selection.rangeCount; i++)
{
var range = selection.getRangeAt(i);
if (range)
{
dump("Range "+i+": StartParent="+range.startContainer.nodeName+", offset="+range.startOffset+"\n");
dump("Range "+i+": EndParent="+range.endContainer.nodeName+", offset="+range.endOffset+"\n\n");
}
}
var editor = GetCurrentEditor();
dump("====== Selection as unformatted text ==========\n");
output = editor.outputToString("text/plain", 1);
dump(output + "\n\n");
dump("====== Selection as formatted text ============\n");
output = editor.outputToString("text/plain", 3);
dump(output + "\n\n");
dump("====== Selection as HTML ======================\n");
output = editor.outputToString("text/html", 1);
dump(output + "\n\n");
dump("====== Selection as prettyprinted HTML ========\n");
output = editor.outputToString("text/html", 3);
dump(output + "\n\n");
dump("====== Length and status =====================\n");
output = "Document is ";
if (editor.documentIsEmpty)
output += "empty\n";
else
output += "not empty\n";
output += "Text length is " + editor.textLength + " characters";
dump(output + "\n\n");
}
function EditorTestTableLayout()
{
dump("\n\n\n************ Dump Selection Ranges ************\n");
var selection = GetCurrentEditor().selection;
var i;
for (i = 0; i < selection.rangeCount; i++)
{
var range = selection.getRangeAt(i);
if (range)
{
dump("Range "+i+": StartParent="+range.startParent+", offset="+range.startOffset+"\n");
}
}
dump("\n\n");
var editor = GetCurrentEditor();
var table = editor.getElementOrParentByTagName("table", null);
if (!table) {
dump("Enclosing Table not found: Place caret in a table cell to do this test\n\n");
return;
}
var cell;
var startRowIndexObj = { value: null };
var startColIndexObj = { value: null };
var rowSpanObj = { value: null };
var colSpanObj = { value: null };
var actualRowSpanObj = { value: null };
var actualColSpanObj = { value: null };
var isSelectedObj = { value: false };
var startRowIndex = 0;
var startColIndex = 0;
var rowSpan;
var colSpan;
var actualRowSpan;
var actualColSpan;
var isSelected;
var col = 0;
var row = 0;
var rowCount = 0;
var maxColCount = 0;
var doneWithRow = false;
var doneWithCol = false;
dump("\n\n\n************ Starting Table Layout test ************\n");
// Note: We could also get the number of rows, cols and use for loops,
// but this tests using out-of-bounds offsets to detect end of row or column
while (!doneWithRow) // Iterate through rows
{
dump("* Data for ROW="+row+":\n");
while(!doneWithCol) // Iterate through cells in the row
{
try {
cell = editor.getCellDataAt(table, row, col,
startRowIndexObj, startColIndexObj,
rowSpanObj, colSpanObj,
actualRowSpanObj, actualColSpanObj,
isSelectedObj);
if (cell)
{
rowSpan = rowSpanObj.value;
colSpan = colSpanObj.value;
actualRowSpan = actualRowSpanObj.value;
actualColSpan = actualColSpanObj.value;
isSelected = isSelectedObj.value;
dump(" Row="+row+", Col="+col+" StartRow="+startRowIndexObj.value+", StartCol="+startColIndexObj.value+"\n");
dump(" RowSpan="+rowSpan+", ColSpan="+colSpan+" ActualRowSpan="+actualRowSpan+", ActualColSpan="+actualColSpan);
if (isSelected)
dump(" Cell is selected\n");
else
dump(" Cell is NOT selected\n");
// Save the indexes of a cell that will span across the cellmap grid
if (rowSpan > 1)
startRowIndex = startRowIndexObj.value;
if (colSpan > 1)
startColIndex = startColIndexObj.value;
// Initialize these for efficient spanned-cell search
startRowIndexObj.value = startRowIndex;
startColIndexObj.value = startColIndex;
col++;
} else {
doneWithCol = true;
// Get maximum number of cells in any row
if (col > maxColCount)
maxColCount = col;
dump(" End of row found\n\n");
}
}
catch (e) {
dump(" *** GetCellDataAt failed at Row="+row+", Col="+col+" ***\n\n");
return;
}
}
if (col == 0) {
// Didn't find a cell in the first col of a row,
// thus no more rows in table
doneWithRow = true;
rowCount = row;
dump("No more rows in table\n\n");
} else {
// Setup for next row
col = 0;
row++;
doneWithCol = false;
}
}
dump("Counted during scan: Number of rows="+rowCount+" Number of Columns="+maxColCount+"\n");
rowCount = editor.getTableRowCount(table);
maxColCount = editor.getTableColumnCount(table);
dump("From nsITableLayout: Number of rows="+rowCount+" Number of Columns="+maxColCount+"\n****** End of Table Layout Test *****\n\n");
}
function EditorShowEmbeddedObjects()
{
dump("\nEmbedded Objects:\n");
try {
var objectArray = GetCurrentEditor().getEmbeddedObjects();
dump(objectArray.Count() + " embedded objects\n");
for (var i=0; i < objectArray.Count(); ++i)
dump(objectArray.GetElementAt(i) + "\n");
} catch(e) {}
}
function EditorUnitTests()
{
dump("Running Unit Tests\n");
var numTests = { value:0 };
var numTestsFailed = { value:0 };
GetCurrentEditor().debugUnitTests(numTests, numTestsFailed);
}
function EditorTestDocument()
{
dump("Getting document\n");
var theDoc = GetCurrentEditor().document;
if (theDoc)
{
dump("Got the doc\n");
dump("Document name:" + theDoc.nodeName + "\n");
dump("Document type:" + theDoc.doctype + "\n");
}
else
{
dump("Failed to get the doc\n");
}
}
// --------------------------- Logging stuff ---------------------------
function EditorExecuteScript(theFile)
{
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance();
inputStream = inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
inputStream.init(theFile, 1, 0, false); // open read only
var scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance();
scriptableInputStream = scriptableInputStream.QueryInterface(Components.interfaces.nsIScriptableInputStream);
scriptableInputStream.init(inputStream); // open read only
var buf = { value:null };
var tmpBuf = { value:null };
var didTruncate = { value:false };
var lineNum = 0;
var ex;
/*
// Log files can be quite huge, so read in a line
// at a time and execute it:
while (!inputStream.eof())
{
buf.value = "";
didTruncate.value = true;
// Keep looping until we get a complete line of
// text, or we hit the end of file:
while (didTruncate.value && !inputStream.eof())
{
didTruncate.value = false;
fileSpec.readLine(tmpBuf, 1024, didTruncate);
buf.value += tmpBuf.value;
// XXX Need to null out tmpBuf.value to avoid crashing
// XXX in some JavaScript string allocation method.
// XXX This is probably leaking the buffer allocated
// XXX by the readLine() implementation.
tmpBuf.value = null;
}
++lineNum;
*/
{
// suck in the entire file
var fileSize = scriptableInputStream.available();
var fileContents = scriptableInputStream.read(fileSize);
dump(fileContents);
try { eval(fileContents); }
catch(ex) { dump("Playback ERROR: Line " + lineNum + " " + ex + "\n"); return; }
}
buf.value = null;
}
function EditorGetScriptFileSpec()
{
var dirServ = Components.classes['@mozilla.org/file/directory_service;1'].createInstance();
dirServ = dirServ.QueryInterface(Components.interfaces.nsIProperties);
var processDir = dirServ.get("Home", Components.interfaces.nsIFile);
processDir.append("journal.js");
return processDir;
}
function EditorStartLog()
{
try {
var edlog = GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorLogging);
var fs = EditorGetScriptFileSpec();
edlog.startLogging(fs);
window._content.focus();
fs = null;
}
catch(ex) { dump("Can't start logging!:\n" + ex + "\n"); }
}
function EditorStopLog()
{
try {
var edlog = GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorLogging);
edlog.stopLogging();
window._content.focus();
}
catch(ex) { dump("Can't stop logging!:\n" + ex + "\n"); }
}
function EditorRunLog()
{
var fs;
fs = EditorGetScriptFileSpec();
EditorExecuteScript(fs);
window._content.focus();
}
// --------------------------- TransactionManager ---------------------------
function DumpUndoStack()
{
try {
var txmgr = GetCurrentEditor().transactionManager;
if (!txmgr)
{
dump("**** Editor has no TransactionManager!\n");
return;
}
dump("---------------------- BEGIN UNDO STACK DUMP\n");
dump("\n");
PrintTxnList(txmgr.getUndoList(), "");
dump("\n");
dump("Num Undo Items: " + txmgr.numberOfUndoItems + "\n");
dump("---------------------- END UNDO STACK DUMP\n");
} catch (e) {
dump("ERROR: DumpUndoStack() failed: " + e);
}
}
function DumpRedoStack()
{
try {
var txmgr = GetCurrentEditor().transactionManager;
if (!txmgr)
{
dump("**** Editor has no TransactionManager!\n");
return;
}
dump("---------------------- BEGIN REDO STACK DUMP\n");
dump("\n");
PrintTxnList(txmgr.getRedoList(), "");
dump("\n");
dump("Num Redo Items: " + txmgr.numberOfRedoItems + "\n");
dump("---------------------- END REDO STACK DUMP\n");
} catch (e) {
dump("ERROR: DumpUndoStack() failed: " + e);
}
}
function PrintTxnList(txnList, prefixStr)
{
var i;
for (i=0 ; i < txnList.numItems; i++)
{
var txn = txnList.getItem(i);
var desc = "TXMgr Batch";
if (txn)
{
try {
txn = txn.QueryInterface(Components.interfaces.nsPIEditorTransaction);
desc = txn.txnDescription;
} catch(e) {
desc = "UnknownTxnType";
}
}
dump(prefixStr + "+ " + desc + "\n");
PrintTxnList(txnList.getChildListForItem(i), prefixStr + "| ");
}
}
// ------------------------ 3rd Party Transaction Test ------------------------
function sampleJSTransaction()
{
this.wrappedJSObject = this;
}
sampleJSTransaction.prototype = {
isTransient: false,
mStrData: "[Sample-JS-Transaction-Content]",
mObject: null,
mContainer: null,
mOffset: null,
doTransaction: function()
{
if (this.mContainer.nodeName != "#text")
{
// We're not in a text node, so create one and
// we'll just insert it at (mContainer, mOffset).
this.mObject = this.mContainer.ownerDocument.createTextNode(this.mStrData);
}
this.redoTransaction();
},
undoTransaction: function()
{
if (!this.mObject)
this.mContainer.deleteData(this.mOffset, this.mStrData.length);
else
this.mContainer.removeChild(this.mObject);
},
redoTransaction: function()
{
if (!this.mObject)
this.mContainer.insertData(this.mOffset, this.mStrData);
else
this.insert_node_at_point(this.mObject, this.mContainer, this.mOffset);
},
merge: function(aTxn)
{
// We don't do any merging!
return false;
},
QueryInterface: function(theUID, theResult)
{
if (theUID == Components.interfaces.nsITransaction ||
theUID == Components.interfaces.nsISupports)
return this;
return nsnull;
},
insert_node_at_point: function(node, container, offset)
{
var childList = container.childNodes;
if (childList.length == 0 || offset >= childList.length)
container.appendChild(node);
else
container.insertBefore(node, childList.item(offset));
}
}
function ExecuteJSTransactionViaTxmgr()
{
try {
var editor = GetCurrentEditor();
var txmgr = editor.transactionManager;
txmgr = txmgr.QueryInterface(Components.interfaces.nsITransactionManager);
var selection = editor.selection;
var range = selection.getRangeAt(0);
var txn = new sampleJSTransaction();
txn.mContainer = range.startContainer;
txn.mOffset = range.startOffset;
txmgr.doTransaction(txn);
} catch (e) {
dump("ExecuteJSTransactionViaTxmgr() failed!");
}
}
function ExecuteJSTransactionViaEditor()
{
try {
var editor = GetCurrentEditor();
var selection = editor.selection;
var range = selection.getRangeAt(0);
var txn = new sampleJSTransaction();
txn.mContainer = range.startContainer;
txn.mOffset = range.startOffset;
editor.doTransaction(txn);
} catch (e) {
dump("ExecuteJSTransactionViaEditor() failed!");
}
}
PK
\.gL # content/editor/EditorContextMenu.jsUT ?(?NDDUx /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Charles Manske (cmanske@netscape.com)
*/
function EditorFillContextMenu(event, contextMenuNode)
{
if ( event.target != contextMenuNode )
return;
// Setup object property menuitem
var objectName = InitObjectPropertiesMenuitem("objectProperties_cm");
var isInLink = objectName == "href";
// Special case of an image inside a link
if (objectName == "img")
try {
isInLink = GetCurrentEditor().getElementOrParentByTagName("href", GetObjectForProperties());
} catch (e) {}
InitRemoveStylesMenuitems("removeStylesMenuitem_cm", "removeLinksMenuitem_cm", "removeNamedAnchorsMenuitem_cm");
var inCell = IsInTableCell();
// Set appropriate text for join cells command
InitJoinCellMenuitem("joinTableCells_cm");
// Update enable states for all table commands
goUpdateTableMenuItems(document.getElementById("composerTableMenuItems"));
// Loop through all children to hide disabled items
var children = contextMenuNode.childNodes;
if (children)
{
var count = children.length;
for (var i = 0; i < count; i++)
HideDisabledItem(children[i]);
}
// The above loop will always show all separators and the next two items
// Hide "Create Link" if in a link
ShowMenuItem("createLink_cm", !isInLink);
// Hide "Edit link in new Composer" unless in a link
ShowMenuItem("editLink_cm", isInLink);
// Remove separators if all items in immediate group above are hidden
// A bit complicated to account if multiple groups are completely hidden!
var haveUndo =
IsMenuItemShowing("menu_undo_cm") ||
IsMenuItemShowing("menu_redo_cm");
var haveEdit =
IsMenuItemShowing("menu_cut_cm") ||
IsMenuItemShowing("menu_copy_cm") ||
IsMenuItemShowing("menu_paste_cm") ||
IsMenuItemShowing("menu_pasteNoFormatting_cm") ||
IsMenuItemShowing("menu_delete_cm");
var haveStyle =
IsMenuItemShowing("removeStylesMenuitem_cm") ||
IsMenuItemShowing("createLink_cm") ||
IsMenuItemShowing("removeLinksMenuitem_cm") ||
IsMenuItemShowing("removeNamedAnchorsMenuitem_cm");
var haveProps =
IsMenuItemShowing("objectProperties_cm");
ShowMenuItem("undoredo-separator", haveUndo && haveEdit);
ShowMenuItem("edit-separator", haveEdit || haveUndo);
// Note: Item "menu_selectAll_cm" and
// following separator are ALWAYS enabled,
// so there will always be 1 separator here
var showStyleSep = haveStyle && (haveProps || inCell);
ShowMenuItem("styles-separator", showStyleSep);
var showPropSep = (haveProps && inCell);
ShowMenuItem("property-separator", showPropSep);
// Remove table submenus if not in table
ShowMenuItem("tableInsertMenu_cm", inCell);
ShowMenuItem("tableSelectMenu_cm", inCell);
ShowMenuItem("tableDeleteMenu_cm", inCell);
}
function IsItemOrCommandEnabled( item )
{
var command = item.getAttribute("command");
if (command) {
// If possible, query the command controller directly
var controller = document.commandDispatcher.getControllerForCommand(command);
if (controller)
return controller.isCommandEnabled(command);
}
// Fall back on the inefficient observed disabled attribute
return item.getAttribute("disabled") != "true";
}
function HideDisabledItem( item )
{
item.hidden = !IsItemOrCommandEnabled(item);
}
function ShowMenuItem(id, showItem)
{
var item = document.getElementById(id);
if (item && !showItem)
{
item.hidden = true;
}
// else HideDisabledItem showed the item anyway
}
function IsMenuItemShowing(menuID)
{
var item = document.getElementById(menuID);
if (item)
return !item.hidden;
return false;
}
PK
\.W! ! + content/editor/EditorContextMenuOverlay.xulUT ?(?NDDUx
PK
i(0K " content/editor/EditorInitPage.htmlUT 68NDDUx
Ender HTML Test Page
Here's the deal...
This is a good place to add in html to aid in testing features
under development. It's also a great place to not use latin.
Here is an acute entity: "á".
This sentence has two tags between each word.
This paragraph is inside a <div>. Here is some
rather boring text that is a link. Now is the time for all good men (and women)
to come to the mozilla.org party. And bring the quick brown fox and the lazy dog with you.
For your editing pleasure, here is some inline style for you.
A Named Anchor is just before this sentence.
"This paragraph has "class=note", so that we can play with styles."
For example, we might insert generated content, like "Note: " before this
paragraph.
Here is some very run-o-the-mill text in a paragraph tag, for those
of you who are into that kind of thing. I think at this point I shall
regale you with some of my inestimable poetry, which will be presented
in blockquote mode for your reading pleasure. This particular sample
was written when I was eleven years old, but is remarkably similar to
the writings of my later "hard-livin" years. It's titled "Reruns":
Reruns
Reruns are about as much fun,
as your dad taking all your mun,
and giving it to a nun,
as a contribution.
There are 4 br tags on either side of this sentence.
This text has two spaces between every word
Underlined text with space at end and bold text with a space at front
A random list of things to do
- Status report
- Fix bugs
- Call home
Here is some
preformatted text.
Here is some
preformatted text.
- list item 1
- list item 2
- list item 3
- list item with child paragraphs
First child paragraph
Second child paragraph
Third child paragraph
-
Another list item
-
Something else.
-
Another thing.
| cell 1 | cell 2 | cell 3 |
| cell 4 | cell 5 | cell 6 |
| cell 7 | cell 8 | cell 9 |
| big cell 1 |
| nested cell 1 | nested cell 2 |
| nested cell 3 | nested cell 4 |
|
| nested cell 5 | nested cell 6 |
| nested cell 7 | nested cell 8 |
| big cell 4 |
Japanese for ya: プロ野球速報
One more paragraph for the road. A true Klingon fears not the atrocious
editing file format hoisted on us by html. Well, maybe he does, a little.
But he hides it well.
PK
s.'D&w ' content/editor/EditorInitPagePlain.htmlUT 7NDDUx
Ender Plain Text Test Page
80 char width (for reference only)
---------|---------|---------|---------|---------|---------|---------|---------|
Welcome to the Gecko Plaintext Editor.
This message has the wrapping set to 72 columns using a style sheet.
Typed text will wrap to the current wrap setting. You can view or set the wrap settings by typing various characters, as such:
- alt-C: print the current wrap column setting.
- alt-]: increase the wrap setting by 5
- alt-[: decrease the wrap setting by 5
- ctrl-\: wrap to window width (wrapcolumn = -1)
- alt-\: turn off wrapping (wrapcolumn = 0)
PK
B3+l content/editor/EditorExtra.cssUT 1;NDDUx /*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* This contains CSS just for smiley menu */
#smileButton {
list-style-image:url("chrome://editor/content/images/smile.gif");
}
menu:hover > #smileButton,
menu:hover:active > #smileButton[toggled="true"] {
list-style-image:url("chrome://editor/content/images/smile_hover.gif");
}
menu:hover:active > #smileButton,
menu:hover > #smileButton[toggled="true"] {
list-style-image:url("chrome://editor/content/images/smile_active.gif");
}
#smileButton[disabled="true"],
menu:hover > #smileButton[disabled="true"],
menu:hover:active > #smileButton[disabled="true"] {
list-style-image:url("chrome://editor/content/images/smile_disabled.gif");
}
#insert-smile {
list-style-image:url(chrome://editor/content/images/smile.gif);
}
#insert-frown {
list-style-image:url(chrome://editor/content/images/frown.gif);
}
#insert-wink {
list-style-image:url(chrome://editor/content/images/wink.gif);
}
#insert-sick {
list-style-image:url(chrome://editor/content/images/sick.gif);
}
#insert-smile5 {
list-style-image:url(chrome://editor/content/images/smile.gif);
}
#insert-smile6 {
list-style-image:url(chrome://editor/content/images/frown.gif);
}
#insert-smile7 {
list-style-image:url(chrome://editor/content/images/wink.gif);
}
PK
mc)0RD$CW CW content/editor/EditorAllTags.cssUT ?NDDUx /*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Styles to alter look of things in the Editor content window
* for the "All Tags Edit Mode" Every HTML tag shows up as an icon.
*/
/* For "userdefined" or "unknown" tags
(Note that "_" must be escaped)
*/
*[\_moz-userdefined] {
display: inline;
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 16px;
background-image: url(chrome://editor/content/images/tag-userdefined.gif);
background-repeat: no-repeat;
background-position: top left;
}
a:not([\_moz_anonclass]) {
min-height: 16px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-a.gif);
background-repeat: no-repeat;
background-position: top left;
}
abbr {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 35px;
background-image: url(chrome://editor/content/images/tag-abr.gif);
background-repeat: no-repeat;
background-position: top left;
}
acronym {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 57px;
background-image: url(chrome://editor/content/images/tag-acr.gif);
background-repeat: no-repeat;
background-position: top left;
}
address {
min-height: 44px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-adr.gif);
background-repeat: no-repeat;
background-position: top left;
}
applet {
min-height: 35px; margin-top: 2px;
padding-left: 47px;
background-image: url(chrome://editor/content/images/tag-app.gif);
background-repeat: no-repeat;
background-position: top left;
}
area {
min-height: 35px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-ara.gif);
background-repeat: no-repeat;
background-position: top left;
}
b {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-b.gif);
background-repeat: no-repeat;
background-position: top left;
}
basefont {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 57px;
background-image: url(chrome://editor/content/images/tag-bsf.gif);
background-repeat: no-repeat;
background-position: top left;
}
bdo {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-bdo.gif);
background-repeat: no-repeat;
background-position: top left;
}
big {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-big.gif);
background-repeat: no-repeat;
background-position: top left;
}
blockquote {
min-height: 44px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-blq.gif);
background-repeat: no-repeat;
background-position: top left;
}
body {
min-height: 36px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-body.gif);
background-repeat: no-repeat;
background-position: top left;
}
br {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-br.gif);
background-repeat: no-repeat;
background-position: top left;
}
button {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 57px;
background-image: url(chrome://editor/content/images/tag-btn.gif);
background-repeat: no-repeat;
background-position: top left;
}
caption {
min-height: 35px; margin-top: 2px;
padding-left: 55px;
background-image: url(chrome://editor/content/images/tag-cpt.gif);
background-repeat: no-repeat;
background-position: top left;
}
center {
min-height: 44px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-ctr.gif);
background-repeat: no-repeat;
background-position: top left;
}
cite {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-cit.gif);
background-repeat: no-repeat;
background-position: top left;
}
code {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-cod.gif);
background-repeat: no-repeat;
background-position: top left;
}
col {
min-height: 35px; margin-left: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-col.gif);
background-repeat: no-repeat;
background-position: top left;
}
colgroup {
min-height: 35px; margin-left: 2px;
padding-left: 51px;
background-image: url(chrome://editor/content/images/tag-clg.gif);
background-repeat: no-repeat;
background-position: top left;
}
dd {
min-height: 35px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-dd.gif);
background-repeat: no-repeat;
background-position: top left;
}
del {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-del.gif);
background-repeat: no-repeat;
background-position: top left;
}
dfn {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-dfn.gif);
background-repeat: no-repeat;
background-position: top left;
}
dir {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-dir.gif);
background-repeat: no-repeat;
background-position: top left;
}
div {
min-height: 24px; margin-top: 2px;
/* TEMPORARY TO COMPENSATE FOR BUG */
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-div.gif);
background-repeat: no-repeat;
background-position: top left;
}
input div {
min-height: 0px; margin-left: 0px; margin-top: 0px;
padding-left: 0px;
background-image: none;
}
dl {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-dl.gif);
background-repeat: no-repeat;
background-position: top left;
}
dt {
min-height: 35px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-dt.gif);
background-repeat: no-repeat;
background-position: top left;
}
em {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-em.gif);
background-repeat: no-repeat;
background-position: top left;
}
fieldset {
min-height: 44px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-fld.gif);
background-repeat: no-repeat;
background-position: top left;
}
font {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-fnt.gif);
background-repeat: no-repeat;
background-position: top left;
}
form {
min-height: 36px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-for.gif);
background-repeat: no-repeat;
background-position: top left;
}
frame {
min-height: 40px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-frm.gif);
background-repeat: no-repeat;
background-position: top left;
}
frameset {
min-height: 44px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-fst.gif);
background-repeat: no-repeat;
background-position: top left;
}
h1 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h1.gif);
background-repeat: no-repeat;
background-position: top left;
}
h2 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h2.gif);
background-repeat: no-repeat;
background-position: top left;
}
h3 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h3.gif);
background-repeat: no-repeat;
background-position: top left;
}
h4 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h4.gif);
background-repeat: no-repeat;
background-position: top left;
}
h5 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h5.gif);
background-repeat: no-repeat;
background-position: top left;
}
h6 {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-h6.gif);
background-repeat: no-repeat;
background-position: top left;
}
hr {
min-height: 20px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-hr.gif);
background-repeat: no-repeat;
background-position: top left;
}
i {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-i.gif);
background-repeat: no-repeat;
background-position: top left;
}
iframe {
min-height: 35px; margin-left: 2px;
padding-left: 47px;
background-image: url(chrome://editor/content/images/tag-ifr.gif);
background-repeat: no-repeat;
background-position: top left;
}
img:not([\_moz_anonclass]) {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-img.gif);
background-repeat: no-repeat;
background-position: top left;
}
input {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-inp.gif);
background-repeat: no-repeat;
background-position: top left;
}
ins {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-ins.gif);
background-repeat: no-repeat;
background-position: top left;
}
isindex {
min-height: 40px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-isx.gif);
background-repeat: no-repeat;
background-position: top left;
}
kbd {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-kbd.gif);
background-repeat: no-repeat;
background-position: top left;
}
label {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-lbl.gif);
background-repeat: no-repeat;
background-position: top left;
}
legend {
min-height: 35px; margin-top: 2px;
padding-left: 49px;
background-image: url(chrome://editor/content/images/tag-lgn.gif);
background-repeat: no-repeat;
background-position: top left;
}
li {
min-height: 35px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-li.gif);
background-repeat: no-repeat;
background-position: top left;
}
listing {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 57px;
background-image: url(chrome://editor/content/images/tag-lst.gif);
background-repeat: no-repeat;
background-position: top left;
}
map {
min-height: 35px; margin-left: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-map.gif);
background-repeat: no-repeat;
background-position: top left;
}
menu {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-men.gif);
background-repeat: no-repeat;
background-position: top left;
}
nobr {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-nbr.gif);
background-repeat: no-repeat;
background-position: top left;
}
noframes {
min-height: 44px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-nfr.gif);
background-repeat: no-repeat;
background-position: top left;
}
noscript {
min-height: 44px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-nsc.gif);
background-repeat: no-repeat;
background-position: top left;
}
object {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 49px;
background-image: url(chrome://editor/content/images/tag-obj.gif);
background-repeat: no-repeat;
background-position: top left;
}
ol {
min-height: 38px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-ol.gif);
background-repeat: no-repeat;
background-position: top left;
}
optgroup {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 51px;
background-image: url(chrome://editor/content/images/tag-opg.gif);
background-repeat: no-repeat;
background-position: top left;
}
option {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 47px;
background-image: url(chrome://editor/content/images/tag-opt.gif);
background-repeat: no-repeat;
background-position: top left;
}
p {
min-height: 38px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-p.gif);
background-repeat: no-repeat;
background-position: top left;
}
param {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 43px;
background-image: url(chrome://editor/content/images/tag-prm.gif);
background-repeat: no-repeat;
background-position: top left;
}
plaintext {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 57px;
background-image: url(chrome://editor/content/images/tag-pln.gif);
background-repeat: no-repeat;
background-position: top left;
}
pre {
min-height: 24px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-pre.gif);
background-repeat: no-repeat;
background-position: top left;
}
q {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-q.gif);
background-repeat: no-repeat;
background-position: top left;
}
s {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-s.gif);
background-repeat: no-repeat;
background-position: top left;
}
samp {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-smp.gif);
background-repeat: no-repeat;
background-position: top left;
}
script {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 45px;
background-image: url(chrome://editor/content/images/tag-scr.gif);
background-repeat: no-repeat;
background-position: top left;
}
select {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 47px;
background-image: url(chrome://editor/content/images/tag-slc.gif);
background-repeat: no-repeat;
background-position: top left;
}
small {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 41px;
background-image: url(chrome://editor/content/images/tag-sml.gif);
background-repeat: no-repeat;
background-position: top left;
}
span:not([\_moz_anonclass]) {
min-height: 35px; margin-left: 2px; margin-top: 2px;
/* TEMPORARY TO COMPENSATE FOR BUG */
padding-left: 39px;
background-image: url(chrome://editor/content/images/tag-spn.gif);
background-repeat: no-repeat;
background-position: top left;
}
strike {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 45px;
background-image: url(chrome://editor/content/images/tag-stk.gif);
background-repeat: no-repeat;
background-position: top left;
}
strong {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 51px;
background-image: url(chrome://editor/content/images/tag-stn.gif);
background-repeat: no-repeat;
background-position: top left;
}
sub {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-sub.gif);
background-repeat: no-repeat;
background-position: top left;
}
sup {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-sup.gif);
background-repeat: no-repeat;
background-position: top left;
}
/* The background image technique is not working for
some table elements. Trying the "before" strategy
*/
table {
min-height: 40px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-tbl.gif);
background-repeat: no-repeat;
background-position: top left;
}
tbody {
min-height: 42px; margin-left: 2px; margin-top: 1px;
padding-left: 17px;
content: url(chrome://editor/content/images/tag-tbd.gif);
background-repeat: no-repeat;
background-position: top left;
}
td {
min-height: 22px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-td.gif);
background-repeat: no-repeat;
background-position: top left;
}
textarea {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 59px;
background-image: url(chrome://editor/content/images/tag-txt.gif);
background-repeat: no-repeat;
background-position: top left;
}
tfoot {
min-height: 42px; margin-left: 2px; margin-top: 1px;
padding-left: 17px;
content: url(chrome://editor/content/images/tag-tft.gif);
background-repeat: no-repeat;
background-position: top left;
}
th {
min-height: 22px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-th.gif);
background-repeat: no-repeat;
background-position: top left;
}
thead {
min-height: 42px; margin-left: 2px; margin-top: 1px;
padding-left: 17px;
content: url(chrome://editor/content/images/tag-thd.gif);
background-repeat: no-repeat;
background-position: top left;
}
tr {
min-height: 22px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-tr.gif);
background-repeat: no-repeat;
background-position: top left;
}
tt {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-tt.gif);
background-repeat: no-repeat;
background-position: top left;
}
u {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 23px;
background-image: url(chrome://editor/content/images/tag-u.gif);
background-repeat: no-repeat;
background-position: top left;
}
ul {
min-height: 20px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-ul.gif);
background-repeat: no-repeat;
background-position: top left;
}
var {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-var.gif);
background-repeat: no-repeat;
background-position: top left;
}
xmp {
min-height: 35px; margin-left: 2px; margin-top: 2px;
padding-left: 31px;
background-image: url(chrome://editor/content/images/tag-xmp.gif);
background-repeat: no-repeat;
background-position: top left;
}
/* These are tags that we DON'T want to show icons for.
We have images for them in case we want to utilize them
for some other purpose than the "All Tags" editor mode
html {
min-height: 36px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-html.gif);
background-repeat: no-repeat;
background-position: top left;
}
head {
min-height: 36px; margin-left: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-hed.gif);
background-repeat: no-repeat;
background-position: top left;
}
These are tags that are ONLY allowed as children of HEAD:
title {
min-height: 40px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-ttl.gif);
background-repeat: no-repeat;
background-position: top left;
}
base {
min-height: 36px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-bas.gif);
background-repeat: no-repeat;
background-position: top left;
}
style {
min-height: 40px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-stl.gif);
background-repeat: no-repeat;
background-position: top left;
}
meta {
min-height: 36px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-met.gif);
background-repeat: no-repeat;
background-position: top left;
}
link {
min-height: 30px; margin-left: 2px; margin-top: 2px;
padding-left: 17px;
background-image: url(chrome://editor/content/images/tag-lnk.gif);
background-repeat: no-repeat;
background-position: top left;
}
*/
PK
B3+N&d d ' content/editor/EditorParagraphMarks.cssUT 1;NDDUx /*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* This adds the standard paragraph symbol
* after paragraphs (block container tags)
*/
p:after,br:after,
h1:after,h2:after,h3:after,h4:after,h5:after,h6:after,
address:after,blockquote:after,listing:after,
plaintext:after, xmp:after, pre:after,
li:after,dt:after,dd:after
{
content: "\B6 ";
}
PK
]Yj0ϸ
content/editor/EditorContent.cssUT AhO@NDDUx /*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Daniel Glazman
*/
/* Styles to alter look of things in the Editor content window
* for the "Normal Edit Mode" These settings will be removed
* when we display in completely WYSIWYG "Edit Preview" mode
* Anything that should never change, like cursors, should be
* place in EditorOverride.css, instead of here.
*/
@import url(chrome://communicator/skin/smileys.css);
a[name] {
min-height: 17px; margin-left: 2px; margin-top: 2px;
padding-left: 20px;
background-image: url(chrome://editor/content/images/tag-anchor.gif);
background-repeat: no-repeat;
background-position: top left;
}
/* Force border display for empty cells
and tables with 0 border
*/
table {
empty-cells: show;
}
/* give a red dotted border to tables and cells with no border
otherwise they are invisible
*/
table[empty-cells],
table[border="0"],
/* next two selectors on line below for the case where tbody is omitted */
table[border="0"] > tr > td, table[border="0"] > tr > th,
table[border="0"] > thead > tr > td, table[border="0"] > tbody > tr > td, table[border="0"] > tfoot > tr > td,
table[border="0"] > thead > tr > th, table[border="0"] > tbody > tr > th, table[border="0"] > tfoot > tr > th,
table:not([border]),
/* next two selectors on line below for the case where tbody is omitted */
table:not([border]) > tr > td, table:not([border]) > tr > th,
table:not([border]) > thead > tr > td, table:not([border]) > tbody > tr > td, table:not([border]) > tfoot > tr > td,
table:not([border]) > thead > tr > th, table:not([border]) > tbody > tr > th, table:not([border]) > tfoot > tr > th
{
border: 1px dotted red;
}
/* give a green dashed border to forms otherwise they are invisible
*/
form
{
border: 2px dashed green;
}
/* give a green dotted border to labels otherwise they are invisible
*/
label
{
border: 1px dotted green;
}
img {
-moz-force-broken-image-icon: 1;
}
PK
ơo-+ content/editor/editorOverlay.jsUT =NDDUx /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function EditorNew()
{
dump("In EditorNew..\n");
}
function EditorNewFromTemplate()
{
dump("In EditorNewFromTemplate..\n");
}
function EditorNewFromDraft()
{
dump("In EditorNewFromDraft..\n");
}
PK
,VO " content/editor/composerOverlay.xulUT