PageSourceSearch

https://www.medioq.com/js/facebook-picture-placeholder.js?v=6

js medioq.com collected 2026-10-02 06:57:49 UTC 5,992 bytes, 131 lines download raw bytes

1(function () {
2    'use strict';
3
4    var placeholderHash = '376c362ac05909bf7e992d71ee25519c7218b46d810b5c24e49710f061eee485';
5    var checks = new Map();
6    var hiddenImages = new WeakMap();
7
8    function hideFailedDescriptionImage(img) {
9        if (img && img.tagName === 'IMG' && img.complete && img.naturalWidth === 0 &&
10            img.closest('[data-description-pictures]')) {
11            img.hidden = true;
12            img.style.setProperty('display', 'none', 'important');
13        }
14    }
15
16    function createInitials(img) {
17        if (!img.hasAttribute('data-listing-initials')) { return null; }
18        var name = (img.alt || '').trim();
19        var initials = name.split(/\s+/).map(function (word) {
20            var first = word.match(/[\p{L}\p{N}]/u);
21            return first ? first[0].toUpperCase() : '';
22        }).filter(Boolean).slice(0, 3).join('');
23        if (!initials || !img.parentNode) { return null; }
24        var placeholder = document.createElement('span');
25        var size = img.offsetWidth || img.width || 100;
26        var layout = window.getComputedStyle(img);
27        placeholder.className = 'listing-picture-initials';
28        placeholder.textContent = initials;
29        placeholder.setAttribute('role', 'img');
30        placeholder.setAttribute('aria-label', name);
31        placeholder.style.width = size + 'px';
32        placeholder.style.height = size + 'px';
33        placeholder.style.fontSize = Math.max(10, size * 0.28) + 'px';
34        // Older cards position and space their pictures with img-only rules.
35        // Preserve that outer layout and the template's image corner shape.
36        ['cssFloat', 'clear', 'marginTop', 'marginRight', 'marginBottom', 'marginLeft',
37            'verticalAlign', 'alignSelf', 'order', 'borderTopLeftRadius',
38            'borderTopRightRadius', 'borderBottomRightRadius', 'borderBottomLeftRadius'].forEach(function (property) {
39            placeholder.style[property] = layout[property];
40        });
41        placeholder.style.display = layout.display === 'block' ? 'flex' : 'inline-flex';
42        img.parentNode.insertBefore(placeholder, img);
43        return placeholder;
44    }
45
46    function checkImage(img) {
47        if (!img || img.tagName !== 'IMG') {
48            return;
49        }
50        var source = img.currentSrc || img.src;
51        var previous = hiddenImages.get(img);
52        // Account uploads reuse the image element. Undo only our own hiding.
53        if (previous && previous.source !== source) {
54            if (previous.placeholder) { previous.placeholder.remove(); }
55            img.hidden = previous.hidden;
56            if (previous.display) {
57                img.style.setProperty('display', previous.display, previous.priority);
58            } else {
59                img.style.removeProperty('display');
60            }
61            hiddenImages.delete(img);
62        }
63        if (img.naturalWidth !== 198 || img.naturalHeight !== 126) {
64            return;
65        }
66        if (!/^https:\/\/graph\.facebook\.com\/(?:v\d+\.\d+\/)?\d+\/picture(?:\?|$)/i.test(source)) {
67            return;
68        }
69        if (!window.fetch || !window.crypto || !window.crypto.subtle || !window.AbortController) {
70            return;
71        }
72
73        // Share verification between repeated pictures on the same page.
74        if (!checks.has(source)) {
75            var controller = new AbortController();
76            var timeout = window.setTimeout(function () { controller.abort(); }, 5000);
77            var check = window.fetch(source, { credentials: 'omit', signal: controller.signal })
78                .then(function (response) {
79                    if (!response.ok) { return null; }
80                    return response.blob();
81                })
82                .then(function (blob) {
83                    if (!blob || blob.size !== 2380) { return null; }
84                    return blob.arrayBuffer();
85                })
86                .then(function (bytes) {
87                    if (!bytes) { return null; }
88                    return window.crypto.subtle.digest('SHA-256', bytes);
89                })
90                .then(function (hash) {
91                    if (!hash) { return false; }
92                    return Array.prototype.map.call(new Uint8Array(hash), function (byte) {
93                        return ('0' + byte.toString(16)).slice(-2);
94                    }).join('') === placeholderHash;
95                })
96                .catch(function () { return false; })
97                .then(function (matches) {
98                    window.clearTimeout(timeout);
99                    return matches;
100                });
101            checks.set(source, check);
102        }
103        checks.get(source).then(function (matches) {
104            // Do not hide a replacement uploaded while verification was pending.
105            if (matches && (img.currentSrc || img.src) === source) {
106                if (!hiddenImages.has(img)) {
107                    hiddenImages.set(img, {
108                        source: source,
109                        hidden: img.hidden,
110                        display: img.style.getPropertyValue('display'),
111                        priority: img.style.getPropertyPriority('display'),
112                        placeholder: img.hidden ? null : createInitials(img)
113                    });
114                }
115                img.hidden = true;
116                img.style.setProperty('display', 'none', 'important');
117            }
118        });
119    }
120
121    // Capture image loads, including lazy-loaded pictures added later.
122    document.addEventListener('load', function (event) { checkImage(event.target); }, true);
123    document.addEventListener('error', function (event) { hideFailedDescriptionImage(event.target); }, true);
124    // The deferred script may run after cached images have already loaded.
125    Array.prototype.forEach.call(document.images, function (img) {
126        if (img.complete) {
127            hideFailedDescriptionImage(img);
128            checkImage(img);
129        }
130    });
131}());

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.