Carpool checkin, r=brade. Lots of editor UI work, including new Advanced Edit dialog by Ben Goodger. Fixed style sheet loading leaks and implemented override style sheets for editor behavior, which be unloaded for edit mode vs. browser preview mode

This commit is contained in:
cmanske%netscape.com 1999-09-29 21:45:50 +00:00
parent f0fdbc6804
commit d20641b38c
42 changed files with 1401 additions and 397 deletions

View File

@ -25,7 +25,6 @@
#include "pratom.h"
#include "prprf.h"
#include "nsIComponentManager.h"
//#include "nsAppCores.h"
#include "nsAppCoresCIDs.h"
#include "nsIDOMAppCoresManager.h"
@ -36,6 +35,12 @@
#include "nsIDiskDocument.h"
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsICSSLoader.h"
#include "nsICSSStyleSheet.h"
#include "nsIHTMLContentContainer.h"
#include "nsIStyleSet.h"
#include "nsIURI.h"
#include "nsNeckoUtil.h"
#include "nsIScriptGlobalObject.h"
#include "nsIWebShell.h"
@ -63,7 +68,6 @@
#include "nsIFindComponent.h"
#include "nsIPrompt.h"
#include "nsICommonDialogs.h"
//#include "nsIDialogParamBlock.h"
///////////////////////////////////////
// Editor Includes
@ -149,6 +153,7 @@ nsEditorShell::nsEditorShell()
, mSuggestedWordIndex(0)
, mDictionaryIndex(0)
, mStringBundle(0)
, mEditModeStyleSheet(0)
{
#ifdef APP_DEBUG
printf("Created nsEditorShell\n");
@ -596,13 +601,122 @@ NS_IMETHODIMP nsEditorShell::ApplyStyleSheet(const PRUnichar *url)
nsAutoString aURL(url);
nsCOMPtr<nsIEditorStyleSheets> styleSheetFoobar = do_QueryInterface(mEditor);
if (styleSheetFoobar)
result = styleSheetFoobar->ApplyStyleSheet(aURL);
nsCOMPtr<nsIEditorStyleSheets> styleSheets = do_QueryInterface(mEditor);
if (styleSheets)
result = styleSheets->ApplyStyleSheet(aURL);
return result;
}
// Note: This is not undoable action (on purpose!)
NS_IMETHODIMP nsEditorShell::SetDisplayMode(PRInt32 aDisplayMode)
{
// We are already in EditMode
if (aDisplayMode == eDisplayModeEdit && mEditModeStyleSheet)
return NS_OK;
if (!mContentAreaWebShell)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> presShell = dont_AddRef(GetPresShellFor(mContentAreaWebShell));
if (!presShell)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDocument> document;
nsresult rv = presShell->GetDocument(getter_AddRefs(document));
if (NS_SUCCEEDED(rv))
{
if(!document)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIStyleSet> styleSet;
rv = presShell->GetStyleSet(getter_AddRefs(styleSet));
if (NS_SUCCEEDED(rv))
{
if (!styleSet)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIStyleSheet> styleSheet;
if (aDisplayMode == 0)
{
// Create and load the style sheet for editor content
nsAutoString styleURL("chrome://editor/content/EditorContent.css");
nsCOMPtr<nsIURI>uaURL;
#ifndef NECKO
rv = NS_NewURL(getter_AddRefs(uaURL), styleURL);
#else
rv = NS_NewURI(getter_AddRefs(uaURL), styleURL);
#endif // NECKO
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!container)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSLoader> cssLoader;
rv = container->GetCSSLoader(*getter_AddRefs(cssLoader));
if (NS_SUCCEEDED(rv))
{
if (!cssLoader)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSStyleSheet>cssStyleSheet;
PRBool complete;
// We use null for the callback and data pointer because
// we MUST ONLY load synchronous local files (no @import)
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, nsnull, nsnull);
if (NS_SUCCEEDED(rv))
{
// Synchronous loads should ALWAYS return completed
if (!complete || !cssStyleSheet)
return NS_ERROR_NULL_POINTER;
// Don't need to QI (subclass)
styleSheet = cssStyleSheet;
if (!styleSheet)
return NS_ERROR_NULL_POINTER;
}
}
}
}
else if (aDisplayMode >= 1)
{
if (!mEditModeStyleSheet)
{
// The edit mode sheet was not previously loaded
return NS_OK;
}
styleSheet = mEditModeStyleSheet;
}
if (NS_SUCCEEDED(rv))
{
switch (aDisplayMode)
{
case eDisplayModeEdit:
styleSet->AppendOverrideStyleSheet(styleSheet);
mEditModeStyleSheet = styleSheet;
break;
case eDisplayModeBrowserPreview:
styleSet->RemoveOverrideStyleSheet(mEditModeStyleSheet);
mEditModeStyleSheet = 0;
break;
// Add more modes here, e.g., browser mode with JavaScript turned on?
default:
break;
}
// This notifies document observers to rebuild all frames
// (this doesn't affect style sheet because it is not a doc sheet)
document->SetStyleSheetDisabledState(styleSheet, PR_FALSE);
}
}
}
return rv;
}
NS_IMETHODIMP nsEditorShell::SetBodyAttribute(const PRUnichar *attr, const PRUnichar *value)
{
nsresult result = NS_NOINTERFACE;
@ -819,10 +933,17 @@ nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl)
}
}
#endif
//TODO: TEMPORARY -- THIS IS NOT THE RIGHT THING TO DO!
nsAutoString styleURL("chrome://editor/content/EditorContent.css");
ApplyStyleSheet(styleURL.GetUnicode());
nsCOMPtr<nsIEditorStyleSheets> styleSheets = do_QueryInterface(mEditor);
if (!styleSheets)
return NS_NOINTERFACE;
// Load style sheet with settings that should never
// change, even in "Browser" mode
styleSheets->ApplyOverrideStyleSheet("chrome://editor/content/EditorOverride.css");
// Load the edit mode override style sheet
// This will be remove for "Browser" mode
SetDisplayMode(eDisplayModeEdit);
// Force initial focus to the content window -- HOW?
// mWebShellWin->SetFocus();

View File

@ -42,6 +42,7 @@
#include "nsInterfaceState.h"
#include "nsIHTMLEditor.h"
#include "nsIStringBundle.h"
#include "nsICSSStyleSheet.h"
class nsIBrowserWindow;
class nsIWebShell;
@ -56,7 +57,7 @@ class nsIOutputStream;
class nsISupportsArray;
class nsIStringBundleService;
class nsIStringBundle;
class nsIStyleSheet;
#define NS_EDITORSHELL_CID \
{ /* {} */ \
@ -207,6 +208,9 @@ class nsEditorShell : public nsIEditorShell,
private:
// Pointer to localized strings used for UI
nsCOMPtr<nsIStringBundle> mStringBundle;
// Pointer to the EditorContent style sheet we load/unload
// for "Edit Mode"/"Browser mode" display
nsCOMPtr<nsIStyleSheet> mEditModeStyleSheet;
};
#endif // nsEditorShell_h___

View File

@ -2279,9 +2279,11 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu
{
nsCOMPtr<nsIEnumerator> enumerator;
res = selection->GetEnumerator(getter_AddRefs(enumerator));
// XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed?
if (NS_SUCCEEDED(res) && enumerator)
if (NS_SUCCEEDED(res))
{
if(!enumerator)
return NS_ERROR_NULL_POINTER;
enumerator->First();
nsCOMPtr<nsISupports> currentItem;
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
@ -2716,18 +2718,29 @@ nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet)
return rv;
}
NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
NS_IMETHODIMP
nsHTMLEditor::ApplyOverrideStyleSheet(const nsString& aURL)
{
// XXX: Note that this is not an undo-able action yet!
return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
{
return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE);
}
//Note: Loading a document style sheet is undoable, loading an override sheet is not
nsresult
nsHTMLEditor::ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride)
{
nsresult rv = NS_OK;
nsIURI* uaURL = 0;
nsCOMPtr<nsIURI> uaURL;
#ifndef NECKO
rv = NS_NewURL(&uaURL, aURL);
rv = NS_NewURL(getter_AddRefs(uaURL), aURL);
#else
rv = NS_NewURI(&uaURL, aURL);
rv = NS_NewURI(getter_AddRefs(uaURL), aURL);
#endif // NECKO
if (NS_SUCCEEDED(rv)) {
@ -2739,57 +2752,77 @@ NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
rv = ps->GetDocument(getter_AddRefs(document));
if (NS_SUCCEEDED(rv)) {
if (document) {
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!document)
return NS_ERROR_NULL_POINTER;
if (container) {
nsICSSLoader *cssLoader = 0;
nsICSSStyleSheet *cssStyleSheet = 0;
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!container)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSLoader> cssLoader;
nsCOMPtr<nsICSSStyleSheet> cssStyleSheet;
rv = container->GetCSSLoader(cssLoader);
rv = container->GetCSSLoader(*getter_AddRefs(cssLoader));
if (NS_SUCCEEDED(rv)) {
PRBool complete;
if (!cssLoader)
return NS_ERROR_NULL_POINTER;
if (aOverride) {
// We use null for the callback and data pointer because
// we MUST ONLY load synchronous local files (no @import)
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete,
nsnull, nsnull);
// Synchronous loads should ALWAYS return completed
if (!complete || !cssStyleSheet)
return NS_ERROR_NULL_POINTER;
// Don't need to QI (subclass)
nsCOMPtr<nsIStyleSheet> styleSheet = cssStyleSheet;
nsCOMPtr<nsIStyleSet> styleSet;
rv = ps->GetStyleSet(getter_AddRefs(styleSet));
if (NS_SUCCEEDED(rv)) {
if (cssLoader) {
PRBool complete;
if (!styleSet)
return NS_ERROR_NULL_POINTER;
rv = cssLoader->LoadAgentSheet(uaURL, cssStyleSheet, complete,
ApplyStyleSheetToPresShellDocument,
this);
// Add the override style sheet
// (This checks if already exists
// If yes, it and reads it does)
styleSet->AppendOverrideStyleSheet(styleSheet);
if (NS_SUCCEEDED(rv)) {
if (complete) {
if (cssStyleSheet) {
ApplyStyleSheetToPresShellDocument(cssStyleSheet,
this);
}
else
rv = NS_ERROR_NULL_POINTER;
}
//
// If not complete, we will be notified later
// with a call to AddStyleSheetToEditorDocument().
//
}
}
else
rv = NS_ERROR_NULL_POINTER;
// This notifies document observers to rebuild all frames
// (this doesn't affect style sheet because it is not a doc sheet)
document->SetStyleSheetDisabledState(styleSheet, PR_FALSE);
}
}
else {
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete,
ApplyStyleSheetToPresShellDocument,
this);
if (NS_SUCCEEDED(rv)) {
if (complete) {
if (cssStyleSheet) {
ApplyStyleSheetToPresShellDocument(cssStyleSheet,this);
}
else
rv = NS_ERROR_NULL_POINTER;
}
//
// If not complete, we will be notified later
// with a call to ApplyStyleSheetToPresShellDocument().
//
}
}
else
rv = NS_ERROR_NULL_POINTER;
}
else
rv = NS_ERROR_NULL_POINTER;
}
NS_RELEASE(uaURL);
}
return rv;
}
#ifdef XP_MAC
#pragma mark -
#pragma mark --- nsIEditorMailSupport methods ---
@ -3526,7 +3559,32 @@ NS_IMETHODIMP nsHTMLEditor::OutputToStream(nsIOutputStream* aOutputStream,
return encoder->EncodeToStream(aOutputStream);
}
#if 0
NS_IMETHODIMP
nsHTMLEditor::GetTextNearNode(nsIDOMNode *aNode, aNode, PRInt32 aMaxChars, nsString& aOutputString)
{
if (!aNode)
return NS_ERROR_NULL_POINTER;
// Create a temporary selection object and
// based on the suppled
nsCOMPtr<nsIDOMSelection> selection;
nsCOMPtr<nsIDOMRange> range;
nsresult rv = NS_NewRange(getter_AddRsfs(range))
if (NS_SUCCEEDED(rv))
{
if (!range)
return NS_ERROR_NULL_POINTER;
range.SetStart(aNode,0);
range.SetEnd(aNode,
}
if (NS_SUCCEEDED(rv) && selection)
encoder->SetSelection(selection);
return rv;
}
#endif
NS_IMETHODIMP
nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
@ -3547,7 +3605,6 @@ nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
#endif
}
#ifdef XP_MAC
#pragma mark -
#pragma mark --- nsIEditorIMESupport overrides ---
@ -3606,7 +3663,6 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet)
}
/* static callback */
void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, void *aData)
{
@ -3617,7 +3673,6 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet,
{
rv = editor->ReplaceStyleSheet(aSheet);
}
// XXX: we lose the return value here. Set a flag in the editor?
}

View File

@ -29,6 +29,7 @@
#include "nsEditor.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventListener.h"
#include "nsICSSLoader.h"
#include "nsITableLayout.h"
#include "TypeInState.h"
@ -120,6 +121,11 @@ public:
/* ------------ nsIEditorStyleSheets methods -------------- */
NS_IMETHOD ApplyStyleSheet(const nsString& aURL);
NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL);
/* Above 2 methods call this with appropriate aOverride value
* Not exposed to IDL interface
*/
nsresult ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride);
NS_IMETHOD AddStyleSheet(nsICSSStyleSheet* aSheet);
NS_IMETHOD RemoveStyleSheet(nsICSSStyleSheet* aSheet);
@ -172,8 +178,6 @@ public:
NS_IMETHOD SetBackgroundColor(const nsString& aColor);
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue);
/* ------------ Overrides of nsEditor interface methods -------------- */
/** prepare the editor for use */

View File

@ -25,7 +25,6 @@
#include "pratom.h"
#include "prprf.h"
#include "nsIComponentManager.h"
//#include "nsAppCores.h"
#include "nsAppCoresCIDs.h"
#include "nsIDOMAppCoresManager.h"
@ -36,6 +35,12 @@
#include "nsIDiskDocument.h"
#include "nsIDocument.h"
#include "nsIDOMWindow.h"
#include "nsICSSLoader.h"
#include "nsICSSStyleSheet.h"
#include "nsIHTMLContentContainer.h"
#include "nsIStyleSet.h"
#include "nsIURI.h"
#include "nsNeckoUtil.h"
#include "nsIScriptGlobalObject.h"
#include "nsIWebShell.h"
@ -63,7 +68,6 @@
#include "nsIFindComponent.h"
#include "nsIPrompt.h"
#include "nsICommonDialogs.h"
//#include "nsIDialogParamBlock.h"
///////////////////////////////////////
// Editor Includes
@ -149,6 +153,7 @@ nsEditorShell::nsEditorShell()
, mSuggestedWordIndex(0)
, mDictionaryIndex(0)
, mStringBundle(0)
, mEditModeStyleSheet(0)
{
#ifdef APP_DEBUG
printf("Created nsEditorShell\n");
@ -596,13 +601,122 @@ NS_IMETHODIMP nsEditorShell::ApplyStyleSheet(const PRUnichar *url)
nsAutoString aURL(url);
nsCOMPtr<nsIEditorStyleSheets> styleSheetFoobar = do_QueryInterface(mEditor);
if (styleSheetFoobar)
result = styleSheetFoobar->ApplyStyleSheet(aURL);
nsCOMPtr<nsIEditorStyleSheets> styleSheets = do_QueryInterface(mEditor);
if (styleSheets)
result = styleSheets->ApplyStyleSheet(aURL);
return result;
}
// Note: This is not undoable action (on purpose!)
NS_IMETHODIMP nsEditorShell::SetDisplayMode(PRInt32 aDisplayMode)
{
// We are already in EditMode
if (aDisplayMode == eDisplayModeEdit && mEditModeStyleSheet)
return NS_OK;
if (!mContentAreaWebShell)
return NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIPresShell> presShell = dont_AddRef(GetPresShellFor(mContentAreaWebShell));
if (!presShell)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDocument> document;
nsresult rv = presShell->GetDocument(getter_AddRefs(document));
if (NS_SUCCEEDED(rv))
{
if(!document)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIStyleSet> styleSet;
rv = presShell->GetStyleSet(getter_AddRefs(styleSet));
if (NS_SUCCEEDED(rv))
{
if (!styleSet)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIStyleSheet> styleSheet;
if (aDisplayMode == 0)
{
// Create and load the style sheet for editor content
nsAutoString styleURL("chrome://editor/content/EditorContent.css");
nsCOMPtr<nsIURI>uaURL;
#ifndef NECKO
rv = NS_NewURL(getter_AddRefs(uaURL), styleURL);
#else
rv = NS_NewURI(getter_AddRefs(uaURL), styleURL);
#endif // NECKO
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!container)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSLoader> cssLoader;
rv = container->GetCSSLoader(*getter_AddRefs(cssLoader));
if (NS_SUCCEEDED(rv))
{
if (!cssLoader)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSStyleSheet>cssStyleSheet;
PRBool complete;
// We use null for the callback and data pointer because
// we MUST ONLY load synchronous local files (no @import)
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete, nsnull, nsnull);
if (NS_SUCCEEDED(rv))
{
// Synchronous loads should ALWAYS return completed
if (!complete || !cssStyleSheet)
return NS_ERROR_NULL_POINTER;
// Don't need to QI (subclass)
styleSheet = cssStyleSheet;
if (!styleSheet)
return NS_ERROR_NULL_POINTER;
}
}
}
}
else if (aDisplayMode >= 1)
{
if (!mEditModeStyleSheet)
{
// The edit mode sheet was not previously loaded
return NS_OK;
}
styleSheet = mEditModeStyleSheet;
}
if (NS_SUCCEEDED(rv))
{
switch (aDisplayMode)
{
case eDisplayModeEdit:
styleSet->AppendOverrideStyleSheet(styleSheet);
mEditModeStyleSheet = styleSheet;
break;
case eDisplayModeBrowserPreview:
styleSet->RemoveOverrideStyleSheet(mEditModeStyleSheet);
mEditModeStyleSheet = 0;
break;
// Add more modes here, e.g., browser mode with JavaScript turned on?
default:
break;
}
// This notifies document observers to rebuild all frames
// (this doesn't affect style sheet because it is not a doc sheet)
document->SetStyleSheetDisabledState(styleSheet, PR_FALSE);
}
}
}
return rv;
}
NS_IMETHODIMP nsEditorShell::SetBodyAttribute(const PRUnichar *attr, const PRUnichar *value)
{
nsresult result = NS_NOINTERFACE;
@ -819,10 +933,17 @@ nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl)
}
}
#endif
//TODO: TEMPORARY -- THIS IS NOT THE RIGHT THING TO DO!
nsAutoString styleURL("chrome://editor/content/EditorContent.css");
ApplyStyleSheet(styleURL.GetUnicode());
nsCOMPtr<nsIEditorStyleSheets> styleSheets = do_QueryInterface(mEditor);
if (!styleSheets)
return NS_NOINTERFACE;
// Load style sheet with settings that should never
// change, even in "Browser" mode
styleSheets->ApplyOverrideStyleSheet("chrome://editor/content/EditorOverride.css");
// Load the edit mode override style sheet
// This will be remove for "Browser" mode
SetDisplayMode(eDisplayModeEdit);
// Force initial focus to the content window -- HOW?
// mWebShellWin->SetFocus();

View File

@ -42,6 +42,7 @@
#include "nsInterfaceState.h"
#include "nsIHTMLEditor.h"
#include "nsIStringBundle.h"
#include "nsICSSStyleSheet.h"
class nsIBrowserWindow;
class nsIWebShell;
@ -56,7 +57,7 @@ class nsIOutputStream;
class nsISupportsArray;
class nsIStringBundleService;
class nsIStringBundle;
class nsIStyleSheet;
#define NS_EDITORSHELL_CID \
{ /* {} */ \
@ -207,6 +208,9 @@ class nsEditorShell : public nsIEditorShell,
private:
// Pointer to localized strings used for UI
nsCOMPtr<nsIStringBundle> mStringBundle;
// Pointer to the EditorContent style sheet we load/unload
// for "Edit Mode"/"Browser mode" display
nsCOMPtr<nsIStyleSheet> mEditModeStyleSheet;
};
#endif // nsEditorShell_h___

View File

@ -0,0 +1,40 @@
/*
* 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
* that should NOT be removed when we display in completely WYSIWYG
* "Browser Preview" mode.
* Anything that should change, like appearance of table borders
* and Named Anchors, should be placed in EditorContent.css instead of here.
*/
/* Override the browser's pointer cursor over links */
a:link, a:visited, a:active, a:out-of-date {
cursor: text;
}
a:link img, a:visited img, a:active img,
a:out-of-date img, img[usemap], object[usemap] {
cursor: default;
}

View File

@ -45,6 +45,11 @@ interface nsIEditorShell : nsISupports
eDocumentStatusUnmodified,
eDocumentStatusModified
};
enum {
eDisplayModeEdit,
eDisplayModeBrowserPreview
};
%}
readonly attribute boolean documentModified;
readonly attribute boolean documentIsEmpty;
@ -285,6 +290,17 @@ interface nsIEditorShell : nsISupports
void SetBackgroundColor(in wstring color);
void ApplyStyleSheet(in wstring url);
/** Set the display mode for editing
* @param displayMode
* 0 (eDisplayModeEdit) Use extra CSS style
* (from override styles in EditorContent.css)
* to show named anchors, table borders, etc for editing
* 1 (eDisplayModeBrowserPreview) "WYSIWIG" or Preview mode
* that looks exactly like the browser display except
* for certain behaviors like cursor style over links, etc.
*/
void SetDisplayMode(in PRInt32 displayMode);
/* Output.
* format is mime type, e.g. text/html;

View File

@ -2279,9 +2279,11 @@ nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aRetu
{
nsCOMPtr<nsIEnumerator> enumerator;
res = selection->GetEnumerator(getter_AddRefs(enumerator));
// XXX: ERROR_HANDLING unclear what to do here, should an error just be returned if enumerator is null or res failed?
if (NS_SUCCEEDED(res) && enumerator)
if (NS_SUCCEEDED(res))
{
if(!enumerator)
return NS_ERROR_NULL_POINTER;
enumerator->First();
nsCOMPtr<nsISupports> currentItem;
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
@ -2716,18 +2718,29 @@ nsHTMLEditor::RemoveStyleSheet(nsICSSStyleSheet* aSheet)
return rv;
}
NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
NS_IMETHODIMP
nsHTMLEditor::ApplyOverrideStyleSheet(const nsString& aURL)
{
// XXX: Note that this is not an undo-able action yet!
return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE);
}
NS_IMETHODIMP
nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
{
return ApplyDocumentOrOverrideStyleSheet(aURL, PR_TRUE);
}
//Note: Loading a document style sheet is undoable, loading an override sheet is not
nsresult
nsHTMLEditor::ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride)
{
nsresult rv = NS_OK;
nsIURI* uaURL = 0;
nsCOMPtr<nsIURI> uaURL;
#ifndef NECKO
rv = NS_NewURL(&uaURL, aURL);
rv = NS_NewURL(getter_AddRefs(uaURL), aURL);
#else
rv = NS_NewURI(&uaURL, aURL);
rv = NS_NewURI(getter_AddRefs(uaURL), aURL);
#endif // NECKO
if (NS_SUCCEEDED(rv)) {
@ -2739,57 +2752,77 @@ NS_IMETHODIMP nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
rv = ps->GetDocument(getter_AddRefs(document));
if (NS_SUCCEEDED(rv)) {
if (document) {
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!document)
return NS_ERROR_NULL_POINTER;
if (container) {
nsICSSLoader *cssLoader = 0;
nsICSSStyleSheet *cssStyleSheet = 0;
nsCOMPtr<nsIHTMLContentContainer> container = do_QueryInterface(document);
if (!container)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsICSSLoader> cssLoader;
nsCOMPtr<nsICSSStyleSheet> cssStyleSheet;
rv = container->GetCSSLoader(cssLoader);
rv = container->GetCSSLoader(*getter_AddRefs(cssLoader));
if (NS_SUCCEEDED(rv)) {
PRBool complete;
if (!cssLoader)
return NS_ERROR_NULL_POINTER;
if (aOverride) {
// We use null for the callback and data pointer because
// we MUST ONLY load synchronous local files (no @import)
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete,
nsnull, nsnull);
// Synchronous loads should ALWAYS return completed
if (!complete || !cssStyleSheet)
return NS_ERROR_NULL_POINTER;
// Don't need to QI (subclass)
nsCOMPtr<nsIStyleSheet> styleSheet = cssStyleSheet;
nsCOMPtr<nsIStyleSet> styleSet;
rv = ps->GetStyleSet(getter_AddRefs(styleSet));
if (NS_SUCCEEDED(rv)) {
if (cssLoader) {
PRBool complete;
if (!styleSet)
return NS_ERROR_NULL_POINTER;
rv = cssLoader->LoadAgentSheet(uaURL, cssStyleSheet, complete,
ApplyStyleSheetToPresShellDocument,
this);
// Add the override style sheet
// (This checks if already exists
// If yes, it and reads it does)
styleSet->AppendOverrideStyleSheet(styleSheet);
if (NS_SUCCEEDED(rv)) {
if (complete) {
if (cssStyleSheet) {
ApplyStyleSheetToPresShellDocument(cssStyleSheet,
this);
}
else
rv = NS_ERROR_NULL_POINTER;
}
//
// If not complete, we will be notified later
// with a call to AddStyleSheetToEditorDocument().
//
}
}
else
rv = NS_ERROR_NULL_POINTER;
// This notifies document observers to rebuild all frames
// (this doesn't affect style sheet because it is not a doc sheet)
document->SetStyleSheetDisabledState(styleSheet, PR_FALSE);
}
}
else {
rv = cssLoader->LoadAgentSheet(uaURL, *getter_AddRefs(cssStyleSheet), complete,
ApplyStyleSheetToPresShellDocument,
this);
if (NS_SUCCEEDED(rv)) {
if (complete) {
if (cssStyleSheet) {
ApplyStyleSheetToPresShellDocument(cssStyleSheet,this);
}
else
rv = NS_ERROR_NULL_POINTER;
}
//
// If not complete, we will be notified later
// with a call to ApplyStyleSheetToPresShellDocument().
//
}
}
else
rv = NS_ERROR_NULL_POINTER;
}
else
rv = NS_ERROR_NULL_POINTER;
}
NS_RELEASE(uaURL);
}
return rv;
}
#ifdef XP_MAC
#pragma mark -
#pragma mark --- nsIEditorMailSupport methods ---
@ -3526,7 +3559,32 @@ NS_IMETHODIMP nsHTMLEditor::OutputToStream(nsIOutputStream* aOutputStream,
return encoder->EncodeToStream(aOutputStream);
}
#if 0
NS_IMETHODIMP
nsHTMLEditor::GetTextNearNode(nsIDOMNode *aNode, aNode, PRInt32 aMaxChars, nsString& aOutputString)
{
if (!aNode)
return NS_ERROR_NULL_POINTER;
// Create a temporary selection object and
// based on the suppled
nsCOMPtr<nsIDOMSelection> selection;
nsCOMPtr<nsIDOMRange> range;
nsresult rv = NS_NewRange(getter_AddRsfs(range))
if (NS_SUCCEEDED(rv))
{
if (!range)
return NS_ERROR_NULL_POINTER;
range.SetStart(aNode,0);
range.SetEnd(aNode,
}
if (NS_SUCCEEDED(rv) && selection)
encoder->SetSelection(selection);
return rv;
}
#endif
NS_IMETHODIMP
nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
@ -3547,7 +3605,6 @@ nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
#endif
}
#ifdef XP_MAC
#pragma mark -
#pragma mark --- nsIEditorIMESupport overrides ---
@ -3606,7 +3663,6 @@ nsHTMLEditor::ReplaceStyleSheet(nsICSSStyleSheet *aNewSheet)
}
/* static callback */
void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, void *aData)
{
@ -3617,7 +3673,6 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet,
{
rv = editor->ReplaceStyleSheet(aSheet);
}
// XXX: we lose the return value here. Set a flag in the editor?
}

View File

@ -29,6 +29,7 @@
#include "nsEditor.h"
#include "nsIDOMElement.h"
#include "nsIDOMEventListener.h"
#include "nsICSSLoader.h"
#include "nsITableLayout.h"
#include "TypeInState.h"
@ -120,6 +121,11 @@ public:
/* ------------ nsIEditorStyleSheets methods -------------- */
NS_IMETHOD ApplyStyleSheet(const nsString& aURL);
NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL);
/* Above 2 methods call this with appropriate aOverride value
* Not exposed to IDL interface
*/
nsresult ApplyDocumentOrOverrideStyleSheet(const nsString& aURL, PRBool aOverride);
NS_IMETHOD AddStyleSheet(nsICSSStyleSheet* aSheet);
NS_IMETHOD RemoveStyleSheet(nsICSSStyleSheet* aSheet);
@ -172,8 +178,6 @@ public:
NS_IMETHOD SetBackgroundColor(const nsString& aColor);
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue);
/* ------------ Overrides of nsEditor interface methods -------------- */
/** prepare the editor for use */

View File

@ -39,10 +39,24 @@ public:
/** load and apply the style sheet, specified by aURL, to
* the editor's document. This can involve asynchronous
* network I/O
* @param aURL The style sheet to be loaded and applied.
* @param aURL The style sheet to be loaded and applied.
*/
NS_IMETHOD ApplyStyleSheet(const nsString& aURL)=0;
/** load and apply an Override style sheet, specified by aURL, to
* the editor's document.
* IMPORTANT: This is assumed to be synchronous:
* URL is a local file with no @import used
* This action is not undoable.
* It is not intended for use by "user", only editor developers
* to change display behavior for editing (like showing special cursors)
* that will not be affected by loading other "document" style sheets
* loaded using ApplyStyleSheet.
*
* @param aURL The style sheet to be loaded and applied.
*/
NS_IMETHOD ApplyOverrideStyleSheet(const nsString& aURL)=0;
/** Add the given Style Sheet to the editor's document
* This is always synchronous
* @param aSheet The style sheet to be applied.

View File

@ -364,7 +364,6 @@ public:
*
*/
NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue)=0;
};
#endif // nsIHTMLEditor_h__

View File

@ -153,9 +153,7 @@
<titledbutton id="namedAnchorButton"/>
<html:div class="separator" align="vertical" />
<spring flex="100%"/>
<titledbutton id="DisplayStyleButton"/>
</toolbar>
<toolbar id="FormatToolbar">
@ -207,6 +205,21 @@
<html:iframe type="content-primary" id="content-frame" src="about:blank" flex="100%"/>
<box align="horizontal" id="DisplayModeBar">
<spring class="spacer"/>
<!-- This is a pain: can't use CSS margin to add extra space above text? -->
<box align="vertical">
<spring style="height: 2px"/>
<html:div>&displayMode.label;</html:div>
</box>
<spring class="spacer"/>
<titledbutton id="EditModeButton" class="DisplayModeButton" selected="1" value="&editModeButton.label;" onclick="EditorSetDisplayStyle(0)"/>
<titledbutton id="BrowserModeButton" class="DisplayModeButton" selected="0" value="&browserModeButton.label;" onclick="EditorSetDisplayStyle(1)"/>
<html:div class="VerticalSeparator"/>
<!-- <html:div id="LeftGrayBorder"/> -->
<spring flex="100%"/>
</box>
<!-- status bar, from editorOverlay.xul -->
<box id="EditorStatusBar" />
</box>

View File

@ -24,7 +24,7 @@
var editorShell;
var toolbar;
var documentModified;
var EditorDisplayStyle = true;
var EditorDisplayMode = 0; // Normal Editor mode
var gTagToFormat = {
"P" : "Normal", // these should really be entities. Not sure how to do that from JS
@ -508,6 +508,8 @@ function EditorRemoveLinks()
function EditorApplyStyleSheet(styleSheetURL)
{
// Second param is true for "override" type of sheet
// We don't let users use that option
editorShell.ApplyStyleSheet(styleSheetURL);
contentWindow.focus();
}
@ -767,24 +769,19 @@ function EditorAlign(align)
contentWindow.focus();
}
function EditorToggleDisplayStyle()
function EditorSetDisplayStyle(mode)
{
if (EditorDisplayStyle) {
EditorDisplayStyle = false;
styleSheet = "resource:/res/ua.css";
buttonText = editorShell.GetString("EditMode");
}
else {
EditorDisplayStyle = true;
styleSheet = "chrome://editor/content/EditorContent.css"
buttonText = editorShell.GetString("Preview");
}
//TODO: THIS IS NOT THE RIGHT THING TO DO!
EditorApplyStyleSheet(styleSheet);
button = document.getElementById("DisplayStyleButton");
if (button)
button.setAttribute("value",buttonText);
EditorDisplayMode = mode;
editorShell.SetDisplayMode(mode);
editButton = document.getElementById("EditModeButton");
browserButton = document.getElementById("BrowserModeButton");
var editSelected = 0;
var browserSelected = 0;
if (mode == 0) editSelected = 1;
if (mode == 1) browserSelected = 1;
dump(editButton+browserButton+" Display mode: EditSelected="+editSelected+" BrowserSelected="+browserSelected+"\n");
editButton.setAttribute("selected",Number(editSelected));
browserButton.setAttribute("selected",Number(browserSelected));
}
function EditorPrintPreview()
@ -833,14 +830,6 @@ function OnCreateAlignmentPopup()
// --------------------------- Debug stuff ---------------------------
function EditorApplyStyleSheet(url)
{
if (editorShell)
{
editorShell.ApplyStyleSheet(url);
}
}
function EditorExecuteScript(fileSpec)
{
fileSpec.openStreamForReading();

View File

@ -20,34 +20,15 @@
* Contributor(s):
*/
/* Styles to alter look of things in the Editor content window */
/* Override the browser's pointer cursor over links */
a:link, a:visited, a:active, a:out-of-date {
cursor: text;
}
a:link img, a:visited img, a:active img,
a:out-of-date img, img[usemap], object[usemap] {
cursor: default;
}
/* new feature, not implemented yet
a[name] {
display: inline-block;
min-width: 10px;
width: 10px;
height: 10px;
background-image: url(chrome://editor/skin/images/ED_Left.gif);
border: 1px solid blue;
cursor: default;
}
/* 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 "Browser Preview" mode
* Anything that should never change, like cursors, should be
* place in EditorOverride.css, instead of here.
*/
a[name] {
padding-left: 10px;
padding-left: 20px;
background: url(chrome://editor/skin/images/ED_Left.gif) 5px 50% no-repeat;
}

View File

@ -0,0 +1,40 @@
/*
* 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
* that should NOT be removed when we display in completely WYSIWYG
* "Browser Preview" mode.
* Anything that should change, like appearance of table borders
* and Named Anchors, should be placed in EditorContent.css instead of here.
*/
/* Override the browser's pointer cursor over links */
a:link, a:visited, a:active, a:out-of-date {
cursor: text;
}
a:link img, a:visited img, a:active img,
a:out-of-date img, img[usemap], object[usemap] {
cursor: default;
}

View File

@ -29,6 +29,7 @@ EditorInitPage.html
EditorInitPagePlain.html
EditorStyles1.css
EditorContent.css
EditorOverride.css
editorOverlay.js
editorOverlay.xul
sidebar-editor.rdf

View File

@ -33,6 +33,7 @@ EXPORT_RESOURCE_CONTENT = \
$(srcdir)/EditorInitPagePlain.html \
$(srcdir)/EditorStyles1.css \
$(srcdir)/EditorContent.css \
$(srcdir)/EditorOverride.css \
$(srcdir)/sidebar-editor.rdf \
$(srcdir)/sidebar-editor.xul \
$(srcdir)/sb-bookmarks-panel.xul \

View File

@ -616,9 +616,6 @@
<titledbutton id="linkButton" src="&linkIcon.url;" value="&linkToolbarCmd.label;" onclick="EditorInsertLink()"/>
<titledbutton id="namedAnchorButton" src="&targetIcon.url;" value="&anchorToolbarCmd.label;" onclick="EditorInsertNamedAnchor()"/>
<titledbutton id="DisplayStyleButton" src="&previewIcon.url;" value="&previewToolbarCmd.label;" onclick="EditorToggleDisplayStyle()"/>
<!-- Formatting toolbar items -->
<titledbutton style="width:68pt" id="ParagraphPopupButton" value="&paragraphToolbarMenu.label;" class="popup" align="left" popupanchor="bottomleft">
<observes element="Editor:Paragraph:Format" attribute="format" onbroadcast="onParagraphFormatChange()"/>

View File

@ -27,6 +27,7 @@ install::
$(MAKE_INSTALL) EditorInitPagePlain.html $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorStyles1.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorContent.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EditorOverride.css $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) sidebar-editor.rdf $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) sidebar-editor.xul $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) sb-bookmarks-panel.xul $(DIST)\bin\chrome\editor\content\default
@ -48,6 +49,7 @@ clobber::
rm -f $(DIST)\bin\chrome\editor\content\default\EditorInitPagePlain.html
rm -f $(DIST)\bin\chrome\editor\content\default\EditorStyles1.css
rm -f $(DIST)\bin\chrome\editor\content\default\EditorContent.css
rm -f $(DIST)\bin\chrome\editor\content\default\EditorOverride.css
rm -f $(DIST)\bin\chrome\editor\content\default\sidebar-editor.rdf
rm -f $(DIST)\bin\chrome\editor\content\default\sidebar-editor.xul
rm -f $(DIST)\bin\chrome\editor\content\default\sb-bookmarks-panel.xul

View File

@ -41,3 +41,7 @@
<!ENTITY helpMenu.label "Help">
<!ENTITY aboutCmd.label ".About">
<!-- Display Mode Toolbar -->
<!ENTITY displayMode.label "Display Mode:">
<!ENTITY editModeButton.label "Normal Editing">
<!ENTITY browserModeButton.label "Edit in Browser Layout">

View File

@ -33,6 +33,8 @@ EmptyHREFError=You must enter or choose<br>a location (URL) to create a new link
LinkText=Link text:
EnterLinkText=Enter text to display for the link:
EmptyLinkTextError=You must enter some text for this link.
HeadingsCaption=Headings:
NamedAnchorsCaption=NamedAnchors:
ValidateNumber1=The number you entered (
ValidateNumber2=) is outside of allowed range.<br>Please enter a number between
ValidateNumber3=and

View File

@ -32,12 +32,21 @@ toolbox#EditorToolbars {
box#EditorStatusBar {
min-width: 50px;
border-top: 1px solid darkgray;
}
box#EditorProgessBox {
min-width:30px;
}
box#DisplayModeBar {
margin-top: -2px;
border-top: 1px solid black;
min-width:30px;
/* temporary - testing background */
background-color: inherit; /*#99CCCC; */
}
window.popup {
border: 2px outset;
}
@ -90,6 +99,29 @@ titledbutton#underlineButton {
text-decoration: underline;
}
titledbutton[class~=DisplayModeButton] {
padding: 1px 4px 0px 4px;
margin: 0px;
border-width: 1px;
border: 1px solid transparent;
border-left: 1px solid darkgray;
}
/* Color must be same as above for Display */
div.VerticalSeparator {
height: 100%;
max-width: 1px;
border-left: 1px solid darkgray;
/* margin: 1px; 0px; */
}
titledbutton[class~=DisplayModeButton][selected="1"] {
border: 1px white outset;
padding: 2px 4px 0px 4px;
margin: -2px 0px 0px 0px;
background-color: white;
}
button.PopupButton {
align: left;
margin: 0px;
@ -130,5 +162,17 @@ titledbutton[toggled="1"] {
border: 1px white inset;
}
// Override the browser's pointer cursor over links
a { cursor: default; }
/* Messenger uses this -- IT SHOULD BE IN XUL.CSS */
spring.spacer {
width: 5px;
height: 5px;
}
spring.bigspacer {
width: 10px;
height: 10px;
}

View File

@ -0,0 +1,95 @@
// build attribute list in tree form from element attributes
function BuildCSSAttributeTable()
{
dump("populating CSS Attributes tree\n");
dump("elStyle: " + element.getAttribute("style") + "\n");
var style = element.getAttribute("style");
if(style == undefined || style == "")
{
dump("no style attributes to add\n");
return false;
}
if(style.indexOf(";") == -1) {
if(style.indexOf(":") != -1) {
name = TrimString(nvpairs.split(":")[0]);
value = TrimString(nvpairs.split(":")[1]);
if(!AddCSSAttribute(name,value)) {
dump("Failed to add CSS attribute: " + i + "\n");
}
} else
return false;
}
nvpairs = style.split(";");
for(i = 0; i < nvpairs.length; i++)
{
if(nvpairs[i].indexOf(":") != -1) {
name = TrimString(nvpairs[i].split(":")[0]);
value = TrimString(nvpairs[i].split(":")[1]);
if(!AddCSSAttribute(name,value)) {
dump("Failed to add CSS attribute: " + i + "\n");
}
}
}
}
function AddCSSAttribute(name,value)
{
var treekids = document.getElementById("CSSAList");
if(!CheckAttributeNameSimilarity(name, CSSAttrs)) {
dump("repeated CSS attribute, ignoring\n");
return false;
}
CSSAttrs[CSSAttrs.length] = name;
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(name.toLowerCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
var attrValue = value;
valField.setAttribute("type","text");
valField.setAttribute("id",name.toLowerCase());
valField.setAttribute("value",attrValue);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
return true;
}
// add an attribute to the tree widget
function onAddCSSAttribute()
{
var name = dialog.AddCSSAttributeNameInput.value;
var value = TrimString(dialog.AddCSSAttributeValueInput.value);
if(name == "")
return;
// WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"???
dump(name+"= New Attribute Name - SHOULD BE EMPTY\n");
if(AddCSSAttribute(name,value)) {
dialog.AddCSSAttributeNameInput.value = "";
dialog.AddCSSAttributeValueInput.value = "";
}
dialog.AddCSSAttributeNameInput.focus();
}
// does enabling based on any user input.
function doCSSEnabling()
{
var name = TrimString(dialog.AddCSSAttributeNameInput.value).toLowerCase();
if( name == "" || !CheckAttributeNameSimilarity(name,CSSAttrs)) {
dialog.AddCSSAttribute.setAttribute("disabled","true");
} else {
dialog.AddCSSAttribute.removeAttribute("disabled");
}
}

View File

@ -0,0 +1,95 @@
// build attribute list in tree form from element attributes
function BuildHTMLAttributeTable()
{
dump("NODENAME: " + element.nodeName + "\n");
var nodeMap = element.attributes;
var nodeMapCount = nodeMap.length;
var treekids = document.getElementById("HTMLAList");
if(nodeMapCount > 0) {
for(i = 0; i < nodeMapCount; i++)
{
if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName, JSEAttrs) ||
IsEventHandler(nodeMap[i].nodeName) ||
TrimString(nodeMap[i].nodeName.toLowerCase()) == "style") {
dump("repeated property, JS event handler or style property!\n");
continue; // repeated attribute, ignore this one and go to next
}
HTMLAttrs[i] = nodeMap[i].nodeName;
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(nodeMap[i].nodeName.toUpperCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
var attrValue = element.getAttribute(nodeMap[i].nodeName);
valField.setAttribute("type","text");
valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase());
valField.setAttribute("value",attrValue);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
}
}
}
function AddHTMLAttribute(name,value)
{
HTMLAttrs[HTMLAttrs.length] = name;
var treekids = document.getElementById("HTMLAList");
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(name.toUpperCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
valField.setAttribute("type","text");
valField.setAttribute("id",name);
valField.setAttribute("value",value);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
return true;
}
// add an attribute to the tree widget
function onAddHTMLAttribute()
{
var name = dialog.AddHTMLAttributeNameInput.value;
var value = TrimString(dialog.AddHTMLAttributeValueInput.value);
if(name == "")
return;
// WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"???
dump(name+"= New Attribute Name - SHOULD BE EMPTY\n");
if(AddHTMLAttribute(name,value)) {
dialog.AddHTMLAttributeNameInput.value = "";
dialog.AddHTMLAttributeValueInput.value = "";
}
dialog.AddHTMLAttributeNameInput.focus();
}
// does enabling based on any user input.
function doHTMLEnabling()
{
var name = TrimString(dialog.AddHTMLAttributeNameInput.value).toLowerCase();
if( name == "" || !CheckAttributeNameSimilarity(name,HTMLAttrs)) {
dialog.AddHTMLAttribute.setAttribute("disabled","true");
} else {
dialog.AddHTMLAttribute.removeAttribute("disabled");
}
}

View File

@ -0,0 +1,104 @@
// build attribute list in tree form from element attributes
function BuildJSEAttributeTable()
{
dump("Loading event handlers list...\n");
var nodeMap = element.attributes;
var nodeMapCount = nodeMap.length;
var treekids = document.getElementById("JSEAList");
dump("nmc: " + nodeMapCount + "\n");
if(nodeMapCount > 0) {
for(var i = 0; i < nodeMapCount; i++)
{
if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName, JSEAttrs)) {
dump("repeated JS handler!\n");
continue; // repeated attribute, ignore this one and go to next
}
if(!IsEventHandler(nodeMap[i].nodeName)) {
dump("not an event handler\n");
continue; // attribute isn't an event handler.
}
JSEAttrs[i] = nodeMap[i].nodeName;
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(nodeMap[i].nodeName.toLowerCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
var attrValue = element.getAttribute(nodeMap[i].nodeName);
valField.setAttribute("type","text");
valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase());
valField.setAttribute("value",attrValue);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
}
}
}
function IsEventHandler(which)
{
var handlerName = which.toLowerCase();
var firstTwo = handlerName.substring(0,2);
if(firstTwo == "on")
return true;
else
return false;
}
function AddJSEAttribute(name,value)
{
JSEAttrs[JSEAttrs.length] = name;
var treekids = document.getElementById("JSEAList");
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(name.toLowerCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
valField.setAttribute("type","text");
valField.setAttribute("id",name);
valField.setAttribute("value",value);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
}
// add an attribute to the tree widget
function onAddJSEAttribute()
{
var name = dialog.AddJSEAttributeNameInput.value;
var value = TrimString(dialog.AddJSEAttributeValueInput.value);
if(name == "")
return;
// WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"???
dump(name+"= New Attribute Name - SHOULD BE EMPTY\n");
if(AddJSEAttribute(name,value)) {
dialog.AddJSEAttributeNameInput.value = "";
dialog.AddJSEAttributeValueInput.value = "";
}
dialog.AddJSEAttributeNameInput.focus();
}
// does enabling based on any user input.
function doJSEEnabling()
{
var name = TrimString(dialog.AddJSEAttributeNameInput.value).toLowerCase();
if( name == "" || !CheckAttributeNameSimilarity(name,JSEAttrs)) {
dialog.AddJSEAttribute.setAttribute("disabled","true");
} else {
dialog.AddJSEAttribute.removeAttribute("disabled");
}
}

View File

@ -21,17 +21,18 @@
* Ben Goodger
*/
/************** GLOBALS **************/
var tagname = null;
var element = null;
//Cancel() is in EdDialogCommon.js
// Note: This dialog
var tagname;
var element;
var elAttrs = new Array();
var HTMLAttrs = []; // html attributes
var CSSAttrs = []; // css attributes
var JSEAttrs = []; // js events
// dialog initialization code
/************** INITIALISATION && SETUP **************/
function Startup()
{
dump("START DLG\n");
dump("Welcome to EdAdvancedEdit '99 \n");
// This is the return value for the parent,
// who only needs to know if OK was clicked
window.opener.AdvancedEditOK = false;
@ -59,163 +60,92 @@ function Startup()
// Create dialog object to store controls for easy access
dialog = new Object;
dialog.AddAttributeNameInput = document.getElementById("AddAttributeNameInput");
dialog.AddAttributeValueInput = document.getElementById("AddAttributeValueInput");
dialog.AddAttribute = document.getElementById("AddAttribute");
dialog.AddHTMLAttributeNameInput = document.getElementById("AddHTMLAttributeNameInput");
dialog.AddHTMLAttributeValueInput = document.getElementById("AddHTMLAttributeValueInput");
dialog.AddHTMLAttribute = document.getElementById("AddHTMLAttribute");
dialog.AddCSSAttributeNameInput = document.getElementById("AddCSSAttributeNameInput");
dialog.AddCSSAttributeValueInput = document.getElementById("AddCSSAttributeValueInput");
dialog.AddCSSAttribute = document.getElementById("AddCSSAttribute");
dialog.AddJSEAttributeNameInput = document.getElementById("AddJSEAttributeNameInput");
dialog.AddJSEAttributeValueInput = document.getElementById("AddJSEAttributeValueInput");
dialog.AddJSEAttribute = document.getElementById("AddJSEAttribute");
// build an attribute tree
BuildAttributeTable();
// build the attribute trees
BuildHTMLAttributeTable();
BuildCSSAttributeTable();
BuildJSEAttributeTable();
window.sizeToContent();
}
// build attribute list in tree form from element attributes
function BuildAttributeTable()
{
dump("NODENAME: " + element.nodeName + "\n");
var nodeMap = element.attributes;
var nodeMapCount = nodeMap.length;
var treekids = document.getElementById("attributelist");
if(nodeMapCount > 0) {
for(i = 0; i < nodeMapCount; i++)
{
if(!CheckAttributeNameSimilarity(nodeMap[i].nodeName)) {
dump("repeated attribute!\n");
continue; // repeated attribute, ignore this one and go to next
}
elAttrs[i] = nodeMap[i].nodeName;
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(nodeMap[i].nodeName.toUpperCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
var attrValue = element.getAttribute(nodeMap[i].nodeName);
valField.setAttribute("type","text");
valField.setAttribute("id",nodeMap[i].nodeName.toLowerCase());
valField.setAttribute("value",attrValue);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
}
}
}
// add an attribute to the tree widget
function onAddAttribute()
{
//var name = TrimString(dialog.AddAttributeNameInput.value);
name = dialog.AddAttributeNameInput.value;
var value = TrimString(dialog.AddAttributeValueInput.value);
// Must have a name to be able to add (Value may be empty)
if(name == "")
return;
// WHAT'S GOING ON? NAME ALWAYS HAS A VALUE OF accented "a"???
dump(name+"= New Attribute Name - SHOULD BE EMPTY\n");
// for..in loop, typeof, /^on/ match
elAttrs[elAttrs.length] = name;
// TODO: Add a new text + editbox to the treewidget editing list
var treekids = document.getElementById("attributelist");
var treeitem = document.createElement("treeitem");
var treerow = document.createElement("treerow");
var attrcell = document.createElement("treecell");
var attrcontent = document.createTextNode(name.toUpperCase());
attrcell.appendChild(attrcontent);
treerow.appendChild(attrcell);
var valcell = document.createElement("treecell");
valcell.setAttribute("class","value");
var valField = document.createElement("html:input");
valField.setAttribute("type","text");
valField.setAttribute("id",name);
valField.setAttribute("value",value);
valField.setAttribute("flex","100%");
valField.setAttribute("class","AttributesCell");
valcell.appendChild(valField);
treerow.appendChild(valcell);
treeitem.appendChild(treerow);
treekids.appendChild(treeitem);
dialog.AddAttributeNameInput.value = "";
dialog.AddAttributeValueInput.value = "";
// Set focus to the value edit field just added:
valField.focus();
//Clear the edit boxes
dialog.AddAttributeNameInput.value = "";
dialog.AddAttributeValueInput.value = "";
}
// shut the dialog, apply changes and tidy up
function onOK()
{
dump("in onOK\n")
UpdateObject(); // call UpdateObject fn to update element in document
window.opener.AdvancedEditOK = true;
window.opener.globalElement = element;
return true; // do close the window
}
// updates the element object with values set in the tree.
// TODO: make this work for many objects, so the "vicinity diagram"
// can be used.
// function EdAvancedEdit.js::<UpdateObject>
// Updates the copy of the page object with the data set in this dialog.
function UpdateObject()
{
var treekids = document.getElementById("attributelist");
for(i = 0; i < treekids.childNodes.length; i++)
dump("in UpdateObject\n");
var HTMLAList = document.getElementById("HTMLAList");
var CSSAList = document.getElementById("CSSAList");
var JSEAList = document.getElementById("JSEAList");
// HTML ATTRIBUTES
for(var i = 0; i < HTMLAList.childNodes.length; i++)
{
var item = treekids.childNodes[i];
var name = item.firstChild.firstChild.firstChild.nodeValue;
var item = HTMLAList.childNodes[i];
var name = TrimString(item.firstChild.firstChild.firstChild.nodeValue);
var value = TrimString(item.firstChild.lastChild.firstChild.value);
dump("HTML Attrs: n: " + name + "; v: " + value + "\n");
element.setAttribute(name,value);
}
// CSS ATTRIBUTES
var styleString = "";
for(var i = 0; i < CSSAList.childNodes.length; i++)
{
var item = CSSAList.childNodes[i];
var name = TrimString(item.firstChild.firstChild.firstChild.nodeValue);
var value = TrimString(item.firstChild.lastChild.firstChild.value);
if(name.lastIndexOf(":") == (name.length - 1) && name.length > 0)
name = name.substring(0,name.length-1);
if(value.lastIndexOf(";") == (value.length - 1) && value.length > 0)
value = name.substring(0,value.length-1);
if(i == (CSSAList.childNodes.length - 1))
styleString += name + ": " + value + ";"; // last property
else
styleString += name + ": " + value + "; ";
}
dump("stylestring: ||" + styleString + "||\n");
var name = "width";
if(styleString.length > 0) {
element.setAttribute(name,styleString);
}
// JS EVENT HANDLERS
for(var i = 0; i < JSEAList.childNodes.length; i++)
{
var item = JSEAList.childNodes[i];
name = TrimString(item.firstChild.firstChild.firstChild.nodeValue);
value = TrimString(item.firstChild.lastChild.firstChild.value);
element.setAttribute(name,value);
}
}
// checks to see if any other attributes by the same name as the arg supplied
// already exist.
function CheckAttributeNameSimilarity(attName)
function CheckAttributeNameSimilarity(attName, attArray)
{
for(i = 0; i < elAttrs.length; i++)
for(var i = 0; i < attArray.length; i++)
{
if(attName == elAttrs[i])
if(attName == attArray[i])
return false;
}
return true;
}
// does enabling based on any user input.
function doOverallEnabling()
{
var name = TrimString(dialog.AddAttributeNameInput.value);
if( name == "" || !CheckAttributeNameSimilarity(name)) {
dialog.AddAttribute.setAttribute("disabled","true");
} else {
dialog.AddAttribute.removeAttribute("disabled");
}
}
function doSort()
{
/* UpdateObject();
var treekids = document.getElementById("attributelist");
var nameArray = []
for(i = 0; i < treekids.childNodes.length; i++)
{
var item = treekids.childNodes[i];
nameArray[i] = item.firstChild.firstChild.firstChild.nodeValue;
}
nameArray.sort(posval);
dump("nameArray: " + nameArray + "\n");
nameArray.sort(negval);
dump("nameArray: " + nameArray + "\n");
*/
}

View File

@ -39,51 +39,132 @@
<!-- Methods common to all editor dialogs -->
<html:script language="JavaScript" src="chrome://editor/content/EdDialogCommon.js"/>
<!-- global dialog functions -->
<html:script language="JavaScript" src="chrome://editor/content/EdAdvancedEdit.js"/>
<!-- element page functions -->
<html:script language="JavaScript" src="chrome://editor/content/EdAEHTMLAttributes.js"/>
<html:script language="JavaScript" src="chrome://editor/content/EdAECSSAttributes.js"/>
<html:script language="JavaScript" src="chrome://editor/content/EdAEJSEAttributes.js"/>
<html:script language="JavaScript" src="chrome://global/content/dialogOverlay.js" />
<broadcaster id="args" value=""/>
<keyset id="keyset"/>
<box align="horizontal">
<html:label flex="100%">&currentattributesfor.label;</html:label>
<html:div flex="100%" id="tagLabel"/>
</box>
<spring class="spacer"/>
<box>
<tree id="AttributesTree" class="AttributesTree" flex="100%">
<tabcontrol align="vertical">
<tabbox>
<tab>&tabHTML.label;</tab>
<tab>&tabCSS.label;</tab>
<tab>&tabJSE.label;</tab>
</tabbox>
<tabpanel>
<!-- CSS Properties -->
<box class="tabpanel" flex="100%" align="vertical">
<tree id="HTMLATree" class="AttributesTree" flex="100%">
<treecol width="20%"/>
<treecol width="80%"/>
<treehead>
<treerow>
<treecell onclick="doSort()">&tree.attributeHeader.label;</treecell>
<treecell>&tree.valueHeader.label;</treecell>
</treerow>
<treerow>
<treecell>&tree.attributeHeader.label;</treecell>
<treecell>&tree.valueHeader.label;</treecell>
</treerow>
</treehead>
<treechildren id="attributelist"/>
</tree>
</box>
<treechildren id="HTMLAList"/>
</tree>
<box align="vertical">
<spring class="spacer"/>
<html:fieldset>
<html:legend>&AddHTMLAttributeLabel.label;</html:legend>
<box align="horizontal">
<html:label for="AddHTMLAttributeNameInput"> &AttName.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddHTMLAttributeNameInput" onkeyup="doHTMLEnabling()" onmouseup="doHTMLEnabling()"/></html:div>
<spring class="spacer"/>
</box>
<html:label for="AddHTMLAttributeValueInput"> &AttValue.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddHTMLAttributeValueInput"/></html:div>
<spring flex="100%" class="spacer"/>
<html:div><titledbutton class="hspaced" id="AddHTMLAttribute" onclick="onAddHTMLAttribute()" value="&AddAttributeButton.label;" disabled="true"/></html:div>
</box>
</box>
</html:fieldset>
</box>
</box>
<!-- JavaScript Event Handlers -->
<box class="tabpanel" flex="100%" align="vertical">
<tree id="JSEATree" class="AttributesTree" flex="100%">
<treecol width="20%"/>
<treecol width="80%"/>
<treehead>
<treerow>
<treecell>&tree.attributeHeader.label;</treecell>
<treecell>&tree.valueHeader.label;</treecell>
</treerow>
</treehead>
<treechildren id="JSEAList"/>
</tree>
<box align="vertical">
<spring class="spacer"/>
<html:fieldset>
<html:legend>&AddJSEAttributeLabel.label;</html:legend>
<box align="horizontal">
<html:label for="JSEAddAttributeNameInput"> &AttName.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddJSEAttributeNameInput" onkeyup="doJSEEnabling()" onmouseup="doJSEEnabling()"/></html:div>
<spring class="spacer"/>
</box>
<html:label for="AddJSEAttributeValueInput"> &AttValue.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddJSEAttributeValueInput"/></html:div>
<spring flex="100%" class="spacer"/>
<html:div><titledbutton class="hspaced" id="AddJSEAttribute" onclick="onAddJSEAttribute()" value="&AddAttributeButton.label;" disabled="true"/></html:div>
</box>
</box>
</html:fieldset>
</box>
</box>
<!-- HTML Attributes -->
<box class="tabpanel" flex="100%" align="vertical">
<tree id="CSSATree" class="AttributesTree" flex="100%">
<treecol width="20%"/>
<treecol width="80%"/>
<treehead>
<treerow>
<treecell>&tree.attributeHeader.label;</treecell>
<treecell>&tree.valueHeader.label;</treecell>
</treerow>
</treehead>
<treechildren id="CSSAList"/>
</tree>
<box align="vertical">
<spring class="spacer"/>
<html:fieldset>
<html:legend>&AddCSSAttributeLabel.label;</html:legend>
<box align="horizontal">
<html:label for="AddCSSAttributeNameInput"> &AttName.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddCSSAttributeNameInput" onkeyup="doCSSEnabling()" onmouseup="doCSSEnabling()"/></html:div>
<spring class="spacer"/>
</box>
<html:label for="AddCSSAttributeValueInput"> &AttValue.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddCSSAttributeValueInput"/></html:div>
<spring flex="100%" class="spacer"/>
<html:div><titledbutton class="hspaced" id="AddCSSAttribute" onclick="onAddCSSAttribute()" value="&AddAttributeButton.label;" disabled="true"/></html:div>
</box>
</box>
</html:fieldset>
</box>
</box>
</tabpanel>
</tabcontrol>
<box align="vertical">
<spring class="spacer"/>
<html:fieldset>
<html:legend>&AddAttributeLabel.label;</html:legend>
<box align="horizontal">
<html:label for="AddAttributeNameInput"> &AttName.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddAttributeNameInput" onkeyup="doOverallEnabling()" onmouseup="doOverallEnabling()"/></html:div>
<spring class="spacer"/>
</box>
<html:label for="AddAttributeValueInput"> &AttValue.label;</html:label>
<box align="horizontal" flex="100%">
<html:div><html:input type="text" id="AddAttributeValueInput"/></html:div>
<spring flex="100%" class="spacer"/>
<html:div><titledbutton class="hspaced" id="AddAttribute" onclick="onAddAttribute()" value="&AddAttributeButton.label;" disabled="true"/></html:div>
</box>
</box>
</html:fieldset>
</box>
<box align="horizontal">
<html:div style="margin-top: 0.5em"><titledbutton value="&HTMLReference.label;"/></html:div>
<spring flex="100%"/>

View File

@ -47,7 +47,7 @@
<xul:keyset id="keyset"/>
<xul:box>
<label id="srcMessage"> &sourceEditField.label; </label>
<label id="srcMessage"/>
</xul:box>
<xul:box>
<textarea rows="6" cols="50" id="srcInput" />

View File

@ -61,23 +61,28 @@ function Startup()
// Initialize all widgets with image attributes
InitDialog();
// Set initial number to 1 row, 2 columns:
// Note, these are not attributes on the table,
// so don't put them in InitDialog(),
// else the user's values will be trashed when they use
// the Advanced Edit dialog
dialog.rowsInput.value = 1;
dialog.columnsInput.value = 2;
dialog.rowsInput.focus();
}
// Set dialog widgets with attribute data
// We get them from globalElement copy so this can be used
// by AdvancedEdit(), which is shared by all property dialogs
function InitData()
function InitDialog()
{
// Get default attributes set on the created table:
// Get the width attribute of the element, stripping out "%"
// This sets contents of button text and "percentChar" variable
dialog.widthInput.value = InitPixelOrPercentPopupButton(globalElement, "width", "pixelOrPercentButton");
dialog.borderInput.value = globalElement.getAttribute("border");
// Set default number to 1 row, 2 columns:
dialog.rowsInput.value = 1;
dialog.columnsInput.value = 2;
}
// Get and validate data from widgets.

View File

@ -30,6 +30,11 @@ var hrefInput;
var linkMessage;
var href;
var newLinkText;
var HeadingsIndex = -1;
var NamedAnchorsIndex = -1;
var NamedAnchorsList = 0;
var HNodeArray;
var StartIndexOfHeadings = 1;
// NOTE: Use "href" instead of "a" to distinguish from Named Anchor
// The returned node is has an "a" tagName
@ -144,6 +149,9 @@ function Startup()
// Make a copy to use for AdvancedEdit and onSaveDefault
globalElement = anchorElement.cloneNode(false);
// Get the list of existing named anchors and headings
FillNamedAnchorList();
// Set data for the dialog controls
InitDialog();
@ -192,6 +200,41 @@ function RemoveLink()
hrefInput.value = "";
}
function FillNamedAnchorList()
{
NamedAnchorNodeList = editorShell.editorDocument.anchors;
var headingList = editorShell.editorDocument.getElementsByTagName("h2");
dump(headingList+" Count= "+headingList.length+"\n");
if (headingList.length > 0) {
dump("HELLO\n");
var heading = headingList.item(0);
var range = editorShell.editorDocument.createRange();
range.setStart(heading,0);
var lastChildIndex = heading.childNodes.length;
range.setEnd(heading,lastChildIndex);
var text = range.toString();
dump("Range:"+range+" LastChildIndex = "+lastChildIndex+"\nText: "+text+"\n");
}
}
function SelectNamedAnchor()
{
}
function AnchorNameExists(name)
{
if (NamedAnchorsList) {
for (i=0; i < NamedAnchorsList.length; i++) {
if (NamedAnchorsList[i].name == name)
return true;
}
}
return false;
}
// Get and validate data from widgets.
// Set attributes on globalElement so they can be accessed by AdvancedEdit()
function ValidateData()

View File

@ -50,24 +50,29 @@
<label id="linkTextCaption" for="linkTextMessage"> &LinkText.label; </label>
<div id="linkTextMessage" style="margin-left: 3em">[replace this]</div>
<input type="text" size="25" length="25" id="linkTextInput"/>
<xul:spring class="bigspacer"/>
<xul:spring class="spacer"/>
<fieldset><legend align="left"> &LinkURLFieldset.label; </legend>
<xul:box align="vertical" style="width: 100%; height: 100%">
<xul:box align="horizontal">
<div> &LinkURLEditField.label;</div>
<xul:spring flex="100%"/>
<xul:titledbutton class="hspaced" id="RemoveLink" onclick="RemoveLink()" value="&RemoveLinkButton.label;"/>
<div><xul:titledbutton id="RemoveLink" onclick="RemoveLink()" value="&RemoveLinkButton.label;"/>
</div>
</xul:box>
<xul:box align="horizontal">
<input type="text" size="25" length="25" id="hrefInput"></input>
<xul:spring flex="100%"/>
<!-- The div prevents button from being the same height as the input field -->
<div><xul:titledbutton class="hspaced" id="ChooseFile" onclick="ChooseFile()" value="&LinkChooseFileButton.label;"/></div>
<div><xul:titledbutton id="ChooseFile1" onclick="ChooseFile()" value="&LinkChooseFileButton.label;"/></div>
</xul:box>
</xul:box>
<xul:spring class="spacer"/>
<div>&NamedAnchorMsg.label;</div>
<select id="NamedAnchorList" style="min-width: 15em; max-width: 25em" size="5" onchange="SelectNamedAnchor()"/>
</fieldset>
</xul:box>
<!-- from EdDialogOverlay -->
<xul:box id="AdvancedEditButton"/>
<!-- from global dialogOverlay -->

View File

@ -47,6 +47,8 @@ function Startup()
StartingNumberInput = document.getElementById("StartingNumber");
StartingNumberLabel = document.getElementById("StartingNumberLabel");
// Try to get an existing list
//
InitDialog();
ListStyleList.focus();
}

View File

@ -47,6 +47,8 @@
<label class="spacedtext" for="nameInput"> &anchorNameEditField.label; </label>
<input type="text" id="nameInput" size="30" maxlength="255" />
<div>&noSpacesMsg.label;</div>
<xul:spring class="spacer"/>
<!-- from EdDialogOverlay -->
<xul:box id="AdvancedEditButton"/>
<!-- from global dialogOverlay -->

View File

@ -48,3 +48,6 @@ EdAdvancedEdit.xul
EdAdvancedEdit.js
EdListProps.xul
EdListProps.js
EdAECSSAttributes.js
EdAEHTMLAttributes.js
EdAEJSEAttributes.js

View File

@ -49,6 +49,9 @@ EXPORT_RESOURCE_CONTENT = \
$(srcdir)/EdDialogOverlay.xul \
$(srcdir)/EdAdvancedEdit.xul \
$(srcdir)/EdAdvancedEdit.js \
$(srcdir)/EdAECSSAttributes.js \
$(srcdir)/EdAEHTMLAttributes.js \
$(srcdir)/EdAEJSEAttributes.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -46,6 +46,9 @@ install::
$(MAKE_INSTALL) EdAdvancedEdit.js $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EdListProps.xul $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EdListProps.js $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EdAECSSAttributes.js $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EdAEHTMLAttributes.js $(DIST)\bin\chrome\editor\content\default
$(MAKE_INSTALL) EdAEJSEAttributes.js $(DIST)\bin\chrome\editor\content\default
clobber::
@ -75,3 +78,6 @@ clobber::
rm -f $(DIST)\bin\chrome\editor\content\default\EdAdvancedEdit.js
rm -f $(DIST)\bin\chrome\editor\content\default\EdListProps.xul
rm -f $(DIST)\bin\chrome\editor\content\default\EdListProps.js
rm -f $(DIST)\bin\chrome\editor\content\default\EdAECSSAttributes.js
rm -f $(DIST)\bin\chrome\editor\content\default\EdAEHTMLAttributes.js
rm -f $(DIST)\bin\chrome\editor\content\default\EdAEJSEAttributes.js

View File

@ -30,3 +30,10 @@
<!ENTITY currentattributesfor.label "Current attributes for: ">
<!ENTITY tree.attributeHeader.label "Attribute">
<!ENTITY tree.valueHeader.label "Value">
<!ENTITY tabHTML.label "HTML Attributes">
<!ENTITY tabCSS.label "Style/Appearance">
<!ENTITY tabJSE.label "JavaScript Events">
<!ENTITY AddJSEAttributeLabel.label "Add a JavaScript Event Handler">
<!ENTITY AddHTMLAttributeLabel.label "Add a HTML Attribute">
<!ENTITY AddCSSAttributeLabel.label "Add a CSS/Style Attribute">

View File

@ -22,4 +22,6 @@
<!ENTITY windowTitle.label "Named Anchor Properties">
<!ENTITY anchorNameEditField.label "Anchor Name:">
<!ENTITY noSpacesMsg.label "(Spaces are not allowed.)">

View File

@ -22,6 +22,5 @@
<!-- Window title -->
<!ENTITY windowTitle.label "Insert HTML">
<!ENTITY sourceFieldset.label "HTML Source">
<!ENTITY sourceEditField.label "Enter HTML source to insert:">
<!ENTITY sourceEditField.label "Enter HTML tags and text:">
<!ENTITY example.label "Hello World!">

View File

@ -38,3 +38,7 @@
<!ENTITY LinkURLEditField.label "Enter a web page location or local file:">
<!ENTITY LinkChooseFileButton.label "Choose File...">
<!ENTITY RemoveLinkButton.label "Remove Link">
<!ENTITY NamedAnchorMsg.label "Or select a named anchor or heading:">
<!ENTITY NamedAnchorMsg.label "Create named anchors and/or headings and they will appear in this list">

View File

@ -36,7 +36,130 @@ window{
}
/* THIS SHOULD BE KILLED. NO SPECIAL TITLED BUTTONS SHOULD BE USED! */
tab {
padding: 0px 3px;
}
titledbutton.popup {
list-style-image: url(resource:/res/toolbar/TB_popup.gif);
width: auto;
display: inline;
text-decoration: none;
color: black;
padding: 0px;
margin: 0px;
border: 1px outset white;
font: inherit;
}
titledbutton.popup:hover {
background-color: inherit;
background-image: inherit;
border: 1px outset white;
padding: 0px;
margin: 0px;
color: black;
text-decoration: none;
}
titledbutton.popup:active {
text-decoration: none;
border: 1px outset white;
color: none;
color: black; /* why is color set twice? */
padding: 0px;
margin: 0px;
}
titledbutton.popup[disabled="true"] {
background-color: inherit;
background-image: inherit;
border : 1px solid #999999;
padding: 0px;
margin: 0px;
color: #999999;
text-decoration: none;
image-opacity: 25%;
}
titledbutton.popup[disabled="true"]:hover {
background-color: inherit;
background-image: inherit;
border : 1px solid #999999;
padding: 0px;
margin: 0px;
color: #999999;
text-decoration: none;
}
titledbutton.popup[disabled="true"]:active {
background-color: inherit;
background-image: inherit;
padding: 0px;
margin: 0px;
border : 1px solid #999999;
color: #999999;
text-decoration: none;
}
titledbutton.dropdown {
width: 100%;
display: inline;
text-decoration: none;
color: black;
padding: 0px;
margin: 0px;
border: none;
font: inherit;
background-repeat: no-repeat;
background-color: inherit;
color: black;
}
titledbutton.dropdown:hover {
width: 100%;
display: inline;
text-decoration: none;
color: black;
padding: 0px;
margin: 0px;
border: none;
font: inherit;
background-repeat: no-repeat;
background-color: #666699;
color: white;
}
titledbutton.dropdown:active {
width: 100%;
display: inline;
text-decoration: none;
color: white;
padding: 0px;
margin: 0px;
border: none;
font: inherit;
background-repeat: no-repeat;
background-color: #666699;
}
titledbutton.select {
width: 100%;
@ -87,7 +210,7 @@ titledbutton.select:active {
}
/* Subtle changes, like a little more space, is OK */
/* Don't mess with top and bottom margin! */
titledbutton[class=~spaced] {
@ -95,6 +218,8 @@ titledbutton[class=~spaced] {
margin-right: 5px;
}
/* This assumes 1px is shifted to the border
@ -183,29 +308,30 @@ titledbutton.MsgButton {
margin: 5px;
}
/* What is this for!
menupopup {
font: inherit;
visibility: hidden;
background-color: #CCCCDD;
background-color: inherit;
color: inherit;
border: 1px white outset;
}
*/
select.ComboBox {
/*
EXPERIMENTAL: This ADDS an outset border,
but doesn't affect inset border of item and trigger button!
select.combobox {
font-family: Sans-Serif;
font-size: 8pt;
border-top: 2px;
border-left: 4px;
border-right: 2px;
border-style: outset;
*/
}
select.SpellCheckList, select.SpellCheckLanguage, input.SpellCheckWord {
width: 20em;
/* border-style: inset; */
border-style: inset;
background-color: #CCCCCC; /* not working on Macintosh */
}
@ -501,7 +627,6 @@ spring.bigspacer {
height: 10px;
}
/* From Ben Goodger (originally EdAdvancedEdit.css) */
div.spacer [align~=horizontal] {
border : 1px inset white;
height : 2px;
@ -587,7 +712,7 @@ input.AttributesCell {
border : none;
height : 100%;
}
/*
input.AttributesCell:active {
border: 1px white inset;
}
@ -595,33 +720,15 @@ input.AttributesCell:active {
input.AttributesCell:hover {
border: 1px white inset;
}
*/
/* From Ben Goodger (originally EdTableProps.css) */
box.header {
/* background-color: #7777A4;*/
padding: 2px;
}
box.header > div {
color: #000000;
font-size: 16px;
font-weight: bold;
margin-left: 5px;
}
box.panel {
border: 1px outset white;
width: 350px;
}
fieldset.holder {
width: 350px;
/* Always use the arrow cursor, except in input widget */
*,p,div,legend,box {cursor: pointer;}
button { cursor: crosshair; }
input[type=text], input[type=textarea] {
cursor: text;
treecell input:hover {
background-color : #ECECEC;
font-weight : bold;
border : 2px solid #666699;
}
box.tabpanel {
border: 1px outset #CCCCDD;
padding: 10px;
}