MediaWiki:Gadget-GalleryFilterExtension.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/**
* Filter any gallery by file-type
* @author [[User:Rillke]], 2011
* @author [[User:Perhelion]], 2017 (jQuery replaced for performance)
* @revision 22:31, 19 January 2018 (UTC)
* This code is jshint-valid!
* required modules: mediawiki.Title, mediawiki.util, mediawiki.page.ready
*/
/*global jQuery, mediaWiki*/
/*jshint curly:false, forin:false */
(function ($, mw) {
"use strict";
var boxes = [];
var ok = 0;
var GalleryFilterMIME = window.GalleryFilterMIME || 1;
var isCAT = mw.config.get('wgNamespaceNumber') === 14;
var content = ( isCAT ? $('#mw-category-media')[0] : null ) || $('#mw-content-text')[0];
var galleries = content.getElementsByClassName('gallery');
if (!galleries[0]) return;
for (var i = 0; i < galleries.length; i++) {
var gal = galleries[i].getElementsByClassName('gallerybox');
if (ok || gal.length > 3) ok = 1;
boxes.push(gal);
}
if (!ok) return;
function init() {
var boxByMIME = {}; // boxes by MIME-type
var mime = "unknown", ext;
// First, find out which types we have on the page.
// We do not use jQuery on start in a loop for performance.
for (var box in boxes) {
box = boxes[box];
for (var b = 0; b < box.length; b++) {
var li = box[b];
var t = li.getElementsByClassName('thumb')[0];
if (!t) continue;
ext = mime = "other";
var e = t.getElementsByClassName('mw-file-description')[0];
if (e) ext = mime = "images";
else {
e = t.querySelector('.PopUpMediaTransform');
if (e) ext = mime = "videos";
}
if (e) {
e = e.getElementsByTagName('img')[0];
if (e)
ext = mw.Title.newFromImg(e).getExtension().toUpperCase().replace(/(?:(JP)E(G)|(TI)F(F))$/, '$1$2$3$4');
} else if(t.querySelector('audio, video, .mediaContainer')) {
ext = mime = t.querySelector('video') ? 'videos' : 'audios';
e = li.getElementsByClassName('galleryfilename')[0]; // exists also on non categories
if (e && e.title)
ext = e.title.match(/\.([^\. ]{2,5})$/)[1].toUpperCase();
} // else other?
if (!boxByMIME[mime]) boxByMIME[mime] = {};
if (!boxByMIME[mime][ext]) boxByMIME[mime][ext] = [];
boxByMIME[mime][ext].push(li);
}
}
// Don't show selection if only one file-type
if (Object.keys(boxByMIME).length === 1 && Object.keys(boxByMIME[mime]).length === 1) return;
function showAll(list) {
$.each(list, function(i, box) {
$(box).show();
});
}
// Then, build a select and bind the change-event
var $select = $('<select id="galleryFilterExt">').on('change', function (e) {
var ext = this.value;
if ('all' === ext)
return showAll(boxes);
var sel = this.options[this.selectedIndex];
if (sel.className === 'optionGroup')
$.each(boxByMIME, function(value, boxesOfMIME) {
if (ext === value) {
showAll(boxesOfMIME);
} else $.each(boxesOfMIME, function(i, boxesOfExt) {
$(boxesOfExt).hide();
});
});
else {
var type = sel.getAttribute('name');
if (!type) return;
$.each(boxByMIME, function(mime, boxesOfExt) {
var selBoxes = boxByMIME[mime];
$.each(selBoxes, function(value, boxesOfExt) {
if (ext === value && mime === type) {
$(boxesOfExt).show();
} else {
$(boxesOfExt).hide();
}
});
});
}
});
var all = 0;
var opt = 1; // Only for groups
var width = 0; // For absolute
for (var type in boxByMIME) {
$select.append($('<option>', {
// value: mime,
'class': "optionGroup",
'text': type
})
);
opt++;
for (var fext in boxByMIME[type]) {
var cnt = boxByMIME[type][fext].length;
all += cnt;
opt++;
$select.append($('<option>', {
'class': "optionChild",
'value': fext,
'name': type, // sure?
'text': fext + ' (' + cnt + ')'
})
);
}
}
$select.append($('<option>', {
selected: 'selected',
value: 'all',
text: mw.msg("Pagetriage-filter-all") + (isCAT ? '' : ' (' + all + ')')
})).css({
margin: '0 5px'
// display: 'inline-block'
});
if (!GalleryFilterMIME || Object.keys(boxByMIME).length === 1) { // Remove MIME select
GalleryFilterMIME = 0;
$select.find(".optionGroup").remove();
width = 1;
} else {
mw.util.addCSS(
'.optionGroup{font-weight:bold;font-style:italic;}\n.optionChild{padding-left:15px;}');
$select.css({
position: 'absolute',
zIndex: 9
}).on('focus', function (e) {
e = $(this);
e.height(opt * e.height());
e.one('change', function (e) {
if (this.multiple) return $(this).blur();
}).one('blur', function (e) {
this.multiple = false;
$(this).height('auto');
});
this.multiple = true;
});
}
isCAT = isCAT ? content.getElementsByTagName('h2')[0] : 0;
if (isCAT) {
var p = $(isCAT).next(); // content.getElementsByTagName('p')[0];
if (p && p.prop("tagName") === 'P') {
p.prepend($select); // p.insertBefore($select[0], p.firstChild);
if (GalleryFilterMIME) {
width = $select.outerWidth() + 5; // width first after insert
p.css({ 'paddingLeft': width + 5 });
$select.offset({ left: $select.offset().left - width - 5 });
}
} else {
content.insertBefore(
$select[0],
content.getElementsByTagName('h2')[0].nextSibling);
}
} else {
content.insertBefore($select[0], content.firstChild);
}
if (!width)
$select.wrap($("<p>").css({
width: $select.outerWidth(),
height: $select.outerHeight()
})
);
}
$.when(mw.loader.using('mediawiki.api'), $.ready).then(function () {
return new mw.Api().loadMessagesIfMissing(['Pagetriage-filter-all']);
}).then(init);
}(jQuery, mediaWiki));