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-2008, 2011, 2012, 2014 Apple Inc. All rights reserved. | 4 * Copyright (C) 2003-2008, 2011, 2012, 2014 Apple Inc. All rights 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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 case WindowNamedItems: | 248 case WindowNamedItems: |
249 case NameNodeListType: | 249 case NameNodeListType: |
250 case RadioNodeListType: | 250 case RadioNodeListType: |
251 case RadioImgNodeListType: | 251 case RadioImgNodeListType: |
252 case LabelsNodeListType: | 252 case LabelsNodeListType: |
253 ASSERT_NOT_REACHED(); | 253 ASSERT_NOT_REACHED(); |
254 } | 254 } |
255 return false; | 255 return false; |
256 } | 256 } |
257 | 257 |
258 template <class NodeListType> | 258 inline bool HTMLCollection::elementMatches(const Element& element) const |
259 inline bool isMatchingElement(const NodeListType&, const Element&); | |
260 | |
261 template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) | |
262 { | 259 { |
263 // These collections apply to any kind of Elements, not just HTMLElements. | 260 // These collections apply to any kind of Elements, not just HTMLElements. |
264 switch (htmlCollection.type()) { | 261 switch (type()) { |
265 case DocAll: | 262 case DocAll: |
266 case NodeChildren: | 263 case NodeChildren: |
267 return true; | 264 return true; |
268 case ClassCollectionType: | 265 case ClassCollectionType: |
269 return toClassCollection(htmlCollection).elementMatches(element); | 266 return toClassCollection(*this).elementMatches(element); |
270 case TagCollectionType: | 267 case TagCollectionType: |
271 return toTagCollection(htmlCollection).elementMatches(element); | 268 return toTagCollection(*this).elementMatches(element); |
272 case HTMLTagCollectionType: | 269 case HTMLTagCollectionType: |
273 return toHTMLTagCollection(htmlCollection).elementMatches(element); | 270 return toHTMLTagCollection(*this).elementMatches(element); |
274 case DocumentNamedItems: | 271 case DocumentNamedItems: |
275 return toDocumentNameCollection(htmlCollection).elementMatches(element); | 272 return toDocumentNameCollection(*this).elementMatches(element); |
276 case WindowNamedItems: | 273 case WindowNamedItems: |
277 return toWindowNameCollection(htmlCollection).elementMatches(element); | 274 return toWindowNameCollection(*this).elementMatches(element); |
278 default: | 275 default: |
279 break; | 276 break; |
280 } | 277 } |
281 | 278 |
282 // The following only applies to HTMLElements. | 279 // The following only applies to HTMLElements. |
283 return element.isHTMLElement() && isMatchingHTMLElement(htmlCollection, toHT MLElement(element)); | 280 return element.isHTMLElement() && isMatchingHTMLElement(*this, toHTMLElement (element)); |
284 } | 281 } |
285 | 282 |
286 template <> inline bool isMatchingElement(const ClassCollection& collection, con st Element& element) | 283 template <class HTMLCollectionType> |
287 { | 284 class IsMatch { |
adamk
2014/08/13 20:53:55
Same with this, anonymous namespace please.
Inactive
2014/08/13 21:17:19
Done.
| |
288 return collection.elementMatches(element); | 285 public: |
289 } | 286 IsMatch(const HTMLCollectionType& list) |
287 : m_list(list) | |
288 { } | |
290 | 289 |
291 template <> inline bool isMatchingElement(const HTMLTagCollection& collection, c onst Element& element) | 290 bool operator() (const Element& element) const |
292 { | 291 { |
293 return collection.elementMatches(element); | 292 return m_list.elementMatches(element); |
294 } | 293 } |
294 | |
295 private: | |
296 const HTMLCollectionType& m_list; | |
297 }; | |
298 | |
299 template <class HTMLCollectionType> | |
300 static inline IsMatch<HTMLCollectionType> makeIsMatch(const HTMLCollectionType& list) { return IsMatch<HTMLCollectionType>(list); } | |
295 | 301 |
296 Element* HTMLCollection::virtualItemAfter(Element*) const | 302 Element* HTMLCollection::virtualItemAfter(Element*) const |
297 { | 303 { |
298 ASSERT_NOT_REACHED(); | 304 ASSERT_NOT_REACHED(); |
299 return 0; | 305 return 0; |
300 } | 306 } |
301 | 307 |
302 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) | 308 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) |
303 { | 309 { |
304 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: | 310 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: |
305 // The document.all collection returns only certain types of elements by nam e, | 311 // The document.all collection returns only certain types of elements by nam e, |
306 // although it returns any type of element by id. | 312 // although it returns any type of element by id. |
307 return element.hasTagName(aTag) | 313 return element.hasTagName(aTag) |
308 || element.hasTagName(appletTag) | 314 || element.hasTagName(appletTag) |
309 || element.hasTagName(areaTag) | 315 || element.hasTagName(areaTag) |
310 || element.hasTagName(embedTag) | 316 || element.hasTagName(embedTag) |
311 || element.hasTagName(formTag) | 317 || element.hasTagName(formTag) |
312 || element.hasTagName(frameTag) | 318 || element.hasTagName(frameTag) |
313 || element.hasTagName(framesetTag) | 319 || element.hasTagName(framesetTag) |
314 || element.hasTagName(iframeTag) | 320 || element.hasTagName(iframeTag) |
315 || element.hasTagName(imgTag) | 321 || element.hasTagName(imgTag) |
316 || element.hasTagName(inputTag) | 322 || element.hasTagName(inputTag) |
317 || element.hasTagName(objectTag) | 323 || element.hasTagName(objectTag) |
318 || element.hasTagName(selectTag); | 324 || element.hasTagName(selectTag); |
319 } | 325 } |
320 | 326 |
321 inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) | |
322 { | |
323 Element* element = ElementTraversal::firstChild(nodeList.rootNode()); | |
324 while (element && !isMatchingElement(nodeList, *element)) | |
325 element = ElementTraversal::nextSibling(*element); | |
326 return element; | |
327 } | |
328 | |
329 inline Element* lastMatchingChildElement(const HTMLCollection& nodeList) | |
330 { | |
331 Element* element = ElementTraversal::lastChild(nodeList.rootNode()); | |
332 while (element && !isMatchingElement(nodeList, *element)) | |
333 element = ElementTraversal::previousSibling(*element); | |
334 return element; | |
335 } | |
336 | |
337 inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element & current) | |
338 { | |
339 Element* next = ¤t; | |
340 do { | |
341 next = ElementTraversal::nextSibling(*next); | |
342 } while (next && !isMatchingElement(nodeList, *next)); | |
343 return next; | |
344 } | |
345 | |
346 inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Ele ment& current) | |
347 { | |
348 Element* previous = ¤t; | |
349 do { | |
350 previous = ElementTraversal::previousSibling(*previous); | |
351 } while (previous && !isMatchingElement(nodeList, *previous)); | |
352 return previous; | |
353 } | |
354 | |
355 Element* HTMLCollection::traverseToFirstElement() const | 327 Element* HTMLCollection::traverseToFirstElement() const |
356 { | 328 { |
357 switch (type()) { | 329 switch (type()) { |
358 case HTMLTagCollectionType: | 330 case HTMLTagCollectionType: |
359 return firstMatchingElement(toHTMLTagCollection(*this)); | 331 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toHTMLTagCo llection(*this))); |
360 case ClassCollectionType: | 332 case ClassCollectionType: |
361 return firstMatchingElement(toClassCollection(*this)); | 333 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toClassColl ection(*this))); |
362 default: | 334 default: |
363 if (overridesItemAfter()) | 335 if (overridesItemAfter()) |
364 return virtualItemAfter(0); | 336 return virtualItemAfter(0); |
365 if (shouldOnlyIncludeDirectChildren()) | 337 if (shouldOnlyIncludeDirectChildren()) |
366 return firstMatchingChildElement(*this); | 338 return ElementTraversal::firstChild(rootNode(), makeIsMatch(*this)); |
367 return firstMatchingElement(*this); | 339 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(*this)); |
368 } | 340 } |
369 } | 341 } |
370 | 342 |
371 Element* HTMLCollection::traverseToLastElement() const | 343 Element* HTMLCollection::traverseToLastElement() const |
372 { | 344 { |
373 ASSERT(canTraverseBackward()); | 345 ASSERT(canTraverseBackward()); |
374 if (shouldOnlyIncludeDirectChildren()) | 346 if (shouldOnlyIncludeDirectChildren()) |
375 return lastMatchingChildElement(*this); | 347 return ElementTraversal::lastChild(rootNode(), makeIsMatch(*this)); |
376 return lastMatchingElement(*this); | 348 return ElementTraversal::lastWithin(rootNode(), makeIsMatch(*this)); |
377 } | 349 } |
378 | 350 |
379 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const | 351 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const |
380 { | 352 { |
381 ASSERT(currentOffset < offset); | 353 ASSERT(currentOffset < offset); |
382 switch (type()) { | 354 switch (type()) { |
383 case HTMLTagCollectionType: | 355 case HTMLTagCollectionType: |
384 return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this ), offset, currentElement, currentOffset); | 356 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toHTMLTagCollection(*this))); |
385 case ClassCollectionType: | 357 case ClassCollectionType: |
386 return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); | 358 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toClassCollection(*this))); |
387 default: | 359 default: |
388 if (overridesItemAfter()) { | 360 if (overridesItemAfter()) { |
389 for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) { | 361 for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) { |
390 if (++currentOffset == offset) | 362 if (++currentOffset == offset) |
391 return next; | 363 return next; |
392 } | 364 } |
393 return 0; | 365 return 0; |
394 } | 366 } |
395 if (shouldOnlyIncludeDirectChildren()) { | 367 if (shouldOnlyIncludeDirectChildren()) { |
396 for (Element* next = nextMatchingChildElement(*this, currentElement) ; next; next = nextMatchingChildElement(*this, *next)) { | 368 IsMatch<HTMLCollection> isMatch(*this); |
369 for (Element* next = ElementTraversal::nextSibling(currentElement, i sMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) { | |
397 if (++currentOffset == offset) | 370 if (++currentOffset == offset) |
398 return next; | 371 return next; |
399 } | 372 } |
400 return 0; | 373 return 0; |
401 } | 374 } |
402 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle ment, currentOffset); | 375 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(*this)); |
403 } | 376 } |
404 } | 377 } |
405 | 378 |
406 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const | 379 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const |
407 { | 380 { |
408 ASSERT(currentOffset > offset); | 381 ASSERT(currentOffset > offset); |
409 ASSERT(canTraverseBackward()); | 382 ASSERT(canTraverseBackward()); |
410 if (shouldOnlyIncludeDirectChildren()) { | 383 if (shouldOnlyIncludeDirectChildren()) { |
411 for (Element* previous = previousMatchingChildElement(*this, currentElem ent); previous; previous = previousMatchingChildElement(*this, *previous)) { | 384 IsMatch<HTMLCollection> isMatch(*this); |
385 for (Element* previous = ElementTraversal::previousSibling(currentElemen t, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, i sMatch)) { | |
412 if (--currentOffset == offset) | 386 if (--currentOffset == offset) |
413 return previous; | 387 return previous; |
414 } | 388 } |
415 return 0; | 389 return 0; |
416 } | 390 } |
417 return traverseMatchingElementsBackwardToOffset(*this, offset, currentElemen t, currentOffset); | 391 return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this)); |
418 } | 392 } |
419 | 393 |
420 Element* HTMLCollection::namedItem(const AtomicString& name) const | 394 Element* HTMLCollection::namedItem(const AtomicString& name) const |
421 { | 395 { |
422 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp | 396 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp |
423 // This method first searches for an object with a matching id | 397 // This method first searches for an object with a matching id |
424 // attribute. If a match is not found, the method then searches for an | 398 // attribute. If a match is not found, the method then searches for an |
425 // object with a matching name attribute, but only on those elements | 399 // object with a matching name attribute, but only on those elements |
426 // that are allowed a name attribute. | 400 // that are allowed a name attribute. |
427 updateIdNameCache(); | 401 updateIdNameCache(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
525 } | 499 } |
526 | 500 |
527 void HTMLCollection::trace(Visitor* visitor) | 501 void HTMLCollection::trace(Visitor* visitor) |
528 { | 502 { |
529 visitor->trace(m_namedItemCache); | 503 visitor->trace(m_namedItemCache); |
530 visitor->trace(m_collectionIndexCache); | 504 visitor->trace(m_collectionIndexCache); |
531 LiveNodeListBase::trace(visitor); | 505 LiveNodeListBase::trace(visitor); |
532 } | 506 } |
533 | 507 |
534 } // namespace blink | 508 } // namespace blink |
OLD | NEW |