PageSourceSearch

https://marytavyparishcouncil.gov.uk/wp-content/plugins/pcw-core/modules/js/link-behavior.js

js marytavyparishcouncil.gov.uk collected 2026-10-10 01:46:35 UTC 2,956 bytes, 87 lines download raw bytes

1/**
2 * Link Behavior Enhancements
3 * - Optionally adds icon to external links
4 * - Ensures PDFs open in a new tab
5 * - Normalizes mailto: links to use target="_self"
6 * - Adds "(opens in new tab)" to aria-label for links opening in a new tab
7 */
8jQuery(document).ready(function($) {
9    const settings = window.pcwLinkBehaviorSettings || {};
10    const enableExternalIcon = !!settings.enableExternalIcon;
11    const forceExternalNewTab = !!settings.forceExternalNewTab;
12    const newTabSuffix = ' (opens in new tab)';
13
14    const ensureRelTokens = function($link, requiredTokens) {
15        const existingRel = ($link.attr('rel') || '').trim();
16        const parts = existingRel ? existingRel.split(/\s+/) : [];
17        const lower = parts.map(token => token.toLowerCase());
18
19        requiredTokens.forEach(token => {
20            if (!lower.includes(token)) {
21                parts.push(token);
22            }
23        });
24
25        $link.attr('rel', parts.join(' ').trim());
26    };
27
28    const addNewTabAriaLabel = function($link) {
29        const existing = ($link.attr('aria-label') || '').trim();
30        if (existing) {
31            if (!/opens in new tab/i.test(existing)) {
32                $link.attr('aria-label', existing + newTabSuffix);
33            }
34            return;
35        }
36
37        const text = ($link.text() || '').trim();
38        const labelBase = text ? text : 'Link';
39        $link.attr('aria-label', labelBase + newTabSuffix);
40    };
41
42    if (forceExternalNewTab) {
43        $('a[href]').each(function() {
44            const $link = $(this);
45            const href = ($link.attr('href') || '').trim();
46
47            // Only force normal web links (http/https and protocol-relative)
48            if (!/^(https?:)?\/\//i.test(href)) {
49                return;
50            }
51
52            const isExternal = this.hostname && this.hostname !== window.location.hostname;
53            if (!isExternal) {
54                return;
55            }
56
57            $link.attr('target', '_blank');
58            ensureRelTokens($link, ['noopener', 'noreferrer']);
59        });
60    }
61
62    $('a[target="_blank"]').each(function() {
63        const $link = $(this);
64        addNewTabAriaLabel($link);
65
66        if (!enableExternalIcon) {
67            return;
68        }
69
70        const isExternal = this.hostname !== window.location.hostname;
71        if (isExternal && !$link.hasClass('external-icon')) {
72            const icon = $('<span aria-hidden="true">↗</span>').css({marginLeft: '4px'});
73            $link.addClass('external-icon').append(icon);
74        }
75    });
76
77    $('a[href$=".pdf"]').each(function() {
78        const $link = $(this);
79        $link.attr('target', '_blank');
80        ensureRelTokens($link, ['noopener', 'noreferrer']);
81        addNewTabAriaLabel($link);
82    });
83
84    $('a[href^="mailto:"]').each(function() {
85        $(this).attr('target', '_self');
86    });
87});

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.