User:SunAfterRain/GallerySlideshow/setting.js
(Redirected from User:Sunny00217/GallerySlideshow/setting.js)
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:SunAfterRain/GallerySlideshow/setting. |
//https://commons.wikimedia.org/w/index.php?title=MediaWiki:GallerySlideshow.js&oldid=255240758
//mw.loader.load('//zh.wikipedia.org/w/load.php?modules=ext.gadget.site-lib');
window.wgUXS = function (wg, hans, hant, cn, tw, hk, sg, zh, mo, my) {
var ret = {
'zh': zh || hans || hant || cn || tw || hk || sg || mo || my,
'zh-hans': hans || cn || sg || my,
'zh-hant': hant || tw || hk || mo,
'zh-cn': cn || hans || sg || my,
'zh-sg': sg || hans || cn || my,
'zh-tw': tw || hant || hk || mo,
'zh-hk': hk || hant || mo || tw,
'zh-mo': mo || hant || hk || tw
};
return ret[wg] || zh || hans || hant || cn || tw || hk || sg || mo || my; //保證每一語言有值
};
window.wgULS = function (hans, hant, cn, tw, hk, sg, zh, mo, my) {
return wgUXS(mw.config.get('wgUserLanguage'), hans, hant, cn, tw, hk, sg, zh, mo, my);
};
(function($) {
if (typeof window.GallerySlide !== 'undefined' || mw.config.get('wgNamespaceNumber') < 0) {
return;
}
// Declare global variable so that it is no longer undefined,
// will be populated later from the document ready hook
window.GallerySlide = null;
// Globally keep track of all images by their unique hash. Each item is an image data object.
var isCategory = (mw.config.get('wgNamespaceNumber') === 14);
var isRtl = $('body').hasClass('rtl');
var allImages = {};
var imageCounter = 0;
// Galleriffic static class
$.galleriffic = {
version: '2.2',
// Strips invalid characters and any leading # characters
normalizeHash: function(hash) {
return hash.replace('#', '');
},
getImage: function(hash) {
if (!hash) {
return;
}
hash = $.galleriffic.normalizeHash(hash);
return allImages[hash];
},
// Global function that looks up an image by its hash and displays the image.
// Returns false when an image is not found for the specified hash.
// @param {String} hash This is the unique hash value assigned to an image.
gotoImage: function(hash) {
var imageData = $.galleriffic.getImage(hash);
if (!imageData) {
return false;
}
var gallery = imageData.gallery;
gallery.gotoImage(imageData);
return true;
}
};
var i18n;
var i18nStore = {
zh: {
delayInsertBtn: wgULS('以毫秒为单位设置延迟','以毫秒為單位設置延遲'),
delayInsert: wgULS('文件切换时间','檔案切換時間'),
delayInvalid: wgULS('输入错误,只接受大于1500的值','輸入錯誤,只接受大於1500的值。'),
playLinkText: wgULS('播放','播放'),
pauseLinkText: wgULS('暂停','暫停'),
prevLinkText: wgULS('上一张','上一張'),
nextLinkText: wgULS('下一张','下一張'),
hideText: wgULS('关闭幻灯片','關閉幻燈片'),
continueKeyHowTo: wgULS('当前位置网址continue-key(如果您想稍后从这个位置开始,可以保存此链接或将链接加入书签。)','當前位置網址continue-key(如果您想稍後從這個位置開始,可以保存此連結或將連結加入書籤。)'),
continueKeyInsert: wgULS('请输入continue-key。你必须在幻灯片中继续播放才能看到效果','請輸入continue-key。你必須在幻燈片中繼續播放才能看到效果'),
continueKeyInsertBtn: wgULS('输入continue-key','輸入continue-key'),
continueKeyInvalid: wgULS('continue-key值无效。','continue-key值無效。'),
licenseLabel: wgULS('许可协议:','授權條款:'),
uploaderLabel: wgULS('上传者:','上傳者:'),
helpLinkTitle: wgULS('此工具的说明文档','此工具的說明文檔'),
descriptionLoadText: wgULS('正在加载说明...','正在載入說明...')
}
};
i18n = $.extend({}, i18nStore.zh, i18nStore[mw.config.get('wgUserLanguage').split('-')[0]], i18nStore[mw.config.get('wgUserLanguage')]);
var defaults = {
delay: 7000,
preloadAhead: 25,
enableKeyboardNavigation: true,
autoPlay: false,
defaultTransitionDuration: 700,
defaultSizes: [{
w: 1500,
h: 1500
}, {
w: 1280,
h: 1024
}, {
w: 1024,
h: 768
}, {
w: 800,
h: 600
}, {
w: 640,
h: 480
}, {
w: 320,
h: 240
}, {
w: 220,
h: 240
}],
// The maximum image heigh (window's height - space - thumbbar)
maxImageHeight: $(window).height() - 125,
// The maximum image width (window's width - navi-controls - space - caption bar)
maxImageWidth: $(window).width() - 50 - Math.max(Math.min($(window).width() * 0.2, 320), 180),
actualMaxSize: {
w: 640,
h: 480
},
cmdir: 'asc',
continueKey: '',
continueKeyPattern: isCategory ? /^file\|[\da-fA-F]+\|\d+$/ : /\d+\|.+/,
lastPositionExpiry: 2,
readFromScreen: false,
readFromScreenSmallImages: false,
licenseRecognization: [
// RegExp for the tag note to add to the thumb-page
[/Category:CC[\- _]BY-SA.*/i, 'CC-By-SA'],
[/Category:CC[\- _]BY.*/i, 'CC-By'],
[/Category:CC[\- _]Zero.*/i, 'CC0'],
[/Category:GFDL.*/i, 'GFDL'],
[/Category:PD[\- _]Old.*/i, 'PD-old'],
[/Category:PD[\- _]self.*/i, 'PD-self'],
[/Category:PD[\- _]author.*/i, 'PD-author'],
[/Category:PD.*/i, 'PDx'],
[/Category:FAL/i, 'Art Libre - Free Art'],
[/Category:Images requiring attribution/i, 'Attribution'],
[/Category:Copyrighted free use.*/i, 'Copyrighted FreeUse'],
[/Category:Mozilla Public License/i, 'MPL'],
[/Category:GPL/i, 'GPL'],
[/Category:LGPL/i, 'LGPL'],
[/Category:Copyright by Wikimedia.*/i, '(c)WMF'],
[/Category:Free screenshot.*/i, 'free-Screenshot']
],
onSlideChange: function(prevIndex, nextIndex) {
var current, offset;
var displayed = Math.floor(this.$thumbsUl.parent().width() / 81);
var spaceRight = displayed - (nextIndex - this.hiddenLeft);
var spaceLeft = (1 + nextIndex - this.hiddenLeft);
if (spaceRight < 3) {
// Time to slide viewport
current = this.$thumbsUl.css('left').replace('px', '');
offset = (parseFloat(current) - (3 - spaceRight) * 81);
this.$thumbsUl.animate({
left: offset
}, 'fast');
this.hiddenLeft = this.hiddenLeft + (3 - spaceRight);
}
if (spaceLeft < 3 && nextIndex > 1) {
current = this.$thumbsUl.css('left').replace('px', '');
offset = (parseFloat(current) + (3 - spaceLeft) * 81);
this.$thumbsUl.animate({
left: offset
}, 'fast');
this.hiddenLeft = this.hiddenLeft - (3 - spaceLeft);
}
if (nextIndex === 0) {
this.$thumbsUl.animate({
left: 0
}, 'fast');
this.hiddenLeft = 0;
}
if (this.data.length - 5 < nextIndex) {
// Time to fetch more
this.queryApi();
}
},
// accepts a delegate like such: function(prevIndex, nextIndex) { ... }
onTransitionOut: undefined,
// accepts a delegate like such: function(slide, caption, isSync, callback) { ... }
onTransitionIn: undefined
};
// Primary Galleriffic initialization function that should be called on the thumbnail container.
$.fn.galleriffic = function(settings) {
// Extend Gallery Object
$.extend(this, {
// Returns the version of the script
version: $.galleriffic.version,
// Current state of the slideshow
isSlideshowRunning: false,
slideshowTimeout: undefined,
hiddenLeft: 0,
apiURL: mw.util.wikiScript('api'),
indexURL: mw.util.wikiScript('index'),
initial: true,
data: [],
// This function is attached to the click event of generated hyperlinks within the gallery
clickHandler: function(e, link) {
this.pause();
// The href attribute holds the unique hash for an image
var hash = $.galleriffic.normalizeHash($(link).attr('href'));
$.galleriffic.gotoImage(hash);
e.preventDefault();
},
createContainer: function() {
var gallery = this;
this.$slideshowContainer = $('<div class="slideshow-container"></div>');
this.$imageContainer = $('<div id="slideshow" class="slideshow"></div>');
this.$captionContainer = $('<div id="caption" class="caption-container"></div>');
this.$loadingContainer = $('<div id="loading" class="loader"></div>');
this.$controlsContainer = $('<div id="controls" class="controls"></div>');
// Gray lines for navigation
this.$ctrBack = $('<div>', {
'class': 'bar-bwd'
}).append($('<div>', {
'class': 'bar-btn-bwd'
}).text('<')).click(function(e) {
gallery.previous();
e.preventDefault();
}).mouseenter(function() {
$(this).find('div').fadeIn('fast');
}).mouseleave(function() {
$(this).find('div').fadeOut('fast');
});
this.$ctrFwd = $('<div>', {
'class': 'bar-fwd'
}).append($('<div>', {
'class': 'bar-btn-fwd'
}).text('>')).click(function(e) {
gallery.next();
e.preventDefault();
}).mouseenter(function() {
$(this).find('div').last().fadeIn('fast');
}).mouseleave(function() {
$(this).find('div').last().fadeOut('fast');
});
this.$closeButton = $('<div>', {
'class': 'slideshow-close-button',
'title': this.hideText
}).text('×').click(function(e) {
gallery.pause();
gallery.toggleVisibility();
// stop propagation & prevent default
return false;
});
this.append('<div id="com-gs-thumbs" class="navigation"><ul class="com-gs-thumbs"></ul></div>');
this.append(this.$controlsContainer).append(this.$slideshowContainer);
this.$slideshowContainer.append(this.$loadingContainer).append(this.$captionContainer).append(this.$imageContainer);
this.append(this.$ctrBack).append(this.$ctrFwd.prepend(this.$closeButton));
this.$thumbsUl = this.find('ul.com-gs-thumbs');
},
// Scrapes the thumbnail container for thumbs and adds each to the gallery
initializeThumbs: function() {
var data = this.passedData;
var gallery = this;
$.each(data, function(i, imageData) {
var hash;
imageData.index = hash = imageCounter;
imageData.gallery = gallery;
var aspect = (imageData.width / imageData.height);
var size = (aspect > 1) ? 'height' : 'width';
var $thumb = $('<li><a class="com-gs-thumb"><img ' + size + '=75px src="' + (imageData.slideThumb || imageData.slideUrl) + '" /></a></li>');
$thumb.css('opacity', 0.67).hover(function() {
$(this).not('.selected').fadeTo('fast', 1);
}, function() {
$(this).not('.selected').fadeTo('fast', 0.67);
});
gallery.$thumbsUl.append($thumb);
imageData.caption = $('<div>').append(
$('<a>', {
href: imageData.link,
text: imageData.title.replace('File:', '').replace(/\.[\w]{3,4}$/, '')
})).html();
// Register the image globally
allImages['' + hash] = imageData;
// Setup attributes and click handler
$thumb.find('a').attr('href', '#' + hash).removeAttr('name').click(function(e) {
gallery.clickHandler(e, this);
});
imageCounter++;
});
this.data = this.data.concat(data);
return this;
},
isPreloadComplete: false,
// Initalizes the image preloader
preloadInit: function() {
if (this.preloadAhead === 0) {
return this;
}
this.preloadStartIndex = this.currentImage.index;
var nextIndex = this.getNextIndex(this.preloadStartIndex);
return this.preloadRecursive(this.preloadStartIndex, nextIndex);
},
// Changes the location in the gallery the preloader should work
// @param {Integer} index The index of the image where the preloader should restart at.
preloadRelocate: function(index) {
// By changing this startIndex, the current preload script will restart
this.preloadStartIndex = index;
return this;
},
// Recursive function that performs the image preloading
// @param {Integer} startIndex The index of the first image the current preloader started on.
// @param {Integer} currentIndex The index of the current image to preload.
preloadRecursive: function(startIndex, currentIndex) {
// Check if startIndex has been relocated
if (startIndex !== this.preloadStartIndex) {
var nextIndex = this.getNextIndex(this.preloadStartIndex);
return this.preloadRecursive(this.preloadStartIndex, nextIndex);
}
var gallery = this;
// Now check for preloadAhead count
var preloadCount = currentIndex - startIndex;
if (preloadCount < 0) {
preloadCount = this.data.length - 1 - startIndex + currentIndex;
}
if (this.preloadAhead >= 0 && preloadCount > this.preloadAhead) {
// Do this in order to keep checking for relocated start index
setTimeout(function() {
gallery.preloadRecursive(startIndex, currentIndex);
}, 500);
return this;
}
var imageData = this.data[currentIndex];
if (!imageData) {
return this;
}
// If already loaded, continue
if (imageData.image) {
return this.preloadNext(startIndex, currentIndex);
}
// Preload the image
var image = new Image();
image.onload = function() {
imageData.image = this;
gallery.preloadNext(startIndex, currentIndex);
};
image.alt = imageData.title;
image.src = imageData.slideUrl;
return this;
},
// Called by preloadRecursive in order to preload the next image after the previous has loaded.
// @param {Integer} startIndex The index of the first image the current preloader started on.
// @param {Integer} currentIndex The index of the current image to preload.
preloadNext: function(startIndex, currentIndex) {
var nextIndex = this.getNextIndex(currentIndex);
if (nextIndex === startIndex) {
this.isPreloadComplete = true;
} else {
// Use setTimeout to free up thread
var gallery = this;
setTimeout(function() {
gallery.preloadRecursive(startIndex, nextIndex);
}, 100);
}
return this;
},
// Safe way to get the next image index relative to the current image.
// If the current image is the last, returns 0
getNextIndex: function(index) {
var nextIndex = index + 1;
if (nextIndex >= this.data.length) {
nextIndex = 0;
}
return nextIndex;
},
// Safe way to get the previous image index relative to the current image.
// If the current image is the first, return the index of the last image in the gallery.
getPrevIndex: function(index) {
var prevIndex = index - 1;
if (prevIndex < 0) {
prevIndex = this.data.length - 1;
}
return prevIndex;
},
// Pauses the slideshow
pause: function() {
this.isSlideshowRunning = false;
$(document).triggerHandler('slideshow', ['actionPause', this]); // For external scripts
if (this.slideshowTimeout) {
clearTimeout(this.slideshowTimeout);
this.slideshowTimeout = undefined;
}
if (this.$controlsContainer) {
this.$controlsContainer.find('div.nav-controls a.gs-play-pause').removeClass('gs-play-pause').addClass('gs-play-play').attr('title', this.playLinkText).attr('href', '#play');
}
return this;
},
// Plays the slideshow
play: function() {
this.isSlideshowRunning = true;
$(document).triggerHandler('slideshow', ['actionPlay', this]); // For external scripts
if (this.$controlsContainer) {
this.$controlsContainer.find('div.nav-controls a.gs-play-play').removeClass('gs-play-play').addClass('gs-play-pause').attr('title', this.pauseLinkText).attr('href', '#pause');
}
if (!this.slideshowTimeout) {
var gallery = this;
this.slideshowTimeout = setTimeout(function() {
gallery.next(true);
}, this.delay);
}
return this;
},
// Toggles the state of the slideshow (playing/paused)
toggleSlideshow: function() {
if (this.isSlideshowRunning) {
this.pause();
} else {
this.play();
}
return this;
},
// Advances the gallery to the next image.
// @param {Boolean} dontPause Specifies whether to pause the slideshow.
next: function(dontPause) {
this.gotoIndex(this.getNextIndex(this.currentImage.index), dontPause);
return this;
},
// Navigates to the previous image in the gallery.
// @param {Boolean} dontPause Specifies whether to pause the slideshow.
previous: function(dontPause) {
this.gotoIndex(this.getPrevIndex(this.currentImage.index), dontPause);
return this;
},
// Navigates to the image at the specified index in the gallery
// @param {Integer} index The index of the image in the gallery to display.
// @param {Boolean} dontPause Specifies whether to pause the slideshow.
gotoIndex: function(index, dontPause) {
if (!dontPause) {
this.pause();
}
if (index < 0) {
index = 0;
} else if (index >= this.data.length) {
index = this.data.length - 1;
}
var imageData = this.data[index];
this.gotoImage(imageData);
return this;
},
// This function is guaranteed to be called anytime a gallery slide changes.
// @param {Object} imageData An object holding the image metadata of the image to navigate to.
gotoImage: function(imageData) {
var index = imageData.index;
if (this.onSlideChange) {
this.onSlideChange(this.currentImage.index, index);
}
this.currentImage = imageData;
this.preloadRelocate(index);
this.refresh();
return this;
},
// Returns the default transition duration value. The value is halved when not
// performing a synchronized transition.
// @param {Boolean} isSync Specifies whether the transitions are synchronized.
getDefaultTransitionDuration: function(isSync) {
if (isSync) {
return this.defaultTransitionDuration;
}
return this.defaultTransitionDuration / 2;
},
// Rebuilds the slideshow image and controls and performs transitions
refresh: function() {
var imageData = this.currentImage;
if (!imageData) {
return this;
}
var previousSlide = this.$imageContainer.find('span.current').addClass('previous').removeClass('current');
var previousCaption = 0;
if (this.$captionContainer) {
previousCaption = this.$captionContainer.find('span.current').addClass('previous').removeClass('current');
}
// Perform transitions simultaneously if the next image is already preloaded
var isSync = imageData.image;
// Flag we are transitioning
var isTransitioning = true;
var gallery = this;
var transitionOutCallback = function() {
// Flag that the transition has completed
isTransitioning = false;
// Remove the old slide
previousSlide.remove();
// Remove old caption
if (previousCaption) {
previousCaption.remove();
}
if (!isSync) {
if (imageData.image && imageData.index === gallery.data[gallery.currentImage.index].index) {
gallery.buildImage(imageData, isSync);
} else {
// Show loading container
if (gallery.$loadingContainer) {
gallery.$loadingContainer.show();
}
}
}
};
if (previousSlide.length === 0) {
// For the first slide, the previous slide will be empty, so we will call the callback immediately
transitionOutCallback();
} else {
previousSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0, transitionOutCallback);
if (previousCaption) {
previousCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 0.0);
}
}
// Go ahead and begin transitioning in of next image
if (isSync) {
this.buildImage(imageData, isSync);
}
if (!imageData.image) {
var image = new Image();
// Wire up mainImage onload event
image.onload = function() {
imageData.image = this;
// Only build image if the out transition has completed and we are still on the same image hash
if (!isTransitioning && imageData.index === gallery.data[gallery.currentImage.index].index) {
gallery.buildImage(imageData, isSync);
}
};
// set alt and src
image.alt = imageData.title;
image.src = imageData.slideUrl;
}
// This causes the preloader (if still running) to relocate out from the currentIndex
this.relocatePreload = true;
return this.syncThumbs();
},
// Shrinking The Tower of Babel
// Hide other languages, if script is available
shrinkTowerOfBabel: function($node) {
if (window.multilingual) {
var ml = window.multilingual;
ml.langCountThreshold = 2;
ml.method = 'prepend';
ml.$p = ml.$OuterContainer = $node;
ml.init();
}
},
// Called by the refresh method after the previous image has been transitioned out or at the same time
// as the out transition when performing a synchronous transition.
// @param {Object} imageData An object holding the image metadata of the image to build.
// @param {Boolean} isSync Specifies whether the transitions are synchronized.
buildImage: function(imageData, isSync) {
var gallery = this;
var nextIndex = this.getNextIndex(imageData.index);
// We have loaded bigger images, size them down, now; 1 prevents upscaling (looks ugly)
var scaleRatio = Math.max(
imageData.width / this.maxImageWidth,
imageData.height / (this.maxImageHeight - 20),
1);
var imgWidth = Math.floor(imageData.width / scaleRatio);
var imgHeight = Math.floor(imageData.height / scaleRatio);
// computing the "center-position of the space"
var hSpace = isRtl ? (this.$captionContainer.position().left - 2 * this.$imageContainer.position().left) : (this.$imageContainer.width() - this.$captionContainer.position().left - this.$captionContainer.width());
var hPos = isRtl ? (this.$imageContainer.width() - this.$captionContainer.position().left + 2 * this.$imageContainer.position().left + (hSpace - imgWidth) / 2) : (this.$captionContainer.position().left + this.$captionContainer.width() + (hSpace - imgWidth) / 2);
var vSpace = this.$imageContainer.height() - 130;
var top = (vSpace - imgHeight) / 2;
// Send a XHrequest in case of unknown description
if (typeof imageData.description !== 'string') {
this.queryFile(imageData.title);
}
if (typeof this.data[nextIndex].description !== 'string') {
this.queryFile(this.data[nextIndex].title);
}
// Construct new hidden span for the image
var newSlide = this.$imageContainer.append(
$('<span>', {
'class': 'image-wrapper current'
}).css(isRtl ? 'right' : 'left', hPos).css('top', top).append(
$('<a>', {
'class': 'advance-link',
href: imageData.link,
title: imageData.title,
target: '_blank',
css: {
width: imgWidth
}
}))).find('span.current').css('opacity', '0');
newSlide.find('a').append(imageData.image);
var descript = imageData.description || $('<span>').append($.createSpinner(), mw.html.escape(this.descriptionLoadText));
var newCaption = 0;
var extraParams = '&gsDir=' + this.cmdir + '&gsAutoStart=1' + (mw.util.getParamValue('withJS') ? ('&withJS=' + mw.util.getParamValue('withJS')) : '') + (mw.util.getParamValue('withCSS') ? ('&withCSS=' + mw.util.getParamValue('withCSS')) : '');
if (this.$captionContainer) {
// Construct new hidden caption for the image
newCaption = this.$captionContainer.append(
$('<span>', {
'class': 'image-caption current',
style: 'height:' + (this.maxImageHeight - 30) + 'px;'
})).find('span.current').css('opacity', '0').append(imageData.caption, $('<br>')).append(
$('<div>', {
'class': 'gs-img-description',
id: 'desc' + imageData.index,
append: descript
})).append(
$('<div>', {
'class': 'gs-img-uploader'
}).append(imageData.$user.clone())).append(
imageData.$cats,
imageData.$licenses).append(
$('<div>', {
'class': 'gs-img-metrics',
html: imageData.oWidth + ' × ' + imageData.oHeight + ' / ' + imageData.oSize
})).append(imageData.contKey ? $('<div>', {
'class': 'cont-key-container gs-icon',
title: this.continueKeyHowTo,
append: $('<a>', {
href: mw.util.getUrl(mw.config.get('wgPageName')) + '?gsContinue=' + imageData.contKey + extraParams,
target: '_blank',
text: imageData.contKey
})
}) : '');
}
this.shrinkTowerOfBabel(newCaption.find('.gs-img-description'));
// Hide the loading conatiner
if (this.$loadingContainer) {
this.$loadingContainer.hide();
}
// Transition in the new image
if (this.onTransitionIn) {
this.onTransitionIn(newSlide, newCaption, isSync);
} else {
newSlide.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
if (newCaption) {
newCaption.fadeTo(this.getDefaultTransitionDuration(isSync), 1.0);
}
}
if (this.isSlideshowRunning) {
if (this.slideshowTimeout) {
clearTimeout(this.slideshowTimeout);
}
this.slideshowTimeout = setTimeout(function() {
gallery.next(true);
}, this.delay);
}
// Save the current position in a cookie or delete the cookie
if (imageData.contKey) {
this.saveContinueKey(imageData.contKey);
} else {
this.saveContinueKey(null);
}
$(document).triggerHandler('slideshow', ['newSlide', this]); // For external scripts
return this;
},
saveContinueKey: function(key) {
// Breaks some clients! Needs investigation and migration to jStorage.
return;
/*if (this.remoteUse) {
return;
}
mw.cookie.get('gs' + mw.config.get('wgPageName').replace('Category:', '1:').replace('Commons:', '2:'),
key, {
expires: this.lastPositionExpiry
});*/
},
getContinueKey: function() {
return mw.cookie.get('gs' + mw.config.get('wgPageName').replace('Category:', '1:').replace('Commons:', '2:'));
},
// Applies the selected class to the current image's corresponding thumbnail.
// Also checks if the current page has changed and updates the displayed page of thumbnails if necessary.
syncThumbs: function() {
// Remove existing selected class and add selected class to new thumb
var $thumbs = this.$thumbsUl.children();
$thumbs.filter('.selected').removeClass('selected').fadeTo('fast', 0.67);
$thumbs.eq(this.currentImage.index).addClass('selected').fadeTo('fast', 1);
return this;
},
findImageSize: function(h, w) {
var that = this,
sOld = this.defaultSizes[0];
$.each(this.defaultSizes, function(i, s) {
if (s.w > w || s.h > h) {
sOld = s;
return;
} else {
that.actualMaxSize = sOld;
return false;
}
});
},
init: function() {
var $navCont, $playBtn, $prevBtn, $nextBtn;
this.createContainer();
var gallery = this;
$(window).resize(function() {
gallery.maxImageHeight = $(window).height() - gallery.$thumbsUl.height() - gallery.$controlsContainer.height();
gallery.maxImageWidth = gallery.$slideshowContainer.width() - gallery.$captionContainer.width() - 16;
gallery.findImageSize(gallery.maxImageHeight, gallery.maxImageWidth);
gallery.css('height', $(window).height());
}).resize();
// Initialize the thumbails
this.initializeThumbs();
this.currentImage = this.data[0];
// Hide the loadingContainer
this.$loadingContainer.hide();
this.gotoIndex(0);
// Setup controls
if (this.autoPlay) {
$playBtn = $('<a>').attr({
'class': 'gs-play gs-play-pause',
title: this.pauseLinkText,
href: '#pause'
});
} else {
$playBtn = $('<a>').attr({
'class': 'gs-play gs-play-play',
title: this.playLinkText,
href: '#play'
});
}
$playBtn.click(function(e) {
gallery.toggleSlideshow();
e.preventDefault();
});
$prevBtn = $('<a>').attr({
'class': 'gs-play gs-play-bwd',
title: this.prevLinkText,
href: '#previous'
}).click(function(e) {
gallery.previous();
e.preventDefault();
});
$nextBtn = $('<a>').attr({
'class': 'gs-play gs-play-fwd',
title: this.nextLinkText,
href: '#next'
}).click(function(e) {
gallery.next();
e.preventDefault();
});
$navCont = $('<div class="nav-controls">');
$navCont.hover(function() {
$(this).fadeTo('fast', 0.75);
}, function() {
$(this).fadeTo('fast', 0.4);
});
this.$controlsContainer.append(
$navCont.append($prevBtn, $playBtn, $nextBtn));
// Option icons
if (!this.remoteUse) {
this.$continueKey = $('<a>', {
'class': 'continue-key-insert gs-icon gs-icon-keyGo',
href: '#',
title: gallery.continueKeyInsertBtn,
click: function(e) {
e.preventDefault();
var ckey = prompt(gallery.continueKeyInsert, gallery.cont ? gallery.cont : '');
ckey = $.trim(ckey);
if (gallery.continueKeyPattern.test(ckey)) {
gallery.cont = ckey;
} else {
alert(gallery.continueKeyInvalid);
}
}
});
}
var $setDelay = $('<a>', {
'class': 'delay-insert gs-icon gs-icon-clock',
href: '#',
title: gallery.delayInsertBtn,
click: function(e) {
e.preventDefault();
var delay = prompt(gallery.delayInsert, gallery.delay ? gallery.delay : '');
if (!delay) {
return;
}
delay = $.trim(delay.replace(/ms|s/, ''));
if (/^\d+$/.test(delay)) {
if (delay > 1000) {
gallery.delay = delay;
} else if ((0.9 < delay) && (delay < 61)) {
gallery.delay = delay * 1000;
} else {
alert(gallery.delayInvalid);
}
// Set cookie
mw.cookie.set('slideshow-delay', gallery.delay, {
expires: 100,
path: '/'
});
} else {
alert(gallery.delayInvalid);
}
}
});
var $helpLink = $('<a>', {
'class': 'gs-help-link gs-icon gs-icon-help',
href: mw.util.getUrl('Help:Slideshow'),
title: gallery.helpLinkTitle,
target: '_blank'
});
var otherCont = $('<div>', {
'class': 'other-controls'
});
this.$controlsContainer.append(
otherCont.append(
(this.$continueKey || ' '),
$setDelay,
$helpLink));
otherCont.hover(function() {
$(this).fadeTo('fast', 1);
}, function() {
$(this).fadeTo('fast', 0.6);
});
// Setup Keyboard Navigation
if (this.enableKeyboardNavigation) {
$(document).keydown(function(e) {
var key = e.charCode || e.keyCode || 0;
switch (key) {
case 32:
// space
gallery.next();
e.preventDefault();
break;
case 35:
// End
gallery.gotoIndex(gallery.data.length - 1);
e.preventDefault();
break;
case 37:
// left arrow
gallery.previous();
e.preventDefault();
break;
case 39:
// right arrow
gallery.next();
e.preventDefault();
break;
case 19:
// break
gallery.toggleSlideshow();
e.preventDefault();
break;
}
});
$(document).keyup(function(e) {
var key = e.charCode || e.keyCode || 0;
//Hide on escape
if ($('#SlideContainer').height() && key === 27) {
gallery.pause();
gallery.toggleVisibility();
}
});
}
// Auto start the slideshow
if (this.autoPlay) {
this.play();
}
// Kickoff Image Preloader after 1 second
setTimeout(function() {
gallery.preloadInit();
}, 1000);
$(document).triggerHandler('slideshow', ['shown', this]); // For external scripts
},
start: function() {
$(document).triggerHandler('slideshow', ['starting', this]); // For external scripts
$('#GallerySlideStartButtons').find('button').hide();
$('#SlideContainer').animate({
height: $(window).height()
});
// Once done, hide scrollbar
// disabled for IE 6/7
if ('\v' !== 'v') {
$('body').css('overflow', 'hidden');
}
// Settings from URL
var autoPlay = mw.util.getParamValue('gsAutoPlay');
if (autoPlay) {
if ('1' === autoPlay || 'true' === autoPlay || 'yes' === autoPlay || '-1' === autoPlay) {
this.autoPlay = true;
} else {
this.autoPlay = false;
}
}
var delay = mw.util.getParamValue('gsDelay') || mw.cookie.get('slideshow-delay');
if (delay) {
if (/^\d+$/.test(delay)) {
if (delay > 1999) {
this.delay = delay;
} else if ((1 < delay) && (delay < 61)) {
this.delay = delay * 1000;
}
}
}
var cmdir = mw.util.getParamValue('gsDir');
if (cmdir) {
if ('climbing' === cmdir || 'ascending' === cmdir || 'asc' === cmdir || '123' === cmdir || 'rising' === cmdir) {
this.cmdir = 'asc';
} else {
this.cmdir = 'desc';
}
}
var cmcontinue = mw.util.getParamValue('gsContinue');
if (cmcontinue) {
if (this.continueKeyPattern.test(cmcontinue)) {
this.cont = cmcontinue;
} else {
this.cont = '';
}
}
var readFromScreen = mw.util.getParamValue('gsReadFromScreen');
if (readFromScreen) {
this.readFromScreen = true;
this.remoteUse = true;
}
this.findImageSize(this.maxImageHeight, this.maxImageWidth);
this.queryApi();
// For IE 6
if ('\v' === 'v') {
setTimeout(function() {
window.location.hash = '#SlideContainer';
}, 2000);
}
// Display dynamic help from Help:Gadget-GallerySlideshow/OSDHelp
var _this = this;
var showHelpSplash = function(result) {
if (!result) {
return;
}
result = $(result);
result.find('.editsection').remove();
var $slideC = $('#SlideContainer');
var helpSplash = $('<div id="GallerySlideHelpSplash"></div>').append(result);
setTimeout(function() {
helpSplash.fadeOut();
}, 15000);
helpSplash.css('right', 0);
helpSplash.css('bottom', 0);
$slideC.prepend(helpSplash.hide().fadeTo(400, 0.7));
helpSplash.click(function() {
$(this).fadeOut();
});
};
$.get(this.indexURL, {
title: 'Help:Gadget-GallerySlideshow/OSDHelp',
action: 'render',
uselang: mw.config.get('wgUserLanguage')
}, showHelpSplash);
},
toggleVisibility: function() {
$('#GallerySlidestart').toggle().off('click').click(GallerySlide.toggleVisibility);
$('#GallerySlideStartButtons').buttonset();
$('#SlideContainer').slideToggle(function() {
$(document).triggerHandler('slideshow', ['visibility', GallerySlide]);
});
$('body').css('overflow', 'visible');
// For external scripts
},
queryFile: function(title) {
var _this = this;
var params = {
action: 'render',
title: title
};
$.ajax({
url: this.indexURL,
cache: true,
dataType: 'html',
data: params,
type: 'GET',
success: function(result) {
_this.processDetails(result, title);
}
});
},
processDetails: function(result, title) {
if (typeof result !== 'string') {
return;
}
var i,
dItem,
dDescription,
$node,
parsedDOM = $(result),
$author;
parsedDOM.find('table, div').attr('style', '');
parsedDOM.find('table').attr('cellspacing', 1).attr('cellpadding', 0);
// Clean up author field. Some users are very important and therefore designed logos etc. for themselves
// But they are not really important and possibly distract the slideviewer
$author = $('#fileinfotpl_aut', parsedDOM).siblings().eq(0).contents().clone();
$author.find('img').remove();
$author.find('*').removeAttr('style');
$author.find('font').contents().unwrap();
$author.find('b').contents().unwrap();
dDescription = $('<div>').append(
$('<div>').addClass('gs-img-description-desc').append(
$('#fileinfotpl_desc', parsedDOM).siblings().eq(0).contents()),
$('<div>').addClass('gs-img-description-aut').append($author).prepend(
$('<span>', {
'class': 'gs-author-label'
}).text($(parsedDOM).find('#fileinfotpl_aut').text())),
$('<div>').addClass('gs-img-description-date').append(
$(parsedDOM).find('#fileinfotpl_date').siblings().eq(0).contents().clone()).prepend(
$('<span>', {
'class': 'gs-date-label'
}).text($('#fileinfotpl_date', parsedDOM).text()))).html();
if (!dDescription) {
dDescription = result;
}
for (i in this.data) {
dItem = this.data[i];
if (dItem.title === title) {
dItem.description = dDescription;
$node = $('#desc' + i);
if ($node.length !== 0) {
$node.html(dDescription);
this.shrinkTowerOfBabel($node);
}
}
}
},
queryApi: function() {
var _this = this;
var params = {};
if (_this.queryRunning || (_this.cont === false && !_this.readFromScreen)) {
return;
}
$(document).triggerHandler('slideshow', ['beforeQuery', this]); // For external scripts
// New restrictions in image info API
var limit = Math.min(Math.floor($('#SlideContainer').width() / 81) + 1, 50);
if (_this.readFromScreen) {
_this.qFiles = [];
if (!_this.$galleryBoxes) {
_this.$galleryBoxes = $('.gallerybox');
_this.queryImageId = -1;
}
if (_this.queryImageId === (_this.$galleryBoxes.length - 1)) {
return; // All images loaded
}
_this.$galleryBoxes.each(function(i, e) {
if (_this.queryImageId >= i) {
return;
}
if (_this.qFiles.length === limit) {
return;
}
_this.queryImageId = i;
_this.qFiles.push('File:' + mw.libs.commons.titleFromImgSrc($(e).find('.thumb').find('img').attr('src')));
});
}
if (_this.readFromScreen) {
params = {
format: 'json',
action: 'query',
titles: _this.qFiles.join('|'),
rawcontinue: 1,
prop: 'imageinfo|categories',
clprop: 'hidden',
cllimit: 500,
iiprop: 'url|user|size',
iilimit: 1,
iiurlwidth: this.actualMaxSize.w,
iiurlheight: this.actualMaxSize.h,
indexpageids: 1
};
} else if (isCategory) {
params = {
format: 'json',
action: 'query',
generator: 'categorymembers',
rawcontinue: 1,
gcmtitle: mw.config.get('wgPageName'),
gcmlimit: limit,
gcmtype: 'file',
gcmdir: this.cmdir,
prop: 'imageinfo|categories',
clprop: 'sortkey|hidden',
cllimit: 500,
iiprop: 'url|user|size',
iilimit: 1,
iiurlwidth: this.actualMaxSize.w,
iiurlheight: this.actualMaxSize.h,
indexpageids: 1
};
if (this.cont) {
params.gcmcontinue = this.cont;
}
} else {
params = {
action: 'query',
generator: 'images',
rawcontinue: 1,
titles: mw.config.get('wgPageName'),
gimlimit: limit,
prop: 'imageinfo|categories',
clprop: 'hidden',
cllimit: 500,
iiprop: 'url|user|size',
iilimit: 1,
iiurlwidth: this.actualMaxSize.w,
iiurlheight: this.actualMaxSize.h,
format: 'json',
indexpageids: 1
};
if (this.cont) {
params.gimcontinue = this.cont;
}
}
if (!this.initial && !this.cont && !this.readFromScreen) {
return;
}
_this.queryRunning = true;
$.ajax({
url: this.apiURL,
cache: false,
dataType: 'json',
data: params,
type: 'POST',
success: function(result) {
_this.queryRunning = false;
_this.processReturn(result);
},
error: function() {
_this.queryRunning = false;
}
});
},
processReturn: function(result) {
$(document).triggerHandler('slideshow', ['afterQuery', this]); // For external scripts
var pages = result.query.pages,
pages2 = [],
data = [],
i = 0, j = 0;
if (result['query-continue'] && (result['query-continue'].categorymembers || result['query-continue'].images)) {
if (typeof this.cont !== 'undefined') {
this.contOld = this.cont;
}
this.cont = isCategory ? result['query-continue'].categorymembers.gcmcontinue : result['query-continue'].images.gimcontinue;
} else {
this.cont = false;
}
// Fromatt a number
var fm = function(iNr) {
iNr += '';
var rx = /(\d+)(\d{3})/;
while (rx.test(iNr)) {
iNr = iNr.replace(rx, '$1' + '<span class="digit-separator"> </span>' + '$2');
}
return iNr;
};
if (this.readFromScreen) {
// sorting the mess, the API has created to fit the page-diplay
var qFilesL = this.qFiles.length,
qFilesTitle,
qfi,
p, pg;
sreenreadorderloop: for (qfi = 0; qfi !== qFilesL; qfi++) {
qFilesTitle = this.qFiles[qfi];
for (p in pages) {
pg = pages[p];
if (pg.title === qFilesTitle) {
pages2.push(pg);
continue sreenreadorderloop;
}
}
}
pages = pages2;
} else {
// This is for Chrome: https://bugs.chromium.org/p/v8/issues/detail?id=164
// and Opera and InternetExplorer
var pgIds = result.query.pageids;
for (j = 0; j < pgIds.length; j++) {
pages2.push(pages[pgIds[j]]);
}
pages = pages2;
}
for (j = 0; j < pages.length; j++) {
var v = pages[j];
if ('undefined' !== typeof v.missing || !v.imageinfo) {
continue;
}
var r = v.imageinfo[v.imageinfo.length - 1],
rc = v.imageinfo[0],
n = data[i] = {},
sortkey = '',
$cats = $('<div>', {
'class': 'cat-wrap'
}),
$licenses = $('<div>', {
'class': 'license-wrap'
}).append($('<span>', {
style: 'display:inline-block;'
}).text(this.licenseLabel));
// Process categories; Extract visible cats, sortkey for current cat, licenses
if (v.categories) {
var c, clen = v.categories.length;
processCats: for (c = 0; c < clen; c++) {
var tCat = v.categories[c];
if (isCategory && tCat.title === mw.config.get('wgPageName').replace(/_/g, ' ')) {
sortkey = 'file' + '|' + tCat.sortkey + '|' + v.pageid;
}
if (typeof tCat.hidden === 'undefined') {
$cats.append(
$('<a>', {
'class': 'cat-label',
href: mw.util.getUrl(tCat.title),
target: '_blank',
text: tCat.title.replace('Category:', '')
}), ' ');
} else {
var recogID, recogLen = this.licenseRecognization.length;
for (recogID = 0; recogID < recogLen; recogID++) {
if (this.licenseRecognization[recogID][0].test(tCat.title)) {
$licenses.append(
$('<span>', {
'class': 'license-label',
title: tCat.title.replace('Category:', ''),
html: this.licenseRecognization[recogID][1]
}), ' ');
continue processCats;
}
}
}
}
}
if (!isCategory) {
sortkey = mw.config.get('wgArticleId') + '|' + v.title.replace('File:', '');
}
n.title = v.title;
n.link = rc.descriptionurl;
n.slideUrl = rc.thumburl;
n.width = rc.thumbwidth;
n.height = rc.thumbheight;
n.oWidth = fm(r.width);
n.oHeight = fm(r.height);
n.oSize = fm(r.size >> 10) + ' <abbr title="1 KibiByte= 1024 Bytes">KiB</abbr>';
n.$user = $('<span>').append(
$('<span>', {
'class': 'gs-uploader-label'
}).text(this.uploaderLabel)).append(
$('<span>').css({
direction: 'ltr',
display: 'inline-block'
}).append(
$('<a>', {
href: mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[2] + ':' + r.user),
target: '_blank',
text: r.user
}), ' (',
$('<a>', {
href: mw.util.getUrl(mw.config.get('wgFormattedNamespaces')[3] + ':' + r.user),
target: '_blank',
text: 'talk'
}), ')'));
n.$cats = $cats;
n.$licenses = $licenses;
n.contKey = (sortkey || this.contOld);
// reset to empty string when using screen-read-mode (too instable to rely on it)
if (this.readFromScreen) {
n.contKey = '';
}
i++;
}
this.passedData = data;
if (this.initial) {
this.init();
} else {
this.initializeThumbs();
}
this.initial = false;
}
});
// Now initialize the gallery
$.extend(this, defaults, i18n, settings);
return this;
};
$(document).ready(function() {
if ($('.gallery li').length < 2) {
// no need for a gallery with a few images
return;
}
mw.loader.using(['mediawiki.cookie', 'mediawiki.util', 'jquery.ui', 'jquery.spinner'], function() {
$('body').append('<div id="SlideContainer"></div>');
window.GallerySlide = $('#SlideContainer').galleriffic();
$(document).triggerHandler('slideshow', ['codeLoaded', window.GallerySlide]); // For external scripts
});
});
// When this script is loaded, someone started the slideshow gadget
// To prepare un-defaulting, set a user preference and count usage
if (mw.user.isAnon()) return;
mw.loader.using('ext.gadget.SettingsManager', function() {
mw.libs.settingsManager.fetchGadgetSetting('slideshow-usage').done(function(o, v) {
v = Number(v) || 0;
v++;
if (v > 9) return;
mw.libs.settingsManager.switchGadgetPref('slideshow-usage', v);
});
});
})(jQuery);