Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

forum_fn.js

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 22.66 KiB


001  /* global phpbb */
002   
003  /**
004  * phpBB3 forum functions
005  */
006   
007  /**
008  * Find a member
009  */
010  function find_username(url) {
011      'use strict';
012   
013      popup(url, 760, 570, '_usersearch');
014      return false;
015  }
016   
017  /**
018  * Window popup
019  */
020  function popup(url, width, height, name) {
021      'use strict';
022   
023      if (!name) {
024          name = '_popup';
025      }
026   
027      window.open(url.replace(/&/g, '&'), name, 'height=' + height + ',resizable=yes,scrollbars=yes, width=' + width);
028      return false;
029  }
030   
031  /**
032  * Jump to page
033  */
034  function pageJump(item) {
035      'use strict';
036   
037      var page = parseInt(item.val(), 10),
038          perPage = item.attr('data-per-page'),
039          baseUrl = item.attr('data-base-url'),
040          startName = item.attr('data-start-name');
041   
042      if (page !== null && !isNaN(page) && page === Math.floor(page) && page > 0) {
043          if (baseUrl.indexOf('?') === -1) {
044              document.location.href = baseUrl + '?' + startName + '=' + ((page - 1) * perPage);
045          } else {
046              document.location.href = baseUrl.replace(/&/g, '&') + '&' + startName + '=' + ((page - 1) * perPage);
047          }
048      }
049  }
050   
051  /**
052  * Mark/unmark checklist
053  * id = ID of parent container, name = name prefix, state = state [true/false]
054  */
055  function marklist(id, name, state) {
056      'use strict';
057   
058      jQuery('#' + id + ' input[type=checkbox][name]').each(function() {
059          var $this = jQuery(this);
060          if ($this.attr('name').substr(0, name.length) === name && !$this.prop('disabled')) {
061              $this.prop('checked', state);
062          }
063      });
064  }
065   
066  /**
067  * Resize viewable area for attached image or topic review panel (possibly others to come)
068  * e = element
069  */
070  function viewableArea(e, itself) {
071      'use strict';
072   
073      if (!e) {
074          return;
075      }
076   
077      if (!itself) {
078          e = e.parentNode;
079      }
080   
081      if (!e.vaHeight) {
082          // Store viewable area height before changing style to auto
083          e.vaHeight = e.offsetHeight;
084          e.vaMaxHeight = e.style.maxHeight;
085          e.style.height = 'auto';
086          e.style.maxHeight = 'none';
087          e.style.overflow = 'visible';
088      } else {
089          // Restore viewable area height to the default
090          e.style.height = e.vaHeight + 'px';
091          e.style.overflow = 'auto';
092          e.style.maxHeight = e.vaMaxHeight;
093          e.vaHeight = false;
094      }
095  }
096   
097  /**
098  * Alternate display of subPanels
099  */
100  jQuery(function($) {
101      'use strict';
102   
103      $('.sub-panels').each(function() {
104   
105          var $childNodes = $('a[data-subpanel]', this),
106              panels = $childNodes.map(function () {
107                  return this.getAttribute('data-subpanel');
108              }),
109              showPanel = this.getAttribute('data-show-panel');
110   
111          if (panels.length) {
112              activateSubPanel(showPanel, panels);
113              $childNodes.click(function () {
114                  activateSubPanel(this.getAttribute('data-subpanel'), panels);
115                  return false;
116              });
117          }
118      });
119  });
120   
121  /**
122  * Activate specific subPanel
123  */
124  function activateSubPanel(p, panels) {
125      'use strict';
126   
127      var i, showPanel;
128   
129      if (typeof p === 'string') {
130          showPanel = p;
131      }
132      $('input[name="show_panel"]').val(showPanel);
133   
134      if (typeof panels === 'undefined') {
135          panels = jQuery('.sub-panels a[data-subpanel]').map(function() {
136              return this.getAttribute('data-subpanel');
137          });
138      }
139   
140      for (i = 0; i < panels.length; i++) {
141          jQuery('#' + panels[i]).css('display', panels[i] === showPanel ? 'block' : 'none');
142          jQuery('#' + panels[i] + '-tab').toggleClass('activetab', panels[i] === showPanel);
143      }
144  }
145   
146  function selectCode(a) {
147      'use strict';
148   
149      // Get ID of code block
150      var e = a.parentNode.parentNode.getElementsByTagName('CODE')[0];
151      var s, r;
152   
153      // Not IE and IE9+
154      if (window.getSelection) {
155          s = window.getSelection();
156          // Safari and Chrome
157          if (s.setBaseAndExtent) {
158              var l = (e.innerText.length > 1) ? e.innerText.length - 1 : 1;
159              try {
160                  s.setBaseAndExtent(e, 0, e, l);
161              } catch (error) {
162                  r = document.createRange();
163                  r.selectNodeContents(e);
164                  s.removeAllRanges();
165                  s.addRange(r);
166              }
167          }
168          // Firefox and Opera
169          else {
170              // workaround for bug # 42885
171              if (window.opera && e.innerHTML.substring(e.innerHTML.length - 4) === '<BR>') {
172                  e.innerHTML = e.innerHTML + '&nbsp;';
173              }
174   
175              r = document.createRange();
176              r.selectNodeContents(e);
177              s.removeAllRanges();
178              s.addRange(r);
179          }
180      }
181      // Some older browsers
182      else if (document.getSelection) {
183          s = document.getSelection();
184          r = document.createRange();
185          r.selectNodeContents(e);
186          s.removeAllRanges();
187          s.addRange(r);
188      }
189      // IE
190      else if (document.selection) {
191          r = document.body.createTextRange();
192          r.moveToElementText(e);
193          r.select();
194      }
195  }
196   
197  var inAutocomplete = false;
198  var lastKeyEntered = '';
199   
200  /**
201  * Check event key
202  */
203  function phpbbCheckKey(event) {
204      'use strict';
205   
206      // Keycode is array down or up?
207      if (event.keyCode && (event.keyCode === 40 || event.keyCode === 38)) {
208          inAutocomplete = true;
209      }
210   
211      // Make sure we are not within an "autocompletion" field
212      if (inAutocomplete) {
213          // If return pressed and key changed we reset the autocompletion
214          if (!lastKeyEntered || lastKeyEntered === event.which) {
215              inAutocomplete = false;
216              return true;
217          }
218      }
219   
220      // Keycode is not return, then return. ;)
221      if (event.which !== 13) {
222          lastKeyEntered = event.which;
223          return true;
224      }
225   
226      return false;
227  }
228   
229  /**
230  * Apply onkeypress event for forcing default submit button on ENTER key press
231  */
232  jQuery(function($) {
233      'use strict';
234   
235      $('form input[type=text], form input[type=password]').on('keypress', function (e) {
236          var defaultButton = $(this).parents('form').find('input[type=submit].default-submit-action');
237   
238          if (!defaultButton || defaultButton.length <= 0) {
239              return true;
240          }
241   
242          if (phpbbCheckKey(e)) {
243              return true;
244          }
245   
246          if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
247              defaultButton.click();
248              return false;
249          }
250   
251          return true;
252      });
253  });
254   
255  /**
256  * Functions for user search popup
257  */
258  function insertUser(formId, value) {
259      'use strict';
260   
261      var $form = jQuery(formId),
262          formName = $form.attr('data-form-name'),
263          fieldName = $form.attr('data-field-name'),
264          item = opener.document.forms[formName][fieldName];
265   
266      if (item.value.length && item.type === 'textarea') {
267          value = item.value + '\n' + value;
268      }
269   
270      item.value = value;
271  }
272   
273  function insert_marked_users(formId, users) {
274      'use strict';
275   
276      $(users).filter(':checked').each(function() {
277          insertUser(formId, this.value);
278      });
279   
280      window.close();
281  }
282   
283  function insert_single_user(formId, user) {
284      'use strict';
285   
286      insertUser(formId, user);
287      window.close();
288  }
289   
290  /**
291  * Parse document block
292  */
293  function parseDocument($container) {
294      'use strict';
295   
296      var test = document.createElement('div'),
297          oldBrowser = (typeof test.style.borderRadius === 'undefined'),
298          $body = $('body');
299   
300      /**
301      * Reset avatar dimensions when changing URL or EMAIL
302      */
303      $container.find('input[data-reset-on-edit]').on('keyup', function() {
304          $(this.getAttribute('data-reset-on-edit')).val('');
305      });
306   
307      /**
308      * Pagination
309      */
310      $container.find('.pagination .page-jump-form :button').click(function() {
311          var $input = $(this).siblings('input.inputbox');
312          pageJump($input);
313      });
314   
315      $container.find('.pagination .page-jump-form input.inputbox').on('keypress', function(event) {
316          if (event.which === 13 || event.keyCode === 13) {
317              event.preventDefault();
318              pageJump($(this));
319          }
320      });
321   
322      $container.find('.pagination .dropdown-trigger').click(function() {
323          var $dropdownContainer = $(this).parent();
324          // Wait a little bit to make sure the dropdown has activated
325          setTimeout(function() {
326              if ($dropdownContainer.hasClass('dropdown-visible')) {
327                  $dropdownContainer.find('input.inputbox').focus();
328              }
329          }, 100);
330      });
331   
332      /**
333      * Resize navigation (breadcrumbs) block to keep all links on same line
334      */
335      $container.find('.navlinks').each(function() {
336          var $this = $(this),
337              $left = $this.children().not('.rightside'),
338              $right = $this.children('.rightside');
339   
340          if ($left.length !== 1 || !$right.length) {
341              return;
342          }
343   
344          function resize() {
345              var width = 0,
346                  diff = $left.outerWidth(true) - $left.width(),
347                  minWidth = Math.max($this.width() / 3, 240),
348                  maxWidth;
349   
350              $right.each(function() {
351                  var $this = $(this);
352                  if ($this.is(':visible')) {
353                      width += $this.outerWidth(true);
354                  }
355              });
356   
357              maxWidth = $this.width() - width - diff;
358              $left.css('max-width', Math.floor(Math.max(maxWidth, minWidth)) + 'px');
359          }
360   
361          resize();
362          $(window).resize(resize);
363      });
364   
365      /**
366      * Makes breadcrumbs responsive
367      */
368      $container.find('.breadcrumbs:not([data-skip-responsive])').each(function() {
369          var $this = $(this),
370              $links = $this.find('.crumb'),
371              length = $links.length,
372              classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'],
373              classesLength = classes.length,
374              maxHeight = 0,
375              lastWidth = false,
376              wrapped = false;
377   
378          // Set tooltips
379          $this.find('a').each(function() {
380              var $link = $(this);
381              $link.attr('title', $link.text());
382          });
383   
384          // Function that checks breadcrumbs
385          function check() {
386              var height = $this.height(),
387                  width;
388   
389              // Test max-width set in code for .navlinks above
390              width = parseInt($this.css('max-width'), 10);
391              if (!width) {
392                  width = $body.width();
393              }
394   
395              maxHeight = parseInt($this.css('line-height'), 10);
396              $links.each(function() {
397                  if ($(this).height() > 0) {
398                      maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
399                  }
400              });
401   
402              if (height <= maxHeight) {
403                  if (!wrapped || lastWidth === false || lastWidth >= width) {
404                      return;
405                  }
406              }
407              lastWidth = width;
408   
409              if (wrapped) {
410                  $this.removeClass('wrapped').find('.crumb.wrapped').removeClass('wrapped ' + classes.join(' '));
411                  if ($this.height() <= maxHeight) {
412                      return;
413                  }
414              }
415   
416              wrapped = true;
417              $this.addClass('wrapped');
418              if ($this.height() <= maxHeight) {
419                  return;
420              }
421   
422              for (var i = 0; i < classesLength; i++) {
423                  for (var j = length - 1; j >= 0; j--) {
424                      $links.eq(j).addClass('wrapped ' + classes[i]);
425                      if ($this.height() <= maxHeight) {
426                          return;
427                      }
428                  }
429              }
430          }
431   
432          // Run function and set event
433          check();
434          $(window).resize(check);
435      });
436   
437      /**
438      * Responsive link lists
439      */
440      var selector = '.linklist:not(.navlinks, [data-skip-responsive]),' +
441          '.postbody .post-buttons:not([data-skip-responsive])';
442      $container.find(selector).each(function() {
443          var $this = $(this),
444              filterSkip = '.breadcrumbs, [data-skip-responsive]',
445              filterLast = '.edit-icon, .quote-icon, [data-last-responsive]',
446              $linksAll = $this.children(),
447              $linksNotSkip = $linksAll.not(filterSkip), // All items that can potentially be hidden
448              $linksFirst = $linksNotSkip.not(filterLast), // The items that will be hidden first
449              $linksLast = $linksNotSkip.filter(filterLast), // The items that will be hidden last
450              persistent = $this.attr('id') === 'nav-main', // Does this list already have a menu (such as quick-links)?
451              html = '<li class="responsive-menu hidden"><a href="javascript:void(0);" class="js-responsive-menu-link responsive-menu-link"><i class="icon fa-bars fa-fw" aria-hidden="true"></i></a><div class="dropdown"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>',
452              slack = 3; // Vertical slack space (in pixels). Determines how sensitive the script is in determining whether a line-break has occurred.
453   
454          // Add a hidden drop-down menu to each links list (except those that already have one)
455          if (!persistent) {
456              if ($linksNotSkip.is('.rightside')) {
457                  $linksNotSkip.filter('.rightside:first').before(html);
458                  $this.children('.responsive-menu').addClass('rightside');
459              } else {
460                  $this.append(html);
461              }
462          }
463   
464          // Set some object references and initial states
465          var $menu = $this.children('.responsive-menu'),
466              $menuContents = $menu.find('.dropdown-contents'),
467              persistentContent = $menuContents.find('li:not(.separator)').length,
468              lastWidth = false,
469              compact = false,
470              responsive1 = false,
471              responsive2 = false,
472              copied1 = false,
473              copied2 = false,
474              maxHeight = 0;
475   
476          // Find the tallest element in the list (we assume that all elements are roughly the same height)
477          $linksAll.each(function() {
478              if (!$(this).height()) {
479                  return;
480              }
481              maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
482          });
483          if (maxHeight < 1) {
484              return; // Shouldn't be possible, but just in case, abort
485          } else {
486              maxHeight = maxHeight + slack;
487          }
488   
489          function check() {
490              var width = $body.width();
491              // We can't make it any smaller than this, so just skip
492              if (responsive2 && compact && (width <= lastWidth)) {
493                  return;
494              }
495              lastWidth = width;
496   
497              // Reset responsive and compact layout
498              if (responsive1 || responsive2) {
499                  $linksNotSkip.removeClass('hidden');
500                  $menuContents.children('.clone').addClass('hidden');
501                  responsive1 = responsive2 = false;
502              }
503              if (compact) {
504                  $this.removeClass('compact');
505                  compact = false;
506              }
507   
508              // Unhide the quick-links menu if it has "persistent" content
509              if (persistent && persistentContent) {
510                  $menu.removeClass('hidden');
511              } else {
512                  $menu.addClass('hidden');
513              }
514   
515              // Nothing to resize if block's height is not bigger than tallest element's height
516              if ($this.height() <= maxHeight) {
517                  return;
518              }
519   
520              // STEP 1: Compact
521              if (!compact) {
522                  $this.addClass('compact');
523                  compact = true;
524              }
525              if ($this.height() <= maxHeight) {
526                  return;
527              }
528   
529              // STEP 2: First responsive set - compact
530              if (compact) {
531                  $this.removeClass('compact');
532                  compact = false;
533              }
534              // Copy the list items to the dropdown
535              if (!copied1) {
536                  var $clones1 = $linksFirst.clone(true);
537                  $menuContents.prepend($clones1.addClass('clone clone-first').removeClass('leftside rightside'));
538   
539                  if ($this.hasClass('post-buttons')) {
540                      $('.button', $menuContents).removeClass('button');
541                      $('.sr-only', $menuContents).removeClass('sr-only');
542                      $('.js-responsive-menu-link').addClass('button').addClass('button-icon-only');
543                      $('.js-responsive-menu-link .icon').removeClass('fa-bars').addClass('fa-ellipsis-h');
544                  }
545                  copied1 = true;
546              }
547              if (!responsive1) {
548                  $linksFirst.addClass('hidden');
549                  responsive1 = true;
550                  $menuContents.children('.clone-first').removeClass('hidden');
551                  $menu.removeClass('hidden');
552              }
553              if ($this.height() <= maxHeight) {
554                  return;
555              }
556   
557              // STEP 3: First responsive set + compact
558              if (!compact) {
559                  $this.addClass('compact');
560                  compact = true;
561              }
562              if ($this.height() <= maxHeight) {
563                  return;
564              }
565   
566              // STEP 4: Last responsive set - compact
567              if (!$linksLast.length) {
568                  return; // No other links to hide, can't do more
569              }
570              if (compact) {
571                  $this.removeClass('compact');
572                  compact = false;
573              }
574              // Copy the list items to the dropdown
575              if (!copied2) {
576                  var $clones2 = $linksLast.clone();
577                  $menuContents.prepend($clones2.addClass('clone clone-last').removeClass('leftside rightside'));
578                  copied2 = true;
579              }
580              if (!responsive2) {
581                  $linksLast.addClass('hidden');
582                  responsive2 = true;
583                  $menuContents.children('.clone-last').removeClass('hidden');
584              }
585              if ($this.height() <= maxHeight) {
586                  return;
587              }
588   
589              // STEP 5: Last responsive set + compact
590              if (!compact) {
591                  $this.addClass('compact');
592                  compact = true;
593              }
594          }
595   
596          if (!persistent) {
597              phpbb.registerDropdown($menu.find('a.js-responsive-menu-link'), $menu.find('.dropdown'), false);
598          }
599   
600          // If there are any images in the links list, run the check again after they have loaded
601          $linksAll.find('img').each(function() {
602              $(this).on('load', function() {
603                  check();
604              });
605          });
606   
607          check();
608          $(window).resize(check);
609      });
610   
611      /**
612      * Do not run functions below for old browsers
613      */
614      if (oldBrowser) {
615          return;
616      }
617   
618      /**
619      * Adjust topiclist lists with check boxes
620      */
621      $container.find('ul.topiclist dd.mark').siblings('dt').children('.list-inner').addClass('with-mark');
622   
623      /**
624      * Appends contents of all extra columns to first column in
625      * .topiclist lists for mobile devices. Copies contents as is.
626      *
627      * To add that functionality to .topiclist list simply add
628      * responsive-show-all to list of classes
629      */
630      $container.find('.topiclist.responsive-show-all > li > dl').each(function() {
631          var $this = $(this),
632              $block = $this.find('dt .responsive-show:last-child'),
633              first = true;
634   
635          // Create block that is visible only on mobile devices
636          if (!$block.length) {
637              $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
638              $block = $this.find('dt .responsive-show:last-child');
639          } else {
640              first = ($.trim($block.text()).length === 0);
641          }
642   
643          // Copy contents of each column
644          $this.find('dd').not('.mark').each(function() {
645              var column = $(this),
646                  $children = column.children(),
647                  html = column.html();
648   
649              if ($children.length === 1 && $children.text() === column.text()) {
650                  html = $children.html();
651              }
652   
653              $block.append((first ? '' : '<br>') + html);
654   
655              first = false;
656          });
657      });
658   
659      /**
660      * Same as above, but prepends text from header to each
661      * column before contents of that column.
662      *
663      * To add that functionality to .topiclist list simply add
664      * responsive-show-columns to list of classes
665      */
666      $container.find('.topiclist.responsive-show-columns').each(function() {
667          var $list = $(this),
668              headers = [],
669              headersLength = 0;
670   
671          // Find all headers, get contents
672          $list.prev('.topiclist').find('li.header dd').not('.mark').each(function() {
673              headers.push($("<div>").text($(this).text()).html());
674              headersLength++;
675          });
676   
677          if (!headersLength) {
678              return;
679          }
680   
681          // Parse each row
682          $list.find('dl').each(function() {
683              var $this = $(this),
684                  $block = $this.find('dt .responsive-show:last-child'),
685                  first = true;
686   
687              // Create block that is visible only on mobile devices
688              if (!$block.length) {
689                  $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
690                  $block = $this.find('dt .responsive-show:last-child');
691              } else {
692                  first = ($.trim($block.text()).length === 0);
693              }
694   
695              // Copy contents of each column
696              $this.find('dd').not('.mark').each(function(i) {
697                  var column = $(this),
698                      children = column.children(),
699                      html = column.html();
700   
701                  if (children.length === 1 && children.text() === column.text()) {
702                      html = children.html();
703                  }
704   
705                  // Prepend contents of matching header before contents of column
706                  if (i < headersLength) {
707                      html = headers[i] + ': <strong>' + html + '</strong>';
708                  }
709   
710                  $block.append((first ? '' : '<br>') + html);
711   
712                  first = false;
713              });
714          });
715      });
716   
717      /**
718      * Responsive tables
719      */
720      $container.find('table.table1').not('.not-responsive').each(function() {
721          var $this = $(this),
722              $th = $this.find('thead > tr > th'),
723              headers = [],
724              totalHeaders = 0,
725              i, headersLength;
726   
727          // Find each header
728          $th.each(function(column) {
729              var cell = $(this),
730                  colspan = parseInt(cell.attr('colspan'), 10),
731                  dfn = cell.attr('data-dfn'),
732                  text = dfn ? dfn : cell.text();
733   
734              colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
735   
736              for (i = 0; i < colspan; i++) {
737                  headers.push(text);
738              }
739              totalHeaders++;
740   
741              if (dfn && !column) {
742                  $this.addClass('show-header');
743              }
744          });
745   
746          headersLength = headers.length;
747   
748          // Add header text to each cell as <dfn>
749          $this.addClass('responsive');
750   
751          if (totalHeaders < 2) {
752              $this.addClass('show-header');
753              return;
754          }
755   
756          $this.find('tbody > tr').each(function() {
757              var row = $(this),
758                  cells = row.children('td'),
759                  column = 0;
760   
761              if (cells.length === 1) {
762                  row.addClass('big-column');
763                  return;
764              }
765   
766              cells.each(function() {
767                  var cell = $(this),
768                      colspan = parseInt(cell.attr('colspan'), 10),
769                      text = $.trim(cell.text());
770   
771                  if (headersLength <= column) {
772                      return;
773                  }
774   
775                  if ((text.length && text !== '-') || cell.children().length) {
776                      if (headers[column].length) {
777                          cell.prepend($("<dfn>").css('display', 'none').text(headers[column]));
778                      }
779                  } else {
780                      cell.addClass('empty');
781                  }
782   
783                  colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
784                  column += colspan;
785              });
786          });
787      });
788   
789      /**
790      * Hide empty responsive tables
791      */
792      $container.find('table.responsive > tbody').not('.responsive-skip-empty').each(function() {
793          var $items = $(this).children('tr');
794          if (!$items.length) {
795              $(this).parent('table:first').addClass('responsive-hide');
796          }
797      });
798   
799      /**
800      * Responsive tabs
801      */
802      $container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() {
803          var $this = $(this),
804              $ul = $this.children(),
805              $tabs = $ul.children().not('[data-skip-responsive]'),
806              $links = $tabs.children('a'),
807              $item = $ul.append('<li class="tab responsive-tab" style="display:none;"><a href="javascript:void(0);" class="responsive-tab-link">&nbsp;</a><div class="dropdown tab-dropdown" style="display: none;"><div class="pointer"><div class="pointer-inner"></div></div><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab'),
808              $menu = $item.find('.dropdown-contents'),
809              maxHeight = 0,
810              lastWidth = false,
811              responsive = false;
812   
813          $links.each(function() {
814              var $this = $(this);
815              maxHeight = Math.max(maxHeight, Math.max($this.outerHeight(true), $this.parent().outerHeight(true)));
816          });
817   
818          function check() {
819              var width = $body.width(),
820                  height = $this.height();
821   
822              if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) {
823                  return;
824              }
825   
826              $tabs.show();
827              $item.hide();
828   
829              lastWidth = width;
830              height = $this.height();
831              if (height <= maxHeight) {
832                  if ($item.hasClass('dropdown-visible')) {
833                      phpbb.toggleDropdown.call($item.find('a.responsive-tab-link').get(0));
834                  }
835                  return;
836              }
837   
838              responsive = true;
839              $item.show();
840              $menu.html('');
841   
842              var $availableTabs = $tabs.filter(':not(.activetab, .responsive-tab)'),
843                  total = $availableTabs.length,
844                  i, $tab;
845   
846              for (i = total - 1; i >= 0; i--) {
847                  $tab = $availableTabs.eq(i);
848                  $menu.prepend($tab.clone(true).removeClass('tab'));
849                  $tab.hide();
850                  if ($this.height() <= maxHeight) {
851                      $menu.find('a').click(function() {
852                          check(true);
853                      });
854                      return;
855                  }
856              }
857              $menu.find('a').click(function() {
858                  check(true);
859              });
860          }
861   
862          var $tabLink = $item.find('a.responsive-tab-link');
863          phpbb.registerDropdown($tabLink, $item.find('.dropdown'), {
864              visibleClass: 'activetab'
865          });
866   
867          check(true);
868          $(window).resize(check);
869      });
870   
871      /**
872       * Hide UCP/MCP navigation if there is only 1 item
873       */
874      $container.find('#navigation').each(function() {
875          var $items = $(this).children('ol, ul').children('li');
876          if ($items.length === 1) {
877              $(this).addClass('responsive-hide');
878          }
879      });
880   
881      /**
882      * Replace responsive text
883      */
884      $container.find('[data-responsive-text]').each(function() {
885          var $this = $(this),
886              fullText = $this.text(),
887              responsiveText = $this.attr('data-responsive-text'),
888              responsive = false;
889   
890          function check() {
891              if ($(window).width() > 700) {
892                  if (!responsive) {
893                      return;
894                  }
895                  $this.text(fullText);
896                  responsive = false;
897                  return;
898              }
899              if (responsive) {
900                  return;
901              }
902              $this.text(responsiveText);
903              responsive = true;
904          }
905   
906          check();
907          $(window).resize(check);
908      });
909  }
910   
911  /**
912  * Run onload functions
913  */
914  jQuery(function($) {
915      'use strict';
916   
917      // Swap .nojs and .hasjs
918      $('#phpbb.nojs').toggleClass('nojs hasjs');
919      $('#phpbb').toggleClass('hastouch', phpbb.isTouch);
920      $('#phpbb.hastouch').removeClass('notouch');
921   
922      // Focus forms
923      $('form[data-focus]:first').each(function() {
924          $('#' + this.getAttribute('data-focus')).focus();
925      });
926   
927      parseDocument($('body'));
928  });
929