diff options
author | Vjacheslav Trushkin <cyberalien@gmail.com> | 2013-10-23 22:53:10 +0300 |
---|---|---|
committer | Vjacheslav Trushkin <cyberalien@gmail.com> | 2013-10-24 18:36:17 +0300 |
commit | 016958ea5e64d291b73beb16db10fdd7e2e7a089 (patch) | |
tree | 76512e1eae421bd3afc8d76504e60611975525ad | |
parent | 6f97367ef065b871fdfbdddbd7919af886897a9f (diff) | |
download | forums-016958ea5e64d291b73beb16db10fdd7e2e7a089.tar forums-016958ea5e64d291b73beb16db10fdd7e2e7a089.tar.gz forums-016958ea5e64d291b73beb16db10fdd7e2e7a089.tar.bz2 forums-016958ea5e64d291b73beb16db10fdd7e2e7a089.tar.xz forums-016958ea5e64d291b73beb16db10fdd7e2e7a089.zip |
[ticket/11956] Reusable dropdown handler
Replace dropdown menu code with reusable handler that
is shared between all types of dropdown menus and can
be used by custom menus by extensions.
PHPBB3-11956
-rw-r--r-- | phpBB/styles/prosilver/template/forum_fn.js | 136 | ||||
-rw-r--r-- | phpBB/styles/prosilver/template/overall_header.html | 66 | ||||
-rw-r--r-- | phpBB/styles/prosilver/theme/colours.css | 38 | ||||
-rw-r--r-- | phpBB/styles/prosilver/theme/common.css | 137 | ||||
-rw-r--r-- | phpBB/styles/prosilver/theme/cp.css | 36 |
5 files changed, 249 insertions, 164 deletions
diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index b46a2baaf5..1169c9f2dc 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -410,6 +410,83 @@ function insert_single_user(formId, user) } /** +* Dropdown handler +* Shows/hides dropdown, decides which side to open to +* +* @param [jQuery] toggle Link that toggles dropdown +* @param [jQuery] dropdown Dropdown menu +* @param [Object] [options] List of options +*/ +function toggle_dropdown() +{ + var $this = $(this), + options = $this.data('dropdown-options'), + parent = options.parent, + visible = parent.hasClass('dropdown-visible'); + + if (!visible) { + // Hide other dropdown menus + $('.dropdown-container.dropdown-visible .dropdown-toggle').each(toggle_dropdown); + + // Figure out direction of dropdown + var direction = options.direction, + verticalDirection = options.verticalDirection, + offset = $this.offset(); + + if (direction == 'auto') { + if (($(window).width() - $this.outerWidth(true)) / 2 > offset.left) { + direction = 'right'; + } + else { + direction = 'left'; + } + } + parent.toggleClass(options.leftClass, direction == 'left').toggleClass(options.rightClass, direction == 'right'); + + if (verticalDirection == 'auto') { + var height = $(window).height(), + top = offset.top - $(window).scrollTop(); + + if (top < height * 0.7) { + verticalDirection = 'down'; + } + else { + verticalDirection = 'up'; + } + } + parent.toggleClass(options.upClass, verticalDirection == 'up').toggleClass(options.downClass, verticalDirection == 'down'); + } + + options.dropdown.toggle(); + parent.toggleClass(options.visibleClass, !visible).toggleClass('dropdown-visible', !visible); +} + +function register_dropdown(toggle, dropdown, options) +{ + var ops = { + parent: toggle.parent(), // Parent item to add classes to + direction: 'auto', // Direction of dropdown menu. Possible values: auto, left, right + verticalDirection: 'auto', // Vertical direction. Possible values: auto, up, down + visibleClass: 'visible', // Class to add to parent item when dropdown is visible + leftClass: 'dropdown-left', // Class to add to parent item when dropdown opens to left side + rightClass: 'dropdown-right', // Class to add to parent item when dropdown opens to right side + upClass: 'dropdown-up', // Class to add to parent item when dropdown opens above menu item + downClass: 'dropdown-down' // Class to add to parent item when dropdown opens below menu item + }; + if (options) { + ops = $.extend(ops, options); + } + ops.dropdown = dropdown; + + ops.parent.addClass('dropdown-container'); + toggle.addClass('dropdown-toggle'); + + toggle.data('dropdown-options', ops); + + toggle.click(toggle_dropdown); +} + +/** * Parse document block */ function parse_document(container) @@ -730,7 +807,7 @@ function parse_document(container) filterLast = '.pagination, .icon-notifications, .icon-pm, .icon-logout, .icon-login, .mark-read, .edit-icon, .quote-icon', allLinks = $this.children(), links = allLinks.not(filterSkip), - html = '<li class="responsive-menu" style="display:none;"><a href="javascript:void(0);" class="responsive-menu-link"> </a><div class="popup-pointer" style="display: none;"><div class="popup-pointer-inner" /></div><ul class="responsive-popup" style="display:none;" /></li>', + html = '<li class="responsive-menu" style="display:none;"><a href="javascript:void(0);" class="responsive-menu-link"> </a><div class="dropdown" style="display:none;"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>', filterLastList = links.filter(filterLast); if (links.is('.rightside')) @@ -742,10 +819,8 @@ function parse_document(container) $this.append(html); } - var toggle = $this.children('.responsive-menu'), - toggleLink = toggle.find('a.responsive-menu-link'), - menu = toggle.find('ul.responsive-popup'), - toggleItems = toggle.find('ul.responsive-popup, div.popup-pointer'), + var item = $this.children('.responsive-menu'), + menu = item.find('.dropdown-contents'), lastWidth = false, compact = false, responsive = false, @@ -762,7 +837,7 @@ function parse_document(container) responsive = false; $this.removeClass('responsive'); links.css('display', ''); - toggle.css('display', 'none'); + item.css('display', 'none'); } if (compact) { @@ -774,7 +849,6 @@ function parse_document(container) var maxHeight = 0; allLinks.each(function() { if (!$(this).height()) return; - $(this).attr('data-height', $(this).outerHeight(true)); maxHeight = Math.max(maxHeight, $(this).outerHeight(true)); }); @@ -784,8 +858,6 @@ function parse_document(container) // Nothing to resize if block's height is not bigger than tallest element's height if ($this.height() <= maxHeight) { - toggle.removeClass('visible'); - toggleItems.hide(); return; } @@ -800,8 +872,6 @@ function parse_document(container) }); if ($this.height() <= maxHeight) { - toggle.removeClass('visible'); - toggleItems.hide(); return; } @@ -811,9 +881,6 @@ function parse_document(container) responsive = true; if (!copied) { - if (menu.parents().is('.rightside')) { - toggle.addClass('responsive-rightside'); - } menu.append(links.clone(true)); menu.find('li.leftside, li.rightside').removeClass('leftside rightside'); menu.find('.inputbox').parents('li:first').css('white-space', 'normal'); @@ -823,7 +890,7 @@ function parse_document(container) menu.children().css('display', ''); } - toggle.css('display', ''); + item.css('display', ''); $this.addClass('responsive'); // Try to not hide filtered items @@ -845,15 +912,7 @@ function parse_document(container) links.css('display', 'none'); } - toggleLink.click(function() { - if (!responsive) return; - if (!toggle.hasClass('visible')) { - // Hide other popups - $('.responsive-menu.visible').removeClass('visible').find('.responsive-popup, .popup-pointer').hide(); - } - toggle.toggleClass('visible'); - toggleItems.toggle(); - }); + register_dropdown(item.find('a.responsive-menu-link'), item.find('.dropdown')); check(); $(window).resize(check); @@ -868,9 +927,8 @@ function parse_document(container) ul = $this.children(), tabs = ul.children().not('[data-skip-responsive]'), links = tabs.children('a'), - toggle = ul.append('<li class="responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link"><span> </span></a><ul class="responsive-tabs" style="display:none;" /></li>').find('li.responsive-tab'), - toggleLink = toggle.find('a.responsive-tab-link'), - menu = toggle.find('ul.responsive-tabs'), + item = ul.append('<li class="responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link"><span> </span></a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab'), + menu = item.find('.dropdown-contents'), maxHeight = 0, lastWidth = false, responsive = false; @@ -888,18 +946,21 @@ function parse_document(container) } tabs.show(); - toggle.hide(); + item.hide(); lastWidth = width; height = $this.height(); if (height <= maxHeight) { responsive = false; + if (item.hasClass('dropdown-visible')) { + toggle_dropdown.call(item.find('a.responsive-tab-link').get(0)); + } return; } responsive = true; - toggle.show(); - menu.hide().html(''); + item.show(); + menu.html(''); var availableTabs = tabs.filter(':not(.activetab, .responsive-tab)'), total = availableTabs.length, @@ -917,10 +978,7 @@ function parse_document(container) menu.find('a').click(function() { check(true); }); } - toggleLink.click(function() { - if (!responsive) return; - menu.toggle(); - }); + register_dropdown(item.find('a.responsive-tab-link'), item.find('.dropdown'), {visibleClass: 'activetab'}); check(true); $(window).resize(check); @@ -951,14 +1009,12 @@ function parse_document(container) $('#' + this.getAttribute('data-focus')).focus(); }); - // Hide responsive menu and tabs + // Hide active dropdowns when click event happens outside $('#phpbb').click(function(e) { + var parents = $(e.target).parents(); - if (!parents.is('.responsive-menu.visible')) { - $('.responsive-menu.visible').removeClass('visible').find('.responsive-popup, .popup-pointer').hide(); - } - if (!parents.is('.responsive-tab')) { - $('.responsive-tabs').hide(); + if (!parents.is('.dropdown-container.dropdown-visible')) { + $('.dropdown-container.dropdown-visible .dropdown-toggle').each(toggle_dropdown); } }); diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index abe79e3808..854f92e9ce 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -102,38 +102,40 @@ <!-- IF S_NOTIFICATIONS_DISPLAY --> <li class="icon-notification" data-skip-responsive="true"> <a href="{U_VIEW_ALL_NOTIFICATIONS}" id="notification_list_button"><span>{L_NOTIFICATIONS} [</span><strong>{NOTIFICATIONS_COUNT}</strong><span>]</span></a> - <div id="notification_list" class="notification_list"> - <div class="popup-pointer"><div class="popup-pointer-inner"></div></div> - <div class="header"> - {L_NOTIFICATIONS} - <span class="header_settings"><a href="{U_NOTIFICATION_SETTINGS}">{L_SETTINGS}</a></span> - </div> - - <ul> - <!-- IF not .notifications --> - <li> - {L_NO_NOTIFICATIONS} - </li> - <!-- ENDIF --> - <!-- BEGIN notifications --> - <li class="<!-- IF notifications.UNREAD --> bg2<!-- ENDIF -->"> - <!-- IF notifications.URL --><a href="<!-- IF notifications.UNREAD -->{notifications.U_MARK_READ}<!-- ELSE -->{notifications.URL}<!-- ENDIF -->"><!-- ENDIF --> - <!-- IF notifications.AVATAR -->{notifications.AVATAR}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF --> - <div class="notification_text"> - <p>{notifications.FORMATTED_TITLE}</p> - <p>» {notifications.TIME}</p> - - <!-- IF not notifications.URL and notifications.U_MARK_READ --> - <p><a href="{notifications.U_MARK_READ}">{L_MARK_READ}</a></p> - <!-- ENDIF --> - </div> - <!-- IF notifications.URL --></a><!-- ENDIF --> - </li> - <!-- END notifications --> - </ul> - - <div class="footer"> - <a href="{U_VIEW_ALL_NOTIFICATIONS}"><span>{L_SEE_ALL}</span></a> + <div id="notification_list" class="dropdown notification_list"> + <div class="pointer"><div class="pointer-inner"></div></div> + <div class="dropdown-contents"> + <div class="header"> + {L_NOTIFICATIONS} + <span class="header_settings"><a href="{U_NOTIFICATION_SETTINGS}">{L_SETTINGS}</a></span> + </div> + + <ul> + <!-- IF not .notifications --> + <li> + {L_NO_NOTIFICATIONS} + </li> + <!-- ENDIF --> + <!-- BEGIN notifications --> + <li class="<!-- IF notifications.UNREAD --> bg2<!-- ENDIF -->"> + <!-- IF notifications.URL --><a href="<!-- IF notifications.UNREAD -->{notifications.U_MARK_READ}<!-- ELSE -->{notifications.URL}<!-- ENDIF -->"><!-- ENDIF --> + <!-- IF notifications.AVATAR -->{notifications.AVATAR}<!-- ELSE --><img src="{T_THEME_PATH}/images/no_avatar.gif" alt="" /><!-- ENDIF --> + <div class="notification_text"> + <p>{notifications.FORMATTED_TITLE}</p> + <p>» {notifications.TIME}</p> + + <!-- IF not notifications.URL and notifications.U_MARK_READ --> + <p><a href="{notifications.U_MARK_READ}">{L_MARK_READ}</a></p> + <!-- ENDIF --> + </div> + <!-- IF notifications.URL --></a><!-- ENDIF --> + </li> + <!-- END notifications --> + </ul> + + <div class="footer"> + <a href="{U_VIEW_ALL_NOTIFICATIONS}"><span>{L_SEE_ALL}</span></a> + </div> </div> </div> </li> diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index c16452a148..19021ca387 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -1104,11 +1104,6 @@ input.disabled { background-color: #000000; } -#notification_list { - background-color: #FFFFFF; - border-color: #B9B9B9; -} - #notification_list ul li { border-bottom-color: #B9B9B9; } @@ -1118,12 +1113,12 @@ input.disabled { color: #000000; } -#notification_list > .header, .notification_list > .footer { +#notification_list .header, .notification_list .footer { border-color: #B9B9B9; color: #000000; } -#notification_list > .header { +#notification_list .header { background: #F1F8FF; background: -moz-linear-gradient(top, #F1F8FF 0%, #CADCEB 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F1F8FF), color-stop(100%, #CADCEB)); @@ -1133,12 +1128,16 @@ input.disabled { background: linear-gradient(to bottom, #F1F8FF 0%, #CADCEB 100%); } -.popup-pointer { - border-bottom-color: #B9B9B9; +.dropdown .pointer { + border-color: #B9B9B9 transparent; +} + +.dropdown .pointer-inner { + border-color: #FFF transparent; } -.popup-pointer-inner { - border-bottom-color: #F1F8FF; +#notification_list .pointer-inner { + border-color: #F1F8FF transparent; } ul.linklist li.responsive-menu a.responsive-menu-link:before { @@ -1149,22 +1148,11 @@ ul.linklist li.responsive-menu a.responsive-menu-link:hover:before, ul.linklist border-color: #D31141; } -ul.responsive-popup { +.dropdown .dropdown-contents { background: #fff; border-color: #b9b9b9; box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.2); } - -.responsive-menu .popup-pointer { - border-bottom-color: #b9b9b9; -} - -.responsive-menu .popup-pointer-inner { - border-bottom-color: #fff; -} - -#tabs ul.responsive-tabs, #minitabs ul.responsive-tabs { - background: #ddedfb; - border-color: #c0c9d5; - box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.4); +.dropdown-up .dropdown-contents { + box-shadow: 1px 0 5px rgba(0, 0, 0, 0.2); } diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 4f55d3e92c..9e15eada22 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -363,6 +363,7 @@ ul.rightside { ul.linklist li.responsive-menu { position: relative; + margin: 0 5px; } ul.linklist li.responsive-menu a.responsive-menu-link { @@ -394,6 +395,24 @@ ul.linklist li.responsive-menu a.responsive-menu-link:before { max-width: none; } +li.responsive-menu.dropdown-right .dropdown { + left: -9px; +} + +li.responsive-menu.dropdown-left .dropdown { + right: -6px; +} + +li.responsive-menu .dropdown .dropdown-contents { + padding: 0 5px; +} + +ul.linklist .dropdown li { + clear: both; +} + + + /* Bulletin icons for list items ----------------------------------------*/ ul.linklist.bulletin li:before { @@ -416,54 +435,95 @@ ul.linklist.bulletin li.no-bulletin:before { display: none !important; } -/* Responsive popup +/* Dropdown menu ----------------------------------------*/ -ul.responsive-popup { +.dropdown { position: absolute; left: 0; top: 22px; z-index: 2; border: 1px solid transparent; border-radius: 5px; - padding: 5px; + padding: 9px 0 0; } -.responsive-rightside ul.responsive-popup { +.dropdown-up .dropdown { + top: auto; + bottom: 18px; + padding: 0 0 9px; +} + +.dropdown-left .dropdown { left: auto; right: 0; } -.responsive-menu .popup-pointer { - top: 22px; + +.dropdown .pointer, .dropdown .pointer-inner { + position: absolute; + width: 0; + height: 0; + border-top-width: 0; + border-bottom: 10px solid transparent; + border-left: 10px dashed transparent; + border-right: 10px dashed transparent; + -webkit-transform: rotate(360deg); /* better anti-aliasing in webkit */ + display: block; +} + +.dropdown-up .pointer, .dropdown-up .pointer-inner { + border-bottom-width: 0; + border-top: 10px solid transparent; +} + +.dropdown .pointer { + right: auto; + left: 10px; + top: 0; z-index: 3; - left: 2px; } -.responsive-menu ul.responsive-popup { - top: 32px; - left: -5px; + +.dropdown-up .pointer { + bottom: 0; + top: auto; } -.responsive-menu.responsive-rightside .popup-pointer { +.dropdown-left .dropdown .pointer { left: auto; - right: 2px; + right: 10px; } -.responsive-menu.responsive-rightside ul.responsive-popup { - left: auto; - right: -5px; + +.dropdown .pointer-inner { + top: auto; + bottom: -11px; + left: -10px; +} + +.dropdown-up .pointer-inner { + bottom: auto; + top: -11px; } -ul.responsive-popup li { +.dropdown .dropdown-contents { + z-index: 2; + overflow: hidden; + border: 1px solid transparent; + border-radius: 5px; + padding: 5px; +} + +.dropdown li { float: none; margin: 0; white-space: nowrap; text-align: left; } -.wrap ul.responsive-popup li { +.wrap .dropdown li, .dropdown.wrap li { white-space: normal; } -ul.responsive-popup li:before, ul.responsive-popup li:after { +.dropdown li:before, .dropdown li:after { display: none !important; } @@ -854,10 +914,7 @@ form > p.post-notice strong { left: 0; width: 330px; z-index: 1; - border: 1px solid; - box-shadow: 3px 3px 5px darkgray; - border-radius: 5px; - top: 32px; + top: 22px; } #notification_list ul { @@ -881,7 +938,11 @@ form > p.post-notice strong { display: none; } -#notification_list > .header { +#notification_list .dropdown-contents { + padding: 0; +} + +#notification_list .header { padding: 0 10px; font-family: Arial, "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 11px; @@ -893,18 +954,18 @@ form > p.post-notice strong { border-radius: 5px 5px 0 0; } -#notification_list > .header > .header_settings { +#notification_list .header .header_settings { float: right; font-weight: normal; text-transform: none; } -#notification_list > .footer { +#notification_list .footer { text-align: center; font-size: 1.2em; } -#notification_list ul li a, .notification_list dt > a, #notification_list > .footer > a { +#notification_list ul li a, .notification_list dt > a, #notification_list .footer > a { display: block; text-decoration: none; } @@ -921,30 +982,6 @@ form > p.post-notice strong { margin: 0; } -.popup-pointer, .popup-pointer-inner { - position: absolute; - width: 0; - height: 0; - border-top-width: 0; - border-bottom: 10px solid; - border-left: 10px dashed transparent; - border-right: 10px dashed transparent; - -webkit-transform: rotate(360deg); /* better anti-aliasing in webkit */ - display: block; -} - -.popup-pointer { - right: auto; - left: 10px; - top: -11px; -} - -.popup-pointer-inner { - top: auto; - bottom: -11px; - left: -10px; -} - .notification_list div.notifications { padding: 5px; } diff --git a/phpBB/styles/prosilver/theme/cp.css b/phpBB/styles/prosilver/theme/cp.css index f6bb1d0623..3e017719d6 100644 --- a/phpBB/styles/prosilver/theme/cp.css +++ b/phpBB/styles/prosilver/theme/cp.css @@ -218,6 +218,10 @@ ul.cplist { /* Responsive tabs ----------------------------------------*/ +.responsive-tab { + position: relative; +} + .responsive-tab .responsive-tab-link span { display: inline-block; font-size: 16px; @@ -251,29 +255,25 @@ ul.cplist { position: relative; } -#tabs ul.responsive-tabs, #minitabs ul.responsive-tabs { - position: absolute; - right: 0; - top: 26px; - z-index: 2; - border: 1px solid transparent; - border-radius: 5px; +#tabs .dropdown, #minitabs .dropdown { + top: 29px; + margin-right: -1px; } -#minitabs ul.responsive-tabs { - top: 23px; +#tabs .dropdown-up .dropdown, #minitabs .dropdown-up .dropdown { + bottom: -5px; + top: auto; } -.tabs-container #minitabs ul.responsive-tabs { - right: auto; - left: 0; +#tabs .dropdown-right .dropdown, #minitabs .dropdown-right .dropdown { + margin-left: -41px; } -#tabs .responsive-tabs li, #minitabs .responsive-tabs li { +#tabs .dropdown li, #minitabs .dropdown li { display: block !important; } -#tabs .responsive-tabs a, #tabs .responsive-tabs a span, #minitabs .responsive-tabs a, #minitabs .responsive-tabs a span { +#tabs .dropdown a, #tabs .dropdown a span, #minitabs .dropdown a, #minitabs .dropdown a span { background: transparent; float: none; margin: 0; @@ -281,14 +281,16 @@ ul.cplist { text-align: right; } -.tabs-container #minitabs .responsive-tabs a span { +.tabs-container #minitabs .dropdown a span { text-align: left; } -#tabs .responsive-tabs a span, #minitabs .responsive-tabs a span { - padding: 5px; +#tabs .dropdown a span, #minitabs .dropdown a span { + padding: 5px 8px; + color: inherit !important; } + /* UCP navigation menu ----------------------------------------*/ /* Container for sub-navigation list */ |