diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2015-11-07 13:37:08 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2015-11-07 13:37:08 +0000 |
commit | e680ae1aa31b9a48fb6a94b3a728ff962102bd42 (patch) | |
tree | 7956fb1a78a8cf8647a3348eacb2cd516ef1c724 /public | |
parent | 9c85a341ca01b8af0f7b157f7aa011a048341a9d (diff) | |
download | redmine-e680ae1aa31b9a48fb6a94b3a728ff962102bd42.tar.gz redmine-e680ae1aa31b9a48fb6a94b3a728ff962102bd42.zip |
Responsive layout for mobile devices (#19097).
Patch by Felix Gliesche.
git-svn-id: http://svn.redmine.org/redmine/trunk@14817 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'public')
-rw-r--r-- | public/javascripts/responsive.js | 83 | ||||
-rw-r--r-- | public/stylesheets/responsive.css | 595 |
2 files changed, 678 insertions, 0 deletions
diff --git a/public/javascripts/responsive.js b/public/javascripts/responsive.js new file mode 100644 index 000000000..4c6c3be8f --- /dev/null +++ b/public/javascripts/responsive.js @@ -0,0 +1,83 @@ +// generic layout specific responsive stuff goes here + +function openFlyout() { + $('html').addClass('flyout-is-active'); + $('#wrapper2').on('click', function(e){ + e.preventDefault(); + e.stopPropagation(); + closeFlyout(); + }); +} + +function closeFlyout() { + $('html').removeClass('flyout-is-active'); + $('#wrapper2').off('click'); +} + + +function isMobile() { + return $('.js-flyout-menu-toggle-button').is(":visible"); +} + +function setupFlyout() { + var mobileInit = false, + desktopInit = false; + + /* click handler for mobile menu toggle */ + $('.js-flyout-menu-toggle-button').on('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + if($('html').hasClass('flyout-is-active')) { + closeFlyout(); + } else { + openFlyout(); + } + }); + + /* bind resize handler */ + $(window).resize(function() { + initMenu(); + }) + + /* menu init function for dom detaching and appending on mobile / desktop view */ + function initMenu() { + + var _initMobileMenu = function() { + /* only init mobile menu, if it hasn't been done yet */ + if(!mobileInit) { + + $('#main-menu > ul').detach().appendTo('.js-project-menu'); + $('#top-menu > ul').detach().appendTo('.js-general-menu'); + $('#sidebar > *').detach().appendTo('.js-sidebar'); + $('#account ul').detach().appendTo('.js-profile-menu'); + + mobileInit = true; + desktopInit = false; + } + } + + var _initDesktopMenu = function() { + if(!desktopInit) { + + $('.js-project-menu > ul').detach().appendTo('#main-menu'); + $('.js-general-menu ul').detach().appendTo('#top-menu'); + $('.js-sidebar > *').detach().appendTo('#sidebar'); + $('.js-profile-menu ul').detach().appendTo('#account'); + + desktopInit = true; + mobileInit = false; + } + } + + if(isMobile()) { + _initMobileMenu(); + } else { + _initDesktopMenu(); + } + } + + // init menu on page load + initMenu(); +} + +$(document).ready(setupFlyout); diff --git a/public/stylesheets/responsive.css b/public/stylesheets/responsive.css new file mode 100644 index 000000000..a01d126a4 --- /dev/null +++ b/public/stylesheets/responsive.css @@ -0,0 +1,595 @@ +/*----------------------------------------*\ + RESPONSIVE CSS +\*----------------------------------------*/ + + +/* + + CONTENTS + + A) BASIC MOBILE RESETS + B) HEADER & TOP MENUS + C) MAIN CONTENT & SIDEBAR + D) TOGGLE BUTTON & FLYOUT MENU + +*/ + + +/* Hide new elements (toggle button and flyout menu) above 900px */ +.mobile-toggle-button, +.flyout-menu +{ + display: none; +} + +/* + redmine's body is set to min-width: 900px + add first breakpoint here and start adding responsiveness +*/ + +@media all and (max-width: 899px) +{ + /*----------------------------------------*\ + A) BASIC MOBILE RESETS + \*----------------------------------------*/ + + /* + apply natural border box, see: http://www.paulirish.com/2012/box-sizing-border-box-ftw/ + this helps us to better deal with percentages and padding / margin + */ + *, + *:before, + *:after + { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + body, + html + { + height: 100%; + margin: 0; + padding: 0; + } + + html + { + overflow-y: auto; /* avoid 2nd scrollbar on desktop */ + } + + body + { + overflow-x: hidden; /* hide horizontal overflow */ + + min-width: 0; /* reset the min-width of 900px */ + } + + + body, + input, + select, + textarea, + button + { + font-size: 14px; /* Set font-size for standard elements to 14px */ + } + + + select + { + max-width: 100%; /* prevent long names within select menues from breaking content */ + } + + + #wrapper + { + position: relative; + + max-width: 100%; + } + + #wrapper, + #wrapper2 + { + margin: 0; + } + + /*----------------------------------------*\ + B) HEADER & TOP MENUS + \*----------------------------------------*/ + + #header + { + width: 100%; + height: 64px; /* the height of our header on mobile */ + min-height: 0; + margin: 0; + padding: 0; + + border: none; + background-color: #628db6; + } + + /* Hide project name on mobile (project name is still visible in select menu) */ + #header h1 + { + display: none !important; + } + + /* reset #header a color for mobile toggle button */ + #header a.mobile-toggle-button + { + color: #f8f8f8; + } + + + /* Hide top-menu and main-menu on mobile, because it's placed in our flyout menu */ + #top-menu, + #header #main-menu + { + display: none; + } + + /* the quick search within header holding search form and #project_quick_jump_box box*/ + #header #quick-search + { + float: none; + clear: none; /* there are themes which set clear property, this resets it */ + + max-width: 100%; /* reset max-width */ + margin: 0; + + background: inherit; + } + + /* this represents the dropdown arrow to left of the mobile project menu */ + #header .jump-box-arrow:before + { + /* set a font-size in order to achive same result in different themes */ + font-family: Verdana, sans-serif; + font-size: 2em; + line-height: 64px; + + position: absolute; + left: 0; + + width: 2em; + padding: 0 .5em; + /* achieve dropdwon arrow by scaling a caret character */ + + content: '^'; + -webkit-transform: scale(1,-.8); + -ms-transform: scale(1,-.8); + transform: scale(1,-.8); + text-align: right; + pointer-events: none; + + opacity: .6; + } + + /* styles for combobox within quick-search (#project_quick_jump_box) */ + #header #quick-search select + { + font-size: 1.5em; + font-weight: bold; + line-height: 1.2; + + position: absolute; + top: 15px; + left: 0; + + float: left; + + width: 100%; + max-width: 100%; + height: 2em; + height: 35px; + padding: 5px; + padding-right: 72px; + padding-left: 50px; + + text-indent: .01px; + + color: inherit; + border: 0; + -webkit-border-radius: 0; + border-radius: 0; + background: none; + -webkit-box-shadow: none; + box-shadow: none; + /* hide default browser arrow */ + + -webkit-appearance: none; + -moz-appearance: none; + } + + #header #quick-search form + { + display: none; + } + + /*----------------------------------------*\ + C) MAIN CONTENT & SIDEBAR + \*----------------------------------------*/ + + #main + { + padding: 0; + } + + #main.nosidebar #content, + div#content + { + width: 100%; + min-height: 0; /* reset min-height of #content */ + margin: 0; + } + + + /* hide sidebar and sidebar switch panel, since it's placed in mobile flyout menu */ + #sidebar, + #sidebar-switch-panel + { + display: none; + } + + .splitcontentleft + { + width: 100%; /* use full width */ + } + + .splitcontentright + { + width: 100%; /* use full width */ + } + + /*----------------------------------------*\ + D) TOGGLE BUTTON & FLYOUT MENU + \*----------------------------------------*/ + + /* Mobile toggle button */ + + .mobile-toggle-button + { + font-size: 42px; + line-height: 64px; + + position: relative; + z-index: 10; + + display: block; /* remove display: none; of non-mobile version */ + float: right; + + width: 60px; + height: 64px; + margin-top: 0; + + text-align: center; + + border-left: 1px solid #ddd; + } + + .mobile-toggle-button:hover, + .mobile-toggle-button:active + { + text-decoration: none; + } + + .mobile-toggle-button:after + { + font-family: Verdana, sans-serif; + + display: block; + + margin-top: -3px; + + content: '\2261'; + } + + /* search magnifier icon */ + .search-magnifier + { + font-family: Verdana; + + cursor: pointer; + -webkit-transform: rotate(-45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + + color: #bbb; + } + + .search-magnifier--flyout + { + font-size: 25px; + line-height: 54px; + + position: absolute; + z-index: 1; + left: 12px; + } + + + /* Flyout Menu */ + + .flyout-menu + { + position: absolute; + right: -250px; + + display: block; /* remove display: none; of non-mobile version */ + overflow-x: hidden; + + width: 250px; + height: 100%; + margin: 0; /* reset margin for themes that define it */ + padding: 0; /* reset padding for themes that define it */ + + color: white; + background-color: #3e5b76; + } + + + /* avoid zoom on search input focus for ios devices */ + .flyout-menu input[type='text'] + { + font-size: 16px; + } + + .flyout-menu h3 + { + font-size: 11px; + line-height: 19px; + + height: 20px; + margin: 0; + padding: 0; + + letter-spacing: .1em; + text-transform: uppercase; + + color: white; + border-top: 1px solid #506a83; + border-bottom: 1px solid #506a83; + background-color: #628db6; + } + + .flyout-menu h4 + { + color: white; + } + + .flyout-menu h3, + .flyout-menu h4, + .flyout-menu > p, + .flyout-menu > a, + .flyout-menu ul li a, + .flyout-menu__search, + .flyout-menu__sidebar > div, + .flyout-menu__sidebar > p, + .flyout-menu__sidebar > a, + .flyout-menu__sidebar > form, + .flyout-menu > div, + .flyout-menu > form + { + padding-left: 8px; + } + + .flyout-menu .flyout-menu__avatar + { + margin-top: -1px; /* move avatar up 1px */ + padding-left: 0; + } + + .flyout-menu__sidebar > form + { + display: block; + } + + .flyout-menu__sidebar > form h3 + { + margin-left: -8px; + } + + .flyout-menu__sidebar > form label + { + display: inline-block; + + margin: 8px 0; + } + + .flyout-menu__sidebar > form br br + { + display: none; + } + + .flyout-menu ul + { + margin: 0; + padding: 0; + + list-style: none; + } + + .flyout-menu ul li a + { + line-height: 40px; + + display: block; + overflow: hidden; + + height: 40px; + + white-space: nowrap; + text-overflow: ellipsis; + + border-top: 1px solid rgba(255,255,255,.1); + } + + .flyout-menu ul li:first-child a + { + line-height: 39px; + + height: 39px; + + border-top: none; + } + + .flyout-menu a + { + color: white; + } + + .flyout-menu ul li a:hover + { + text-decoration: none; + } + + .flyout-menu ul li a.new-object, + .new-object ~ .menu-children + { + display: none; + } + + /* Left flyout search container */ + .flyout-menu__search + { + line-height: 54px; + + height: 64px; + padding-top: 3px; + padding-right: 8px; + } + + .flyout-menu__search input[type='text'] + { + line-height: 2; + + width: 100%; + height: 38px; + padding-left: 27px; + + vertical-align: middle; + + border: none; + -webkit-border-radius: 3px; + border-radius: 3px; + background-color: #fff; + } + + .flyout-menu__avatar + { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + + width: 100%; + + border-top: 1px solid rgba(255,255,255,.1); + } + + + .flyout-menu__avatar img.gravatar + { + width: 40px; + height: 40px; + padding: 0; + + vertical-align: top; + + border-width: 0; + } + + .flyout-menu__avatar a + { + line-height: 40px; + + height: auto; + height: 40px; + + text-decoration: none; + + color: white; + } + + /* avatar */ + .flyout-menu__avatar a:first-child + { + line-height: 0; + + width: 40px; + padding: 0; + } + + .flyout-menu__avatar .user + { + padding-left: 15px; + } + + /* user link when no avatar is present */ + .flyout-menu__avatar--no-avatar a.user + { + line-height: 40px; + + padding-left: 8px; + } + + + .flyout-is-active body + { + overflow: hidden; /* for body not to have scrollbars when left flyout menu is active */ + } + + html.flyout-is-active + { + overflow: hidden; + } + + + .flyout-is-active #wrapper + { + right: 250px; /* when left flyout is active, move body to the right (same amount like flyout-menu's width) */ + + height: 100%; + } + + .flyout-is-active .mobile-toggle-button:after + { + content: '\00D7'; /* close glyph */ + } + + .flyout-is-active #wrapper2 + { + + /* + * only relevant for devices with cursor when flyout it active, in order to show, + * that whole wrapper content is clickable and closes flyout menu + */ + cursor: pointer; + } + + + #admin-menu + { + padding-left: 0; + } + + #admin-menu li + { + padding-bottom: 0; + } + + #admin-menu a, + #admin-menu a.selected + { + line-height: 40px; + + padding: 0; + padding-left: 32px !important; + + background-position: 8px 50%; + } +} |