User:Cacycle/wikEdDiff.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | This user script seems to have a documentation page at User:Cacycle/wikEdDiff. |
/* {{en:User:Cacycle/wikEd_template}} <pre clear="all"><nowiki> */
// version info
var wikEdDiffProgramVersion = '0.9.1';
var wikEdDiffProgramDate = 'April 14, 2007';
/*
== wikEdDiff ==
wikEdDiff provides enhanced diff view for comparing different versions of MediaWiki articles
Features:
* Optimized for MediaWiki source texts
* Additions and deletions are highlighted by color in a single article text
* Block moves are detected and indicated by color
* Unchanged parts are omitted from the output
wikEdDiff uses the diff.js tool [[en:User:Cacycle/diff]] and is also an integrated part of wikEd,
the full-featured JavaScript in-browser editor (http://en.wikipedia.org/wiki/User:Cacycle/wikEd)
Homepage: http://en.wikipedia.org/wiki/User:Cacycle/wikEdDiff
Author: Cacycle (http://en.wikipedia.org/wiki/User:Cacycle)
License: This code has been released into the public domain
== Installation ==
* Copy the following short block of code to [[User:YOURUSERNAME/monobook.js]]
* Press SHIFT-Reload to update to the newest version
* PLEASE DO NOT COPY THE WHOLE PROGRAM
* See http://en.wikipedia.org/wiki/User:Cacycle/wikEdDiff for detailed instructions
* Users of wikEd do not have to install wikEdDiff
// ---- START INSTALLATION CODE ----
// install [[User:Cacycle/wikEdDiff]] enhanced diff view using ajax
document.write('<script type="text/javascript" src="'
+ 'http://en.wikipedia.org/w/index.php?title=User:Cacycle/wikEdDiff.js'
+ '&action=raw&ctype=text/javascript&dontcountme=s"></script>');
// ---- END INSTALLATION CODE ----
*/
//
// user configurable variables
//
// wikEdDiff script URL, also defined in wikEd.js
var wikEdDiffScriptSrc = wikEdDiffScriptSrc || 'http://en.wikipedia.org/w/index.php?title=User:Cacycle/diff.js&action=raw&ctype=text/javascript&dontcountme=s';
// allow ajax requests from local copy for testing, also defined in wikEd.js
var wikEdAllowLocalAjax = wikEdAllowLocalAjax || false;
// wikEdDiff css rules
var wikEdDiffCSS = wikEdDiffCSS || [];
WikEdDiffInitObject(wikEdDiffCSS, {
'.wikEdDiffWrapper': 'margin: 0 0 1em 0;',
'.wikEdDiffButtonWrapper': 'text-align: center;',
'.wikEdDiffButton': 'padding: 0; margin: 0.2em 0 0.33em 0;',
'.wikEdDiffDiv': 'background: #faf8f6; padding: 0.5em; border: 1px solid; border-color: #808080;'
});
// path to local images for testing, also defined in wikEd.js
var wikEdImagePathLocal = wikEdImagePathLocal || 'file:///D:/wikEd/images/';
// path to images, also defined in wikEd.js
var wikEdImagePath = wikEdImagePath || '/media/wikipedia/commons/';
// image filenames, also defined in wikEd.js
var wikEdImage = wikEdImage || [];
WikEdDiffInitImage(wikEdImage, {
'wikEdDiff': '0/00/WikEdDiff.png'
});
// user readable texts, copy changes to http://en.wikipedia.org/wiki/User:Cacycle/wikEd_international_en.js
var wikEdText = wikEdText || [];
WikEdDiffInitObject(wikEdText, {
'wikEdDiffButtonImg alt': 'wikEdDiff',
'wikEdDiffButton title': 'Show enhanced diff view',
'wikEdDiffLoading': '...'
});
//
// end of user configurable variables
//
// global dom elements
var wikEdDiffWrapper;
var wikEdDiffButtonWrapper;
var wikEdDiffDiv;
var wikEdDiffButton;
// hash of loaded scripts, also defined in wikEd.js
var wikEdExternalScripts = wikEdExternalScripts || [];
// diff table element, also defined in wikEd.js
var wikEdDiffTable = wikEdDiffTable || [];
// call the setup routine
if (typeof(doneOnloadHook) == 'boolean') {
if (doneOnloadHook == true) {
WikEdDiffSetup();
}
else {
if (typeof(addOnloadHook) == 'function') {
addOnloadHook(WikEdDiffSetup);
}
}
}
else {
window.onload = WikEdDiffSetup;
}
//
// WikEdDiffSetup: create wikEdDiff elements
//
function WikEdDiffSetup() {
// run only once
if (wikEdDiffWrapper != null) {
return;
}
// detect diff table
var table = document.getElementsByTagName('TABLE');
for (var i = 0; i < table.length; i ++) {
if (table[i].className == 'diff') {
wikEdDiffTable = table[i];
}
}
// check if this is a diff page
if (wikEdDiffTable == null) {
return;
}
// detect already loaded external scripts
if (wikEdExternalScripts == null) {
var pageScripts = document.getElementsByTagName('script');
for (var i = 0; i < pageScripts.length; i ++) {
var nameMatch = pageScripts[i].src.match(/\/([^\/]*?)($|\?)/);
if (nameMatch != null) {
var scriptName = nameMatch[1];
if (scriptName != '') {
wikEdExternalScripts[scriptName] = true;
}
}
}
}
// load the external diff script
if (wikEdExternalScripts['diff.js'] == null) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = wikEdDiffScriptSrc;
head.appendChild(script);
wikEdExternalScripts['diff.js'] = true;
}
// add stylesheet definitions (slow method for IE compatibility)
var diffStyle = new WikEdDiffStyleSheet();
var rules = '';
for (var ruleName in wikEdDiffCSS) {
var ruleStyle = wikEdDiffCSS[ruleName];
ruleStyle = ruleStyle.replace(/\{wikEdGrip\}/g, wikEdImage['grip']);
diffStyle.addRule(ruleName, ruleStyle);
}
// create wikEdDiff wrapper
wikEdDiffWrapper = document.createElement('div');
wikEdDiffWrapper.id = 'wikEdDiffWrapper';
wikEdDiffWrapper.className = 'wikEdDiffWrapper';
// create wikEdDiff button wrapper
wikEdDiffButtonWrapper = document.createElement('div');
wikEdDiffButtonWrapper.id = 'wikEdDiffButtonWrapper';
wikEdDiffButtonWrapper.className = 'wikEdDiffButtonWrapper';
wikEdDiffWrapper.appendChild(wikEdDiffButtonWrapper);
// create wikEdDiff button
wikEdDiffButton = document.createElement('button');
wikEdDiffButton.id = 'wikEdDiffButton';
wikEdDiffButton.title = wikEdText['wikEdDiffButton title'];
wikEdDiffButton.className = 'wikEdDiffButton';
wikEdDiffButtonWrapper.appendChild(wikEdDiffButton);
// add button image
var diffImg = document.createElement('img');
diffImg.id = 'wikEdDiffButtonImg';
diffImg.src = wikEdImage['wikEdDiff'];
diffImg.title = wikEdText['wikEdDiffButton title'];
diffImg.alt = wikEdText['wikEdDiffButtonImg alt'];
wikEdDiffButton.appendChild(diffImg);
wikEdDiffDiv = document.createElement('div');
wikEdDiffDiv.id = 'wikEdDiffDiv';
wikEdDiffDiv.className = 'wikEdDiffDiv';
wikEdDiffDiv.style.display = 'none';
// add wrapper after diff table
wikEdDiffWrapper.appendChild(wikEdDiffDiv);
if (wikEdDiffTable.nextSibling != null) {
wikEdDiffTable.parentNode.insertBefore(wikEdDiffWrapper, wikEdDiffTable.nextSibling);
}
else {
wikEdDiffTable.parentNode.appendChild(wikEdDiffWrapper);
}
// add event listener to button
wikEdDiffButton.onclick = WikEdDiff;
// run WikEdDiff if enabled in wikEd
if (typeof(wikEdDiff) == 'boolean') {
if (wikEdDiff == true) {
WikEdDiff();
window.scroll(0, WikEdDiffGetOffsetTop(wikEdDiffDiv));
}
}
return;
}
//
// WikEdDiff: fetch the old versions using ajax to display a diff
//
function WikEdDiff() {
// check if set tup
if (wikEdDiffDiv == null) {
return;
}
// display diff
wikEdDiffDiv.style.display = 'block';
// fetch only once
if (wikEdDiffDiv.innerHTML.length > 0) {
return;
}
// check if this is a diff page
if (wikEdDiffTable == null) {
return;
}
// display div
if (wikEdDiffDiv.innerHTML.length == 0) {
wikEdDiffDiv.innerHTML = wikEdText['wikEdDiffLoading'];
}
// generate request url from MediaWiki variables or from location url
var url;
if (typeof(wgScriptPath) == 'string') {
url = wgScriptPath + '/index.php';
}
else {
url = window.location.protocol + '//' + window.location.hostname + '/' + window.location.pathname;
}
var article;
if (typeof(wgTitle) == 'string') {
article = wgTitle;
}
else {
var articleMatch = window.location.search.match(/(\?|&)title=([^&#]+)/);
article = articleMatch[2];
}
url += '?title=' + encodeURIComponent(article) + '&action=raw&dontcountme=s&maxage=0';
// get diff table and version link cells
var tdArray = document.getElementsByTagName('TD');
var tdOld;
var tdNew;
for (var i = 0; i < tdArray.length; i ++) {
if (tdArray[i].className == 'diff-otitle') {
tdOld = tdArray[i];
}
else if (tdArray[i].className == 'diff-ntitle') {
tdNew = tdArray[i];
break;
}
}
if ( (tdOld == null) || (tdNew == null) ) {
return;
}
var oldVersion = null;
var newVersion = null;
var oldUrl;
var newUrl;
// preview pages use latest article version and textarea
if (/(\?|&)action=submit\b/.test(window.location.search) == true) {
var textarea = document.getElementsByName('wpTextbox1')[0];
if (textarea == null) {
return;
}
newVersion = textarea.value;
if (typeof(wgCurRevisionId) == 'string') {
oldUrl = url + '&oldid=' + wgCurRevisionId;
}
else {
oldUrl = url;
}
}
// diff pages use two different old versions
else {
// get revision id numbers from links in table cells
var versionMatchOld = tdOld.innerHTML.match(/(\?|&)oldid=(\d+)/);
var versionMatchNew = tdNew.innerHTML.match(/(\?|&)oldid=(\d+)/);
if ( (versionMatchOld == null) && (versionMatchNew == null) ) {
return;
}
oldUrl = url + '&oldid=' + versionMatchOld[2];
newUrl = url + '&oldid=' + versionMatchNew[2];
}
// allow ajax request from local copy for testing
if (wikEdAllowLocalAjax == true) {
if (typeof(netscape) == 'object') {
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
}
}
// get the old version using ajax
var ajaxOld = WikEdDiffAjaxInitObject();
if (ajaxOld == null) {
return;
}
ajaxOld.open('GET', oldUrl, true);
ajaxOld.send(null);
// ajax response handler for old version
ajaxOld.onreadystatechange = function() {
if (ajaxOld.readyState != 4) {
return;
}
oldVersion = ajaxOld.responseText;
if (newVersion != null) {
WikEdDiffResponse(oldVersion, newVersion);
}
return;
}
// get the new version using ajax
if (newUrl != null) {
var ajaxNew = WikEdDiffAjaxInitObject();
if (ajaxNew == null) {
return;
}
ajaxNew.open('GET', newUrl, true);
ajaxNew.send(null);
// ajax response handler for new version
ajaxNew.onreadystatechange = function() {
if (ajaxNew.readyState != 4) {
return;
}
newVersion = ajaxNew.responseText;
if (oldVersion != null) {
WikEdDiffResponse(oldVersion, newVersion);
}
return;
}
}
}
//
// WikEdDiffResponse: calculate and display the diff between two versions
//
function WikEdDiffResponse(oldVersion, newVersion) {
// call external diff program
var diffText = WDiffString(oldVersion, newVersion);
if (wikEdFullDiff != true) {
diffText = WDiffShortenOutput(diffText);
}
wikEdDiffDiv.innerHTML = diffText;
wikEdDiffDiv.style.display = 'block';
return;
}
//
// WikEdDiffInitObject: initialize object, keep pre-defined values
//
function WikEdDiffInitObject(array, preset) {
for (var key in preset) {
if (array[key] == null) {
array[key] = preset[key];
}
}
return;
}
//
// WikEdDiffInitImage: initialize images, keep pre-defined values
//
function WikEdDiffInitImage(array, preset) {
for (var key in preset) {
if (array[key] == null) {
// remove MediaWiki path prefixes and add local path
if (wikEdUseLocalImages == true) {
array[key] = wikEdImagePathLocal + preset[key].replace(/^[0-9a-f]+\/[0-9a-f]+\//, '');
}
// add path
else {
array[key] = wikEdImagePath + preset[key];
}
}
}
return;
}
//
// WikEdDiffStyleSheet: create a new style sheet object, also defined in wikEdDiff.js
//
function WikEdDiffStyleSheet(documentObject) {
this.styleElement = null;
if (documentObject == null) {
documentObject = document;
}
// IE
if (documentObject.createStyleSheet) {
this.styleElement = documentObject.createStyleSheet();
}
// standards compliant browsers
else {
this.styleElement = documentObject.createElement('style');
this.styleElement.from = 'text/css';
var insert = documentObject.getElementsByTagName('head')[0];
if (insert != null) {
insert.appendChild(this.styleElement);
}
}
// addRule: add one rule at the time using DOM method, very slow
// IE
this.addRule = function(selector, declaration) {
if (this.styleElement.addRule) {
this.styleElement.addRule(selector, declaration);
}
// standards compliant browsers
else {
if (this.styleElement.sheet != null) {
if (this.styleElement.sheet.insertRule != null) {
this.styleElement.sheet.insertRule(selector + ' { ' + declaration + ' } ', 0);
}
}
}
};
// addRules: add all rules at once, much faster
this.addRules = function(rules) {
this.styleElement.innerHTML = rules;
return;
}
}
//
// WikEdDiffAjaxInitObject: cross browser wrapper for creating new XMLHttpRequest object
//
function WikEdDiffAjaxInitObject() {
var ajax;
// current browsers
try {
ajax = new XMLHttpRequest();
}
catch (e) {
// IE 6
try {
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {
// IE 5.5
try {
ajax = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) { }
}
}
return(ajax);
}
//
// WikEdDiffGetOffsetTop: get element offset relative to window top
//
function WikEdDiffGetOffsetTop(element) {
var offset = 0;
do {
offset += element.offsetTop;
} while ( (element = element.offsetParent) != null );
return(offset);
}
/* </nowiki></pre> */