MediaWiki:Common.js: Difference between revisions

From GDPRhub
(Finish code for putting random banner above pages)
(Fetch integromat-created news.json instead of using NewestPages+opengraph)
Line 24: Line 24:
if (newOnGdprHubContainer) loadNewOnGdprHubItems(); // only on the main page
if (newOnGdprHubContainer) loadNewOnGdprHubItems(); // only on the main page
function loadNewOnGdprHubItems() {
function loadNewOnGdprHubItems() {
items = Array.from(newOnGdprHubContainer.querySelectorAll('li a'));
items = Array.from(newOnGdprHubContainer.querySelectorAll('li'));
var parser = new DOMParser();
    items.forEach(function (item) {
var promises = items.map(function (item) {
    item.classList.add('preview-loading');
var pageTitle = item.textContent;
    });
updateContent(item, {
return fetch('/gdprhubomatic/news.json')
title: pageTitle,
.then(function (response) {
});
if (!response.ok) throw new Error('fetch got ' + response.status);
item.classList.add('preview-loading');
return response.json();
var pageUrl = '/index.php?title=' + encodeURIComponent(pageTitle);
}).then(function (json) {
return fetch(pageUrl)
// remove incomplete entries
.then(function (response) {
json = json.filter(function (obj) {
if (!response.ok) throw new Error('fetch got ' + response.status);
return obj['Page Title'];
return response.text();
});
}).then(function (html) {
// for each card, render content of a json item
// Cut off html source to only parse content of each page’s <head>
items.forEach(function (item, i) {
html = html.slice(0, html.indexOf('</head>'));
var jsonItem = json[i];
var dom = parser.parseFromString(html, 'text/html');
if (jsonItem === undefined) item.remove();
 
var props = {
var props = getOpenGraphData(dom, ['title', 'description', 'image']);
href: jsonItem['URL'],
props.title = pageTitle; // overwrite title to keep title of redirects
description: jsonItem['Summary'],
image: jsonItem['Logo URL'],
title: jsonItem['Page Title'],
};
updateContent(item, props);
updateContent(item, props);
item.classList.add('preview-loaded');
item.classList.add('preview-loaded');
item.classList.add('preview-loading');
item.classList.remove('preview-loading');
}).catch(function (error) {
console.log('Failed to load page preview for "' + pageTitle + '": ' + error);
updateContent(item, {
title: pageTitle,
description: '',
});
});
});
});
}).catch(function (error) {
return Promise.all(promises);
console.log('Failed to fetch/display “new on gdprhub” items: ' + error.message);
});


function updateContent(item, props) {
function updateContent(item, props) {
item.innerHTML =
item.innerHTML =
'<div class="card-text">'
'<a href="' + (props.href ? props.href : '#') + '">'
+ (props.title ? '<h4 class="card-title">' + props.title + '</h4>' : '')
+ '<div class="card-text">'
+ (props.description ? '<p class="card-description">' + props.description + '</p>' : '')
+ (props.title ? '<h3 class="card-title">' + props.title + '</h3>' : '')
+ '</div>'
+ (props.description ? '<p class="card-description">' + props.description + '</p>' : '')
+ '<div class="card-image">'
+ '</div>'
+ (props.image ? '<img src="' + props.image + '"/>' : '')
+ '<div class="card-image">'
+ '</div>'
+ (props.image ? '<img src="' + props.image + '"/>' : '')
+ '</div>'
+ '</a>'
;
;
}
function getOpenGraphData(dom, propertyNames) {
var ns = 'og'; // techinaclly we should read this from an xmlns attribute.
var props = {};
    propertyNames.forEach(function (name) {
    var el = dom.head.querySelector('meta[property="' + ns + ':' + name + '"]');
    if (el) props[name] = el.content;
    });
    return props;
}
}
}
}

Revision as of 13:11, 26 July 2021

/* Any JavaScript here will be loaded for all users on every page load. */

/* Show random banner (see MediaWiki:Sitenotice, and MediaWiki:Common.css) */
var randomBannerContainers = Array.from(document.querySelectorAll('.random-banner-container'));
randomBannerContainers.forEach(function (randomBannerContainer) {
	var elements = randomBannerContainer.querySelectorAll('.random-banner-option');
	if (elements.length === 0) {
		randomBannerContainer.replaceChildren(); // remove any children
	} else {
		var index = Math.floor(Math.random() * elements.length);
		randomBannerContainer.replaceChildren(elements[index]);
	}
	randomBannerContainer.classList.add('ready');
});

/* “New on GDPRhub” list on main page
 Functionality defined by multiple pieces: 
 - the NewPages extension
 - MediaWiki:Common.js to load the content to preview
	- relies on OpenGraphMeta+Description2 extensions to provide those contents
 - MediaWiki:Common.css to style the items as cards
*/
var newOnGdprHubContainer = document.getElementById('new-on-gdprhub');
if (newOnGdprHubContainer) loadNewOnGdprHubItems(); // only on the main page
function loadNewOnGdprHubItems() {
	items = Array.from(newOnGdprHubContainer.querySelectorAll('li'));
    items.forEach(function (item) {
    	item.classList.add('preview-loading');
    });
	return fetch('/gdprhubomatic/news.json')
		.then(function (response) {
			if (!response.ok) throw new Error('fetch got ' + response.status);
			return response.json();
		}).then(function (json) {
			// remove incomplete entries
			json = json.filter(function (obj) {
				return obj['Page Title'];
			});
			// for each card, render content of a json item
			items.forEach(function (item, i) {
				var jsonItem = json[i];
				if (jsonItem === undefined) item.remove();
				var props = {
					href: jsonItem['URL'],
					description: jsonItem['Summary'],
					image: jsonItem['Logo URL'],
					title: jsonItem['Page Title'],
				};
				updateContent(item, props);
				item.classList.add('preview-loaded');
				item.classList.remove('preview-loading');
			});
		}).catch(function (error) {
			console.log('Failed to fetch/display “new on gdprhub” items: ' + error.message);
		});

	function updateContent(item, props) {
		item.innerHTML =
			'<a href="' + (props.href ? props.href : '#') + '">'
				+ '<div class="card-text">'
					+ (props.title ? '<h3 class="card-title">' + props.title + '</h3>' : '')
					+ (props.description ? '<p class="card-description">' + props.description + '</p>' : '')
				+ '</div>'
				+ '<div class="card-image">'
					+ (props.image ? '<img src="' + props.image + '"/>' : '')
				+ '</div>'
			+ '</a>'
		;
	}
}