/*global console: false */
/*jslint onevar: false */
// Released under the MIT/X11 license
// http://www.opensource.org/licenses/mit-license.php
"use strict";
// ==============================================================
/**
* parse URL to get its parts.
*
* @param url
* @return object with all parsed parts of URL as properties
*
* Originally from
* http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ Copyright
* February 19th, 2009, James Padolsey, <license undeclared>
*
* This function creates a new anchor element and uses location properties
* (inherent) to get the desired URL data. Some String operations are used (to
* normalize results across browsers).
*/
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return {
source: url,
protocol: a.protocol.replace(':',''),
host: a.hostname,
port: a.port,
query: a.search,
params: (function(){
var ret = {},
seg = a.search.replace(/^\?/,'').split('&'),
len = seg.length, i = 0, s;
for (;i<len;i++) {
if (!seg[i]) { continue; }
s = seg[i].split('=');
ret[s[0]] = s[1];
}
return ret;
})(),
file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
hash: a.hash.replace('#',''),
path: a.pathname.replace(/^([^\/])/,'/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
segments: a.pathname.replace(/^\//,'').split('/')
};
}
/**
* parse XML object out of string working around various bugs in Gecko
* implementation see https://developer.mozilla.org/en/E4X for more information
*
* @param inStr
* String with unparsed XML string
* @return XML object
*/
function parseXMLfromString (inStuff) {
// if (typeof inStuff !== 'string') In future we should recognize
// this.response
// and get just .text property out of it. TODO
var respStr = inStuff.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/, ""); // bug
// 336551
return new XML(respStr);
}
/**
* Get a bug no
*/
function getBugNo() {
console.log("bugNo = " + document.getElementsByName("id")[0].value);
return document.getElementsByName("id")[0].value;
}
/**
* Get a bug no from URL ... fails with aliases
*
* @param url
* String with URL to be analyzed
* @return String with the bug ID
*/
function getBugNoFromURL(url) {
var params = parseURL(url).params;
if (params && params.id) {
return params.id;
}
}
/**
* Send mouse click to the specified element
*
* @param String
* ID of the element to send mouseclick to
* @return None
*/
function clickMouse (targetID) {
var localEvent = document.createEvent("MouseEvents");
localEvent.initMouseEvent("click", true, true, document.defaultView, 0, 0,
0, 0, 0, false, false, false, false, 0, null);
document.getElementById(targetID).dispatchEvent(localEvent);
}
/**
* Create a A element leadink nowhere, but with listener running a callback on
* the click
*
* @param id
* String with a id to be added to the element
* @param text
* String with a string to be added as a textContent of the element
* @param parent
* Node which is a parent of the object
* @param callback
* Function to be called after clicking on the link
* @param params
* Array with parameters of the callback
* @param Boolean
* before if there should be a <br>
* element before.
* @return none
*/
function createDeadLink (id, text, parent, callback, params, before, covered, accesskey) {
params = valToArray(params);
var locParent = {};
// Yes, I want != here, not !==
if (covered != null) {
locParent = document.createElement(covered);
parent.appendChild(locParent);
}
else {
locParent = parent;
}
var newAElem = document.createElement("a");
newAElem.setAttribute("id", id);
if (accesskey) {
newAElem.setAttribute("accesskey", accesskey);
}
newAElem.textContent = text;
if (typeof callback === "string") {
newAElem.setAttribute("href", callback);
}
else {
newAElem.setAttribute("href", "");
newAElem.addEventListener("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
// We need apply, because params could be array of parameters
callback.apply(null, params);
}, false);
}
locParent.appendChild(newAElem);
if ((before === "br") || (before === true)) {
locParent.insertBefore(document.createElement("br"), newAElem);
}
else if (before === "dash") {
locParent.insertBefore(document.createTextNode("\u00A0-\u00A0"), newAElem);
}
else if (before === "pipe") {
locParent.insertBefore(document.createTextNode("\u00A0|\u00A0"), newAElem);
}
else if (before === "parens") {
locParent.appendChild(document.createTextNode(")"));
locParent.insertBefore(document.createTextNode("("), newAElem);
}
}
/*
* From <a> element diggs out just plain email address Note that
* bugzilla.gnome.org doesn't have mailto: url but
* https://bugzilla.gnome.org/page.cgi?id=describeuser.html&login=mcepl%40redhat.com
*
* @param aElement Element with href attribute or something else @return String
* with the address or null
*
*/
function parseMailto(aElement) {
var emailStr = "", hrefStr = "";
// use url utils
if (aElement) {
hrefStr = decodeURIComponent(aElement.getAttribute("href"));
emailStr = hrefStr.split(":");
// workaround for Gnome bugzilla ... no mailto: here.
if (emailStr.length < 2) {
var params = parseURL("https://" + window.location.hostname + "/" + hrefStr).params;
return decodeURI(params.login);
}
return emailStr[1];
}
return null;
}
/**
* format date to be in ISO format (just day part)
*
* @param date
* @return string with the formatted date
*/
function getISODate(dateStr) {
function pad(n) {
return n < 10 ? '0' + n : n;
}
var date = new Date(dateStr);
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' +
pad(date.getDate());
}
/**
* Check whether an item is member of the list. Idea is just to make long if
* commands slightly more readable.
*
* @param mbr
* string to be searched in the list
* @param list
* list
* @return position of the string in the list, or -1 if none found.
*/
function isInList(mbr, list) {
if (!list) {
return false;
}
return (list.indexOf(mbr) !== -1);
};
/**
* Make sure value returned is Array
*
* @param Array/String
* @return Array
*
* If something else than Array or String is passed to the function the result
* will be untouched actual argument of the call.
*/
function valToArray(val) {
var isArr = val &&
val.constructor &&
val.constructor.name === "Array";
return isArr ? val : [val];
}
/**
* Merges two comma separated string as a list and returns new string
*
* @param str
* String with old values
* @param value
* String/Array with other values
* @return String with merged lists
*/
function addCSVValue(str, value) {
var parts = (str.trim().length > 0 ? str.split(/[,\s]+/) : []);
if (!value) {
return str;
}
if (!isInList(value, parts)) {
var newValue = valToArray(value);
parts = parts.concat(newValue);
}
// this is necessary to get comma-space separated string even when
// value is an array already
parts = parts.join(",").split(",");
return parts.join(", ");
}
/**
* Treats comma separated string as a list and removes one item from it
*
* @param str
* String treated as a list
* @param value
* String with the value to be removed from str
* @return String with the resulting list comma separated
*/
function removeCSVValue(str, value) {
str = str.trim();
var parts = str ? str.split(/[,\s]+/) : [];
var valueArr = value instanceof Array ? value : value.split(/[,\s]+/);
parts = parts.filter(function (e, i, a) {
return (!isInList(e, valueArr));
});
return parts.join(", ");
}
/**
* select element of the array where regexp in the first element matches second
* parameter of this function
*
* @param list
* Array with regexps and return values
* @param chosingMark
* String by which the element of array is to be matched
* @return Object chosen element
*/
function filterByRegexp(list, chosingMark) {
var chosenPair = [];
if (list && list.length > 0) {
chosenPair = list.filter(function (pair) {
return new RegExp(pair.regexp, "i").test(chosingMark);
});
}
if (chosenPair.length > 0) {
return chosenPair[0].addr;
}
else {
return null;
}
}
/**
* remove elements from the page based on their IDs
*
* @param doc
* Document object
* @param target
* String/Array with ID(s)
* @param remove
* Boolean indicating whether the node should be actually removed or
* just hidden.
* @return none TODO remove parameter could be replaced by function which would
* do actual activity.
*/
function killNodes(doc, target, remove) {
target = target.trim();
var targetArr = target instanceof Array ? target : target.split(/[,\s]+/);
targetArr.forEach(function(x) {
if (remove) {
var targetNode = doc.getElementById(x);
targetNode.parentNode.removeChild(targetNode);
}
else {
x.style.display = "none";
}
});
}
/**
* Remove duplicate elements from array
*
* @param arr
* Array which needs to be cleaned up
* @return cleaned up array
*/
function removeDuplicates (arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice (j, 1);
}
}
}
return arr;
}
// ============================================
/**
* object to pack messaging. Use as in self.postMessage(new
* Message("GetPassword", { login: login, hostname: location.hostname }));
*/
function Message(cmd, data) {
this.cmd = cmd;
this.data = data;
}
function log(msg) {
self.postMessage(new Message("LogMessage", msg));
}
var NotLoggedinException = function NotLoggedinException (message) {
this.message = message;
this.name = "NotLoggedinException";
};
NotLoggedinException.prototype.toString = function () {
return this.name + ': "' + this.message + '"';
};
console.myDebug = function myDebug(str) {
if (typeof config !== "undefined") {
if (config.debuggingVerbose) {
console.log(str);
}
}
};