Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(753)

Side by Side Diff: Source/core/html/HTMLCollection.cpp

Issue 468183002: Move matching Element traversal functions from LiveNodeListBase to ElementTraversal (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Use anonymous namespace Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/HTMLCollection.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 namespace {
287 {
288 return collection.elementMatches(element);
289 }
290 284
291 template <> inline bool isMatchingElement(const HTMLTagCollection& collection, c onst Element& element) 285 template <class HTMLCollectionType>
292 { 286 class IsMatch {
293 return collection.elementMatches(element); 287 public:
294 } 288 IsMatch(const HTMLCollectionType& list)
289 : m_list(list)
290 { }
291
292 bool operator() (const Element& element) const
293 {
294 return m_list.elementMatches(element);
295 }
296
297 private:
298 const HTMLCollectionType& m_list;
299 };
300
301 } // namespace
302
303 template <class HTMLCollectionType>
304 static inline IsMatch<HTMLCollectionType> makeIsMatch(const HTMLCollectionType& list) { return IsMatch<HTMLCollectionType>(list); }
295 305
296 Element* HTMLCollection::virtualItemAfter(Element*) const 306 Element* HTMLCollection::virtualItemAfter(Element*) const
297 { 307 {
298 ASSERT_NOT_REACHED(); 308 ASSERT_NOT_REACHED();
299 return 0; 309 return 0;
300 } 310 }
301 311
302 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) 312 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element)
303 { 313 {
304 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: 314 // 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, 315 // The document.all collection returns only certain types of elements by nam e,
306 // although it returns any type of element by id. 316 // although it returns any type of element by id.
307 return element.hasTagName(aTag) 317 return element.hasTagName(aTag)
308 || element.hasTagName(appletTag) 318 || element.hasTagName(appletTag)
309 || element.hasTagName(areaTag) 319 || element.hasTagName(areaTag)
310 || element.hasTagName(embedTag) 320 || element.hasTagName(embedTag)
311 || element.hasTagName(formTag) 321 || element.hasTagName(formTag)
312 || element.hasTagName(frameTag) 322 || element.hasTagName(frameTag)
313 || element.hasTagName(framesetTag) 323 || element.hasTagName(framesetTag)
314 || element.hasTagName(iframeTag) 324 || element.hasTagName(iframeTag)
315 || element.hasTagName(imgTag) 325 || element.hasTagName(imgTag)
316 || element.hasTagName(inputTag) 326 || element.hasTagName(inputTag)
317 || element.hasTagName(objectTag) 327 || element.hasTagName(objectTag)
318 || element.hasTagName(selectTag); 328 || element.hasTagName(selectTag);
319 } 329 }
320 330
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 = &current;
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 = &current;
349 do {
350 previous = ElementTraversal::previousSibling(*previous);
351 } while (previous && !isMatchingElement(nodeList, *previous));
352 return previous;
353 }
354
355 Element* HTMLCollection::traverseToFirstElement() const 331 Element* HTMLCollection::traverseToFirstElement() const
356 { 332 {
357 switch (type()) { 333 switch (type()) {
358 case HTMLTagCollectionType: 334 case HTMLTagCollectionType:
359 return firstMatchingElement(toHTMLTagCollection(*this)); 335 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toHTMLTagCo llection(*this)));
360 case ClassCollectionType: 336 case ClassCollectionType:
361 return firstMatchingElement(toClassCollection(*this)); 337 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toClassColl ection(*this)));
362 default: 338 default:
363 if (overridesItemAfter()) 339 if (overridesItemAfter())
364 return virtualItemAfter(0); 340 return virtualItemAfter(0);
365 if (shouldOnlyIncludeDirectChildren()) 341 if (shouldOnlyIncludeDirectChildren())
366 return firstMatchingChildElement(*this); 342 return ElementTraversal::firstChild(rootNode(), makeIsMatch(*this));
367 return firstMatchingElement(*this); 343 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(*this));
368 } 344 }
369 } 345 }
370 346
371 Element* HTMLCollection::traverseToLastElement() const 347 Element* HTMLCollection::traverseToLastElement() const
372 { 348 {
373 ASSERT(canTraverseBackward()); 349 ASSERT(canTraverseBackward());
374 if (shouldOnlyIncludeDirectChildren()) 350 if (shouldOnlyIncludeDirectChildren())
375 return lastMatchingChildElement(*this); 351 return ElementTraversal::lastChild(rootNode(), makeIsMatch(*this));
376 return lastMatchingElement(*this); 352 return ElementTraversal::lastWithin(rootNode(), makeIsMatch(*this));
377 } 353 }
378 354
379 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const 355 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const
380 { 356 {
381 ASSERT(currentOffset < offset); 357 ASSERT(currentOffset < offset);
382 switch (type()) { 358 switch (type()) {
383 case HTMLTagCollectionType: 359 case HTMLTagCollectionType:
384 return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this ), offset, currentElement, currentOffset); 360 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toHTMLTagCollection(*this)));
385 case ClassCollectionType: 361 case ClassCollectionType:
386 return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); 362 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toClassCollection(*this)));
387 default: 363 default:
388 if (overridesItemAfter()) { 364 if (overridesItemAfter()) {
389 for (Element* next = virtualItemAfter(&currentElement); next; next = virtualItemAfter(next)) { 365 for (Element* next = virtualItemAfter(&currentElement); next; next = virtualItemAfter(next)) {
390 if (++currentOffset == offset) 366 if (++currentOffset == offset)
391 return next; 367 return next;
392 } 368 }
393 return 0; 369 return 0;
394 } 370 }
395 if (shouldOnlyIncludeDirectChildren()) { 371 if (shouldOnlyIncludeDirectChildren()) {
396 for (Element* next = nextMatchingChildElement(*this, currentElement) ; next; next = nextMatchingChildElement(*this, *next)) { 372 IsMatch<HTMLCollection> isMatch(*this);
373 for (Element* next = ElementTraversal::nextSibling(currentElement, i sMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) {
397 if (++currentOffset == offset) 374 if (++currentOffset == offset)
398 return next; 375 return next;
399 } 376 }
400 return 0; 377 return 0;
401 } 378 }
402 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle ment, currentOffset); 379 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(*this));
403 } 380 }
404 } 381 }
405 382
406 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const 383 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const
407 { 384 {
408 ASSERT(currentOffset > offset); 385 ASSERT(currentOffset > offset);
409 ASSERT(canTraverseBackward()); 386 ASSERT(canTraverseBackward());
410 if (shouldOnlyIncludeDirectChildren()) { 387 if (shouldOnlyIncludeDirectChildren()) {
411 for (Element* previous = previousMatchingChildElement(*this, currentElem ent); previous; previous = previousMatchingChildElement(*this, *previous)) { 388 IsMatch<HTMLCollection> isMatch(*this);
389 for (Element* previous = ElementTraversal::previousSibling(currentElemen t, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, i sMatch)) {
412 if (--currentOffset == offset) 390 if (--currentOffset == offset)
413 return previous; 391 return previous;
414 } 392 }
415 return 0; 393 return 0;
416 } 394 }
417 return traverseMatchingElementsBackwardToOffset(*this, offset, currentElemen t, currentOffset); 395 return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this));
418 } 396 }
419 397
420 Element* HTMLCollection::namedItem(const AtomicString& name) const 398 Element* HTMLCollection::namedItem(const AtomicString& name) const
421 { 399 {
422 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp 400 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp
423 // This method first searches for an object with a matching id 401 // 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 402 // 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 403 // object with a matching name attribute, but only on those elements
426 // that are allowed a name attribute. 404 // that are allowed a name attribute.
427 updateIdNameCache(); 405 updateIdNameCache();
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 } 503 }
526 504
527 void HTMLCollection::trace(Visitor* visitor) 505 void HTMLCollection::trace(Visitor* visitor)
528 { 506 {
529 visitor->trace(m_namedItemCache); 507 visitor->trace(m_namedItemCache);
530 visitor->trace(m_collectionIndexCache); 508 visitor->trace(m_collectionIndexCache);
531 LiveNodeListBase::trace(visitor); 509 LiveNodeListBase::trace(visitor);
532 } 510 }
533 511
534 } // namespace blink 512 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/html/HTMLCollection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698