зеркало из https://github.com/mozilla/gecko-dev.git
Bug 613662 - Implement insertAdjacentHTML. r=bzbarsky.
This commit is contained in:
Родитель
783a7d246e
Коммит
3aa0ce16e6
|
@ -721,6 +721,26 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML)
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLElement::FireMutationEventsForDirectParsing(nsIDocument* aDoc,
|
||||
nsIContent* aDest,
|
||||
PRInt32 aOldChildCount)
|
||||
{
|
||||
// Fire mutation events. Optimize for the case when there are no listeners
|
||||
PRInt32 newChildCount = aDest->GetChildCount();
|
||||
if (newChildCount && nsContentUtils::
|
||||
HasMutationListeners(aDoc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsAutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
|
||||
NS_ASSERTION(newChildCount - aOldChildCount >= 0,
|
||||
"What, some unexpected dom mutation has happened?");
|
||||
childNodes.SetCapacity(newChildCount - aOldChildCount);
|
||||
for (nsINode::ChildIterator iter(aDest); !iter.IsDone(); iter.Next()) {
|
||||
childNodes.AppendElement(iter);
|
||||
}
|
||||
nsGenericElement::FireNodeInserted(aDoc, aDest, childNodes);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
||||
{
|
||||
|
@ -755,19 +775,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
|||
eCompatibility_NavQuirks,
|
||||
PR_TRUE);
|
||||
// HTML5 parser has notified, but not fired mutation events.
|
||||
// Fire mutation events. Optimize for the case when there are no listeners
|
||||
PRInt32 newChildCount = GetChildCount();
|
||||
if (newChildCount && nsContentUtils::
|
||||
HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsAutoTArray<nsCOMPtr<nsIContent>, 50> childNodes;
|
||||
NS_ASSERTION(newChildCount - oldChildCount >= 0,
|
||||
"What, some unexpected dom mutation has happened?");
|
||||
childNodes.SetCapacity(newChildCount - oldChildCount);
|
||||
for (nsINode::ChildIterator iter(this); !iter.IsDone(); iter.Next()) {
|
||||
childNodes.AppendElement(iter);
|
||||
}
|
||||
nsGenericElement::FireNodeInserted(doc, this, childNodes);
|
||||
}
|
||||
FireMutationEventsForDirectParsing(doc, this, oldChildCount);
|
||||
} else {
|
||||
rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML,
|
||||
PR_TRUE,
|
||||
|
@ -781,6 +789,104 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
|||
return rv;
|
||||
}
|
||||
|
||||
enum nsAdjacentPosition {
|
||||
eBeforeBegin,
|
||||
eAfterBegin,
|
||||
eBeforeEnd,
|
||||
eAfterEnd
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::InsertAdjacentHTML(const nsAString& aPosition,
|
||||
const nsAString& aText)
|
||||
{
|
||||
nsAdjacentPosition position;
|
||||
if (aPosition.LowerCaseEqualsLiteral("beforebegin")) {
|
||||
position = eBeforeBegin;
|
||||
} else if (aPosition.LowerCaseEqualsLiteral("afterbegin")) {
|
||||
position = eAfterBegin;
|
||||
} else if (aPosition.LowerCaseEqualsLiteral("beforeend")) {
|
||||
position = eBeforeEnd;
|
||||
} else if (aPosition.LowerCaseEqualsLiteral("afterend")) {
|
||||
position = eAfterEnd;
|
||||
} else {
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> destination;
|
||||
if (position == eBeforeBegin || position == eAfterEnd) {
|
||||
destination = GetParent();
|
||||
if (!destination) {
|
||||
return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
|
||||
}
|
||||
} else {
|
||||
destination = this;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetOwnerDoc();
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
// Needed when insertAdjacentHTML is used in combination with contenteditable
|
||||
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE);
|
||||
|
||||
// Batch possible DOMSubtreeModified events.
|
||||
mozAutoSubtreeModified subtree(doc, nsnull);
|
||||
|
||||
// Parse directly into destination if possible
|
||||
if (doc->IsHTML() &&
|
||||
(position == eBeforeEnd ||
|
||||
(position == eAfterEnd && !GetNextSibling()) ||
|
||||
(position == eAfterBegin && !GetFirstChild()))) {
|
||||
PRInt32 oldChildCount = destination->GetChildCount();
|
||||
PRInt32 contextNs = destination->GetNameSpaceID();
|
||||
nsIAtom* contextLocal = destination->Tag();
|
||||
if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) {
|
||||
// For compat with IE6 through IE9. Willful violation of HTML5 as of
|
||||
// 2011-04-06. CreateContextualFragment does the same already.
|
||||
// Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434
|
||||
contextLocal = nsGkAtoms::body;
|
||||
}
|
||||
nsContentUtils::ParseFragmentHTML(aText,
|
||||
destination,
|
||||
contextLocal,
|
||||
contextNs,
|
||||
doc->GetCompatibilityMode() ==
|
||||
eCompatibility_NavQuirks,
|
||||
PR_TRUE);
|
||||
// HTML5 parser has notified, but not fired mutation events.
|
||||
FireMutationEventsForDirectParsing(doc, destination, oldChildCount);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// couldn't parse directly
|
||||
nsCOMPtr<nsIDOMDocumentFragment> df;
|
||||
nsresult rv = nsContentUtils::CreateContextualFragment(destination,
|
||||
aText,
|
||||
PR_TRUE,
|
||||
getter_AddRefs(df));
|
||||
nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
switch (position) {
|
||||
case eBeforeBegin:
|
||||
destination->InsertBefore(fragment, this, &rv);
|
||||
break;
|
||||
case eAfterBegin:
|
||||
static_cast<nsINode*>(this)->InsertBefore(fragment, GetFirstChild(), &rv);
|
||||
break;
|
||||
case eBeforeEnd:
|
||||
static_cast<nsINode*>(this)->AppendChild(fragment, &rv);
|
||||
break;
|
||||
case eAfterEnd:
|
||||
destination->InsertBefore(fragment, GetNextSibling(), &rv);
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Bad position.");
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
|
||||
{
|
||||
|
|
|
@ -135,6 +135,8 @@ public:
|
|||
nsresult GetOffsetParent(nsIDOMElement** aOffsetParent);
|
||||
virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
|
||||
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
|
||||
virtual nsresult InsertAdjacentHTML(const nsAString& aPosition,
|
||||
const nsAString& aText);
|
||||
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
|
||||
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetHidden(),
|
||||
// SetHidden(), GetSpellcheck(), SetSpellcheck(), and GetDraggable() such that
|
||||
|
@ -571,6 +573,18 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Fire mutation events for changes caused by parsing directly into a
|
||||
* context node.
|
||||
*
|
||||
* @param aDoc the document of the node
|
||||
* @param aDest the destination node that got stuff appended to it
|
||||
* @param aOldChildCount the number of children the node had before parsing
|
||||
*/
|
||||
void FireMutationEventsForDirectParsing(nsIDocument* aDoc,
|
||||
nsIContent* aDest,
|
||||
PRInt32 aOldChildCount);
|
||||
|
||||
void RegUnRegAccessKey(PRBool aDoReg);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
interface nsIDOMDOMStringMap;
|
||||
|
||||
[scriptable, uuid(cf76761d-2d93-4e88-aaf1-b637878bad65)]
|
||||
[scriptable, uuid(4012e9a9-f6fb-48b3-9a80-b096c1dcb5ba)]
|
||||
interface nsIDOMNSHTMLElement : nsISupports
|
||||
{
|
||||
readonly attribute long offsetTop;
|
||||
|
@ -65,6 +65,10 @@ interface nsIDOMNSHTMLElement : nsISupports
|
|||
// for WHAT-WG drag and drop
|
||||
attribute boolean draggable;
|
||||
|
||||
void insertAdjacentHTML(in DOMString position,
|
||||
in DOMString text)
|
||||
raises(DOMException);
|
||||
|
||||
[optional_argc] void scrollIntoView([optional] in boolean top);
|
||||
|
||||
attribute boolean spellcheck;
|
||||
|
|
Загрузка…
Ссылка в новой задаче