예제 #1
0
PassRefPtr<DOMStringList> HTMLPropertiesCollection::names() const
{
    m_properties.clear();
    m_propertyNames->clear();

    if (!base()->isHTMLElement() || !toHTMLElement(base())->fastHasAttribute(itemscopeAttr))
        return m_propertyNames;

    findPropetiesOfAnItem(base());

    std::sort(m_properties.begin(), m_properties.end(), compareTreeOrder);

    for (size_t i = 0; i < m_properties.size(); ++i) {
        // For each item properties, split the value of that itemprop attribute on spaces.
        // Add all tokens to property names, with the order preserved but with duplicates removed.
        DOMSettableTokenList* itemProperty = m_properties[i]->itemProp();
        for (size_t i = 0; i < itemProperty->length(); ++i) {
            AtomicString propertyName = itemProperty->item(i);
            if (m_propertyNames->isEmpty() || !m_propertyNames->contains(propertyName))
                m_propertyNames->append(propertyName);
        }
    }

    return m_propertyNames;
}
예제 #2
0
void HTMLPropertiesCollection::findPropetiesOfAnItem(Node* root) const
{
    // 5.2.5 Associating names with items.
    Vector<Node*> memory;

    memory.append(root);

    Vector<Node*> pending;
    // Add the child elements of root, if any, to pending.
    for (Node* child = root->firstChild(); child; child = child->nextSibling())
        if (child->isHTMLElement())
            pending.append(child);

    // If root has an itemref attribute, split the value of that itemref attribute on spaces.
    // For each resulting token ID, if there is an element in the home subtree of root with the ID ID,
    // then add the first such element to pending.
    if (toHTMLElement(root)->fastHasAttribute(itemrefAttr)) {
        DOMSettableTokenList* itemRef = root->itemRef();

        for (size_t i = 0; i < itemRef->length(); ++i) {
            AtomicString id = itemRef->item(i);

            Element* element = root->document()->getElementById(id);
            if (element && element->isHTMLElement())
                pending.append(element);
        }
    }

    // Loop till we have processed all pending elements
    while (!pending.isEmpty()) {

        // Remove first element from pending and let current be that element.
        Node* current = pending[0];
        pending.remove(0);

        // If current is already in memory, there is a microdata error;
        if (memory.contains(current)) {
            // microdata error;
            continue;
        }

        memory.append(current);

        // If current does not have an itemscope attribute, then: add all the child elements of current to pending.
        HTMLElement* element = toHTMLElement(current);
        if (!element->fastHasAttribute(itemscopeAttr)) {
            for (Node* child = current->firstChild(); child; child = child->nextSibling())
                if (child->isHTMLElement())
                    pending.append(child);
        }

        // If current has an itemprop attribute specified, add it to results.
        if (element->fastHasAttribute(itempropAttr))
             m_properties.append(current);
    }
}
예제 #3
0
void HTMLPropertiesCollection::updateNameCache() const
{
    if (hasNameCache())
        return;

    updateRefElements();

    for (unsigned i = 0; i < m_itemRefElements.size(); ++i) {
        HTMLElement* refElement = m_itemRefElements[i];
        for (HTMLElement* element = virtualItemAfter(refElement, 0); element; element = virtualItemAfter(refElement, element)) {
            DOMSettableTokenList* itemProperty = element->itemProp();
            for (unsigned propertyIndex = 0; propertyIndex < itemProperty->length(); ++propertyIndex)
                updatePropertyCache(element, itemProperty->item(propertyIndex));
        }
    }

    setHasNameCache();
}