diff --git a/html.go b/html.go index 73c56c18..7b0f4131 100644 --- a/html.go +++ b/html.go @@ -6,92 +6,100 @@ import ( "strings" ) -func pageHTML(title string, content string) string { +func pageHTML(title string, content string, containsview bool, showsearch bool) string { var html bytes.Buffer html.WriteString(` - + -`) - html.WriteString(title) - html.WriteString(` - - +`) + html.WriteString(title) + html.WriteString(` - - +
- +
+
`) + if showsearch { + html.WriteString(``) + } else { + html.WriteString(`
`) + } + html.WriteString(`
+ + + + + + +
`) html.WriteString(content) html.WriteString(`
- - - +
+ + + `) return html.String() } -func bookHTML(b *Book, isCard bool) string { +func bookHTML(b *Book, isInfo bool) string { var html bytes.Buffer - if isCard { - html.WriteString(`
`) - } else { + if isInfo { html.WriteString(`
`) + } else { + html.WriteString(``) } - if !isCard && b.Description != "" { + if isInfo && b.Description != "" { html.WriteString(`
`) html.WriteString(b.Description) html.WriteString(`
`) @@ -141,30 +149,25 @@ func bookHTML(b *Book, isCard bool) string { return html.String() } -func bookListPageHTML(books []Book, title string, notfoundtext string) (html string, notfound bool) { +func bookListPageHTML(books []Book, title string, notfoundtext string, showsearch bool) (html string, notfound bool) { if len(books) == 0 { - return pageHTML("Not Found", notfoundtext), true + return pageHTML("Not Found", notfoundtext, false, false), true } var booksHTML bytes.Buffer - booksHTML.WriteString(`
`) + booksHTML.WriteString(`
`) for _, b := range books { - booksHTML.WriteString(bookHTML(&b, true)) + booksHTML.WriteString(bookHTML(&b, false)) } booksHTML.WriteString(`
`) - return pageHTML(title, booksHTML.String()), false + return pageHTML(title, booksHTML.String(), true, showsearch), false } -func itemCardHTML(title string, description string, link string) string { +func itemCardHTML(title string, link string) string { var html bytes.Buffer - html.WriteString(`
`) - html.WriteString(``) - html.WriteString(`
`) - html.WriteString(description) - html.WriteString(`
`) html.WriteString(`
`) return html.String() } diff --git a/server.go b/server.go index f50976f8..84429096 100644 --- a/server.go +++ b/server.go @@ -149,7 +149,7 @@ html, body { } w.WriteHeader(http.StatusNotFound) - io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid)) + io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid, false, false)) } // AuthorsHandler handles the authors page @@ -170,13 +170,13 @@ func AuthorsHandler(w http.ResponseWriter, r *http.Request) { }, func(a nameID, b nameID) bool { return a.Name < b.Name }) - listHTML.WriteString(`
`) + listHTML.WriteString(`
`) for _, ni := range authors { - listHTML.WriteString(itemCardHTML(ni.Name, "", "/authors/"+ni.ID)) + listHTML.WriteString(itemCardHTML(ni.Name, "/authors/"+ni.ID)) } listHTML.WriteString(`
`) - io.WriteString(w, pageHTML("Authors", listHTML.String())) + io.WriteString(w, pageHTML("Authors", listHTML.String(), true, false)) return } @@ -193,7 +193,7 @@ func AuthorsHandler(w http.ResponseWriter, r *http.Request) { aname = matched[0].Author } - html, notfound := bookListPageHTML(matched, aname, "Author not found") + html, notfound := bookListPageHTML(matched, aname, "Author not found", false) if notfound { w.WriteHeader(http.StatusNotFound) @@ -220,17 +220,17 @@ func SeriesHandler(w http.ResponseWriter, r *http.Request) { }, func(a nameID, b nameID) bool { return a.Name < b.Name }) - listHTML.WriteString(`
`) + listHTML.WriteString(`
`) for _, ni := range series { - listHTML.WriteString(itemCardHTML(ni.Name, "", "/series/"+ni.ID)) + listHTML.WriteString(itemCardHTML(ni.Name, "/series/"+ni.ID)) } listHTML.WriteString(`
`) if len(series) == 0 { - io.WriteString(w, pageHTML("Series", "No series have been found.")) + io.WriteString(w, pageHTML("Series", "No series have been found.", false, false)) return } - io.WriteString(w, pageHTML("Series", listHTML.String())) + io.WriteString(w, pageHTML("Series", listHTML.String(), true, false)) return } @@ -247,7 +247,7 @@ func SeriesHandler(w http.ResponseWriter, r *http.Request) { sname = matched[0].Series.Name } - html, notfound := bookListPageHTML(matched, sname, "Series not found") + html, notfound := bookListPageHTML(matched, sname, "Series not found", false) if notfound { w.WriteHeader(http.StatusNotFound) @@ -269,7 +269,7 @@ func BooksHandler(w http.ResponseWriter, r *http.Request) { return a.ModTime.Unix() > b.ModTime.Unix() }) - html, notfound := bookListPageHTML(matched, "Books", "There are no books in your library.") + html, notfound := bookListPageHTML(matched, "Books", "There are no books in your library.", true) if notfound { w.WriteHeader(http.StatusNotFound) @@ -282,13 +282,13 @@ func BooksHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") for _, b := range books { if b.ID == bid { - io.WriteString(w, pageHTML(b.Title, bookHTML(&b, false))) + io.WriteString(w, pageHTML(b.Title, bookHTML(&b, true), false, false)) return } } w.WriteHeader(http.StatusNotFound) - io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid)) + io.WriteString(w, pageHTML("Not Found", "Could not find book with id "+bid, false, false)) } // SearchHandler handles the search page @@ -299,15 +299,8 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) { if len(q) != 0 { w.Header().Set("Content-Type", "text/html") var booksHTML bytes.Buffer - booksHTML.WriteString(`
-
- -
- -
-
-

`) - booksHTML.WriteString(`
`) + booksHTML.WriteString(``) + booksHTML.WriteString(`
`) matched := false for _, b := range books { matches := false @@ -316,7 +309,7 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) { matches = matches || strings.Contains(strings.ToLower(b.Series.Name), ql) if matches { - booksHTML.WriteString(bookHTML(&b, true)) + booksHTML.WriteString(bookHTML(&b, false)) matched = true } } @@ -324,17 +317,10 @@ func SearchHandler(w http.ResponseWriter, r *http.Request) { if !matched { booksHTML.WriteString("No books matching your query have been found.") } - io.WriteString(w, pageHTML("Search Results", booksHTML.String())) + io.WriteString(w, pageHTML("Search Results", booksHTML.String(), true, true)) } else { w.Header().Set("Content-Type", "text/html") - io.WriteString(w, pageHTML("Search", `
-
- -
- -
-
-

Advanced Search
`)) + io.WriteString(w, pageHTML("Search", `
Advanced Search
`, false, true)) } } diff --git a/static/normalize.css b/static/normalize.css new file mode 100644 index 00000000..fa4e73dd --- /dev/null +++ b/static/normalize.css @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} diff --git a/static/picomodal.js b/static/picomodal.js new file mode 100644 index 00000000..77cf3c6a --- /dev/null +++ b/static/picomodal.js @@ -0,0 +1 @@ +!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],b):"object"==typeof module&&module.exports?module.exports=b():a.picoModal=b()}(this,function(){"use strict";function a(a){return"object"==typeof Node?a instanceof Node:a&&"object"==typeof a&&"number"==typeof a.nodeType}function b(a){return"string"==typeof a}function c(){var a=[];return{watch:a.push.bind(a),trigger:function(b,c){for(var d=!0,e={detail:c,preventDefault:function(){d=!1}},f=0;f.container { + background: #EBEBEB; + -webkit-box-shadow: 0px 0px 20px -2px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 20px -2px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 20px -2px rgba(0, 0, 0, 0.75); +} + +body.light { + background: #EEEEEE; +} + +body.light>.container { + background: #FAFAFA; +} + +body>.container { + margin: 0 auto; + max-width: 860px; +} + +@media only screen and (min-width: 860px) { + body.dark>.container {} + body.light>.container { + border: 1px solid #AAA; + } + body>.container { + margin: 20px auto; + } +} + + +/* ================= NAV ==================== */ + +.nav { + display: block; + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: row; + padding: 20px 40px; + font-size: 18px; + border-bottom: 1px solid #AAA; + text-align: left; +} + +.nav .left, +.nav .right { + display: inline-block; + text-align: left; + flex: 0 0 auto; + vertical-align: middle; + margin: 0; +} + +.nav .right { + text-align: right; + float: right; +} + +.nav a.item, +.nav a.item:link, +.nav a.item:visited { + display: inline-block; + margin: 0 5px; + color: inherit; + text-decoration: none; + border-bottom: 4px solid transparent; + padding: 0 2px; +} + +.nav a.item:hover { + border-bottom: 4px solid #CCC; +} + +.nav a.item:active { + border-bottom: 4px solid #AAA; +} + +.nav a.item.active { + border-bottom: 4px solid green; +} + +@media only screen and (max-width: 860px) { + .nav { + display: block; + display: flex; + justify-content: space-between; + align-items: center; + flex-direction: column; + padding: 10px 10px; + font-size: 16px; + border-bottom: 1px solid #AAA; + text-align: center; + } + .nav .left, + .nav .right { + display: block; + text-align: center; + flex: 0 0 auto; + margin: 5px 0; + } + .nav .right { + text-align: center; + float: none; + } + .nav a.item, + .nav a.item:link, + .nav a.item:visited { + display: inline-block; + margin: 0 5px; + color: inherit; + text-decoration: none; + border-bottom: 4px solid transparent; + padding: 0 2px; + } + .nav a.item:hover { + border-bottom: 4px solid #CCC; + } + .nav a.item:active { + border-bottom: 4px solid #AAA; + } + .nav a.item.active { + border-bottom: 4px solid green; + } + .nav .title { + font-size: 20px; + } +} + + +/* ================= BUTTONS ==================== */ + +.button, +.button:link, +.button:visited, +.btn, +.btn:link, +.btn:visited { + display: inline-block; + border-radius: 5px; + background: #008000; + border: 1px solid #004000; + color: #FFFFFF; + text-decoration: none; + padding: 8px 10px; + margin: 10px 5px; +} + +.button:hover, +.btn:hover { + background: #007000; +} + +.button:active, +.btn:active { + transform: scale(0.98); +} + + +/* ================= CONTENT ==================== */ + +.section { + display: block; + border-bottom: 1px solid #AAA; + padding: 20px 40px; +} + +.section>.title { + display: block; + font-size: 26px; + margin: 20px 0; text-align: center; } +@media only screen and (max-width: 860px) { + .section { + padding: 10px 0; + } + .section>.title { + margin: 20px 0; + } +} + +.section>.body { + display: block; +} + + +/* ================= BOOKS ==================== */ + .books.cards { + display: block; display: flex; flex-wrap: wrap; + flex-direction: row; justify-content: center; + text-align: center; } -.books.cards .book.card { +.books.cards .book { display: inline-block; - background: #fff; - vertical-align: top; + display: inline-flex; + flex-direction: column; + text-align: left; width: 150px; - margin: 5px; + margin: 20px 15px; + border: 1px solid #CCC; + background: #FFFFFF; } -@media only screen and (min-width: 500px) { - .books.cards .book.card { - margin: 10px; +@media only screen and (max-width: 635px) { + .books.cards .book { + margin: 5px; } } -.books.cards .book.card .cover { +.books.cards .book .cover { display: block; width: 100%; height: 225px; } -.books.cards .book.card .cover img { +.books.cards .book .cover img { display: block; width: 100%; max-height: 225px; } -.books.cards .book.card .meta { +.books.cards .book .meta { display: block; padding: 5px; } -.books.cards .book.card .meta .title { +.books.cards .book .meta .title { display: block; font-weight: bold; font-size: 14px; @@ -75,9 +269,10 @@ body { text-overflow: ellipsis; -o-text-overflow: ellipsis; -webkit-text-overflow: ellipsis; + margin-bottom: 2px; } -.books.cards .book.card .meta .author { +.books.cards .book .meta .author { display: block; color: inherit; font-size: 12px; @@ -88,9 +283,10 @@ body { text-overflow: ellipsis; -o-text-overflow: ellipsis; -webkit-text-overflow: ellipsis; + margin-bottom: 3px; } -.books.cards .book.card .meta .series { +.books.cards .book .meta .series { display: block; font-size: 12px; color: inherit; @@ -104,162 +300,413 @@ body { text-transform: uppercase; } -.books.cards .book.card .meta .series .name { +.books.cards .book .meta .series .name { display: inline-block; color: inherit; text-decoration: none; } -.books.cards .book.card .meta .series .index { +.books.cards .book .meta .series .index { display: inline-block; color: inherit; text-decoration: none; } -.books.cards .book.card .meta .description { +.books.cards .book .meta .description { display: none; } -.books.cards .book.card .meta .download { +.books.cards .book .meta .download { display: none; } -.books.cards .book.card .meta .reader { +.books.cards .book .meta .reader { display: none; } -.book.info { - display: flex; +.books.cards .book:hover { + border: 1px solid #AAA; + box-shadow: 0 0 12px -5px black; } -.book.info .cover { +.books.list { display: block; - flex: 0 0 200px; - margin: 10px; } -.book.info .cover img { +.books.list .book { display: block; - max-height: 300px; + display: flex; + height: 80px; + overflow: hidden; + margin: 5px; + padding: 5px; + border: 1px solid #CCC; + background: #FFFFFF; +} + +.books.list .book .cover { + flex: 0 0 60px; + display: inline-block; + vertical-align: top; + width: 60px; + height: 80px; + margin-right: 10px; +} + +.books.list .book .cover img { + display: inline-block; max-width: 100%; - margin: auto; - -webkit-box-shadow: 0 5px 8px -6px #777; - -moz-box-shadow: 0 5px 8px -6px #777; - box-shadow: 0 5px 8px -6px #777; + height: 80px; } -.book.info .meta { - display: block; +.books.list .book .meta { flex: 1; - margin: 10px; + display: inline-block; + vertical-align: top; } -.book.info .meta .title { - display: none; - font-size: 20px; +.books.list .book .meta .title { + display: block; + font-weight: bold; + font-size: 16px; + color: inherit; + text-decoration: none; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -webkit-text-overflow: ellipsis; + margin-bottom: 2px; + padding: 2px 0; } -.book.info .meta .author { +.books.list .book .meta .author { display: block; - font-size: 20px; + color: inherit; + font-size: 14px; + text-decoration: none; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -webkit-text-overflow: ellipsis; + margin-bottom: 3px; + padding: 1px 0; } -.book.info .meta .author:before { - color: #000; - text-decoration: none !important; - content: 'By: '; +.books.list .book .meta .series { + display: block; + font-size: 14px; + color: inherit; + text-decoration: none; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + -webkit-text-overflow: ellipsis; + padding: 1px 0; } -.book.info .meta .series:before { - color: #000; - text-decoration: none !important; - content: 'Series: '; +.books.list .book .meta .series .name { + display: inline-block; + color: inherit; + text-decoration: none; } -.book.info .meta .series { - display: block; - font-size: 18px; +.books.list .book .meta .series .index { + display: inline-block; + color: inherit; + text-decoration: none; } -.book.info .meta .series .name { - display: inline-block; +.books.list .book .meta .description { + display: none; +} + +.books.list .book .meta .download { + display: none; +} + +.books.list .book .meta .reader { + display: none; } -.book.info .meta .series .index { +.books.list .book:hover { + border: 1px solid #AAA; + box-shadow: 0 0 12px -5px black; +} + +.bar { + display: flex; + margin: 10px 0; + text-align: center; +} + +.bar>div { display: inline-block; + margin: 5px; + text-align: left; } -@media only screen and (max-width: 500px) { - .book.info { - display: block; - } - .book.info .meta .author, - .book.info .meta .series { - text-align: center; - } +.bar .search { + display: inline-block; + display: flex; + flex: 1; } -.book.info .meta .description { - display: block; - padding-top: 10px; - border-top: 1px solid #CCC; - margin-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid #CCC; - margin-bottom: 10px; +.bar .search form { + display: inline-block; + display: flex; + flex: 1; + border: none; + background: #FAFAFA; } -.book.info .meta .download { +.bar .search form .q { display: inline-block; + display: flex; + flex: 1; + border: none; + background: transparent; + padding: 6px; + outline: none; + border: 1px solid #CCC; + border-right: none; +} + +.bar .search form .q:focus { + border: 1px solid #AAA; + border-right: none; } -.book.info .meta .reader { +.bar .search form .s { display: inline-block; + display: flex; + flex: 0 0 auto; + border: none; + background: transparent; + padding: 6px 10px; + border: 1px solid #CCC; + border-left: 1px solid #CCC; + outline: 0; +} + +.bar .search form .s:hover { + background: #EAEAEA; + cursor: pointer; + border-left: 1px solid #CCC; } -.item.card { +.bar .search form .s:active { + background: #E0E0E0; + cursor: pointer; + border-left: 1px solid #CCC; + box-shadow: inset 0 0 11px -5px black; +} + +.bar .view-buttons { display: inline-block; - background: #fff; - vertical-align: top; - color: inherit; - text-decoration: none; - width: 150px; - margin: 5px; - padding: 5px; + display: flex; } -.item.card .title { - display: block; - font-weight: bold; - font-size: 14px; +.bar .view-buttons .view-button, +.bar .view-buttons .view-button:link, +.bar .view-buttons .view-button:visited { + border: 1px solid #CCC; + border-right: none; color: inherit; text-decoration: none; - width: 100%; + display: flex; + flex: 0 0 auto; + background: transparent; + padding: 6px 10px; + outline: 0; +} + +.bar .view-buttons .view-button:hover { + background: #EAEAEA; + cursor: pointer; + border-left: 1px solid #CCC; +} + +.bar .view-buttons .view-button:active, +.bar .view-buttons .view-button.active { + background: #E0E0E0; + cursor: pointer; + border-left: 1px solid #CCC; + box-shadow: inset 0 0 11px -5px black; +} + +.bar .view-buttons .list.view-button { + border-right: 1px solid #CCC; +} + +.items.cards { + text-align: center; +} + +.items.cards .item { + display: inline-block; + margin: 5px; + padding: 5px; + border: 1px solid #CCC; + background: #FFFFFF; + width: 150px; + max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; -o-text-overflow: ellipsis; -webkit-text-overflow: ellipsis; + color: inherit; + text-decoration: none; + text-align: center; +} + +.items.cards .item:hover { + border: 1px solid #AAA; + box-shadow: 0 0 12px -5px black; +} + +.items.list { + text-align: center; } -.item.card .description { +.items.list .item { display: block; - font-size: 12px; - color: inherit; - text-decoration: none; - width: 100%; + margin: 5px; + padding: 5px; + border: 1px solid #CCC; + background: #FFFFFF; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; -o-text-overflow: ellipsis; -webkit-text-overflow: ellipsis; + color: inherit; + text-decoration: none; + text-align: left; } -.book.card, .item.card { - border: 1px solid #CCC; -} - -.book.card:hover, .item.card:hover { +.items.list .item:hover { border: 1px solid #AAA; box-shadow: 0 0 12px -5px black; +} + +.book.info { + display: table; + flex-direction: row; + margin: 20px 0; +} + +.book.info .cover { + display: table-cell; + vertical-align: top; + width: 200px; + flex: 0 0 200px; + height: 100%; +} + +.book.info .cover img { + display: inline-block; + vertical-align: top; + width: 100%; + max-height: 305px; +} + +.book.info .meta { + display: table-cell; + padding-left: 15px; +} + +.book.info .meta .title { + display: block; + font-size: 28px; + margin: 5px 0; + margin-top: 0; + color: #337ab7; + text-decoration: none; + cursor: pointer; +} + +.book.info .meta .author { + display: block; + font-size: 20px; + margin: 5px 0; + margin-bottom: 10px; + color: inherit; + text-decoration: none; + color: #337ab7; + text-decoration: none; + cursor: pointer; +} + +.book.info .meta .series { + display: block; + font-size: 20px; + margin: 5px 0; + margin-bottom: 10px; + color: inherit; + text-decoration: none; +} + +.book.info .meta .series a { + color: #337ab7; + text-decoration: none; + cursor: pointer; +} + +.book.info .meta .description { + display: block; + padding: 20px; + margin-right: 15px; + margin-top: 10px; + border-top: 1px solid #CCCCCC; +} + +.book.info .meta .btn-group { + display: block; + padding-top: 10px; + margin-right: 15px; + border-top: 1px solid #CCCCCC; +} + +@media only screen and (max-width: 600px) { + .book.info { + flex-direction: column; + display: block; + } + .book.info .cover { + display: block; + margin: 30px auto; + width: 180px; + flex: 0 0 180px; + } + .book.info .meta { + padding-left: 15px; + } + .book.info .meta .title { + text-align: center; + } + .book.info .meta .author { + text-align: center; + } + .book.info .meta .series { + text-align: center; + } + .book.info .meta .btn-group { + text-align: center; + } +} + +.footer.section { + font-size: 12px; + text-align: center; +} + +body.no-contains-view .view-buttons { + display: none !important; } \ No newline at end of file diff --git a/static/updater.js b/static/updater.js index 133290ca..dd6d5e3e 100644 --- a/static/updater.js +++ b/static/updater.js @@ -97,9 +97,7 @@ window.checkForUpdates = function(version) { console.log(message); if (window.location.pathname == "/books/") { - var modalHTML = ''; - document.body.appendChild(document.createElement("div")).innerHTML = modalHTML; - $('#updateModal').modal('show'); + picoModal('

BookBrowser Update Available

' + message + '
Update').show(); } } catch (err) { console.warn(err); diff --git a/static/view.js b/static/view.js new file mode 100644 index 00000000..40d315af --- /dev/null +++ b/static/view.js @@ -0,0 +1,45 @@ +if (document.body.className.indexOf("no-contains-view")>-1) { + console.log("No view detected"); +} else { + var cvbtn = document.querySelector(".view-buttons .cards"); + var lvbtn = document.querySelector(".view-buttons .list"); + var vlst = document.querySelector(".view"); + + var listView = function () { + cvbtn.classList.remove("active"); + lvbtn.classList.add("active"); + vlst.classList.remove("cards"); + vlst.classList.add("list"); + localStorage.setItem("view", "list"); + } + + var cardsView = function () { + lvbtn.classList.remove("active"); + cvbtn.classList.add("active"); + vlst.classList.remove("list"); + vlst.classList.add("cards"); + localStorage.setItem("view", "cards"); + } + + var restoreView = function () { + if (localStorage in window) { + var v = localStorage.getItem("view"); + if (v !== null) { + if (v == "list") { + listView(); + } else { + cardsView(); + } + } else { + cardsView(); + } + } else { + cardsView(); + } + } + + lvbtn.addEventListener("click", listView); + cvbtn.addEventListener("click", cardsView); + + restoreView(); +} \ No newline at end of file