From 0567fff028f2f8db6fe5034ce92d52f62469ae1f Mon Sep 17 00:00:00 2001 From: Joris Date: Sun, 26 Feb 2017 16:29:25 +0100 Subject: Use anchor instead of div or button for filters and details tags --- README.md | 5 +-- src/main/scala/reading/Route.scala | 7 +++- .../scala/reading/component/index/BookDetail.scala | 13 +++++-- src/main/scala/reading/component/index/Books.scala | 15 +++++--- .../scala/reading/component/index/Filters.scala | 11 ++++-- src/main/scala/reading/component/index/Menu.scala | 45 ++++++++++++---------- .../reading/component/index/style/Books.scala | 2 + .../scala/reading/component/index/style/Menu.scala | 17 +++++--- .../scala/reading/component/style/Global.scala | 5 +-- .../scala/reading/component/widget/Input.scala | 2 + .../reading/component/widget/style/Input.scala | 10 ++++- 11 files changed, 84 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index a19499d..2e62924 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,5 @@ Dev environment: TODO ---- -- Resumes for every book -- Click on filter on a book detail must do something -- Links attached to filters and book details +- Add a resume to every book. +- Filter when the user click on a theme / genre / program on book detail. diff --git a/src/main/scala/reading/Route.scala b/src/main/scala/reading/Route.scala index 76a9431..f098468 100644 --- a/src/main/scala/reading/Route.scala +++ b/src/main/scala/reading/Route.scala @@ -1,6 +1,6 @@ package reading -import org.scalajs.dom.window +import org.scalajs.dom.{ window, MouseEvent } import org.scalajs.dom.raw.PopStateEvent import scala.scalajs.js.URIUtils @@ -19,6 +19,11 @@ object Route { current() = parse(window.location.hash) } + // Prevent page changes when clicking with the mouse left button + window.onclick = { (event: MouseEvent) => + if (event.button == 0) event.preventDefault() + } + def parse(hash: String): Route = pathAndParams(hash) match { case ("books" :: Nil, params) => { diff --git a/src/main/scala/reading/component/index/BookDetail.scala b/src/main/scala/reading/component/index/BookDetail.scala index 24f48b3..f532c02 100644 --- a/src/main/scala/reading/component/index/BookDetail.scala +++ b/src/main/scala/reading/component/index/BookDetail.scala @@ -8,12 +8,18 @@ import scalatags.JsDom.all._ import reading.component.index.style.{ BookDetail => BookStyle } import reading.component.widget.AnimateMethod -import reading.models.{ Book, Program } +import reading.models.{ Book, Program, Filter } +import reading.Route object BookDetail { val componentId = s"books${Random.nextInt}" - def apply(book: Book, parentId: String, onClose: => Unit): Frag = { + def apply( + filters: Seq[Filter], + book: Book, + parentId: String, + onClose: => Unit + ): Frag = { val titleParts = if (book.parts > 1) s", ${book.parts} volumes" else "" val grades = book.programs.map(Program.grade(_)).distinct.sorted @@ -62,9 +68,10 @@ object BookDetail { definition("niveau", "niveaux", Seq(book.level.prettyPrint)) ), - button( + a( BookStyle.close, onclick := (() => onClose), + href := Route.url(Route.Books(filters)), "Fermer" ) ) diff --git a/src/main/scala/reading/component/index/Books.scala b/src/main/scala/reading/component/index/Books.scala index b5e172b..f15e2dc 100644 --- a/src/main/scala/reading/component/index/Books.scala +++ b/src/main/scala/reading/component/index/Books.scala @@ -50,17 +50,20 @@ object Books { searchedBooks().sorted.map { book => div( BooksStyle.book, - img( - BooksStyle.cover, - src := s"cover/${book.title}.jpg", - alt := s"${book.title}, ${book.author}", + a( + href := Rx(Route.url(Route.Books(filters = filters(), detail = Some(book)))), onclick := (() => { Route.push(Route.Books(filters.now, Some(book))) AnimateMethod.fadeOut( id = componentId, onEnd = detail() = Some(book) ) - }) + }), + img( + BooksStyle.cover, + src := s"cover/${book.title}.jpg", + alt := s"${book.title}, ${book.author}" + ) ) ) } @@ -72,7 +75,7 @@ object Books { Rx { detail() match { case Some(book) => - BookDetail(book, componentId, onClose = closeDetail(filters, detail)) + BookDetail(filters.now, book, componentId, onClose = closeDetail(filters, detail)) case None => span("") } diff --git a/src/main/scala/reading/component/index/Filters.scala b/src/main/scala/reading/component/index/Filters.scala index 3aa26e8..935e501 100644 --- a/src/main/scala/reading/component/index/Filters.scala +++ b/src/main/scala/reading/component/index/Filters.scala @@ -2,14 +2,15 @@ package reading.component.index import rx._ -import scalatags.JsDom.all._ import scalacss.Defaults._ import scalacss.ScalatagsCss._ +import scalatags.JsDom.all._ import reading.component.index.style.{ Filters => FiltersStyle } -import reading.component.widget.Cross import reading.component.style.{ Color => C } +import reading.component.widget.Cross import reading.models.{ Filter, Book } +import reading.Route import reading.utils.RxUtils._ object Filters { @@ -43,16 +44,18 @@ object Filters { div( FiltersStyle.values, - div( + a( FiltersStyle.clear, onclick := (() => FilterUtils.removeAll(filters, detail, search)), + href := Route.url(Route.Books()), "Effacer les filtres" ), filters().sortBy(_.name).map { filter => - div( + a( FiltersStyle.filter, onclick := (() => FilterUtils.remove(filters, detail, search, filter)), + href := Rx(Route.url(Route.Books(Filter.remove(filters(), filter)))), span(FiltersStyle.name, filter.name.capitalize), Cross(15.px, C.gray.value) ) diff --git a/src/main/scala/reading/component/index/Menu.scala b/src/main/scala/reading/component/index/Menu.scala index cfeb6d4..0ea6ca4 100644 --- a/src/main/scala/reading/component/index/Menu.scala +++ b/src/main/scala/reading/component/index/Menu.scala @@ -8,6 +8,7 @@ import scalatags.JsDom.all._ import reading.component.index.style.{ Menu => MenuStyle } import reading.models._ +import reading.Route import reading.utils.RxUtils._ object Menu { @@ -88,8 +89,11 @@ object Menu { span("") else div( - div( + a( MenuStyle.filterTitle, + parentFilter.map { filter => + href := Route.url(Route.Books(filters = Filter.remove(filters(), filter))) + }.getOrElse(""), parentFilter.map { filter => onclick := (() => FilterUtils.remove(filters, detail, search, filter)) }.getOrElse(""), @@ -104,10 +108,14 @@ object Menu { filtersWithCount().map { case (filter, count) => { val isActive = Filter.contains(filters(), filter) + val route = Route.Books( + filters = if (isActive) Filter.remove(filters(), filter) else filter +: filters() + ) - button( + a( MenuStyle.filter, if (isActive) MenuStyle.activeFilter else "", + href := Rx(Route.url(route)), onclick := (() => if (isActive) FilterUtils.remove(filters, detail, search, filter) @@ -135,25 +143,22 @@ object Menu { implicit ctx: Ctx.Owner ): Frag = - Rx { - div( - MenuStyle.footer, + div( + MenuStyle.footer, - if (filters().nonEmpty) - div( - MenuStyle.clear, - onclick := (() => if (filters.now.nonEmpty) FilterUtils.removeAll(filters, detail, search)), - "Effacer" - ) - else - span(""), + a( + MenuStyle.clear, + Rx(if (filters().nonEmpty) MenuStyle.clearActive else MenuStyle.empty), + href := Route.url(Route.Books()), + onclick := (() => if (filters.now.nonEmpty) FilterUtils.removeAll(filters, detail, search)), + "Effacer" + ), - div( - MenuStyle.returnToBooks, - onclick := (() => showFiltersMenu() = false), - "Afficher", - span(MenuStyle.bookCount, books().length) - ) + div( + MenuStyle.returnToBooks, + onclick := (() => showFiltersMenu() = false), + "Afficher", + Rx(span(MenuStyle.bookCount, books().length)) ) - } + ) } diff --git a/src/main/scala/reading/component/index/style/Books.scala b/src/main/scala/reading/component/index/style/Books.scala index f7c1ffc..a1f0374 100644 --- a/src/main/scala/reading/component/index/style/Books.scala +++ b/src/main/scala/reading/component/index/style/Books.scala @@ -41,6 +41,8 @@ object Books extends StyleSheet.Inline { display.inlineBlock, backgroundColor(C.gray.lighten(90).value), cursor.pointer, + transition := "transform 0.2s ease-in-out", + &.hover(transform := "scale(1.1)"), Media.desktop( height(250.px), maxWidth(200.px) diff --git a/src/main/scala/reading/component/index/style/Menu.scala b/src/main/scala/reading/component/index/style/Menu.scala index 09f529c..d824a1a 100644 --- a/src/main/scala/reading/component/index/style/Menu.scala +++ b/src/main/scala/reading/component/index/style/Menu.scala @@ -101,20 +101,26 @@ object Menu extends StyleSheet.Inline { Media.desktop(display.none), Media.mobile( display.flex, - width(100.%%), height(60.px) ) ) val clear = style( Commons.footerButton, - border(2.px, solid, C.gray.value) + border(2.px, solid, C.gray.value), + opacity(0.3) + ) + + val clearActive = style( + opacity(1), + cursor.pointer ) val returnToBooks = style( Commons.footerButton, backgroundColor(C.stiletto.value), - color(C.white.value) + color(C.white.value), + cursor.pointer ) val bookCount = style( @@ -136,14 +142,13 @@ object Commons extends StyleSheet.Inline { val footerButton = style( display.flex, - flexGrow(1), + width(50.%%), justifyContent.center, alignItems.center, height(50.px), margin(5.px), textTransform.uppercase, fontSize(14.px), - fontWeight.bold, - cursor.pointer + fontWeight.bold ) } diff --git a/src/main/scala/reading/component/style/Global.scala b/src/main/scala/reading/component/style/Global.scala index b7bf38c..9551424 100644 --- a/src/main/scala/reading/component/style/Global.scala +++ b/src/main/scala/reading/component/style/Global.scala @@ -18,10 +18,7 @@ object Global extends StyleSheet.Standalone { ) "a" - ( - color(C.eastBay.value), - &.hover( - textDecoration := "underline" - ) + color(inherit) ) "*, *:before, *:after" - ( diff --git a/src/main/scala/reading/component/widget/Input.scala b/src/main/scala/reading/component/widget/Input.scala index 1a1157e..9855c5f 100644 --- a/src/main/scala/reading/component/widget/Input.scala +++ b/src/main/scala/reading/component/widget/Input.scala @@ -12,6 +12,7 @@ import rx._ import reading.component.style.{ Color => C } import reading.component.widget.style.{ Input => InputStyle } +import reading.utils.RxUtils._ object Input { def apply( @@ -47,6 +48,7 @@ object Input { inputBox, span( InputStyle.clear, + Rx(if (query().nonEmpty) InputStyle.showClear else InputStyle.empty), onclick := (() => query() = ""), Cross(15.px, C.gray.value) ) diff --git a/src/main/scala/reading/component/widget/style/Input.scala b/src/main/scala/reading/component/widget/style/Input.scala index 9453640..a9d61dc 100644 --- a/src/main/scala/reading/component/widget/style/Input.scala +++ b/src/main/scala/reading/component/widget/style/Input.scala @@ -26,6 +26,14 @@ object Input extends StyleSheet.Inline { display.flex, height(100.%%), alignItems.center, - cursor.pointer + cursor.pointer, + opacity(0), + transition := "opacity 0.2s ease-in-out" ) + + val showClear = style( + opacity(1) + ) + + val empty = style() } -- cgit v1.2.3