[ticket/13163] Fix responsive link lists

PHPBB3-13163
This commit is contained in:
PayBas 2014-10-13 23:29:01 +02:00
parent 29b54d12cc
commit 36d1f87c5a
2 changed files with 120 additions and 124 deletions

View file

@ -1,5 +1,3 @@
/* global phpbb */
/** /**
* phpBB3 forum functions * phpBB3 forum functions
*/ */
@ -321,7 +319,8 @@ function parseDocument($container) {
'use strict'; 'use strict';
var test = document.createElement('div'), var test = document.createElement('div'),
oldBrowser = (typeof test.style.borderRadius == 'undefined'); oldBrowser = (typeof test.style.borderRadius == 'undefined'),
$body = $('body');
/** /**
* Reset avatar dimensions when changing URL or EMAIL * Reset avatar dimensions when changing URL or EMAIL
@ -348,7 +347,7 @@ function parseDocument($container) {
$container.find('.pagination .dropdown-trigger').click(function() { $container.find('.pagination .dropdown-trigger').click(function() {
var $dropdownContainer = $(this).parent(); var $dropdownContainer = $(this).parent();
// Wait a little bit to make sure the dropdown has activated // Wait a little bit to make sure the dropdown has activated
setTimeout(function() { setTimeout(function() {
if ($dropdownContainer.hasClass('dropdown-visible')) { if ($dropdownContainer.hasClass('dropdown-visible')) {
$dropdownContainer.find('input.inputbox').focus(); $dropdownContainer.find('input.inputbox').focus();
} }
@ -356,7 +355,7 @@ function parseDocument($container) {
}); });
/** /**
* Adjust HTML code for IE8 and older versions * Adjust HTML code for IE8 and older versions
*/ */
if (oldBrowser) { if (oldBrowser) {
// Fix .linklist.bulletin lists // Fix .linklist.bulletin lists
@ -364,7 +363,7 @@ function parseDocument($container) {
} }
/** /**
* Resize navigation block to keep all links on same line * Resize navigation (breadcrumbs) block to keep all links on same line
*/ */
$container.find('.navlinks').each(function() { $container.find('.navlinks').each(function() {
var $this = $(this), var $this = $(this),
@ -394,7 +393,6 @@ function parseDocument($container) {
*/ */
$container.find('.breadcrumbs:not([data-skip-responsive])').each(function() { $container.find('.breadcrumbs:not([data-skip-responsive])').each(function() {
var $this = $(this), var $this = $(this),
$body = $('body'),
$links = $this.find('.crumb'), $links = $this.find('.crumb'),
length = $links.length, length = $links.length,
classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'], classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'],
@ -461,151 +459,158 @@ function parseDocument($container) {
*/ */
$container.find('.linklist:not(.navlinks, [data-skip-responsive]), .postbody .post-buttons:not([data-skip-responsive])').each(function() { $container.find('.linklist:not(.navlinks, [data-skip-responsive]), .postbody .post-buttons:not([data-skip-responsive])').each(function() {
var $this = $(this), var $this = $(this),
$body = $('body'),
filterSkip = '.breadcrumbs, [data-skip-responsive]', filterSkip = '.breadcrumbs, [data-skip-responsive]',
filterLast = '.edit-icon, .quote-icon, [data-last-responsive]', filterLast = '.edit-icon, .quote-icon, [data-last-responsive]',
persist = $this.attr('id') == 'nav-main', $linksAll = $this.children(),
$allLinks = $this.children(), $linksNotSkip = $linksAll.not(filterSkip), // All items that can potentially be hidden
$links = $allLinks.not(filterSkip), $linksFirst = $linksNotSkip.not(filterLast), // The items that will be hidden first
html = '<li class="responsive-menu" style="display:none;"><a href="javascript:void(0);" class="responsive-menu-link">&nbsp;</a><div class="dropdown" style="display:none;"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>', $linksLast = $linksNotSkip.filter(filterLast), // The items that will be hidden last
$filterLastList = $links.filter(filterLast), persistent = $this.attr('id') == 'nav-main', // Does this list already have a menu (such as quick-links)?
slack = 1; // Vertical slack space (in pixels). Determines how sensitive the script is in determining whether a line-break has occured. html = '<li class="responsive-menu hidden"><a href="javascript:void(0);" class="responsive-menu-link">&nbsp;</a><div class="dropdown hidden"><div class="pointer"><div class="pointer-inner" /></div><ul class="dropdown-contents" /></div></li>',
slack = 3; // Vertical slack space (in pixels). Determines how sensitive the script is in determining whether a line-break has occured.
if (!persist) { // Add a hidden drop-down menu to each links list (except those that already have one)
if ($links.is('.rightside')) { if (!persistent) {
$links.filter('.rightside:first').before(html); if ($linksNotSkip.is('.rightside')) {
$linksNotSkip.filter('.rightside:first').before(html);
$this.children('.responsive-menu').addClass('rightside'); $this.children('.responsive-menu').addClass('rightside');
} else { } else {
$this.append(html); $this.append(html);
} }
} }
var $item = $this.children('.responsive-menu'), // Set some object references and initial states
$menu = $item.find('.dropdown-contents'), var $menu = $this.children('.responsive-menu'),
$menuContents = $menu.find('.dropdown-contents'),
persistentContent = $menuContents.find('li:not(.separator)').length,
lastWidth = false, lastWidth = false,
compact = false, compact = false,
responsive = false, responsive1 = false,
copied = false; responsive2 = false,
copied1 = false,
copied2 = false,
maxHeight = 0;
// Find the tallest element in the list (we assume that all elements are roughly the same height)
$linksAll.each(function() {
if (!$(this).height()) {
return;
}
maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
});
if (maxHeight < 1) {
return; // Shouldn't be possible, but just in case, abort
} else {
maxHeight = maxHeight + slack;
}
function check() { function check() {
var width = $body.width(); var width = $body.width();
if (responsive && width <= lastWidth) { // We can't make it any smaller than this, so just skip
if (responsive2 && compact && (width <= lastWidth)) {
return; return;
} }
lastWidth = width;
// Unhide the quick-links menu if it has content
if (persist) {
$item.addClass('hidden');
if ($menu.find('li:not(.separator, .clone)').length || (responsive && $menu.find('li.clone').length)) {
$item.removeClass('hidden');
}
}
// Reset responsive and compact layout // Reset responsive and compact layout
if (responsive) { if (responsive1 || responsive2) {
$this.removeClass('responsive'); $linksNotSkip.removeClass('hidden');
$links.css('display', ''); $menuContents.children('.clone').addClass('hidden');
if (!persist) { responsive1 = responsive2 = false;
$item.css('display', 'none');
}
} }
if (compact) { if (compact) {
$this.removeClass('compact'); $this.removeClass('compact');
compact = false;
} }
// Find tallest element // Unhide the quick-links menu if it has "persistent" content
var maxHeight = 0; if (persistent && persistentContent) {
$allLinks.each(function() { $menu.removeClass('hidden');
if (!$(this).height()) { } else {
return; $menu.addClass('hidden');
}
maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
});
if (maxHeight < 1) {
return;
} }
// Nothing to resize if block's height is not bigger than tallest element's height // Nothing to resize if block's height is not bigger than tallest element's height
if ($this.height() <= (maxHeight + slack)) { if ($this.height() <= maxHeight) {
return; return;
} }
// Enable compact layout, find tallest element, compare to height of whole block // STEP 1: Compact
$this.addClass('compact'); if (!compact) {
$this.addClass('compact');
var compactMaxHeight = 0; compact = true;
$allLinks.each(function() { }
if (!$(this).height()) { if ($this.height() <= maxHeight) {
return;
}
compactMaxHeight = Math.max(compactMaxHeight, $(this).outerHeight(true));
});
if ($this.height() <= (maxHeight + slack)) {
return; return;
} }
// Compact layout did not resize block enough, switch to responsive layout // STEP 2: First responsive set - compact
$this.removeClass('compact'); if (compact) {
responsive = true; $this.removeClass('compact');
compact = false;
if (!copied) { }
var clone = $links.clone(true); // Copy the list items to the dropdown
clone.filter('.rightside').each(function() { if (!copied1) {
if (persist) { var $clones1 = $linksFirst.clone();
$(this).addClass('clone'); $menuContents.prepend($clones1.addClass('clone clone-first').removeClass('leftside rightside'));
}
$menu.prepend(this);
});
if (persist) {
$menu.prepend(clone.not('.rightside').addClass('clone'));
} else {
$menu.prepend(clone.not('.rightside'));
}
$menu.find('li.leftside, li.rightside').removeClass('leftside rightside');
$menu.find('.inputbox').parents('li:first').css('white-space', 'normal');
if ($this.hasClass('post-buttons')) { if ($this.hasClass('post-buttons')) {
$('.button', $menu).removeClass('button icon-button'); $('.button', $menuContents).removeClass('button icon-button');
$('.responsive-menu-link', $item).addClass('button icon-button').prepend('<span></span>'); $('.responsive-menu-link', $menu).addClass('button icon-button').prepend('<span></span>');
} }
copied = true; copied1 = true;
} else { }
$menu.children().css('display', ''); if (!responsive1) {
$linksFirst.addClass('hidden');
responsive1 = true;
$menuContents.children('.clone-first').removeClass('hidden');
$menu.removeClass('hidden');
}
if ($this.height() <= maxHeight) {
return;
} }
$item.css('display', ''); // STEP 3: First responsive set + compact
$this.addClass('responsive'); if (!compact) {
$this.addClass('compact');
// Try to not hide filtered items compact = true;
if ($filterLastList.length) { }
$links.not(filterLast).css('display', 'none'); if ($this.height() <= maxHeight) {
return;
maxHeight = 0;
$filterLastList.each(function() {
if (!$(this).height()) return;
maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
});
if ($this.height() <= (maxHeight + slack)) {
$menu.children().filter(filterLast).css('display', 'none');
return;
}
} }
// If even responsive isn't enough, use both responsive and compact at same time // STEP 4: Last responsive set - compact
compact = true; if (compact) {
$this.addClass('compact'); $this.removeClass('compact');
compact = false;
}
// Copy the list items to the dropdown
if (!copied2) {
var $clones2 = $linksLast.clone();
$menuContents.prepend($clones2.addClass('clone clone-last').removeClass('leftside rightside'));
copied2 = true;
}
if (!responsive2) {
$linksLast.addClass('hidden');
responsive2 = true;
$menuContents.children('.clone-last').removeClass('hidden');
}
if ($this.height() <= maxHeight) {
return;
}
$links.css('display', 'none'); // STEP 5: Last responsive set + compact
if (!compact) {
$this.addClass('compact');
compact = true;
}
if ($this.height() <= maxHeight) {
return;
}
} }
if (!persist) { if (!persistent) {
phpbb.registerDropdown($item.find('a.responsive-menu-link'), $item.find('.dropdown')); phpbb.registerDropdown($menu.find('a.responsive-menu-link'), $menu.find('.dropdown'), false);
} }
check(); check();
@ -613,7 +618,7 @@ function parseDocument($container) {
}); });
/** /**
* Do not run functions below for old browsers * Do not run functions below for old browsers
*/ */
if (oldBrowser) { if (oldBrowser) {
return; return;
@ -747,7 +752,7 @@ function parseDocument($container) {
$this.addClass('show-header'); $this.addClass('show-header');
} }
}); });
headersLength = headers.length; headersLength = headers.length;
// Add header text to each cell as <dfn> // Add header text to each cell as <dfn>
@ -804,7 +809,6 @@ function parseDocument($container) {
*/ */
$container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() { $container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() {
var $this = $(this), var $this = $(this),
$body = $('body'),
$ul = $this.children(), $ul = $this.children(),
$tabs = $ul.children().not('[data-skip-responsive]'), $tabs = $ul.children().not('[data-skip-responsive]'),
$links = $tabs.children('a'), $links = $tabs.children('a'),

View file

@ -1289,18 +1289,10 @@ ul.linklist:after,
width: 50px; width: 50px;
} }
.dropdown .clone { .dropdown .clone.hidden + li.separator {
display: none; display: none;
} }
.responsive .dropdown .clone { .dropdown .clone.hidden + li {
display: inherit; border-top: none;
}
.dropdown .clone + li.separator {
display: none;
}
.responsive .dropdown .clone + li.separator {
display: inherit;
} }