Benutzer:Christoph Jauera (WMDE)/gadget-test.js
Erscheinungsbild
Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
// Page title
var gPageName = mw.config.get( 'wgPageName' );
// Gives us the most current revision ID for the page
var gCurRevisionId = mw.config.get( 'wgCurRevisionId' );
// Action: view/query/history
var gAction = mw.config.get( 'wgAction' );
// User name
var gUserName = mw.config.get( 'wgUserName' );
// The URL of the page, relative to DOCUMENT_ROOT
var gScript = mw.config.get( 'wgScript' );
// Revision ID of right revision on diff page
var gRightRevID = mw.config.get( 'wgRevisionId' );
// Revision ID of left revision on diff page
var gLeftRevID = mw.util.getParamValue( 'oldid' );
// Get value of diff param in URL
var gDiff = mw.util.getParamValue( 'diff' );
// Page ID
var gPageID = mw.config.get( 'wgArticleID' );
// Server
var gServer = mw.config.get( 'wgServer' );
// Function called when a tick on the slider is clicked
// Params: v1 - Left revision ID; v2 - Right revision ID
function refresh( v1, v2 ) {
var $url = gServer + gScript + '?title=' + gPageName + '&diff=' + v2 + '&oldid=' + v1;
location.href = $url;
}
// Formating date in JS
function formatDate( rawDate ) {
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
var f = new Date( rawDate );
var fDate = f.getUTCDate();
var fMonth = f.getUTCMonth();
var fYear = f.getUTCFullYear();
var fHours = ( '0' + f.getUTCHours()).slice(-2);
var fMinutes = ( '0' + f.getUTCMinutes()).slice(-2);
return ( fHours + ':' + fMinutes + ', ' + fDate + ' ' + months[fMonth] + ' ' + fYear ).toString();
}
// Setting the tick marks on the slider
// Params: element - jQuery slider; revs - revisions data from API
function setSliderTicks( element, revs ) {
var $slider = $( element ),
max = $slider.slider( "option", "max" ),
min = $slider.slider( "option", "min" ),
spacing = 100 / ( max - min ),
revData = getComposedRevData( revs ),
maxChangeSizeLogged = Math.log( revData.maxChangeSize );
for ( var i = 1; i <= max-min ; i++ ) {
var diffSize = revs[i].size - revs[i-1].size,
relativeChangeSize = Math.ceil( 65.0 * Math.log( Math.abs( diffSize ) ) / maxChangeSizeLogged ) + 5,
section = getSection( revs[i].comment ),
html = '<b>' + formatDate( revs[i].timestamp ) + '</b><br>';
html += mw.html.escape( revs[i].user ) + '<br>';
if( revs[i].comment !== '' ) {
html += '<br><i>' + mw.html.escape( revs[i].parsedcomment ) + '</i>';
}
html += '<br>' + diffSize + ' byte';
$('<div class="ui-slider-tick-mark" title="<center>' + html +'</center>"></div>')
.css( {
'left' : ( spacing * i - 0.75 ) + '%',
'width' : spacing + '%',
'height' : relativeChangeSize + 'px',
'top' : diffSize > 0 ? '-' + relativeChangeSize + 'px' : 0,
'background' : revData.sectionMap.get( section ) ? revData.sectionMap.get( section ) : 'black'
} )
.tipsy( {
gravity: 's',
html: true,
fade: true
} )
.appendTo( $slider );
}
}
function getComposedRevData( revs ) {
var max = 0,
changeSize = 0,
section,
sectionMap = new Map(),
result;
for ( i = 1; i < revs.length; i++) {
changeSize = Math.abs( revs[i].size - revs[i-1].size );
section = getSection( revs[i].comment );
if( changeSize > max ) {
max = changeSize;
}
if( section.length > 0 && !sectionMap.has( section )) {
sectionMap.set( section );
}
}
var i = 0;
sectionMap.forEach( function (item, key, sectionMap) {
sectionMap.set( key, rainbow( sectionMap.size, i ) );
i++;
});
for ( i = 0; i < sectionMap.length; i++) {
sectionMap.set()
}
result = {
maxChangeSize: max,
sectionMap: sectionMap
};
return result;
}
function getSection( text ) {
text = text.match(
new RegExp(
'(/\\* [^\\*]* \\*/)',
'gi' ) );
if( !text ) {
return '';
}
return text[0].replace(
new RegExp( ' \\*/|/\\* ', 'ig' ),
'' );
}
// Adding the initial barebones slider
// Params: revs - revisions data from API; vals - initial positions for the slider handles
function addSlider( revs, vals ) {
numberRevs = revs.length;
var $slider = $( '<div class="range-slider"></div>' )
.slider({
range: true,
min: 1,
max: numberRevs,
step: 1,
animate: "fast",
values: vals,
create: function( event, ui ) {
setSliderTicks( event.target, revs );
},
stop: function( event, ui ) {
var v1 = revs[ui.values[0]-1].revid;
var v2 = revs[ui.values[1]-1].revid;
refresh( v1, v2 );
},
slide: function( event, ui ) {
}
});
$( '.ui-slider-handle:first' ).attr( 'title', 'Huh' ).tipsy({ gravity: 's', html: true, fade: true });
$html = $( '<td colspan="4" style="text-align:center;" class="slider"></td>' ).append( $slider );
$html2 = $( '<tr>' ).append( $html );
$legendHtml = $( '<td colspan="4" style="text-align:center; font-size: 0.7em"></td>' ).append( getSectionLegend( revs ) );
$element = $( '.diff > tbody > tr' ).eq(0).after( $legendHtml );
$element = $( '.diff > tbody > tr' ).eq(0).after( $html2 );
}
function getSectionLegend( revs ) {
var revData = getComposedRevData( revs ),
html = '';
revData.sectionMap.forEach( function( item, key, sectionMap ) {
html += '<span style="color:' + item + '; opacity: 0.25"> ■ </span>' + key + '';
});
return html;
}
// Function to find the initial positions of the slider handles
// Params: revs - revisions data from API
function findInitialValues( revs ) {
var v1, v2, f1 = false, f2 = false, i;
if ( gDiff == 'prev' ) {
for ( i = 0; i < revs.length; i++) {
if( revs[i].revid == gRightRevID ) {
v2 = i+1;
v1 = i;
f1 = true;
f2 = true;
break;
}
}
} else {
for( i = 0; i < revs.length; i++ ) {
if( revs[i].revid == gLeftRevID ) {
v1 = i+1;
f1 = true;
}
}
for ( i = 0; i < revs.length; i++) {
if( revs[i].revid == gRightRevID ) {
v2 = i+1;
f2 = true;
}
}
}
if( f1 === false || f2 === false ) {
return false;
}
return [v1, v2];
}
// Driver function
mw.loader.using( ['jquery.ui.slider', 'jquery.ui.tooltip', 'jquery.tipsy'], function () {
$( document ).ready( function() {
$.ajax( {
url: mw.util.wikiScript( 'api' ),
data: {
action: 'query',
prop: 'revisions',
format: 'json',
rvprop: 'ids|timestamp|user|comment|parsedcomment|size',
titles: gPageName,
formatversion: 2,
rvstartid: gCurRevisionId,
"continue": "",
rvlimit: "120"
},
success: function( data ) {
revs = data.query.pages[0].revisions;
if ( !revs ) {
return;
}
revs.reverse();
vals = findInitialValues( revs );
if( vals !== false ) {
addSlider( revs, vals );
}
}
} );
} );
} );
// see http://stackoverflow.com/a/7419630/4782503
function rainbow( numOfSteps, step ) {
// This function generates vibrant, "evenly spaced" colours (i.e. no clustering). This is ideal for creating easily distinguishable vibrant markers in Google Maps and other apps.
// Adam Cole, 2011-Sept-14
// HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
var r, g, b;
var h = step / numOfSteps;
var i = ~~(h * 6);
var f = h * 6 - i;
var q = 1 - f;
switch(i % 6){
case 0: r = 1; g = f; b = 0; break;
case 1: r = q; g = 1; b = 0; break;
case 2: r = 0; g = 1; b = f; break;
case 3: r = 0; g = q; b = 1; break;
case 4: r = f; g = 0; b = 1; break;
case 5: r = 1; g = 0; b = q; break;
}
var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
return (c);
}