diff --git a/mozilla/editor/ui/composer/content/EditorContent.css b/mozilla/editor/ui/composer/content/EditorContent.css
index 1e7af7766e3..d212d100c07 100644
--- a/mozilla/editor/ui/composer/content/EditorContent.css
+++ b/mozilla/editor/ui/composer/content/EditorContent.css
@@ -61,6 +61,19 @@ table[empty-cells],
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;
+}
+
/* smileys */
span.moz-smiley-s1,
span.moz-smiley-s2,
diff --git a/mozilla/editor/ui/composer/locale/en-US/editor.properties b/mozilla/editor/ui/composer/locale/en-US/editor.properties
index 5e5921e205c..532e785d798 100644
--- a/mozilla/editor/ui/composer/locale/en-US/editor.properties
+++ b/mozilla/editor/ui/composer/locale/en-US/editor.properties
@@ -20,6 +20,7 @@ MoreAttributes=More Attributes
FewerAttributes=Fewer Attributes
MoreProperties=More Properties
FewerProperties=Fewer Properties
+PropertiesAccessKey=P
None=None
none=none
OpenHTMLFile=Open HTML File
diff --git a/mozilla/editor/ui/dialogs/content/EdButtonProps.js b/mozilla/editor/ui/dialogs/content/EdButtonProps.js
index 630cc716043..69f813527cd 100644
--- a/mozilla/editor/ui/dialogs/content/EdButtonProps.js
+++ b/mozilla/editor/ui/dialogs/content/EdButtonProps.js
@@ -61,8 +61,10 @@ function Startup()
};
// Get a single selected button element
- var tagName = "button";
- buttonElement = editor.getSelectedElement(tagName);
+ const kTagName = "button";
+ try {
+ buttonElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
if (buttonElement)
// We found an element and don't need to insert one
@@ -73,8 +75,10 @@ function Startup()
// We don't have an element selected,
// so create one with default attributes
+ try {
+ buttonElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
- buttonElement = editor.createElementWithDefaults(tagName);
if (!buttonElement)
{
dump("Failed to get selected element or create a new one!\n");
@@ -120,7 +124,7 @@ function InitDialog()
function RemoveButton()
{
- RemoveElementKeepingChildren(buttonElement);
+ RemoveContainer(buttonElement);
SaveWindowLocation();
window.close();
}
@@ -158,10 +162,13 @@ function onAccept()
editor.cloneAttributes(buttonElement, globalElement);
- if (insertNew && !InsertElementAroundSelection(buttonElement))
+ if (insertNew)
{
- buttonElement.innerHTML = editor.outputToString("text/html", 1); // OutputSelectionOnly (see nsIDocumentEncoder.h)
- editor.insertElementAtSelection(buttonElement, true);
+ if (!InsertElementAroundSelection(buttonElement))
+ {
+ buttonElement.innerHTML = editor.outputToString("text/html", 1); // OutputSelectionOnly (see nsIDocumentEncoder.h)
+ editor.insertElementAtSelection(buttonElement, true);
+ }
}
SaveWindowLocation();
diff --git a/mozilla/editor/ui/dialogs/content/EdButtonProps.xul b/mozilla/editor/ui/dialogs/content/EdButtonProps.xul
index 6359ac0f4cc..41e5d505e4c 100644
--- a/mozilla/editor/ui/dialogs/content/EdButtonProps.xul
+++ b/mozilla/editor/ui/dialogs/content/EdButtonProps.xul
@@ -56,11 +56,11 @@
-
+
-
+
@@ -70,11 +70,11 @@
-
+
-
+
@@ -86,16 +86,16 @@
-
+
-
+
-
+
@@ -106,7 +106,7 @@
-
+
diff --git a/mozilla/editor/ui/dialogs/content/EdDialogCommon.js b/mozilla/editor/ui/dialogs/content/EdDialogCommon.js
index b01ff2a4cdf..af409bc4c98 100644
--- a/mozilla/editor/ui/dialogs/content/EdDialogCommon.js
+++ b/mozilla/editor/ui/dialogs/content/EdDialogCommon.js
@@ -390,6 +390,7 @@ function InitMoreFewer()
// onMoreFewer will toggle it and redraw the dialog
SeeMore = (gDialog.MoreFewerButton.getAttribute("more") != "1");
onMoreFewer();
+ gDialog.MoreFewerButton.setAttribute("accesskey",GetString("PropertiesAccessKey"));
}
function onMoreFewer()
@@ -781,199 +782,194 @@ var NotAnInlineParent = {
UL: true
};
-function nodeDepth(node)
+function nodeIsBreak(editor, node)
{
- for (var depth = 0; node != null; depth++)
- node = node.parentNode;
- return depth;
+ return !node || node.localName == 'BR' || editor.nodeIsBlock(node);
}
-function nthParent(node, n)
-{
- for (; n > 0; n--)
- node = node.parentNode;
- return node;
-}
-
-function nodeIsBlock(node)
-{
- // HR doesn't count because it's not a container
- var editor = GetCurrentEditor();
- return !editor || !node ||
- (node.localName != 'HR' && editor.nodeIsBlock(node));
-}
-
-/* Ugly code alert! If only I could do this:
- * var range = editor.selection.flattenRange(range); // ensure anchorNode == parentNode
- * if (editor.isInlineRange(range) && editor.nodeIsBlock(node)) return false;
- * while (!editor.containmentAllowed(range.anchorNode, element))
- * range = editor.parentRangeOf(range);
- * editor.insertNodeAtRange(element, range);
- * return true;
- */
function InsertElementAroundSelection(element)
{
var editor = GetCurrentEditor();
+ editor.beginTransaction();
try {
- // We need to find a suitable container for the element.
- // First get the selection
- var anchorParent = editor.selection.anchorNode;
- if (!anchorParent.localName)
- var anchorSelected = true;
- else if (editor.selection.anchorOffset < anchorParent.childNodes.length)
- var anchor = anchorParent.childNodes[editor.selection.anchorOffset];
- var focusParent = editor.selection.focusNode;
- if (!focusParent.localName)
- var focusSelected = true;
- else if (editor.selection.focusOffset < focusParent.childNodes.length)
- var focus = focusParent.childNodes[editor.selection.focusOffset];
-
- // Find the common ancestor
- var anchorDepth = nodeDepth(anchorParent);
- var focusDepth = nodeDepth(focusParent);
- if (anchorDepth > focusDepth)
- {
- anchor = nthParent(anchorParent, anchorDepth - focusDepth - 1);
- anchorParent = anchor.parentNode;
- anchorSelected = true;
- }
- else if (anchorDepth < focusDepth)
- {
- focus = nthParent(focusParent, focusDepth - anchorDepth - 1);
- focusParent = focus.parentNode;
- focusSelected = true;
- }
- var ordered = false;
- while (anchorParent != focusParent)
- {
- anchor = anchorParent;
- anchorParent = anchor.parentNode;
- focus = focusParent;
- focusParent = focus.parentNode;
- anchorSelected = focusSelected = true;
- }
-
- // The common ancestor may not be suitable, so find a suitable one.
- if (editor.nodeIsBlock(element))
- {
- // Block element parent must be a valid block
- while (!(anchorParent.localName in IsBlockParent))
- {
- anchor = focus = anchorParent;
- anchorSelected = focusSelected = true;
- anchorParent = anchor.parentNode;
- ordered = true;
- }
- }
+ // First get the selection as a single range
+ var range, start, end, offset;
+ var count = editor.selection.rangeCount;
+ if (count == 1)
+ range = editor.selection.getRangeAt(0).cloneRange();
else
{
- // Inline element parent must not be an invalid block
- while (anchorParent.localName in NotAnInlineParent)
- {
- anchor = focus = anchorParent;
- anchorSelected = focusSelected = true;
- anchorParent = anchor.parentNode;
- ordered = true;
- }
+ range = editor.document.createRange();
+ start = editor.selection.getRangeAt(0)
+ range.setStart(start.startContainer, start.startOffset);
+ end = editor.selection.getRangeAt(--count);
+ range.setEnd(end.endContainer, end.endOffset);
}
- // We now have an ancestor to hold the element
- // and a range of child nodes to move into the element
- if (anchor != focus)
+ // Flatten the selection to child nodes of the common ancestor
+ while (range.startContainer != range.commonAncestorContainer)
+ range.setStartBefore(range.startContainer);
+ while (range.endContainer != range.commonAncestorContainer)
+ range.setEndAfter(range.endContainer);
+
+ if (editor.nodeIsBlock(element))
+ // Block element parent must be a valid block
+ while (!(range.commonAncestorContainer.localName in IsBlockParent))
+ range.selectNode(range.commonAncestorContainer);
+ else
{
- if (!ordered)
- {
- // Ensure anchor <= focus
- for (var node = anchorParent.firstChild; node != anchor; node = node.nextSibling)
- {
- if (node == focus)
- {
- focus = anchor;
- anchor = node;
- focusSelected = anchorSelected;
+ // Fail if we're not inserting a block (use setInlineProperty instead)
+ if (!nodeIsBreak(editor, range.commonAncestorContainer))
+ return false;
+ else if (range.commonAncestorContainer.localName in NotAnInlineParent)
+ // Inline element parent must not be an invalid block
+ do range.selectNode(range.commonAncestorContainer);
+ while (range.commonAncestorContainer.localName in NotAnInlineParent);
+ else
+ // Further insert block check
+ for (var i = range.startOffset; ; i++)
+ if (i == range.endOffset)
+ return false;
+ else if (nodeIsBreak(editor, range.commonAncestorContainer.childNodes[i]))
break;
- }
- }
- }
- if (focus && !focusSelected)
- focus = focus.previousSibling;
- }
- if (!editor.nodeIsBlock(element))
- {
- // Fail if we're not inserting a block
- if (!anchor) return false;
- for (node = anchor; ; node = node.nextSibling)
- if (!node)
- return false;
- else if (nodeIsBlock(node))
- break;
- else if (node == focus)
- return false;
}
// The range may be contained by body text, which should all be selected.
- if (!nodeIsBlock(anchor))
- while (!nodeIsBlock(anchor.previousSibling))
- anchor = anchor.previousSibling;
- if (!nodeIsBlock(focus))
- while (!nodeIsBlock(focus.nextSibling))
- focus = focus.nextSibling;
- } catch (e) {return false;}
-
- editor.beginTransaction();
- try {
- var anchorOffset = 0;
- // Calculate the insertion point for the undoable insertNode method
- if (!anchor)
- anchor = anchorParent.firstChild;
- else
- for (node = anchorParent.firstChild; node != anchor; node = node.nextSibling)
- anchorOffset++;
- editor.insertNode(element, anchorParent, anchorOffset, true);
- // Move all the old child nodes to the element
- // Use editor methods in case of text nodes
- while (anchor)
+ offset = range.startOffset;
+ start = range.startContainer.childNodes[offset];
+ if (!nodeIsBreak(editor, start))
{
- node = anchor.nextSibling;
- editor.deleteNode(anchor);
- editor.insertNode(anchor, element, element.childNodes.length);
- if (anchor == focus) break;
- anchor = node;
+ while (!nodeIsBreak(editor, start.previousSibling))
+ {
+ start = start.previousSibling;
+ offset--;
+ }
+ }
+ end = range.endContainer.childNodes[range.endOffset];
+ if (end && !nodeIsBreak(editor, end.previousSibling))
+ {
+ while (!nodeIsBreak(editor, end))
+ end = end.nextSibling;
+ }
+
+ // Now insert the node
+ editor.insertNode(element, range.commonAncestorContainer, offset, true);
+ offset = element.childNodes.length;
+ if (!editor.nodeIsBlock(element))
+ editor.setShouldTxnSetSelection(false);
+
+ // Move all the old child nodes to the element
+ var empty = true;
+ while (start != end)
+ {
+ var next = start.nextSibling;
+ editor.deleteNode(start);
+ editor.insertNode(start, element, element.childNodes.length);
+ empty = false;
+ start = next;
+ }
+ if (!editor.nodeIsBlock(element))
+ editor.setShouldTxnSetSelection(true);
+ else
+ {
+ // Also move a trailing
+ if (start && start.localName == 'BR')
+ {
+ editor.deleteNode(start);
+ editor.insertNode(start, element, element.childNodes.length);
+ empty = false;
+ }
+ // Still nothing? Insert a so the node is not empty
+ if (empty)
+ editor.insertNode(editor.createElementWithDefaults("br"), element, element.childNodes.length);
+
+ // Hack to set the selection just inside the element
+ editor.insertNode(editor.document.createTextNode(""), element, offset);
}
}
- catch (ex) {}
+ finally {
+ editor.endTransaction();
+ }
- editor.endTransaction();
return true;
}
-// Should I set the selection to the element, then insert HTML the element's innerHTML?
-// I would prefer to say editor.deleteNode(element, FLAG_TO_KEEP_CHILD_NODES);
-function RemoveElementKeepingChildren(element)
+function nodeIsBlank(node)
+{
+ return node && node.NODE_TYPE == Node.TEXT_NODE && !/\S/.test(node.data);
+}
+
+function nodeBeginsBlock(node)
+{
+ while (nodeIsBlank(node))
+ node = node.nextSibling;
+ return nodeIsBlock(node);
+}
+
+function nodeEndsBlock(node)
+{
+ while (nodeIsBlank(node))
+ node = node.previousSibling;
+ return nodeIsBlock(node);
+}
+
+// C++ function isn't exposed to JS :-(
+function RemoveBlockContainer(element)
{
var editor = GetCurrentEditor();
+ editor.beginTransaction();
try {
- editor.beginTransaction();
- if (element.firstChild)
- {
- // Use editor methods in case of text nodes
- var parent = element.parentNode;
- var offset = 0;
- for (var node = parent.firstChild; node != element; node = node.nextSibling)
- offset++;
- while ((node = element.firstChild))
- {
- editor.deleteNode(node);
- editor.insertNode(node, parent, offset++);
- }
+ var range = editor.document.createRange();
+ range.selectNode(element);
+ var offset = range.startOffset;
+ var parent = element.parentNode;
+
+ // May need to insert a break after the removed element
+ if (!nodeBeginsBlock(editor, element.nextSibling) &&
+ !nodeEndsBlock(editor, element.lastChild))
+ editor.insertNode(editor.createElementWithDefaults("br"), parent, range.endOffset);
+
+ // May need to insert a break before the removed element, or if it was empty
+ if (!nodeEndsBlock(editor, element.previousSibling) &&
+ !nodeBeginsBlock(editor, element.firstChild || element.nextSibling))
+ editor.insertNode(editor.createElementWithDefaults("br"), parent, offset++);
+
+ // Now remove the element
+ editor.deleteNode(element);
+
+ // Need to copy the contained nodes?
+ for (var i = 0; i < element.childNodes.length; i++)
+ editor.insertNode(element.childNodes[i].cloneNode(true), parent, offset++);
+ }
+ finally {
+ editor.endTransaction();
+ }
+}
+
+// C++ function isn't exposed to JS :-(
+function RemoveContainer(element)
+{
+ var editor = GetCurrentEditor();
+ editor.beginTransaction();
+
+ try {
+ var range = editor.document.createRange();
+ var parent = element.parentNode;
+ // Allow for automatic joining of text nodes
+ // so we can't delete the container yet
+ // so we need to copy the contained nodes
+ for (var i = 0; i < element.childNodes.length; i++) {
+ range.selectNode(element);
+ editor.insertNode(element.childNodes[i].cloneNode(true), parent, range.startOffset);
}
+ // Now remove the element
editor.deleteNode(element);
}
- catch (ex) {}
-
- editor.endTransaction();
+ finally {
+ editor.endTransaction();
+ }
}
function FillLinkMenulist(linkMenulist, headingsArray)
diff --git a/mozilla/editor/ui/dialogs/content/EdFieldSetProps.js b/mozilla/editor/ui/dialogs/content/EdFieldSetProps.js
index 3e984ea91da..8d120f13385 100644
--- a/mozilla/editor/ui/dialogs/content/EdFieldSetProps.js
+++ b/mozilla/editor/ui/dialogs/content/EdFieldSetProps.js
@@ -62,9 +62,9 @@ function Startup()
// Find a selected fieldset, or if one is at start or end of selection.
fieldsetElement = editor.getSelectedElement(kTagName);
if (!fieldsetElement)
- fieldsetElement = editor.getElementOrParentBykTagName(kTagName, editor.selection.anchorNode);
+ fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
if (!fieldsetElement)
- fieldsetElement = editor.getElementOrParentBykTagName(kTagName, editor.selection.focusNode);
+ fieldsetElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
} catch (e) {}
if (fieldsetElement)
@@ -95,8 +95,7 @@ function Startup()
{
newLegend = false;
var range = editor.document.createRange();
- range.setStart(legendElement, 0);
- range.setEnd(legendElement, legendElement.childNodes.length);
+ range.selectNode(legendElement);
gDialog.legendText.value = range.toString();
if (/s needed
- RemoveElementKeepingChildren(fieldsetElement);
+ editor.deleteNode(legendElement);
+ RemoveBlockContainer(fieldsetElement);
} finally {
editor.endTransaction();
}
@@ -184,9 +181,15 @@ function onAccept()
editor.cloneAttributes(legendElement, globalElement);
if (insertNew)
+ {
+ if (gDialog.legendText.value)
+ {
+ fieldsetElement.appendChild(legendElement);
+ legendElement.appendChild(editor.document.createTextNode(gDialog.legendText.value));
+ }
InsertElementAroundSelection(fieldsetElement);
-
- if (gDialog.editText.checked)
+ }
+ else if (gDialog.editText.checked)
{
editor.setShouldTxnSetSelection(false);
@@ -199,7 +202,7 @@ function onAccept()
editor.insertNode(editor.document.createTextNode(gDialog.legendText.value), legendElement, 0);
}
else if (!newLegend)
- editor.DeleteNode(legendElement);
+ editor.deleteNode(legendElement);
editor.setShouldTxnSetSelection(true);
}
diff --git a/mozilla/editor/ui/dialogs/content/EdFieldSetProps.xul b/mozilla/editor/ui/dialogs/content/EdFieldSetProps.xul
index 7e1822e801c..51646ad0515 100644
--- a/mozilla/editor/ui/dialogs/content/EdFieldSetProps.xul
+++ b/mozilla/editor/ui/dialogs/content/EdFieldSetProps.xul
@@ -56,16 +56,16 @@
-
+
-
-
+
-
+
@@ -81,7 +81,7 @@
-
+
diff --git a/mozilla/editor/ui/dialogs/content/EdFormProps.js b/mozilla/editor/ui/dialogs/content/EdFormProps.js
index 28e4bbd6462..887c6c25167 100644
--- a/mozilla/editor/ui/dialogs/content/EdFormProps.js
+++ b/mozilla/editor/ui/dialogs/content/EdFormProps.js
@@ -44,6 +44,7 @@ function Startup()
var editor = GetCurrentEditor();
if (!editor)
{
+ dump("Failed to get active editor!\n");
window.close();
return;
}
@@ -60,12 +61,14 @@ function Startup()
gDialog.RemoveForm = document.getElementById("RemoveForm")
// Get a single selected form element
- var tagName = "form";
- formElement = editor.getSelectedElement(tagName);
- if (!formElement)
- formElement = editor.getElementOrParentByTagName(tagName, editor.selection.anchorNode);
- if (!formElement)
- formElement = editor.getElementOrParentByTagName(tagName, editor.selection.focusNode);
+ const kTagName = "form";
+ try {
+ formElement = editor.getSelectedElement(kTagName);
+ if (!formElement)
+ formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.anchorNode);
+ if (!formElement)
+ formElement = editor.getElementOrParentByTagName(kTagName, editor.selection.focusNode);
+ } catch (e) {}
if (formElement)
{
@@ -80,8 +83,10 @@ function Startup()
// We don't have an element selected,
// so create one with default attributes
+ try {
+ formElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
- formElement = editor.createElementWithDefaults(tagName);
if (!formElement)
{
dump("Failed to get selected element or create a new one!\n");
@@ -112,7 +117,7 @@ function InitDialog()
function RemoveForm()
{
- RemoveElementKeepingChildren(formElement);
+ RemoveBlockContainer(formElement);
SaveWindowLocation();
window.close();
}
diff --git a/mozilla/editor/ui/dialogs/content/EdFormProps.xul b/mozilla/editor/ui/dialogs/content/EdFormProps.xul
index 91fdb4ead36..90d8f5193a2 100644
--- a/mozilla/editor/ui/dialogs/content/EdFormProps.xul
+++ b/mozilla/editor/ui/dialogs/content/EdFormProps.xul
@@ -56,19 +56,19 @@
-
+
-
+
-
+
-
+
@@ -83,7 +83,7 @@
-
+
@@ -93,7 +93,7 @@
-
+
@@ -110,7 +110,7 @@
-
+
diff --git a/mozilla/editor/ui/dialogs/content/EdInputProps.js b/mozilla/editor/ui/dialogs/content/EdInputProps.js
index 3bfcd2e154b..b6b6b0c5dcb 100644
--- a/mozilla/editor/ui/dialogs/content/EdInputProps.js
+++ b/mozilla/editor/ui/dialogs/content/EdInputProps.js
@@ -44,6 +44,7 @@ function Startup()
var editor = GetCurrentEditor();
if (!editor)
{
+ dump("Failed to get active editor!\n");
window.close();
return;
}
@@ -72,8 +73,10 @@ function Startup()
};
// Get a single selected input element
- var tagName = "input";
- inputElement = editor.getSelectedElement(tagName);
+ const kTagName = "input";
+ try {
+ inputElement = editor.getSelectedElement(kTagName);
+ } catch (e) {}
if (inputElement)
// We found an element and don't need to insert one
@@ -84,8 +87,10 @@ function Startup()
// We don't have an element selected,
// so create one with default attributes
+ try {
+ inputElement = editor.createElementWithDefaults(kTagName);
+ } catch (e) {}
- inputElement = editor.createElementWithDefaults(tagName);
if (!inputElement)
{
dump("Failed to get selected element or create a new one!\n");
diff --git a/mozilla/editor/ui/dialogs/content/EdInputProps.xul b/mozilla/editor/ui/dialogs/content/EdInputProps.xul
index c611a9db01f..9993c8cfff1 100644
--- a/mozilla/editor/ui/dialogs/content/EdInputProps.xul
+++ b/mozilla/editor/ui/dialogs/content/EdInputProps.xul
@@ -56,7 +56,7 @@
-