PageSourceSearch

https://www.dolmorgul.de/forum/styles/DolMorgul/template/forum_fn.js?assets_version=17

js dolmorgul.de collected 2026-09-26 04:16:10 UTC 23,422 bytes, 941 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.