All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.karasiq.bootstrap4.navbar.UniversalNavigationBars.scala Maven / Gradle / Ivy

package com.karasiq.bootstrap4.navbar

import rx.Rx

import com.karasiq.bootstrap.components.BootstrapComponents
import com.karasiq.bootstrap.context.{ClassModifiers, RenderingContext}
import com.karasiq.bootstrap4.grid.Grids
import com.karasiq.bootstrap4.icons.Icons
import com.karasiq.bootstrap4.utils.Utils

trait UniversalNavigationBars { self: RenderingContext with Icons with Grids with Utils with BootstrapComponents with ClassModifiers with NavigationBars with NavigationBarStyles ⇒
  import scalaTags.all._

  import BootstrapAttrs._

  type Navigation = UniversalNavigation
  object Navigation extends NavigationFactory {
    def tabs(tabs: NavigationTab*): Navigation = {
      new UniversalNavigation(Rx(tabs))
    }

    def pills(tabs: NavigationTab*): Navigation = {
      new UniversalNavigation(Rx(tabs), "pills")
    }
  }

  type NavigationBar = NavigationBarBuilder
  object NavigationBar extends NavigationBarFactory {
    def apply(tabs: Seq[NavigationTab] = Nil, barId: String = Bootstrap.newId, brand: Modifier = "Navigation",
              styles: Seq[Modifier] = Seq(NavigationBarStyle.light, NavigationBarStyle.fixedTop, NavigationBarExpand.lg, Bootstrap.background.light),
              inlineContent: Modifier = (),
              container: Modifier ⇒ Modifier = md ⇒ GridSystem.container(md),
              contentContainer: Modifier ⇒ Modifier = md ⇒ GridSystem.container(GridSystem.mkRow(md))): NavigationBarBuilder = {
      NavigationBarBuilder(tabs, barId, brand, styles, inlineContent, container, contentContainer)
    }
  }

  class UniversalNavigation(val navTabs: NavigationTabs, val navType: String = "tabs",
                            val navId: String = Bootstrap.newId)
    extends AbstractNavigation with BootstrapHtmlComponent {

    private def tabContainer = Rx {
      def renderTab(tab: NavigationTab, active: Boolean): Tag = {
        val idLink = this.tabId(tab.id)
        li(`class` := "nav-item", tab.modifiers)(
          a(`class` := "nav-link", "active".classIf(active), href := "#", aria.controls := idLink, role := "tab", `data-toggle` := "tab", `data-target` := s"#$idLink")(
            if (tab.icon != NoIcon) Seq[Modifier](tab.icon, Bootstrap.nbsp) else (),
            tab.name
          )
        )
      }

      val tabs = navTabs()
      val tag = ul(`class` := "nav nav-" + navType, role := "tablist")

      if (tabs.nonEmpty) tag(
        renderTab(tabs.head, active = true),
        for (t ← tabs.tail) yield renderTab(t, active = false)
      ) else tag 
    }

    private def tabContentContainer = Rx {
      def renderPanel(t: NavigationTab): Tag = {
        div(role := "tabpanel", "tab-pane".addClass, "fade".addClass, id := this.tabId(t.id))(
          t.content
        )
      }

      val tabs = navTabs()
      div("tab-content".addClass)(
        renderPanel(tabs.head)("active".addClass, "show".addClass),
        for (t <- tabs.tail) yield renderPanel(t)
      )
    }

    override def renderTag(md: ModifierT*): TagT = {
      div(tabContainer, tabContentContainer, md)
    }
  }

  /**
    * Simple bootstrap navigation bar
    */
  class UniversalNavigationBar(val navTabs: NavigationTabs,
                               val navId: String,
                               brand: Modifier,
                               styles: Seq[Modifier],
                               inlineContent: Modifier,
                               container: Modifier ⇒ Modifier,
                               contentContainer: Modifier ⇒ Modifier)
    extends AbstractNavigationBar with BootstrapComponent {

    private[this] val nav = tag("nav")

    private[this] val tabContainer = Rx {
      def renderTab(active: Boolean, tab: NavigationTab): Tag = {
        val idLink = this.tabId(tab.id)
        li(
          `class` := "nav-item",
          a(href := "#", `class` := "nav-link", "active".classIf(active), aria.controls := idLink,  role := "tab", `data-toggle` := "tab", `data-target` := s"#$idLink", id := idLink + "link")(
            if (tab.icon != NoIcon) Seq[Modifier](tab.icon, Bootstrap.nbsp) else (),
            tab.name
          ),
          tab.modifiers
        )
      }

      val tabs = navTabs()
      val tag = ul(`class` := "navbar-nav nav mr-auto", role := "tablist")
      if (tabs.nonEmpty) tag(
        renderTab(active = true, tabs.head),
        for (tab <- tabs.tail) yield renderTab(active = false, tab)
      ) else tag
    }

    private[this] val tabContentContainer = Rx {
      def renderContent(active: Boolean, tab: NavigationTab): Tag = {
        val tabId = this.tabId(tab.id)
        div(id := tabId, role := "tabpanel", `class` := (if (active) "tab-pane active fade show" else "tab-pane fade"), aria.labelledby := tabId + "link")(
          tab.content
        )
      }

      val tabs = navTabs()
      div(id := s"$navId-tabcontent", `class` := "tab-content")(
        renderContent(active = true, tabs.head),
        for (tab <- tabs.tail) yield renderContent(active = false, tab)
      )
    }

    def navbar(md: Modifier*): Tag = {
      nav(`class` := "navbar", styles)(
        a(href := "javascript:void(0);", `class` := "navbar-brand", brand),
        button(`class` := "navbar-toggler", `type` := "button", `data-toggle` := "collapse", `data-target` := "#" + navId, aria.controls := navId, aria.expanded := false, aria.label := "Toggle navigation", span(`class` := "navbar-toggler-icon")),
        div(`class` := "collapse navbar-collapse", id := navId, tabContainer, inlineContent, md)
      )
    }

    def content: Modifier = {
      tabContentContainer
    }

    def render(md: ModifierT*): ModifierT = {
      Seq(container(navbar(md:_*)), contentContainer(content))
    }
  }

  //noinspection TypeAnnotation
  case class NavigationBarBuilder(navTabs: NavigationTabs, navId: String,
                                  brand: Modifier, styles: Seq[Modifier], inlineContent: Modifier,
                                  container: Modifier ⇒ Modifier, contentContainer: Modifier ⇒ Modifier) extends AbstractNavigationBar with BootstrapComponent {

    def withTabs(tabs: NavigationTabs) = copy(navTabs = tabs)
    def withTabs(tabs: NavigationTab*) = copy(navTabs = NavigationTabs.fromSeq(tabs))
    def withId(id: String) = copy(navId = id)
    def withBrand(brand: Modifier*) = copy(brand = brand)
    def withStyles(styles: Modifier*) = copy(styles = styles)
    def withInlineContent(inlineContent: Modifier) = copy(inlineContent = inlineContent)
    def withContainer(container: Modifier ⇒ Modifier) = copy(container = container)
    def withContentContainer(contentContainer: Modifier ⇒ Modifier) = copy(contentContainer = contentContainer)

    def build(): UniversalNavigationBar = {
      new UniversalNavigationBar(navTabs, navId, brand, styles, inlineContent, container, contentContainer)
    }

    def render(md: ModifierT*): ModifierT = {
      build().render(md:_*)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy