package io.udash.bindings.inputs import io.udash._ import io.udash.properties.seq.SeqProperty import org.scalajs.dom.Event import org.scalajs.dom.html.Select import org.scalajs.dom.raw.HTMLOptionElement import scalatags.JsDom.all._ /** * Select of finite options for single and multi selection. */ object Select { val defaultLabel: String => Modifier = s => StringFrag(s) /** * Single select for ValueProperty. * * @param selectedItem Property to bind. * @param options SeqProperty of available options. * @param label Provides element's label. * @param selectModifiers Additional Modifiers for the select tag, don't use modifiers on value, onchange and selected attributes. * @return Binding with `select` element, which can be used as Scalatags modifier. */ def apply[T]( selectedItem: Property[T], options: ReadableSeqProperty[T] )(label: T => Modifier, selectModifiers: Modifier*): InputBinding[Select] = { new SelectBinding(options, label, selectModifiers)( opt => selectedItem.transform(_ == opt), opts => if (opts.nonEmpty && !opts.contains(selectedItem.get)) selectedItem.set(opts.head), selector => (_: Event) => selectedItem.set(options.get.apply(selector.value.toInt)) ) } /** * Multi selection for SeqProperty. Bound SeqProperty will contain selected options. * * @param selectedItems Property to bind. * @param options SeqProperty of available options. * @param label Provides element label. * @param selectModifiers Additional Modifiers, don't use modifiers on value, onchange and selected attributes. * @return Binding with `select` element, which can be used as Scalatags modifier. */ def apply[T, ElemType <: Property[T]]( selectedItems: SeqProperty[T, ElemType], options: ReadableSeqProperty[T] )(label: T => Modifier, selectModifiers: Modifier*): InputBinding[Select] = { new SelectBinding(options, label, selectModifiers :+ (multiple := true))( opt => selectedItems.transform(_.contains(opt)), opts => selectedItems.set(selectedItems.get.filter(opts.contains)), selector => (_: Event) => { val opts = options.get val selectedNodes = selector.querySelectorAll("option:checked") val selection = (0 until selectedNodes.length).map { idx => opts(selectedNodes(idx).asInstanceOf[HTMLOptionElement].value.toInt) } selectedItems.set(selection) } ) } }