From eadd889813e6cffe3ea8527dea4ecf8f7d04ac90 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Fri, 2 Jun 2017 17:39:26 +1000 Subject: [PATCH] Improve mobile and settings page Use native scroll on mobile devices (much better UX) Stack settings menu items 2 column medium, 3 column large The settings search is now forcibly focused --- modules/backend/assets/css/october.css | 50 +++++++----- modules/backend/assets/js/october-min.js | 44 +++++------ modules/backend/assets/js/october.navbar.js | 6 +- .../backend/assets/js/october.scrollbar.js | 11 ++- .../backend/assets/js/october.sidenav-tree.js | 78 +++++++++++-------- modules/backend/assets/js/october.sidenav.js | 10 ++- .../backend/assets/js/october.verticalmenu.js | 3 +- .../assets/less/controls/scrollbar.less | 37 +++++---- .../assets/less/controls/sidenav-tree.less | 53 +++++++++++-- .../backend/assets/less/core/variables.less | 2 +- .../backend/assets/less/layout/layout.less | 4 +- .../backend/assets/less/layout/mainmenu.less | 38 ++++++--- .../backend/assets/less/layout/sidenav.less | 7 ++ modules/backend/layouts/_browser_detector.htm | 19 +++-- modules/backend/layouts/_mainmenu.htm | 2 +- .../backend/models/brandsetting/custom.less | 9 --- modules/system/assets/ui/js/drag.scroll.js | 66 +++++++++------- .../assets/ui/js/inspector.editor.dropdown.js | 11 +-- modules/system/assets/ui/js/toolbar.js | 12 ++- modules/system/assets/ui/less/toolbar.less | 7 ++ modules/system/assets/ui/storm-min.js | 39 +++++----- modules/system/assets/ui/storm.css | 1 + modules/system/controllers/Settings.php | 6 ++ modules/system/controllers/settings/index.htm | 13 +++- 24 files changed, 339 insertions(+), 189 deletions(-) diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 100badd03..94c5c4e69 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -154,18 +154,19 @@ .control-scrollbar > div{-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0)} .control-scrollbar > .scrollbar-scrollbar{position:absolute;z-index:100} .control-scrollbar > .scrollbar-scrollbar .scrollbar-track{background-color:transparent;position:relative;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} -.control-scrollbar > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{background-color:#aaaaaa;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;overflow:hidden;position:absolute} +.control-scrollbar > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{background-color:rgba(0,0,0,0.35);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;overflow:hidden;position:absolute} .control-scrollbar > .scrollbar-scrollbar.disabled{display:none !important} -.control-scrollbar.vertical > .scrollbar-scrollbar{right:0;width:4px} -.control-scrollbar.vertical > .scrollbar-scrollbar .scrollbar-track{height:100%;width:4px} -.control-scrollbar.vertical > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:20px;width:4px;top:0;left:0} -.control-scrollbar.vertical > .scrollbar-scrollbar:active,.control-scrollbar.vertical > .scrollbar-scrollbar:hover{width:6px;-webkit-transition:width 0.3s;transition:width 0.3s} -.control-scrollbar.vertical > .scrollbar-scrollbar:active .scrollbar-track,.control-scrollbar.vertical > .scrollbar-scrollbar:hover .scrollbar-track,.control-scrollbar.vertical > .scrollbar-scrollbar:active .scrollbar-thumb,.control-scrollbar.vertical > .scrollbar-scrollbar:hover .scrollbar-thumb{width:6px;-webkit-transition:width 0.3s;transition:width 0.3s} -.control-scrollbar.horizontal > .scrollbar-scrollbar{margin:0 0 5px;clear:both;height:4px} -.control-scrollbar.horizontal > .scrollbar-scrollbar .scrollbar-track{width:100%;height:4px} -.control-scrollbar.horizontal > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:4px;margin:2px 0;left:0;top:0} -.control-scrollbar.horizontal > .scrollbar-scrollbar:active,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover{height:6px;-webkit-transition:height 0.3s;transition:height 0.3s} -.control-scrollbar.horizontal > .scrollbar-scrollbar:active .scrollbar-track,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover .scrollbar-track,.control-scrollbar.horizontal > .scrollbar-scrollbar:active .scrollbar-thumb,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover .scrollbar-thumb{height:6px;-webkit-transition:height 0.3s;transition:height 0.3s} +.control-scrollbar.vertical > .scrollbar-scrollbar{right:0;margin-right:5px;width:6px} +.control-scrollbar.vertical > .scrollbar-scrollbar .scrollbar-track{height:100%;width:6px} +.control-scrollbar.vertical > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:20px;width:6px;top:0;left:0} +.control-scrollbar.vertical > .scrollbar-scrollbar:active,.control-scrollbar.vertical > .scrollbar-scrollbar:hover{width:8px;-webkit-transition:width 0.3s;transition:width 0.3s} +.control-scrollbar.vertical > .scrollbar-scrollbar:active .scrollbar-track,.control-scrollbar.vertical > .scrollbar-scrollbar:hover .scrollbar-track,.control-scrollbar.vertical > .scrollbar-scrollbar:active .scrollbar-thumb,.control-scrollbar.vertical > .scrollbar-scrollbar:hover .scrollbar-thumb{width:8px;-webkit-transition:width 0.3s;transition:width 0.3s} +.control-scrollbar.horizontal > .scrollbar-scrollbar{margin:0 0 5px;clear:both;height:6px} +.control-scrollbar.horizontal > .scrollbar-scrollbar .scrollbar-track{width:100%;height:6px} +.control-scrollbar.horizontal > .scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:6px;margin:2px 0;left:0;top:0} +.control-scrollbar.horizontal > .scrollbar-scrollbar:active,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover{height:8px;-webkit-transition:height 0.3s;transition:height 0.3s} +.control-scrollbar.horizontal > .scrollbar-scrollbar:active .scrollbar-track,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover .scrollbar-track,.control-scrollbar.horizontal > .scrollbar-scrollbar:active .scrollbar-thumb,.control-scrollbar.horizontal > .scrollbar-scrollbar:hover .scrollbar-thumb{height:8px;-webkit-transition:height 0.3s;transition:height 0.3s} +html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} .no-touch .control-scrollbar > .scrollbar-scrollbar{opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s} .no-touch .control-scrollbar:active > .scrollbar-scrollbar,.no-touch .control-scrollbar:hover > .scrollbar-scrollbar{opacity:1} @media (max-width:768px){.responsive-sidebar > .layout-cell:last-child .control-scrollbar{overflow:visible;height:auto} @@ -431,7 +432,7 @@ body.dragging .control-treeview.treeview-light ol.dragging > li > div,body.dragg .sidenav-tree ul.top-level > li > div.group:before,.sidenav-tree ul.top-level > li > div.group:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #34495e;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101} .sidenav-tree ul.top-level > li > div.group:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid rgba(0,0,0,0.15);border-bottom-width:0} .sidenav-tree ul.top-level > li > ul li a{display:block;position:relative;padding:18px 25px 18px 55px;background:transparent;border-bottom:1px solid rgba(0,0,0,0.15);color:#ffffff;text-decoration:none !important;opacity:0.65;filter:alpha(opacity=65)} -.sidenav-tree ul.top-level > li > ul li a:hover{text-decoration:none} +.sidenav-tree ul.top-level > li > ul li a:active,.sidenav-tree ul.top-level > li > ul li a:hover{opacity:1;filter:alpha(opacity=100);text-decoration:none} .sidenav-tree ul.top-level > li > ul li a i{position:absolute;left:16px;top:18px;font-size:22px} .sidenav-tree ul.top-level > li > ul li a span{display:block;line-height:150%} .sidenav-tree ul.top-level > li > ul li a span.header{color:#ffffff;font-size:15px;margin-bottom:5px} @@ -441,8 +442,17 @@ body.dragging .control-treeview.treeview-light ol.dragging > li > div,body.dragg .sidenav-tree ul.top-level > li > ul li.active a{color:rgba(255,255,255,0.91);padding-right:20px} .sidenav-tree ul.top-level > li > ul li.active a span.header{color:#ffffff} .sidenav-tree ul.top-level > li > ul li.active a span.description{color:rgba(255,255,255,0.91)} -.sidenav-tree ul.top-level > li > ul li:last-child a{border-bottom:none} .sidenav-tree .back-link{display:none} +@media (min-width:768px){.sidenav-tree-root .sidenav-tree{width:600px} +.sidenav-tree-root .sidenav-tree ul.top-level > li > ul{font-size:0;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;align-content:stretch} +.sidenav-tree-root .sidenav-tree ul.top-level > li > ul > li{display:inline-block;width:300px} +.sidenav-tree-root .sidenav-tree ul.top-level > li > ul > li a{height:100%} +} +@media (min-width:768px) and (max-width:991px){.sidenav-tree-root .sidenav-tree{width:100%} +.sidenav-tree-root .sidenav-tree ul.top-level > li > ul > li{width:50%} +} +@media (min-width:1200px){.sidenav-tree-root .sidenav-tree{width:900px} +} @media (max-width:768px){.sidenav-tree{width:100%;height:auto !important;display:block !important} .sidenav-tree > .layout{display:none} .sidenav-tree-root .sidenav-tree{width:100% !important;height:100% !important;display:table-cell !important} @@ -501,7 +511,7 @@ div.control-scrollpad > div::-webkit-scrollbar{width:0;height:0} div.control-scrollpad[data-direction=horizontal] > div{overflow-x:scroll;overflow-y:hidden;width:100%} div.control-scrollpad[data-direction=horizontal] > div::-webkit-scrollbar{width:auto;height:0} div.control-scrollpad > .scrollpad-scrollbar{z-index:199;position:absolute;top:0;right:0;bottom:0;width:11px;background-color:transparent;opacity:0;overflow:hidden;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.3s;transition:opacity 0.3s} -div.control-scrollpad > .scrollpad-scrollbar .drag-handle{position:absolute;right:2px;min-height:10px;width:7px;background-color:#aaaaaa;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} +div.control-scrollpad > .scrollpad-scrollbar .drag-handle{position:absolute;right:2px;min-height:10px;width:7px;background-color:rgba(0,0,0,0.35);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} div.control-scrollpad > .scrollpad-scrollbar:hover{opacity:0.7;filter:alpha(opacity=70);-webkit-transition:opacity 0 linear;transition:opacity 0 linear} div.control-scrollpad > .scrollpad-scrollbar[data-visible]{opacity:0.7;filter:alpha(opacity=70)} div.control-scrollpad > .scrollpad-scrollbar[data-hidden]{display:none} @@ -584,7 +594,7 @@ html.svg .svg-icon-container i.svg-replace{display:none} 100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)} } .fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp} -body.drag *{cursor:drag !important;cursor:-webkit-grab !important;cursor:-moz-grab !important} +html:not(.mobile) body.drag *{cursor:drag !important;cursor:-webkit-grab !important;cursor:-moz-grab !important} body.dragging,body.dragging *{cursor:move !important} body.loading,body.loading *{cursor:wait !important} body.no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default !important} @@ -648,7 +658,7 @@ body.slim-container .layout.layout-container,body.slim-container .layout .layout .flex-layout-item.center{-webkit-align-self:center;-moz-align-self:center;-ms-align-self:center;align-self:center} .flex-layout-item.relative{position:relative} .flex-layout-item.layout-container{max-width:none} -body.mainmenu-open{overflow:hidden} +body.mainmenu-open{overflow:hidden;position:fixed} .mainmenu-tooltip .tooltip-inner{font-size:13px;padding:6px 16px} nav#layout-mainmenu{background-color:#000000;padding:0 0 0 20px;line-height:0;white-space:nowrap;vertical-align:top} nav#layout-mainmenu a{text-decoration:none} @@ -712,9 +722,11 @@ nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:first-child{margin-left: nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:hover .nav-label{width:auto;min-width:100px;text-overflow:all;overflow:visible;z-index:2} nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li.active:first-child{margin-left:0} nav#layout-mainmenu .menu-toggle{height:45px;line-height:45px;font-size:16px;display:none} -nav#layout-mainmenu .menu-toggle .menu-toggle-icon{background:#333;display:inline-block;height:45px;line-height:45px;width:45px;text-align:center} -nav#layout-mainmenu .menu-toggle .menu-toggle-icon i{line-height:1;font-size:30px;vertical-align:middle} +nav#layout-mainmenu .menu-toggle .menu-toggle-icon{background:#333;display:inline-block;height:45px;line-height:45px;width:45px;text-align:center;opacity:.7} +nav#layout-mainmenu .menu-toggle .menu-toggle-icon i{line-height:45px;font-size:20px;vertical-align:bottom} nav#layout-mainmenu .menu-toggle .menu-toggle-title{margin-left:10px} +nav#layout-mainmenu .menu-toggle:hover .menu-toggle-icon{opacity:1} +body.mainmenu-open nav#layout-mainmenu .menu-toggle-icon{opacity:1} nav#layout-mainmenu.navbar-mode-collapse{padding-left:0;height:45px} nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-preview a{height:45px;line-height:45px} nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-account > a{height:45px;line-height:45px} @@ -758,6 +770,7 @@ nav#layout-mainmenu.navbar .menu-toggle{display:inline-block;color:#ffffff !impo .mainmenu-collapsed.scroll-before .scroll-marker.before{display:block} .mainmenu-collapsed.scroll-after .scroll-marker.after{display:block} body.mainmenu-open .mainmenu-collapsed ul{position:absolute;left:0;top:10px;bottom:10px} +html.mobile .mainmenu-collapsed ul{overflow:auto;-webkit-overflow-scrolling:touch} nav#layout-mainmenu.navbar ul li:hover a:active,.mainmenu-collapsed li:hover a:active,nav#layout-mainmenu.navbar ul li:hover a:focus,.mainmenu-collapsed li:hover a:focus{color:#ffffff !important} .touch .mainmenu-collapsed li a:hover{color:rgba(255,255,255,0.6)} nav#layout-mainmenu.navbar ul li.highlight > a,.mainmenu-collapsed li.highlight > a{color:#ffffff !important} @@ -777,6 +790,7 @@ body.drag nav#layout-mainmenu.navbar ul.nav li:hover,body.drag .mainmenu-collaps #layout-sidenav ul li.active a i,#layout-sidenav ul li a:hover i{color:#ffffff} #layout-sidenav ul li span.counter{display:block;position:absolute;top:15px;right:15px;padding:2px 6px 3px 4px;background-color:#d9350f;color:#ffffff;font-size:11px;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} #layout-sidenav ul li span.counter.empty{opacity:0;filter:alpha(opacity=0);-webkit-transform:scale(0,);-ms-transform:scale(0,);transform:scale(0,)} +html.mobile #layout-sidenav ul{overflow:auto;-webkit-overflow-scrolling:touch} #layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover,.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover{color:rgba(255,255,255,0.6) !important} #layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover i,.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover i{color:rgba(255,255,255,0.6) !important} #layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover:after,.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover:after{display:none !important} diff --git a/modules/backend/assets/js/october-min.js b/modules/backend/assets/js/october-min.js index a353edc5a..3d8b366c4 100644 --- a/modules/backend/assets/js/october-min.js +++ b/modules/backend/assets/js/october-min.js @@ -670,7 +670,7 @@ return false}) this.wrapper.click(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){closeMenu() return false}}) $(window).resize(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){if($(window).width()>self.breakpoint){hideMenu()}}}) -this.menuElement.dragScroll({vertical:true,start:function(){self.menuElement.addClass('drag')},stop:function(){self.menuElement.removeClass('drag')},scrollClassContainer:self.menuPanel,scrollMarkerContainer:self.menuContainer}) +this.menuElement.dragScroll({vertical:true,useNative:true,start:function(){self.menuElement.addClass('drag')},stop:function(){self.menuElement.removeClass('drag')},scrollClassContainer:self.menuPanel,scrollMarkerContainer:self.menuContainer}) this.menuElement.on('click',function(){if(self.menuElement.hasClass('drag')) return false}) function hideMenu(){self.body.removeClass(self.options.bodyMenuOpenClass) @@ -691,9 +691,9 @@ if(typeof option=='string')data[option].call($this)})} $.fn.verticalMenu.Constructor=VerticalMenu $.fn.verticalMenu.noConflict=function(){$.fn.verticalMenu=old return this}}(window.jQuery);(function($){$(window).load(function(){$('nav.navbar').each(function(){var -navbar=$(this),nav=$('ul.nav',navbar),collapseMode=navbar.hasClass('navbar-mode-collapse') +navbar=$(this),nav=$('ul.nav',navbar),collapseMode=navbar.hasClass('navbar-mode-collapse'),isMobile=$('html').hasClass('mobile') nav.verticalMenu($('a.menu-toggle',navbar),{breakpoint:collapseMode?Infinity:769}) -$('li.with-tooltip:not(.active) > a',navbar).tooltip({container:'body',placement:'bottom',template:''}) +$('li.with-tooltip:not(.active) > a',navbar).tooltip({container:'body',placement:'bottom',template:''}).on('show.bs.tooltip',function(e){if(isMobile)e.preventDefault()}) $('[data-calculate-width]',navbar).one('oc.widthFixed',function(){var dragScroll=$('[data-control=toolbar]',navbar).data('oc.dragScroll') if(dragScroll){dragScroll.goToElement($('ul.nav > li.active',navbar),undefined,{'duration':0})}})})})})(jQuery);+function($){"use strict";if($.oc===undefined) $.oc={} @@ -703,9 +703,9 @@ this.$list=$('ul',this.$el) this.$items=$('li',this.$list) this.init();} SideNav.DEFAULTS={activeClass:'active'} -SideNav.prototype.init=function(){var self=this;this.$list.dragScroll({vertical:true,start:function(){self.$list.addClass('drag')},stop:function(){self.$list.removeClass('drag')},scrollClassContainer:self.$el,scrollMarkerContainer:self.$el}) -this.$list.on('click',function(){if(self.$list.hasClass('drag')) -return false})} +SideNav.prototype.init=function(){var self=this +this.$list.dragScroll({vertical:true,useNative:true,start:function(){self.$list.addClass('drag')},stop:function(){self.$list.removeClass('drag')},scrollClassContainer:self.$el,scrollMarkerContainer:self.$el}) +this.$list.on('click',function(){if(self.$list.hasClass('drag')){return false}})} SideNav.prototype.unsetActiveItem=function(itemId){this.$items.removeClass(this.options.activeClass)} SideNav.prototype.setActiveItem=function(itemId){if(!itemId){return} this.$items.removeClass(this.options.activeClass).filter('[data-menu-item='+itemId+']').addClass(this.options.activeClass)} @@ -740,9 +740,10 @@ $.fn.sideNav.noConflict=function(){$.fn.sideNav=old return this} $(document).ready(function(){$('[data-control="sidenav"]').sideNav()})}(window.jQuery);+function($){"use strict";var Base=$.oc.foundation.base,BaseProto=Base.prototype var Scrollbar=function(element,options){var -$el=this.$el=$(element),el=$el.get(0),self=this,options=this.options=options||{},sizeName=this.sizeName=options.vertical?'height':'width',isTouch=this.isTouch=Modernizr.touch,isScrollable=this.isScrollable=false,isLocked=this.isLocked=false,eventElementName=options.vertical?'pageY':'pageX',dragStart=0,startOffset=0;$.oc.foundation.controlUtils.markDisposable(element) +$el=this.$el=$(element),el=$el.get(0),self=this,options=this.options=options||{},sizeName=this.sizeName=options.vertical?'height':'width',isNative=$('html').hasClass('mobile'),isTouch=this.isTouch=Modernizr.touch,isScrollable=this.isScrollable=false,isLocked=this.isLocked=false,eventElementName=options.vertical?'pageY':'pageX',dragStart=0,startOffset=0;$.oc.foundation.controlUtils.markDisposable(element) Base.call(this) this.$el.one('dispose-control',this.proxy(this.dispose)) +if(isNative){return} this.$scrollbar=$('
').addClass('scrollbar-scrollbar') this.$track=$('
').addClass('scrollbar-track').appendTo(this.$scrollbar) this.$thumb=$('
').addClass('scrollbar-thumb').appendTo(this.$track) @@ -1074,7 +1075,7 @@ $.fn.treeListWidget.noConflict=function(){$.fn.treeListWidget=old return this} $(document).render(function(){$('[data-control="treelist"]').treeListWidget();})}(window.jQuery);+function($){"use strict";var SidenavTree=function(element,options){this.options=options this.$el=$(element) -this.init();} +this.init()} SidenavTree.DEFAULTS={treeName:'sidenav_tree'} SidenavTree.prototype.init=function(){var self=this $(document.body).addClass('has-sidenav-tree') @@ -1082,17 +1083,18 @@ this.statusCookieName=this.options.treeName+'groupStatus' this.searchCookieName=this.options.treeName+'search' this.$searchInput=$(this.options.searchInput) this.$el.on('click','li > div.group',function(){self.toggleGroup($(this).closest('li')) -return false;});this.$searchInput.on('keyup',function(){self.handleSearchChange()}) +return false}) +this.$searchInput.on('keyup',function(){self.handleSearchChange()}) var searchTerm=$.cookie(this.searchCookieName) if(searchTerm!==undefined&&searchTerm.length>0){this.$searchInput.val(searchTerm) this.applySearch()} var scrollbar=$('[data-control=scrollbar]',this.$el).data('oc.scrollbar'),active=$('li.active',this.$el) -if(active.length>0) -scrollbar.gotoElement(active)} +if(active.length>0){scrollbar.gotoElement(active)}} SidenavTree.prototype.toggleGroup=function(group){var $group=$(group),status=$group.attr('data-status') status===undefined||status=='expanded'?this.collapseGroup($group):this.expandGroup($group)} SidenavTree.prototype.collapseGroup=function(group){var -$list=$('> ul',group),self=this;$list.css('overflow','hidden') +$list=$('> ul',group),self=this +$list.css('overflow','hidden') $list.animate({'height':0},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','display':'none'}) $(group).attr('data-status','collapsed') $(window).trigger('oc.updateUi') @@ -1100,32 +1102,30 @@ self.saveGroupStatus($(group).data('group-code'),true)}})} SidenavTree.prototype.expandGroup=function(group,duration){var $list=$('> ul',group),self=this duration=duration===undefined?100:duration -$list.css({'overflow':'hidden','display':'block','height':0}) +$list.css({'overflow':'hidden','display':'','height':0}) $list.animate({'height':$list[0].scrollHeight},{duration:duration,queue:false,complete:function(){$list.css({'overflow':'visible','height':'auto'}) $(group).attr('data-status','expanded') $(window).trigger('oc.updateUi') self.saveGroupStatus($(group).data('group-code'),false)}})} SidenavTree.prototype.saveGroupStatus=function(groupCode,collapsed){var collapsedGroups=$.cookie(this.statusCookieName),updatedGroups=[] -if(collapsedGroups===undefined) -collapsedGroups='' +if(collapsedGroups===undefined){collapsedGroups=''} collapsedGroups=collapsedGroups.split('|') $.each(collapsedGroups,function(){if(groupCode!=this) updatedGroups.push(this)}) -if(collapsed) -updatedGroups.push(groupCode) +if(collapsed){updatedGroups.push(groupCode)} $.cookie(this.statusCookieName,updatedGroups.join('|'),{expires:30,path:'/'})} -SidenavTree.prototype.handleSearchChange=function(){var lastValue=this.$searchInput.data('oc.lastvalue');if(lastValue!==undefined&&lastValue==this.$searchInput.val()) -return +SidenavTree.prototype.handleSearchChange=function(){var lastValue=this.$searchInput.data('oc.lastvalue');if(lastValue!==undefined&&lastValue==this.$searchInput.val()){return} this.$searchInput.data('oc.lastvalue',this.$searchInput.val()) -if(this.dataTrackInputTimer!==undefined) -window.clearTimeout(this.dataTrackInputTimer);var self=this +if(this.dataTrackInputTimer!==undefined){window.clearTimeout(this.dataTrackInputTimer)} +var self=this this.dataTrackInputTimer=window.setTimeout(function(){self.applySearch()},300);$.cookie(this.searchCookieName,$.trim(this.$searchInput.val()),{expires:30,path:'/'})} SidenavTree.prototype.applySearch=function(){var query=$.trim(this.$searchInput.val()),words=query.toLowerCase().split(' '),visibleGroups=[],visibleItems=[],self=this if(query.length==0){$('li',this.$el).removeClass('hidden') return} $('ul.top-level > li',this.$el).each(function(){var $li=$(this) if(self.textContainsWords($('div.group h3',$li).text(),words)){visibleGroups.push($li.get(0)) -$('ul li',$li).each(function(){visibleItems.push(this)})}else{$('ul li',$li).each(function(){if(self.textContainsWords($(this).text(),words)||self.textContainsWords($(this).data('keywords'),words)){visibleGroups.push($li.get(0)) +$('ul li',$li).each(function(){visibleItems.push(this)})} +else{$('ul li',$li).each(function(){if(self.textContainsWords($(this).text(),words)||self.textContainsWords($(this).data('keywords'),words)){visibleGroups.push($li.get(0)) visibleItems.push(this)}})}}) $('ul.top-level > li',this.$el).each(function(){var $li=$(this),groupIsVisible=$.inArray(this,visibleGroups)!==-1 $li.toggleClass('hidden',!groupIsVisible) diff --git a/modules/backend/assets/js/october.navbar.js b/modules/backend/assets/js/october.navbar.js index bd8ce116b..4519e4797 100644 --- a/modules/backend/assets/js/october.navbar.js +++ b/modules/backend/assets/js/october.navbar.js @@ -15,7 +15,8 @@ var navbar = $(this), nav = $('ul.nav', navbar), - collapseMode = navbar.hasClass('navbar-mode-collapse') + collapseMode = navbar.hasClass('navbar-mode-collapse'), + isMobile = $('html').hasClass('mobile') nav.verticalMenu($('a.menu-toggle', navbar), { breakpoint: collapseMode ? Infinity : 769 @@ -26,6 +27,9 @@ placement: 'bottom', template: '' }) + .on('show.bs.tooltip', function (e) { + if (isMobile) e.preventDefault() + }) $('[data-calculate-width]', navbar).one('oc.widthFixed', function() { var dragScroll = $('[data-control=toolbar]', navbar).data('oc.dragScroll') diff --git a/modules/backend/assets/js/october.scrollbar.js b/modules/backend/assets/js/october.scrollbar.js index f796cadc4..26feadaed 100644 --- a/modules/backend/assets/js/october.scrollbar.js +++ b/modules/backend/assets/js/october.scrollbar.js @@ -25,6 +25,7 @@ self = this, options = this.options = options || {}, sizeName = this.sizeName = options.vertical ? 'height' : 'width', + isNative = $('html').hasClass('mobile'), isTouch = this.isTouch = Modernizr.touch, isScrollable = this.isScrollable = false, isLocked = this.isLocked = false, @@ -38,6 +39,13 @@ this.$el.one('dispose-control', this.proxy(this.dispose)) + /* + * Native (mobile) environments use overflow auto in CSS + */ + if (isNative) { + return + } + /* * Create Scrollbar */ @@ -53,7 +61,6 @@ /* * Bind events */ - if (isTouch) { this.$el.on('touchstart', function (event){ var touchEvent = event.originalEvent; @@ -116,7 +123,7 @@ moveDrag(event) return false }) - + $(window).on('mouseup.scrollbar', function(){ stopDrag() return false diff --git a/modules/backend/assets/js/october.sidenav-tree.js b/modules/backend/assets/js/october.sidenav-tree.js index d0351e037..a4978ba9a 100644 --- a/modules/backend/assets/js/october.sidenav-tree.js +++ b/modules/backend/assets/js/october.sidenav-tree.js @@ -21,7 +21,7 @@ this.options = options this.$el = $(element) - this.init(); + this.init() } SidenavTree.DEFAULTS = { @@ -32,16 +32,15 @@ var self = this $(document.body).addClass('has-sidenav-tree') - + this.statusCookieName = this.options.treeName + 'groupStatus' this.searchCookieName = this.options.treeName + 'search' this.$searchInput = $(this.options.searchInput) this.$el.on('click', 'li > div.group', function() { self.toggleGroup($(this).closest('li')) - - return false; - }); + return false + }) this.$searchInput.on('keyup', function(){ self.handleSearchChange() @@ -56,38 +55,44 @@ var scrollbar = $('[data-control=scrollbar]', this.$el).data('oc.scrollbar'), active = $('li.active', this.$el) - if (active.length > 0) + if (active.length > 0) { scrollbar.gotoElement(active) + } } SidenavTree.prototype.toggleGroup = function(group) { var $group = $(group), status = $group.attr('data-status') - status === undefined || status == 'expanded' ? - this.collapseGroup($group) : - this.expandGroup($group) + status === undefined || status == 'expanded' + ? this.collapseGroup($group) + : this.expandGroup($group) } SidenavTree.prototype.collapseGroup = function(group) { - var + var $list = $('> ul', group), - self = this; + self = this $list.css('overflow', 'hidden') - $list.animate({'height': 0}, { duration: 100, queue: false, complete: function() { - $list.css({ - 'overflow': 'visible', - 'display': 'none' - }) - $(group).attr('data-status', 'collapsed') - $(window).trigger('oc.updateUi') - self.saveGroupStatus($(group).data('group-code'), true) - } }) + $list.animate({ 'height': 0 }, { + duration: 100, + queue: false, + complete: function() { + $list.css({ + 'overflow': 'visible', + 'display': 'none' + }) + + $(group).attr('data-status', 'collapsed') + $(window).trigger('oc.updateUi') + self.saveGroupStatus($(group).data('group-code'), true) + } + }) } SidenavTree.prototype.expandGroup = function(group, duration) { - var + var $list = $('> ul', group), self = this @@ -95,7 +100,7 @@ $list.css({ 'overflow': 'hidden', - 'display': 'block', + 'display': '', 'height': 0 }) $list.animate({'height': $list[0].scrollHeight}, { duration: duration, queue: false, complete: function() { @@ -113,8 +118,9 @@ var collapsedGroups = $.cookie(this.statusCookieName), updatedGroups = [] - if (collapsedGroups === undefined) + if (collapsedGroups === undefined) { collapsedGroups = '' + } collapsedGroups = collapsedGroups.split('|') $.each(collapsedGroups, function() { @@ -122,8 +128,9 @@ updatedGroups.push(this) }) - if (collapsed) + if (collapsed) { updatedGroups.push(groupCode) + } $.cookie(this.statusCookieName, updatedGroups.join('|'), { expires: 30, path: '/' }) } @@ -131,13 +138,15 @@ SidenavTree.prototype.handleSearchChange = function() { var lastValue = this.$searchInput.data('oc.lastvalue'); - if (lastValue !== undefined && lastValue == this.$searchInput.val()) + if (lastValue !== undefined && lastValue == this.$searchInput.val()) { return + } this.$searchInput.data('oc.lastvalue', this.$searchInput.val()) - if (this.dataTrackInputTimer !== undefined) - window.clearTimeout(this.dataTrackInputTimer); + if (this.dataTrackInputTimer !== undefined) { + window.clearTimeout(this.dataTrackInputTimer) + } var self = this this.dataTrackInputTimer = window.setTimeout(function(){ @@ -160,8 +169,9 @@ return } - // Find visible groups and items - // + /* + * Find visible groups and items + */ $('ul.top-level > li', this.$el).each(function() { var $li = $(this) @@ -171,7 +181,8 @@ $('ul li', $li).each(function(){ visibleItems.push(this) }) - } else { + } + else { $('ul li', $li).each(function(){ if (self.textContainsWords($(this).text(), words) || self.textContainsWords($(this).data('keywords'), words)) { visibleGroups.push($li.get(0)) @@ -181,8 +192,9 @@ } }) - // Hide invisible groups and items - // + /* + * Hide invisible groups and items + */ $('ul.top-level > li', this.$el).each(function() { var $li = $(this), groupIsVisible = $.inArray(this, visibleGroups) !== -1 @@ -253,4 +265,4 @@ $('[data-control=sidenav-tree]').sidenavTree() }) -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff --git a/modules/backend/assets/js/october.sidenav.js b/modules/backend/assets/js/october.sidenav.js index c33bc11a4..292caab93 100644 --- a/modules/backend/assets/js/october.sidenav.js +++ b/modules/backend/assets/js/october.sidenav.js @@ -35,20 +35,22 @@ } SideNav.prototype.init = function (){ - var self = this; + var self = this this.$list.dragScroll({ vertical: true, - start: function(){ self.$list.addClass('drag') }, - stop: function(){ self.$list.removeClass('drag') }, + useNative: true, + start: function() { self.$list.addClass('drag') }, + stop: function() { self.$list.removeClass('drag') }, scrollClassContainer: self.$el, scrollMarkerContainer: self.$el }) this.$list.on('click', function() { /* Do not handle menu item clicks while dragging */ - if (self.$list.hasClass('drag')) + if (self.$list.hasClass('drag')) { return false + } }) } diff --git a/modules/backend/assets/js/october.verticalmenu.js b/modules/backend/assets/js/october.verticalmenu.js index f5a6d7ca7..79ecc2892 100644 --- a/modules/backend/assets/js/october.verticalmenu.js +++ b/modules/backend/assets/js/october.verticalmenu.js @@ -83,6 +83,7 @@ */ this.menuElement.dragScroll({ vertical: true, + useNative: true, start: function(){self.menuElement.addClass('drag')}, stop: function(){self.menuElement.removeClass('drag')}, scrollClassContainer: self.menuPanel, @@ -155,4 +156,4 @@ return this } -}(window.jQuery); \ No newline at end of file +}(window.jQuery); diff --git a/modules/backend/assets/less/controls/scrollbar.less b/modules/backend/assets/less/controls/scrollbar.less index 1f0acd840..92f6bd444 100644 --- a/modules/backend/assets/less/controls/scrollbar.less +++ b/modules/backend/assets/less/controls/scrollbar.less @@ -6,6 +6,8 @@ .user-select(none); } +@scrollbar-thumb-size: 6px; + .control-scrollbar { position: relative; overflow: hidden; @@ -32,32 +34,34 @@ position: absolute; } } + &.disabled { - display: none!important; + display: none !important; } } &.vertical { >.scrollbar-scrollbar { right: 0; - width: 4px; + margin-right: 5px; + width: @scrollbar-thumb-size; .scrollbar-track { height: 100%; - width: 4px; + width: @scrollbar-thumb-size; .scrollbar-thumb { height: 20px; - width: 4px; + width: @scrollbar-thumb-size; top: 0; left: 0; } } &:active, &:hover { - width: 6px; + width: @scrollbar-thumb-size + 2px; .transition(width .3s); .scrollbar-track, .scrollbar-thumb { - width: 6px; + width: @scrollbar-thumb-size + 2px; .transition(width .3s); } } @@ -68,24 +72,24 @@ >.scrollbar-scrollbar { margin: 0 0 5px; clear: both; - height: 4px; + height: @scrollbar-thumb-size; .scrollbar-track { width: 100%; - height: 4px; + height: @scrollbar-thumb-size; .scrollbar-thumb { - height: 4px; - margin:2px 0; + height: @scrollbar-thumb-size; + margin: 2px 0; left: 0; top: 0; } } - + &:active, &:hover { - height: 6px; + height: @scrollbar-thumb-size + 2px; .transition(height .3s); .scrollbar-track, .scrollbar-thumb { - height: 6px; + height: @scrollbar-thumb-size + 2px; .transition(height .3s); } } @@ -93,6 +97,13 @@ } } +html.mobile { + .control-scrollbar { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + .no-touch .control-scrollbar { >.scrollbar-scrollbar { opacity: 0; diff --git a/modules/backend/assets/less/controls/sidenav-tree.less b/modules/backend/assets/less/controls/sidenav-tree.less index 35f96a155..334eecb9e 100644 --- a/modules/backend/assets/less/controls/sidenav-tree.less +++ b/modules/backend/assets/less/controls/sidenav-tree.less @@ -103,10 +103,12 @@ background: @color-sidebarnav-tree-inactive-bg; border-bottom: 1px solid @color-sidebarnav-tree-group-bg; color: @color-sidebarnav-tree-inactive-text; - text-decoration: none!important; + text-decoration: none !important; .opacity(.65); + &:active, &:hover { + .opacity(1); text-decoration: none; } @@ -156,10 +158,9 @@ } } - - &:last-child a { - border-bottom: none; - } + // &:last-child a { + // border-bottom: none; + // } } } } @@ -169,6 +170,48 @@ } } +@media (min-width: @screen-sm-min) { + .sidenav-tree-root .sidenav-tree { + width: 600px; + + ul.top-level > li > ul { + font-size: 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + align-items: stretch; + align-content: stretch; + + > li { + display: inline-block; + // flex-grow: 1; + width: 300px; + + a { + height: 100%; + } + } + } + } +} + +@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { + .sidenav-tree-root .sidenav-tree { + width: 100%; + + ul.top-level > li > ul > li { + width: 50%; + } + } +} + +@media (min-width: @screen-lg-min) { + .sidenav-tree-root .sidenav-tree { + width: 900px; + } +} + @media (max-width: @screen-sm) { .sidenav-tree { width: 100%; diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less index b4e25fc9a..e2141ecab 100644 --- a/modules/backend/assets/less/core/variables.less +++ b/modules/backend/assets/less/core/variables.less @@ -51,7 +51,7 @@ @color-sidebarnav-back-link-text: #bdc3c7; @color-scrollbar-track: transparent; -@color-scrollbar-thumb: #aaa; +@color-scrollbar-thumb: rgba(0,0,0,.35); @color-scrollpanel-border: #efefef; @color-scrollpanel-fix-button: #aaaaaa; @color-scrollpanel-fix-button-light: #eeeeee; diff --git a/modules/backend/assets/less/layout/layout.less b/modules/backend/assets/less/layout/layout.less index fea57dac7..4d5ad5fff 100644 --- a/modules/backend/assets/less/layout/layout.less +++ b/modules/backend/assets/less/layout/layout.less @@ -2,7 +2,7 @@ // Common layout elements // -------------------------------------------------- -body.drag * { +html:not(.mobile) body.drag * { cursor: drag !important; cursor: -webkit-grab !important; cursor: -moz-grab !important; @@ -19,7 +19,7 @@ body.loading, body.loading * { body.no-select { .user-select(none); - cursor: default!important; + cursor: default !important; } // diff --git a/modules/backend/assets/less/layout/mainmenu.less b/modules/backend/assets/less/layout/mainmenu.less index 2163c2b90..1370e3b39 100644 --- a/modules/backend/assets/less/layout/mainmenu.less +++ b/modules/backend/assets/less/layout/mainmenu.less @@ -13,6 +13,7 @@ body.mainmenu-open { overflow: hidden; + position: fixed; } .mainmenu-item-link() { @@ -460,17 +461,32 @@ nav#layout-mainmenu { line-height: @mainmenu-mode-collapse-height; width: @mainmenu-mode-collapse-height; text-align: center; + opacity: .7; i { - line-height: 1; - font-size: 30px; - vertical-align: middle; + line-height: @mainmenu-mode-collapse-height; + font-size: 20px; + vertical-align: bottom; } } .menu-toggle-title { margin-left: 10px; } + + &:hover { + .menu-toggle-icon { + opacity: 1; + } + } + } +} + +body.mainmenu-open { + nav#layout-mainmenu { + .menu-toggle-icon { + opacity: 1; + } } } @@ -484,15 +500,6 @@ nav#layout-mainmenu.navbar-mode-collapse { } } -// This logic is implemented in the october.navbar.js script, -// it prevents the collapse mode from working beyond the min -// breakpoint. Leaving this code just in case, remove later. -// -SG -@media (min-width: @menu-breakpoint-min) { - // #layout-canvas { position: static !important; } - // .mainmenu-collapsed { display: none !important; } -} - .mainmenu-navbar-collapse() { padding-left: 0; @@ -569,6 +576,13 @@ body.mainmenu-open .mainmenu-collapsed ul { bottom: 10px; } +html.mobile { + .mainmenu-collapsed ul { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + // // Misc // diff --git a/modules/backend/assets/less/layout/sidenav.less b/modules/backend/assets/less/layout/sidenav.less index a239ecfe1..b50c7b89d 100644 --- a/modules/backend/assets/less/layout/sidenav.less +++ b/modules/backend/assets/less/layout/sidenav.less @@ -78,6 +78,13 @@ } } +html.mobile { + #layout-sidenav ul { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + #layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover, .touch #layout-sidenav.layout-sidenav li:not(.active) a:hover { color: @color-sidebarnav-inactive-text !important; diff --git a/modules/backend/layouts/_browser_detector.htm b/modules/backend/layouts/_browser_detector.htm index c6695aa5e..c59afdc0e 100644 --- a/modules/backend/layouts/_browser_detector.htm +++ b/modules/backend/layouts/_browser_detector.htm @@ -10,11 +10,12 @@ $ua = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : null; if (!$ua) - return; + return; $g = 'gecko'; $w = 'webkit'; $s = 'safari'; +$m = 'mobile'; $b = array(); // browser @@ -42,13 +43,19 @@ if(!preg_match('/opera|webtv/i', $ua) && preg_match('/msie\s(\d)/', $ua, $array) $b[] = $g; } -// platform +// platform if(strstr($ua, 'j2me')) { - $b[] = 'mobile'; + $b[] = $m . ' j2me'; } else if(strstr($ua, 'iphone')) { - $b[] = 'iphone'; + $b[] = $m . ' iphone'; } else if(strstr($ua, 'ipod')) { - $b[] = 'ipod'; + $b[] = $m . ' ipod'; +} else if(strstr($ua, 'ipad')) { + $b[] = $m . ' ipad'; +} else if(strstr($ua, 'android')) { + $b[] = $m . ' android'; +} else if(strstr($ua, 'blackberry')) { + $b[] = $m . ' blackberry'; } else if(strstr($ua, 'mac')) { $b[] = 'mac'; } else if(strstr($ua, 'darwin')) { @@ -63,4 +70,4 @@ if(strstr($ua, 'j2me')) { $b[] = 'linux'; } -echo join(' ', $b); \ No newline at end of file +echo join(' ', $b); diff --git a/modules/backend/layouts/_mainmenu.htm b/modules/backend/layouts/_mainmenu.htm index 193bf4587..57889b86f 100644 --- a/modules/backend/layouts/_mainmenu.htm +++ b/modules/backend/layouts/_mainmenu.htm @@ -5,7 +5,7 @@ ?>