зеркало из 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;
|
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
|
nsresult
|
||||||
nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
||||||
{
|
{
|
||||||
|
@ -755,19 +775,7 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
||||||
eCompatibility_NavQuirks,
|
eCompatibility_NavQuirks,
|
||||||
PR_TRUE);
|
PR_TRUE);
|
||||||
// HTML5 parser has notified, but not fired mutation events.
|
// HTML5 parser has notified, but not fired mutation events.
|
||||||
// Fire mutation events. Optimize for the case when there are no listeners
|
FireMutationEventsForDirectParsing(doc, this, oldChildCount);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML,
|
rv = nsContentUtils::CreateContextualFragment(this, aInnerHTML,
|
||||||
PR_TRUE,
|
PR_TRUE,
|
||||||
|
@ -781,6 +789,104 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
|
||||||
return rv;
|
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
|
nsresult
|
||||||
nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
|
nsGenericHTMLElement::ScrollIntoView(PRBool aTop, PRUint8 optional_argc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,6 +135,8 @@ public:
|
||||||
nsresult GetOffsetParent(nsIDOMElement** aOffsetParent);
|
nsresult GetOffsetParent(nsIDOMElement** aOffsetParent);
|
||||||
virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
|
virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
|
||||||
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
|
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
|
||||||
|
virtual nsresult InsertAdjacentHTML(const nsAString& aPosition,
|
||||||
|
const nsAString& aText);
|
||||||
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
|
nsresult ScrollIntoView(PRBool aTop, PRUint8 optional_argc);
|
||||||
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetHidden(),
|
// Declare Focus(), Blur(), GetTabIndex(), SetTabIndex(), GetHidden(),
|
||||||
// SetHidden(), GetSpellcheck(), SetSpellcheck(), and GetDraggable() such that
|
// SetHidden(), GetSpellcheck(), SetSpellcheck(), and GetDraggable() such that
|
||||||
|
@ -571,6 +573,18 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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);
|
void RegUnRegAccessKey(PRBool aDoReg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
interface nsIDOMDOMStringMap;
|
interface nsIDOMDOMStringMap;
|
||||||
|
|
||||||
[scriptable, uuid(cf76761d-2d93-4e88-aaf1-b637878bad65)]
|
[scriptable, uuid(4012e9a9-f6fb-48b3-9a80-b096c1dcb5ba)]
|
||||||
interface nsIDOMNSHTMLElement : nsISupports
|
interface nsIDOMNSHTMLElement : nsISupports
|
||||||
{
|
{
|
||||||
readonly attribute long offsetTop;
|
readonly attribute long offsetTop;
|
||||||
|
@ -65,6 +65,10 @@ interface nsIDOMNSHTMLElement : nsISupports
|
||||||
// for WHAT-WG drag and drop
|
// for WHAT-WG drag and drop
|
||||||
attribute boolean draggable;
|
attribute boolean draggable;
|
||||||
|
|
||||||
|
void insertAdjacentHTML(in DOMString position,
|
||||||
|
in DOMString text)
|
||||||
|
raises(DOMException);
|
||||||
|
|
||||||
[optional_argc] void scrollIntoView([optional] in boolean top);
|
[optional_argc] void scrollIntoView([optional] in boolean top);
|
||||||
|
|
||||||
attribute boolean spellcheck;
|
attribute boolean spellcheck;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче