org.scalajs.dom.Element Scala Examples

The following examples show how to use org.scalajs.dom.Element. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: JSLauncher.scala    From udash-demos   with GNU General Public License v3.0 5 votes vote down vote up
package io.udash.demos.files

import io.udash.logging.CrossLogging
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element

import scala.scalajs.js.annotation.JSExport

object JSLauncher extends CrossLogging {
  @JSExport
  def main(args: Array[String]): Unit = {
    jQ((_: Element) => {
      val appRoot = jQ("#application").get(0)
      if (appRoot.isEmpty) {
        logger.error("Application root element not found! Check your index.html file!")
      } else {
        ApplicationContext.applicationInstance.run(appRoot.get)
      }
    })
  }
} 
Example 2
Source File: UdashAlert.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package alert

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.BootstrapStyles
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class UdashAlert private[alert](
  alertStyle: ReadableProperty[BootstrapStyles.Color], override val componentId: ComponentId
)(content: Binding.NestedInterceptor => Modifier) extends UdashAlertBase(alertStyle, componentId) {
  override val render: Element =
    template(content(nestedInterceptor)).render
}

object UdashAlert extends UdashAlertBaseCompanion[UdashAlert] {
  protected def create(alertStyle: ReadableProperty[BootstrapStyles.Color], componentId: ComponentId)(
    content: Binding.NestedInterceptor => Modifier
  ): UdashAlert = {
    new UdashAlert(alertStyle, componentId)(content)
  }
} 
Example 3
Source File: UdashButtonToolbar.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package button

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import io.udash.properties.seq
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class UdashButtonToolbar[ItemType, ElemType <: ReadableProperty[ItemType]] private(
  val items: seq.ReadableSeqProperty[ItemType, ElemType],
  override val componentId: ComponentId
)(itemFactory: (ElemType, Binding.NestedInterceptor) => Seq[Element]) extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  override val render: Element =
    div(role := "toolbar", BootstrapStyles.Button.toolbar, componentId)(
      repeatWithNested(items)(itemFactory)
    ).render
}

object UdashButtonToolbar {
  
  def reactive[ItemType, ElemType <: ReadableProperty[ItemType]](
    items: seq.ReadableSeqProperty[ItemType, ElemType], componentId: ComponentId = ComponentId.generate()
  )(itemFactory: (ElemType, Binding.NestedInterceptor) => Seq[Element]): UdashButtonToolbar[ItemType, ElemType] = {
    new UdashButtonToolbar[ItemType, ElemType](items, componentId)(itemFactory)
  }
} 
Example 4
Source File: UdashBadge.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package badge

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import org.scalajs.dom.Element
import scalatags.JsDom.TypedTag
import scalatags.JsDom.all._

class UdashBadge private[badge](
  badgeStyle: ReadableProperty[BootstrapStyles.Color],
  pillStyle: ReadableProperty[Boolean],
  override val componentId: ComponentId
)(content: Binding.NestedInterceptor => Modifier)
  extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  protected def baseTag: TypedTag[Element] = span

  override val render: Element = {
    baseTag(
      componentId, BootstrapStyles.Badge.badge,
      nestedInterceptor((BootstrapStyles.Badge.color _).reactiveApply(badgeStyle)),
      nestedInterceptor(BootstrapStyles.Badge.pill.styleIf(pillStyle))
    )(content(nestedInterceptor)).render
  }
}

private[badge] class UdashBadgeLink(
  link: ReadableProperty[String],
  badgeStyle: ReadableProperty[BootstrapStyles.Color],
  pillStyle: ReadableProperty[Boolean],
  override val componentId: ComponentId
)(content: Binding.NestedInterceptor => Modifier)
  extends UdashBadge(badgeStyle, pillStyle, componentId)(content) {

  protected override def baseTag: TypedTag[Element] =
    a(nestedInterceptor(href.bind(link)))
}

object UdashBadge {
  
  def link(
    link: ReadableProperty[String],
    badgeStyle: ReadableProperty[BootstrapStyles.Color] = UdashBootstrap.ColorSecondary,
    pillStyle: ReadableProperty[Boolean] = UdashBootstrap.False,
    componentId: ComponentId = ComponentId.generate()
  )(content: Binding.NestedInterceptor => Modifier): UdashBadge = {
    new UdashBadgeLink(link, badgeStyle, pillStyle, componentId)(content)
  }
} 
Example 5
Source File: UdashNavbar.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package nav

import com.avsystem.commons.misc.{AbstractValueEnum, AbstractValueEnumCompanion, EnumCtx}
import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.nav.UdashNavbar.Position
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import org.scalajs.dom.Element
import scalatags.JsDom.all._
import scalatags.JsDom.tags2

final class UdashNavbar[ItemType, ElemType <: ReadableProperty[ItemType]] private(
  expandBreakpoint: ReadableProperty[BootstrapStyles.ResponsiveBreakpoint],
  darkStyle: ReadableProperty[Boolean],
  backgroundStyle: ReadableProperty[BootstrapStyles.Color],
  position: ReadableProperty[UdashNavbar.Position],
  override val componentId: ComponentId
)(
  navigationFactory: Binding.NestedInterceptor => Modifier,
  brand: Modifier
)
  extends UdashBootstrapComponent {

  import io.udash.bootstrap.utils.BootstrapTags._
  import io.udash.css.CssView._

  private val collapseId = ComponentId.generate()

  override val render: Element =
    tags2.nav(
      componentId, BootstrapStyles.NavigationBar.navbar,
      nestedInterceptor(BootstrapStyles.Position.fixedTop.styleIf(position.transform(_ == Position.FixedTop))),
      nestedInterceptor(BootstrapStyles.Position.fixedBottom.styleIf(position.transform(_ == Position.FixedBottom))),
      nestedInterceptor(BootstrapStyles.Position.stickyTop.styleIf(position.transform(_ == Position.StickyTop))),
      nestedInterceptor(((dark: Boolean) =>
        if (dark) BootstrapStyles.NavigationBar.dark
        else BootstrapStyles.NavigationBar.light
      ).reactiveApply(darkStyle)),
      nestedInterceptor((BootstrapStyles.Background.color _).reactiveApply(backgroundStyle)),
      nestedInterceptor((BootstrapStyles.NavigationBar.expand _).reactiveApply(expandBreakpoint))
    )(
      div(BootstrapStyles.NavigationBar.brand)(brand),
      button(
        tpe := "button", dataToggle := "collapse", dataTarget := s"#$collapseId",
        aria.expanded := false, aria.label := "Toggle navigation",
        BootstrapStyles.NavigationBar.toggler
      )(span(BootstrapStyles.NavigationBar.togglerIcon)),
      div(
        collapseId, BootstrapStyles.Collapse.collapse,
        BootstrapStyles.NavigationBar.collapse
      )(
        navigationFactory(nestedInterceptor)
      )
    ).render
}

object UdashNavbar {
  final class Position(implicit enumCtx: EnumCtx) extends AbstractValueEnum
  object Position extends AbstractValueEnumCompanion[Position] {
    final val Auto, FixedTop, FixedBottom, StickyTop: Value = new Position
  }

  
  def customContent[ItemType, ElemType <: ReadableProperty[ItemType]](
    expandBreakpoint: ReadableProperty[BootstrapStyles.ResponsiveBreakpoint] = BootstrapStyles.ResponsiveBreakpoint.Large.toProperty,
    darkStyle: ReadableProperty[Boolean] = UdashBootstrap.False,
    backgroundStyle: ReadableProperty[BootstrapStyles.Color] = BootstrapStyles.Color.Light.toProperty,
    position: ReadableProperty[UdashNavbar.Position] = Position.Auto.toProperty,
    componentId: ComponentId = ComponentId.generate()
  )(
    navigationFactory: Binding.NestedInterceptor => Modifier,
    brand: Modifier = ()
  ): UdashNavbar[ItemType, ElemType] = {
    new UdashNavbar(expandBreakpoint, darkStyle, backgroundStyle, position, componentId)(navigationFactory, brand)
  }
} 
Example 6
Source File: UdashCollapse.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash
package bootstrap
package collapse

import com.avsystem.commons.misc.{AbstractCase, AbstractValueEnum, AbstractValueEnumCompanion, EnumCtx}
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import io.udash.wrappers.jquery.JQuery
import org.scalajs.dom.Element
import scalatags.JsDom.all._
import scalatags.generic.AttrPair

import scala.scalajs.js

final class UdashCollapse private(
  parentSelector: Option[String],
  toggleOnInit: Boolean,
  override val componentId: ComponentId
)(
  content: Binding.NestedInterceptor => Modifier
) extends UdashBootstrapComponent with Listenable {

  import UdashCollapse._
  import io.udash.bootstrap.utils.BootstrapTags._
  import io.udash.css.CssView._
  import io.udash.wrappers.jquery._

  override type EventType = UdashCollapse.CollapseEvent

  
  def apply(
    parentSelector: Option[String] = None,
    toggleOnInit: Boolean = true,
    componentId: ComponentId = ComponentId.generate()
  )(content: Binding.NestedInterceptor => Modifier): UdashCollapse = {
    new UdashCollapse(parentSelector, toggleOnInit, componentId)(content)
  }

  @js.native
  private trait UdashCollapseJQuery extends JQuery {
    def collapse(cmd: String): UdashCollapseJQuery = js.native
  }
} 
Example 7
Source File: BootstrapImplicitsTest.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap

import io.udash._
import io.udash.css.CssStyleName
import io.udash.testing.UdashCoreFrontendTest
import org.scalajs.dom.Element

class BootstrapImplicitsTest extends UdashCoreFrontendTest {
  import io.udash.css.CssView._

  "StyleOps" should {
    "apply style conditionally" in {
      val textArea = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(false)).render
      textArea.hasStyles(BootstrapStyles.Form.control) shouldBe false
      val textArea2 = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(true)).render
      textArea2.hasStyles(BootstrapStyles.Form.control) shouldBe true
    }

    "apply style conditionally from property" in {
      val p = Property(false)
      val textArea = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(p)).render
      textArea.hasStyles(BootstrapStyles.Form.control) shouldBe false
      p.set(true)
      val textArea2 = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(p)).render
      textArea2.hasStyles(BootstrapStyles.Form.control) shouldBe true
    }

    "apply style conditionally from property with `true` on init" in {
      val p = Property(true)
      val textArea = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(p)).render
      textArea.hasStyles(BootstrapStyles.Form.control) shouldBe true
      p.set(false)
      val textArea2 = TextArea(Property(""))(BootstrapStyles.Form.control.styleIf(p)).render
      textArea2.hasStyles(BootstrapStyles.Form.control) shouldBe false
    }
  }

  implicit class ElemOps(elem: Element) {
    def hasStyles(styles: CssStyleName*): Boolean =
      styles
        .map(_.className)
        .forall(elem.classList.contains)
  }
} 
Example 8
Source File: UdashFrontendTest.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.testing

import com.avsystem.commons._
import org.scalajs.dom
import org.scalajs.dom.Element
import org.scalajs.dom.raw.DOMTokenList
import org.scalatest.enablers.Containing

trait FrontendTestUtils {
  def emptyComponent(): Element = dom.document.createElement("div")

  implicit val DOMTokensListContains: Containing[DOMTokenList] = new Containing[DOMTokenList] {
    override def contains(container: DOMTokenList, element: Any): Boolean = element match {
      case s: String => container.contains(s)
      case _ => false
    }

    override def containsOneOf(container: DOMTokenList, elements: BSeq[Any]): Boolean = elements.exists {
      case s: String => container.contains(s)
      case _ => false
    }

    override def containsNoneOf(container: DOMTokenList, elements: BSeq[Any]): Boolean = elements.forall {
      case s: String => container.contains(s)
      case _ => false
    }
  }
}

trait UdashFrontendTest extends UdashSharedTest with FrontendTestUtils

trait AsyncUdashFrontendTest extends AsyncUdashSharedTest with FrontendTestUtils 
Example 9
Source File: ViewRenderer.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.view

import com.avsystem.commons._
import io.udash.core.{ContainerView, View}
import io.udash.utils.FilteringUtils._
import org.scalajs.dom.Element

import scala.collection.mutable


  def renderView(subPathToLeave: Iterator[View], pathToAdd: Iterable[View]): Unit = {
    val currentViewsToLeaveSize = findEqPrefix(subPathToLeave, views.iterator).size
    if (currentViewsToLeaveSize == 0) {
      require(pathToAdd.nonEmpty, "You cannot remove all views, without adding any new view.")
      replaceCurrentViews(pathToAdd)
    } else {
      val removedViews = views.size - currentViewsToLeaveSize
      views.trimEnd(removedViews)
      val rootView = views.last
      val rootViewToAttach = mergeViews(pathToAdd.iterator)
      if (removedViews > 0 || rootViewToAttach.isDefined) renderChild(rootView, rootViewToAttach)
    }
  }
} 
Example 10
Source File: UrlChangeProvider.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.routing

import com.avsystem.commons._
import io.udash.core.Url
import io.udash.properties.MutableBufferRegistration
import io.udash.utils.Registration
import org.scalajs.dom
import org.scalajs.dom.raw.{HTMLAnchorElement, HashChangeEvent}
import org.scalajs.dom.{Element, Location}

import scala.scalajs.js


final class WindowUrlPathChangeProvider extends UrlChangeProvider {

  import dom.window
  import org.scalajs.dom.experimental.{URL => JSUrl}
  import org.scalajs.dom.raw.{MouseEvent, Node, PopStateEvent}

  private val callbacks: js.Array[Url => Unit] = js.Array()

  @inline
  private def isSameOrigin(loc: Location, url: JSUrl): Boolean =
    loc.protocol == url.protocol && loc.hostname == url.hostname && loc.port == url.port

  @inline
  private def isSamePath(loc: Location, url: JSUrl): Boolean =
    loc.pathname == url.pathname && loc.search == url.search

  @inline
  private def isSameHash(loc: Location, url: JSUrl): Boolean =
    loc.hash == url.hash

  @inline
  private def shouldIgnoreClick(
    event: MouseEvent, target: Element, href: String,
    samePath: Boolean, sameHash: Boolean, sameOrigin: Boolean
  ): Boolean = {
    // handle only links in the same browser card
    event.button != 0 || event.metaKey || event.ctrlKey || event.shiftKey ||
      // ignore click if default already prevented
      event.defaultPrevented ||
      // ignore special link types
      target.hasAttribute("download") || target.getAttribute("rel") == "external" || href.contains("mailto:") ||
      // ignore if links to different domain
      !sameOrigin ||
      // ignore if only the URL fragment changed, but path is the same
      (samePath && !sameHash)
  }

  override def initialize(): Unit = {
    window.document.addEventListener("click", (event: MouseEvent) => {
      event.target.opt
        .collect { case node: Node => node }
        .flatMap(Iterator.iterate(_)(_.parentNode).takeWhile(_ != null).collectFirstOpt { case a: HTMLAnchorElement => a })
        .filter(_.getAttribute("href") != null)
        .foreach { target =>
          val href = target.getAttribute("href")
          val location = window.location
          val newUrl = new JSUrl(href, location.toString)
          val (samePath, sameHash, sameOrigin) =
            (isSamePath(location, newUrl), isSameHash(location, newUrl), isSameOrigin(location, newUrl))
          if (!shouldIgnoreClick(event, target, href, samePath, sameHash, sameOrigin)) {
            if (!samePath) changeFragment(Url(href))
            event.preventDefault()
          }
        }
    })

    window.addEventListener("popstate", (_: PopStateEvent) => callbacks.foreach(_.apply(currentFragment)))
  }

  override def onFragmentChange(callback: Url => Unit): Registration = {
    callbacks.push(callback)
    new MutableBufferRegistration(callbacks, callback, Opt.Empty)
  }

  override def changeFragment(url: Url, replaceCurrent: Boolean): Unit = {
    (null, "", url.value) |> (
      if (replaceCurrent) window.history.replaceState(_: js.Any, _: String, _: String)
      else window.history.pushState(_: js.Any, _: String, _: String)
      ).tupled
    val withoutHash = Url(url.value.takeWhile(_ != '#'))
    callbacks.foreach(_.apply(withoutHash))
  }

  override def currentFragment: Url =
    Url(window.history.state.opt.map(_.asInstanceOf[js.Dynamic].url.toString).getOrElse(window.location.pathname))
} 
Example 11
Source File: TextArea.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bindings.inputs

import io.udash._
import org.scalajs.dom.html.TextArea
import org.scalajs.dom.{Element, Event, KeyboardEvent}
import scalatags.JsDom.all._

import scala.concurrent.duration.{Duration, DurationInt}


  def apply(value: Property[String], debounce: Duration = 20 millis)(textareaModifiers: Modifier*): InputBinding[TextArea] =
    new InputBinding[TextArea] {
      private val element = textarea(
        textareaModifiers, nestedInterceptor(new TextAreaModifier(value, Some(debounce)))
      ).render

      override def render: TextArea = element
    }

  private class TextAreaModifier(property: Property[String], debounce: Option[Duration])
    extends TextInputsModifier(property, debounce)  {

    override def elementValue(t: Element): String =
      t.asInstanceOf[TextArea].value

    override def setElementValue(t: Element, v: String): Unit =
      t.asInstanceOf[TextArea].value = v

    override def setElementKeyUp(t: Element, callback: KeyboardEvent => Unit): Unit =
      t.asInstanceOf[TextArea].onkeyup = callback

    override def setElementOnChange(t: Element, callback: Event => Unit): Unit =
      t.asInstanceOf[TextArea].onchange = callback

    override def setElementOnInput(t: Element, callback: Event => Unit): Unit =
      t.asInstanceOf[TextArea].oninput = callback

    override def setElementOnPaste(t: Element, callback: Event => Unit): Unit =
      t.asInstanceOf[TextArea].onpaste = callback
  }
} 
Example 12
Source File: AttrTranslationModifier.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.i18n.bindings

import com.avsystem.commons._
import io.udash.i18n.Translated
import io.udash.logging.CrossLogging
import org.scalajs.dom.Element
import scalatags.JsDom.Modifier

import scala.concurrent.Future
import scala.util.{Failure, Success}

private[i18n] class AttrTranslationModifier(translation: => Future[Translated], attr: String)
  extends Modifier with CrossLogging {

  override def applyTo(t: Element): Unit =
    translation.onCompleteNow {
      case Success(text) =>
        t.setAttribute(attr, text.string)
      case Failure(ex) =>
        logger.error(ex.getMessage)
    }
} 
Example 13
Source File: JSLauncher.scala    From udash-demos   with GNU General Public License v3.0 5 votes vote down vote up
package io.udash.todo

import io.udash.logging.CrossLogging
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element

import scala.scalajs.js.annotation.JSExport

object JSLauncher extends CrossLogging {
  import ApplicationContext._

  @JSExport
  def main(args: Array[String]): Unit = {
    jQ((_: Element) => {
      jQ(".todoapp").get(0) match {
        case None =>
          logger.error("Application root element not found! Check your index.html file!")
        case Some(root) =>
          applicationInstance.run(root)
      }
    })
  }
} 
Example 14
Source File: JSLauncher.scala    From udash-demos   with GNU General Public License v3.0 5 votes vote down vote up
package io.udash.todo

import io.udash.logging.CrossLogging
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element

import scala.scalajs.js.annotation.JSExport

object JSLauncher extends CrossLogging {
  import ApplicationContext._

  @JSExport
  def main(args: Array[String]): Unit = {
    jQ((_: Element) => {
      jQ(".todoapp").get(0) match {
        case None =>
          logger.error("Application root element not found! Check your index.html file!")
        case Some(root) =>
          applicationInstance.run(root)
      }
    })
  }
} 
Example 15
Source File: JSLauncher.scala    From udash-demos   with GNU General Public License v3.0 5 votes vote down vote up
package io.udash.demos.rest

import io.udash.logging.CrossLogging
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element

import scala.scalajs.js.annotation.JSExport

object JSLauncher extends CrossLogging {
  import ApplicationContext._

  @JSExport
  def main(args: Array[String]): Unit = {
    jQ((_: Element) => {
      jQ("#application").get(0) match {
        case None =>
          logger.error("Application root element not found! Check your index.html file!")
        case Some(root) =>
          applicationInstance.run(root)
      }
    })
  }
} 
Example 16
Source File: DismissibleUdashAlert.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package alert

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.button.UdashButton
import io.udash.bootstrap.utils.{BootstrapStyles, BootstrapTags}
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class DismissibleUdashAlert private[alert](
  alertStyle: ReadableProperty[BootstrapStyles.Color], override val componentId: ComponentId
)(content: Binding.NestedInterceptor => Modifier) extends UdashAlertBase(alertStyle, componentId) {
  import io.udash.css.CssView._

  private val _dismissed = Property[Boolean](false)

  def dismissed: ReadableProperty[Boolean] =
    _dismissed.readable

  private val button = UdashButton(buttonStyle = BootstrapStyles.Color.Link.toProperty) { _ => Seq[Modifier](
    componentId.withSuffix("close"),
    `type` := "button", BootstrapStyles.close,
    BootstrapTags.dataDismiss := "alert", aria.label := "close",
    span(aria.hidden := "true")("×")
  )}

  button.listen { case UdashButton.ButtonClickEvent(_, _) =>
    _dismissed.set(true)
  }

  private val buttonRendered = button.render

  override val render: Element = template(
    BootstrapStyles.Alert.dismissible,
    content(nestedInterceptor), buttonRendered
  ).render

  def dismiss(): Unit =
    buttonRendered.click()
}

object DismissibleUdashAlert extends UdashAlertBaseCompanion[DismissibleUdashAlert] {
  protected def create(alertStyle: ReadableProperty[BootstrapStyles.Color], componentId: ComponentId)(
    content: Binding.NestedInterceptor => Modifier
  ): DismissibleUdashAlert = {
    new DismissibleUdashAlert(alertStyle, componentId)(content)
  }
} 
Example 17
Source File: DiffRender.scala    From pine   with Apache License 2.0 5 votes vote down vote up
package pine.dom

import scala.collection.mutable

import org.scalajs.dom.Element

import pine._

object DiffRender {
  def render(dom: Element, diff: Diff): Unit =
    diff match {
      case Diff.SetAttribute(name, value) => dom.setAttribute(name, value)
      case Diff.RemoveAttribute(name) => dom.removeAttribute(name)
      case Diff.UpdateAttribute(name, f) =>
        f(Option(dom.getAttribute(name))) match {
          case None    => dom.removeAttribute(name)
          case Some(v) => dom.setAttribute(name, v)
        }

      case Diff.InsertBefore(childRef, nodes) =>
        val ref = DOM.resolve(dom, childRef)
        nodes.reverse.foreach(child =>
          dom.insertBefore(NodeRender.renderChild(child), ref))

      case Diff.InsertAfter(childRef, nodes) =>
        val ref = DOM.resolve(dom, childRef)
        nodes.reverse.foreach(child =>
          dom.insertAfter(NodeRender.renderChild(child), ref))

      case Diff.SetChildren(children) =>
        dom.removeChildren()
        children.foreach(child =>
          dom.appendChild(NodeRender.renderChild(child)))

      case Diff.Replace(nodes) =>
        nodes.foreach(node =>
          dom.parentNode.insertBefore(NodeRender.renderChild(node), dom))
        dom.parentNode.removeChild(dom)

      case Diff.PrependChildren(children) =>
        children.reverse.foreach(child =>
          dom.prependChild(NodeRender.renderChild(child)))

      case Diff.AppendChildren(children) =>
        children.foreach(child =>
          dom.appendChild(NodeRender.renderChild(child)))

      case Diff.InsertAt(position, children) =>
        children.reverse.foreach(child =>
          dom.insertChildAt(position, NodeRender.renderChild(child)))

      case Diff.RemoveNode => dom.parentNode.removeChild(dom)
    }
}

class DomRenderContext extends RenderContext {
  var committed = false
  val diffs = mutable.Queue.empty[(TagRef[Singleton], Diff)]

  override def render[T <: Singleton](tagRef: TagRef[T], diff: Diff): Unit = {
    if (committed) throw new Exception("Dangling rendering context")
    diffs.enqueue((tagRef.asInstanceOf[TagRef[Singleton]], diff))
  }

  def commit(): Unit = {
    while (diffs.nonEmpty) {
      val (ref, diff) = diffs.dequeue()
      ref.resolve.foreach(node => DiffRender.render(node, diff))
    }

    committed = true
  }
} 
Example 18
Source File: FunctionView.scala    From scala-js-jquery   with Apache License 2.0 5 votes vote down vote up
package io.udash.demos.jquery.views

import org.scalajs.dom.{Element, Event}

abstract class FunctionView {

  import scalatags.JsDom.all._

  protected val content: Element

  protected def script: () => Any

  final def getTemplate: Modifier =
    div(
      content,
      h3(button(
        marginTop := 10.px,
        onclick := ((_: Event) => {
          script()
          false
        })
      )("Run script"))
    )
} 
Example 19
Source File: EachView.scala    From scala-js-jquery   with Apache License 2.0 5 votes vote down vote up
package io.udash.demos.jquery.views.functions

import io.udash.demos.jquery.views.FunctionView
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element


object EachView extends FunctionView {

  import scalatags.JsDom.all._

  override protected val content = div(
    h3(".each()"),
    div("Click button"),
    div("to iterate through"),
    div("these divs.")
  ).render

  override protected def script = () => {
    jQ("div", content).each((el: Element, idx: Int) => {
      jQ(el).replaceWith(span(s"${el.textContent} ").render)
    })
  }
} 
Example 20
Source File: AnimateView.scala    From scala-js-jquery   with Apache License 2.0 5 votes vote down vote up
package io.udash.demos.jquery.views.functions

import io.udash.demos.jquery.views.FunctionView
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element
import scalatags.JsDom.tags2


object AnimateView extends FunctionView {

  import scalatags.JsDom.all._

  override protected val content = div(cls := "animate")(
    h3(".animate() & .click()"),
    tags2.style(
      """.animate div {
        |  background-color: #bca;
        |  width: 200px;
        |  height: 1.1em;
        |  text-align: center;
        |  border: 2px solid green;
        |  margin: 3px;
        |  font-size: 14px;
        |}
        |.animate button {
        |  font-size: 14px;
        |}""".stripMargin
    ),
    button(id := "go1", disabled := "disabled")("» Animate Block1"),
    button(id := "go2", disabled := "disabled")("» Animate Block2"),
    button(id := "go3", disabled := "disabled")("» Animate Both"),
    button(id := "go4", disabled := "disabled")("» Reset"),
    div(id := "block1")("Block1"),
    div(id := "block2")("Block2")
  ).render

  override protected def script = () => {
    jQ("#go1", content).on(EventName.click, (_: Element, _: JQueryEvent) => {
      jQ("#block1", content)
        .animate(Map(
          "width" -> "90%"
        ), AnimationOptions(
          queue = Some(false),
          duration = Some(3000)
        ))
        .animate(Map("fontSize" -> "24px"), 1500)
        .animate(Map("borderRightWidth" -> "15px"), 1500)
    })

    jQ("#go2", content).on(EventName.click, (_: Element, _: JQueryEvent) => {
      jQ("#block2", content)
        .animate(Map("width" -> "90%"), 1000)
        .animate(Map("fontSize" -> "24px"), 1000)
        .animate(Map("borderLeftWidth" -> "15px"), 1000)
    })

    jQ("#go3", content).on(EventName.click, (_: Element, _: JQueryEvent) => {
      jQ("#go1", content).add("#go2", content).trigger("click")
    })

    jQ("#go4", content).on(EventName.click, (_: Element, _: JQueryEvent) => {
      // TODO: It does not work without explicit Map elements type
      import scala.scalajs.js.`|`
      jQ("div", content).css(Map[String, String | Int | Double | Boolean](
        "width" -> "",
        "fontSize" -> "",
        "borderWidth" -> ""
      ))
    })

    jQ("button", content).prop("disabled", "")
  }
} 
Example 21
Source File: AttrView.scala    From scala-js-jquery   with Apache License 2.0 5 votes vote down vote up
package io.udash.demos.jquery.views.functions

import io.udash.demos.jquery.views.FunctionView
import io.udash.wrappers.jquery._
import org.scalajs.dom.html.Div
import org.scalajs.dom.{Element, Event}


object AttrView extends FunctionView {

  import scalatags.JsDom.all._

  override protected val content: Div = div(
    h3(".attr() & .prop()"),
    input(id := "check1", tpe := "checkbox", checked := "checked"),
    label(`for` := "check1")("Check me"),
    p(),
    button(onclick := ((_: Event) => {
      jQ("input", content).attr("data-checked", "checked").trigger("change")
      false
    }))(".attr(\"data-checked\", \"checked\")"),
    button(onclick := ((_: Event) => {
      jQ("input", content).attr("data-checked", "").trigger("change")
      false
    }))(".attr(\"data-checked\", \"\")"),
    button(onclick := ((_: Event) => {
      jQ("input", content).attr("data-checked", null).trigger("change")
      false
    }))(".attr(\"data-checked\", null)"), br(),
    button(onclick := ((_: Event) => {
      jQ("input", content).prop("checked", true).trigger("change")
      false
    }))(".prop(\"checked\", true)"),
    button(onclick := ((_: Event) => {
      jQ("input", content).prop("checked", false).trigger("change")
      false
    }))(".prop(\"checked\", false)")
  ).render

  override protected def script = () => {
    jQ("input", content).on(EventName.change, (input: Element, _: JQueryEvent) => {
      jQ("p", content).html(
        s""".attr('data-checked'): ${jQ(input).attr("data-checked")}<br/>
           |.prop('checked'): ${jQ(input).prop("checked")}<br/>
           |.is(':checked'): ${jQ(input).is(":checked")}""".stripMargin
      )
    }).trigger("change")
  }
} 
Example 22
Source File: OnOneOffView.scala    From scala-js-jquery   with Apache License 2.0 5 votes vote down vote up
package io.udash.demos.jquery.views.functions

import io.udash.demos.jquery.views.FunctionView
import io.udash.wrappers.jquery._
import org.scalajs.dom.html.Div
import org.scalajs.dom.{Element, Event}


object OnOneOffView extends FunctionView {

  import scalatags.JsDom.all._

  val onCallback = (_: Element, _: JQueryEvent) =>
    jQ("ul", content).append(li("This will be added on every click").render)
  val oneCallback = (_: Element, _: JQueryEvent) =>
    jQ("ul", content).append(li("This will be added only once").render)

  override protected val content: Div = div(
    h3(".on() & .one() & .off()"),
    button(id := "click", disabled := "disabled")("Click me"),
    ul(),
    button(
      id := "off",
      disabled := "disabled",
      onclick := ((_: Event) => {
        jQ("#click", content)
          .off(EventName.click, onCallback)
          .off(EventName.click, oneCallback)
        false
      })
    )("Off")
  ).render

  override protected def script = () => {
    jQ("#click", content)
      .on(EventName.click, onCallback)
      .one(EventName.click, oneCallback)

    jQ("button", content)
      .prop("disabled", "")
  }
} 
Example 23
Source File: ManipulationsUI.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.frontend

import org.scalajs.dom.Element
import org.scalajs.dom.html.Input
import org.scalajs.dom.raw.Event
import rx.Var

import scala.scalajs.js.ThisFunction1
import scalatags.JsDom.all._

trait ManipulationsUI {
  lazy val delaySlider = input(id := "delay-slider", tpe := "range", min := 0, max := 2000, step := 100, value := 0, onchange := handleSliderChange).render
  lazy val delayDisplay = span("0 msec").render

  val receiveDelayPanel: Seq[Frag] = {
    Seq(
      div(`class` := "panel-heading", "Receive delay"),
      div(
        `class` := "panel-body",
        delaySlider, delayDisplay,
        p("Warning: can cause TimeoutException! Use with care!")
      )
    )
  }

  val delayMillis: Var[Int] = Var(0)

  def handleSliderChange: ThisFunction1[Element, Event, Unit] = { (self: Element, event: Event) =>
    delayMillis() = self.asInstanceOf[Input].valueAsNumber
  }

  delayMillis.trigger {
    val millis: Int = delayMillis.now
    delaySlider.value = millis.toString
    delayDisplay.innerHTML = s"$millis msec"
  }
} 
Example 24
Source File: Alert.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.frontend.components

import org.scalajs.dom.Element
import org.scalajs.dom.raw.MouseEvent

import scala.concurrent.duration._
import scala.scalajs.js.timers
import scalatags.JsDom.all._

class Alert extends Component {
  private[this] lazy val connectionAlert = div(
    "Connecting...",
    cls := "alert fade in",
    id := "connectionStatus",
    position.fixed, right := 0.px, zIndex := 90210
  ).render

  override def attach(parent: Element): Unit = {
    parent.appendChild(connectionAlert)
  }

  private[this] def updateElement(msg: String, currentClass: String, fn: MouseEvent => Unit = _ => {}): Unit = {
    connectionAlert.onclick = fn
    connectionAlert.innerHTML = msg
    connectionAlert.classList.remove("alert-warning")
    connectionAlert.classList.remove("alert-danger")
    connectionAlert.classList.remove("alert-success")
    connectionAlert.classList.add(currentClass)
    connectionAlert.classList.add("in")
  }

  def success(msg: String, fn: MouseEvent => Unit = _ => {}): Unit = {
    updateElement(msg, "alert-success", fn)
  }

  def warning(msg: String, fn: MouseEvent => Unit = _ => {}): Unit = {
    updateElement(msg, "alert-warning", fn)
  }

  def error(msg: String, fn: MouseEvent => Unit = _ => {}): Unit = {
    updateElement(msg, "alert-danger", fn)
  }

  def fadeOut(after: FiniteDuration = 2.seconds) = timers.setTimeout(after) {
    connectionAlert.classList.remove("in")
  }

} 
Example 25
Source File: TabMenu.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.frontend.components

import org.scalajs.dom.Element
import org.scalajs.dom.raw.HTMLAnchorElement

import scalatags.JsDom.all._

class TabMenu(elemId: String, initTabs: Tab*) extends Component {

  private[this] val navbar = ul(cls := "nav nav-tabs")
  private[this] val tabContent = div(cls := "tab-content")
  private[this] val rendered: Element = div(id := elemId, cls := "menu tab-container", navbar, tabContent).render

  private[this] var tabs: Seq[Tab] = Seq()

  def attachTab(tab: Tab): Unit = {
    tabs :+= tab
    tab.attach(rendered)
    tab.onCreate()
    if (tabs.size == 1)
      activate(tab)
  }

  override def attach(parent: Element): Unit = {
    parent.appendChild(rendered)
    initTabs.foreach(attachTab)
    tabs.headOption.foreach(activate)
  }

  def activate(tab: Tab): Unit = {
    tab.tab.querySelector("a").asInstanceOf[HTMLAnchorElement].click()
  }
} 
Example 26
Source File: UnconnectedOnOff.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.frontend.components

import org.scalajs.dom.{Element, Event}
import rx.Var

import scalatags.JsDom.all._

class UnconnectedOnOff(status: Var[Boolean]) extends OnOffWithLabel with Component {
  lbl.innerHTML = "Show actors without any connections on graph"
  inp.onchange = { e: Event =>
    status() = inp.checked
  }

  override def attach(parent: Element): Unit = {
    val elem = Seq[Frag](
      div(`class` := "panel-body", stateBtn)
    ).render
    parent.appendChild(elem)
  }
} 
Example 27
Source File: nodes.scala    From akka-viz   with MIT License 5 votes vote down vote up
package scalatags.rx

import java.util.concurrent.atomic.AtomicReference

import org.scalajs.dom
import org.scalajs.dom.Element
import org.scalajs.dom.ext._
import org.scalajs.dom.raw.Comment
import rx._

import scala.collection.immutable
import scala.language.implicitConversions
import scalatags.JsDom.all._
import scalatags.jsdom
import scalatags.rx.ext._

trait RxNodeInstances {

  implicit class rxStringFrag(v: Rx[String])(implicit val ctx: Ctx.Owner) extends jsdom.Frag {
    def render: dom.Text = {
      val node = dom.document.createTextNode(v.now)
      v foreach { s => node.replaceData(0, node.length, s) } attachTo node
      node
    }
  }

  implicit class bindRxElement[T <: dom.Element](e: Rx[T])(implicit val ctx: Ctx.Owner) extends Modifier {
    def applyTo(t: Element) = {
      val element = new AtomicReference(e.now)
      t.appendChild(element.get())
      e.triggerLater {
        val current = e.now
        val previous = element getAndSet current
        t.replaceChild(current, previous)
      } attachTo t
    }
  }

  implicit class bindRxElements(e: Rx[immutable.Iterable[Element]])(implicit val ctx: Ctx.Owner) extends Modifier {
    def applyTo(t: Element) = {
      val nonEmpty = e.map { t => if (t.isEmpty) List(new Comment) else t }
      val fragments = new AtomicReference(nonEmpty.now)
      nonEmpty.now foreach t.appendChild
      nonEmpty triggerLater {
        val current = e.now
        val previous = fragments getAndSet current
        val i = t.childNodes.indexOf(previous.head)
        if (i < 0) throw new IllegalStateException("Children changed")
        0 to (previous.size - 1) foreach (_ => t.removeChild(t.childNodes.item(i)))
        if (t.childNodes.length > i) {
          val next = t.childNodes.item(i)
          current foreach (t.insertBefore(_, next))
        } else {
          current foreach t.appendChild
        }
      }
    }
  }

} 
Example 28
Source File: ReactDOM.scala    From slinky   with MIT License 5 votes vote down vote up
package slinky.web

import slinky.core.facade.{React, ReactElement, ReactInstance}
import org.scalajs.dom.Element

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("react-dom", JSImport.Namespace, "ReactDOM")
object ReactDOM extends js.Object {
  def render(component: ReactElement, target: Element): ReactInstance  = js.native
  def hydrate(component: ReactElement, target: Element): ReactInstance = js.native
  def findDOMNode(instance: React.Component): Element                  = js.native

  def unmountComponentAtNode(container: Element): Unit = js.native

  
  def createPortal(child: ReactElement, container: Element): ReactElement = js.native
}

@js.native
@JSImport("react-dom/server", JSImport.Namespace, "ReactDOMServer")
object ReactDOMServer extends js.Object {
  def renderToString(element: ReactElement): String       = js.native
  def renderToStaticMarkup(element: ReactElement): String = js.native

  def renderToNodeStream(element: ReactElement): js.Object       = js.native
  def renderToStaticNodeStream(element: ReactElement): js.Object = js.native
} 
Example 29
Source File: ReactDOMTest.scala    From slinky   with MIT License 5 votes vote down vote up
package slinky.web

import slinky.core.ComponentWrapper
import slinky.core.facade.ReactElement
import org.scalajs.dom.{Element, document}

import scala.scalajs.js
import html._

import org.scalatest.funsuite.AnyFunSuite

object TestComponent extends ComponentWrapper {
  type Props = Unit
  type State = Unit

  class Def(jsProps: js.Object) extends Definition(jsProps) {
    override def initialState: Unit = ()

    override def render(): ReactElement = {
      a()
    }
  }
}

class ReactDOMTest extends AnyFunSuite {
  test("Renders a single element into the DOM") {
    val target = document.createElement("div")
    ReactDOM.render(
      a(),
      target
    )

    assert(target.innerHTML == "<a></a>")
  }

  test("Finds a dom node for a component") {
    val comp: ReactElement = TestComponent(())
    val target = document.createElement("div")
    val instance = ReactDOM.render(
      comp,
      target
    ).asInstanceOf[TestComponent.Def]

    assert(target.childNodes(0).asInstanceOf[Element] == ReactDOM.findDOMNode(instance))
  }

  test("Renders portals to the appropriate container DOM node") {
    val target = document.createElement("div")
    val container = document.createElement("div")
    ReactDOM.render(
      div(
        ReactDOM.createPortal(h1("hi"), container)
      ),
      target
    )

    assert(container.innerHTML == "<h1>hi</h1>")
    assert(target.innerHTML == "<div></div>")
  }

  test("unmountComponentAtNode clears out the container") {
    val container = document.createElement("div")
    ReactDOM.render(
      div("hello"),
      container
    )

    assert(container.innerHTML == "<div>hello</div>")

    ReactDOM.unmountComponentAtNode(container)

    assert(container.innerHTML.length == 0)
  }
} 
Example 30
Source File: CodeBlock.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash
package web.commons.components

import com.avsystem.commons._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.progressbar.UdashProgressBar
import io.udash.bootstrap.utils.BootstrapStyles
import io.udash.web.commons.styles.components.CodeBlockStyles
import org.scalajs.dom.Element
import org.scalajs.dom.html.Pre
import scalatags.JsDom
import scalatags.JsDom.all._

import scala.scalajs.js
import scala.scalajs.js.annotation.JSGlobal

object CodeBlock {
  import io.udash.css.CssView._

  @js.native
  @JSGlobal("Prism")
  private object Prism extends js.Object {
    //https://prismjs.com/extending.html#api
    def highlightAllUnder(element: Element): Unit = js.native
  }

  def apply(data: String, language: String = "language-scala")(styles: CodeBlockStyles): JsDom.TypedTag[Pre] = {
    pre(styles.codeWrapper)(
      ol(styles.codeBlock)(
        data.split("\\r?\\n").map(line =>
          li(code(cls := language)(line))
        )
      )
    )
  }

  def lines(lines: Iterator[String], language: String = "language-scala")(styles: CodeBlockStyles): JsDom.TypedTag[Pre] = {
    pre(styles.codeWrapper)(
      ol(styles.codeBlock)(
        lines.map(line =>
          li(code(cls := language)(line))
        ).toList
      )
    )
  }

  def reactive(data: ReadableProperty[String], placeholder: Modifier, language: String = "language-scala")(styles: CodeBlockStyles): Binding = {
    val progressBar = UdashProgressBar(
      progress = 100.toProperty,
      showPercentage = true.toProperty,
      barStyle = Some(BootstrapStyles.Color.Success).toProperty,
      stripped = true.toProperty,
      animated = true.toProperty
    ) { case _ => b(placeholder) }
    produceWithNested(data)((data, nested) =>
      if (data.isEmpty) ForceBootstrap(nested(progressBar)).render
      else apply(data)(styles).render.setup(rendered => Prism.highlightAllUnder(rendered))
    )
  }
} 
Example 31
Source File: StxsView.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.views

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import com.thoughtworks.binding.Binding.{Constants, Var}
import jbok.app.AppState
import jbok.app.helper.{ContractAddress, TableRenderHelper}
import jbok.core.api.HistoryTransaction
import jbok.core.models.{Address, UInt256}
import org.scalajs.dom.{Element, Event}

final case class StxsView(state: AppState, stxs: Var[List[HistoryTransaction]]) {
  val header: List[String] = List("Tx Hash", "From", "To", "Value")
  val tableRenderHelper    = TableRenderHelper(header)

  @binding.dom
  def renderTable(stxs: List[HistoryTransaction]): Binding[Element] =
    <table class="table-view">
      {tableRenderHelper.renderTableHeader.bind}
      <tbody>
      {
      for (tx <- Constants(stxs: _*)) yield {
        <tr>
            <td>
              <a onclick={(e: Event) => state.searchTxHash(tx.txHash.toHex)}>
                {tx.txHash.toHex}
              </a>
            </td>
            <td>
              {
          val senderAddress = tx.fromAddress.toString
          <a onclick={(e: Event) => state.searchAccount(senderAddress)}>
                {senderAddress}
              </a>
        }
            </td>
            <td>
            {
          if (tx.toAddress == Address.empty) {
            val contractAddress = ContractAddress.getContractAddress(tx.fromAddress, UInt256(tx.nonce)).toString
            <p>Create Contract: <a onclick={(e: Event) => state.searchAccount(contractAddress)}>{contractAddress}</a></p>
          } else {
            <a onclick={(e: Event) => state.searchAccount(tx.toAddress.toString)}>{tx.toAddress.toString}</a>
          }
        }
            </td>
            <td>
              {tx.value.toString}
            </td>
          </tr>
      }
    }
      </tbody>
    </table>

  @binding.dom
  def render: Binding[Element] =
    <div>
    {
      val history = stxs.bind
      if (history.nonEmpty) {
        renderTable(history).bind
      } else {
        tableRenderHelper.renderEmptyTable.bind
      }
    }
    </div>
} 
Example 32
Source File: RegisterView.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.views

import cats.implicits._
import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import com.thoughtworks.binding.Binding.Var
import fastparse.Parsed.Failure
import jbok.app.{AppState, Contract}
import jbok.app.components.{Input, Notification}
import jbok.app.helper.InputValidator
import jbok.core.models.Address
import jbok.evm.solidity.SolidityParser
import org.scalajs.dom.{Element, Event}
import scodec.bits.ByteVector

final case class RegisterView(state: AppState) {
  val currentId = state.activeNode.value

  val contractAddress = Input("Address", "address", validator = InputValidator.isValidAddress)
  val contractCode = Input(
    "Code",
    """pragma solidity ^0.4.0;
      |
      |contract SimpleStorage {
      |    uint storedData;
      |
      |    function set(uint x) public {
      |        storedData = x;
      |    }
      |
      |    function get() public view returns (uint) {
      |        return storedData;
      |    }
      |}
    """.stripMargin,
    `type` = "textarea"
  )
  val statusMessage: Var[Option[String]] = Var(None)

  def checkAndGenerateInput() = {
    statusMessage.value = None
    for {
      address <- if (contractAddress.isValid) Right(contractAddress.value) else Left("not valid contract address.")
      code    <- if (contractCode.isValid) Right(contractCode.value) else Left("not valid contract code.")
    } yield _submit(address, code)
  }

  def _submit(address: String, code: String) = {
    val parseResult     = SolidityParser.parseSource(code)
    val contractAddress = Address(ByteVector.fromValidHex(address))
    parseResult.fold(
      (s, i, e) => {
        val msg = s match {
          case "" =>
            "Position " + e.input.prettyIndex(i) +
              ", found " + Failure.formatTrailing(e.input, i)
          case s => Failure.formatMsg(e.input, List(s -> i), i)
        }
        statusMessage.value = Some(s"parse error: ${msg}")
      },
      (r, i) =>
        currentId.foreach(id => {
          state.nodes.value.get(id).foreach(_.contractsABI.value += contractAddress -> Contract(contractAddress, r.ABI.last.methods))
          statusMessage.value = Some("register success.")
        })
    )
  }

  val registerOnClick = (_: Event) => checkAndGenerateInput().leftMap(error => statusMessage.value = Some(error))

  @binding.dom
  def render: Binding[Element] =
    <div>
      <div>
        <label for="address"><b>Address</b></label>
        {contractAddress.render.bind}
      </div>
      <div>
        <label for="code"><b>Address</b></label>
        {contractCode.render.bind}
      </div>

      {
        val onclose = (_: Event) => statusMessage.value = None
        @binding.dom def content(status: String):Binding[Element] =
          <div style="padding-left: 10px">{status}</div>
        statusMessage.bind match {
          case None => <div/>
          case Some(status) if status =="register success." =>
            Notification.renderSuccess(content(status), onclose).bind
          case Some(status) =>
            Notification.renderWarning(content(status), onclose).bind
        }
      }

      <div>
        <button id="register-contract" onclick={registerOnClick} style={"width: 100%"} >register</button>
      </div>
    </div>

} 
Example 33
Source File: TableRenderHelper.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.helper

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import com.thoughtworks.binding.Binding.Constants
import jbok.app.components.{Empty, Skeleton}
import org.scalajs.dom.Element

final case class TableRenderHelper(header: List[String]) {
  @binding.dom
  val renderTableHeader: Binding[Element] =
    <thead>
      <tr>
        {Constants(header: _*).map { text =>
        <th>{text}</th> }}
      </tr>
    </thead>

  @binding.dom
  val renderEmptyTable: Binding[Element] =
    <div>
      <table>
        {renderTableHeader.bind}
      </table>
      {Empty.render.bind}
    </div>

  @binding.dom
  val renderTableSkeleton: Binding[Element] =
    <div>
      <table>{renderTableHeader.bind}</table>
      {Skeleton.renderTable(3, header.length).bind}
    </div>
} 
Example 34
Source File: Empty.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.components

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import org.scalajs.dom.Element

object Empty {
  private val AntdEmptyImage =
    "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTg0IiBoZWlnaHQ9IjE1MiIgdmlld0JveD0iMCAwIDE4NCAxNTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI0IDMxLjY3KSI+CiAgICAgIDxlbGxpcHNlIGZpbGwtb3BhY2l0eT0iLjgiIGZpbGw9IiNGNUY1RjciIGN4PSI2Ny43OTciIGN5PSIxMDYuODkiIHJ4PSI2Ny43OTciIHJ5PSIxMi42NjgiLz4KICAgICAgPHBhdGggZD0iTTEyMi4wMzQgNjkuNjc0TDk4LjEwOSA0MC4yMjljLTEuMTQ4LTEuMzg2LTIuODI2LTIuMjI1LTQuNTkzLTIuMjI1aC01MS40NGMtMS43NjYgMC0zLjQ0NC44MzktNC41OTIgMi4yMjVMMTMuNTYgNjkuNjc0djE1LjM4M2gxMDguNDc1VjY5LjY3NHoiIGZpbGw9IiNBRUI4QzIiLz4KICAgICAgPHBhdGggZD0iTTEwMS41MzcgODYuMjE0TDgwLjYzIDYxLjEwMmMtMS4wMDEtMS4yMDctMi41MDctMS44NjctNC4wNDgtMS44NjdIMzEuNzI0Yy0xLjU0IDAtMy4wNDcuNjYtNC4wNDggMS44NjdMNi43NjkgODYuMjE0djEzLjc5Mmg5NC43NjhWODYuMjE0eiIgZmlsbD0idXJsKCNsaW5lYXJHcmFkaWVudC0xKSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTMuNTYpIi8+CiAgICAgIDxwYXRoIGQ9Ik0zMy44MyAwaDY3LjkzM2E0IDQgMCAwIDEgNCA0djkzLjM0NGE0IDQgMCAwIDEtNCA0SDMzLjgzYTQgNCAwIDAgMS00LTRWNGE0IDQgMCAwIDEgNC00eiIgZmlsbD0iI0Y1RjVGNyIvPgogICAgICA8cGF0aCBkPSJNNDIuNjc4IDkuOTUzaDUwLjIzN2EyIDIgMCAwIDEgMiAyVjM2LjkxYTIgMiAwIDAgMS0yIDJINDIuNjc4YTIgMiAwIDAgMS0yLTJWMTEuOTUzYTIgMiAwIDAgMSAyLTJ6TTQyLjk0IDQ5Ljc2N2g0OS43MTNhMi4yNjIgMi4yNjIgMCAxIDEgMCA0LjUyNEg0Mi45NGEyLjI2MiAyLjI2MiAwIDAgMSAwLTQuNTI0ek00Mi45NCA2MS41M2g0OS43MTNhMi4yNjIgMi4yNjIgMCAxIDEgMCA0LjUyNUg0Mi45NGEyLjI2MiAyLjI2MiAwIDAgMSAwLTQuNTI1ek0xMjEuODEzIDEwNS4wMzJjLS43NzUgMy4wNzEtMy40OTcgNS4zNi02LjczNSA1LjM2SDIwLjUxNWMtMy4yMzggMC01Ljk2LTIuMjktNi43MzQtNS4zNmE3LjMwOSA3LjMwOSAwIDAgMS0uMjIyLTEuNzlWNjkuNjc1aDI2LjMxOGMyLjkwNyAwIDUuMjUgMi40NDggNS4yNSA1LjQydi4wNGMwIDIuOTcxIDIuMzcgNS4zNyA1LjI3NyA1LjM3aDM0Ljc4NWMyLjkwNyAwIDUuMjc3LTIuNDIxIDUuMjc3LTUuMzkzVjc1LjFjMC0yLjk3MiAyLjM0My01LjQyNiA1LjI1LTUuNDI2aDI2LjMxOHYzMy41NjljMCAuNjE3LS4wNzcgMS4yMTYtLjIyMSAxLjc4OXoiIGZpbGw9IiNEQ0UwRTYiLz4KICAgIDwvZz4KICAgIDxwYXRoIGQ9Ik0xNDkuMTIxIDMzLjI5MmwtNi44MyAyLjY1YTEgMSAwIDAgMS0xLjMxNy0xLjIzbDEuOTM3LTYuMjA3Yy0yLjU4OS0yLjk0NC00LjEwOS02LjUzNC00LjEwOS0xMC40MDhDMTM4LjgwMiA4LjEwMiAxNDguOTIgMCAxNjEuNDAyIDAgMTczLjg4MSAwIDE4NCA4LjEwMiAxODQgMTguMDk3YzAgOS45OTUtMTAuMTE4IDE4LjA5Ny0yMi41OTkgMTguMDk3LTQuNTI4IDAtOC43NDQtMS4wNjYtMTIuMjgtMi45MDJ6IiBmaWxsPSIjRENFMEU2Ii8+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDkuNjUgMTUuMzgzKSIgZmlsbD0iI0ZGRiI+CiAgICAgIDxlbGxpcHNlIGN4PSIyMC42NTQiIGN5PSIzLjE2NyIgcng9IjIuODQ5IiByeT0iMi44MTUiLz4KICAgICAgPHBhdGggZD0iTTUuNjk4IDUuNjNIMEwyLjg5OC43MDR6TTkuMjU5LjcwNGg0Ljk4NVY1LjYzSDkuMjU5eiIvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg=="

  @binding.dom
  def render: Binding[Element] =
    <div class="empty">
      <div class="empty-image">
        <img src={AntdEmptyImage}></img>
      </div>
      <p class="empty-text">no data</p>
      <div class="empty-footer"></div>
    </div>

} 
Example 35
Source File: Skeleton.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.components

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import com.thoughtworks.binding.Binding.Constants
import org.scalajs.dom.Element

object Skeleton {
  val minTableRow = 2
  val minTableCol = 2

  @binding.dom
  def render: Binding[Element] =
    <div></div>

  @binding.dom
  def renderTable(row: Int, column: Int): Binding[Element] = {
    val rowNumber    = row.max(minTableRow)
    val columnNumber = column.max(minTableCol)
    val rowWidth     = f"${100.0 / columnNumber}%.2f"

    <div class="skeleton">
      {
        Constants((1 to rowNumber).toList: _*).map { _ =>
          <div class="row">
          {
            Constants((1 to columnNumber).toList: _*).map { _ =>
              <div class="col" style={s"width: $rowWidth%"}>
                <div class="skeleton-cell"></div>
              </div>
            }
          }
          </div>
        }
      }
    </div>
  }

} 
Example 36
Source File: Form.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.components

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import com.thoughtworks.binding.Binding.{Constants, Var}
import org.scalajs.dom.Element

final case class FormEntry(name: String, `type`: String = "text", value: Var[String] = Var("")) {
  val initValue: String = value.value
}

final case class Form(entries: Constants[Input], submit: Map[String, Input] => Unit) {
  def entryMap = entries.value.map(x => x.name -> x).toMap

  def clear(): Unit = entries.value.foreach(_.clear())

  @binding.dom
  def render: Binding[Element] =
    <div> 
      {
        entries.map { entry =>
          <div>
            <label for={entry.name}>
              <b>{entry.name}</b>
            </label>
            {entry.render.bind}
          </div>
        }
      }
    </div>
} 
Example 37
Source File: Spin.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.components

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import org.scalajs.dom.Element

import scala.util.{Failure, Success, Try}

object Spin {
  @binding.dom
  def render(color: String = "blue"): Binding[Element] =
    <div class="spinner">
        <div class={s"rect1 $color"}></div>
        <div class={s"rect2 $color"}></div>
        <div class={s"rect3 $color"}></div>
        <div class={s"rect4 $color"}></div>
        <div class={s"rect5 $color"}></div>
      </div>

  @binding.dom
  def renderFuture[A](fb: Binding[Option[Try[A]]]): Binding[Element] = fb.bind match {
    case Some(Success(a)) => <div>{a.toString}</div>
    case Some(Failure(e)) => <div>{e.toString}</div>
    case None             => <div>{render().bind}</div>
  }
} 
Example 38
Source File: Notification.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.components

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import org.scalajs.dom.{Element, Event, Node}

object Notification {
  @binding.dom
  def renderInfo(content: Binding[Node], onClick: Event => Unit = (_: Event) => ()): Binding[Element] =
    <div class="notification info">
      <span class="close" onclick={onClick}>&times;</span>
      <strong>Info:</strong>
      <div class="content">{content.bind}</div>
    </div>

  @binding.dom
  def renderSuccess(content: Binding[Element], onClick: Event => Unit = (_: Event) => ()): Binding[Element] =
    <div class="notification success">
      <span class="close" onclick={onClick}>&times;</span>
      <strong>Success:</strong>
      <div class="content">{content.bind}</div>
    </div>

  @binding.dom
  def renderError(content: Binding[Element], onClick: Event => Unit = (_: Event) => ()): Binding[Element] =
    <div class="notification error">
      <span class="close" onclick={onClick}>&times;</span>
      <strong>Error:</strong>
      <div class="content">{content.bind}</div>
    </div>

  @binding.dom
  def renderWarning(content: Binding[Node], onClick: Event => Unit = (_: Event) => ()): Binding[Element] =
    <div class="notification warning">
      <span class="close" onclick={onClick}>&times;</span>
      <strong>Warning:</strong>
      <div class="content">{content.bind}</div>
    </div>
} 
Example 39
Source File: NativeHelpers.scala    From outwatch   with Apache License 2.0 5 votes vote down vote up
package outwatch.helpers

import com.github.ghik.silencer.silent
import org.scalajs.dom.Element
import org.scalajs.dom.raw.CSSStyleDeclaration

import scala.scalajs.js
import scala.scalajs.js.annotation.JSBracketAccess

private[outwatch] object JSDefined {
  // provides an extractor for js.UndefOr
  // https://gitter.im/scala-js/scala-js?at=5c3e221135350772cf375515
  def apply[A](a: A): js.UndefOr[A] = a
  def unapply[A](a: js.UndefOr[A]): UnapplyResult[A] = new UnapplyResult(a)

  final class UnapplyResult[+A](val self: js.UndefOr[A])
  extends AnyVal {
    @inline def isEmpty: Boolean = self eq js.undefined
    
    @inline def get: A = self.asInstanceOf[A]
  }
}

@js.native
@silent("never used|dead code")
private[outwatch] trait DictionaryRawApply[A] extends js.Object {
  @JSBracketAccess
  def apply(key: String): js.UndefOr[A] = js.native
}

private[outwatch] object NativeHelpers {
  implicit class WithRaw[A](val dict: js.Dictionary[A]) extends AnyVal {
    @inline def raw: DictionaryRawApply[A] = dict.asInstanceOf[DictionaryRawApply[A]]
  }

  implicit class RichElement(val elem: Element) extends AnyVal {
    @inline def style: CSSStyleDeclaration = elem.asInstanceOf[js.Dynamic].style.asInstanceOf[CSSStyleDeclaration] // HTMLElement already has .style, but SVGElement doesn't
    @inline def dataset: js.Dictionary[String] = elem.asInstanceOf[js.Dynamic].dataset.asInstanceOf[js.Dictionary[String]] //TODO: https://github.com/scala-js/scala-js-dom/pull/337
  }

  @inline def assign[T](value: T)(f: T => Unit): T = { f(value); value }

  @noinline def appendSeq[T](source: js.Array[T], other: collection.Seq[T]): js.Array[T] = if (other.isEmpty) source else other match {
    case wrappedOther:js.WrappedArray[T] =>
      if (source.isEmpty) wrappedOther.array else source.concat(wrappedOther.array)
    case _ =>
      val arr = new js.Array[T]()
      source.foreach(arr.push(_))
      other.foreach(arr.push(_))
      arr
  }

  @noinline def prependSeq[T](source: js.Array[T], other: collection.Seq[T]): js.Array[T] = if (other.isEmpty) source else other match {
    case wrappedOther:js.WrappedArray[T] =>
      if (source.isEmpty) wrappedOther.array else wrappedOther.array.concat(source)
    case _ =>
      val arr = new js.Array[T]()
      other.foreach(arr.push(_))
      source.foreach(arr.push(_))
      arr
  }
} 
Example 40
Source File: DomChangesPerformer.scala    From levsha   with Apache License 2.0 5 votes vote down vote up
package levsha.dom

import levsha.{Id, XmlNs}
import levsha.impl.DiffRenderContext.ChangesPerformer
import org.scalajs.dom.raw.HTMLElement
import org.scalajs.dom.{Element, Node}
import org.scalajs.{dom => browserDom}

import scala.collection.mutable
import scala.scalajs.js

final class DomChangesPerformer(target: Element) extends ChangesPerformer {

  private val index = mutable.Map[Id, Node](Id.TopLevel -> target)

  private def create(id: Id)(createNewElement: => Node): Unit = {
    val parentId = id.parent
    parentId.flatMap(index.get) foreach { parent =>
      val newEl = createNewElement
      newEl.asInstanceOf[js.Dynamic]
        .vid = id.mkString
      index.get(id) match {
        case Some(oldEl) if oldEl.parentNode == parent =>
          parent.replaceChild(newEl, oldEl)
          index.update(id, newEl)
        case _ =>
          parent.appendChild(newEl)
          index.update(id, newEl)
      }
    }
  }

  def createText(id: Id, text: String): Unit = create(id) {
    browserDom.document.createTextNode(text)
  }

  def create(id: Id, tag: String, xmlNs: String): Unit = create(id) {
    browserDom.document.createElementNS(xmlNs, tag)
  }

  def remove(id: Id): Unit = index.remove(id) foreach { el =>
    el.parentNode.removeChild(el)
  }

  def setAttr(id: Id, xmlNs: String, name: String, value: String): Unit = index.get(id) foreach {
    case node: Element if xmlNs eq XmlNs.html.uri => node.setAttribute(name, value)
    case node: Element => node.setAttributeNS(xmlNs, name, value)
    case node => browserDom.console.warn(s"Can't set attribute to $node")
  }

  def removeAttr(id: Id, xmlNs: String, name: String): Unit = index.get(id) foreach {
    case node: Element if xmlNs eq XmlNs.html.uri => node.removeAttribute(name)
    case node: Element => node.removeAttributeNS(xmlNs, name)
    case node => browserDom.console.warn(s"Can't remove attribute from $node")
  }

  def setStyle(id: Id, name: String, value: String): Unit = index.get(id) foreach {
    case node: HTMLElement => node.style.setProperty(name, value)
    case node => browserDom.console.warn(s"Can't set style to $node")
  }

  def removeStyle(id: Id, name: String): Unit = index.get(id) foreach {
    case node: HTMLElement => node.style.removeProperty(name)
    case node => browserDom.console.warn(s"Can't remove style from $node")
  }
} 
Example 41
Source File: package.scala    From levsha   with Apache License 2.0 5 votes vote down vote up
package levsha

import levsha.dsl.SymbolDsl
import levsha.events.{EventId, EventPhase}
import levsha.impl.DiffRenderContext
import org.scalajs.dom.Element
import org.scalajs.{dom => browser}

import scala.collection.mutable
import levsha.events.calculateEventPropagation

import scala.scalajs.js


package object dom {

  private class Root(root: Element) {

    val miscBuffer = mutable.Buffer.empty[(Id, Misc)]
    var events = Map.empty[EventId, () => Any]
    val performer = new DomChangesPerformer(root)
    val renderContext = DiffRenderContext[Misc](onMisc = Function.untupled(miscBuffer.+=))
    val registeredNativeEvents = mutable.Set.empty[String]
    val nativeEventHandler = { (nativeEvent: browser.Event) =>
      nativeEvent.target.asInstanceOf[js.Dynamic].vid.asInstanceOf[Any] match {
        case () | null => // do nothing
        case vid: String =>
          val targetId = Id(vid)
          calculateEventPropagation(targetId, nativeEvent.`type`) forall { eid =>
            events.get(eid) match {
              case Some(f) => f() == true
              case None => true
            }
          }
      }
    }

    def saveEvents(): Unit = {
      events = miscBuffer.toMap collect {
        case (id, Misc.Event(t, p, f)) =>
          if (!registeredNativeEvents.contains(t)) {
            registeredNativeEvents += t
            root.addEventListener(t, nativeEventHandler)
          }
          EventId(id, t , p) -> f
      }
      
      // Reset the buffer
      miscBuffer.clear()
    }
  }

  private val roots = mutable.Map.empty[Element, Root]

  val symbolDsl = new SymbolDsl[Misc]

  def render(target: Element)(node: Document.Node[Misc]): Unit = {
    val root = roots.getOrElseUpdate(target, new Root(target))
    node(root.renderContext)
    root.saveEvents()
    root.renderContext.diff(root.performer)
    root.renderContext.swap()
  }

  def event(`type`: String, phase: EventPhase = EventPhase.Bubbling)
           (callback: => Any): Misc.Event = {
    Misc.Event(`type`, phase, () => callback)
  }
} 
Example 42
Source File: ErrorView.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.guide.views

import io.udash._
import io.udash.css.CssView
import io.udash.web.commons.styles.GlobalStyles
import io.udash.web.commons.styles.components.FooterStyles
import io.udash.web.commons.styles.utils.StyleConstants
import io.udash.web.guide.Context._
import io.udash.web.guide.styles.partials.{GuideStyles, HeaderStyles}
import io.udash.web.guide.{ErrorState, IntroState}
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element
import scalatags.JsDom.tags2._

object ErrorViewFactory extends StaticViewFactory[ErrorState.type](() => new ErrorView)

class ErrorView extends View with CssView {
  import scalatags.JsDom.all._

  private val content = section(GuideStyles.sectionError)(
    div(GlobalStyles.body)(
      div(GuideStyles.errorInner)(
        p(GuideStyles.errorHead)(
          span(GlobalStyles.red)("Oops! 404"), br(),
          span(
            "The link doesn't work. Or maybe it never did? You can still ",
            a(GlobalStyles.grey, href := "/assets/pdf/origami_crane_printok.pdf", target := "_blank")("make origami")
          ), br(),
          span("... or go "), a(GlobalStyles.red, href := IntroState.url)("home"), span(".")
        )
      )
    )
  ).render

  private lazy val jqTemplate = jQ(content)

  val window = jQ(org.scalajs.dom.window)
  window.on(EventName.resize, (_: Element, _: JQueryEvent) => onResize())
  onResize()

  private def onResize(): Unit = {
    if (window.width <= StyleConstants.MediaQueriesBounds.TabletLandscapeMax) {
      val h = window.height -
        jQ(s".${FooterStyles.footer.className}").outerHeight().getOrElse(0d) -
        jQ(s".${HeaderStyles.header.className}").outerHeight().getOrElse(0d)
      jqTemplate.css("min-height", s"${h}px")
    }
  }

  override def getTemplate: Modifier = content
} 
Example 43
Source File: AlertsDemo.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.guide.views.ext.demo.bootstrap

import io.udash.web.guide.demos.AutoDemo
import io.udash.web.guide.styles.partials.GuideStyles
import scalatags.JsDom.all._

object AlertsDemo extends AutoDemo {

  private val (rendered, source) = {
    import io.udash._
    import io.udash.bootstrap._
    import BootstrapStyles._
    import io.udash.bootstrap.alert._
    import io.udash.bootstrap.button.UdashButton
    import io.udash.css.CssView._
    import org.scalajs.dom.Element
    import scalatags.JsDom.all._

    import scala.util.Random

    val dismissed = SeqProperty.blank[String]

    def contentCentered: Seq[Modifier] = {
      Seq(Display.flex(), Flex.justifyContent(FlexContentJustification.Center))
    }

    def randomDismissible: Element = {
      val title = Random.nextLong().toString
      val alert = DismissibleUdashAlert(
        alertStyle = Color.values(
          Random.nextInt(Color.values.size)
        ).toProperty
      )(div(title, contentCentered))
      alert.dismissed.listen(_ => dismissed.append(title))
      alert.render
    }

    val alerts = div()(
      UdashAlert(Color.Info.toProperty)(div("info", contentCentered)),
      UdashAlert(Color.Success.toProperty)(div("success", contentCentered)),
      UdashAlert(Color.Warning.toProperty)(div("warning", contentCentered)),
      UdashAlert(Color.Danger.toProperty)(div("danger", contentCentered))
    ).render

    val create = UdashButton()("Create dismissible alert")
    create.listen { case _ =>
      alerts.appendChild(randomDismissible)
    }

    div(
      alerts,
      create,
      div(Spacing.margin(
        side = Side.Top,
        size = SpacingSize.Normal
      ))(
        h4("Dismissed: "),
        div(Card.card, Card.body, Background.color(Color.Light))(
          produce(dismissed)(seq => ul(seq.map(li(_))).render)
        )
      )
    ).render
  }.withSourceCode

  override protected def demoWithSource(): (Modifier, Iterator[String]) = {
    import io.udash.css.CssView._
    (rendered.setup(_.applyTags(GuideStyles.frame)), source.linesIterator)
  }
} 
Example 44
Source File: TxView.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.app.views

import com.thoughtworks.binding
import com.thoughtworks.binding.Binding
import jbok.app.AppState
import jbok.core.models.SignedTransaction
import org.scalajs.dom.{Element, Event}

object TxView {
  @binding.dom
  def render(state: AppState, tx: SignedTransaction): Binding[Element] =
    <div>
      <h3>{s"Transaction (${tx.hash.toHex})"}</h3>

      <table class="table-view">
        <tbody>
          <tr>
            <th>amount</th>
            <td>{tx.value.toString()}</td>
          </tr>

          <tr>
            <th>from</th>
            <td>
              {
                val senderAddress = tx.senderAddress.getOrElse("error address").toString
                <a onclick={(e: Event) => state.searchAccount(senderAddress)}>{senderAddress}</a>
              }
            </td>
          </tr>

          <tr>
            <th>to</th>
            <td><a onclick={(e: Event) => state.searchAccount(tx.receivingAddress.toString)}>{tx.receivingAddress.toString}</a></td>
          </tr>

          <tr>
            <th>send data</th>
            <td>{tx.payload.toHex}</td>
          </tr>
        </tbody>
      </table>
    </div>
} 
Example 45
Source File: HeaderNav.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.commons.components

import io.udash.web.commons.styles.components.HeaderNavStyles
import org.scalajs.dom.Element

trait HeaderNav {
  import io.udash.css.CssView._
  import scalatags.JsDom.all._
  import scalatags.JsDom.tags2.nav

  val navStyles: HeaderNavStyles

  case class NavItem(url: String, title: String)

  def navigation(items: NavItem*): Element =
    nav(navStyles.headerNav)(
      ul(navStyles.headerLinkList)(
        items.map(item =>
          li(navStyles.headerLinkWrapper)(
            a(href := item.url, navStyles.headerLink)(item.title)
          )
        )
      )
    ).render
} 
Example 46
Source File: ErrorView.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.homepage.views

import io.udash._
import io.udash.css.CssView
import io.udash.web.commons.styles.GlobalStyles
import io.udash.web.commons.styles.components.FooterStyles
import io.udash.web.commons.styles.utils.StyleConstants
import io.udash.web.homepage.Context._
import io.udash.web.homepage.IndexState
import io.udash.web.homepage.styles.partials.HomepageStyles
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element
import scalatags.JsDom.tags2._

object ErrorViewFactory extends StaticViewFactory[IndexState](() => new ErrorView)

class ErrorView extends View with CssView {
  import scalatags.JsDom.all._

  private val content = section(HomepageStyles.sectionError)(
    div(GlobalStyles.body, HomepageStyles.body)(
      div(HomepageStyles.errorInner)(
        p(HomepageStyles.errorHead)(
          span(GlobalStyles.red)("Oops! 404"), br(),
          span(
            "The link doesn't work. Or maybe it never did? You can still ",
            a(GlobalStyles.grey, href := "/assets/pdf/origami_crane_printok.pdf", target := "_blank")("make origami")
          ), br(),
          span("... or go "), a(GlobalStyles.red, href := IndexState(None).url)("home"), span(".")
        )
      )
    )
  ).render

  private lazy val jqTemplate = jQ(content)

  val window = jQ(org.scalajs.dom.window)
  window.on(EventName.resize, (_: Element, _: JQueryEvent) => onResize())
  onResize()

  private def onResize(): Unit = {
    if (window.width <= StyleConstants.MediaQueriesBounds.TabletLandscapeMax) {
      val h = window.height - jQ(s".${FooterStyles.footer.className}").outerHeight().getOrElse(0d)
      jqTemplate.css("min-height", s"${h}px")
    }
  }

  override def getTemplate: Modifier = content
} 
Example 47
Source File: init.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.homepage

import io.udash._
import io.udash.logging.CrossLogging
import io.udash.routing.WindowUrlPathChangeProvider
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element

import scala.scalajs.js.annotation.JSExport

object Context {
  implicit val executionContext = scalajs.concurrent.JSExecutionContext.Implicits.queue
  private val routingRegistry = new RoutingRegistryDef
  private val viewFactoriesRegistry = new StatesToViewFactoryDef

  implicit val applicationInstance = new Application[RoutingState](routingRegistry, viewFactoriesRegistry, new WindowUrlPathChangeProvider)
}

object Init extends CrossLogging {
  import Context._

  @JSExport
  def main(args: Array[String]): Unit = {
    jQ((_: Element) => {
      val appRoot = jQ("#application").get(0)
      if (appRoot.isEmpty) {
        logger.error("Application root element not found! Check you index.html file!")
      } else applicationInstance.run(appRoot.get)
    })
  }
} 
Example 48
Source File: DemoComponent.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.web.homepage.components.demo

import io.udash._
import io.udash.web.commons.styles.attributes.Attributes
import io.udash.web.commons.views.{Component, Image}
import io.udash.web.homepage.Context._
import io.udash.web.homepage.IndexState
import io.udash.web.homepage.styles.partials.DemoStyles
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element
import scalatags.JsDom.all._
import scalatags.generic.Attr



class DemoComponent(url: Property[IndexState]) extends Component {

  private val fiddleContainer = div(DemoStyles.demoFiddle).render
  private val jqFiddleContainer = jQ(fiddleContainer)

  private val template = div(DemoStyles.demoComponent)(
    Image("laptop.png", "", DemoStyles.laptopImage),
    div(DemoStyles.demoBody)(
      ul(DemoStyles.demoTabs)(
        DemoComponent.demoEntries.map(entry =>
          li(DemoStyles.demoTabsItem)(
            a(DemoStyles.demoTabsLink, href := entry.targetState.url)(
              entry.name
            )
          )
        )
      ),
      fiddleContainer
    )
  ).render

  url.listen(onUrlChange, initUpdate = true)

  private def onUrlChange(update: IndexState) = {
    val entryOption = DemoComponent.demoEntries.find(_.targetState == update)
    val entry = entryOption.getOrElse(DemoComponent.demoEntries.head)
    val urlString = s""""${entry.targetState.url}""""
    val tab = jQ(template).find(s".${DemoStyles.demoTabsLink.className}[href=$urlString]")

    jQ(template).not(tab).find(s".${DemoStyles.demoTabsLink.className}").attr(Attributes.data(Attributes.Active), "false")
    tab.attr(Attributes.data(Attributes.Active), "true")

    jqFiddleContainer
      .animate(Map[String, Any]("opacity" -> 0), 150, EasingFunction.swing,
        (_: Element) => {
          jqFiddleContainer
            .html(entry.fiddle)
            .animate(Map[String, Any]("opacity" -> 1), 200)
        })
  }

  override def getTemplate: Modifier = template
}

object DemoComponent {
  def fiddle(fiddleId: String): Element =
    iframe(
      Attr("frameborder") := "0",
      style := "width: 100%; height: 100%; overflow: hidden;",
      src := s"https://embed.scalafiddle.io/embed?sfid=$fiddleId&theme=dark"
    ).render

  def demoEntries: Seq[DemoEntry] = Seq(
    DemoEntry("Hello World", IndexState(Option("hello")), fiddle("yJVjCFf/0")),
    DemoEntry("Properties", IndexState(Option("properties")), fiddle("a10A6UA/0")),
    DemoEntry("Validation", IndexState(Option("validation")), fiddle("ButwLWQ/0")),
    DemoEntry("i18n", IndexState(Option("i18n")), fiddle("aczBObA/0")),
  )
} 
Example 49
Source File: CssView.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash
package css

import io.udash.bindings.modifiers.{Binding, EmptyModifier}
import org.scalajs.dom.Element
import scalatags.JsDom.all.Modifier

import scala.annotation.tailrec


trait CssView extends CssText {

  import CssView._

  implicit def style2Mod(style: CssStyle): Modifier = new StyleModifier(style)
  implicit def elementOps(element: Element): ElementOps = new ElementOps(element)
  implicit def styleOps(style: CssStyle): StyleOps = new StyleOps(style)
  implicit def styleFactoryOps[T](factory: T => CssStyle): StyleFactoryOps[T] = new StyleFactoryOps[T](factory)
}

object CssView extends CssView {
  private final class StyleModifier(styles: CssStyle*) extends Modifier {
    override def applyTo(t: Element): Unit =
      styles.foreach(_.addTo(t))
  }

  final class ElementOps(private val element: Element) extends AnyVal {
    def styles(styles: CssStyle*): Element = {
      styles.foreach(_.addTo(element))
      element
    }
  }

  final class StyleOps(private val style: CssStyle) extends AnyVal {
    def addTo(element: Element): Unit =
      style.classNames.foreach(element.classList.add)

    def removeFrom(element: Element): Unit = {
      val cl = element.classList
      cl.remove(style.className)
      style.commonPrefixClass.foreach { prefixClass =>
        @tailrec def removePrefix(i: Int = 0): Boolean =
          i >= cl.length || (!cl(i).startsWith(s"$prefixClass-") && removePrefix(i + 1))
        if (removePrefix()) {
          cl.remove(prefixClass)
        }
      }
    }

    def styleIf(property: ReadableProperty[Boolean]): Binding =
      property.reactiveApply(
        (elem, value) =>
          if (value) addTo(elem)
          else removeFrom(elem)
      )

    def styleIf(condition: Boolean): Modifier = {
      if (condition) new StyleModifier(style)
      else new EmptyModifier[Element]
    }
  }

  final class StyleFactoryOps[T](private val factory: T => CssStyle) extends AnyVal {
    def reactiveApply(property: ReadableProperty[T]): Binding =
      reactiveOptionApply(property.transform(Option.apply))

    def reactiveOptionApply(property: ReadableProperty[Option[T]]): Binding = new Binding {
      private var prevStyle: CssStyle = _
      override def applyTo(el: Element): Unit = {
        propertyListeners += property.listen(t => {
          if (prevStyle != null) {
            prevStyle.classNames.foreach(el.classList.remove)
          }
          t match {
            case Some(t) =>
              val newStyle = factory(t)
              newStyle.classNames.foreach(el.classList.add)
              prevStyle = newStyle
            case None =>
              prevStyle = null
          }
        }, initUpdate = true)
      }
    }
  }
} 
Example 50
Source File: UdashInputGroup.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package form

import io.udash._
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class UdashInputGroup private(
  groupSize: ReadableProperty[Option[BootstrapStyles.Size]],
  override val componentId: ComponentId
)(content: Modifier*) extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  override val render: Element =
    div(
      BootstrapStyles.InputGroup.inputGroup,
      nestedInterceptor((BootstrapStyles.InputGroup.size _).reactiveOptionApply(groupSize))
    )(content).render
}

object UdashInputGroup {
  import io.udash.css.CssView._

  
  @inline def appendButton(content: Modifier*): Modifier =
    append(content)

} 
Example 51
Source File: UdashPopover.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package tooltip

import io.udash.bootstrap.utils.BootstrapStyles
import io.udash.wrappers.jquery._
import org.scalajs.dom
import org.scalajs.dom.Element

import scala.scalajs.js

final class UdashPopover(selector: UdashPopover.UdashPopoverJQuery) extends Tooltip {

  
  def destroy(): Unit = {
    off(selector)
    selector.popover("dispose")
  }

  private[tooltip] def reloadContent(): Unit =
    selector.popover("setContent")

  on(selector, "show.bs.popover", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Show)))
  on(selector,"shown.bs.popover", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Shown)))
  on(selector,"hide.bs.popover", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Hide)))
  on(selector,"hidden.bs.popover", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Hidden)))
  on(selector,"inserted.bs.popover", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Inserted)))
}

object UdashPopover extends TooltipUtils[UdashPopover] {
  override protected def initTooltip(options: js.Dictionary[Any])(el: dom.Node): UdashPopover = {
    val tp: UdashPopoverJQuery = jQ(el).asInstanceOf[UdashPopoverJQuery]
    tp.popover(options)
    new UdashPopover(tp)
  }

  override protected val defaultPlacement = Placement.Right
  override protected val defaultTemplate: String = {
    import io.udash.css.CssView._
    import scalatags.Text.all._
    div(BootstrapStyles.Popover.popover, role := "tooltip")(
      div(BootstrapStyles.arrow),
      h3(BootstrapStyles.Popover.header),
      div(BootstrapStyles.Popover.body)
    ).render
  }
  override protected val defaultTrigger: Seq[Trigger] = Seq(Trigger.Click)

  @js.native
  private trait UdashPopoverJQuery extends JQuery {
    def popover(arg: js.Any): UdashPopoverJQuery = js.native
  }
} 
Example 52
Source File: UdashTooltip.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package tooltip

import io.udash.bootstrap.utils.BootstrapStyles
import io.udash.wrappers.jquery._
import org.scalajs.dom
import org.scalajs.dom.Element

import scala.scalajs.js

final class UdashTooltip private(selector: UdashTooltip.UdashTooltipJQuery) extends Tooltip {

  
  def destroy(): Unit = {
    off(selector)
    selector.tooltip("dispose")
  }

  private[tooltip] def reloadContent(): Unit =
    selector.tooltip("setContent")

  on(selector,"show.bs.tooltip", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Show)))
  on(selector,"shown.bs.tooltip", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Shown)))
  on(selector,"hide.bs.tooltip", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Hide)))
  on(selector,"hidden.bs.tooltip", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Hidden)))
  on(selector,"inserted.bs.tooltip", (_: Element, _: JQueryEvent) => fire(TooltipEvent(this, TooltipEvent.EventType.Inserted)))
}

object UdashTooltip extends TooltipUtils[UdashTooltip] {
  override protected def initTooltip(options: js.Dictionary[Any])(el: dom.Node): UdashTooltip = {
    val tp: UdashTooltipJQuery = jQ(el).asInstanceOf[UdashTooltipJQuery]
    tp.tooltip(options)
    new UdashTooltip(tp)
  }

  override protected val defaultPlacement = Placement.Top
  override protected val defaultTemplate: String = {
    import io.udash.css.CssView._
    import scalatags.Text.all._
    div(BootstrapStyles.Tooltip.tooltip, role := "tooltip")(
      div(BootstrapStyles.Tooltip.arrow),
      div(BootstrapStyles.Tooltip.inner)
    ).render
  }
  override protected val defaultTrigger: Seq[Trigger] = Seq(Trigger.Hover, Trigger.Focus)

  @js.native
  private trait UdashTooltipJQuery extends JQuery {
    def tooltip(arg: js.Any): UdashTooltipJQuery = js.native
  }
} 
Example 53
Source File: UdashProgressBar.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package progressbar

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class UdashProgressBar private[progressbar](
  progress: ReadableProperty[Int],
  showPercentage: ReadableProperty[Boolean],
  barStyle: ReadableProperty[Option[BootstrapStyles.Color]],
  stripped: ReadableProperty[Boolean],
  animated: ReadableProperty[Boolean],
  minValue: ReadableProperty[Int],
  maxValue: ReadableProperty[Int],
  minWidthEm: ReadableProperty[Int],
  override val componentId: ComponentId
)(labelFactory: (ReadableProperty[Int], ReadableProperty[Int], ReadableProperty[Int], Binding.NestedInterceptor) => Modifier) extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  protected def barModifiers: Seq[Modifier] = Seq[Modifier](
    role := "progressbar", BootstrapStyles.ProgressBar.progressBar,
    nestedInterceptor(
      width.bind(
        progress.combine(minValue.combine(maxValue)((_, _)))((_, _)).transform {
          case (current, (min, max)) => s"${100 * (current - min) / (max - min)}%"
        }
      )
    ),
    nestedInterceptor(aria.valuenow.bind(progress.transform(_.toString))),
    nestedInterceptor(aria.valuemin.bind(minValue.transform(_.toString))),
    nestedInterceptor(aria.valuemax.bind(maxValue.transform(_.toString))),
    nestedInterceptor(minWidth.bind(minWidthEm.transform(v => s"${v}em"))),
    nestedInterceptor((BootstrapStyles.Background.color _).reactiveOptionApply(barStyle)),
    nestedInterceptor(BootstrapStyles.ProgressBar.animated.styleIf(animated)),
    nestedInterceptor(BootstrapStyles.ProgressBar.striped.styleIf(stripped))
  )

  override val render: Element = {
    div(BootstrapStyles.ProgressBar.progress)(
      div(componentId, barModifiers)(
        nestedInterceptor(
          produceWithNested(showPercentage) { (shouldShow, nested) =>
            if (shouldShow) div(labelFactory(progress, minValue, maxValue, nested)).render
            else span(BootstrapStyles.Visibility.srOnly)(labelFactory(progress, minValue, maxValue, nested)).render
          }
        )
      )
    ).render
  }
}

object UdashProgressBar {
  val ToStringValueStringifier: (ReadableProperty[Int], ReadableProperty[Int], ReadableProperty[Int], Binding.NestedInterceptor) => Modifier =
    (p, _, _, nested) => nested(bind(p.transform(_.toString)))

  
  def apply(
    progress: ReadableProperty[Int],
    showPercentage: ReadableProperty[Boolean] = UdashBootstrap.False,
    barStyle: ReadableProperty[Option[BootstrapStyles.Color]]  = UdashBootstrap.None,
    stripped: ReadableProperty[Boolean] = UdashBootstrap.False,
    animated: ReadableProperty[Boolean] = UdashBootstrap.False,
    minValue: ReadableProperty[Int] = 0.toProperty,
    maxValue: ReadableProperty[Int] = 100.toProperty,
    minWidth: ReadableProperty[Int] = 1.toProperty,
    componentId: ComponentId = ComponentId.generate()
  )(
    labelFactory: (ReadableProperty[Int], ReadableProperty[Int], ReadableProperty[Int], Binding.NestedInterceptor) => Modifier =
      PercentValueStringifier
  ): UdashProgressBar = {
    new UdashProgressBar(
      progress, showPercentage, barStyle, stripped, animated,
      minValue, maxValue, minWidth, componentId
    )(labelFactory)
  }

} 
Example 54
Source File: UdashListGroup.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package list

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import io.udash.properties.seq
import org.scalajs.dom.Element

final class UdashListGroup[ItemType, ElemType <: ReadableProperty[ItemType]] private(
  items: seq.ReadableSeqProperty[ItemType, ElemType],
  flush: ReadableProperty[Boolean],
  override val componentId: ComponentId
)(itemFactory: (ElemType, Binding.NestedInterceptor) => Element) extends UdashBootstrapComponent {
  import io.udash.css.CssView._
  import scalatags.JsDom.all._

  override val render: Element =
    div(
      componentId, BootstrapStyles.ListGroup.listGroup,
      nestedInterceptor(BootstrapStyles.ListGroup.flush.styleIf(flush))
    )(
      nestedInterceptor(
        repeatWithNested(items) { (item, nested) =>
          itemFactory(item, nested).styles(BootstrapStyles.ListGroup.item)
        }
      )
    ).render
}

object UdashListGroup {
  
  def apply[ItemType, ElemType <: ReadableProperty[ItemType]](
    items: seq.ReadableSeqProperty[ItemType, ElemType],
    flush: ReadableProperty[Boolean] = UdashBootstrap.False,
    componentId: ComponentId = ComponentId.generate()
  )(itemFactory: (ElemType, Binding.NestedInterceptor) => Element): UdashListGroup[ItemType, ElemType] =
    new UdashListGroup(items, flush, componentId)(itemFactory)
} 
Example 55
Source File: UdashJumbotron.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package jumbotron

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import org.scalajs.dom.Element
import scalatags.JsDom.all._

final class UdashJumbotron private(
  fluid: ReadableProperty[Boolean],
  override val componentId: ComponentId
)(content: Binding.NestedInterceptor => Modifier) extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  override val render: Element = {
    div(
      componentId,
      BootstrapStyles.Jumbotron.jumbotron,
      nestedInterceptor(BootstrapStyles.Jumbotron.fluid.styleIf(fluid))
    )(content(nestedInterceptor)).render
  }
}

object UdashJumbotron {
  
  def apply(
    fluid: ReadableProperty[Boolean] = UdashBootstrap.False,
    componentId: ComponentId = ComponentId.generate()
  )(content: Binding.NestedInterceptor => Modifier): UdashJumbotron = {
    new UdashJumbotron(fluid, componentId)(content)
  }
} 
Example 56
Source File: UdashBootstrapComponent.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap.utils

import io.udash.bindings.modifiers.Binding
import io.udash.component.Component
import io.udash.wrappers.jquery._
import org.scalajs.dom.Element


trait UdashBootstrapComponent extends Component {
  override val render: Element

  protected class JQueryOnBinding(selector: JQuery, event: EventName, callback: JQueryCallback) extends Binding {
    selector.on(event, callback)

    override def kill(): Unit = {
      super.kill()
      selector.off(event, callback)
    }

    override def applyTo(t: Element): Unit = ()
  }
} 
Example 57
Source File: UdashBreadcrumbs.scala    From udash-core   with Apache License 2.0 5 votes vote down vote up
package io.udash.bootstrap
package breadcrumb

import io.udash._
import io.udash.bindings.modifiers.Binding
import io.udash.bootstrap.utils.{BootstrapStyles, UdashBootstrapComponent}
import io.udash.properties.seq
import org.scalajs.dom.Element
import scalatags.JsDom.all.Modifier

final class UdashBreadcrumbs[ItemType, ElemType <: ReadableProperty[ItemType]] private(
  pages: seq.ReadableSeqProperty[ItemType, ElemType],
  override val componentId: ComponentId
)(
  itemFactory: (ElemType, Binding.NestedInterceptor) => Modifier,
  isActive: ItemType => Boolean
) extends UdashBootstrapComponent {

  import io.udash.css.CssView._

  override val render: Element = {
    import scalatags.JsDom.all._
    import scalatags.JsDom.tags2.nav

    nav(componentId, aria.label := "breadcrumb")(
      ol(BootstrapStyles.Navigation.breadcrumb)(
        nestedInterceptor(
          repeatWithNested(pages) { case (page, nested) =>
            li(
              BootstrapStyles.Navigation.breadcrumbItem,
              nested(BootstrapStyles.active.styleIf(page.transform(isActive)))
            )(itemFactory(page, nested)).render
          }
        )
      )
    ).render
  }
}

object UdashBreadcrumbs {
  import scalatags.JsDom.all._

  
  def text(
    items: ReadableSeqProperty[String],
    componentId: ComponentId = ComponentId.generate()
  )(
    itemFactory: (ReadableProperty[String], Binding.NestedInterceptor) => Modifier = (p, nested) => nested(bind(p)),
    isActive: String => Boolean = (_: String) => false
  ): UdashBreadcrumbs[String, ReadableProperty[String]] = {
    new UdashBreadcrumbs(items, componentId)(itemFactory, isActive)
  }
}