/*
 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

[
    JSCustomHeader,
    JSCustomMarkFunction,
    JSCustomPushEventHandlerScope,
    JSCustomIsReachable,
    JSCustomFinalize,
    CustomToJSObject,
    EventTarget,
    JSGenerateToNativeObject,
    JSInlineGetOwnPropertySlot,
    ObjCPolymorphic,
    V8DependentLifetime
] interface Node
#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
    : Object, EventTarget
#endif /* defined(LANGUAGE_OBJECTIVE_C) */
 {
    // NodeType
    const unsigned short      ELEMENT_NODE                   = 1;
    const unsigned short      ATTRIBUTE_NODE                 = 2;
    const unsigned short      TEXT_NODE                      = 3;
    const unsigned short      CDATA_SECTION_NODE             = 4;
    const unsigned short      ENTITY_REFERENCE_NODE          = 5;
    const unsigned short      ENTITY_NODE                    = 6;
    const unsigned short      PROCESSING_INSTRUCTION_NODE    = 7;
    const unsigned short      COMMENT_NODE                   = 8;
    const unsigned short      DOCUMENT_NODE                  = 9;
    const unsigned short      DOCUMENT_TYPE_NODE             = 10;
    const unsigned short      DOCUMENT_FRAGMENT_NODE         = 11;
    const unsigned short      NOTATION_NODE                  = 12;

    readonly attribute [TreatReturnedNullStringAs=Null, V8PerWorldBindings] DOMString        nodeName;

             // FIXME: the spec says this can also raise on retrieval.
             attribute [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, V8PerWorldBindings] DOMString        nodeValue
                 setter raises(DOMException);

    readonly attribute [V8PerWorldBindings] unsigned short   nodeType;
    readonly attribute [V8PerWorldBindings] Node             parentNode;
    readonly attribute [V8PerWorldBindings] NodeList         childNodes;
    readonly attribute [V8PerWorldBindings] Node             firstChild;
    readonly attribute [V8PerWorldBindings] Node             lastChild;
    readonly attribute [V8PerWorldBindings] Node             previousSibling;
    readonly attribute [V8PerWorldBindings] Node             nextSibling;
    readonly attribute [V8PerWorldBindings] Document         ownerDocument;

    [ObjCLegacyUnnamedParameters, Custom, V8PerWorldBindings] Node insertBefore(in [CustomReturn] Node newChild,
                                                            in Node refChild)
        raises(DOMException);
    [ObjCLegacyUnnamedParameters, Custom] Node replaceChild(in Node newChild,
                                                            in [CustomReturn] Node oldChild)
        raises(DOMException);
    [Custom, V8PerWorldBindings] Node removeChild(in [CustomReturn] Node oldChild)
        raises(DOMException);
    [Custom, V8PerWorldBindings] Node appendChild(in [CustomReturn] Node newChild)
        raises(DOMException);

    boolean            hasChildNodes();
    [V8DeliverCustomElementCallbacks, V8PerWorldBindings]
    Node               cloneNode(in [Optional=DefaultIsUndefined] boolean deep);
    void               normalize();

    // Introduced in DOM Level 2:

    [ObjCLegacyUnnamedParameters] boolean isSupported(in [Optional=DefaultIsUndefined] DOMString feature, 
                                       in [TreatNullAs=NullString,Optional=DefaultIsUndefined] DOMString version);

    readonly attribute [TreatReturnedNullStringAs=Null, V8PerWorldBindings] DOMString        namespaceURI;
             attribute [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, V8PerWorldBindings] DOMString        prefix
                 setter raises(DOMException);
    readonly attribute [TreatReturnedNullStringAs=Null, V8PerWorldBindings] DOMString        localName;

#if defined(LANGUAGE_OBJECTIVE_C)
    readonly attribute [V8PerWorldBindings] NamedNodeMap     attributes;
    boolean            hasAttributes();
#endif


    // Introduced in DOM Level 3:

    readonly attribute [TreatReturnedNullStringAs=Null, V8PerWorldBindings] DOMString       baseURI;

             // FIXME: the spec says this can also raise on retrieval.
             attribute [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, V8PerWorldBindings] DOMString       textContent
                 setter raises(DOMException);

    boolean            isSameNode(in [Optional=DefaultIsUndefined] Node other);
    boolean            isEqualNode(in [Optional=DefaultIsUndefined] Node other);
    [TreatReturnedNullStringAs=Null] DOMString          lookupPrefix(in [TreatNullAs=NullString,Optional=DefaultIsUndefined] DOMString namespaceURI);
    boolean            isDefaultNamespace(in [TreatNullAs=NullString,Optional=DefaultIsUndefined] DOMString namespaceURI);
    [TreatReturnedNullStringAs=Null] DOMString          lookupNamespaceURI(in [TreatNullAs=NullString,Optional=DefaultIsUndefined] DOMString prefix);

    // DocumentPosition
    const unsigned short      DOCUMENT_POSITION_DISCONNECTED = 0x01;
    const unsigned short      DOCUMENT_POSITION_PRECEDING    = 0x02;
    const unsigned short      DOCUMENT_POSITION_FOLLOWING    = 0x04;
    const unsigned short      DOCUMENT_POSITION_CONTAINS     = 0x08;
    const unsigned short      DOCUMENT_POSITION_CONTAINED_BY = 0x10;
    const unsigned short      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;

    unsigned short     compareDocumentPosition(in [Optional=DefaultIsUndefined] Node other);

    // Introduced in DOM4
    boolean contains(in [Optional=DefaultIsUndefined] Node other);

    // IE extensions
    readonly attribute [V8PerWorldBindings] Element          parentElement;

#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
    // Objective-C extensions
    readonly attribute [V8PerWorldBindings] boolean          isContentEditable;

    void inspect();
#endif /* defined(LANGUAGE_OBJECTIVE_C) */

#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
    void addEventListener(in DOMString type, 
                          in EventListener listener, 
                          in [Optional] boolean useCapture);
    void removeEventListener(in DOMString type, 
                             in EventListener listener, 
                             in [Optional] boolean useCapture);
    boolean dispatchEvent(in Event event)
        raises(EventException);
#endif
#endif

#if defined(LANGUAGE_CPP) && LANGUAGE_CPP
    [Custom] void addEventListener(in DOMString type, 
                                      in EventListener listener, 
                                      in boolean useCapture);
    [Custom] void removeEventListener(in DOMString type, 
                                         in EventListener listener, 
                                         in boolean useCapture);
    boolean dispatchEvent(in Event event)
        raises(EventException);
#endif

};

