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

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: Clean up 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
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 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 = &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 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(&currentElement); next; next = virtualItemAfter(next)) { 361 for (Element* next = virtualItemAfter(&currentElement); 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
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
OLDNEW
« Source/core/dom/LiveNodeList.cpp ('K') | « Source/core/html/HTMLCollection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698