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

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: Rebase 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 {
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() (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 };
295 298
296 Element* HTMLCollection::virtualItemAfter(Element*) const 299 Element* HTMLCollection::virtualItemAfter(Element*) const
297 { 300 {
298 ASSERT_NOT_REACHED(); 301 ASSERT_NOT_REACHED();
299 return 0; 302 return 0;
300 } 303 }
301 304
302 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) 305 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element)
303 { 306 {
304 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: 307 // 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, 308 // The document.all collection returns only certain types of elements by nam e,
306 // although it returns any type of element by id. 309 // although it returns any type of element by id.
307 return element.hasTagName(aTag) 310 return element.hasTagName(aTag)
308 || element.hasTagName(appletTag) 311 || element.hasTagName(appletTag)
309 || element.hasTagName(areaTag) 312 || element.hasTagName(areaTag)
310 || element.hasTagName(embedTag) 313 || element.hasTagName(embedTag)
311 || element.hasTagName(formTag) 314 || element.hasTagName(formTag)
312 || element.hasTagName(frameTag) 315 || element.hasTagName(frameTag)
313 || element.hasTagName(framesetTag) 316 || element.hasTagName(framesetTag)
314 || element.hasTagName(iframeTag) 317 || element.hasTagName(iframeTag)
315 || element.hasTagName(imgTag) 318 || element.hasTagName(imgTag)
316 || element.hasTagName(inputTag) 319 || element.hasTagName(inputTag)
317 || element.hasTagName(objectTag) 320 || element.hasTagName(objectTag)
318 || element.hasTagName(selectTag); 321 || element.hasTagName(selectTag);
319 } 322 }
320 323
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 324 Element* HTMLCollection::traverseToFirstElement() const
356 { 325 {
357 switch (type()) { 326 switch (type()) {
358 case HTMLTagCollectionType: 327 case HTMLTagCollectionType:
359 return firstMatchingElement(toHTMLTagCollection(*this)); 328 return ElementTraversal::firstWithin(rootNode(), IsMatch<HTMLTagCollecti on>(toHTMLTagCollection(*this)));
360 case ClassCollectionType: 329 case ClassCollectionType:
361 return firstMatchingElement(toClassCollection(*this)); 330 return ElementTraversal::firstWithin(rootNode(), IsMatch<ClassCollection >(toClassCollection(*this)));
362 default: 331 default:
363 if (overridesItemAfter()) 332 if (overridesItemAfter())
364 return virtualItemAfter(0); 333 return virtualItemAfter(0);
365 if (shouldOnlyIncludeDirectChildren()) 334 if (shouldOnlyIncludeDirectChildren())
366 return firstMatchingChildElement(*this); 335 return ElementTraversal::firstChild(rootNode(), IsMatch<HTMLCollecti on>(*this));
367 return firstMatchingElement(*this); 336 return ElementTraversal::firstWithin(rootNode(), IsMatch<HTMLCollection> (*this));
368 } 337 }
369 } 338 }
370 339
371 Element* HTMLCollection::traverseToLastElement() const 340 Element* HTMLCollection::traverseToLastElement() const
372 { 341 {
373 ASSERT(canTraverseBackward()); 342 ASSERT(canTraverseBackward());
374 if (shouldOnlyIncludeDirectChildren()) 343 if (shouldOnlyIncludeDirectChildren())
375 return lastMatchingChildElement(*this); 344 return ElementTraversal::lastChild(rootNode(), IsMatch<HTMLCollection>(* this));
376 return lastMatchingElement(*this); 345 return ElementTraversal::lastWithin(rootNode(), IsMatch<HTMLCollection>(*thi s));
377 } 346 }
378 347
379 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const 348 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const
380 { 349 {
381 ASSERT(currentOffset < offset); 350 ASSERT(currentOffset < offset);
382 switch (type()) { 351 switch (type()) {
383 case HTMLTagCollectionType: 352 case HTMLTagCollectionType:
384 return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this ), offset, currentElement, currentOffset); 353 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, IsMatch<HTMLTagCollection>(toHTMLTagCollection(*this) ));
385 case ClassCollectionType: 354 case ClassCollectionType:
386 return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); 355 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, IsMatch<ClassCollection>(toClassCollection(*this)));
387 default: 356 default:
388 if (overridesItemAfter()) { 357 if (overridesItemAfter()) {
389 for (Element* next = virtualItemAfter(&currentElement); next; next = virtualItemAfter(next)) { 358 for (Element* next = virtualItemAfter(&currentElement); next; next = virtualItemAfter(next)) {
390 if (++currentOffset == offset) 359 if (++currentOffset == offset)
391 return next; 360 return next;
392 } 361 }
393 return 0; 362 return 0;
394 } 363 }
395 if (shouldOnlyIncludeDirectChildren()) { 364 if (shouldOnlyIncludeDirectChildren()) {
396 for (Element* next = nextMatchingChildElement(*this, currentElement) ; next; next = nextMatchingChildElement(*this, *next)) { 365 IsMatch<HTMLCollection> isMatch(*this);
366 for (Element* next = ElementTraversal::nextSibling(currentElement, i sMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) {
397 if (++currentOffset == offset) 367 if (++currentOffset == offset)
398 return next; 368 return next;
399 } 369 }
400 return 0; 370 return 0;
401 } 371 }
402 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle ment, currentOffset); 372 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, IsMatch<HTMLCollection>(*this));
403 } 373 }
404 } 374 }
405 375
406 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const 376 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const
407 { 377 {
408 ASSERT(currentOffset > offset); 378 ASSERT(currentOffset > offset);
409 ASSERT(canTraverseBackward()); 379 ASSERT(canTraverseBackward());
410 if (shouldOnlyIncludeDirectChildren()) { 380 if (shouldOnlyIncludeDirectChildren()) {
411 for (Element* previous = previousMatchingChildElement(*this, currentElem ent); previous; previous = previousMatchingChildElement(*this, *previous)) { 381 IsMatch<HTMLCollection> isMatch(*this);
382 for (Element* previous = ElementTraversal::previousSibling(currentElemen t, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, i sMatch)) {
412 if (--currentOffset == offset) 383 if (--currentOffset == offset)
413 return previous; 384 return previous;
414 } 385 }
415 return 0; 386 return 0;
416 } 387 }
417 return traverseMatchingElementsBackwardToOffset(*this, offset, currentElemen t, currentOffset); 388 return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, IsMatch<HTMLCollection>(*this));
418 } 389 }
419 390
420 Element* HTMLCollection::namedItem(const AtomicString& name) const 391 Element* HTMLCollection::namedItem(const AtomicString& name) const
421 { 392 {
422 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp 393 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp
423 // This method first searches for an object with a matching id 394 // 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 395 // 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 396 // object with a matching name attribute, but only on those elements
426 // that are allowed a name attribute. 397 // that are allowed a name attribute.
427 updateIdNameCache(); 398 updateIdNameCache();
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 } 496 }
526 497
527 void HTMLCollection::trace(Visitor* visitor) 498 void HTMLCollection::trace(Visitor* visitor)
528 { 499 {
529 visitor->trace(m_namedItemCache); 500 visitor->trace(m_namedItemCache);
530 visitor->trace(m_collectionIndexCache); 501 visitor->trace(m_collectionIndexCache);
531 LiveNodeListBase::trace(visitor); 502 LiveNodeListBase::trace(visitor);
532 } 503 }
533 504
534 } // namespace blink 505 } // 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