text: /*
   * Copyright (C) 2006, 2011, 2012 Apple Computer, Inc.
   * Copyright (C) 2014 Samsung Electronics. All rights reserved.
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Library General Public
   * License as published by the Free Software Foundation; either
   * version 2 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Library General Public License for more details.
   *
   * You should have received a copy of the GNU Library General Public License
   * along with this library; see the file COPYING.LIB.  If not, write to
   * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   * Boston, MA 02110-1301, USA.
   *
   */
  
  #include "third_party/blink/renderer/core/html/forms/html_options_collection.h"
  
  #include "third_party/blink/renderer/core/html/forms/html_option_element.h"
  #include "third_party/blink/renderer/core/html/forms/html_select_element.h"
  #include "third_party/blink/renderer/platform/bindings/exception_state.h"
  
  namespace blink {
  
  HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select)
      : HTMLCollection(select, kSelectOptions, kDoesNotOverrideItemAfter) {
    DCHECK(IsA<HTMLSelectElement>(select));
  }
  
  HTMLOptionsCollection::HTMLOptionsCollection(ContainerNode& select,
                                               CollectionType type)
      : HTMLOptionsCollection(select) {
    DCHECK_EQ(type, kSelectOptions);
  }
  
  void HTMLOptionsCollection::SupportedPropertyNames(Vector<String>& names) {
    // As per
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmloptionscollection:
    // The supported property names consist of the non-empty values of all the id
    // and name attributes of all the elements represented by the collection, in
    // tree order, ignoring later duplicates, with the id of an element preceding
    // its name if it contributes both, they differ from each other, and neither
    // is the duplicate of an earlier entry.
    HashSet<AtomicString> existing_names;
    unsigned length = this->length();
    for (unsigned i = 0; i < length; ++i) {
      Element* element = item(i);
      DCHECK(element);
      const AtomicString& id_attribute = element->GetIdAttribute();
      if (!id_attribute.IsEmpty()) {
        HashSet<AtomicString>::AddResult add_result =
            existing_names.insert(id_attribute);
        if (add_result.is_new_entry)
          names.push_back(id_attribute);
      }
      const AtomicString& name_attribute = element->GetNameAttribute();
      if (!name_attribute.IsEmpty()) {
        HashSet<AtomicString>::AddResult add_result =
            existing_names.insert(name_attribute);
        if (add_result.is_new_entry)
          names.push_back(name_attribute);
      }
    }
  }
  
  void HTMLOptionsCollection::add(
      const V8UnionHTMLOptGroupElementOrHTMLOptionElement* element,
      const V8UnionHTMLElementOrLong* before,
      ExceptionState& exception_state) {
    To<HTMLSelectElement>(ownerNode()).add(element, before, exception_state);
  }
  
  void HTMLOptionsCollection::remove(int index) {
    To<HTMLSelectElement>(ownerNode()).remove(index);
  }
  
  int HTMLOptionsCollection::selectedIndex() const {
    return To<HTMLSelectElement>(ownerNode()).selectedIndex();
  }
  
  void HTMLOptionsCollection::setSelectedIndex(int index) {
    To<HTMLSelectElement>(ownerNode()).setSelectedIndex(index);
  }
  
  void HTMLOptionsCollection::setLength(unsigned length,
                                        ExceptionState& exception_state) {
    To<HTMLSelectElement>(ownerNode()).setLength(length, exception_state);
  }
  
  IndexedPropertySetterResult HTMLOptionsCollection::AnonymousIndexedSetter(
      unsigned index,
      HTMLOptionElement* value,
      ExceptionState& exception_state) {
    auto& base = To<HTMLSelectElement>(ownerNode());
    if (!value) {  // undefined or null
      base.remove(index);
      return IndexedPropertySetterResult::kIntercepted;
    }
    base.SetOption(index, value, exception_state);
    return IndexedPropertySetterResult::kIntercepted;
  }
  
  }  // namespace blink
  