Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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: 09.10.2024, 12:54 - Dateigröße: 23.48 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) {
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  /**
198  * Play quicktime file by determining it's width/height
199  * from the displayed rectangle area
200  */
201  function play_qt_file(obj) {
202      'use strict';
203   
204      var rectangle = obj.GetRectangle();
205      var width, height;
206   
207      if (rectangle) {
208          rectangle = rectangle.split(',');
209          var x1 = parseInt(rectangle[0], 10);
210          var x2 = parseInt(rectangle[2], 10);
211          var y1 = parseInt(rectangle[1], 10);
212          var y2 = parseInt(rectangle[3], 10);
213   
214          width = (x1 < 0) ? (x1 * -1) + x2 : x2 - x1;
215          height = (y1 < 0) ? (y1 * -1) + y2 : y2 - y1;
216      } else {
217          width = 200;
218          height = 0;
219      }
220   
221      obj.width = width;
222      obj.height = height + 16;
223   
224      obj.SetControllerVisible(true);
225      obj.Play();
226  }
227   
228  var inAutocomplete = false;
229  var lastKeyEntered = '';
230   
231  /**
232  * Check event key
233  */
234  function phpbbCheckKey(event) {
235      'use strict';
236   
237      // Keycode is array down or up?
238      if (event.keyCode && (event.keyCode === 40 || event.keyCode === 38)) {
239          inAutocomplete = true;
240      }
241   
242      // Make sure we are not within an "autocompletion" field
243      if (inAutocomplete) {
244          // If return pressed and key changed we reset the autocompletion
245          if (!lastKeyEntered || lastKeyEntered === event.which) {
246              inAutocomplete = false;
247              return true;
248          }
249      }
250   
251      // Keycode is not return, then return. ;)
252      if (event.which !== 13) {
253          lastKeyEntered = event.which;
254          return true;
255      }
256   
257      return false;
258  }
259   
260  /**
261  * Apply onkeypress event for forcing default submit button on ENTER key press
262  */
263  jQuery(function($) {
264      'use strict';
265   
266      $('form input[type=text], form input[type=password]').on('keypress', function (e) {
267          var defaultButton = $(this).parents('form').find('input[type=submit].default-submit-action');
268   
269          if (!defaultButton || defaultButton.length <= 0) {
270              return true;
271          }
272   
273          if (phpbbCheckKey(e)) {
274              return true;
275          }
276   
277          if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
278              defaultButton.click();
279              return false;
280          }
281   
282          return true;
283      });
284  });
285   
286  /**
287  * Functions for user search popup
288  */
289  function insertUser(formId, value) {
290      'use strict';
291   
292      var $form = jQuery(formId),
293          formName = $form.attr('data-form-name'),
294          fieldName = $form.attr('data-field-name'),
295          item = opener.document.forms[formName][fieldName];
296   
297      if (item.value.length && item.type === 'textarea') {
298          value = item.value + '\n' + value;
299      }
300   
301      item.value = value;
302  }
303   
304  function insert_marked_users(formId, users) {
305      'use strict';
306   
307      for (var i = 0; i < users.length; i++) {
308          if (users[i].checked) {
309              insertUser(formId, users[i].value);
310          }
311      }
312   
313      window.close();
314  }
315   
316  function insert_single_user(formId, user) {
317      'use strict';
318   
319      insertUser(formId, user);
320      window.close();
321  }
322   
323  /**
324  * Parse document block
325  */
326  function parseDocument($container) {
327      'use strict';
328   
329      var test = document.createElement('div'),
330          oldBrowser = (typeof test.style.borderRadius === 'undefined'),
331          $body = $('body');
332   
333      /**
334      * Reset avatar dimensions when changing URL or EMAIL
335      */
336      $container.find('input[data-reset-on-edit]').on('keyup', function() {
337          $(this.getAttribute('data-reset-on-edit')).val('');
338      });
339   
340      /**
341      * Pagination
342      */
343      $container.find('.pagination .page-jump-form :button').click(function() {
344          var $input = $(this).siblings('input.inputbox');
345          pageJump($input);
346      });
347   
348      $container.find('.pagination .page-jump-form input.inputbox').on('keypress', function(event) {
349          if (event.which === 13 || event.keyCode === 13) {
350              event.preventDefault();
351              pageJump($(this));
352          }
353      });
354   
355      $container.find('.pagination .dropdown-trigger').click(function() {
356          var $dropdownContainer = $(this).parent();
357          // Wait a little bit to make sure the dropdown has activated
358          setTimeout(function() {
359              if ($dropdownContainer.hasClass('dropdown-visible')) {
360                  $dropdownContainer.find('input.inputbox').focus();
361              }
362          }, 100);
363      });
364   
365      /**
366      * Adjust HTML code for IE8 and older versions
367      */
368      // if (oldBrowser) {
369      //     // Fix .linklist.bulletin lists
370      //     $container
371      //         .find('ul.linklist.bulletin > li')
372      //         .filter(':first-child, .rightside:last-child')
373      //         .addClass('no-bulletin');
374      // }
375   
376      /**
377      * Resize navigation (breadcrumbs) block to keep all links on same line
378      */
379      $container.find('.navlinks').each(function() {
380          var $this = $(this),
381              $left = $this.children().not('.rightside'),
382              $right = $this.children('.rightside');
383   
384          if ($left.length !== 1 || !$right.length) {
385              return;
386          }
387   
388          function resize() {
389              var width = 0,
390                  diff = $left.outerWidth(true) - $left.width(),
391                  minWidth = Math.max($this.width() / 3, 240),
392                  maxWidth;
393   
394              $right.each(function() {
395                  var $this = $(this);
396                  if ($this.is(':visible')) {
397                      width += $this.outerWidth(true);
398                  }
399              });
400   
401              maxWidth = $this.width() - width - diff;
402              $left.css('max-width', Math.floor(Math.max(maxWidth, minWidth)) + 'px');
403          }
404   
405          resize();
406          $(window).resize(resize);
407      });
408   
409      /**
410      * Makes breadcrumbs responsive
411      */
412      $container.find('.breadcrumbs:not([data-skip-responsive])').each(function() {
413          var $this = $(this),
414              $links = $this.find('.crumb'),
415              length = $links.length,
416              classes = ['wrapped-max', 'wrapped-wide', 'wrapped-medium', 'wrapped-small', 'wrapped-tiny'],
417              classesLength = classes.length,
418              maxHeight = 0,
419              lastWidth = false,
420              wrapped = false;
421   
422          // Set tooltips
423          $this.find('a').each(function() {
424              var $link = $(this);
425              $link.attr('title', $link.text());
426          });
427   
428          // Function that checks breadcrumbs
429          function check() {
430              var height = $this.height(),
431                  width;
432   
433              // Test max-width set in code for .navlinks above
434              width = parseInt($this.css('max-width'), 10);
435              if (!width) {
436                  width = $body.width();
437              }
438   
439              maxHeight = parseInt($this.css('line-height'), 10);
440              $links.each(function() {
441                  if ($(this).height() > 0) {
442                      maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
443                  }
444              });
445   
446              if (height <= maxHeight) {
447                  if (!wrapped || lastWidth === false || lastWidth >= width) {
448                      return;
449                  }
450              }
451              lastWidth = width;
452   
453              if (wrapped) {
454                  $this.removeClass('wrapped').find('.crumb.wrapped').removeClass('wrapped ' + classes.join(' '));
455                  if ($this.height() <= maxHeight) {
456                      return;
457                  }
458              }
459   
460              wrapped = true;
461              $this.addClass('wrapped');
462              if ($this.height() <= maxHeight) {
463                  return;
464              }
465   
466              for (var i = 0; i < classesLength; i++) {
467                  for (var j = length - 1; j >= 0; j--) {
468                      $links.eq(j).addClass('wrapped ' + classes[i]);
469                      if ($this.height() <= maxHeight) {
470                          return;
471                      }
472                  }
473              }
474          }
475   
476          // Run function and set event
477          check();
478          $(window).resize(check);
479      });
480   
481      /**
482      * Responsive link lists
483      */
484      var selector = '.linklist:not(.navlinks, [data-skip-responsive]),' +
485          '.postbody .post-buttons:not([data-skip-responsive])';
486      $container.find(selector).each(function() {
487          var $this = $(this),
488              filterSkip = '.breadcrumbs, [data-skip-responsive]',
489              filterLast = '.edit-icon, .quote-icon, [data-last-responsive]',
490              $linksAll = $this.children(),
491              $linksNotSkip = $linksAll.not(filterSkip), // All items that can potentially be hidden
492              $linksFirst = $linksNotSkip.not(filterLast), // The items that will be hidden first
493              $linksLast = $linksNotSkip.filter(filterLast), // The items that will be hidden last
494              persistent = $this.attr('id') === 'nav-main', // Does this list already have a menu (such as quick-links)?
495              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><ul class="dropdown-contents" /></div></li>',
496              slack = 3; // Vertical slack space (in pixels). Determines how sensitive the script is in determining whether a line-break has occured.
497   
498          // Add a hidden drop-down menu to each links list (except those that already have one)
499          if (!persistent) {
500              if ($linksNotSkip.is('.rightside')) {
501                  $linksNotSkip.filter('.rightside:first').before(html);
502                  $this.children('.responsive-menu').addClass('rightside');
503              } else {
504                  $this.append(html);
505              }
506          }
507   
508          // Set some object references and initial states
509          var $menu = $this.children('.responsive-menu'),
510              $menuContents = $menu.find('.dropdown-contents'),
511              persistentContent = $menuContents.find('li:not(.separator)').length,
512              lastWidth = false,
513              compact = false,
514              responsive1 = false,
515              responsive2 = false,
516              copied1 = false,
517              copied2 = false,
518              maxHeight = 0;
519   
520          // Find the tallest element in the list (we assume that all elements are roughly the same height)
521          $linksAll.each(function() {
522              if (!$(this).height()) {
523                  return;
524              }
525              maxHeight = Math.max(maxHeight, $(this).outerHeight(true));
526          });
527          if (maxHeight < 1) {
528              return; // Shouldn't be possible, but just in case, abort
529          } else {
530              maxHeight = maxHeight + slack;
531          }
532   
533          function check() {
534              var width = $body.width();
535              // We can't make it any smaller than this, so just skip
536              if (responsive2 && compact && (width <= lastWidth)) {
537                  return;
538              }
539              lastWidth = width;
540   
541              // Reset responsive and compact layout
542              if (responsive1 || responsive2) {
543                  $linksNotSkip.removeClass('hidden');
544                  $menuContents.children('.clone').addClass('hidden');
545                  responsive1 = responsive2 = false;
546              }
547              if (compact) {
548                  $this.removeClass('compact');
549                  compact = false;
550              }
551   
552              // Unhide the quick-links menu if it has "persistent" content
553              if (persistent && persistentContent) {
554                  $menu.removeClass('hidden');
555              } else {
556                  $menu.addClass('hidden');
557              }
558   
559              // Nothing to resize if block's height is not bigger than tallest element's height
560              if ($this.height() <= maxHeight) {
561                  return;
562              }
563   
564              // STEP 1: Compact
565              if (!compact) {
566                  $this.addClass('compact');
567                  compact = true;
568              }
569              if ($this.height() <= maxHeight) {
570                  return;
571              }
572   
573              // STEP 2: First responsive set - compact
574              if (compact) {
575                  $this.removeClass('compact');
576                  compact = false;
577              }
578              // Copy the list items to the dropdown
579              if (!copied1) {
580                  var $clones1 = $linksFirst.clone();
581                  $menuContents.prepend($clones1.addClass('clone clone-first').removeClass('leftside rightside'));
582   
583                  if ($this.hasClass('post-buttons')) {
584                      $('.button', $menuContents).removeClass('button');
585                      $('.sr-only', $menuContents).removeClass('sr-only');
586                      $('.js-responsive-menu-link').addClass('button').addClass('button-icon-only');
587                      $('.js-responsive-menu-link .icon').removeClass('fa-bars').addClass('fa-ellipsis-h');
588                  }
589                  copied1 = true;
590              }
591              if (!responsive1) {
592                  $linksFirst.addClass('hidden');
593                  responsive1 = true;
594                  $menuContents.children('.clone-first').removeClass('hidden');
595                  $menu.removeClass('hidden');
596              }
597              if ($this.height() <= maxHeight) {
598                  return;
599              }
600   
601              // STEP 3: First responsive set + compact
602              if (!compact) {
603                  $this.addClass('compact');
604                  compact = true;
605              }
606              if ($this.height() <= maxHeight) {
607                  return;
608              }
609   
610              // STEP 4: Last responsive set - compact
611              if (!$linksLast.length) {
612                  return; // No other links to hide, can't do more
613              }
614              if (compact) {
615                  $this.removeClass('compact');
616                  compact = false;
617              }
618              // Copy the list items to the dropdown
619              if (!copied2) {
620                  var $clones2 = $linksLast.clone();
621                  $menuContents.prepend($clones2.addClass('clone clone-last').removeClass('leftside rightside'));
622                  copied2 = true;
623              }
624              if (!responsive2) {
625                  $linksLast.addClass('hidden');
626                  responsive2 = true;
627                  $menuContents.children('.clone-last').removeClass('hidden');
628              }
629              if ($this.height() <= maxHeight) {
630                  return;
631              }
632   
633              // STEP 5: Last responsive set + compact
634              if (!compact) {
635                  $this.addClass('compact');
636                  compact = true;
637              }
638          }
639   
640          if (!persistent) {
641              phpbb.registerDropdown($menu.find('a.js-responsive-menu-link'), $menu.find('.dropdown'), false);
642          }
643   
644          // If there are any images in the links list, run the check again after they have loaded
645          $linksAll.find('img').each(function() {
646              $(this).load(function() {
647                  check();
648              });
649          });
650   
651          check();
652          $(window).resize(check);
653      });
654   
655      /**
656      * Do not run functions below for old browsers
657      */
658      if (oldBrowser) {
659          return;
660      }
661   
662      /**
663      * Adjust topiclist lists with check boxes
664      */
665      $container.find('ul.topiclist dd.mark').siblings('dt').children('.list-inner').addClass('with-mark');
666   
667      /**
668      * Appends contents of all extra columns to first column in
669      * .topiclist lists for mobile devices. Copies contents as is.
670      *
671      * To add that functionality to .topiclist list simply add
672      * responsive-show-all to list of classes
673      */
674      $container.find('.topiclist.responsive-show-all > li > dl').each(function() {
675          var $this = $(this),
676              $block = $this.find('dt .responsive-show:last-child'),
677              first = true;
678   
679          // Create block that is visible only on mobile devices
680          if (!$block.length) {
681              $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
682              $block = $this.find('dt .responsive-show:last-child');
683          } else {
684              first = ($.trim($block.text()).length === 0);
685          }
686   
687          // Copy contents of each column
688          $this.find('dd').not('.mark').each(function() {
689              var column = $(this),
690                  $children = column.children(),
691                  html = column.html();
692   
693              if ($children.length === 1 && $children.text() === column.text()) {
694                  html = $children.html();
695              }
696   
697              $block.append((first ? '' : '<br />') + html);
698   
699              first = false;
700          });
701      });
702   
703      /**
704      * Same as above, but prepends text from header to each
705      * column before contents of that column.
706      *
707      * To add that functionality to .topiclist list simply add
708      * responsive-show-columns to list of classes
709      */
710      $container.find('.topiclist.responsive-show-columns').each(function() {
711          var $list = $(this),
712              headers = [],
713              headersLength = 0;
714   
715          // Find all headers, get contents
716          $list.prev('.topiclist').find('li.header dd').not('.mark').each(function() {
717              headers.push($(this).text());
718              headersLength++;
719          });
720   
721          if (!headersLength) {
722              return;
723          }
724   
725          // Parse each row
726          $list.find('dl').each(function() {
727              var $this = $(this),
728                  $block = $this.find('dt .responsive-show:last-child'),
729                  first = true;
730   
731              // Create block that is visible only on mobile devices
732              if (!$block.length) {
733                  $this.find('dt > .list-inner').append('<div class="responsive-show" style="display:none;" />');
734                  $block = $this.find('dt .responsive-show:last-child');
735              } else {
736                  first = ($.trim($block.text()).length === 0);
737              }
738   
739              // Copy contents of each column
740              $this.find('dd').not('.mark').each(function(i) {
741                  var column = $(this),
742                      children = column.children(),
743                      html = column.html();
744   
745                  if (children.length === 1 && children.text() === column.text()) {
746                      html = children.html();
747                  }
748   
749                  // Prepend contents of matching header before contents of column
750                  if (i < headersLength) {
751                      html = headers[i] + ': <strong>' + html + '</strong>';
752                  }
753   
754                  $block.append((first ? '' : '<br />') + html);
755   
756                  first = false;
757              });
758          });
759      });
760   
761      /**
762      * Responsive tables
763      */
764      $container.find('table.table1').not('.not-responsive').each(function() {
765          var $this = $(this),
766              $th = $this.find('thead > tr > th'),
767              headers = [],
768              totalHeaders = 0,
769              i, headersLength;
770   
771          // Find each header
772          $th.each(function(column) {
773              var cell = $(this),
774                  colspan = parseInt(cell.attr('colspan'), 10),
775                  dfn = cell.attr('data-dfn'),
776                  text = dfn ? dfn : cell.text();
777   
778              colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
779   
780              for (i = 0; i < colspan; i++) {
781                  headers.push(text);
782              }
783              totalHeaders++;
784   
785              if (dfn && !column) {
786                  $this.addClass('show-header');
787              }
788          });
789   
790          headersLength = headers.length;
791   
792          // Add header text to each cell as <dfn>
793          $this.addClass('responsive');
794   
795          if (totalHeaders < 2) {
796              $this.addClass('show-header');
797              return;
798          }
799   
800          $this.find('tbody > tr').each(function() {
801              var row = $(this),
802                  cells = row.children('td'),
803                  column = 0;
804   
805              if (cells.length === 1) {
806                  row.addClass('big-column');
807                  return;
808              }
809   
810              cells.each(function() {
811                  var cell = $(this),
812                      colspan = parseInt(cell.attr('colspan'), 10),
813                      text = $.trim(cell.text());
814   
815                  if (headersLength <= column) {
816                      return;
817                  }
818   
819                  if ((text.length && text !== '-') || cell.children().length) {
820                      cell.prepend('<dfn style="display: none;">' + headers[column] + '</dfn>');
821                  } else {
822                      cell.addClass('empty');
823                  }
824   
825                  colspan = isNaN(colspan) || colspan < 1 ? 1 : colspan;
826                  column += colspan;
827              });
828          });
829      });
830   
831      /**
832      * Hide empty responsive tables
833      */
834      $container.find('table.responsive > tbody').not('.responsive-skip-empty').each(function() {
835          var $items = $(this).children('tr');
836          if (!$items.length) {
837              $(this).parent('table:first').addClass('responsive-hide');
838          }
839      });
840   
841      /**
842      * Responsive tabs
843      */
844      $container.find('#tabs, #minitabs').not('[data-skip-responsive]').each(function() {
845          var $this = $(this),
846              $ul = $this.children(),
847              $tabs = $ul.children().not('[data-skip-responsive]'),
848              $links = $tabs.children('a'),
849              $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><ul class="dropdown-contents" /></div></li>').find('li.responsive-tab'),
850              $menu = $item.find('.dropdown-contents'),
851              maxHeight = 0,
852              lastWidth = false,
853              responsive = false;
854   
855          $links.each(function() {
856              var $this = $(this);
857              maxHeight = Math.max(maxHeight, Math.max($this.outerHeight(true), $this.parent().outerHeight(true)));
858          });
859   
860          function check() {
861              var width = $body.width(),
862                  height = $this.height();
863   
864              if (!arguments.length && (!responsive || width <= lastWidth) && height <= maxHeight) {
865                  return;
866              }
867   
868              $tabs.show();
869              $item.hide();
870   
871              lastWidth = width;
872              height = $this.height();
873              if (height <= maxHeight) {
874                  if ($item.hasClass('dropdown-visible')) {
875                      phpbb.toggleDropdown.call($item.find('a.responsive-tab-link').get(0));
876                  }
877                  return;
878              }
879   
880              responsive = true;
881              $item.show();
882              $menu.html('');
883   
884              var $availableTabs = $tabs.filter(':not(.activetab, .responsive-tab)'),
885                  total = $availableTabs.length,
886                  i, $tab;
887   
888              for (i = total - 1; i >= 0; i--) {
889                  $tab = $availableTabs.eq(i);
890                  $menu.prepend($tab.clone(true).removeClass('tab'));
891                  $tab.hide();
892                  if ($this.height() <= maxHeight) {
893                      $menu.find('a').click(function() {
894                          check(true);
895                      });
896                      return;
897                  }
898              }
899              $menu.find('a').click(function() {
900                  check(true);
901              });
902          }
903   
904          var $tabLink = $item.find('a.responsive-tab-link');
905          phpbb.registerDropdown($tabLink, $item.find('.dropdown'), {
906              visibleClass: 'activetab'
907          });
908   
909          check(true);
910          $(window).resize(check);
911      });
912   
913      /**
914       * Hide UCP/MCP navigation if there is only 1 item
915       */
916      $container.find('#navigation').each(function() {
917          var $items = $(this).children('ol, ul').children('li');
918          if ($items.length === 1) {
919              $(this).addClass('responsive-hide');
920          }
921      });
922   
923      /**
924      * Replace responsive text
925      */
926      $container.find('[data-responsive-text]').each(function() {
927          var $this = $(this),
928              fullText = $this.text(),
929              responsiveText = $this.attr('data-responsive-text'),
930              responsive = false;
931   
932          function check() {
933              if ($(window).width() > 700) {
934                  if (!responsive) {
935                      return;
936                  }
937                  $this.text(fullText);
938                  responsive = false;
939                  return;
940              }
941              if (responsive) {
942                  return;
943              }
944              $this.text(responsiveText);
945              responsive = true;
946          }
947   
948          check();
949          $(window).resize(check);
950      });
951  }
952   
953  /**
954  * Run onload functions
955  */
956  jQuery(function($) {
957      'use strict';
958   
959      // Swap .nojs and .hasjs
960      $('#phpbb.nojs').toggleClass('nojs hasjs');
961      $('#phpbb').toggleClass('hastouch', phpbb.isTouch);
962      $('#phpbb.hastouch').removeClass('notouch');
963   
964      // Focus forms
965      $('form[data-focus]:first').each(function() {
966          $('#' + this.getAttribute('data-focus')).focus();
967      });
968   
969      parseDocument($('body'));
970  });
971