Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* ============================================== *\
** WikiApps JavaScript GUI, API & AJAX Library
** for MediaWiki v1.13 and above
**
** Created (c) by Alex Barley [[User:Ale_jrb]]
** version 1.0.11
\* ============================================== */
// mediawiki objects
function wa_mediawikiUser ( who ) {
if ( ! who ) return false;
var waUserObj = this;
this.rootApi = mw.config.get('wgScriptPath') + '/api.php';
this.getUserGroup = function(group, onDone) {
var groups;
if (who == 'self') {
groups = mw.config.get('wgUserGroups');
for (var i = 0; i < groups.length; i ++) {
if (groups[i] == group) return true;
}
return false;
} else {
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi + '?format=xml&action=query&list=users&usprop=groups&ususers=' + encodeURIComponent(who);
this.ajax.doRequest (function() {
wa_mediawikiUser.apiResponse = waUserObj.ajax.response;
waUserGroups = wa_mediawikiUser.apiResponse.getElementsByTagName('g');
for (var i = 0; i < waUserGroups.length; i ++) {
if (waUserGroups[i].childNodes[0].nodeValue == group) { onDone(true); return true; }
}
onDone(false);
});
}
};
this.getUserContribs = function ( number, onDone ) {
if (who == 'self') { var user = mw.config.get('wgUserName'); } else { var user = who; }
if (number === 0) number = 1;
if (number > 100) number = 100;
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi + '?format=xml&action=query&list=usercontribs&uclimit=' + number + '&ucuser=' + encodeURIComponent(who) + '&ucprop=ids|title|timestamp|comment';
this.ajax.doRequest (function() {
wa_mediawikiUser.apiResponse = waUserObj.ajax.response;
waUserObj.editDetails = [];
if (wa_mediawikiUser.apiResponse.getElementsByTagName('item').length === 0) {
waUserObj.editDetails[0] = {};
waUserObj.editDetails[0].pageid = false; waUserObj.editDetails[0].revid = false;
waUserObj.editDetails[0].title = false; waUserObj.editDetails[0].timestamp = false;
}
for (var i = 0; i < wa_mediawikiUser.apiResponse.getElementsByTagName('item').length; i ++) { // for each revision
var tempData = wa_mediawikiUser.apiResponse.getElementsByTagName('item')[i];
waUserObj.editDetails[i] = {};
waUserObj.editDetails[i].pageid = tempData.getAttribute('pageid');
waUserObj.editDetails[i].revid = tempData.getAttribute('revid');
waUserObj.editDetails[i].title = tempData.getAttribute('title');
waUserObj.editDetails[i].timestamp = tempData.getAttribute('timestamp');
}
onDone();
});
};
this.getUserLogs = function(number, onDone) {
if (who == 'self') { var user = mw.config.get('wgUserName'); } else { var user = who; }
if (number === 0) number = 1;
if (number > 100) number = 100;
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi + '?format=xml&action=query&list=logevents&lelimit=' + number + '&leuser=' + encodeURIComponent(who) + '&leprop=ids|title|timestamp|comment|type';
this.ajax.doRequest (function() {
wa_mediawikiUser.apiResponse = waUserObj.ajax.response;
waUserObj.logDetails = [];
if (wa_mediawikiUser.apiResponse.getElementsByTagName('item').length === 0) {
waUserObj.logDetails[0] = {};
waUserObj.logDetails[0].pageid = false; waUserObj.logDetails[0].logid = false;
waUserObj.logDetails[0].title = false; waUserObj.logDetails[0].timestamp = false;
waUserObj.logDetails[0].type = false; waUserObj.logDetails[0].action = false;
}
for (var i = 0; i < wa_mediawikiUser.apiResponse.getElementsByTagName('item').length; i ++) { // for each revision
var tempData = wa_mediawikiUser.apiResponse.getElementsByTagName('item')[i];
waUserObj.logDetails[i] = {};
waUserObj.logDetails[i].pageid = tempData.getAttribute('pageid');
waUserObj.logDetails[i].logid = tempData.getAttribute('logid');
waUserObj.logDetails[i].title = tempData.getAttribute('title');
waUserObj.logDetails[i].timestamp = tempData.getAttribute('timestamp');
waUserObj.logDetails[i].type = tempData.getAttribute('type');
waUserObj.logDetails[i].action = tempData.getAttribute('action');
}
onDone();
});
};
// construct
if (who == 'self') {
this.isSysop = this.getUserGroup('sysop');
this.isRollback = this.getUserGroup('rollback');
this.isAutoconfirmed = this.getUserGroup('autoconfirmed');
}
}
var waUser = new wa_mediawikiUser('self');
function wa_mediawikiApi() {
// this function handles a multitude of Wiki API calls.
var wa_mediaWiki = this; // callback
this.rootApi = mw.config.get('wgScriptPath') + '/api.php';
this.apiResponse = false; // actual response from API - allows manual parsing, if desired
this.apiPage = {};
this.apiPage.plain = false; // the provided name of the last page called in this object
this.apiPage.enc = false; // the encoded name of the last page called in this object
this.data = {}; // general response of the method called - associative array filled with requested data
this.ajax = false; // the ajax object - allows manual access to the ajax object/functions, if desired
this.onCompleteAction = function() { return true; }; // onCompleteAction is the function that will be called whenever the current operation is complete
this.internalOnComplete = function() { return true; }; // internalOnComplete is the function that will be called (callback) when an internal operation completes
this.internalRequest = false; // internalRequest specifies whether this is an internal callback or not
this.getToken = function(token, page) {
// Store per-run information
this.apiPage['plain'] = page;
if (page.indexOf('%20') > -1) {
this.apiPage['enc'] = page;
} else {
this.apiPage['enc'] = encodeURIComponent(page);
}
page = this.apiPage['enc'];
token = token.toLowerCase();
// Check that the operation is supported
var requestToken = "";
if (token.match(/(edit|delete|protect|move|block|unblock)/i)) {
requestToken = "csrf";
} else if (token === "rollback") {
requestToken = "rollback";
} else {
// Not supported
return false;
}
// Build the response handler
var onTokenResponse = function() {
console.log("Got response! " + requestToken);
// Store the result
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
// Parse result data
var pageData = wa_mediaWiki.apiResponse.getElementsByTagName("page")[0];
var tokenData = wa_mediaWiki.apiResponse.getElementsByTagName("tokens")[0];
var pageId = pageData.getAttribute("pageid");
var isMissing = pageData.getAttribute("missing");
var tokenValue = tokenData.getAttribute(requestToken + "token");
// Store specific result data
wa_mediaWiki.data['token'] = [];
wa_mediaWiki.data['token'].push(
wa_mediaWiki.apiPage['enc'],
encodeURIComponent(tokenValue));
// Internal result format
// [<page is missing>, <page ID>]
var internalResult = [];
internalResult[0] = !!isMissing;
internalResult[1] = pageId ? pageId : false;
if (wa_mediaWiki.internalRequest == false) {
wa_mediaWiki.onCompleteAction(wa_mediaWiki.data);
} else {
wa_mediaWiki.internalRequest = false;
wa_mediaWiki.internalOnComplete(wa_mediaWiki.data, internalResult);
}
};
// Run the request
console.log("Running the request!");
var requestUrl = this.rootApi + "?action=query&format=xml&meta=tokens&type=" + requestToken + "&titles=" + page;
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = requestUrl;
this.ajax.doRequest(onTokenResponse);
return true;
}
this.getPage = function(page, revisions, properties) {
// set vars
if (properties == 'rollback-int') {
properties = 'rollback';
} else {
this.apiPage['plain'] = page;
if (page.indexOf('%20') > -1) { this.apiPage['enc'] = page; } else { this.apiPage['enc'] = encodeURIComponent(page); }
page = this.apiPage['enc'];
}
// verification
if (revisions > 500) revisions = 500;
if (properties.match(/^(?:(?:ids|flag|timestamp|user|size|comment|content|rollback)\|?)*$/i) == null) properties = 'ids|user|content';
// go
if (properties.match(/rollback/i) != null) {
var rollbackRequest = true;
properties = properties.replace(/\|rollback\|/ig, '');
properties = properties.replace(/rollback\|/ig, '');
properties = properties.replace(/\|rollback/ig, '');
properties = properties.replace(/\|\|/ig, '|');
properties = properties.replace(/rollback/ig, '');
var requestUrl = this.rootApi + '?action=query&format=xml&prop=revisions&titles=' + page + '&rvtoken=rollback&rvprop=' + properties + '&rvlimit=' + revisions;
} else {
var rollbackRequest = false;
var requestUrl = this.rootApi + '?action=query&format=xml&prop=revisions&titles=' + page + '&rvprop=' + properties + '&rvlimit=' + revisions;
}
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = requestUrl;
this.ajax.doRequest (function() {
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
wa_mediaWiki.data = new Object;
if (wa_mediaWiki.apiResponse.getElementsByTagName('rev')[0] == null) { wa_mediaWiki.data['page'] = new Object; wa_mediaWiki.data['page']['status'] = 'E'; } else {
wa_mediaWiki.data['page'] = new Object;
wa_mediaWiki.data['page']['revisions'] = [];
wa_mediaWiki.data['page']['status'] = 'OK';
for (var i = 0; i < wa_mediaWiki.apiResponse.getElementsByTagName('rev').length; i ++) { // for each revision
wa_mediaWiki.data['page']['revisions'][i] = new Object;
// get details
if (properties.match(/ids/i) != null) wa_mediaWiki.data['page']['revisions'][i]['id']
= wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('revid');
if (properties.match(/size/i) != null) wa_mediaWiki.data['page']['revisions'][i]['size']
= wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('size');
if (properties.match(/user/i) != null) wa_mediaWiki.data['page']['revisions'][i]['user']
= wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('user');
if (properties.match(/comment/i) != null) wa_mediaWiki.data['page']['revisions'][i]['comment']
= wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('comment');
if (properties.match(/timestamp/i) != null) wa_mediaWiki.data['page']['revisions'][i]['timestamp']
= wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('timestamp');
if ( (rollbackRequest == true) && (i == 0) ) {
wa_mediaWiki.data['token'] = [];
wa_mediaWiki.data['token'][1] = encodeURIComponent(wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].getAttribute('rollbacktoken'));
var internal = [];
if (wa_mediaWiki.apiResponse.getElementsByTagName('page')[0].getAttribute('missing') != null) { internal[0] = true; } else { internal[0] = false; }
}
// get content
if (properties.match(/content/i) != null) {
wa_mediaWiki.data['page']['revisions'][i]['content'] = '';
for (var j = 0; j < wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].childNodes.length; j ++) {
wa_mediaWiki.data['page']['revisions'][i]['content'] += wa_mediaWiki.apiResponse.getElementsByTagName('rev')[i].childNodes[j].nodeValue;
}
}
}
}
if (wa_mediaWiki.internalRequest == false) {wa_mediaWiki.onCompleteAction(wa_mediaWiki.data); } else
{ if (typeof internal == 'undefined') { var internal = false; } wa_mediaWiki.internalRequest = false; wa_mediaWiki.internalOnComplete(wa_mediaWiki.data, internal); }
});
return true;
}
this.getLastNotUser = function(page, excludeWho) {
// this function gets the username of the most recent editor to the page who ISN'T excludeWho
if (typeof excludeWho != 'string') return false;
this.apiPage['plain'] = page;
if (page.indexOf('%20') > -1) { this.apiPage['enc'] = page; } else { this.apiPage['enc'] = encodeURIComponent(page); }
page = this.apiPage['enc'];
var requestUrl = this.rootApi + '?action=query&format=xml&prop=revisions&titles=' + page + '&rvprop=user&rvlimit=1&rvexcludeuser=' + encodeURIComponent(excludeWho);
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = requestUrl;
this.ajax.doRequest (function() {
var ret;
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
if (wa_mediaWiki.apiResponse.getElementsByTagName('rev')[0] == null) {
// an error occurred - sort it
if (wa_mediaWiki.apiResponse.getElementsByTagName('rev')[0].getAttribute('missing') != null) { ret = 'missing'; } else {
ret = 'no-other-user'; }
} else {
ret = wa_mediaWiki.apiResponse.getElementsByTagName('rev')[0].getAttribute('user');
}
wa_mediaWiki.onCompleteAction(ret);
});
return true;
}
this.editPage = function(title, text, summary, minor, addWhere, token) {
// shortcut to performAction('edit')
var details = [];
details[0] = text;
details[1] = summary;
details[2] = minor;
details[3] = addWhere;
wa_mediaWiki.performAction('edit', title, details, token);
return true;
}
this.deletePage = function(title, reason, token) {
// shortcut to performAction('delete')
var details = reason;
wa_mediaWiki.performAction('delete', title, details, token);
return true;
}
this.rollbackPage = function(title, user, summary, token) {
// shortcut to performAction('rollback')
// NB. a user must be provided; rollback will only occur if they are the last editor to the page.
var details = [];
details[0] = user;
if (summary !== false) { details[1] = summary; } else { details[1] = ''; }
wa_mediaWiki.performAction('rollback', title, details, token);
}
this.performAction = function(action, target, details, token, internal) {
// this module only accepts block, edit, rollback and deletion requests. Other actions must be performed manually, though the getToken method allows the
// easy retrieval of the correct token for almost any action.
// --
// NB. internal is an internal parameter, allowing library to communicate internal data between functions. Modifying it will result in unexpected actions.
// verification
if ( (token == null) || (token == '') || (token == 0) || (token == false) ) {
// get a token
this.internalRequest = true;
this.internalOnComplete = function(passToken, internal) { wa_mediaWiki.performAction(action, target, details, passToken['token'][1], internal); };
this.getToken(action, target);
return false;
}
if (internal === undefined) {
internal = [];
}
// set vars
this.apiPage['plain'] = target;
if (target.indexOf('%20') > -1) { this.apiPage['enc'] = target; } else { this.apiPage['enc'] = encodeURIComponent(target); }
target = this.apiPage['enc'];
if (details == null) { details = ''; } else if (typeof(details) == 'object') { for (x in details) { if (typeof details[x] == 'string') details[x] = encodeURIComponent(details[x]); } } else { details = encodeURIComponent(details); }
// go
switch ( action ) {
case 'edit': // shortcut to this method from editPage method
if (typeof(details) != 'object') return false; // we need an array:
if (typeof(details[0]) != 'string') details[0] = ''; //details[0] - text
if (typeof(details[1]) != 'string') details[1] = ''; //details[1] - edit summary
if (typeof(details[2]) != 'boolean') details[2] = false; //details[2] - minor edit?
if (typeof(details[3]) != 'string') details[3] = 'text';//details[3] - appendtext, prependtext, text
if (details[2] == true) { var minor = 'minor=true'; } else { var minor = 'notminor=true'; }
if (internal[0] == true) details[3] = 'text';
if (details[3] == 'appendtext') { details[0] = encodeURIComponent('\n\n') + details[0]; }
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi;
this.ajax.postParams = 'format=xml&action=edit&title=' + target + '&summary=' + details[1] + '&' + details[3] + '=' + details[0] + '&' + minor + '&token=' + token;
this.ajax.post (function() {
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
wa_mediaWiki.onCompleteAction();
return true;
});
break;
case 'rollback':
if ( internal[0] == true ) { wa_mediaWiki.onCompleteAction(false); return false; }
if ( (details[1] == '') || (details[1] == null) || (typeof details[1] == 'undefined') ) { var useCustomSummary = false; } else { var useCustomSummary = true; }
var params = 'format=xml&action=rollback&title=' + target + '&user=' + details[0] + '&token=' + token;
if (useCustomSummary == true) params += '&summary=' + details[1];
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi;
this.ajax.postParams = params;
this.ajax.post (function() {
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
if ( (wa_mediaWiki.apiResponse.getElementsByTagName('error')[0] == null) || (wa_mediaWiki.apiResponse.getElementsByTagName('error')[0].getAttribute('code') == null) )
{
//if (wa_mediaWiki.apiResponse.getElementsByTagName('rollback')[0].getAttribute('revid') == wa_mediaWiki.apiResponse.getElementsByTagName('rollback')[0].getAttribute('old_revid')) {
// var r = false;
//} else {
var r = wa_mediaWiki.apiResponse.getElementsByTagName('rollback')[0].getAttribute('revid');
//}
} else { var r = false; }
wa_mediaWiki.onCompleteAction(r);
return true;
});
break;
case 'delete':
// we have the required token. Perform the deletion!
if (internal[0] == true) return false;
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi;
this.ajax.postParams = 'format=xml&action=delete&title=' + target + '&reason=' + details + '&token=' + token;
this.ajax.post (function() {
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
wa_mediaWiki.onCompleteAction(internal[1]);
return true;
});
return true;
break;
case 'block':
// additional verification for blocking
if (typeof(details) != 'object') return false; // we need an array:
if (typeof(details[0]) != 'string') return false; //details[0] - expiry as string - you must provide this, or the block will not happen
if (typeof(details[1]) != 'boolean') return false; //details[1] - anonymous only - you must provide this, or the block will not happen
if (typeof(details[2]) != 'string') details[2] = ''; //details[2] - reason as string
if (typeof(details[3]) != 'boolean') details[3] = true; //details[3] - prevent account creation
if (typeof(details[4]) != 'boolean') details[4] = true; //details[4] - autoblock - default, hardblock
// build valid syntax
if (details[1] == true) { var anonOnly = '&anononly'; } else { var anonOnly = ''; }
if (details[3] == true) { var createAccount = '&nocreate'; } else { var createAccount = ''; }
if (details[4] == true) { var autoblock = '&autoblock'; } else { var autoblock = ''; }
// we have the required token
this.ajax = new wa_ajaxcall();
this.ajax.requestUrl = this.rootApi;
this.ajax.postParams = 'format=xml&action=block&user=' + target + '&expiry=' + details[0] + '&reason=' + details[2] + anonOnly + createAccount +
autoblock + '&token=' + token;
this.ajax.post (function() {
wa_mediaWiki.apiResponse = wa_mediaWiki.ajax.response;
wa_mediaWiki.onCompleteAction();
return true;
});
break;
default:
return false;
break;
}
}
}
// non-gui objects
function wa_ajaxcall () {
var waMyAjax = this;
this.requestType = 'GET';
this.responseType = 'xml';
this.requestUrl = '';
waMyAjax.pageRequest = false;
this.postParams = '';
this.response = false;
this.abort = function () {
if ( waMyAjax.pageRequest != false ) {
waMyAjax.pageRequest.abort ();
return true;
}
}
this.post = function ( runOnComplete ) {
waMyAjax.requestType = 'POST';
waMyAjax.doRequest ( runOnComplete );
}
this.get = function ( runOnComplete ) {
waMyAjax.requestType = 'GET';
waMyAjax.doRequest ( runOnComplete );
}
this.doRequest = function ( runOnComplete ) {
if ( this.requestUrl == '' ) return false;
if ( window.XMLHttpRequest ) { // if good browser
waMyAjax.pageRequest = new XMLHttpRequest ();
}
else if ( window.ActiveXObject ) { // if IE
try { // try request 1
waMyAjax.pageRequest = new ActiveXObject ( "Msxml2.XMLHTTP" );
}
catch ( e ) { // it failed.
try { // try request 2
waMyAjax.pageRequest = new ActiveXObject ( "Microsoft.XMLHTTP" );
}
catch ( e ) { return false; }
}
}
else
{
return false;
}
waMyAjax.pageRequest.onreadystatechange = function () {
if ( waMyAjax.pageRequest.readyState == 4 ) {
if ( waMyAjax.pageRequest.status == 200 ) {
if ( waMyAjax.responseType == 'xml' ) {
waMyAjax.response = waMyAjax.pageRequest.responseXML;
} else {
waMyAjax.response = waMyAjax.pageRequest.responseText;
}
if ( waMyAjax.pageRequest.responseXML ) waMyAjax.responseXML = waMyAjax.pageRequest.responseXML;
if ( waMyAjax.pageRequest.responseText ) waMyAjax.responseText = waMyAjax.pageRequest.responseText;
runOnComplete ();
}
}
}
if ( this.requestType == 'GET' ) {
// do get request
waMyAjax.pageRequest.open('GET', this.requestUrl, true);
switch (this.responseType) {
default: case 'xml':
if ( waMyAjax.pageRequest.overrideMimeType ) { waMyAjax.pageRequest.overrideMimeType ( 'text/xml' ); } else {
waMyAjax.pageRequest.setRequestHeader ( 'Content-type', 'text/xml' ); }
break;
case 'html':
if ( waMyAjax.pageRequest.overrideMimeType ) waMyAjax.pageRequest.overrideMimeType ( 'text/html' );
break;
}
waMyAjax.pageRequest.send ( null );
}
else if ( this.requestType == 'POST' )
{
// do post request
waMyAjax.pageRequest.open ( 'POST', this.requestUrl, true );
waMyAjax.pageRequest.setRequestHeader ( "Content-type", "application/x-www-form-urlencoded" );
waMyAjax.pageRequest.setRequestHeader ( "Content-length", this.postParams.length );
waMyAjax.pageRequest.setRequestHeader ( "Connection", "close" );
waMyAjax.pageRequest.send ( this.postParams );
}
else
{ /* unrecognised */ }
};
return true;
}
// drawing objects
function wa_document () {
// document -- main interface representation. grabs required document ids for easy use. not used directly. sits above wiki interface, to allow override
// vars
this.wk_base = document.getElementsByTagName('body')[0];
this.wk_content_base = document.getElementById('bodyContent');
this.wk_top_links_port = document.getElementById('p-personal');
this.wk_top_links = document.getElementById('pt-watchlist') ? document.getElementById('pt-watchlist').parentNode : this.wk_top_links_port;
this.wk_pref_link = document.getElementById('pt-preferences');
this.root = mw.config.get('wgArticlePath');
this.user = mw.config.get('wgUserName');
this.page = mw.config.get('wgTitle');
return true;
}
function wa_window ( parent_opt ) {
// window -- main interface compontent. wikiapps gui is built of windows. they're esentially divs, attached to a parent div. child of document.
// providing a parent_opt object (must be another window) will result in that object being the parent node. otherwise, the default document
// object is used.
// vars - enable quick window creation by setting CSS style defaults
this.win_fill = false; this.win_bd_wd = 0;
this.win_top = 0; this.win_bd_rt = '';
this.win_left = 0; this.win_bd_lf = '';
this.win_width = 0; this.win_bd_bt = '';
this.win_height = 0; this.win_bd_tp = '';
this.win_bg = '#000000'; this.win_class = '';
this.win_bd = '#000000'; this.win_alpha = 1;
this.win_disp = 'block'; this.win_obj = document.createElement ( 'div' );
this.win_z = '9999999';
this.win_pos = 'absolute'; this.win_handler = 'click';
this.win_func = function() { }; this.win_fade = 'visible';
this.win_attached = false; this.win_cursor = 'auto';
this.win_padding = 3; this.win_content = '';
this.win_margin = 0; this.win_id = '';
this.win_talign = 'left'; this.win_overflow = 'visible';
this.win_right = false; this.win_bottom = false;
this.win_maintfill = true; this.hidden = false;
this.win_fontsize = 10;
if ( parent_opt == null ) { this.parentObj = this.wk_base; } else {
if ( typeof parent_opt.win_obj !== 'undefined' ) {
this.parentObj = parent_opt.win_obj;
} else if ( parent_opt != null ) {
this.parentObj = parent_opt;
}
}
// methods
this.applyAll = function() {
// applyAll - method
// applyAll applies current settings to the window object. if createNew is set as true, a new window will be created and appended to the base.
// if not provided, the current object's settings will be updated. special behaviour: setting win_fill to true will cause the window to
// automatically maintain the shape of the window. setting it to false will disable auto updating, and unfill the screen.
this.win_obj.style.position = this.win_pos;
this.win_obj.style.zIndex = this.win_z;
// special behaviour - fill screen, usage background cover etc. only 1 per page
if (this.win_fill == true) {
this.win_obj.style.position = 'fixed';
this.win_obj.style.top = '0px';
this.win_obj.style.left = '0px';
this.win_obj.style.width = document.documentElement.clientWidth + 'px';
this.win_obj.style.height = document.documentElement.clientHeight + 'px';
// fill screen - attach updater to window resize
var wa_selfFill = this;
if (this.win_maintfill == true) {
if (window.addEventListener) {
window.addEventListener('resize', function() {
wa_selfFill.applyAll();
}, false);
}
else
{
window.attachEvent('onresize', function() {
wa_selfFill.applyAll();
});
}
}
}
else
{
if (this.win_right !== false) { this.win_obj.style.right = this.win_right + 'px'; } else { this.win_obj.style.left = this.win_left + 'px'; }
if (this.win_bottom !== false) { this.win_obj.style.bottom = this.win_bottom + 'px'; } else { this.win_obj.style.top = this.win_top + 'px'; }
if (this.win_width != 0) { this.win_obj.style.width = this.win_width + 'px'; } else { this.win_obj.style.width = 'auto'; }
if (this.win_height != 0) { this.win_obj.style.height= this.win_height + 'px'; } else { this.win_obj.style.height = 'auto'; }
}
if (this.win_obj.addEventListener) { this.win_obj.addEventListener(this.win_handler, this.win_func, false); }
else { this.win_obj.attachEvent('on'+this.win_handler, this.win_func); }
this.win_obj.style.backgroundColor = this.win_bg;
this.win_obj.style.padding = this.win_padding + 'px';
if (this.win_margin != 'auto') { this.win_obj.style.margin = this.win_margin + 'px'; } else { this.win_obj.style.margin = 'auto'; }
this.win_obj.style.border = this.win_bd_wd + 'px solid ' + this.win_bd;
if (this.win_bd_rt != '') this.win_obj.style.borderRight = this.win_bd_rt;
if (this.win_bd_tp != '') this.win_obj.style.borderTop = this.win_bd_tp;
if (this.win_bd_bt != '') this.win_obj.style.borderBottom = this.win_bd_bt;
if (this.win_bd_lf != '') this.win_obj.style.borderLeft = this.win_bd_lf;
this.win_obj.style.cursor = this.win_cursor;
this.win_obj.style.overflow = this.win_overflow;
this.win_obj.style.opacity = this.win_alpha.toString();
this.win_obj.style.MozOpacity = this.win_alpha.toString();
this.win_obj.style.filter = 'alpha(opacity='+ (this.win_alpha * 100) +')';
this.win_obj.style.textAlign = this.win_talign;
this.win_obj.style.fontSize = this.win_fontsize + 'px';
// compatibility with 'hide' module
if (this.hidden == false) this.win_obj.style.display = this.win_disp;
this.win_obj.innerHTML = this.win_content;
if (this.win_attached == false) { this.parentObj.appendChild(this.win_obj); this.win_attached = true; }
return true; // successful init
};
// special methods - effects for windows
this.center = function(centerPositions, maintainCenter, offset) {
// center - places the window in the centre of the user's screen. set maintainCenter to true and this position will be kept even if
// the window is resized.
if (((this.win_pos != 'fixed') && (this.win_pos != 'absolute')) || (this.win_fill == true)) { return false; }
var screenWidth = document.documentElement.clientWidth;
var screenHeight = document.documentElement.clientHeight;
var myWidth = this.win_obj.offsetWidth;
var myHeight = this.win_obj.offsetHeight;
var leftPos = ((screenWidth / 2) - (myWidth / 2));
var topPos = ((screenHeight / 2) - (myHeight / 2));
if (typeof offset == 'object') {
leftPos += offset[0];
topPos += offset[1];
}
if ((centerPositions == 'left') || (centerPositions == 'both')) this.win_obj.style.left = leftPos + 'px';
if ((centerPositions == 'top') || (centerPositions == 'both')) this.win_obj.style.top = topPos + 'px';
if (maintainCenter == true) {
var wa_selfCenter = this;
if (window.addEventListener) {
window.addEventListener('resize', function() {
wa_selfCenter.center(centerPositions);
}, false);
}
else
{
window.attachEvent('onresize', function() {
wa_selfCenter.center(centerPositions);
});
}
}
return true;
};
this.fade = function(fadeSpeed, opacityLimit, runWhenFinished) {
// fade - toggle method - the object will be faded in if currently hidden, and faded out if currently visible.
var stepDefault = 20;
var stepNumber = fadeSpeed * stepDefault;
var stepSize = 1 / stepNumber;
var wa_selfFade = this;
if (opacityLimit == null) opacityLimit = 0;
if (interval != null) clearInterval(interval);
// user call - prepare fade
if (this.win_fade == 'visible') {
// start fade out
var tempAlpha = 1; // just in case
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
var interval = setInterval(function() {
tempAlpha = parseFloat(wa_selfFade.win_obj.style.opacity);
tempAlpha = tempAlpha - stepSize;
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
if (tempAlpha <= (0 + opacityLimit)) {
tempAlpha = (0 + opacityLimit);
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
wa_selfFade.win_obj.style.display = 'none';
wa_selfFade.win_fade = 'invisible';
if (runWhenFinished != null) runWhenFinished();
clearInterval (interval);
}
}, (1000 / stepDefault));
}
else
{
// start fade in
var tempAlpha = 0; // just in case
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
this.win_obj.style.display = 'block';
var interval = setInterval(function() {
tempAlpha = parseFloat(wa_selfFade.win_obj.style.opacity);
tempAlpha = tempAlpha + stepSize;
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
if (tempAlpha >= (1 - opacityLimit)) {
tempAlpha = (1 - opacityLimit);
wa_selfFade.win_alpha = tempAlpha;
wa_selfFade.win_obj.style.opacity = tempAlpha;
wa_selfFade.win_obj.style.MozOpacity = tempAlpha;
wa_selfFade.win_obj.style.filter = 'alpha(opacity='+ (tempAlpha * 100) +')';
wa_selfFade.win_fade = 'visible';
if (runWhenFinished != null) runWhenFinished();
clearInterval (interval);
}
}, (1000 / stepDefault));
}
return true;
};
this.setLocation = function( toLeft, toTop, domMove ) {
// this is a shortcut for setting the position of a window
if ( ! domMove ) {
this.win_top = toTop;
this.win_left = toLeft;
this.applyAll();
} else {
this.win_obj.style.left = toLeft + 'px';
this.win_obj.style.top = toTop + 'px';
}
return true;
};
this.move = function(toTop, toLeft, time, runWhenFinished) {
// time is the length of time for the move. To be smooth, the move needs about a frame per 5 pixels of movement, regardless of time.
if (runWhenFinished == null) runWhenFinished = function() { };
if ( (toTop == this.win_top) && (toLeft == this.win_left) ) return false;
// first, calculate the distance to be travelled on both sides
var topDis = toTop - this.win_top;
var leftDis = toLeft - this.win_left;
// pick the bigger one
if (Math.abs(topDis) >= Math.abs(leftDis)) { var moveDis = Math.abs(topDis); } else { var moveDis = Math.abs(leftDis); }
// divide by the time to get how many pixels we have to move per second
var pps = moveDis / time;
var smoothSteps = ((1 / time) * 4);
var fps = pps / smoothSteps;
// we know the number of frames per second. Now, we need to know how far to move in each direction per step. Multiply the fps by the time,
// to get the total steps then divide the total distance by the total steps to get a value.
var totalSteps = fps * time;
if (topDis > 0) { var topMove = smoothSteps; } else if (topDis < 0) { var topMove = (smoothSteps * -1); } else { var topMove = 0; }
if (leftDis > 0) { var leftMove = smoothSteps; } else if (leftDis < 0) { var leftMove = (smoothSteps * -1); } else { var leftMove = 0; }
var wa_selfMove = this;
var i = 0;
var interval = setInterval(function() {
var newTop = wa_selfMove.win_top + topMove;
var newLeft = wa_selfMove.win_left + leftMove;
wa_selfMove.setLocation(newTop, newLeft);
if (i >= totalSteps) { wa_selfMove.setLocation(toTop, toLeft); clearInterval(interval); runWhenFinished(); }
i ++;
}, (1000 / fps));
};
this.hide = function () {
this.hidden = true;
this.win_obj.style.display = 'none';
return true;
};
this.show = function () {
this.hidden = false;
this.win_obj.style.display = 'block';
return true;
};
this.addScriptEvent = function(eventHandler, eventFunction) {
if (this.win_obj.addEventListener) {
this.win_obj.addEventListener(eventHandler, eventFunction, false);
}
else
{
this.win_obj.attachEvent('on' + eventHandler, eventFunction);
}
};
return true;
}
function wa_element(elementType) {
// element -- wa building block. elements can be of any type, but if a div, use of wa_window is recommended. element offers a greater level of control, but less automation than
// windows. elementType must be a valid html element.
if (elementType == null) return false;
this.ele_obj = document.createElement(elementType);
this.attach = function(attachTo, attachWhere) {
// attachWhere can be [append, before]. if blank, append is used.
if (attachTo == null) return false;
if (attachWhere == null) var attachWhere = 'append';
switch (attachWhere) {
case 'after':
attachTo.parentNode.appendChild(this.ele_obj);
break;
case 'before':
attachTo.parentNode.insertBefore(this.ele_obj, attachTo);
break;
default:
return false;
break;
}
return true;
};
this.addScriptEvent = function(eventHandler, eventFunction) {
if (this.ele_obj.addEventListener) {
this.ele_obj.addEventListener(eventHandler, eventFunction, false);
}
else
{
this.ele_obj.attachEvent('on' + eventHandler, eventFunction);
}
};
this.destroy = function() {
var selfElement = this.ele_obj;
selfElement.parentNode.removeChild(selfElement);
selfElement = null;
return false;
};
return true;
}
$(document).ready( function( $ ) {
wa_window.prototype = new wa_document;
wa_element.prototype = new wa_document;
});
// handy functions
// arrays
function in_array ( needle, haystack, recursive ) {
if ( recursive == true ) {
for ( var i in haystack ) { //var i = 0; i < haystack.length; i ++ ) {
if ( ( typeof haystack[i] == 'object' ) && ( typeof haystack[i] != 'function' ) ) {
var t = in_array ( needle, haystack[i], true );
if ( t == true ) return t;
} else {
if ( haystack[i] == needle ) return true;
}
}
return false;
} else {
if ( typeof haystack != 'object' ) return false;
for ( var i = 0; i < haystack.length; i ++ ) {
if ( haystack[i] == needle ) return true;
}
return false;
}
}
function sort_array_multi(array, id, direction) {
// this function sorts a multi-dimentional array into numerical order based
// on an id field in one of the sets.
// e.g. [0] = [1, hi]
// [1] = [3, test]
// [2] = [2, boo]
// where [#][0] is the id field would be sorted to [0], [2], [1] is acsending order etc.
if (typeof array != 'object') return false;
if ( (direction != 'ascending') && (direction != 'descending') ) { direction = 'descending'; }
if (typeof id != 'number') id = 0;
var index = []; // the index array is what keeps track of the ids in the array before sorting
for (var i = 0; i < array.length; i ++) {
index[i] = array[i][id] + '::' + i;
}
// first, sort the index array into the correct order.
index.sort(function(a,b) {
var ta = a; var tb = b;
ta = ta.substr(0, ta.indexOf('::'));
tb = tb.substr(0, tb.indexOf('::'));
if (direction == 'ascending') { return (ta - tb); } else { return (tb - ta); }
});
// the index array is now in the right order. build a new array with full content based off the order in the index array.
var newArray = [];
for (var i = 0; i < index.length; i ++) {
var aid = index[i].substr(index[i].indexOf('::') + 2);
newArray[i] = array[aid];
}
return newArray;
}
function echo_nodes_recursive ( parent ) {
var nex = '';
if ( ! parent.childNodes ) {
if (parent.nodeValue) if (parent.nodeValue != '') return parent.nodeValue;
return false;
} else
if (parent.childNodes.length == 0) {
if (parent.nodeValue) if (parent.nodeValue != '') return parent.nodeValue;
return false;
}
for (var i = 0; i < parent.childNodes.length; i ++) {
var nex2 = echo_nodes_recursive(parent.childNodes[i]);
if (nex2 != false) nex = nex + nex2;
}
return nex;
}
// internet explorer
function ie_create_document() {
if (typeof ActiveXObject == 'undefined') return false;
var implementations = ['Microsoft.XMLDOM', 'Msxml2.DOMDocument.3.0', 'MSXML2.DOMDocument', 'MSXML.DOMDocument'];
for (var ii in implementations) {
try {
var r = new ActiveXObject(implementations[ii]);
return r;
} catch (e) {}
}
return false;
}
function ie_getElementById(parent, id) {
// parent should be document or an AJAX return etc.
if (parent.childNodes.length == 0) return false;
for (var i = 0; i < parent.childNodes.length; i ++) {
if (parent.childNodes[i].nodeType == 1){
var at = parent.childNodes[i].attributes;
at = at.getNamedItem('id');
if (at != null) if (at.value == id) return parent.childNodes[i];
}
var t = ie_getElementById(parent.childNodes[i], id);
if (typeof t == 'object') return t;
}
return false;
}
function ie_cloneNode(node, cloned) {
// clone a node to avoid the stupid IE no such interface error
var current;
if (!cloned) {
current = document.createElement(node.nodeName);
} else {
current = cloned.appendChild(document.createElement(node.nodeName));
}
for (var j = 0; j < node.attributes.length; j++) {
current.setAttribute(node.attributes[j].nodeName, node.attributes[j].nodeValue);
}
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeType == 1) {
ie_cloneNode(node.childNodes[i], current);
} else if (node.childNodes[i].nodeType == 3) {
var text = document.createTextNode(node.childNodes[i].nodeValue);
current.appendChild(text);
}
}
return current;
}
// events
function wa_attach(object, eventHandler, eventFunction, useCapture) {
if ( useCapture == null ) useCapture = false;
if (object.addEventListener) {
if ( eventHandler == 'mouseenter' ) {
object.addEventListener('mouseover', mouseMove( eventFunction ), useCapture);
} else if ( eventHandler == 'mouseleave' ) {
object.addEventListener('mouseout', mouseMove( eventFunction ), useCapture);
} else {
object.addEventListener(eventHandler, eventFunction, useCapture);
}
}
else
{
object.attachEvent('on' + eventHandler, eventFunction);
}
}
function mouseMove ( eventFunction ) {
return function (e) {
var target = e.relatedTarget;
if ( ( this === target ) || ( wa_isChild ( target, this) ) ) { return; }
eventFunction.call ( this, e );
};
}
function wa_isChild ( childTest, parentTest ) {
if ( childTest === parentTest ) return false;
while ( childTest && ( childTest !== parentTest ) ) {
try { childTest = childTest.parentNode; }
catch ( e ) { return true; }
}
return ( childTest === parentTest );
}
function wa_getObjPos ( object ) {
var curleft = curtop = 0;
if ( object.offsetParent ) {
do {
curleft += object.offsetLeft;
curtop += object.offsetTop;
} while ( object = object.offsetParent );
}
return [ curleft, curtop ];
}
function mousex ( e ) {
// read event, return mouse x pos
if ( !e ) var e = window.event;
if ( e.pageX ) {
var r = e.pageX;
}
else if ( e.clientX ) {
var r = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
}
return r;
}
function mousey ( e ) {
// read event, return mouse x pos
if ( !e ) var e = window.event;
if ( e.pageY ) {
var r = e.pageY;
}
else if ( e.clientY ) {
var r = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return r;
}
var wikiapps = true;