Common.js: Unterschied zwischen den Versionen
Aus exmediawiki
Die Seite wurde neu angelegt: „// MediaWiki Slideshow Gallery - PAGE SPECIFIC ONLY // Only loads on pages with slideshow-gallery-page class // Add this to MediaWiki:Common.js // Check if cu…“ |
Keine Bearbeitungszusammenfassung |
||
| (3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
// Material Archive Overview | |||
// Materials collapsible functionality with cursor tooltip and search | |||
$(document).ready(function() { | |||
// Only run on pages that have materials containers | |||
if ($('.materials-container').length === 0) { | |||
return; // Exit if no materials containers found | |||
} | |||
// Create navigation dynamically using custom tag with line breaks | |||
var navigationHtml ='<br><nav-item><a href="#search-section" class="nav-link">Search</a></nav-item><br>' + | |||
'<nav-item><a href="#materials-section" class="nav-link">Materials</a></nav-item><br>' + | |||
'<nav-item><a href="#resources-section" class="nav-link">Resources</a></nav-item><br>' + | |||
'<nav-item><a href="#about-section" class="nav-link">About</a></nav-item>' + | |||
'<br><br>'; | |||
// Insert navigation at the very top of the page content | |||
$('#mw-content-text').prepend(navigationHtml); | |||
// Create anchor points | |||
var anchorsHtml = '<div id="search-section"></div><div id="materials-section"></div>' + | |||
'<div id="resources-section"></div><div id="about-section"></div>'; | |||
// Insert anchor points before first materials container | |||
$('.materials-container').first().before(anchorsHtml); | |||
// Create search bar dynamically | |||
var searchHtml = '<div class="search-container">' + | |||
'<input type="text" id="material-search" placeholder="Search materials..." autocomplete="off">' + | |||
'<div class="search-suggestions"></div>' + | |||
'</div>'; | |||
// Insert search bar before the first materials container (after anchors) | |||
$('#search-section').after(searchHtml); | |||
// Navigation scroll functionality | |||
$(document).on('click', '.nav-link', function(e) { | |||
e.preventDefault(); | |||
var targetId = $(this).attr('href'); | |||
var $target = $(targetId); | |||
if ($target.length) { | |||
$('html, body').animate({ | |||
scrollTop: $target.offset().top - 20 // 20px offset from top | |||
}, 800); // 800ms smooth animation | |||
} | |||
}); | |||
// Initialize - hide all children AND sub-parents, ensure parents are collapsed | |||
$('.material-child').hide(); | |||
$('.material-parent[data-parent]').hide(); // Hide sub-parents (like Veneer) | |||
$('.material-parent').removeClass('expanded'); | |||
// Create tooltip element | |||
var $tooltip = $('<div class="cursor-image-tooltip"></div>'); | |||
$('body').append($tooltip); | |||
// Build search data from all material children | |||
var searchData = []; | |||
$('.material-child').each(function() { | |||
var $child = $(this); | |||
var title = $child.find('h3').text().replace(/\[\[|\]\]/g, ''); // Remove wiki brackets | |||
var parent = $child.data('parent'); | |||
var parentText = $('.material-parent[data-category="' + parent + '"] h3').text(); | |||
searchData.push({ | |||
title: title, | |||
element: $child, | |||
parent: parent, | |||
parentText: parentText, | |||
parentElement: $('.material-parent[data-category="' + parent + '"]') | |||
}); | |||
}); | |||
// Search functionality | |||
var $searchInput = $('#material-search'); | |||
var $searchSuggestions = $('.search-suggestions'); | |||
$searchInput.on('input', function() { | |||
var query = $(this).val().toLowerCase().trim(); | |||
if (query.length === 0) { | |||
$searchSuggestions.hide().empty(); | |||
return; | |||
} | |||
// Filter search data | |||
var matches = searchData.filter(function(item) { | |||
return item.title.toLowerCase().includes(query) || | |||
item.parentText.toLowerCase().includes(query); | |||
}); | |||
if (matches.length > 0) { | |||
$searchSuggestions.empty().show(); | |||
// Limit to first 8 results | |||
matches.slice(0, 8).forEach(function(match) { | |||
var $suggestion = $('<div class="search-suggestion"></div>'); | |||
$suggestion.html('<span class="suggestion-title">' + match.title + '</span>' + | |||
'<span class="suggestion-category">' + match.parentText + '</span>'); | |||
$suggestion.on('click', function() { | |||
// Expand parent if not expanded | |||
if (!match.parentElement.hasClass('expanded')) { | |||
match.parentElement.addClass('expanded'); | |||
$('.material-child[data-parent="' + match.parent + '"]').show(); | |||
} | |||
// Scroll to element | |||
$('html, body').animate({ | |||
scrollTop: match.element.offset().top - 100 | |||
}, 500); | |||
// Highlight element briefly | |||
match.element.addClass('highlighted'); | |||
setTimeout(function() { | |||
match.element.removeClass('highlighted'); | |||
}, 2000); | |||
// Clear search | |||
$searchInput.val(''); | |||
$searchSuggestions.hide().empty(); | |||
}); | |||
$searchSuggestions.append($suggestion); | |||
}); | |||
} else { | |||
$searchSuggestions.hide().empty(); | |||
} | |||
}); | |||
// Hide suggestions when clicking outside | |||
$(document).on('click', function(e) { | |||
if (!$(e.target).closest('.search-container').length) { | |||
$searchSuggestions.hide(); | |||
} | |||
}); | |||
// Handle material parent clicks | |||
$('.material-parent').on('click', function() { | |||
var $parent = $(this); | |||
var category = $parent.data('category'); | |||
// Toggle expanded state | |||
$parent.toggleClass('expanded'); | |||
// Show/hide direct children AND sub-parents | |||
var $directChildren = $('.material-child[data-parent="' + category + '"], .material-parent[data-parent="' + category + '"]'); | |||
if ($parent.hasClass('expanded')) { | |||
$directChildren.show(); | |||
} else { | |||
$directChildren.hide(); | |||
// When collapsing, also collapse and hide any sub-parents and their children | |||
$('.material-parent[data-parent="' + category + '"]').each(function() { | |||
var $subParent = $(this); | |||
var subCategory = $subParent.data('category'); | |||
// Remove expanded class from sub-parent | |||
$subParent.removeClass('expanded'); | |||
// Hide sub-parent's children | |||
$('.material-child[data-parent="' + subCategory + '"]').hide(); | |||
}); | |||
} | |||
}); | |||
// Handle cursor tooltip for material children | |||
$('.material-child').on('mouseenter', function(e) { | |||
var $child = $(this); | |||
var $imagePreview = $child.find('.image-preview'); | |||
if ($imagePreview.length > 0) { | |||
// Copy the image content to tooltip | |||
$tooltip.html($imagePreview.html()); | |||
$tooltip.show(); | |||
// Position tooltip with offset - image appears lower than cursor | |||
// Offset by half the image height (100px) plus some extra space | |||
$tooltip.css({ | |||
left: (e.clientX + 10) + 'px', // 10px right of cursor | |||
top: (e.clientY + 60) + 'px' // 60px below cursor (half height + spacing) | |||
}); | |||
} | |||
}); | |||
$('.material-child').on('mousemove', function(e) { | |||
if ($tooltip.is(':visible')) { | |||
// Follow cursor with consistent offset | |||
$tooltip.css({ | |||
left: (e.clientX + 10) + 'px', // 10px right of cursor | |||
top: (e.clientY + 60) + 'px' // 60px below cursor (half height + spacing) | |||
}); | |||
} | |||
}); | |||
$('.material-child').on('mouseleave', function() { | |||
$tooltip.hide(); | |||
}); | |||
}); | |||
// Individual material page | |||
// MediaWiki Slideshow Gallery - PAGE SPECIFIC ONLY | // MediaWiki Slideshow Gallery - PAGE SPECIFIC ONLY | ||
// Add this to MediaWiki:Common.js | // Add this to MediaWiki:Common.js | ||
// Check if current page should have slideshow functionality | (function() { | ||
function shouldLoadSlideshow() { | 'use strict'; | ||
// Check if current page should have slideshow functionality | |||
function shouldLoadSlideshow() { | |||
} | return document.body && ( | ||
document.body.classList.contains('slideshow-gallery-page') || | |||
document.querySelector('.slideshow-gallery-page') !== null || | |||
document.querySelector('.slideshow-container') !== null | |||
); | |||
} | |||
// Only load slideshow code if needed | |||
if (!shouldLoadSlideshow()) { | |||
return; | |||
} | |||
console.log('Loading slideshow gallery for this page'); | console.log('Loading slideshow gallery for this page'); | ||
$(document).ready(function() { | // Wait for MediaWiki and jQuery to be ready | ||
function initWhenReady() { | |||
if (typeof mw === 'undefined' || typeof $ === 'undefined') { | |||
setTimeout(initWhenReady, 100); | |||
return; | |||
} | |||
// MediaWiki hook | |||
mw.hook('wikipage.content').add(function($content) { | |||
initSlideshows($content); | |||
}); | |||
// jQuery ready | |||
$(document).ready(function() { | |||
initSlideshows($(document)); | |||
}); | |||
} | |||
function initSlideshows($context) { | function initSlideshows($context) { | ||
| Zeile 27: | Zeile 248: | ||
// Only initialize slideshow containers on pages with the specific class | // Only initialize slideshow containers on pages with the specific class | ||
var $galleryPages = $context.find('.slideshow-gallery-page, body.slideshow-gallery-page'); | |||
if ($galleryPages.length === 0 && !$context.hasClass('slideshow-gallery-page')) { | if ($galleryPages.length === 0 && !$context.hasClass('slideshow-gallery-page')) { | ||
// Also check for direct slideshow containers as fallback | // Also check for direct slideshow containers as fallback | ||
| Zeile 45: | Zeile 266: | ||
function initSingleSlideshow(container) { | function initSingleSlideshow(container) { | ||
var slides = container.querySelectorAll('.mySlides'); | |||
var thumbnails = container.querySelectorAll('.demo'); | |||
var captionText = container.querySelector('#caption, .caption'); | |||
var slideIndex = 1; | |||
console.log('Initializing slideshow with', slides.length, 'slides'); | console.log('Initializing slideshow with', slides.length, 'slides'); | ||
| Zeile 61: | Zeile 282: | ||
// Add click handlers to navigation buttons | // Add click handlers to navigation buttons | ||
var prevBtn = container.querySelector('.prev'); | |||
var nextBtn = container.querySelector('.next'); | |||
if (prevBtn) { | if (prevBtn) { | ||
| Zeile 79: | Zeile 300: | ||
// Add click handlers to thumbnails | // Add click handlers to thumbnails | ||
thumbnails. | for (var i = 0; i < thumbnails.length; i++) { | ||
(function(index) { | |||
thumbnails[index].addEventListener('click', function() { | |||
}); | currentSlide(index + 1); | ||
} | }); | ||
})(i); | |||
} | |||
// Keyboard navigation | // Keyboard navigation | ||
| Zeile 100: | Zeile 323: | ||
// Touch/swipe support | // Touch/swipe support | ||
var startX = 0; | |||
var endX = 0; | |||
container.addEventListener('touchstart', function(e) { | container.addEventListener('touchstart', function(e) { | ||
| Zeile 113: | Zeile 336: | ||
container.addEventListener('touchend', function(e) { | container.addEventListener('touchend', function(e) { | ||
endX = e.changedTouches[0].clientX; | endX = e.changedTouches[0].clientX; | ||
var diffX = startX - endX; | |||
if (Math.abs(diffX) > 50) { | if (Math.abs(diffX) > 50) { | ||
| Zeile 125: | Zeile 348: | ||
// Auto-play functionality (if data-autoplay attribute is set) | // Auto-play functionality (if data-autoplay attribute is set) | ||
var autoPlayInterval; | |||
var autoPlayDelay = container.getAttribute('data-autoplay'); | |||
if (autoPlayDelay) { | if (autoPlayDelay) { | ||
| Zeile 159: | Zeile 382: | ||
function showSlides(n) { | function showSlides(n) { | ||
var i; | |||
if (n > slides.length) { slideIndex = 1; } | if (n > slides.length) { | ||
if (n < 1) { slideIndex = slides.length; } | slideIndex = 1; | ||
} | |||
if (n < 1) { | |||
slideIndex = slides.length; | |||
} | |||
// Hide all slides | // Hide all slides | ||
| Zeile 194: | Zeile 421: | ||
} | } | ||
} | } | ||
// Start initialization | |||
} | initWhenReady(); | ||
})(); | |||
Aktuelle Version vom 24. Juli 2025, 13:57 Uhr
// Material Archive Overview
// Materials collapsible functionality with cursor tooltip and search
$(document).ready(function() {
// Only run on pages that have materials containers
if ($('.materials-container').length === 0) {
return; // Exit if no materials containers found
}
// Create navigation dynamically using custom tag with line breaks
var navigationHtml ='<br><nav-item><a href="#search-section" class="nav-link">Search</a></nav-item><br>' +
'<nav-item><a href="#materials-section" class="nav-link">Materials</a></nav-item><br>' +
'<nav-item><a href="#resources-section" class="nav-link">Resources</a></nav-item><br>' +
'<nav-item><a href="#about-section" class="nav-link">About</a></nav-item>' +
'<br><br>';
// Insert navigation at the very top of the page content
$('#mw-content-text').prepend(navigationHtml);
// Create anchor points
var anchorsHtml = '<div id="search-section"></div><div id="materials-section"></div>' +
'<div id="resources-section"></div><div id="about-section"></div>';
// Insert anchor points before first materials container
$('.materials-container').first().before(anchorsHtml);
// Create search bar dynamically
var searchHtml = '<div class="search-container">' +
'<input type="text" id="material-search" placeholder="Search materials..." autocomplete="off">' +
'<div class="search-suggestions"></div>' +
'</div>';
// Insert search bar before the first materials container (after anchors)
$('#search-section').after(searchHtml);
// Navigation scroll functionality
$(document).on('click', '.nav-link', function(e) {
e.preventDefault();
var targetId = $(this).attr('href');
var $target = $(targetId);
if ($target.length) {
$('html, body').animate({
scrollTop: $target.offset().top - 20 // 20px offset from top
}, 800); // 800ms smooth animation
}
});
// Initialize - hide all children AND sub-parents, ensure parents are collapsed
$('.material-child').hide();
$('.material-parent[data-parent]').hide(); // Hide sub-parents (like Veneer)
$('.material-parent').removeClass('expanded');
// Create tooltip element
var $tooltip = $('<div class="cursor-image-tooltip"></div>');
$('body').append($tooltip);
// Build search data from all material children
var searchData = [];
$('.material-child').each(function() {
var $child = $(this);
var title = $child.find('h3').text().replace(/\[\[|\]\]/g, ''); // Remove wiki brackets
var parent = $child.data('parent');
var parentText = $('.material-parent[data-category="' + parent + '"] h3').text();
searchData.push({
title: title,
element: $child,
parent: parent,
parentText: parentText,
parentElement: $('.material-parent[data-category="' + parent + '"]')
});
});
// Search functionality
var $searchInput = $('#material-search');
var $searchSuggestions = $('.search-suggestions');
$searchInput.on('input', function() {
var query = $(this).val().toLowerCase().trim();
if (query.length === 0) {
$searchSuggestions.hide().empty();
return;
}
// Filter search data
var matches = searchData.filter(function(item) {
return item.title.toLowerCase().includes(query) ||
item.parentText.toLowerCase().includes(query);
});
if (matches.length > 0) {
$searchSuggestions.empty().show();
// Limit to first 8 results
matches.slice(0, 8).forEach(function(match) {
var $suggestion = $('<div class="search-suggestion"></div>');
$suggestion.html('<span class="suggestion-title">' + match.title + '</span>' +
'<span class="suggestion-category">' + match.parentText + '</span>');
$suggestion.on('click', function() {
// Expand parent if not expanded
if (!match.parentElement.hasClass('expanded')) {
match.parentElement.addClass('expanded');
$('.material-child[data-parent="' + match.parent + '"]').show();
}
// Scroll to element
$('html, body').animate({
scrollTop: match.element.offset().top - 100
}, 500);
// Highlight element briefly
match.element.addClass('highlighted');
setTimeout(function() {
match.element.removeClass('highlighted');
}, 2000);
// Clear search
$searchInput.val('');
$searchSuggestions.hide().empty();
});
$searchSuggestions.append($suggestion);
});
} else {
$searchSuggestions.hide().empty();
}
});
// Hide suggestions when clicking outside
$(document).on('click', function(e) {
if (!$(e.target).closest('.search-container').length) {
$searchSuggestions.hide();
}
});
// Handle material parent clicks
$('.material-parent').on('click', function() {
var $parent = $(this);
var category = $parent.data('category');
// Toggle expanded state
$parent.toggleClass('expanded');
// Show/hide direct children AND sub-parents
var $directChildren = $('.material-child[data-parent="' + category + '"], .material-parent[data-parent="' + category + '"]');
if ($parent.hasClass('expanded')) {
$directChildren.show();
} else {
$directChildren.hide();
// When collapsing, also collapse and hide any sub-parents and their children
$('.material-parent[data-parent="' + category + '"]').each(function() {
var $subParent = $(this);
var subCategory = $subParent.data('category');
// Remove expanded class from sub-parent
$subParent.removeClass('expanded');
// Hide sub-parent's children
$('.material-child[data-parent="' + subCategory + '"]').hide();
});
}
});
// Handle cursor tooltip for material children
$('.material-child').on('mouseenter', function(e) {
var $child = $(this);
var $imagePreview = $child.find('.image-preview');
if ($imagePreview.length > 0) {
// Copy the image content to tooltip
$tooltip.html($imagePreview.html());
$tooltip.show();
// Position tooltip with offset - image appears lower than cursor
// Offset by half the image height (100px) plus some extra space
$tooltip.css({
left: (e.clientX + 10) + 'px', // 10px right of cursor
top: (e.clientY + 60) + 'px' // 60px below cursor (half height + spacing)
});
}
});
$('.material-child').on('mousemove', function(e) {
if ($tooltip.is(':visible')) {
// Follow cursor with consistent offset
$tooltip.css({
left: (e.clientX + 10) + 'px', // 10px right of cursor
top: (e.clientY + 60) + 'px' // 60px below cursor (half height + spacing)
});
}
});
$('.material-child').on('mouseleave', function() {
$tooltip.hide();
});
});
// Individual material page
// MediaWiki Slideshow Gallery - PAGE SPECIFIC ONLY
// Add this to MediaWiki:Common.js
(function() {
'use strict';
// Check if current page should have slideshow functionality
function shouldLoadSlideshow() {
return document.body && (
document.body.classList.contains('slideshow-gallery-page') ||
document.querySelector('.slideshow-gallery-page') !== null ||
document.querySelector('.slideshow-container') !== null
);
}
// Only load slideshow code if needed
if (!shouldLoadSlideshow()) {
return;
}
console.log('Loading slideshow gallery for this page');
// Wait for MediaWiki and jQuery to be ready
function initWhenReady() {
if (typeof mw === 'undefined' || typeof $ === 'undefined') {
setTimeout(initWhenReady, 100);
return;
}
// MediaWiki hook
mw.hook('wikipage.content').add(function($content) {
initSlideshows($content);
});
// jQuery ready
$(document).ready(function() {
initSlideshows($(document));
});
}
function initSlideshows($context) {
$context = $context || $(document);
// Only initialize slideshow containers on pages with the specific class
var $galleryPages = $context.find('.slideshow-gallery-page, body.slideshow-gallery-page');
if ($galleryPages.length === 0 && !$context.hasClass('slideshow-gallery-page')) {
// Also check for direct slideshow containers as fallback
if ($context.find('.slideshow-container').length === 0) {
return;
}
}
// Initialize each slideshow container
$context.find('.slideshow-container').each(function() {
if (!$(this).data('slideshow-initialized')) {
$(this).data('slideshow-initialized', true);
initSingleSlideshow(this);
}
});
}
function initSingleSlideshow(container) {
var slides = container.querySelectorAll('.mySlides');
var thumbnails = container.querySelectorAll('.demo');
var captionText = container.querySelector('#caption, .caption');
var slideIndex = 1;
console.log('Initializing slideshow with', slides.length, 'slides');
if (slides.length === 0) {
console.log('No slides found in slideshow container');
return;
}
// Show first slide initially
showSlides(slideIndex);
// Add click handlers to navigation buttons
var prevBtn = container.querySelector('.prev');
var nextBtn = container.querySelector('.next');
if (prevBtn) {
prevBtn.addEventListener('click', function(e) {
e.preventDefault();
plusSlides(-1);
});
}
if (nextBtn) {
nextBtn.addEventListener('click', function(e) {
e.preventDefault();
plusSlides(1);
});
}
// Add click handlers to thumbnails
for (var i = 0; i < thumbnails.length; i++) {
(function(index) {
thumbnails[index].addEventListener('click', function() {
currentSlide(index + 1);
});
})(i);
}
// Keyboard navigation
container.addEventListener('keydown', function(e) {
if (e.keyCode === 37) { // Left arrow
plusSlides(-1);
e.preventDefault();
} else if (e.keyCode === 39) { // Right arrow
plusSlides(1);
e.preventDefault();
}
});
// Make container focusable for keyboard navigation
container.setAttribute('tabindex', '0');
// Touch/swipe support
var startX = 0;
var endX = 0;
container.addEventListener('touchstart', function(e) {
startX = e.touches[0].clientX;
});
container.addEventListener('touchmove', function(e) {
e.preventDefault();
});
container.addEventListener('touchend', function(e) {
endX = e.changedTouches[0].clientX;
var diffX = startX - endX;
if (Math.abs(diffX) > 50) {
if (diffX > 0) {
plusSlides(1); // Swipe left = next
} else {
plusSlides(-1); // Swipe right = previous
}
}
});
// Auto-play functionality (if data-autoplay attribute is set)
var autoPlayInterval;
var autoPlayDelay = container.getAttribute('data-autoplay');
if (autoPlayDelay) {
function startAutoPlay() {
autoPlayInterval = setInterval(function() {
plusSlides(1);
}, parseInt(autoPlayDelay));
}
function stopAutoPlay() {
if (autoPlayInterval) {
clearInterval(autoPlayInterval);
autoPlayInterval = null;
}
}
container.addEventListener('mouseenter', stopAutoPlay);
container.addEventListener('mouseleave', startAutoPlay);
startAutoPlay();
}
// Next/previous controls
function plusSlides(n) {
showSlides(slideIndex += n);
}
// Thumbnail image controls
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
if (n > slides.length) {
slideIndex = 1;
}
if (n < 1) {
slideIndex = slides.length;
}
// Hide all slides
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
slides[i].classList.remove('active');
}
// Remove active class from all thumbnails
for (i = 0; i < thumbnails.length; i++) {
thumbnails[i].classList.remove('active-thumb');
}
// Show current slide
if (slides[slideIndex - 1]) {
slides[slideIndex - 1].style.display = "block";
slides[slideIndex - 1].classList.add('active');
}
// Highlight current thumbnail
if (thumbnails[slideIndex - 1]) {
thumbnails[slideIndex - 1].classList.add('active-thumb');
}
// Update caption
if (captionText && thumbnails[slideIndex - 1]) {
captionText.innerHTML = thumbnails[slideIndex - 1].getAttribute('alt') || '';
}
console.log('Showing slide', slideIndex, 'of', slides.length);
}
}
// Start initialization
initWhenReady();
})();