Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -10,7 +10,7 @@ app.templates.aboutPage = -> """ · 9 unmodified lines | |||
| 10 | </ul> | 10 | </ul> |
| 11 | </nav> | 11 | </nav> |
| 12 | 12 | ||
| 13 | <h1 class="_lined-heading">API Documentation Browser</h1> | 13 | <h1 class="_lined-heading">DevDocs: API Documentation Browser</h1> |
| 14 | <p>DevDocs combines multiple API documentations in a fast, organized, and searchable interface. | 14 | <p>DevDocs combines multiple API documentations in a fast, organized, and searchable interface. |
| 15 | <ul> | 15 | <ul> |
| 16 | <li>Created and maintained by <a href="http://thibaut.me">Thibaut Courouble</a> | 16 | <li>Created and maintained by <a href="http://thibaut.me">Thibaut Courouble</a> |
| @@ -26,7 +26,7 @@ app.templates.aboutPage = -> """ · 9 unmodified lines | |||
| 26 | <p class="_note _note-green">If you like DevDocs, please consider supporting my work on | 26 | <p class="_note _note-green">If you like DevDocs, please consider supporting my work on |
| 27 | <a href="https://gratipay.com/devdocs/">Gratipay</a>. Thanks!<br> | 27 | <a href="https://gratipay.com/devdocs/">Gratipay</a>. Thanks!<br> |
| 28 | 28 | ||
| 29 | <h2 class="_lined-heading" id="credits">Credits</h2> | 29 | <h2 class="_block-heading" id="credits">Credits</h2> |
| 30 | 30 | ||
| 31 | <p><strong>Special thanks to:</strong> | 31 | <p><strong>Special thanks to:</strong> |
| 32 | <ul> | 32 | <ul> |
| @@ -45,7 +45,7 @@ app.templates.aboutPage = -> """ · 12 unmodified lines | |||
| 45 | #{("<tr><td>#{c[0]}<td>© #{c[1]}<td><a href=\"#{c[3]}\">#{c[2]}</a>" for c in credits).join('')} | 45 | #{("<tr><td>#{c[0]}<td>© #{c[1]}<td><a href=\"#{c[3]}\">#{c[2]}</a>" for c in credits).join('')} |
| 46 | </table> | 46 | </table> |
| 47 | 47 | ||
| 48 | <h2 class="_lined-heading" id="faq">Questions & Answers</h2> | 48 | <h2 class="_block-heading" id="faq">Questions & Answers</h2> |
| 49 | <dl> | 49 | <dl> |
| 50 | <dt>Where can I suggest new docs and features? | 50 | <dt>Where can I suggest new docs and features? |
| 51 | <dd>You can suggest and vote for new docs on the <a href="https://trello.com/b/6BmTulfx/devdocs-documentation">Trello board</a>.<br> | 51 | <dd>You can suggest and vote for new docs on the <a href="https://trello.com/b/6BmTulfx/devdocs-documentation">Trello board</a>.<br> |
| @@ -56,7 +56,7 @@ app.templates.aboutPage = -> """ · 4 unmodified lines | |||
| 56 | </dl> | 56 | </dl> |
| 57 | <p>For anything else, feel free to email me at <a href="mailto:thibaut@devdocs.io">thibaut@devdocs.io</a>. | 57 | <p>For anything else, feel free to email me at <a href="mailto:thibaut@devdocs.io">thibaut@devdocs.io</a>. |
| 58 | 58 | ||
| 59 | <h2 class="_lined-heading" id="copyright">Copyright and License</h2> | 59 | <h2 class="_block-heading" id="copyright">Copyright and License</h2> |
| 60 | <p class="_note"> | 60 | <p class="_note"> |
| 61 | <strong>Copyright 2013–2017 Thibaut Courouble and <a href="https://github.com/Thibaut/devdocs/graphs/contributors">other contributors</a></strong><br> | 61 | <strong>Copyright 2013–2017 Thibaut Courouble and <a href="https://github.com/Thibaut/devdocs/graphs/contributors">other contributors</a></strong><br> |
| 62 | This software is licensed under the terms of the Mozilla Public License v2.0.<br> | 62 | This software is licensed under the terms of the Mozilla Public License v2.0.<br> |
| @@ -64,7 +64,7 @@ app.templates.aboutPage = -> """ · 1 unmodified line | |||
| 64 | For more information, see the <a href="https://github.com/Thibaut/devdocs/blob/master/COPYRIGHT">COPYRIGHT</a> | 64 | For more information, see the <a href="https://github.com/Thibaut/devdocs/blob/master/COPYRIGHT">COPYRIGHT</a> |
| 65 | and <a href="https://github.com/Thibaut/devdocs/blob/master/LICENSE">LICENSE</a> files. | 65 | and <a href="https://github.com/Thibaut/devdocs/blob/master/LICENSE">LICENSE</a> files. |
| 66 | 66 | ||
| 67 | <h2 class="_lined-heading" id="plugins">Plugins and Extensions</h2> | 67 | <h2 class="_block-heading" id="plugins">Plugins and Extensions</h2> |
| 68 | <ul> | 68 | <ul> |
| 69 | <li><a href="https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe">Chrome web app</a> | 69 | <li><a href="https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe">Chrome web app</a> |
| 70 | <li><a href="https://sublime.wbond.net/packages/DevDocs">Sublime Text plugin</a> | 70 | <li><a href="https://sublime.wbond.net/packages/DevDocs">Sublime Text plugin</a> |
| @@ -73,7 +73,7 @@ app.templates.aboutPage = -> """ · 2 unmodified lines | |||
| 73 | <li><a href="https://github.com/xuchunyang/DevDocs.el">Emacs Package</a> | 73 | <li><a href="https://github.com/xuchunyang/DevDocs.el">Emacs Package</a> |
| 74 | </ul> | 74 | </ul> |
| 75 | 75 | ||
| 76 | <h2 class="_lined-heading" id="privacy">Privacy Policy</h2> | 76 | <h2 class="_block-heading" id="privacy">Privacy Policy</h2> |
| 77 | <ul> | 77 | <ul> |
| 78 | <li><a href="http://devdocs.io">devdocs.io</a> ("App") is operated by Thibaut Courouble ("We"). | 78 | <li><a href="http://devdocs.io">devdocs.io</a> ("App") is operated by Thibaut Courouble ("We"). |
| 79 | <li>We do not collect personal information. | 79 | <li>We do not collect personal information. |
| @@ -11,7 +11,9 @@ app.templates.helpPage = """ · 10 unmodified lines | |||
| 11 | </ul> | 11 | </ul> |
| 12 | </nav> | 12 | </nav> |
| 13 | 13 | ||
| 14 | <h2 class="_lined-heading" id="search">Search</h2> | 14 | <h1 class="_lined-heading" id="search">Help</h2> |
| 15 | |||
| 16 | <h2 class="_block-heading" id="search">Search</h2> | ||
| 15 | <p> | 17 | <p> |
| 16 | The search is case-insensitive and supports fuzzy matching (for queries longer than two characters). | 18 | The search is case-insensitive and supports fuzzy matching (for queries longer than two characters). |
| 17 | For example, searching <code class="_label">bgcp</code> brings up <code class="_label">background-clip</code>.<br> | 19 | For example, searching <code class="_label">bgcp</code> brings up <code class="_label">background-clip</code>.<br> |
| @@ -42,7 +44,7 @@ app.templates.helpPage = """ · 24 unmodified lines | |||
| 42 | <a href="https://support.mozilla.org/en-US/kb/how-search-from-address-bar">these instructions</a>. | 44 | <a href="https://support.mozilla.org/en-US/kb/how-search-from-address-bar">these instructions</a>. |
| 43 | </dl> | 45 | </dl> |
| 44 | 46 | ||
| 45 | <h2 class="_lined-heading" id="shortcuts">Keyboard Shortcuts</h2> | 47 | <h2 class="_block-heading" id="shortcuts">Keyboard Shortcuts</h2> |
| 46 | <h3 class="_shortcuts-title">Selection</h3> | 48 | <h3 class="_shortcuts-title">Selection</h3> |
| 47 | <dl class="_shortcuts-dl"> | 49 | <dl class="_shortcuts-dl"> |
| 48 | <dt class="_shortcuts-dt"> | 50 | <dt class="_shortcuts-dt"> |
| @@ -110,7 +112,7 @@ app.templates.helpPage = """ · 61 unmodified lines | |||
| 110 | <strong>Tip:</strong> If the cursor is no longer in the search field, press <code class="_label">/</code> or | 112 | <strong>Tip:</strong> If the cursor is no longer in the search field, press <code class="_label">/</code> or |
| 111 | continue to type and it will refocus the search field and start showing new results. | 113 | continue to type and it will refocus the search field and start showing new results. |
| 112 | 114 | ||
| 113 | <h2 class="_lined-heading" id="abbreviations">Abbreviations</h2> | 115 | <h2 class="_block-heading" id="abbreviations">Abbreviations</h2> |
| 114 | <p>Feel free to suggest new abbreviations on <a href="https://github.com/Thibaut/devdocs/issues/new">GitHub</a>. | 116 | <p>Feel free to suggest new abbreviations on <a href="https://github.com/Thibaut/devdocs/issues/new">GitHub</a>. |
| 115 | <table class="_abbreviations"> | 117 | <table class="_abbreviations"> |
| 116 | <tr> | 118 | <tr> |
| @@ -15,7 +15,7 @@ app.templates.newsList = (news, options = {}) -> · 14 unmodified lines | |||
| 15 | date = new Date(value[0]) | 15 | date = new Date(value[0]) |
| 16 | if options.years isnt false and year isnt date.getUTCFullYear() | 16 | if options.years isnt false and year isnt date.getUTCFullYear() |
| 17 | year = date.getUTCFullYear() | 17 | year = date.getUTCFullYear() |
| 18 | result += "<h4>#{year}</h4>" | 18 | result += """<h2 class="_block-heading">#{year}</h2>""" |
| 19 | result += newsItem(date, value[1..]) | 19 | result += newsItem(date, value[1..]) |
| 20 | 20 | ||
| 21 | result | 21 | result |
| @@ -21,7 +21,7 @@ app.templates.offlinePage = (docs) -> """ · 20 unmodified lines | |||
| 21 | #{docs} | 21 | #{docs} |
| 22 | </table> | 22 | </table> |
| 23 | <p class="_note"><strong>Note:</strong> your browser may delete DevDocs's offline data if your computer is running low on disk space and you haven't used the app in a while. Load this page before going offline to make sure the data is still there. | 23 | <p class="_note"><strong>Note:</strong> your browser may delete DevDocs's offline data if your computer is running low on disk space and you haven't used the app in a while. Load this page before going offline to make sure the data is still there. |
| 24 | <h1 class="_lined-heading">Questions & Answers</h1> | 24 | <h2 class="_block-heading">Questions & Answers</h2> |
| 25 | <dl> | 25 | <dl> |
| 26 | <dt>How does this work? | 26 | <dt>How does this work? |
| 27 | <dd>Each page is cached as a key-value pair in <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> (downloaded from a single file).<br> | 27 | <dd>Each page is cached as a key-value pair in <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> (downloaded from a single file).<br> |
| @@ -48,15 +48,6 @@ app.templates.intro = """ · 47 unmodified lines | |||
| 48 | """ | 48 | """ |
| 49 | <% end %> | 49 | <% end %> |
| 50 | 50 | ||
| 51 | app.templates.mobileNav = """ | ||
| 52 | <nav class="_mobile-nav"> | ||
| 53 | <a href="/offline" class="_mobile-nav-link">Offline</a> | ||
| 54 | <a href="/about" class="_mobile-nav-link">About</a> | ||
| 55 | <a href="/news" class="_mobile-nav-link">News</a> | ||
| 56 | <a href="/help" class="_mobile-nav-link">Help</a> | ||
| 57 | </nav> | ||
| 58 | """ | ||
| 59 | |||
| 60 | app.templates.mobileIntro = """ | 51 | app.templates.mobileIntro = """ |
| 61 | <div class="_mobile-intro"> | 52 | <div class="_mobile-intro"> |
| 62 | <h2 class="_intro-title">Welcome!</h2> | 53 | <h2 class="_intro-title">Welcome!</h2> |
| @@ -9,7 +9,6 @@ class app.views.RootPage extends app.View · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | render: -> | 10 | render: -> |
| 11 | @empty() | 11 | @empty() |
| 12 | @append @tmpl('mobileNav') if app.isMobile() | ||
| 13 | if app.isAndroidWebview() | 12 | if app.isAndroidWebview() |
| 14 | @append @tmpl('androidWarning') | 13 | @append @tmpl('androidWarning') |
| 15 | else | 14 | else |
| @@ -1,6 +1,6 @@ | |||
| 1 | class app.views.Document extends app.View | 1 | class app.views.Document extends app.View |
| 2 | MAX_WIDTH_CLASS = '_max-width' | 2 | MAX_WIDTH_LAYOUT = '_max-width' |
| 3 | HIDE_SIDEBAR_CLASS = '_sidebar-hidden' | 3 | SIDEBAR_HIDDEN_LAYOUT = '_sidebar-hidden' |
| 4 | 4 | ||
| 5 | @el: document | 5 | @el: document |
| 6 | 6 | ||
| @@ -14,16 +14,12 @@ class app.views.Document extends app.View · 7 unmodified lines | |||
| 14 | superRight: 'onForward' | 14 | superRight: 'onForward' |
| 15 | 15 | ||
| 16 | init: -> | 16 | init: -> |
| 17 | @addSubview @nav = new app.views.Nav, | 17 | @addSubview @menu = new app.views.Menu, |
| 18 | @addSubview @sidebar = new app.views.Sidebar | 18 | @addSubview @sidebar = new app.views.Sidebar |
| 19 | @addSubview @resizer = new app.views.Resizer if app.views.Resizer.isSupported() | 19 | @addSubview @resizer = new app.views.Resizer if app.views.Resizer.isSupported() |
| 20 | @addSubview @content = new app.views.Content | 20 | @addSubview @content = new app.views.Content |
| 21 | @addSubview @path = new app.views.Path unless app.isSingleDoc() or app.isMobile() | 21 | @addSubview @path = new app.views.Path unless app.isSingleDoc() or app.isMobile() |
| 22 | 22 | ||
| 23 | @sidebar.search | ||
| 24 | .on 'searching', @onSearching | ||
| 25 | .on 'clear', @onSearchClear | ||
| 26 | |||
| 27 | $.on document.body, 'click', @onClick | 23 | $.on document.body, 'click', @onClick |
| 28 | 24 | ||
| 29 | @activate() | 25 | @activate() |
| @@ -39,39 +35,17 @@ class app.views.Document extends app.View · 9 unmodified lines | |||
| 39 | return | 35 | return |
| 40 | 36 | ||
| 41 | toggleLayout: -> | 37 | toggleLayout: -> |
| 42 | wantsMaxWidth = !app.el.classList.contains(MAX_WIDTH_CLASS) | 38 | wantsMaxWidth = !app.el.classList.contains(MAX_WIDTH_LAYOUT) |
| 43 | app.el.classList[if wantsMaxWidth then 'add' else 'remove'](MAX_WIDTH_CLASS) | 39 | app.el.classList[if wantsMaxWidth then 'add' else 'remove'](MAX_WIDTH_LAYOUT) |
| 44 | app.settings.setLayout(MAX_WIDTH_CLASS, wantsMaxWidth) | 40 | app.settings.setLayout(MAX_WIDTH_LAYOUT, wantsMaxWidth) |
| 45 | app.appCache?.updateInBackground() | 41 | app.appCache?.updateInBackground() |
| 46 | return | 42 | return |
| 47 | 43 | ||
| 48 | showSidebar: (options = {}) -> | 44 | toggleSidebarLayout: -> |
| 49 | @toggleSidebar(options, true) | 45 | shouldHide = !app.settings.hasLayout(SIDEBAR_HIDDEN_LAYOUT) |
| 50 | return | 46 | app.el.classList[if shouldHide then 'add' else 'remove'](SIDEBAR_HIDDEN_LAYOUT) |
| 51 | 47 | app.settings.setLayout(SIDEBAR_HIDDEN_LAYOUT, shouldHide) | |
| 52 | hideSidebar: (options = {}) -> | 48 | app.appCache?.updateInBackground() |
| 53 | @toggleSidebar(options, false) | ||
| 54 | return | ||
| 55 | |||
| 56 | toggleSidebar: (options = {}, shouldShow) -> | ||
| 57 | shouldShow ?= if options.save then !@hasSidebar() else app.el.classList.contains(HIDE_SIDEBAR_CLASS) | ||
| 58 | app.el.classList[if shouldShow then 'remove' else 'add'](HIDE_SIDEBAR_CLASS) | ||
| 59 | if options.save | ||
| 60 | app.settings.setLayout(HIDE_SIDEBAR_CLASS, !shouldShow) | ||
| 61 | app.appCache?.updateInBackground() | ||
| 62 | return | ||
| 63 | |||
| 64 | hasSidebar: -> | ||
| 65 | !app.settings.hasLayout(HIDE_SIDEBAR_CLASS) | ||
| 66 | |||
| 67 | onSearching: => | ||
| 68 | unless @hasSidebar() | ||
| 69 | @showSidebar() | ||
| 70 | return | ||
| 71 | |||
| 72 | onSearchClear: => | ||
| 73 | unless @hasSidebar() | ||
| 74 | @hideSidebar() | ||
| 75 | return | 49 | return |
| 76 | 50 | ||
| 77 | setTitle: (title) -> | 51 | setTitle: (title) -> |
| @@ -0,0 +1,24 @@ | |||
| 1 | class app.views.Menu extends app.View | ||
| 2 | @el: '._menu' | ||
| 3 | @activeClass: 'active' | ||
| 4 | |||
| 5 | @events: | ||
| 6 | click: 'onClick' | ||
| 7 | |||
| 8 | init: -> | ||
| 9 | $.on document.body, 'click', @onGlobalClick | ||
| 10 | return | ||
| 11 | |||
| 12 | onClick: => | ||
| 13 | prev = @el.previousElementSibling | ||
| 14 | $.remove @el | ||
| 15 | $.requestAnimationFrame => $.after(prev, @el) | ||
| 16 | return | ||
| 17 | |||
| 18 | onGlobalClick: (event) => | ||
| 19 | return if event.which isnt 1 | ||
| 20 | if event.target.hasAttribute?('data-toggle-menu') | ||
| 21 | @toggleClass @constructor.activeClass | ||
| 22 | else if @hasClass @constructor.activeClass | ||
| 23 | @removeClass @constructor.activeClass | ||
| 24 | return | ||
| @@ -35,44 +35,48 @@ class app.views.Mobile extends app.View · 34 unmodified lines | |||
| 35 | FastClick.attach @body | 35 | FastClick.attach @body |
| 36 | 36 | ||
| 37 | $.on @body, 'click', @onClick | 37 | $.on @body, 'click', @onClick |
| 38 | $.on $('._home-btn'), 'click', @onClickHome | ||
| 39 | $.on $('._menu-btn'), 'click', @onClickMenu | ||
| 40 | $.on $('._search'), 'touchend', @onTapSearch | 38 | $.on $('._search'), 'touchend', @onTapSearch |
| 41 | 39 | ||
| 42 | @back = $('._back-btn') | 40 | @toggleSidebar = $('button[data-toggle-sidebar]') |
| 41 | @toggleSidebar.removeAttribute('hidden') | ||
| 42 | $.on @toggleSidebar, 'click', @onClickToggleSidebar | ||
| 43 | |||
| 44 | @back = $('button[data-back]') | ||
| 45 | @back.removeAttribute('hidden') | ||
| 43 | $.on @back, 'click', @onClickBack | 46 | $.on @back, 'click', @onClickBack |
| 44 | 47 | ||
| 45 | @forward = $('._forward-btn') | 48 | @forward = $('button[data-forward]') |
| 49 | @forward.removeAttribute('hidden') | ||
| 46 | $.on @forward, 'click', @onClickForward | 50 | $.on @forward, 'click', @onClickForward |
| 47 | 51 | ||
| 48 | app.document.sidebar.search | 52 | app.document.sidebar.search |
| 49 | .on 'searching', @showSidebar | 53 | .on 'searching', @showSidebar |
| 50 | .on 'clear', @hideSidebar | ||
| 51 | 54 | ||
| 52 | @activate() | 55 | @activate() |
| 53 | return | 56 | return |
| 54 | 57 | ||
| 55 | showSidebar: => | 58 | showSidebar: => |
| 56 | if @isSidebarShown() | 59 | if @isSidebarShown() |
| 57 | @body.scrollTop = 0 | 60 | window.scrollTo 0, 0 |
| 58 | return | 61 | return |
| 59 | 62 | ||
| 60 | @contentTop = @body.scrollTop | 63 | @contentTop = window.scrollY |
| 61 | @content.style.display = 'none' | 64 | @content.style.display = 'none' |
| 62 | @sidebar.style.display = 'block' | 65 | @sidebar.style.display = 'block' |
| 63 | 66 | ||
| 64 | if selection = @findByClass app.views.ListSelect.activeClass | 67 | if selection = @findByClass app.views.ListSelect.activeClass |
| 65 | $.scrollTo selection, @body, 'center' | 68 | scrollContainer = if window.scrollY is @body.scrollTop then @body else document.documentElement |
| 69 | $.scrollTo selection, scrollContainer, 'center' | ||
| 66 | else | 70 | else |
| 67 | @body.scrollTop = @findByClass(app.views.ListFold.activeClass) and @sidebarTop or 0 | 71 | window.scrollTo 0, @findByClass(app.views.ListFold.activeClass) and @sidebarTop or 0 |
| 68 | return | 72 | return |
| 69 | 73 | ||
| 70 | hideSidebar: => | 74 | hideSidebar: => |
| 71 | return unless @isSidebarShown() | 75 | return unless @isSidebarShown() |
| 72 | @sidebarTop = @body.scrollTop | 76 | @sidebarTop = window.scrollY |
| 73 | @sidebar.style.display = 'none' | 77 | @sidebar.style.display = 'none' |
| 74 | @content.style.display = 'block' | 78 | @content.style.display = 'block' |
| 75 | @body.scrollTop = @contentTop or 0 | 79 | window.scrollTo 0, @contentTop or 0 |
| 76 | return | 80 | return |
| 77 | 81 | ||
| 78 | isSidebarShown: -> | 82 | isSidebarShown: -> |
| @@ -89,17 +93,12 @@ class app.views.Mobile extends app.View · 10 unmodified lines | |||
| 89 | onClickForward: => | 93 | onClickForward: => |
| 90 | history.forward() | 94 | history.forward() |
| 91 | 95 | ||
| 92 | onClickHome: => | 96 | onClickToggleSidebar: => |
| 93 | app.shortcuts.trigger 'escape' | ||
| 94 | @hideSidebar() | ||
| 95 | return | ||
| 96 | |||
| 97 | onClickMenu: => | ||
| 98 | if @isSidebarShown() then @hideSidebar() else @showSidebar() | 97 | if @isSidebarShown() then @hideSidebar() else @showSidebar() |
| 99 | return | 98 | return |
| 100 | 99 | ||
| 101 | onTapSearch: => | 100 | onTapSearch: => |
| 102 | @body.scrollTop = 0 | 101 | window.scrollTo 0, 0 |
| 103 | 102 | ||
| 104 | afterRoute: => | 103 | afterRoute: => |
| 105 | @hideSidebar() | 104 | @hideSidebar() |
| @@ -1,26 +0,0 @@ | |||
| 1 | class app.views.Nav extends app.View | ||
| 2 | @el: '._nav' | ||
| 3 | @activeClass: '_nav-current' | ||
| 4 | |||
| 5 | @routes: | ||
| 6 | after: 'afterRoute' | ||
| 7 | |||
| 8 | select: (href) -> | ||
| 9 | @deselect() | ||
| 10 | if @current = @find "a[href='#{href}']" | ||
| 11 | @current.classList.add @constructor.activeClass | ||
| 12 | @current.setAttribute 'tabindex', '-1' | ||
| 13 | return | ||
| 14 | |||
| 15 | deselect: -> | ||
| 16 | if @current | ||
| 17 | @current.classList.remove @constructor.activeClass | ||
| 18 | @current.removeAttribute 'tabindex' | ||
| 19 | @current = null | ||
| 20 | return | ||
| 21 | |||
| 22 | afterRoute: (route, context) => | ||
| 23 | if route in ['page', 'offline'] | ||
| 24 | @select context.pathname | ||
| 25 | else | ||
| 26 | @deselect() | ||
| @@ -35,7 +35,7 @@ class app.views.Resizer extends app.View · 34 unmodified lines | |||
| 35 | return | 35 | return |
| 36 | 36 | ||
| 37 | onClick: -> | 37 | onClick: -> |
| 38 | app.document.toggleSidebar(save: true) | 38 | app.document.toggleSidebarLayout() |
| 39 | return | 39 | return |
| 40 | 40 | ||
| 41 | onDragStart: (event) => | 41 | onDragStart: (event) => |
| @@ -14,7 +14,7 @@ class app.views.ListFocus extends app.View · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | constructor: (@el) -> | 15 | constructor: (@el) -> |
| 16 | super | 16 | super |
| 17 | @focus = $.framify(@focus, @) | 17 | @focusOnNextFrame = $.framify(@focus, @) |
| 18 | 18 | ||
| 19 | focus: (el) -> | 19 | focus: (el) -> |
| 20 | if el and not el.classList.contains @constructor.activeClass | 20 | if el and not el.classList.contains @constructor.activeClass |
| @@ -87,22 +87,22 @@ class app.views.ListFocus extends app.View · 66 unmodified lines | |||
| 87 | 87 | ||
| 88 | onDown: => | 88 | onDown: => |
| 89 | if cursor = @getCursor() | 89 | if cursor = @getCursor() |
| 90 | @focus @findNext(cursor) | 90 | @focusOnNextFrame @findNext(cursor) |
| 91 | else | 91 | else |
| 92 | @focus @findByTag('a') | 92 | @focusOnNextFrame @findByTag('a') |
| 93 | return | 93 | return |
| 94 | 94 | ||
| 95 | onUp: => | 95 | onUp: => |
| 96 | if cursor = @getCursor() | 96 | if cursor = @getCursor() |
| 97 | @focus @findPrev(cursor) | 97 | @focusOnNextFrame @findPrev(cursor) |
| 98 | else | 98 | else |
| 99 | @focus @findLastByTag('a') | 99 | @focusOnNextFrame @findLastByTag('a') |
| 100 | return | 100 | return |
| 101 | 101 | ||
| 102 | onLeft: => | 102 | onLeft: => |
| 103 | cursor = @getCursor() | 103 | cursor = @getCursor() |
| 104 | if cursor and not cursor.classList.contains(app.views.ListFold.activeClass) and cursor.parentElement isnt @el | 104 | if cursor and not cursor.classList.contains(app.views.ListFold.activeClass) and cursor.parentElement isnt @el |
| 105 | @focus cursor.parentElement.previousSibling | 105 | @focusOnNextFrame cursor.parentElement.previousSibling |
| 106 | return | 106 | return |
| 107 | 107 | ||
| 108 | onEnter: => | 108 | onEnter: => |
| @@ -18,7 +18,6 @@ class app.views.Notice extends app.View · 17 unmodified lines | |||
| 18 | return | 18 | return |
| 19 | 19 | ||
| 20 | show: -> | 20 | show: -> |
| 21 | @addClass '_top' if @type is 'disabledDoc' | ||
| 22 | @html @tmpl("#{@type}Notice", @args...) | 21 | @html @tmpl("#{@type}Notice", @args...) |
| 23 | @prependTo $('._app') | 22 | @prependTo $('._app') |
| 24 | return | 23 | return |
| @@ -130,7 +130,7 @@ class app.views.Search extends app.View · 129 unmodified lines | |||
| 130 | if event.target is @resetLink | 130 | if event.target is @resetLink |
| 131 | $.stopEvent(event) | 131 | $.stopEvent(event) |
| 132 | @reset() | 132 | @reset() |
| 133 | @focus() | 133 | app.document.onEscape() |
| 134 | return | 134 | return |
| 135 | 135 | ||
| 136 | onSubmit: (event) -> | 136 | onSubmit: (event) -> |
| @@ -148,7 +148,7 @@ class app.views.DocList extends app.View · 147 unmodified lines | |||
| 148 | return | 148 | return |
| 149 | 149 | ||
| 150 | scrollTo: (model) -> | 150 | scrollTo: (model) -> |
| 151 | $.scrollTo @find("a[href='#{model.fullPath()}']"), null, 'top', margin: 0 | 151 | $.scrollTo @find("a[href='#{model.fullPath()}']"), null, 'top', margin: if app.isMobile() then 48 else 0 |
| 152 | return | 152 | return |
| 153 | 153 | ||
| 154 | toggleDisabled: -> | 154 | toggleDisabled: -> |
| @@ -15,8 +15,8 @@ class app.views.Results extends app.View · 14 unmodified lines | |||
| 15 | return | 15 | return |
| 16 | 16 | ||
| 17 | init: -> | 17 | init: -> |
| 18 | @addSubview @listSelect = new app.views.ListSelect @el | ||
| 19 | @addSubview @listFocus = new app.views.ListFocus @el unless app.isMobile() | 18 | @addSubview @listFocus = new app.views.ListFocus @el unless app.isMobile() |
| 19 | @addSubview @listSelect = new app.views.ListSelect @el | ||
| 20 | 20 | ||
| 21 | @search | 21 | @search |
| 22 | .on 'results', @onResults | 22 | .on 'results', @onResults |
| @@ -42,7 +42,7 @@ class app.views.Results extends app.View · 19 unmodified lines | |||
| 42 | return | 42 | return |
| 43 | 43 | ||
| 44 | focusFirst: -> | 44 | focusFirst: -> |
| 45 | @listFocus?.focus @el.firstElementChild | 45 | @listFocus?.focusOnNextFrame @el.firstElementChild |
| 46 | return | 46 | return |
| 47 | 47 | ||
| 48 | openFirst: -> | 48 | openFirst: -> |
| @@ -3,6 +3,7 @@ class app.views.Sidebar extends app.View · 2 unmodified lines | |||
| 3 | 3 | ||
| 4 | @events: | 4 | @events: |
| 5 | focus: 'onFocus' | 5 | focus: 'onFocus' |
| 6 | select: 'onSelect' | ||
| 6 | click: 'onClick' | 7 | click: 'onClick' |
| 7 | 8 | ||
| 8 | @shortcuts: | 9 | @shortcuts: |
| @@ -14,8 +15,8 @@ class app.views.Sidebar extends app.View · 5 unmodified lines | |||
| 14 | @addSubview @search = new app.views.Search | 15 | @addSubview @search = new app.views.Search |
| 15 | 16 | ||
| 16 | @search | 17 | @search |
| 17 | .on 'searching', @showResults | 18 | .on 'searching', @onSearching |
| 18 | .on 'clear', @showDocList | 19 | .on 'clear', @onSearchClear |
| 19 | .scope | 20 | .scope |
| 20 | .on 'change', @onScopeChange | 21 | .on 'change', @onScopeChange |
| 21 | 22 | ||
| @@ -27,7 +28,15 @@ class app.views.Sidebar extends app.View · 5 unmodified lines | |||
| 27 | $.on document, 'click', @onGlobalClick if @docPicker | 28 | $.on document, 'click', @onGlobalClick if @docPicker |
| 28 | return | 29 | return |
| 29 | 30 | ||
| 30 | show: (view) -> | 31 | display: -> |
| 32 | @el.style.display = 'block' | ||
| 33 | return | ||
| 34 | |||
| 35 | resetDisplay: -> | ||
| 36 | @el.style.display = '' unless @el.style.display is 'none' | ||
| 37 | return | ||
| 38 | |||
| 39 | showView: (view) -> | ||
| 31 | unless @view is view | 40 | unless @view is view |
| 32 | @hover?.hide() | 41 | @hover?.hide() |
| 33 | @saveScrollPosition() | 42 | @saveScrollPosition() |
| @@ -44,28 +53,29 @@ class app.views.Sidebar extends app.View · 10 unmodified lines | |||
| 44 | @append @tmpl('sidebarSettings') if @view is @docList and @docPicker | 53 | @append @tmpl('sidebarSettings') if @view is @docList and @docPicker |
| 45 | return | 54 | return |
| 46 | 55 | ||
| 47 | showDocList: (reset) => | 56 | showDocList: -> |
| 48 | @show @docList | 57 | @showView @docList |
| 49 | if reset is true | ||
| 50 | @docList.reset(revealCurrent: true) | ||
| 51 | @search.reset() | ||
| 52 | return | 58 | return |
| 53 | 59 | ||
| 54 | showDocPicker: => | 60 | showDocPicker: => |
| 55 | @show @docPicker | 61 | @showView @docPicker |
| 56 | return | 62 | return |
| 57 | 63 | ||
| 58 | showResults: => | 64 | showResults: => |
| 59 | @show @results | 65 | @showView @results |
| 66 | return | ||
| 67 | |||
| 68 | reset: -> | ||
| 69 | @display() | ||
| 70 | @showDocList() | ||
| 71 | @docList.reset() | ||
| 72 | @search.reset() | ||
| 60 | return | 73 | return |
| 61 | 74 | ||
| 62 | onReady: => | 75 | onReady: => |
| 63 | @view = @docList | 76 | @view = @docList |
| 64 | @render() | 77 | @render() |
| 65 | @view.activate() | 78 | @view.activate() |
| 66 | |||
| 67 | reset: -> | ||
| 68 | @showDocList true | ||
| 69 | return | 79 | return |
| 70 | 80 | ||
| 71 | onScopeChange: (newDoc, previousDoc) => | 81 | onScopeChange: (newDoc, previousDoc) => |
| @@ -90,15 +100,30 @@ class app.views.Sidebar extends app.View · 18 unmodified lines | |||
| 90 | @el.scrollTop = 0 | 100 | @el.scrollTop = 0 |
| 91 | return | 101 | return |
| 92 | 102 | ||
| 103 | onSearching: => | ||
| 104 | @display() | ||
| 105 | @showResults() | ||
| 106 | return | ||
| 107 | |||
| 108 | onSearchClear: => | ||
| 109 | @resetDisplay() | ||
| 110 | @showDocList() | ||
| 111 | return | ||
| 112 | |||
| 93 | onFocus: (event) => | 113 | onFocus: (event) => |
| 114 | @display() | ||
| 94 | $.scrollTo event.target, @el, 'continuous', bottomGap: 2 unless event.target is @el | 115 | $.scrollTo event.target, @el, 'continuous', bottomGap: 2 unless event.target is @el |
| 95 | return | 116 | return |
| 96 | 117 | ||
| 118 | onSelect: => | ||
| 119 | @resetDisplay() | ||
| 120 | return | ||
| 121 | |||
| 97 | onClick: (event) => | 122 | onClick: (event) => |
| 98 | return if event.which isnt 1 | 123 | return if event.which isnt 1 |
| 99 | if event.target.hasAttribute? 'data-reset-list' | 124 | if event.target.hasAttribute? 'data-reset-list' |
| 100 | $.stopEvent(event) | 125 | $.stopEvent(event) |
| 101 | @reset() | 126 | @onAltR() |
| 102 | else if event.target.hasAttribute? 'data-light' | 127 | else if event.target.hasAttribute? 'data-light' |
| 103 | $.stopEvent(event) | 128 | $.stopEvent(event) |
| 104 | document.activeElement?.blur() | 129 | document.activeElement?.blur() |
| @@ -120,6 +145,8 @@ class app.views.Sidebar extends app.View · 15 unmodified lines | |||
| 120 | 145 | ||
| 121 | onAltR: => | 146 | onAltR: => |
| 122 | @reset() | 147 | @reset() |
| 148 | @docList.reset(revealCurrent: true) | ||
| 149 | @display() | ||
| 123 | return | 150 | return |
| 124 | 151 | ||
| 125 | onEscape: => | 152 | onEscape: => |
| @@ -35,6 +35,13 @@ class app.View · 34 unmodified lines | |||
| 35 | @el.classList.remove(name) | 35 | @el.classList.remove(name) |
| 36 | return | 36 | return |
| 37 | 37 | ||
| 38 | toggleClass: (name) -> | ||
| 39 | @el.classList.toggle(name) | ||
| 40 | return | ||
| 41 | |||
| 42 | hasClass: (name) -> | ||
| 43 | @el.classList.contains(name) | ||
| 44 | |||
| 38 | resetClass: -> | 45 | resetClass: -> |
| 39 | @el.className = @originalClassName or '' | 46 | @el.className = @originalClassName or '' |
| 40 | if @constructor.className | 47 | if @constructor.className |
| @@ -2,7 +2,6 @@ · 1 unmodified line | |||
| 2 | position: relative; | 2 | position: relative; |
| 3 | z-index: 1; | 3 | z-index: 1; |
| 4 | height: 100%; | 4 | height: 100%; |
| 5 | padding-top: $headerHeight; | ||
| 6 | overflow: hidden; | 5 | overflow: hidden; |
| 7 | background: $contentBackground; | 6 | background: $contentBackground; |
| 8 | -webkit-transition: opacity .2s; | 7 | -webkit-transition: opacity .2s; |
| @@ -12,7 +11,7 @@ · 3 unmodified lines | |||
| 12 | ._booting > & { opacity: 0; } | 11 | ._booting > & { opacity: 0; } |
| 13 | ._noscript > & { display: none; } | 12 | ._noscript > & { display: none; } |
| 14 | 13 | ||
| 15 | &._max-width { | 14 | &._max-width { |
| 16 | margin: 0 auto; | 15 | margin: 0 auto; |
| 17 | max-width: $maxWidth; | 16 | max-width: $maxWidth; |
| 18 | box-shadow: 1px 0 $headerBorder, -1px 0 $headerBorder; | 17 | box-shadow: 1px 0 $headerBorder, -1px 0 $headerBorder; |
| @@ -31,7 +30,7 @@ · 12 unmodified lines | |||
| 31 | left: 0; | 30 | left: 0; |
| 32 | right: 0; | 31 | right: 0; |
| 33 | line-height: 1; | 32 | line-height: 1; |
| 34 | margin-top: -.75em; | 33 | margin-top: -.6em; |
| 35 | font-size: 4rem; | 34 | font-size: 4rem; |
| 36 | font-weight: 300; | 35 | font-weight: 300; |
| 37 | letter-spacing: -.125rem; | 36 | letter-spacing: -.125rem; |
| @@ -20,18 +20,24 @@ · 19 unmodified lines | |||
| 20 | height: 100%; | 20 | height: 100%; |
| 21 | overflow-y: scroll; | 21 | overflow-y: scroll; |
| 22 | margin-left: .875rem; | 22 | margin-left: .875rem; |
| 23 | padding: 1.25rem 1.5rem 0; | 23 | padding: 1.125rem 1.5rem 0; |
| 24 | font-size: .875rem; | 24 | font-size: .875rem; |
| 25 | pointer-events: auto; | 25 | pointer-events: auto; |
| 26 | -webkit-overflow-scrolling: touch; | 26 | -webkit-overflow-scrolling: touch; |
| 27 | @extend %border-box; | 27 | @extend %border-box; |
| 28 | 28 | ||
| 29 | -webkit-padding-start: .75rem; | 29 | -webkit-padding-start: .625rem; |
| 30 | -webkit-padding-end: 1rem; | 30 | -webkit-padding-end: .75rem; |
| 31 | 31 | ||
| 32 | @media (-moz-overlay-scrollbars) { padding-left: .75rem; } | 32 | @media (-moz-overlay-scrollbars) { padding-left: .625rem; } |
| 33 | @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { margin-left: 0; } | 33 | @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { margin-left: 0; } |
| 34 | 34 | ||
| 35 | ._sidebar-hidden &:before { | ||
| 36 | content: ''; | ||
| 37 | display: block; | ||
| 38 | margin-top: $headerHeight; | ||
| 39 | } | ||
| 40 | |||
| 35 | &:after { // padding bottom | 41 | &:after { // padding bottom |
| 36 | content: ''; | 42 | content: ''; |
| 37 | display: block; | 43 | display: block; |
| @@ -77,15 +83,22 @@ · 39 unmodified lines | |||
| 77 | // Intro | 83 | // Intro |
| 78 | // | 84 | // |
| 79 | 85 | ||
| 80 | ._intro { text-align: center; } | 86 | ._intro { |
| 87 | display: flex; | ||
| 88 | flex-direction: column; | ||
| 89 | justify-content: center; | ||
| 90 | align-items: center; | ||
| 91 | min-height: calc(100vh - 2.375rem); | ||
| 92 | |||
| 93 | ._sidebar-hidden & { | ||
| 94 | min-height: calc(100vh - 2.375rem - #{$headerHeight}); | ||
| 95 | } | ||
| 96 | } | ||
| 81 | 97 | ||
| 82 | ._intro-message { | 98 | ._intro-message { |
| 83 | position: relative; | ||
| 84 | display: inline-block; | ||
| 85 | vertical-align: top; | ||
| 86 | max-width: 37rem; | 99 | max-width: 37rem; |
| 100 | margin: .5rem 0; | ||
| 87 | padding: 1rem 1.25rem; | 101 | padding: 1rem 1.25rem; |
| 88 | text-align: left; | ||
| 89 | @extend %note, %note-green; | 102 | @extend %note, %note-green; |
| 90 | } | 103 | } |
| 91 | 104 | ||
| @@ -146,23 +159,25 @@ · 54 unmodified lines | |||
| 146 | 159 | ||
| 147 | ._lined-heading, | 160 | ._lined-heading, |
| 148 | %lined-heading { | 161 | %lined-heading { |
| 149 | white-space: nowrap; | 162 | display: flex; |
| 150 | overflow: hidden; | 163 | justify-content: center; |
| 151 | word-wrap: normal; | 164 | align-items: center; |
| 152 | overflow-wrap: normal; | ||
| 153 | 165 | ||
| 154 | &:after { | 166 | &:after { |
| 155 | content: ''; | 167 | content: ''; |
| 156 | display: inline-block; | 168 | display: inline-block; |
| 157 | vertical-align: middle; | 169 | vertical-align: middle; |
| 158 | width: 100%; | 170 | flex-grow: 1; |
| 159 | height: 1px; | 171 | height: 1px; |
| 160 | line-height: 0; | 172 | line-height: 0; |
| 173 | margin-top: .25rem; | ||
| 161 | margin-left: 1rem; | 174 | margin-left: 1rem; |
| 162 | background: $boxBorderLight; | 175 | background: $boxBorderLight; |
| 163 | } | 176 | } |
| 164 | } | 177 | } |
| 165 | 178 | ||
| 179 | ._block-heading { @extend %block-heading; } | ||
| 180 | |||
| 166 | ._heading-links { | 181 | ._heading-links { |
| 167 | float: right; | 182 | float: right; |
| 168 | font-weight: normal; | 183 | font-weight: normal; |
| @@ -7,79 +7,131 @@ · 6 unmodified lines | |||
| 7 | z-index: $headerZ; | 7 | z-index: $headerZ; |
| 8 | top: 0; | 8 | top: 0; |
| 9 | left: 0; | 9 | left: 0; |
| 10 | right: 0; | 10 | display: flex; |
| 11 | width: $sidebarWidth; | ||
| 11 | height: $headerHeight; | 12 | height: $headerHeight; |
| 12 | line-height: $headerHeight; | ||
| 13 | background: $headerBackground; | 13 | background: $headerBackground; |
| 14 | border-bottom: 1px solid $headerBorder; | 14 | border-bottom: 1px solid $headerBorder; |
| 15 | @extend %user-select-none; | 15 | @extend %user-select-none; |
| 16 | |||
| 17 | @media #{$mediumScreen} { width: $sidebarMediumWidth; } | ||
| 16 | } | 18 | } |
| 17 | 19 | ||
| 18 | // | 20 | ._header-left { |
| 19 | // Navigation menu | 21 | float: left; |
| 20 | // | 22 | height: 100%; |
| 23 | } | ||
| 21 | 24 | ||
| 22 | ._nav { | 25 | ._header-right { |
| 23 | float: right; | 26 | float: right; |
| 24 | margin-right: .5rem; | 27 | height: 100%; |
| 25 | font-size: .875rem; | ||
| 26 | color: $textColor; | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | ._nav-link, | 30 | ._header-btn { |
| 30 | ._nav-link:hover { | ||
| 31 | position: relative; | 31 | position: relative; |
| 32 | float: left; | 32 | width: 2.25rem; |
| 33 | padding: 0 1.25rem; | 33 | height: 100%; |
| 34 | color: inherit; | 34 | color: $textColorLight; |
| 35 | text-decoration: none; | 35 | text-align: center; |
| 36 | 36 | ||
| 37 | @media #{$mediumScreen} { padding: 0 .75rem; } | 37 | &[hidden] { display: none; } |
| 38 | } | ||
| 39 | 38 | ||
| 40 | ._nav-link { | 39 | &[disabled] { |
| 41 | &:before, &:after { | 40 | opacity: .3; |
| 42 | position: absolute; | 41 | cursor: not-allowed; |
| 43 | left: 50%; | ||
| 44 | bottom: 0; | ||
| 45 | width: 0; | ||
| 46 | height: 0; | ||
| 47 | margin-left: -.375rem; | ||
| 48 | border: .375rem solid transparent; | ||
| 49 | border-bottom-color: darken($headerBorder, 2%); | ||
| 50 | } | 42 | } |
| 51 | 43 | ||
| 52 | &:after { | 44 | > svg { |
| 53 | bottom: -1px; | 45 | display: inline-block; |
| 54 | border-bottom-color: $contentBackground; | 46 | vertical-align: top; |
| 47 | width: 1.5rem; | ||
| 48 | height: 1.5rem; | ||
| 49 | fill: currentColor; | ||
| 50 | pointer-events: none; | ||
| 55 | } | 51 | } |
| 56 | } | 52 | } |
| 57 | 53 | ||
| 58 | ._nav-current { | 54 | // |
| 59 | outline: 0; | 55 | // Menu |
| 56 | // | ||
| 60 | 57 | ||
| 61 | &:before, &:after { content: ''; } | 58 | ._menu-btn { |
| 59 | border-right: 1px solid $headerBorder; | ||
| 62 | } | 60 | } |
| 63 | 61 | ||
| 64 | // | 62 | ._menu { |
| 65 | // Logo | 63 | position: absolute; |
| 66 | // | 64 | z-index: 1; |
| 65 | top: .25rem; | ||
| 66 | right: .25rem; | ||
| 67 | width: 8rem; | ||
| 68 | height: calc(11.5rem + 1px); | ||
| 69 | font-size: .875rem; | ||
| 70 | background: $contentBackground; | ||
| 71 | border: 1px solid $headerBorder; | ||
| 72 | border-radius: 3px; | ||
| 73 | box-shadow: -1px 1px 1px rgba(black, .05); | ||
| 74 | transition: all 250ms cubic-bezier(0.23, 1, 0.32, 1); | ||
| 75 | opacity: 0; | ||
| 76 | -webkit-transform: scale(0, 0); | ||
| 77 | transform: scale(0, 0); | ||
| 78 | -webkit-transform-origin: 100% 0; | ||
| 79 | transform-origin: 100% 0; | ||
| 80 | |||
| 81 | &:hover, | ||
| 82 | ._menu-btn:hover + & { | ||
| 83 | transition-delay: 100ms; | ||
| 84 | } | ||
| 67 | 85 | ||
| 68 | ._logo { | 86 | &:hover, |
| 69 | position: relative; | 87 | &.active, |
| 70 | float: left; | 88 | ._menu-btn:hover + &, |
| 71 | height: $headerHeight; | 89 | ._menu-btn:focus + & { |
| 90 | opacity: 1; | ||
| 91 | -webkit-transform: scale(1, 1); | ||
| 92 | transform: scale(1, 1); | ||
| 93 | } | ||
| 94 | |||
| 95 | &:focus-within { | ||
| 96 | opacity: 1; | ||
| 97 | -webkit-transform: scale(1, 1); | ||
| 98 | transform: scale(1, 1); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | ._menu-title { | ||
| 72 | margin: 0; | 103 | margin: 0; |
| 73 | line-height: inherit; | 104 | line-height: 1.5rem; |
| 74 | font-size: inherit; | 105 | font-size: 1rem; |
| 75 | font-weight: $boldFontWeight; | 106 | font-weight: $boldFontWeight; |
| 76 | cursor: default; | 107 | letter-spacing: -.5px; |
| 108 | background: $sidebarBackground; | ||
| 109 | border-bottom: 1px solid $sidebarBorder; | ||
| 110 | border-radius: 2px 2px 0 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | ._menu-title-link, | ||
| 114 | ._menu-title-link:hover { | ||
| 115 | display: block; | ||
| 116 | padding: .5rem 1rem; | ||
| 117 | color: $focusText; | ||
| 118 | text-decoration: none; | ||
| 119 | } | ||
| 77 | 120 | ||
| 78 | > ._nav-link { | 121 | ._menu-link { |
| 79 | float: none; | 122 | display: block; |
| 80 | margin-left: .75rem; | 123 | padding: 0 1rem; |
| 81 | padding: 0 .25rem; | 124 | line-height: 2.25rem; |
| 125 | color: inherit; | ||
| 126 | text-decoration: none; | ||
| 127 | |||
| 128 | &:hover { | ||
| 129 | color: $focusText; | ||
| 130 | text-decoration: none; | ||
| 131 | background: $sidebarBackground; | ||
| 82 | } | 132 | } |
| 133 | |||
| 134 | &:last-child { border-radius: 0 0 2px 2px; } | ||
| 83 | } | 135 | } |
| 84 | 136 | ||
| 85 | // | 137 | // |
| @@ -87,20 +139,19 @@ · 1 unmodified line | |||
| 87 | // | 139 | // |
| 88 | 140 | ||
| 89 | ._search { | 141 | ._search { |
| 142 | flex-grow: 1; | ||
| 90 | position: relative; | 143 | position: relative; |
| 91 | float: left; | ||
| 92 | width: $sidebarWidth; | ||
| 93 | height: 100%; | 144 | height: 100%; |
| 94 | padding: .5rem 0 .5rem .5rem; | 145 | padding: .5rem 0 .5rem .5rem; |
| 95 | @extend %border-box; | 146 | @extend %border-box; |
| 96 | 147 | ||
| 97 | @media #{$mediumScreen} { width: $sidebarMediumWidth; } | ||
| 98 | |||
| 99 | &:before { | 148 | &:before { |
| 100 | position: absolute; | 149 | position: absolute; |
| 150 | z-index: 1; | ||
| 101 | top: 1rem; | 151 | top: 1rem; |
| 102 | left: 1rem; | 152 | left: 1rem; |
| 103 | opacity: .4; | 153 | opacity: .4; |
| 154 | pointer-events: none; | ||
| 104 | @if $style == 'dark' { | 155 | @if $style == 'dark' { |
| 105 | @extend %icon, %icon-search-white; | 156 | @extend %icon, %icon-search-white; |
| 106 | } @else { | 157 | } @else { |
| @@ -110,6 +161,7 @@ · 3 unmodified lines | |||
| 110 | } | 161 | } |
| 111 | 162 | ||
| 112 | ._search-input { | 163 | ._search-input { |
| 164 | position: relative; | ||
| 113 | display: block; | 165 | display: block; |
| 114 | width: 100%; | 166 | width: 100%; |
| 115 | height: 100%; | 167 | height: 100%; |
| @@ -164,6 +216,7 @@ · 48 unmodified lines | |||
| 164 | ._search-tag { | 216 | ._search-tag { |
| 165 | display: none; | 217 | display: none; |
| 166 | position: absolute; | 218 | position: absolute; |
| 219 | z-index: 2; | ||
| 167 | top: .875rem; | 220 | top: .875rem; |
| 168 | left: .875rem; | 221 | left: .875rem; |
| 169 | padding: 0 .5rem; | 222 | padding: 0 .5rem; |
| @@ -10,18 +10,17 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | body { -ms-overflow-style: -ms-autohiding-scrollbar; } | 11 | body { -ms-overflow-style: -ms-autohiding-scrollbar; } |
| 12 | 12 | ||
| 13 | ._app, ._container, ._content { overflow: visible; } | 13 | ._app, ._content { overflow: visible; } |
| 14 | 14 | ._app { padding-top: $headerHeight; } | |
| 15 | ._container { | 15 | ._container { margin: 0; } |
| 16 | margin: 0; | ||
| 17 | border: 0; | ||
| 18 | } | ||
| 19 | 16 | ||
| 20 | ._content { | 17 | ._content { |
| 21 | position: static; | 18 | position: static; |
| 22 | height: auto; | 19 | height: auto; |
| 23 | margin: 0; | 20 | margin: 0; |
| 24 | padding: .75rem 1rem 2.5rem; | 21 | padding: .75rem 1rem 2.5rem; |
| 22 | |||
| 23 | &:before { content: none; } | ||
| 25 | } | 24 | } |
| 26 | 25 | ||
| 27 | ._booting:before, ._content-loading:before { font-size: 3rem; } | 26 | ._booting:before, ._content-loading:before { font-size: 3rem; } |
| @@ -33,16 +32,13 @@ · 5 unmodified lines | |||
| 33 | max-width: 100vw; | 32 | max-width: 100vw; |
| 34 | } | 33 | } |
| 35 | 34 | ||
| 36 | ._logo, ._nav { display: none; } | 35 | ._header-btn { width: 2.5rem; } |
| 37 | ._mobile-btn { display: block; } | 36 | ._header-btn[hidden] { display: block; } |
| 37 | ._menu-btn { border-right: 0; } | ||
| 38 | 38 | ||
| 39 | ._search { | 39 | ._search { |
| 40 | float: none; | 40 | padding-right: .125rem; |
| 41 | width: auto; | 41 | padding-left: .125rem; |
| 42 | overflow: hidden; | ||
| 43 | padding-left: 2px; | ||
| 44 | padding-right: 2px; | ||
| 45 | border-right: 0; | ||
| 46 | 42 | ||
| 47 | &:before { left: .5rem; } | 43 | &:before { left: .5rem; } |
| 48 | } | 44 | } |
| @@ -57,7 +53,7 @@ · 8 unmodified lines | |||
| 57 | overflow: visible; | 53 | overflow: visible; |
| 58 | } | 54 | } |
| 59 | 55 | ||
| 60 | ._list, ._sidebar-footer { width: 100%; } | 56 | ._header, ._list, ._sidebar-footer { width: 100%; } |
| 61 | 57 | ||
| 62 | ._list-item { | 58 | ._list-item { |
| 63 | white-space: normal; | 59 | white-space: normal; |
| @@ -85,33 +81,12 @@ · 21 unmodified lines | |||
| 85 | box-shadow: 0 1px $noteGreenBorder, 0 -1px $noteGreenBorder; | 81 | box-shadow: 0 1px $noteGreenBorder, 0 -1px $noteGreenBorder; |
| 86 | } | 82 | } |
| 87 | 83 | ||
| 88 | // Splash | ||
| 89 | |||
| 90 | ._splash-sponsors { margin-top: 1rem; } | ||
| 91 | |||
| 92 | ._splash-sponsor { | ||
| 93 | position: static; | ||
| 94 | |||
| 95 | ._logo-info { | ||
| 96 | left: 1rem; | ||
| 97 | right: 1rem; | ||
| 98 | width: auto; | ||
| 99 | max-width: none; | ||
| 100 | margin: 0; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | // Notice | 84 | // Notice |
| 105 | 85 | ||
| 106 | ._notice { | 86 | ._notice { |
| 107 | position: fixed; | 87 | position: fixed; |
| 108 | left: 0; | 88 | left: 0; |
| 109 | padding: 0 .5rem; | 89 | padding: 0 .5rem; |
| 110 | |||
| 111 | ~ ._sidebar { | ||
| 112 | margin-top: 2.5rem; | ||
| 113 | padding-bottom: 4rem; | ||
| 114 | } | ||
| 115 | } | 90 | } |
| 116 | 91 | ||
| 117 | ._notice-text { font-size: .75em; } | 92 | ._notice-text { font-size: .75em; } |
| @@ -143,76 +118,10 @@ · 25 unmodified lines | |||
| 143 | // Header buttons | 118 | // Header buttons |
| 144 | // | 119 | // |
| 145 | 120 | ||
| 146 | ._mobile-btn { | ||
| 147 | display: none; | ||
| 148 | position: relative; | ||
| 149 | float: left; | ||
| 150 | width: 2.5rem; | ||
| 151 | height: 100%; | ||
| 152 | @extend %hide-text; | ||
| 153 | |||
| 154 | &[disabled] { | ||
| 155 | opacity: .3; | ||
| 156 | cursor: not-allowed; | ||
| 157 | } | ||
| 158 | |||
| 159 | &:before { | ||
| 160 | position: absolute; | ||
| 161 | top: 50%; | ||
| 162 | left: 50%; | ||
| 163 | margin: -.5rem 0 0 -.5rem; | ||
| 164 | @extend %icon; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | ._back-btn { | ||
| 169 | &:before { @extend %icon-back; } | ||
| 170 | } | ||
| 171 | |||
| 172 | ._forward-btn { | 121 | ._forward-btn { |
| 173 | width: 2.25rem; | 122 | margin-right: -.5rem; |
| 174 | -webkit-transform: rotate(180deg); | ||
| 175 | transform: rotate(180deg); | ||
| 176 | |||
| 177 | &:before { | ||
| 178 | margin-left: -.375rem; | ||
| 179 | @extend %icon-back; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | ._home-btn { | ||
| 184 | float: right; | ||
| 185 | width: 2rem; | ||
| 186 | |||
| 187 | &:before { | ||
| 188 | margin-left: -.375rem; | ||
| 189 | @extend %icon-home; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | 123 | ||
| 193 | ._menu-btn { | 124 | > svg { margin-left: -.375rem; } |
| 194 | float: right; | ||
| 195 | |||
| 196 | &:before { @extend %icon-menu; } | ||
| 197 | } | ||
| 198 | |||
| 199 | // | ||
| 200 | // Navigation menu | ||
| 201 | // | ||
| 202 | |||
| 203 | ._mobile-nav { | ||
| 204 | margin: .25rem 0 1.25rem; | ||
| 205 | padding: 0; | ||
| 206 | line-height: 2.8; | ||
| 207 | overflow: hidden; | ||
| 208 | @extend %box; | ||
| 209 | } | ||
| 210 | |||
| 211 | ._mobile-nav-link { | ||
| 212 | float: left; | ||
| 213 | width: 25%; | ||
| 214 | text-align: center; | ||
| 215 | font-weight: $boldFontWeight; | ||
| 216 | } | 125 | } |
| 217 | 126 | ||
| 218 | // | 127 | // |
| @@ -222,14 +131,11 @@ · 3 unmodified lines | |||
| 222 | ._mobile-intro { | 131 | ._mobile-intro { |
| 223 | > ._intro-list { padding-left: 1.5rem; } | 132 | > ._intro-list { padding-left: 1.5rem; } |
| 224 | 133 | ||
| 225 | > ._intro-hide, | 134 | ._intro-hide { |
| 226 | > ._intro-sponsors { | ||
| 227 | position: static; | 135 | position: static; |
| 228 | float: none; | 136 | float: none; |
| 229 | display: block; | 137 | display: block; |
| 230 | margin-top: .75rem; | 138 | margin-top: .75rem; |
| 231 | text-align: center; | 139 | text-align: center; |
| 232 | } | 140 | } |
| 233 | |||
| 234 | ._intro-sponsor { margin: .5em .75em; } | ||
| 235 | } | 141 | } |
| @@ -12,17 +12,7 @@ · 11 unmodified lines | |||
| 12 | @media #{$mediumScreen} { left: $sidebarMediumWidth; } | 12 | @media #{$mediumScreen} { left: $sidebarMediumWidth; } |
| 13 | 13 | ||
| 14 | ._sidebar-hidden & { left: $sidebarHiddenWidth; } | 14 | ._sidebar-hidden & { left: $sidebarHiddenWidth; } |
| 15 | 15 | ~ ._container { padding-bottom: 2.5rem; } | |
| 16 | &:not(._top) ~ ._container { padding-bottom: 2.5rem; } | ||
| 17 | |||
| 18 | &._top { | ||
| 19 | bottom: auto; | ||
| 20 | top: $headerHeight; | ||
| 21 | margin-top: 1px; | ||
| 22 | box-shadow: inset 0 -1px $noticeBorder; | ||
| 23 | |||
| 24 | ~ ._container { padding-top: 2.5rem; } | ||
| 25 | } | ||
| 26 | } | 16 | } |
| 27 | 17 | ||
| 28 | ._notice-text { | 18 | ._notice-text { |
| @@ -40,7 +40,7 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | ._resizer { | 41 | ._resizer { |
| 42 | position: absolute; | 42 | position: absolute; |
| 43 | z-index: $sidebarZ + 1; | 43 | z-index: $sidebarZ; |
| 44 | top: $headerHeight; | 44 | top: $headerHeight; |
| 45 | bottom: 0; | 45 | bottom: 0; |
| 46 | left: $sidebarWidth; | 46 | left: $sidebarWidth; |
| @@ -37,8 +37,6 @@ · 36 unmodified lines | |||
| 37 | %icon-clear { background-position: -3rem 0; } | 37 | %icon-clear { background-position: -3rem 0; } |
| 38 | %icon-settings { background-position: 0 -1rem; } | 38 | %icon-settings { background-position: 0 -1rem; } |
| 39 | %icon-check { background-position: -1rem -1rem; } | 39 | %icon-check { background-position: -1rem -1rem; } |
| 40 | %icon-menu { background-position: -2rem -1rem; @extend %darkIconFix !optional; } | ||
| 41 | %icon-home { background-position: -3rem -1rem; @extend %darkIconFix !optional; } | ||
| 42 | %icon-path { background-position: 0 -2rem; } | 40 | %icon-path { background-position: 0 -2rem; } |
| 43 | %icon-search-white { background-position: -1rem -2rem; } | 41 | %icon-search-white { background-position: -1rem -2rem; } |
| 44 | %icon-dir-white { background-position: -2rem -2rem; } | 42 | %icon-dir-white { background-position: -2rem -2rem; } |
| @@ -54,7 +52,6 @@ · 9 unmodified lines | |||
| 54 | %icon-clipboard { background-position: 0 -5rem; } | 52 | %icon-clipboard { background-position: 0 -5rem; } |
| 55 | %icon-clipboard-white { background-position: -1rem -5rem; } | 53 | %icon-clipboard-white { background-position: -1rem -5rem; } |
| 56 | %icon-close-white { background-position: -2rem -5rem; } | 54 | %icon-close-white { background-position: -2rem -5rem; } |
| 57 | %icon-back { background-position: -3rem -5rem; @extend %darkIconFix !optional; } | ||
| 58 | 55 | ||
| 59 | ._icon-codeceptjs:before { background-position: -3rem 0; } | 56 | ._icon-codeceptjs:before { background-position: -3rem 0; } |
| 60 | ._icon-codeception:before { background-position: -4rem 0; } | 57 | ._icon-codeception:before { background-position: -4rem 0; } |
| @@ -7,7 +7,7 @@ $style: 'dark'; · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | $maxWidth: 80rem; | 8 | $maxWidth: 80rem; |
| 9 | $headerHeight: 3rem; | 9 | $headerHeight: 3rem; |
| 10 | $sidebarWidth: 18rem; | 10 | $sidebarWidth: 20rem; |
| 11 | $sidebarMediumWidth: 16rem; | 11 | $sidebarMediumWidth: 16rem; |
| 12 | $sidebarHiddenWidth: 9px; | 12 | $sidebarHiddenWidth: 9px; |
| 13 | 13 | ||
| @@ -37,7 +37,7 @@ $linkColor: $textColor; · 23 unmodified lines | |||
| 37 | $linkColorHover: white; | 37 | $linkColorHover: white; |
| 38 | $linkTextDecoration: underline; | 38 | $linkTextDecoration: underline; |
| 39 | 39 | ||
| 40 | $headerBackground: #1e1e1e; | 40 | $headerBackground: #1c1c1c; |
| 41 | $headerBorder: #000; | 41 | $headerBorder: #000; |
| 42 | 42 | ||
| 43 | $sidebarBackground: #24282a; | 43 | $sidebarBackground: #24282a; |
| @@ -7,7 +7,7 @@ $style: 'light'; · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | $maxWidth: 80rem; | 8 | $maxWidth: 80rem; |
| 9 | $headerHeight: 3rem; | 9 | $headerHeight: 3rem; |
| 10 | $sidebarWidth: 18rem; | 10 | $sidebarWidth: 20rem; |
| 11 | $sidebarMediumWidth: 16rem; | 11 | $sidebarMediumWidth: 16rem; |
| 12 | $sidebarHiddenWidth: 9px; | 12 | $sidebarHiddenWidth: 9px; |
| 13 | 13 | ||
| @@ -37,11 +37,11 @@ $linkColor: #3377c0; · 23 unmodified lines | |||
| 37 | $linkColorHover: #2f6cb6; | 37 | $linkColorHover: #2f6cb6; |
| 38 | $linkTextDecoration: none; | 38 | $linkTextDecoration: none; |
| 39 | 39 | ||
| 40 | $headerBackground: #f0f0f0; | 40 | $headerBackground: #eee; |
| 41 | $headerBorder: #d9d9d9; | 41 | $headerBorder: #d7d7d7; |
| 42 | 42 | ||
| 43 | $sidebarBackground: #f9f9f9; | 43 | $sidebarBackground: #f9f9f9; |
| 44 | $sidebarBorder: #e3e3e3; | 44 | $sidebarBorder: #e1e1e1; |
| 45 | 45 | ||
| 46 | $scrollbarColor: #d2d2d2; | 46 | $scrollbarColor: #d2d2d2; |
| 47 | $scrollbarColorHover: #aaa; | 47 | $scrollbarColorHover: #aaa; |
| @@ -184,7 +184,7 @@ class App < Sinatra::Application · 183 unmodified lines | |||
| 184 | end | 184 | end |
| 185 | 185 | ||
| 186 | def app_size | 186 | def app_size |
| 187 | @app_size ||= cookies[:size].nil? ? '18rem' : "#{cookies[:size]}px" | 187 | @app_size ||= cookies[:size].nil? ? '20rem' : "#{cookies[:size]}px" |
| 188 | end | 188 | end |
| 189 | 189 | ||
| 190 | def app_layout | 190 | def app_layout |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -1 +0,0 @@ | |||
| 1 | http://www.entypo.com/ | ||
Binary file not shown.
Binary file not shown.
| @@ -31,7 +31,7 @@ class AppTest < MiniTest::Spec · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | it "sets default size" do | 32 | it "sets default size" do |
| 33 | get '/' | 33 | get '/' |
| 34 | assert_includes last_response.body, 'data-size="18rem"' | 34 | assert_includes last_response.body, 'data-size="20rem"' |
| 35 | end | 35 | end |
| 36 | 36 | ||
| 37 | it "sets size from cookie" do | 37 | it "sets size from cookie" do |
| @@ -115,7 +115,7 @@ class AppTest < MiniTest::Spec · 77 unmodified lines | |||
| 115 | 115 | ||
| 116 | it "sets default size" do | 116 | it "sets default size" do |
| 117 | get '/manifest.appcache' | 117 | get '/manifest.appcache' |
| 118 | assert_includes last_response.body, '18rem' | 118 | assert_includes last_response.body, '20rem' |
| 119 | end | 119 | end |
| 120 | 120 | ||
| 121 | it "sets size from cookie" do | 121 | it "sets size from cookie" do |
| @@ -1,22 +1,28 @@ | |||
| 1 | <div class="_app<%= " #{app_layout}" if app_layout %>" role="application"> | 1 | <div class="_app<%= " #{app_layout}" if app_layout %>" role="application"> |
| 2 | <header class="_header" role="banner"> | 2 | <header class="_header" role="banner"> |
| 3 | <button type="button" class="_mobile-btn _back-btn">Back</button> | 3 | <button type="button" aria-label="Toggle navigation" class="_header-btn" data-toggle-sidebar hidden> |
| 4 | <button type="button" class="_mobile-btn _forward-btn">Forward</button> | 4 | <svg viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg> |
| 5 | <button type="button" class="_mobile-btn _menu-btn">Menu</button> | 5 | </button> |
| 6 | <button type="button" class="_mobile-btn _home-btn">Home</button> | ||
| 7 | <form class="_search" role="search"> | 6 | <form class="_search" role="search"> |
| 8 | <input type="search" name="q" class="_search-input" placeholder="Search…" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" maxlength="30" aria-label="Search"> | 7 | <input type="search" name="q" class="_search-input" placeholder="Search…" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" maxlength="30" aria-label="Search"> |
| 9 | <button type="reset" class="_search-clear" title="Clear search">Clear search</button> | 8 | <button type="reset" class="_search-clear" title="Clear search">Clear search</button> |
| 10 | <div class="_search-tag"></div> | 9 | <div class="_search-tag"></div> |
| 11 | </form> | 10 | </form> |
| 12 | <h1 class="_logo"> | 11 | <button type="button" aria-label="Back" class="_header-btn" data-back hidden> |
| 13 | <a href="/" class="_nav-link" title="Offline API Documentation Browser">DevDocs</a><%= "/ #{@doc['full_name']}" if @doc %> | 12 | <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></svg> |
| 14 | </h1> | 13 | </button> |
| 15 | <nav class="_nav" role="navigation"> | 14 | <button type="button" aria-label="Forward" class="_header-btn _forward-btn" data-forward hidden> |
| 16 | <a href="/offline" class="_nav-link">Offline</a> | 15 | <svg viewBox="0 0 24 24"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></svg> |
| 17 | <a href="/about" class="_nav-link">About</a> | 16 | </button> |
| 18 | <a href="/news" class="_nav-link">News</a> | 17 | <button type="button" aria-label="Toggle menu" title="Toggle menu" class="_header-btn _menu-btn" data-toggle-menu> |
| 19 | <a href="/help" class="_nav-link">Tips</a> | 18 | <svg viewBox="0 0 24 24"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></svg> |
| 19 | </button> | ||
| 20 | <nav class="_menu" role="navigation"> | ||
| 21 | <h1 class="_menu-title"><a href="/" class="_menu-title-link">DevDocs</a></h1> | ||
| 22 | <a href="/offline" class="_menu-link">Offline</a> | ||
| 23 | <a href="/news" class="_menu-link">Changelog</a> | ||
| 24 | <a href="/help" class="_menu-link">Help</a> | ||
| 25 | <a href="/about" class="_menu-link">About</a> | ||
| 20 | </nav> | 26 | </nav> |
| 21 | </header> | 27 | </header> |
| 22 | <section class="_sidebar" tabindex="-1"> | 28 | <section class="_sidebar" tabindex="-1"> |
| @@ -34,7 +40,7 @@ · 11 unmodified lines | |||
| 34 | </div> | 40 | </div> |
| 35 | <style data-size="<%= app_size %>" data-resizer> | 41 | <style data-size="<%= app_size %>" data-resizer> |
| 36 | ._container { margin-left: <%= app_size %>; } | 42 | ._container { margin-left: <%= app_size %>; } |
| 37 | ._search, ._list, ._sidebar-footer { width: <%= app_size %>; } | 43 | ._header, ._list, ._sidebar-footer { width: <%= app_size %>; } |
| 38 | ._list-hover.clone { min-width: <%= app_size %>; } | 44 | ._list-hover.clone { min-width: <%= app_size %>; } |
| 39 | ._notice, ._path, ._resizer { left: <%= app_size %>; } | 45 | ._notice, ._path, ._resizer { left: <%= app_size %>; } |
| 40 | </style> | 46 | </style> |