User:Cleared as filed/util.js

// from User:Quarl/util.js - miscellaneous utility functions for Wikipedia user scripts

// quarl 2006-01-09 initial version

//

///////////////////////////////////////////////////////////// // STRING UTILITY FUNCTIONS

function trimspaces(s) { if (!s) return s;   s = s.replace(/^\s+/,''); s = s.replace(/\s+$/,''); return s; }

function trim_lines(s) { return s.replace(/^\n+/, ).replace(/\n+$/, ); }

function string_quote_escape(str) { if (!str) return str; return "'" + str.replace(/\'/g, '\\\).replace(/\%27/g, '\\\) + "'"; }

// wiki article name escaping function wpaescape(s) { // encodeURIComponent is better than 'escape' for unicode chars; // it also escapes '+'. // Don't escape ':' return encodeURIComponent(s.replace(/ /g,'_')).replace(/%3A/g,':').replace(/%2F/g,'/'); } wpaencode = wpaescape;

function wpadecode(s) { return decodeURIComponent(s).replace(/_/g,' '); } wpaunescape = wpadecode;

function url_getpath(s) { return s.replace(/^http:\/\/[^\/]+/, ''); }

//////////////////////////////////////////////////////////// // DOM UTILITY FUNCTIONS function getElementsByClass(searchClass,node,tag) { /* This script and many more are available free online at The JavaScript Source :: http://javascript.internet.com Created by: Dustin Diaz :: http://www.dustindiaz.com/ */ var classElements = new Array; if (node == null) node = document; if (tag == null) tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); for (i = 0, j = 0; i < elsLen; i++) { if (pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; } }  return classElements; }

function add_before(node, newnode) { node.parentNode.insertBefore(newnode, node); return newnode; }

function add_after(node, newnode) { node.parentNode.insertBefore(newnode, node.nextSibling); return newnode; }

// return nodes in [node_start, node_end) function getNodesInRange(node_start, node_end) {   var nodes = [];    while (node_start != node_end) {        nodes.push(node_start);        node_start = node_start.nextSibling;        if (!node_start) return null; // didn't reach node_end!    }    return nodes; }

function removeNodesInRange(node_start, node_end) { if (!node_end) { alert("## removeNodesInRange: node_end==null"); return null; }   if (!getNodesInRange(node_start, node_end)) { alert("## removeNodesInRange: range does not terminate"); return null; }   var parent = node_start.parentNode; while (node_start != node_end) { var n = node_start.nextSibling; // save before it gets clobbered parent.removeChild(node_start); node_start = n;       if (!node_start) return null; } }

function createHref(href, title, inner) { var a = document.createElement('a'); a.href = href; a.title = title; a.innerHTML = inner; return a; }

function findHref(href) { href = wpaencode(wpadecode(href)); var links=document.links; for(i=0;i<links.length;++i) { // unescape and reescape to ensure canonical escaping if (wpaencode(wpadecode(links[i].href)) == href) return links[i]; }   return null; }

function insertNode(node, newNode) { if (!node) return null;

node.parentNode.replaceChild(newNode, node); newNode.appendChild(node); return newNode; }

function hookEventObj(obj, hookName, hookFunct) { if (!obj) return;

if (obj.addEventListener) obj.addEventListener(hookName, hookFunct, false); else if (obj.attachEvent) obj.attachEvent("on" + hookName, hookFunct); }

function copyArray(a) { var r = new Array; for (var i=0; i < a.length; i++) r[i] = a[i]; return r; }

// AJAX functions

function HTTPClient { var http; if(window.XMLHttpRequest) { http = new XMLHttpRequest; } else if (window.ActiveXObject) { try { http = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { http = false; }       }    }    return http; }

function asyncDownloadXML(url, callback, props) { var req = HTTPClient; if (!req) return null; // add optional arguments if (props) { for (var k in props) { req[k] = props[k]; }   }    req.open("GET", url, true); req.overrideMimeType('text/xml'); // using onload instead of onreadystatechange allows multiple asynchronous requests // TODO: since we now have access to 'req' as a variable, we could change back. // Is there any advantage to using onreadystatechange? req.onload = function(event) { var req = event.target; if (req.readyState == 4) callback(req); };   req.send(null); return req; }

function buildParams(paramArray) { var params = ''; for (k in paramArray) { v = paramArray[k]; // if v is a Boolean then the form was a checkbox. // unchecked checkboxes should not add any input fields. if (v == false) continue; if (v == true) v = 'on'; params += '&' + k + '=' + encodeURIComponent(v); }   params = params.replace(/^&/,''); return params; }

function addFormHiddenParams(newform, d) { for (var k in d) { v = d[k]; // if v is a Boolean then the form was a checkbox. // unchecked checkboxes should not add any input fields. if (v == false) continue; if (v == true) v = 'on'; var t = document.createElement('input'); t.type = 'hidden'; t.name = k;       t.value = d[k]; newform.appendChild(t); }   return newform; }

function asyncPostXML(url, parameters, callback, props) { var req = HTTPClient; if (!req) return null; if (typeof parameters != 'string') parameters = buildParams(parameters); // add optional arguments if (props) { for (var k in props) { req[k] = props[k]; }   }    req.open("POST", url, true); req.overrideMimeType('text/xml'); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.setRequestHeader("Content-length", parameters.length); req.setRequestHeader("Connection", "close"); req.onload = function(event) { var req = event.target; if (req.readyState == 4) callback(req); };   req.send(parameters); return req; }

//

//