1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SetDocTitleTxn.h"
7 #include "mozilla/dom/Element.h" // for Element
9 #include "nsCOMPtr.h" // for nsCOMPtr, getter_AddRefs, etc
10 #include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
11 #include "nsError.h" // for NS_OK, NS_ERROR_FAILURE, etc
12 #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
13 #include "nsIDOMDocument.h" // for nsIDOMDocument
14 #include "nsIDOMElement.h" // for nsIDOMElement
15 #include "nsIDOMNode.h" // for nsIDOMNode
16 #include "nsIDOMNodeList.h" // for nsIDOMNodeList
17 #include "nsIDOMText.h" // for nsIDOMText
18 #include "nsIDocument.h" // for nsIDocument
19 #include "nsIEditor.h" // for nsIEditor
20 #include "nsIHTMLEditor.h" // for nsIHTMLEditor
21 #include "nsLiteralString.h" // for NS_LITERAL_STRING
23 using namespace mozilla
;
25 // note that aEditor is not refcounted
26 SetDocTitleTxn::SetDocTitleTxn()
32 NS_IMETHODIMP
SetDocTitleTxn::Init(nsIHTMLEditor
*aEditor
,
33 const nsAString
*aValue
)
36 NS_ASSERTION(aEditor
&& aValue
, "null args");
37 if (!aEditor
|| !aValue
) { return NS_ERROR_NULL_POINTER
; }
45 NS_IMETHODIMP
SetDocTitleTxn::DoTransaction(void)
47 return SetDomTitle(mValue
);
50 NS_IMETHODIMP
SetDocTitleTxn::UndoTransaction(void)
52 // No extra work required; the DOM changes alone are enough
56 NS_IMETHODIMP
SetDocTitleTxn::RedoTransaction(void)
58 // No extra work required; the DOM changes alone are enough
62 nsresult
SetDocTitleTxn::SetDomTitle(const nsAString
& aTitle
)
64 nsCOMPtr
<nsIEditor
> editor
= do_QueryInterface(mEditor
);
65 NS_ENSURE_TRUE(editor
, NS_ERROR_FAILURE
);
66 nsCOMPtr
<nsIDOMDocument
> domDoc
;
67 nsresult res
= editor
->GetDocument(getter_AddRefs(domDoc
));
68 NS_ENSURE_TRUE(domDoc
, NS_ERROR_FAILURE
);
70 nsCOMPtr
<nsIDOMNodeList
> titleList
;
71 res
= domDoc
->GetElementsByTagName(NS_LITERAL_STRING("title"), getter_AddRefs(titleList
));
72 NS_ENSURE_SUCCESS(res
, res
);
74 // First assume we will NOT really do anything
75 // (transaction will not be pushed on stack)
78 nsCOMPtr
<nsIDOMNode
>titleNode
;
81 res
= titleList
->Item(0, getter_AddRefs(titleNode
));
82 NS_ENSURE_SUCCESS(res
, res
);
85 // Delete existing child textnode of title node
86 // (Note: all contents under a TITLE node are always in a single text node)
87 nsCOMPtr
<nsIDOMNode
> child
;
88 res
= titleNode
->GetFirstChild(getter_AddRefs(child
));
89 if(NS_FAILED(res
)) return res
;
92 // Save current text as the undo value
93 nsCOMPtr
<nsIDOMCharacterData
> textNode
= do_QueryInterface(child
);
96 textNode
->GetData(mUndoValue
);
98 // If title text is identical to what already exists,
99 // quit now (mIsTransient is now TRUE)
100 if (mUndoValue
== aTitle
)
103 res
= editor
->DeleteNode(child
);
104 if(NS_FAILED(res
)) return res
;
109 // We didn't return above, thus we really will be changing the title
110 mIsTransient
= false;
112 // Get the <HEAD> node, create a <TITLE> and insert it under the HEAD
113 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(domDoc
);
114 NS_ENSURE_STATE(document
);
116 dom::Element
* head
= document
->GetHeadElement();
117 NS_ENSURE_STATE(head
);
119 bool newTitleNode
= false;
120 uint32_t newTitleIndex
= 0;
124 // Didn't find one above: Create a new one
125 nsCOMPtr
<nsIDOMElement
>titleElement
;
126 res
= domDoc
->CreateElement(NS_LITERAL_STRING("title"), getter_AddRefs(titleElement
));
127 NS_ENSURE_SUCCESS(res
, res
);
128 NS_ENSURE_TRUE(titleElement
, NS_ERROR_FAILURE
);
130 titleNode
= do_QueryInterface(titleElement
);
133 // Get index so we append new title node after all existing HEAD children.
134 newTitleIndex
= head
->GetChildCount();
137 // Append a text node under the TITLE
138 // only if the title text isn't empty
139 if (titleNode
&& !aTitle
.IsEmpty())
141 nsCOMPtr
<nsIDOMText
> textNode
;
142 res
= domDoc
->CreateTextNode(aTitle
, getter_AddRefs(textNode
));
143 NS_ENSURE_SUCCESS(res
, res
);
144 nsCOMPtr
<nsIDOMNode
> newNode
= do_QueryInterface(textNode
);
145 NS_ENSURE_TRUE(newNode
, NS_ERROR_FAILURE
);
149 // Not undoable: We will insert newTitleNode below
150 nsCOMPtr
<nsIDOMNode
> resultNode
;
151 res
= titleNode
->AppendChild(newNode
, getter_AddRefs(resultNode
));
155 // This is an undoable transaction
156 res
= editor
->InsertNode(newNode
, titleNode
, 0);
158 NS_ENSURE_SUCCESS(res
, res
);
163 // Undoable transaction to insert title+text together
164 res
= editor
->InsertNode(titleNode
, head
->AsDOMNode(), newTitleIndex
);
169 NS_IMETHODIMP
SetDocTitleTxn::GetTxnDescription(nsAString
& aString
)
171 aString
.AssignLiteral("SetDocTitleTxn: ");
176 NS_IMETHODIMP
SetDocTitleTxn::GetIsTransient(bool *aIsTransient
)
178 NS_ENSURE_TRUE(aIsTransient
, NS_ERROR_NULL_POINTER
);
179 *aIsTransient
= mIsTransient
;