OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r
ights reserved. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r
ights reserved. |
5 * Copyright (C) 2014 Samsung Electronics. All rights reserved. | 5 * Copyright (C) 2014 Samsung Electronics. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 || element.hasLocalName(formTag) | 299 || element.hasLocalName(formTag) |
300 || element.hasLocalName(frameTag) | 300 || element.hasLocalName(frameTag) |
301 || element.hasLocalName(framesetTag) | 301 || element.hasLocalName(framesetTag) |
302 || element.hasLocalName(iframeTag) | 302 || element.hasLocalName(iframeTag) |
303 || element.hasLocalName(imgTag) | 303 || element.hasLocalName(imgTag) |
304 || element.hasLocalName(inputTag) | 304 || element.hasLocalName(inputTag) |
305 || element.hasLocalName(objectTag) | 305 || element.hasLocalName(objectTag) |
306 || element.hasLocalName(selectTag); | 306 || element.hasLocalName(selectTag); |
307 } | 307 } |
308 | 308 |
309 inline Element* firstMatchingChildElement(const HTMLCollection& nodeList, const
ContainerNode& root) | 309 inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) |
310 { | 310 { |
311 Element* element = ElementTraversal::firstChild(root); | 311 Element* element = ElementTraversal::firstChild(nodeList.rootNode()); |
312 while (element && !isMatchingElement(nodeList, *element)) | 312 while (element && !isMatchingElement(nodeList, *element)) |
313 element = ElementTraversal::nextSibling(*element); | 313 element = ElementTraversal::nextSibling(*element); |
314 return element; | 314 return element; |
315 } | 315 } |
316 | 316 |
317 inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element
& current) | 317 inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element
& current) |
318 { | 318 { |
319 Element* next = ¤t; | 319 Element* next = ¤t; |
320 do { | 320 do { |
321 next = ElementTraversal::nextSibling(*next); | 321 next = ElementTraversal::nextSibling(*next); |
322 } while (next && !isMatchingElement(nodeList, *next)); | 322 } while (next && !isMatchingElement(nodeList, *next)); |
323 return next; | 323 return next; |
324 } | 324 } |
325 | 325 |
326 Element* HTMLCollection::traverseToFirstElement(const ContainerNode& root) const | 326 Element* HTMLCollection::traverseToFirstElement() const |
327 { | 327 { |
328 switch (type()) { | 328 switch (type()) { |
329 case HTMLTagCollectionType: | 329 case HTMLTagCollectionType: |
330 return firstMatchingElement(static_cast<const HTMLTagCollection&>(*this)
, root); | 330 return firstMatchingElement(static_cast<const HTMLTagCollection&>(*this)
); |
331 case ClassCollectionType: | 331 case ClassCollectionType: |
332 return firstMatchingElement(static_cast<const ClassCollection&>(*this),
root); | 332 return firstMatchingElement(static_cast<const ClassCollection&>(*this)); |
333 default: | 333 default: |
334 if (overridesItemAfter()) | 334 if (overridesItemAfter()) |
335 return virtualItemAfter(0); | 335 return virtualItemAfter(0); |
336 if (shouldOnlyIncludeDirectChildren()) | 336 if (shouldOnlyIncludeDirectChildren()) |
337 return firstMatchingChildElement(*this, root); | 337 return firstMatchingChildElement(*this); |
338 return firstMatchingElement(*this, root); | 338 return firstMatchingElement(*this); |
339 } | 339 } |
340 } | 340 } |
341 | 341 |
342 inline Element* HTMLCollection::traverseNextElement(Element& previous, const Con
tainerNode& root) const | 342 inline Element* HTMLCollection::traverseNextElement(Element& previous) const |
343 { | 343 { |
344 if (overridesItemAfter()) | 344 if (overridesItemAfter()) |
345 return virtualItemAfter(&previous); | 345 return virtualItemAfter(&previous); |
346 if (shouldOnlyIncludeDirectChildren()) | 346 if (shouldOnlyIncludeDirectChildren()) |
347 return nextMatchingChildElement(*this, previous); | 347 return nextMatchingChildElement(*this, previous); |
348 return nextMatchingElement(*this, previous, root); | 348 return nextMatchingElement(*this, previous); |
349 } | 349 } |
350 | 350 |
351 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre
ntElement, unsigned& currentOffset, const ContainerNode& root) const | 351 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre
ntElement, unsigned& currentOffset) const |
352 { | 352 { |
353 ASSERT(currentOffset < offset); | 353 ASSERT(currentOffset < offset); |
354 switch (type()) { | 354 switch (type()) { |
355 case HTMLTagCollectionType: | 355 case HTMLTagCollectionType: |
356 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
Collection&>(*this), offset, currentElement, currentOffset, root); | 356 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
Collection&>(*this), offset, currentElement, currentOffset); |
357 case ClassCollectionType: | 357 case ClassCollectionType: |
358 return traverseMatchingElementsForwardToOffset(static_cast<const ClassCo
llection&>(*this), offset, currentElement, currentOffset, root); | 358 return traverseMatchingElementsForwardToOffset(static_cast<const ClassCo
llection&>(*this), offset, currentElement, currentOffset); |
359 default: | 359 default: |
360 if (overridesItemAfter()) { | 360 if (overridesItemAfter()) { |
361 Element* next = ¤tElement; | 361 Element* next = ¤tElement; |
362 while ((next = virtualItemAfter(next))) { | 362 while ((next = virtualItemAfter(next))) { |
363 if (++currentOffset == offset) | 363 if (++currentOffset == offset) |
364 return next; | 364 return next; |
365 } | 365 } |
366 return 0; | 366 return 0; |
367 } | 367 } |
368 if (shouldOnlyIncludeDirectChildren()) { | 368 if (shouldOnlyIncludeDirectChildren()) { |
369 Element* next = ¤tElement; | 369 Element* next = ¤tElement; |
370 while ((next = nextMatchingChildElement(*this, *next))) { | 370 while ((next = nextMatchingChildElement(*this, *next))) { |
371 if (++currentOffset == offset) | 371 if (++currentOffset == offset) |
372 return next; | 372 return next; |
373 } | 373 } |
374 return 0; | 374 return 0; |
375 } | 375 } |
376 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle
ment, currentOffset, root); | 376 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle
ment, currentOffset); |
377 } | 377 } |
378 } | 378 } |
379 | 379 |
380 Element* HTMLCollection::namedItem(const AtomicString& name) const | 380 Element* HTMLCollection::namedItem(const AtomicString& name) const |
381 { | 381 { |
382 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp | 382 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp |
383 // This method first searches for an object with a matching id | 383 // This method first searches for an object with a matching id |
384 // attribute. If a match is not found, the method then searches for an | 384 // attribute. If a match is not found, the method then searches for an |
385 // object with a matching name attribute, but only on those elements | 385 // object with a matching name attribute, but only on those elements |
386 // that are allowed a name attribute. | 386 // that are allowed a name attribute. |
(...skipping 20 matching lines...) Expand all Loading... |
407 { | 407 { |
408 // As per the specification (http://dom.spec.whatwg.org/#htmlcollection): | 408 // As per the specification (http://dom.spec.whatwg.org/#htmlcollection): |
409 // The supported property names are the values from the list returned by the
se steps: | 409 // The supported property names are the values from the list returned by the
se steps: |
410 // 1. Let result be an empty list. | 410 // 1. Let result be an empty list. |
411 // 2. For each element represented by the collection, in tree order, run the
se substeps: | 411 // 2. For each element represented by the collection, in tree order, run the
se substeps: |
412 // 1. If element has an ID which is neither the empty string nor is in res
ult, append element's ID to result. | 412 // 1. If element has an ID which is neither the empty string nor is in res
ult, append element's ID to result. |
413 // 2. If element is in the HTML namespace and has a name attribute whose v
alue is neither the empty string | 413 // 2. If element is in the HTML namespace and has a name attribute whose v
alue is neither the empty string |
414 // nor is in result, append element's name attribute value to result. | 414 // nor is in result, append element's name attribute value to result. |
415 // 3. Return result. | 415 // 3. Return result. |
416 HashSet<AtomicString> existingNames; | 416 HashSet<AtomicString> existingNames; |
417 ContainerNode& root = rootNode(); | 417 for (Element* element = traverseToFirstElement(); element; element = travers
eNextElement(*element)) { |
418 for (Element* element = traverseToFirstElement(root); element; element = tra
verseNextElement(*element, root)) { | |
419 const AtomicString& idAttribute = element->getIdAttribute(); | 418 const AtomicString& idAttribute = element->getIdAttribute(); |
420 if (!idAttribute.isEmpty()) { | 419 if (!idAttribute.isEmpty()) { |
421 HashSet<AtomicString>::AddResult addResult = existingNames.add(idAtt
ribute); | 420 HashSet<AtomicString>::AddResult addResult = existingNames.add(idAtt
ribute); |
422 if (addResult.isNewEntry) | 421 if (addResult.isNewEntry) |
423 names.append(idAttribute); | 422 names.append(idAttribute); |
424 } | 423 } |
425 if (!element->isHTMLElement()) | 424 if (!element->isHTMLElement()) |
426 continue; | 425 continue; |
427 const AtomicString& nameAttribute = element->getNameAttribute(); | 426 const AtomicString& nameAttribute = element->getNameAttribute(); |
428 if (!nameAttribute.isEmpty() && (type() != DocAll || nameShouldBeVisible
InDocumentAll(toHTMLElement(*element)))) { | 427 if (!nameAttribute.isEmpty() && (type() != DocAll || nameShouldBeVisible
InDocumentAll(toHTMLElement(*element)))) { |
429 HashSet<AtomicString>::AddResult addResult = existingNames.add(nameA
ttribute); | 428 HashSet<AtomicString>::AddResult addResult = existingNames.add(nameA
ttribute); |
430 if (addResult.isNewEntry) | 429 if (addResult.isNewEntry) |
431 names.append(nameAttribute); | 430 names.append(nameAttribute); |
432 } | 431 } |
433 } | 432 } |
434 } | 433 } |
435 | 434 |
436 void HTMLCollection::namedPropertyEnumerator(Vector<String>& names, ExceptionSta
te&) | 435 void HTMLCollection::namedPropertyEnumerator(Vector<String>& names, ExceptionSta
te&) |
437 { | 436 { |
438 supportedPropertyNames(names); | 437 supportedPropertyNames(names); |
439 } | 438 } |
440 | 439 |
441 void HTMLCollection::updateIdNameCache() const | 440 void HTMLCollection::updateIdNameCache() const |
442 { | 441 { |
443 if (hasValidIdNameCache()) | 442 if (hasValidIdNameCache()) |
444 return; | 443 return; |
445 | 444 |
446 NamedItemCache& cache = createNamedItemCache(); | 445 NamedItemCache& cache = createNamedItemCache(); |
447 ContainerNode& root = rootNode(); | 446 for (Element* element = traverseToFirstElement(); element; element = travers
eNextElement(*element)) { |
448 for (Element* element = traverseToFirstElement(root); element; element = tra
verseNextElement(*element, root)) { | |
449 const AtomicString& idAttrVal = element->getIdAttribute(); | 447 const AtomicString& idAttrVal = element->getIdAttribute(); |
450 if (!idAttrVal.isEmpty()) | 448 if (!idAttrVal.isEmpty()) |
451 cache.addElementWithId(idAttrVal, element); | 449 cache.addElementWithId(idAttrVal, element); |
452 if (!element->isHTMLElement()) | 450 if (!element->isHTMLElement()) |
453 continue; | 451 continue; |
454 const AtomicString& nameAttrVal = element->getNameAttribute(); | 452 const AtomicString& nameAttrVal = element->getNameAttribute(); |
455 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) | 453 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) |
456 cache.addElementWithName(nameAttrVal, element); | 454 cache.addElementWithName(nameAttrVal, element); |
457 } | 455 } |
458 } | 456 } |
(...skipping 11 matching lines...) Expand all Loading... |
470 Vector<Element*>* nameResults = cache.getElementsByName(name); | 468 Vector<Element*>* nameResults = cache.getElementsByName(name); |
471 | 469 |
472 for (unsigned i = 0; idResults && i < idResults->size(); ++i) | 470 for (unsigned i = 0; idResults && i < idResults->size(); ++i) |
473 result.append(idResults->at(i)); | 471 result.append(idResults->at(i)); |
474 | 472 |
475 for (unsigned i = 0; nameResults && i < nameResults->size(); ++i) | 473 for (unsigned i = 0; nameResults && i < nameResults->size(); ++i) |
476 result.append(nameResults->at(i)); | 474 result.append(nameResults->at(i)); |
477 } | 475 } |
478 | 476 |
479 } // namespace WebCore | 477 } // namespace WebCore |
OLD | NEW |