Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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: 22.71 KiB


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