diff options
Diffstat (limited to 'bugzillaBugTriage.js')
-rw-r--r-- | bugzillaBugTriage.js | 3630 |
1 files changed, 1885 insertions, 1745 deletions
diff --git a/bugzillaBugTriage.js b/bugzillaBugTriage.js index 594763e..b5e8e74 100644 --- a/bugzillaBugTriage.js +++ b/bugzillaBugTriage.js @@ -2,7 +2,6 @@ /*global jetpack */ // Released under the MIT/X11 license // http://www.opensource.org/licenses/mit-license.php - "use strict"; jetpack.future.import("pageMods"); jetpack.future.import("storage.simple"); @@ -14,7 +13,8 @@ jetpack.future.import("clipboard"); // stupido!!! the string is value in hex for each color const RHColor = new Color(158, 41, 43); // RGB 158, 41, 43; HSL 359, 1, 39 const FedoraColor = new Color(0, 40, 103); // RGB 0, 40, 103; HSL 359, 1, 39 -const RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or HSL 120, 0, 23 +const RawhideColor = new Color(0, 119, 0); // or "green", or RGB 0, 119, 0, or HSL +// 120, 0, 23 const RHITColor = new Color(102, 0, 102); // RGB 102, 0, 102; HSL 300, 0, 20 const SalmonPink = new Color(255, 224, 176); // RGB 255, 224, 176; HSL 36, 2, 85 const ReporterColor = new Color(255, 255, 166); // RGB 255, 255, 166; HSL 60, 2, 83 @@ -28,27 +28,34 @@ var NumberOfFrames = 7; var XMLRPCurl = "https://bugzilla.redhat.com/xmlrpc.cgi"; var bugURL = "https://bugzilla.redhat.com/show_bug.cgi?id="; var myStorage = jetpack.storage.simple; -var badMIMEArray = ["application/octet-stream","text/x-log","undefined"]; +var badMIMEArray = [ "application/octet-stream", "text/x-log", "undefined" ]; -//============================================================== +// ============================================================== // TODO https://wiki.mozilla.org/Labs/Jetpack/JEP/24 var manifest = { - settings: [ - { name: "BZpassword", type: "password", label: "Bugzilla password" }, - { name: "JSONURL", type: "text", label: "Configuration file URL", - "default": "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json" } - ] + settings : [ + { + name : "BZpassword", + type : "password", + label : "Bugzilla password" + }, + { + name : "JSONURL", + type : "text", + label : "Configuration file URL", + "default" : "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json" + } ] }; jetpack.future.import("storage.settings"); -//if (!jetpack.storage.settings.BZpassword) { -// jetpack.settings.open(); -//} +// if (!jetpack.storage.settings.BZpassword) { +// jetpack.settings.open(); +// } -var jsonDataURL = myStorage.JSONURL ? myStorage.JSONURL : - "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json"; +var jsonDataURL = myStorage.JSONURL ? myStorage.JSONURL + : "http://mcepl.fedorapeople.org/scripts/BugZappers_data.json"; var PCIIDsURL = "http://mcepl.fedorapeople.org/scripts/drm_pciids.json"; -var abrtQueryURL = "https://bugzilla.redhat.com/buglist.cgi?"+ - "cmdtype=dorem&remaction=run&namedcmd=all%20NEW%20abrt%20crashes&sharer_id=74116"; +var abrtQueryURL = "https://bugzilla.redhat.com/buglist.cgi?" + + "cmdtype=dorem&remaction=run&namedcmd=all%20NEW%20abrt%20crashes&sharer_id=74116"; var reqCounter = 0; var msgStrs = {}; @@ -56,30 +63,28 @@ var msgStrs = {}; var CommentRe = new RegExp("^\\s*#"); var BlankLineRe = new RegExp("^\\s*$"); // nová řádka -// [ 65.631] (--) intel(0): Chipset: "845G" -var ChipsetRE = new RegExp("^\\s*\\[?[ 0-9.]*\\]?\\s*\\(--\\) ([A-Za-z]+)\\([0-9]?\\): Chipset: (.*)$"); +// [ 65.631] (--) intel(0): Chipset: "845G" +var ChipsetRE = new RegExp( + "^\\s*\\[?[ 0-9.]*\\]?\\s*\\(--\\) ([A-Za-z]+)\\([0-9]?\\): Chipset: (.*)$"); var ATIgetIDRE = new RegExp("^.*\\(ChipID = 0x([0-9a-fA-F]+)\\).*$"); var AbrtRE = new RegExp("^\\s*\\[abrt\\]"); var signalHandlerRE = new RegExp("^\\s*#[0-9]*\\s*<signal handler called>"); var frameNoRE = new RegExp("^\\s*#([0-9]*)\\s"); // For identification of graphics card -var manuChipStrs = [ - ["ATI Radeon", "ATI", "1002"], - ["ATI Mobility Radeon", "ATI", "1002"], - ["Intel Corporation", "INTEL", "8086"], - ["NVIDIA", "NV", "10de"] -]; -var backTranslateManufacturerPCIID = [{ - regexp: "ATI Technologies Inc", - addr: "1002" - }, { - regexp: "Intel Corporation", - addr: "8086" - }, { - regexp: "nVidia Corporation", - addr: "10de" -}]; +var manuChipStrs = [ [ "ATI Radeon", "ATI", "1002" ], + [ "ATI Mobility Radeon", "ATI", "1002" ], + [ "Intel Corporation", "INTEL", "8086" ], [ "NVIDIA", "NV", "10de" ] ]; +var backTranslateManufacturerPCIID = [ { + regexp : "ATI Technologies Inc", + addr : "1002" +}, { + regexp : "Intel Corporation", + addr : "8086" +}, { + regexp : "nVidia Corporation", + addr : "10de" +} ]; // Initialize data from remote URL var XMLHttpRequestDone = false; var hashBugzillaName = []; @@ -88,7 +93,8 @@ var defAssigneeList = []; var suspiciousComponents = []; var signatureFedoraString = ""; -// TODO we should have an array SpecialFlags instead of multiple Boolean variables +// TODO we should have an array SpecialFlags instead of multiple Boolean +// variables var queryButtonAvailable = false; var upstreamButtonAvailable = false; var logSubmits = false; @@ -99,319 +105,338 @@ var topRow = {}; var bottomRow = {}; // Get JSON configuration data -loadText = function(URL, cb_function,what) { - if (what === undefined) { // missing optional argument - what = this; - } - - var req = new XMLHttpRequest(); - req.open("GET",URL,true); - req.onreadystatechange = function (aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - cb_function.call(what,req.responseText); - } else { - throw "Getting " + URL + "failed!" ; - } - } - }; - req.send(""); +loadText = function(URL, cb_function, what) { + if (what === undefined) { // missing optional argument + what = this; + } + + var req = new XMLHttpRequest(); + req.open("GET", URL, true); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + cb_function.call(what, req.responseText); + } else { + throw "Getting " + URL + "failed!"; + } + } + }; + req.send(""); }; loadJSON = function(URL, cb_function, what) { - if (what === undefined) { // missing optional argument - what = this; - } - - loadText(URL,function (text) { - var data = JSON.parse(text); - cb_function.call(what,data); - }, what); -}; - - -loadJSON(jsonDataURL, function (response) { - msgStrs = response.strings; - signatureFedoraString = response.signature; - suspiciousComponents = response.suspiciousComponents; - hashBugzillaName = response.bugzillalabelNames; - hashBugzillaWholeURL = response.bugzillaIDURLs; - // [{'regexp to match component':'email address of an universal maintainer'}, ...] - AddrArray = response.CCmaintainer; - defAssigneeList = response.defaultAssignee; - queryButtonAvailable = response.queryButton; - upstreamButtonAvailable = response.upstreamButton; - logSubmits = response.submitsLogging; - upstreamBugzillasArray = response.upstreamBugzillas; - chipIDsGroupings = response.chipIDsGroupings; - topRow = response.topRow; - bottomRow = response.bottomRow; -}); + if (what === undefined) { // missing optional argument + what = this; + } + + loadText(URL, function(text) { + var data = JSON.parse(text); + cb_function.call(what, data); + }, what); +}; + +loadJSON(jsonDataURL, function(response) { + msgStrs = response.strings; + signatureFedoraString = response.signature; + suspiciousComponents = response.suspiciousComponents; + hashBugzillaName = response.bugzillalabelNames; + hashBugzillaWholeURL = response.bugzillaIDURLs; + // [{'regexp to match component':'email address of an universal + // maintainer'}, ...] + AddrArray = response.CCmaintainer; + defAssigneeList = response.defaultAssignee; + queryButtonAvailable = response.queryButton; + upstreamButtonAvailable = response.upstreamButton; + logSubmits = response.submitsLogging; + upstreamBugzillasArray = response.upstreamBugzillas; + chipIDsGroupings = response.chipIDsGroupings; + topRow = response.topRow; + bottomRow = response.bottomRow; + }); // Get card translation table -loadJSON(PCIIDsURL, - function (response) { - PCI_ID_Array = response; +loadJSON(PCIIDsURL, function(response) { + PCI_ID_Array = response; }); -//======== load external library =============================== - -//var XMLRPCMessage = {}; -//var req = new XMLHttpRequest(); -//req.open("GET","http://mcepl.fedorapeople.org/scripts/xmlrpc.js",true); -//req.onreadystatechange = function (aEvt) { -// if (req.readyState == 4) { -// if (req.status == 200) { -// var thisDoc = jetpack.tabs.focused.contentDocument; -// var script = thisDoc.createElement("script"); -// script.setAttribute("type","text/javascript"); -// script.innerHTML = req.responseText; -// thisDoc.getElementsByTagName("head")[0].appendChild(script); -// XMLRPCMessage = jetpack.tabs.focused.contentWindow.wrappedJSObject.XMLRPCMessage; -// console.log("XMLHTTPRequest should be loaded."); -// console.log(XMLRPCMessage); -// } -// } -//}; -//console.log("Now we are calling XMLHTTPRequest to load xmlrpc.js"); -//req.send(""); +// ======== load external library =============================== + +// var XMLRPCMessage = {}; +// var req = new XMLHttpRequest(); +// req.open("GET","http://mcepl.fedorapeople.org/scripts/xmlrpc.js",true); +// req.onreadystatechange = function (aEvt) { +// if (req.readyState == 4) { +// if (req.status == 200) { +// var thisDoc = jetpack.tabs.focused.contentDocument; +// var script = thisDoc.createElement("script"); +// script.setAttribute("type","text/javascript"); +// script.innerHTML = req.responseText; +// thisDoc.getElementsByTagName("head")[0].appendChild(script); +// XMLRPCMessage = +// jetpack.tabs.focused.contentWindow.wrappedJSObject.XMLRPCMessage; +// console.log("XMLHTTPRequest should be loaded."); +// console.log(XMLRPCMessage); +// } +// } +// }; +// console.log("Now we are calling XMLHTTPRequest to load xmlrpc.js"); +// req.send(""); /* + * + * xmlrpc.js beta version 1 Tool for creating XML-RPC formatted requests in + * JavaScript + * + * Copyright 2001 Scott Andrew LePera scott@scottandrew.com + * http://www.scottandrew.com/xml-rpc + * + * License: You are granted the right to use and/or redistribute this code only + * if this license and the copyright notice are included and you accept that no + * warranty of any kind is made or implied by the author. + * + */ -xmlrpc.js beta version 1 -Tool for creating XML-RPC formatted requests in JavaScript +function XMLRPCMessage(methodname) { + this.method = methodname || "system.listMethods"; + this.params = []; + return this; +} -Copyright 2001 Scott Andrew LePera -scott@scottandrew.com -http://www.scottandrew.com/xml-rpc +XMLRPCMessage.prototype.setMethod = function(methodName) { + if (!methodName) + return; + this.method = methodName; +}; -License: -You are granted the right to use and/or redistribute this -code only if this license and the copyright notice are included -and you accept that no warranty of any kind is made or implied -by the author. +XMLRPCMessage.prototype.addParameter = function(data) { + if (arguments.length == 0) + return; + this.params[this.params.length] = data; +}; -*/ +XMLRPCMessage.prototype.xml = function() { -function XMLRPCMessage(methodname){ - this.method = methodname||"system.listMethods"; - this.params = []; - return this; -} + var method = this.method; -XMLRPCMessage.prototype.setMethod = function(methodName){ - if (!methodName) return; - this.method = methodName; -} + // assemble the XML message header + var xml = ""; -XMLRPCMessage.prototype.addParameter = function(data){ - if (arguments.length==0) return; - this.params[this.params.length] = data; -} + xml += "<?xml version=\"1.0\"?>\n"; + xml += "<methodCall>\n"; + xml += "<methodName>" + method + "</methodName>\n"; + xml += "<params>\n"; -XMLRPCMessage.prototype.xml = function(){ - - var method = this.method; - - // assemble the XML message header - var xml = ""; - - xml += "<?xml version=\"1.0\"?>\n"; - xml += "<methodCall>\n"; - xml += "<methodName>" + method+ "</methodName>\n"; - xml += "<params>\n"; - - // do individual parameters - for (var i = 0; i < this.params.length; i++){ - var data = this.params[i]; - xml += "<param>\n"; - - xml += "<value>" + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data),data) + "</value>\n"; - - xml += "</param>\n"; - } - - xml += "</params>\n"; - xml += "</methodCall>"; - - return xml; // for now -} + // do individual parameters + for ( var i = 0; i < this.params.length; i++) { + var data = this.params[i]; + xml += "<param>\n"; -XMLRPCMessage.dataTypeOf = function (o){ - // identifies the data type - var type = typeof(o); - type = type.toLowerCase(); - switch(type){ - case "number": - if (Math.round(o) == o) type = "i4"; - else type = "double"; - break; - case "object": - var con = o.constructor; - if (con == Date) type = "date"; - else if (con == Array) type = "array"; - else type = "struct"; - break; - } - return type; -} + xml += "<value>" + + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data), + data) + "</value>\n"; -XMLRPCMessage.doValueXML = function(type,data){ - var xml = "<" + type + ">" + data + "</" + type + ">"; - return xml; -} + xml += "</param>\n"; + } -XMLRPCMessage.doBooleanXML = function(data){ - var value = (data==true)?1:0; - var xml = "<boolean>" + value + "</boolean>"; - return xml; -} + xml += "</params>\n"; + xml += "</methodCall>"; -XMLRPCMessage.doDateXML = function(data){ - var xml = "<dateTime.iso8601>"; - xml += dateToISO8601(data); - xml += "</dateTime.iso8601>"; - return xml; -} + return xml; // for now +}; -XMLRPCMessage.doArrayXML = function(data){ - var xml = "<array><data>\n"; - for (var i = 0; i < data.length; i++){ - xml += "<value>" + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data[i]),data[i]) + "</value>\n"; - } - xml += "</data></array>\n"; - return xml; -} +XMLRPCMessage.dataTypeOf = function(o) { + // identifies the data type + var type = typeof (o); + type = type.toLowerCase(); + switch (type) { + case "number": + if (Math.round(o) == o) + type = "i4"; + else + type = "double"; + break; + case "object": + var con = o.constructor; + if (con == Date) + type = "date"; + else if (con == Array) + type = "array"; + else + type = "struct"; + break; + } + return type; +}; -XMLRPCMessage.doStructXML = function(data){ - var xml = "<struct>\n"; - for (var i in data){ - xml += "<member>\n"; - xml += "<name>" + i + "</name>\n"; - xml += "<value>" + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data[i]),data[i]) + "</value>\n"; - xml += "</member>\n"; - } - xml += "</struct>\n"; - return xml; -} +XMLRPCMessage.doValueXML = function(type, data) { + var xml = "<" + type + ">" + data + "</" + type + ">"; + return xml; +}; -XMLRPCMessage.getParamXML = function(type,data){ - var xml; - switch (type){ - case "date": - xml = XMLRPCMessage.doDateXML(data); - break; - case "array": - xml = XMLRPCMessage.doArrayXML(data); - break; - case "struct": - xml = XMLRPCMessage.doStructXML(data); - break; - case "boolean": - xml = XMLRPCMessage.doBooleanXML(data); - break; - default: - xml = XMLRPCMessage.doValueXML(type,data); - break; - } - return xml; +XMLRPCMessage.doBooleanXML = function(data) { + var value = (data == true) ? 1 : 0; + var xml = "<boolean>" + value + "</boolean>"; + return xml; +}; + +XMLRPCMessage.doDateXML = function(data) { + var xml = "<dateTime.iso8601>"; + xml += dateToISO8601(data); + xml += "</dateTime.iso8601>"; + return xml; +}; + +XMLRPCMessage.doArrayXML = function(data) { + var xml = "<array><data>\n"; + for ( var i = 0; i < data.length; i++) { + xml += "<value>" + + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data[i]), + data[i]) + "</value>\n"; + } + xml += "</data></array>\n"; + return xml; +}; + +XMLRPCMessage.doStructXML = function(data) { + var xml = "<struct>\n"; + for ( var i in data) { + xml += "<member>\n"; + xml += "<name>" + i + "</name>\n"; + xml += "<value>" + + XMLRPCMessage.getParamXML(XMLRPCMessage.dataTypeOf(data[i]), + data[i]) + "</value>\n"; + xml += "</member>\n"; + } + xml += "</struct>\n"; + return xml; +}; + +XMLRPCMessage.getParamXML = function(type, data) { + var xml; + switch (type) { + case "date": + xml = XMLRPCMessage.doDateXML(data); + break; + case "array": + xml = XMLRPCMessage.doArrayXML(data); + break; + case "struct": + xml = XMLRPCMessage.doStructXML(data); + break; + case "boolean": + xml = XMLRPCMessage.doBooleanXML(data); + break; + default: + xml = XMLRPCMessage.doValueXML(type, data); + break; + } + return xml; +}; + +function dateToISO8601(date) { + // wow I hate working with the Date object + var year = new String(date.getYear()); + var month = leadingZero(new String(date.getMonth())); + var day = leadingZero(new String(date.getDate())); + var time = leadingZero(new String(date.getHours())) + ":" + + leadingZero(new String(date.getMinutes())) + ":" + + leadingZero(new String(date.getSeconds())); + + var converted = year + month + day + "T" + time; + return converted; } -function dateToISO8601(date){ - // wow I hate working with the Date object - var year = new String(date.getYear()); - var month = leadingZero(new String(date.getMonth())); - var day = leadingZero(new String(date.getDate())); - var time = leadingZero(new String(date.getHours())) + ":" + leadingZero(new String(date.getMinutes())) + ":" + leadingZero(new String(date.getSeconds())); - - var converted = year+month+day+"T"+time; - return converted; -} - -function leadingZero(n){ - // pads a single number with a leading zero. Heh. - if (n.length==1) n = "0" + n; - return n; +function leadingZero(n) { + // pads a single number with a leading zero. Heh. + if (n.length == 1) + n = "0" + n; + return n; } -//============================================================== +// ============================================================== /** * 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()); +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()); } /** - * 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 + * 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 string chosen element */ filterByRegexp = function(list, chosingMark) { - var chosenPair = []; - if (list.length > 0) { - chosenPair = list.filter ( - function (pair) { - return new RegExp(pair.regexp, "i").test(chosingMark); - }); - } - if (chosenPair.length > 0) { - return chosenPair[0].addr.trim(); - } else { - return ""; - } + var chosenPair = []; + if (list.length > 0) { + chosenPair = list.filter(function(pair) { + return new RegExp(pair.regexp, "i").test(chosingMark); + }); + } + if (chosenPair.length > 0) { + return chosenPair[0].addr.trim(); + } else { + return ""; + } }; /** - * Converts attributes value of the given list of elements to the - * Javascript list. - * @param list array of elements - * @return array of values + * Converts attributes value of the given list of elements to the Javascript + * list. + * + * @param list + * array of elements + * @return array of values */ valuesToList = function(list) { - var outL = []; - - list.forEach(function (e, i, a) { - if (e.hasAttribute("value")) { - outL.push(e.getAttribute("value").trim()); - } - }); - return outL; + var outL = []; + + list.forEach(function(e, i, a) { + if (e.hasAttribute("value")) { + outL.push(e.getAttribute("value").trim()); + } + }); + return outL; }; /** - * 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 + * 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. */ isInList = function(mbr, list) { - return (list.indexOf(mbr) !== -1); -}; - -function createBlankPage (ttl,bodyBuildCB) { - var title = ttl || "Yet another untitled page"; - var that = this; - - var logTab = jetpack.tabs.open("about:blank"); - jetpack.tabs.onReady(function() { - var otherDoc = logTab.contentDocument; - otherDoc.title = title; - otherDoc.body.innerHTML = "<h1>"+title+"</h1>"; - bodyBuildCB.call(that,otherDoc.body); - logTab.focus(); - }); + return (list.indexOf(mbr) !== -1); +}; + +function createBlankPage(ttl, bodyBuildCB) { + var title = ttl || "Yet another untitled page"; + var that = this; + + var logTab = jetpack.tabs.open("about:blank"); + jetpack.tabs.onReady(function() { + var otherDoc = logTab.contentDocument; + otherDoc.title = title; + otherDoc.body.innerHTML = "<h1>" + title + "</h1>"; + bodyBuildCB.call(that, otherDoc.body); + logTab.focus(); + }); } // ============================================================================ @@ -420,846 +445,926 @@ function createBlankPage (ttl,bodyBuildCB) { // http://www.mjijackson.com/2008/02\ // /rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript -function Color(r,g,b) { - if (r instanceof Array) { - this.r = r[0]; - this.g = r[1]; - this.b = r[2]; - } else { - this.r = r; - this.g = g; - this.b = b; - } +function Color(r, g, b) { + if (r instanceof Array) { + this.r = r[0]; + this.g = r[1]; + this.b = r[2]; + } else { + this.r = r; + this.g = g; + this.b = b; + } } -Color.prototype.update = function(r,g,b) { - this.r = r; - this.g = g; - this.b = b; +Color.prototype.update = function(r, g, b) { + this.r = r; + this.g = g; + this.b = b; }; Color.prototype.hs = function(nStr) { - if (Number(nStr) === 0) { - return "00"; - } else if (nStr.length < 2) { - return "0" + nStr; - } else { - return nStr; - } + if (Number(nStr) === 0) { + return "00"; + } else if (nStr.length < 2) { + return "0" + nStr; + } else { + return nStr; + } }; Color.prototype.toString = function() { - var rH = Number(this.r.toFixed()).toString(16); - var gH = Number(this.g.toFixed()).toString(16); - var bH = Number(this.b.toFixed()).toString(16); - return "#"+this.hs(rH)+this.hs(gH)+this.hs(bH); + var rH = Number(this.r.toFixed()).toString(16); + var gH = Number(this.g.toFixed()).toString(16); + var bH = Number(this.b.toFixed()).toString(16); + return "#" + this.hs(rH) + this.hs(gH) + this.hs(bH); }; /** - * Converts an RGB color value to HSL. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * Assumes r, g, and b are contained in the set [0, 255] and - * returns h, s, and l in the set [0, 1].4343 - * - * @param Number r The red color value - * @param Number g The green color value - * @param Number b The blue color value - * @return Array The HSL representation + * Converts an RGB color value to HSL. Conversion formula adapted from + * http://en.wikipedia.org/wiki/HSL_color_space. Assumes r, g, and b are + * contained in the set [0, 255] and returns h, s, and l in the set [0, 1].4343 + * + * @param Number + * r The red color value + * @param Number + * g The green color value + * @param Number + * b The blue color value + * @return Array The HSL representation */ -Color.prototype.hsl = function (){ - var r = this.r / 255; - var g = this.g / 255; - var b = this.b / 255; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2; - - if(max === min){ - h = s = 0; // achromatic - }else{ - var d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch(max){ - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - - return [h, s, l]; +Color.prototype.hsl = function() { + var r = this.r / 255; + var g = this.g / 255; + var b = this.b / 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2; + + if (max === min) { + h = s = 0; // achromatic + } else { + var d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ h, s, l ]; }; /** - * Converts an HSL color value to RGB. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSL_color_space. - * Assumes h, s, and l are contained in the set [0, 1] and - * returns r, g, and b in the set [0, 255]. - * - * @param Number h The hue - * @param Number s The saturation - * @param Number l The lightness - * @return Array The RGB representation + * Converts an HSL color value to RGB. Conversion formula adapted from + * http://en.wikipedia.org/wiki/HSL_color_space. Assumes h, s, and l are + * contained in the set [0, 1] and returns r, g, and b in the set [0, 255]. + * + * @param Number + * h The hue + * @param Number + * s The saturation + * @param Number + * l The lightness + * @return Array The RGB representation */ -Color.prototype.hslToRgb = function (h, s, l){ - function hue2rgb(p, q, t){ - if (t < 0) { - t += 1; - } - if (t > 1) { - t -= 1; - } - if (t < 1/6) { - return p + (q - p) * 6 * t; - } - if (t < 1/2) { - return q; - } - if (t < 2/3) { - return p + (q - p) * (2/3 - t) * 6; - } - return p; - } - - var r, g, b; - - if(s === 0){ - r = g = b = l; // achromatic - }else{ - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return [r * 255, g * 255, b * 255]; +Color.prototype.hslToRgb = function(h, s, l) { + function hue2rgb(p, q, t) { + if (t < 0) { + t += 1; + } + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; + } + + var r, g, b; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [ r * 255, g * 255, b * 255 ]; }; /** - * Converts an RGB color value to HSV. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSV_color_space. - * Assumes r, g, and b are contained in the set [0, 255] and - * returns h, s, and v in the set [0, 1]. - * - * @param Number r The red color value - * @param Number g The green color value - * @param Number b The blue color value - * @return Array The HSV representation + * Converts an RGB color value to HSV. Conversion formula adapted from + * http://en.wikipedia.org/wiki/HSV_color_space. Assumes r, g, and b are + * contained in the set [0, 255] and returns h, s, and v in the set [0, 1]. + * + * @param Number + * r The red color value + * @param Number + * g The green color value + * @param Number + * b The blue color value + * @return Array The HSV representation */ -Color.prototype.hsv = function (){ - var r = this.r/255; - var g = this.g/255; - var b = this.b/255; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, v = max; - - var d = max - min; - s = max === 0 ? 0 : d / max; - - if(max === min){ - h = 0; // achromatic - }else{ - switch(max){ - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - - return [h, s, v]; +Color.prototype.hsv = function() { + var r = this.r / 255; + var g = this.g / 255; + var b = this.b / 255; + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + s = max === 0 ? 0 : d / max; + + if (max === min) { + h = 0; // achromatic + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + + return [ h, s, v ]; }; /** - * Converts an HSV color value to RGB. Conversion formula - * adapted from http://en.wikipedia.org/wiki/HSV_color_space. - * Assumes h, s, and v are contained in the set [0, 1] and - * returns r, g, and b in the set [0, 255]. - * - * @param Number h The hue - * @param Number s The saturation - * @param Number v The value - * @return Array The RGB representation + * Converts an HSV color value to RGB. Conversion formula adapted from + * http://en.wikipedia.org/wiki/HSV_color_space. Assumes h, s, and v are + * contained in the set [0, 1] and returns r, g, and b in the set [0, 255]. + * + * @param Number + * h The hue + * @param Number + * s The saturation + * @param Number + * v The value + * @return Array The RGB representation */ -Color.prototype.hsvToRgb = function (h, s, v){ - var r, g, b; - - var i = Math.floor(h * 6); - var f = h * 6 - i; - var p = v * (1 - s); - var q = v * (1 - f * s); - var t = v * (1 - (1 - f) * s); - - switch(i % 6){ - case 0: - r = v; - g = t; - b = p; - break; - case 1: - r = q; - g = v; - b = p; - break; - case 2: - r = p; - g = v; - b = t; - break; - case 3: - r = p; - g = q; - b = v; - break; - case 4: - r = t; - g = p; - b = v; - break; - case 5: - r = v; - g = p; - b = q; - break; - } - - return [r * 255, g * 255, b * 255]; +Color.prototype.hsvToRgb = function(h, s, v) { + var r, g, b; + + var i = Math.floor(h * 6); + var f = h * 6 - i; + var p = v * (1 - s); + var q = v * (1 - f * s); + var t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + + return [ r * 255, g * 255, b * 255 ]; }; /** * Provide */ Color.prototype.lightColor = function() { - var hslArray = this.hsl(); - var h = Number(hslArray[0]); - var s = Number(hslArray[1]) * Desaturated; - var l = Luminosity; - var desA = this.hslToRgb(h, s, l); - return new Color(desA[0],desA[1],desA[2]); + var hslArray = this.hsl(); + var h = Number(hslArray[0]); + var s = Number(hslArray[1]) * Desaturated; + var l = Luminosity; + var desA = this.hslToRgb(h, s, l); + return new Color(desA[0], desA[1], desA[2]); }; - -//==================================================================================== +// ==================================================================================== // BzPage's methods /** + * generalized hasKeyword ... search in the value of the box with given id + * + * @param id + * String with ID of the element we want to check + * @param str + * String to be searched for + * @return Boolean found? + */ +BzPage.prototype.idContainsWord = function(id, str) { + try { + var kwd = this.dok.getElementById(id).value; + } catch (e) { + // For those who don't have particular element at all or if it is empty + return false; + } + console.log("id = " + id + ", kwd = " + kwd.trim()); + return (kwd.trim().indexOf(str) != -1); +}; + +/** * Check for the presence of a keyword - * - * @param str string with the keyword + * + * @param str + * string with the keyword * @return Boolean */ -BzPage.prototype.hasKeyword = function (str) { - var kwd = this.dok.getElementById('keywords').value.trim(); - return (new RegExp(str).test(kwd)); +BzPage.prototype.hasKeyword = function(str) { + return (this.idContainsWord('keywords', str)); }; /** * Set additional keyword if it isn't there - * - * @param str string with the keyword + * + * @param str + * string with the keyword * @return none */ -BzPage.prototype.setKeyword = function (str) { - // Could be probably rewrote to use this.addTextToTextBox, but - // it would be too complicated with a little gain. - var keywordInput = this.dok.getElementById('keywords'); - var kwd = keywordInput.value.trim(); - var strRE = new RegExp(str); - if (!strRE.test(kwd)) { - keywordInput.value = kwd ? kwd + ", " + str : str; - } -}; - -BzPage.prototype.getOptionValue = function (id) { - // Some special bugs don't have version for example - try { - return this.dok.getElementById(id).value; - } - catch (e) { - console.error("Failed to find element with id = " + id); - return "#NA"; - } +BzPage.prototype.setKeyword = function(str) { + this.addTextToTextBox('keywords', str); +}; + +BzPage.prototype.getOptionValue = function(id) { + // Some special bugs don't have version for example + try { + return this.dok.getElementById(id).value; + } catch (e) { + console.error("Failed to find element with id = " + id); + return "#NA"; + } }; /* Offline supporting functions */ /** - * - * @todo FIXME this probably makes a closure and a memory leak - * name='changeform' - * investigate https://developer.mozilla.org/en/How_to_Turn_Off_Form_Autocompletion - * - * <form method="post" action="process_bug.cgi" autocomplete="off"> - - Reading http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.13 - random notes: - - 17.13.3 provides all steps necessary - - enctype != application/x-www-form-urlencoded => SHOULD fails (no further questions needed) - - http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.1. is nice explanation - (albeit quite dated) - - on multiple values http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.6.1 - - příliš jednoduché http://www.innovation.ch/java/HTTPClient/emulating_forms.html - - + * + * @todo FIXME this probably makes a closure and a memory leak name='changeform' + * investigate + * https://developer.mozilla.org/en/How_to_Turn_Off_Form_Autocompletion + * + * <form method="post" action="process_bug.cgi" autocomplete="off"> + * + * Reading + * http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.13 + * random notes: - 17.13.3 provides all steps necessary - enctype != + * application/x-www-form-urlencoded => SHOULD fails (no further questions + * needed) - http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.1. is + * nice explanation (albeit quite dated) - on multiple values + * http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.6.1 - + * příliš jednoduché + * http://www.innovation.ch/java/HTTPClient/emulating_forms.html - */ -BzPage.prototype.serializeForm = function (form) { - var serialForm = { - dataOut: "", - name: form.name, - method: form.method, - acceptCharset: form.acceptCharset, - action: form.action, // TODO shouldn't we get a non-relative URL? - enctype: form.enctype, - cookie: this.dok.cookie, - autocomplete: form.getAttribute("autocomplete"), - bugNo: this.bugNo - }; - - function genURIElement(sName,sValue) { - return encodeURIComponent(sName)+"="+ - encodeURIComponent(sValue); - } - - /** - * @param o control to be serialized - * @return String with the serialized control - */ - function serializeControl(element) { - var val = element.value; - // console.log("val.toSource() = " + val.toSource()); - /* - on HTMLSelectElement we have an attribute 'type' of type DOMString, readonly - The type of this form control. This is the string "select-multiple" - when the multiple attribute is true and the string "select-one" when - false. - */ - if ((val == null) || (val == undefined)|| (val == "")) { - return ; - } else if (val instanceof Array) { - return val.map(function (x) { - return genURIElement(element.name,x.value); - }).join("&"); - } else if (val instanceof String) { - return genURIElement(element.name,val); - } else { // assume HTMLCollection - return Array.map(val,function (x) { - return genURIElement(element.name,x.value); - }).join("&"); - } - } - - serialForm.dataOut = Array.filter(form.elements,function (el) { - return !el.disabled && el.name && - // FIXME shouldn't I just add && el.value here? - (el.checked || /select|textarea/i.test(el.nodeName) || - /text|hidden|password|search/i.test(el.type)); - }).map(serializeControl).join("&"); - return serialForm; +BzPage.prototype.serializeForm = function(form) { + var serialForm = { + dataOut : "", + name : form.name, + method : form.method, + acceptCharset : form.acceptCharset, + action : form.action, // TODO shouldn't we get a non-relative URL? + enctype : form.enctype, + cookie : this.dok.cookie, + autocomplete : form.getAttribute("autocomplete"), + bugNo : this.bugNo + }; + + function genURIElement(sName, sValue) { + return encodeURIComponent(sName) + "=" + encodeURIComponent(sValue); + } + + /** + * @param o + * control to be serialized + * @return String with the serialized control + */ + function serializeControl(element) { + var val = element.value; + // console.log("val.toSource() = " + val.toSource()); + /* + * on HTMLSelectElement we have an attribute 'type' of type DOMString, + * readonly The type of this form control. This is the string + * "select-multiple" when the multiple attribute is true and the string + * "select-one" when false. + */ + if ((val == null) || (val == undefined) || (val == "")) { + return; + } else if (val instanceof Array) { + return val.map(function(x) { + return genURIElement(element.name, x.value); + }).join("&"); + } else if (val instanceof String) { + return genURIElement(element.name, val); + } else { // assume HTMLCollection + return Array.map(val, function(x) { + return genURIElement(element.name, x.value); + }).join("&"); + } + } + + serialForm.dataOut = Array + .filter( + form.elements, + function(el) { + return !el.disabled + && el.name + && + // FIXME shouldn't I just add && el.value here? + (el.checked + || /select|textarea/i.test(el.nodeName) || /text|hidden|password|search/i + .test(el.type)); + }).map(serializeControl).join("&"); + return serialForm; }; BzPage.prototype.submitCallback = function(evt) { - console.log("Submit Callback!"); - if (jetpack.__parent__.navigator.onLine) { - var serForm = this.serializeForm(jetpack.tabs.focused. - contentWindow.document.forms.namedItem("changeform")); - console.log("serForm:\n"+serForm.toSource()); - } else { - var serForm = this.serializeForm(jetpack.tabs.focused. - contentWindow.document.forms.namedItem("changeform")); - myStorage.forms[this.bugNo] = serForm; - evt.stopPropagation(); - evt.preventDefault(); - } + console.log("Submit Callback!"); + if (jetpack.__parent__.navigator.onLine) { + var serForm = this + .serializeForm(jetpack.tabs.focused.contentWindow.document.forms + .namedItem("changeform")); + console.log("serForm:\n" + serForm.toSource()); + } else { + var serForm = this + .serializeForm(jetpack.tabs.focused.contentWindow.document.forms + .namedItem("changeform")); + myStorage.forms[this.bugNo] = serForm; + evt.stopPropagation(); + evt.preventDefault(); + } }; /** - * - * + * + * * Yes, this is correct, this is NOT method of bzPage! */ function onlineCallback() { - function deserializeAndSend(formData) { - // FIXME notImplemented - // is it enough to just - // run XMLHttpRequest? Probably yes, this is just a form - // and this is just a HTTP request - // it is probably better to get already processed - // application/x-www-form-urlencoded - // see http://htmlhelp.com/reference/html40/forms/form.html for details - // and also https://developer.mozilla.org/en/AJAX/Getting_Started - // what's? - // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference\ - // /Global_Functions/encodeURI & co. - // this seems to be also interesting - // https://developer.mozilla.org/en/Code_snippets/Post_data_to_window - console.error("Sending bugs not implemented yet!"); - return ""; // FIXME check other HTTP headers to be set - - var bugID = formData.bugNo; - var req = new XMLHttpRequest(); - req.open("POST",formData.action,true); - // FIXME co očekávám za odpověď? req.overrideMimeType("text/xml"); - // * Accept-Encoding - // * Accept-Language - // * Accept (MIME types) - req.setRequestHeader("Connection","keep-alive"); - req.setRequestHeader("Keep-Alive",300); - req.setRequestHeader("Content-Type",formData.enctype); - req.setRequestHeader("Referer",bugURL+bugID); - req.setRequestHeader("Accept-Charset",formData.acceptCharset); - req.setRequestHeader("Cookie",formData.cookie); - req.onreadystatechange = function (aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - console.log("Sent form for bug " + bugID); - delete myStorage.forms[bugID]; - } else { - console.error("Sending form for bug " + bugID + - "failed!"); - } - } - }; - req.send(formData.data); - } - - if (myStorage.forms.length > 0) { - myStorage.forms.forEach(function (x) { - deserializeAndSend(x); - }); - } + function deserializeAndSend(formData) { + // FIXME notImplemented + // is it enough to just + // run XMLHttpRequest? Probably yes, this is just a form + // and this is just a HTTP request + // it is probably better to get already processed + // application/x-www-form-urlencoded + // see http://htmlhelp.com/reference/html40/forms/form.html for details + // and also https://developer.mozilla.org/en/AJAX/Getting_Started + // what's? + // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference\ + // /Global_Functions/encodeURI & co. + // this seems to be also interesting + // https://developer.mozilla.org/en/Code_snippets/Post_data_to_window + console.error("Sending bugs not implemented yet!"); + return ""; // FIXME check other HTTP headers to be set + + var bugID = formData.bugNo; + var req = new XMLHttpRequest(); + req.open("POST", formData.action, true); + // FIXME co očekávám za odpověď? req.overrideMimeType("text/xml"); + // * Accept-Encoding + // * Accept-Language + // * Accept (MIME types) + req.setRequestHeader("Connection", "keep-alive"); + req.setRequestHeader("Keep-Alive", 300); + req.setRequestHeader("Content-Type", formData.enctype); + req.setRequestHeader("Referer", bugURL + bugID); + req.setRequestHeader("Accept-Charset", formData.acceptCharset); + req.setRequestHeader("Cookie", formData.cookie); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + console.log("Sent form for bug " + bugID); + delete myStorage.forms[bugID]; + } else { + console.error("Sending form for bug " + bugID + "failed!"); + } + } + }; + req.send(formData.data); + } + + if (myStorage.forms.length > 0) { + myStorage.forms.forEach(function(x) { + deserializeAndSend(x); + }); + } } -/* Bugzilla functions.*/ +/* Bugzilla functions. */ /** * Get the current email of the reporter of the bug. - * + * * @return string */ -BzPage.prototype.getReporter = function () { - return this.dok. - querySelector("#bz_show_bug_column_2 > table .vcard:first-of-type > a"). - textContent; +BzPage.prototype.getReporter = function() { + return this.dok + .querySelector("#bz_show_bug_column_2 > table .vcard:first-of-type > a").textContent; }; /** - * Get the current version of the Fedora release ... even if changed - * meanwhile by bug triager. - * + * Get the current version of the Fedora release ... even if changed meanwhile + * by bug triager. + * * @return string (integer for released Fedora, float for RHEL, rawhide) */ -BzPage.prototype.getVersion = function () { - var verStr = this.getOptionValue("version").toLowerCase(); - var verNo = 0; - if (/rawhide/.test(verStr)) { - verNo = 999; - } else { - verNo = Number(verStr); - } - return verNo; +BzPage.prototype.getVersion = function() { + var verStr = this.getOptionValue("version").toLowerCase(); + var verNo = 0; + if (/rawhide/.test(verStr)) { + verNo = 999; + } else { + verNo = Number(verStr); + } + return verNo; }; /** * Send mouse click to the specified element - * @param element where to send mouseclick to + * + * @param element + * where to send mouseclick to * @return None */ BzPage.prototype.clickMouse = function(target) { - var localEvent = this.dok.createEvent("MouseEvents"); - localEvent.initMouseEvent("click", true, true, - this.dok.defaultView, - 0, 0, 0, 0, 0, false, false, false, false, 0, null); - target.dispatchEvent(localEvent); + var localEvent = this.dok.createEvent("MouseEvents"); + localEvent.initMouseEvent("click", true, true, this.dok.defaultView, 0, 0, + 0, 0, 0, false, false, false, false, 0, null); + target.dispatchEvent(localEvent); }; /** - * Add new keyword among the keywords. - * - * @param str string with the new keyword + * Add text to the text box (comment box or status whiteboard) + * + * @param id + * string with the id of the element + * @param string2BAdded + * string to be added to the comment box + * * @return none - * - * Checks for the existing keywords. */ -BzPage.prototype.addKeyword = function (str) { - this.addTextToTextBox("keywords",str); +BzPage.prototype.addTextToTextBox = function(id, string2BAdded) { + var textBox = this.dok.getElementById(id); + var separator = ", "; + if (textBox.tagName.toLowerCase() === "textarea") { + separator = "\n\n"; + } else { + // don't add string if it is already there + if (textBox.value.indexOf(string2BAdded) != -1) { + return; + } + } + + // don't remove the current content of the comment box, + // just behave accordingly + if (textBox.value.length > 0) { + textBox.value = textBox.value.trim() + separator; + } + textBox.value = textBox.value + string2BAdded; }; /** - * Add text to the text box (comment box or status whiteboard) - * - * @param id string with the id of the element - * @param string2BAdded string to be added to the comment box - * + * Add new keyword among the keywords. + * + * @param str + * string with the new keyword * @return none + * + * Checks for the existing keywords. */ -BzPage.prototype.addTextToTextBox = function(id,string2BAdded) { - var textBox = this.dok.getElementById(id); - var separator = ", "; - if (textBox.tagName.toLowerCase() === "textarea") { - separator = "\n\n"; - } - - // don't remove the current content of the comment box, - // just behave accordingly - if (textBox.value.length > 0) { - textBox.value = textBox.value.trim() + separator; - } - textBox.value = textBox.value + string2BAdded; +BzPage.prototype.addKeyword = function(str) { + this.addTextToTextBox("keywords", str); }; -BzPage.prototype.commentsWalker = function (fce) { - var comments = this.dok.getElementById("comments"). - getElementsByClassName("bz_comment"); - Array.forEach(comments,function (item) { fce (item); },this); +BzPage.prototype.commentsWalker = function(fce) { + var comments = this.dok.getElementById("comments").getElementsByClassName( + "bz_comment"); + Array.forEach(comments, function(item) { + fce(item); + }, this); }; /** * Set background color of all comments made by reporter in ReporterColor color - * + * */ -BzPage.prototype.checkComments = function () { - var that = this; - this.commentsWalker( function (x) { - var email = x.getElementsByClassName("vcard")[0]. - getElementsByTagName("a")[0].textContent; - if (new RegExp(that.reporter).test(email)) { - x.style.backgroundColor = ReporterColor.toString(); - } - }); +BzPage.prototype.checkComments = function() { + var that = this; + this.commentsWalker(function(x) { + var email = x.getElementsByClassName("vcard")[0] + .getElementsByTagName("a")[0].textContent; + if (new RegExp(that.reporter).test(email)) { + x.style.backgroundColor = ReporterColor.toString(); + } + }); }; -BzPage.prototype.collectComments = function () { - var outStr = ""; - this.commentsWalker( function (x) { - outStr += x.getElementsByTagName("pre")[0].textContent + "\n"; - }); - return outStr.trim(); +BzPage.prototype.collectComments = function() { + var outStr = ""; + this.commentsWalker(function(x) { + outStr += x.getElementsByTagName("pre")[0].textContent + "\n"; + }); + return outStr.trim(); }; /** * Is this bug a RHEL bug? - * + * * @return Boolean true if it is a RHEL bug */ BzPage.prototype.isRHEL = function() { - return (/Red Hat Enterprise Linux/).test(this.product); + return (/Red Hat Enterprise Linux/).test(this.product); }; /** * Find out whether the bug is needed an attention of bugZappers - * + * * @return Boolean whether the bug has been triaged or not */ BzPage.prototype.isTriaged = function() { - // First excceptions - if (this.version > 7 && this.version < 13) { - return this.dok.getElementById("bug_status"). - value.toUpperCase() !== "NEW"; - } else { // and then the rule - return this.hasKeyword("Triaged"); - } + // First excceptions + if (this.version > 7 && this.version < 13) { + return this.dok.getElementById("bug_status").value.toUpperCase() !== "NEW"; + } else { // and then the rule + return this.hasKeyword("Triaged"); + } }; /** * Set branding colours to easily distinguish between Fedora and RHEL bugs - * - * @param brand string with product of the current bug - * @param version string with the version of the bug - * @param its string with the IsueTracker numbers + * + * @param brand + * string with product of the current bug + * @param version + * string with the version of the bug + * @param its + * string with the IsueTracker numbers * @return none - * + * */ -BzPage.prototype.setBranding = function () { - var brandColor = {}; - var TriagedColor = {}; - - if (this.isRHEL()) { - if (this.its && (this.its.length > 0)) { - brandColor = RHITColor; - } else { - brandColor = RHColor; - } - } else if (new RegExp("Fedora").test(this.product)) { - if (this.version == 999) { - brandColor = RawhideColor; - } else { - brandColor = FedoraColor; - } - } - - // Comment each of the following lines to get only partial branding - this.dok.getElementsByTagName("body")[0]. - style.background = brandColor.toString() + " none"; - this.dok.getElementById("titles"). - style.background = brandColor.toString() + " none"; - - // Remove "Bug" from the title of the bug page, so we have more space with plenty of tabs - var titleElem = this.dok.getElementsByTagName("title")[0]; - titleElem.textContent = titleElem.textContent.slice(4); - var bodyTitleParent = this.dok.getElementById("summary_alias_container").parentNode; - var bodyTitleElem = bodyTitleParent.getElementsByTagName("b")[0]; - bodyTitleElem.textContent = bodyTitleElem.textContent.slice(4); - - // Make background-color of the body of bug salmon pink - // for security bugs. - if (this.hasKeyword("Security")) { - this.dok.getElementById("bugzilla-body"). - style.background = SalmonPink.toString() + ' none'; - } - - // Make it visible whether the bug has been triaged - if (this.isTriaged()) { - this.dok.getElementById("bz_field_status"). - style.background = brandColor.lightColor().toString() + " none"; - } - - // we should make visible whether maintCCAddr is in CCList - if (isInList(this.maintCCAddr, this.CCList)) { - var ccEditBoxElem = this.dok.getElementById("cc_edit_area_showhide"); - //ccEditBoxElem.textContent = "*"+ccEditBoxElem.textContent; - ccEditBoxElem.style.color = "navy"; - ccEditBoxElem.style.fontWeight = "bolder"; - ccEditBoxElem.style.textDecoration = "underline"; - } - - // mark suspicious components - var compElems; - if (suspiciousComponents && isInList(this.component,suspiciousComponents) - && (compElems = - this.dok.getElementById("bz_component_edit_container"))) { - compElems.style.background = "red none"; - } +BzPage.prototype.setBranding = function() { + var brandColor = {}; + var TriagedColor = {}; + + if (this.isRHEL()) { + if (this.its && (this.its.length > 0)) { + brandColor = RHITColor; + } else { + brandColor = RHColor; + } + } else if (new RegExp("Fedora").test(this.product)) { + if (this.version == 999) { + brandColor = RawhideColor; + } else { + brandColor = FedoraColor; + } + } + + // Comment each of the following lines to get only partial branding + this.dok.getElementsByTagName("body")[0].style.background = brandColor + .toString() + + " none"; + this.dok.getElementById("titles").style.background = brandColor.toString() + + " none"; + + // Remove "Bug" from the title of the bug page, so we have more space with + // plenty of tabs + var titleElem = this.dok.getElementsByTagName("title")[0]; + titleElem.textContent = titleElem.textContent.slice(4); + var bodyTitleParent = this.dok.getElementById("summary_alias_container").parentNode; + var bodyTitleElem = bodyTitleParent.getElementsByTagName("b")[0]; + bodyTitleElem.textContent = bodyTitleElem.textContent.slice(4); + + // Make background-color of the body of bug salmon pink + // for security bugs. + if (this.hasKeyword("Security")) { + this.dok.getElementById("bugzilla-body").style.background = SalmonPink + .toString() + ' none'; + } + + // Make it visible whether the bug has been triaged + if (this.isTriaged()) { + this.dok.getElementById("bz_field_status").style.background = brandColor + .lightColor().toString() + + " none"; + } + + // we should make visible whether maintCCAddr is in CCList + if (isInList(this.maintCCAddr, this.CCList)) { + var ccEditBoxElem = this.dok.getElementById("cc_edit_area_showhide"); + // ccEditBoxElem.textContent = "*"+ccEditBoxElem.textContent; + ccEditBoxElem.style.color = "navy"; + ccEditBoxElem.style.fontWeight = "bolder"; + ccEditBoxElem.style.textDecoration = "underline"; + } + + // mark suspicious components + var compElems; + if (suspiciousComponents + && isInList(this.component, suspiciousComponents) + && (compElems = this.dok + .getElementById("bz_component_edit_container"))) { + compElems.style.background = "red none"; + } }; /** - * Given line to be parsed, find out which chipset it is and fill in the whiteboard - * - * @param iLine string with the whole unparsed "interesting line" - * @param driverStr string with the driver name + * Given line to be parsed, find out which chipset it is and fill in the + * whiteboard + * + * @param iLine + * string with the whole unparsed "interesting line" + * @param driverStr + * string with the driver name * @return None */ -BzPage.prototype.fillInWhiteBoard = function (iLine, driverStr) { - function groupIDs (manStr,cardStrID) { - var outStr = filterByRegexp(chipIDsGroupings,manStr+","+cardStrID); - if (outStr.length === 0) { - outStr = "UNGROUPED_" + manStr+"/"+cardStrID; - } - return outStr; - }; - - /** - * Given PCI IDs for manufacturer and card ID return chipset string - * - * @param manufacturerNo string with manufacturer PCI ID - * @param cardNo string with card PCI ID - * - * @return array with chip string and optinoal variants - */ - function checkChipStringFromID (manufacturerNo,cardNo) { - var soughtID = (manufacturerNo+","+cardNo).toUpperCase(); - var outList = PCI_ID_Array[soughtID]; - if (outList) { - return outList; - } else { - return ""; - } - }; - - var outStr = ""; - var cardIDStr = ""; - var cardIDArr = []; - - chipSwitchboard: - if (driverStr === "RADEON") { - var cardID = iLine.replace(ATIgetIDRE,"$1"); - cardIDArr = checkChipStringFromID("1002",cardID); - if (cardIDArr.length > 0) { - cardIDStr = cardIDArr[0]; - if (cardIDArr[1]) { - optionStr = cardIDArr[1]; - outStr = groupIDs(driverStr,cardIDStr)+"/" + optionStr; - } else { - outStr = groupIDs(driverStr,cardIDStr); - optionStr = ""; - } - } else { - outStr = "**** FULLSTRING: " + iLine; - } - } else { - // Intel Corporation, NVIDIA - cardIDArr = manuChipStrs.filter(function (el, ind, arr) { - return new RegExp(el[0],"i").test(iLine); - }); - if (cardIDArr && (cardIDArr.length > 0)) { - cardIDArr = cardIDArr[0]; - } else { - outStr = iLine; - break chipSwitchboard; - } - // cardIDArr [0] = RE, [1] = ("RADEON","INTEL","NOUVEAU"), [2] = manu PCIID - iLine = iLine.replace(new RegExp(cardIDArr[0],"i")).trim(); - // nVidia developers opted-out from grouping - if (driverStr === "INTEL") { - outStr = groupIDs(cardIDArr[1],iLine); - } else { - outStr = iLine; - } - } - this.addTextToTextBox("status_whiteboard",("card_"+outStr).trim()); - this.dok.getElementById("chipmagic").style.display = "none"; +BzPage.prototype.fillInWhiteBoard = function(iLine, driverStr) { + function groupIDs(manStr, cardStrID) { + var outStr = filterByRegexp(chipIDsGroupings, manStr + "," + cardStrID); + if (outStr.length === 0) { + outStr = "UNGROUPED_" + manStr + "/" + cardStrID; + } + return outStr; + } + ; + + /** + * Given PCI IDs for manufacturer and card ID return chipset string + * + * @param manufacturerNo + * string with manufacturer PCI ID + * @param cardNo + * string with card PCI ID + * + * @return array with chip string and optinoal variants + */ + function checkChipStringFromID(manufacturerNo, cardNo) { + var soughtID = (manufacturerNo + "," + cardNo).toUpperCase(); + var outList = PCI_ID_Array[soughtID]; + if (outList) { + return outList; + } else { + return ""; + } + } + ; + + var outStr = ""; + var cardIDStr = ""; + var cardIDArr = []; + + chipSwitchboard: if (driverStr === "RADEON") { + var cardID = iLine.replace(ATIgetIDRE, "$1"); + cardIDArr = checkChipStringFromID("1002", cardID); + if (cardIDArr.length > 0) { + cardIDStr = cardIDArr[0]; + if (cardIDArr[1]) { + optionStr = cardIDArr[1]; + outStr = groupIDs(driverStr, cardIDStr) + "/" + optionStr; + } else { + outStr = groupIDs(driverStr, cardIDStr); + optionStr = ""; + } + } else { + outStr = "**** FULLSTRING: " + iLine; + } + } else { + // Intel Corporation, NVIDIA + cardIDArr = manuChipStrs.filter(function(el, ind, arr) { + return new RegExp(el[0], "i").test(iLine); + }); + if (cardIDArr && (cardIDArr.length > 0)) { + cardIDArr = cardIDArr[0]; + } else { + outStr = iLine; + break chipSwitchboard; + } + // cardIDArr [0] = RE, [1] = ("RADEON","INTEL","NOUVEAU"), [2] = manu + // PCIID + iLine = iLine.replace(new RegExp(cardIDArr[0], "i")).trim(); + // nVidia developers opted-out from grouping + if (driverStr === "INTEL") { + outStr = groupIDs(cardIDArr[1], iLine); + } else { + outStr = iLine; + } + } + this.addTextToTextBox("status_whiteboard", ("card_" + outStr).trim()); + this.dok.getElementById("chipmagic").style.display = "none"; }; /** - * Generic function to add new button to the page. - * Actually copies new button from the old one (in order to have the same - * look-and-feel, etc. - * @param originalLocation object after which the new button will be added - * @param newId string with the id of the new button; has to be unique in - whole page - * @param newLabel string with the label which will be shown to user - * @param commentString string with comment to be added to the comment box - * @param nState string with the new state bug should switch to (see - * generalPurposeCureForAllDisease function for details) - * @param secPar string with second parameter for generalPurposeForAllDisease - * @param doSubmit bool optional whether the button should submit whole page - * (default true) - * + * Generic function to add new button to the page. Actually copies new button + * from the old one (in order to have the same look-and-feel, etc. + * + * @param originalLocation + * object after which the new button will be added + * @param newId + * string with the id of the new button; has to be unique in whole + * page + * @param newLabel + * string with the label which will be shown to user + * @param commentString + * string with comment to be added to the comment box + * @param nState + * string with the new state bug should switch to (see + * generalPurposeCureForAllDisease function for details) + * @param secPar + * string with second parameter for generalPurposeForAllDisease + * @param doSubmit + * bool optional whether the button should submit whole page (default + * true) + * * @return none */ -BzPage.prototype.addNewButton = function (originalLocation,newId,newLabel, - commentString,nState,secPar,doSubmit,after) { - var that = this; - var commStr = ""; - if (doSubmit === undefined) { // missing optional argument - doSubmit = false; - } - if (after === undefined) { // missing optional argument - after = false; - } - if (msgStrs[commentString]) { - commStr = msgStrs[commentString]; - } - var newButton = this.dok.createElement("input"); - newButton.setAttribute("id",newId); - if (doSubmit) { - newButton.setAttribute("type","submit"); - } else { - newButton.setAttribute("type","button"); - } - newButton.value = newLabel; - newButton.addEventListener("click",function (evt) { - that.generalPurposeCureForAllDisease(commStr,nState, secPar); - }, false); - - if (after) { - originalLocation.parentNode.insertBefore(newButton, - originalLocation.nextSibling); - originalLocation.parentNode. - insertBefore(this.dok.createTextNode("\u00A0"),newButton); - } else { - originalLocation.parentNode.insertBefore(newButton, - originalLocation); - originalLocation.parentNode. - insertBefore(this.dok.createTextNode("\u00A0"),originalLocation); - } +BzPage.prototype.addNewButton = function(originalLocation, newId, newLabel, + commentString, nState, secPar, doSubmit, after) { + var that = this; + var commStr = ""; + if (doSubmit === undefined) { // missing optional argument + doSubmit = false; + } + if (after === undefined) { // missing optional argument + after = false; + } + if (msgStrs[commentString]) { + commStr = msgStrs[commentString]; + } + var newButton = this.dok.createElement("input"); + newButton.setAttribute("id", newId); + if (doSubmit) { + newButton.setAttribute("type", "submit"); + } else { + newButton.setAttribute("type", "button"); + } + newButton.value = newLabel; + newButton.addEventListener("click", function(evt) { + that.generalPurposeCureForAllDisease(commStr, nState, secPar); + }, false); + + if (after) { + originalLocation.parentNode.insertBefore(newButton, + originalLocation.nextSibling); + originalLocation.parentNode.insertBefore(this.dok + .createTextNode("\u00A0"), newButton); + } else { + originalLocation.parentNode.insertBefore(newButton, originalLocation); + originalLocation.parentNode.insertBefore(this.dok + .createTextNode("\u00A0"), originalLocation); + } }; /** - * Get attached Xorg.0.log, parse it and find the value of chip. - * Does not fill the whiteboard itself, just adds button to do so,paramList - * so that slow XMLHttpRequest is done in advance. - * + * Get attached Xorg.0.log, parse it and find the value of chip. Does not fill + * the whiteboard itself, just adds button to do so,paramList so that slow + * XMLHttpRequest is done in advance. + * * @return None */ -BzPage.prototype.fillInChipMagic = function () { - var XorgLogURL = ""; - var XorgLogAttID = ""; - var XorgLogFound = false; - var attURL = "", interestingLine = ""; - var interestingArray = []; - - - // Find out Xorg.0.log attachment URL - this.XorgLogAttList = this.attachments.filter(function (value, index, array) { - // Xorg.0.log must be text, otherwise we cannot parse it - return (/[xX].*log/.test(value[0]) && /text/.test(value[2])); - }); - if (this.XorgLogAttList.length === 0) { - return; - } - - XorgLogAttID = this.XorgLogAttList[this.XorgLogAttListIndex][1]; - attURL = "https://bugzilla.redhat.com/attachment.cgi?id="+XorgLogAttID; - that = this; - - var req = new XMLHttpRequest(); - req.open("GET",attURL,true); - req.onreadystatechange = function (aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - var ret = req.responseText; - var interestingLineArr = ret.split("\n"). - filter(function (v,i,a) { - return ChipsetRE.test(v); - }); - console.log("interestingLineArr = " + interestingLineArr.toSource()); - if (interestingLineArr.length >0) { - interestingArray = ChipsetRE.exec(interestingLineArr[0]); - interestingLine = interestingArray[2]. - replace(/[\s"]+/g," ").trim(); - var whiteboardInput = that.dok. - getElementById("status_whiteboard"); - that.addNewButton(whiteboardInput,"chipmagic","Fill In", - "","CHIPMAGIC", - interestingLine+"\t"+interestingArray[1].toUpperCase(), - false,true); - } - } else { - throw "Getting attachment " + attURL + "failed!"; - } - } - }; - req.send(""); - - this.XorgLogAttListIndex++; +BzPage.prototype.fillInChipMagic = function() { + var XorgLogURL = ""; + var XorgLogAttID = ""; + var XorgLogFound = false; + var attURL = "", interestingLine = ""; + var interestingArray = []; + + // Find out Xorg.0.log attachment URL + this.XorgLogAttList = this.attachments + .filter(function(value, index, array) { + // Xorg.0.log must be text, otherwise we cannot parse it + return (/[xX].*log/.test(value[0]) && /text/.test(value[2])); + }); + if (this.XorgLogAttList.length === 0) { + return; + } + + XorgLogAttID = this.XorgLogAttList[this.XorgLogAttListIndex][1]; + attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" + XorgLogAttID; + that = this; + + var req = new XMLHttpRequest(); + req.open("GET", attURL, true); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + var ret = req.responseText; + var interestingLineArr = ret.split("\n").filter( + function(v, i, a) { + return ChipsetRE.test(v); + }); + console.log("interestingLineArr = " + + interestingLineArr.toSource()); + if (interestingLineArr.length > 0) { + interestingArray = ChipsetRE.exec(interestingLineArr[0]); + interestingLine = interestingArray[2].replace(/[\s"]+/g, + " ").trim(); + var whiteboardInput = that.dok + .getElementById("status_whiteboard"); + that.addNewButton(whiteboardInput, "chipmagic", "Fill In", + "", "CHIPMAGIC", interestingLine + "\t" + + interestingArray[1].toUpperCase(), false, + true); + } + } else { + throw "Getting attachment " + attURL + "failed!"; + } + } + }; + req.send(""); + + this.XorgLogAttListIndex++; }; /** * Opens a new tab with a query for the given text in the selected component - * @param text to be searched for - * @param component string with the component name (maybe latter regexp?) - * @param product (optional) string with the product name + * + * @param text + * to be searched for + * @param component + * string with the component name (maybe latter regexp?) + * @param product + * (optional) string with the product name * @return None - * + * */ -BzPage.prototype.queryInNewTab = function(text,component,product) { - // Optional parameter - if (product === undefined) { - product = this.product; - } - var url = "https://bugzilla.redhat.com/buglist.cgi?query_format=advanced"; - if (product) { - url += "&product="+product.trim(); - } - if (component) { - url += "&field0-0-0=component&type0-0-0=substring&value0-0-0="+component.trim(); - } - // using more complicated query tables here, because they can be more easily edited - // for further investigative searches - if (text) { - text = encodeURIComponent(text.trim()); - var searchText = "&field1-0-0=longdesc&type1-0-0=substring&value1-0-0="+text+ - "&field1-0-1=attach_data.thedata&type1-0-1=substring&value1-0-1="+text+ - "&field1-0-2=status_whiteboard&type1-0-2=substring&value1-0-2="+text; - url += searchText; - jetpack.tabs.open(url); - // Don't do it ... b.m.o is apparently not powerful enough to sustain the weight - // of the search - if (false) { - url = "https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced"+ - "field0-0-0=product;type0-0-0=regexp;"+ - "value0-0-0=thunderbird|firefox|xulrunner" + searchText.replace("&",";"); - jetpack.tabs.open(url); - } - } +BzPage.prototype.queryInNewTab = function(text, component, product) { + // Optional parameter + if (product === undefined) { + product = this.product; + } + var url = "https://bugzilla.redhat.com/buglist.cgi?query_format=advanced"; + if (product) { + url += "&product=" + product.trim(); + } + if (component) { + url += "&field0-0-0=component&type0-0-0=substring&value0-0-0=" + + component.trim(); + } + // using more complicated query tables here, because they can be more easily + // edited + // for further investigative searches + if (text) { + text = encodeURIComponent(text.trim()); + var searchText = "&field1-0-0=longdesc&type1-0-0=substring&value1-0-0=" + + text + + "&field1-0-1=attach_data.thedata&type1-0-1=substring&value1-0-1=" + + text + + "&field1-0-2=status_whiteboard&type1-0-2=substring&value1-0-2=" + + text; + url += searchText; + jetpack.tabs.open(url); + // Don't do it ... b.m.o is apparently not powerful enough to sustain + // the weight + // of the search + if (false) { + url = "https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced" + + "field0-0-0=product;type0-0-0=regexp;" + + "value0-0-0=thunderbird|firefox|xulrunner" + + searchText.replace("&", ";"); + jetpack.tabs.open(url); + } + } }; /** @@ -1267,867 +1372,902 @@ BzPage.prototype.queryInNewTab = function(text,component,product) { * function this.queryInNewTab, and run it. */ BzPage.prototype.queryForSelection = function() { - var text = jetpack.selection.text; - if (!text) { - text = jetpack.clipboard.get(); - } - if (text) { - this.queryInNewTab(text, this.component); - } + var text = jetpack.selection.text; + if (!text) { + text = jetpack.clipboard.get(); + } + if (text) { + this.queryInNewTab(text, this.component); + } }; /** - * + * */ BzPage.prototype.sendBugUpstream = function() { - var url = filterByRegexp(upstreamBugzillasArray, - this.getOptionValue("component")); - - var ret = jetpack.tabs.open(url); - var that = this; - jetpack.tabs.onReady(function() { - var otherDoc = ret.contentDocument; - var otherElems = otherDoc.forms.namedItem("Create").elements; - otherElems.namedItem("short_desc").value = - that.dok.getElementById("short_desc_nonedit_display"). - textContent.trim(); - otherElems.namedItem("comment").value = that.collectComments(); - ret.focused(); - }); + var url = filterByRegexp(upstreamBugzillasArray, this + .getOptionValue("component")); + + var ret = jetpack.tabs.open(url); + var that = this; + jetpack.tabs.onReady(function() { + var otherDoc = ret.contentDocument; + var otherElems = otherDoc.forms.namedItem("Create").elements; + otherElems.namedItem("short_desc").value = that.dok + .getElementById("short_desc_nonedit_display").textContent + .trim(); + otherElems.namedItem("comment").value = that.collectComments(); + ret.focused(); + }); }; /** * Parse the row with the attachment - * - * @param <tr> DOM element to be parsed - * @return array with string name of the attachment, - integer its id number, - string of MIME type, - integer of size in kilobytes, - and the whole element itself + * + * @param + * <tr> DOM element to be parsed + * @return array with string name of the attachment, integer its id number, + * string of MIME type, integer of size in kilobytes, and the whole + * element itself */ -BzPage.prototype.parseAttachmentLine = function (inElem) { - var MIMEtype = ""; - var size = 0; +BzPage.prototype.parseAttachmentLine = function(inElem) { + var MIMEtype = ""; + var size = 0; - // Skip over obsolete attachments - if (inElem.getElementsByClassName("bz_obsolete").length>0) { - return([]); - } + // Skip over obsolete attachments + if (inElem.getElementsByClassName("bz_obsolete").length > 0) { + return ( []); + } - // getting name of the attachment - var attName = inElem.getElementsByTagName("b")[0].textContent.trim(); + // getting name of the attachment + var attName = inElem.getElementsByTagName("b")[0].textContent.trim(); - var aHrefsArr = inElem.getElementsByTagName("a"); - var aHref = Array.filter(aHrefsArr,function (x) { - return x.textContent.trim() == "Details"; - })[0]; - var id = parseInt(aHref.getAttribute("href"). - replace(/^.*attachment.cgi\?id=/, ""),10); + var aHrefsArr = inElem.getElementsByTagName("a"); + var aHref = Array.filter(aHrefsArr, function(x) { + return x.textContent.trim() == "Details"; + })[0]; + var id = parseInt(aHref.getAttribute("href").replace( + /^.*attachment.cgi\?id=/, ""), 10); - //getting MIME type and size - var stringArray = inElem.getElementsByClassName("bz_attach_extra_info")[0]. - textContent.replace(/[\n ()]+/g," ").trim().split(", "); - size = parseInt(stringArray[0],10); - MIMEtype = stringArray[1].split(" ")[0]; + // getting MIME type and size + var stringArray = inElem.getElementsByClassName("bz_attach_extra_info")[0].textContent + .replace(/[\n ()]+/g, " ").trim().split(", "); + size = parseInt(stringArray[0], 10); + MIMEtype = stringArray[1].split(" ")[0]; - return [attName,id,MIMEtype,size,inElem]; + return [ attName, id, MIMEtype, size, inElem ]; }; /** * Select option with given label on the <SELECT> element with given id. - * + * * Also execute change HTMLEvent, so that the form behaves accordingly. - * + * * @param id * @param label * @return none */ -BzPage.prototype.selectOption = function(id,label) { - var sel = this.dok.getElementById(id); - var options = Array.filter(sel.getElementsByTagName("option"), - function (x){ return x.textContent.trim() == label; } - ); - theOption = options.length ? options[0] : []; - if (theOption) { - theOption.selected = true; - var intEvent = this.dok.createEvent("HTMLEvents"); - intEvent.initEvent("change", true, true); - theOption.dispatchEvent(intEvent); - } +BzPage.prototype.selectOption = function(id, label) { + var sel = this.dok.getElementById(id); + var options = Array.filter(sel.getElementsByTagName("option"), function(x) { + return x.textContent.trim() == label; + }); + theOption = options.length ? options[0] : []; + if (theOption) { + theOption.selected = true; + var intEvent = this.dok.createEvent("HTMLEvents"); + intEvent.initEvent("change", true, true); + theOption.dispatchEvent(intEvent); + } }; /** * Check for the presence of a keyword - * - * @param str string with the keyword + * + * @param str + * string with the keyword * @return Boolean - * + * */ BzPage.prototype.hasKeyword = function(str) { - var kwd = this.dok.getElementById('keywords').value.trim(); - return (new RegExp(str).test(kwd)); + var kwd = this.dok.getElementById('keywords').value.trim(); + return (new RegExp(str).test(kwd)); }; /** * Add accesskey to the particular element - * - * @param rootElement element to which the new text object will be attached - * @param beforeText text before the accesskey character - * @param accKey what will be the accesskey itself - * @param afterText text after the accesskey character - * @return modified element with the fixed accesskey - * FIXME isn't this closure and possible memleak? -*/ -BzPage.prototype.fixElement = function (elem,beforeText,accKey,afterText) { - elem.setAttribute("accesskey",accKey.toLowerCase()); - elem.innerHTML = beforeText + "<b><u>" + accKey + "</u></b>" + afterText; - return elem; + * + * @param rootElement + * element to which the new text object will be attached + * @param beforeText + * text before the accesskey character + * @param accKey + * what will be the accesskey itself + * @param afterText + * text after the accesskey character + * @return modified element with the fixed accesskey FIXME isn't this closure + * and possible memleak? + */ +BzPage.prototype.fixElement = function(elem, beforeText, accKey, afterText) { + elem.setAttribute("accesskey", accKey.toLowerCase()); + elem.innerHTML = beforeText + "<b><u>" + accKey + "</u></b>" + afterText; + return elem; }; /** - * Add XGL to the CC list - * - * @param evt event which made this function active + * Add XGL to the CC list + * + * @param evt + * event which made this function active * @return none */ BzPage.prototype.changeOwner = function(newAssignee) { - /** Take care that when changing assignment of the bug, - * current owner is added to CC list. - * Switch off setting to the default assignee - */ - var defAssigneeButton; - if (!isInList(newAssignee, this.CCList)) { - this.dok.getElementById("newcc").textContent = newAssignee; - } - if (newAssignee) { - this.clickMouse(this.dok.getElementById("bz_assignee_edit_action")); - this.dok.getElementById("assigned_to").value = newAssignee; - this.dok.getElementById("set_default_assignee").checked = false; - if (defAssigneeButton = this.dok. - getElementById("setdefaultassigneebutton")) { - defAssigneeButton.style.display = "none"; - } - } + /** + * Take care that when changing assignment of the bug, current owner is + * added to CC list. Switch off setting to the default assignee + */ + var defAssigneeButton; + if (!isInList(newAssignee, this.CCList)) { + this.dok.getElementById("newcc").textContent = newAssignee; + } + if (newAssignee) { + this.clickMouse(this.dok.getElementById("bz_assignee_edit_action")); + this.dok.getElementById("assigned_to").value = newAssignee; + this.dok.getElementById("set_default_assignee").checked = false; + if (defAssigneeButton = this.dok + .getElementById("setdefaultassigneebutton")) { + defAssigneeButton.style.display = "none"; + } + } }; /** * Set the bug to NEEDINFO state - * + * * Working function. + * * @return none */ BzPage.prototype.setNeedinfoReporter = function() { - this.clickMouse(this.dok.getElementById("needinfo")); - this.selectOption("needinfo_role", "reporter"); + this.clickMouse(this.dok.getElementById("needinfo")); + this.selectOption("needinfo_role", "reporter"); }; /** - * Return string with the ID for the external_id SELECT for - * external bugzilla - * - * @param URLhostname string hostname of the external bugzilla + * Return string with the ID for the external_id SELECT for external bugzilla + * + * @param URLhostname + * string hostname of the external bugzilla * @return string with the string for the external_id SELECT */ BzPage.prototype.getBugzillaName = function(URLhostname) { - var bugzillaID = ""; - if (hashBugzillaName[URLhostname]) { - bugzillaID = hashBugzillaName[URLhostname]; - } else { - bugzillaID = ""; - } - return bugzillaID; + var bugzillaID = ""; + if (hashBugzillaName[URLhostname]) { + bugzillaID = hashBugzillaName[URLhostname]; + } else { + bugzillaID = ""; + } + return bugzillaID; }; /** * Generate URL of the bug on remote bugzilla - * @param selectValue Number which is index of the bugzilla in hashBugzillaWholeURL - * @param bugID Number which is bug ID + * + * @param selectValue + * Number which is index of the bugzilla in hashBugzillaWholeURL + * @param bugID + * Number which is bug ID * @return string with the URL */ -BzPage.prototype.getWholeURL = function(selectValue,bugID) { - var returnURL = ""; - if (hashBugzillaWholeURL[selectValue]) { - returnURL = hashBugzillaWholeURL[selectValue]+bugID; - } else { - returnURL = ""; - } - return returnURL; +BzPage.prototype.getWholeURL = function(selectValue, bugID) { + var returnURL = ""; + if (hashBugzillaWholeURL[selectValue]) { + returnURL = hashBugzillaWholeURL[selectValue] + bugID; + } else { + returnURL = ""; + } + return returnURL; }; /** * Callback function for the XMLRPC request - * - * @param ret object with xmlhttprequest response - * with attributes: - * + status -- int return code - * + statusText - * + responseHeaders - * + responseText + * + * @param ret + * object with xmlhttprequest response with attributes: + status -- + * int return code + statusText + responseHeaders + responseText */ -BzPage.prototype.callBack = function(data,textStatus) { - if (--this.reqCounter <= 0) { - setTimeout(this.dok.location.reload,1000); - } +BzPage.prototype.callBack = function(data, textStatus) { + if (--this.reqCounter <= 0) { + setTimeout(this.dok.location.reload, 1000); + } }; /** - * The worker function -- call XMLRPC to fix MIME type of the - * particular attachment - * - * @param id integer with the attachment id to be fixed - * @param type string with the new MIME type, optional defaults to "text/plain" - * @param email Boolean whether email should be sent to appropriate person; option, - defaults to false - -updateAttachMimeType($data_ref, $username, $password) - -Update the attachment mime type of an attachment. The first argument is a data hash containing information on the new MIME type and the attachment id that you want to act on. - - $data_ref = { - "attach_id" => "<Attachment ID>", - # Attachment ID to perform MIME type change on. - "mime_type" => "<New MIME Type Value>", - # Legal MIME type value that you want to change the attachment to. - "nomail" => 0, - # OPTIONAL Flag that is either 1 or 0 if you want email to be sent or not for this change - }; - + * The worker function -- call XMLRPC to fix MIME type of the particular + * attachment + * + * @param id + * integer with the attachment id to be fixed + * @param type + * string with the new MIME type, optional defaults to "text/plain" + * @param email + * Boolean whether email should be sent to appropriate person; + * option, defaults to false + * + * updateAttachMimeType($data_ref, $username, $password) + * + * Update the attachment mime type of an attachment. The first argument is a + * data hash containing information on the new MIME type and the attachment id + * that you want to act on. + * + * $data_ref = { "attach_id" => "<Attachment ID>", # Attachment ID to perform + * MIME type change on. "mime_type" => "<New MIME Type Value>", # Legal MIME + * type value that you want to change the attachment to. "nomail" => 0, # + * OPTIONAL Flag that is either 1 or 0 if you want email to be sent or not for + * this change }; + * */ -BzPage.prototype.fixAttachById = function(id,type,email) { - if (type === undefined) { - type = "text/plain"; - } - if (email === undefined) { - email = false; - } - - var msg = new XMLRPCMessage("bugzilla.updateAttachMimeType"); - msg.addParameter({'attach_id':id, 'mime_type':type, 'nomail':!email}); - msg.addParameter(this.login); - msg.addParameter(this.password); - - var req = new XMLHttpRequest(); - var that = this; - req.open("POST",XMLRPCurl,true); - req.overrideMimeType("text/xml"); - req.setRequestHeader("Content-type","text/xml"); - req.onreadystatechange = function (aEvt) { - if (req.readyState == 4) { - if (req.status == 200) { - console.log("Fixing attachment MIME type success!"); - that.callBack(); - } else { - console.error("Fixing MIME type attachment failed!"); - } - } - }; - req.send(msg.xml()); - this.reqCounter++; +BzPage.prototype.fixAttachById = function(id, type, email) { + if (type === undefined) { + type = "text/plain"; + } + if (email === undefined) { + email = false; + } + + var msg = new XMLRPCMessage("bugzilla.updateAttachMimeType"); + msg.addParameter( { + 'attach_id' : id, + 'mime_type' : type, + 'nomail' : !email + }); + msg.addParameter(this.login); + msg.addParameter(this.password); + + var req = new XMLHttpRequest(); + var that = this; + req.open("POST", XMLRPCurl, true); + req.overrideMimeType("text/xml"); + req.setRequestHeader("Content-type", "text/xml"); + req.onreadystatechange = function(aEvt) { + if (req.readyState == 4) { + if (req.status == 200) { + console.log("Fixing attachment MIME type success!"); + that.callBack(); + } else { + console.error("Fixing MIME type attachment failed!"); + } + } + }; + req.send(msg.xml()); + this.reqCounter++; }; // FIXME possibly eliminate this function altogether and // make it inline? BzPage.prototype.fixAllAttachments = function(list) { - Array.forEach(list,function (x) { - this.fixAttachById(x[1]); - }, this); + Array.forEach(list, function(x) { + this.fixAttachById(x[1]); + }, this); }; /** * Create a button for fixing all bad attachments. - * - * @param list Array of all bad attachmentss + * + * @param list + * Array of all bad attachmentss * @return button fixing all bad Attachments */ -BzPage.prototype.createFixAllButton = function (list) { +BzPage.prototype.createFixAllButton = function(list) { if (!XMLRPCMessage) { return; } - var that = this; - var elem = this.dok.createElement("a"); - elem.setAttribute("href",""); - elem.setAttribute("accesskey","f"); - elem.innerHTML = "<b>F</b>ix all"; - elem.addEventListener("click", function() { - that.fixAllAttachments(list); - }, false); - return elem; + var that = this; + var elem = this.dok.createElement("a"); + elem.setAttribute("href", ""); + elem.setAttribute("accesskey", "f"); + elem.innerHTML = "<b>F</b>ix all"; + elem.addEventListener("click", function() { + that.fixAllAttachments(list); + }, false); + return elem; }; /** * Add a link to the bad attachment for fixing it. - * - * @param <TR> DOM jQuery element with a bad attachment + * + * @param + * <TR> DOM jQuery element with a bad attachment * @return none */ -BzPage.prototype.addTextLink = function (row) { - var that = this; - var elemS = row[4].getElementsByTagName("td"); - var elem = elemS[elemS.length-1]; - elem.innerHTML += "<br/><a href=''>Text</a>"; - elem.addEventListener("click",function (x) { - that.fixAttachById(row[1],"text/plain"); - }, false); +BzPage.prototype.addTextLink = function(row) { + var that = this; + var elemS = row[4].getElementsByTagName("td"); + var elem = elemS[elemS.length - 1]; + elem.innerHTML += "<br/><a href=''>Text</a>"; + elem.addEventListener("click", function(x) { + that.fixAttachById(row[1], "text/plain"); + }, false); }; /** * Add information about the upstream bug upstream, and closing it. - * @param evt event which called this handler - * + * + * @param evt + * event which called this handler + * * @return none */ BzPage.prototype.addClosingUpstream = function() { - var refs = this.dok.getElementById("external_bugs_table"). - getElementsByTagName("tr"); - // that's a bad id, if there is a one. :) - var inputBox = this.dok.getElementById("inputbox"); - var externalBugID = 0; - var wholeURL = ""; - - // Fix missing ID on the external_id SELECT - this.dok.getElementsByName("external_id")[0].setAttribute("id","external_id"); - - if (inputBox.value.match(/^http.*/)) { - var helpAElem = this.dok.createElement("a"); - wholeURL = inputBox.value; - helpAElem.setAttribute("href",wholeURL); - var paramsArr = helpAElem.search.replace(/^\?/,'').split('&'); - // get ID# - var params = {}, s = []; - paramsArr.forEach(function (par,idx,arr) { - s = par.split('='); - params[s[0]] = s[1]; - }); - if (params.id) { - externalBugID = parseInt(params.id,10); - inputBox.value = externalBugID; - } - // get host and bugzillaName - var bugzillaName = this.getBugzillaName(helpAElem.hostname); - this.selectOption("external_id", bugzillaName); - } else if (!isNaN(inputBox.value)) { - externalBugID = parseInt(inputBox.value,10); - var bugzillaID = this.dok.getElementById("external_id").value; - wholeURL = this.getWholeURL(bugzillaID,externalBugID); - } else { - // no inputBox.value -- maybe there is an external bug from - // the previous commit? - } - - // It is not good to close bug as UPSTREAM, if there is no reference - // to the upstream bug. - if ((externalBugID > 0) || (refs.length > 2)) { - this.addTextToTextBox("comment", - msgStrs.sentUpstreamString.replace("§§§",wholeURL)); - this.selectOption("bug_status", "CLOSED"); - this.selectOption("resolution", "UPSTREAM"); - } else { - console.log("No external bug specified among the External References!"); - } -}; - -/** Insert a row of buttons before the marked element - * - * @param anchor element before which the row of buttons will be inserted - * @param array array of data for buttons to be generated + var refs = this.dok.getElementById("external_bugs_table") + .getElementsByTagName("tr"); + // that's a bad id, if there is a one. :) + var inputBox = this.dok.getElementById("inputbox"); + var externalBugID = 0; + var wholeURL = ""; + + // Fix missing ID on the external_id SELECT + this.dok.getElementsByName("external_id")[0].setAttribute("id", + "external_id"); + + if (inputBox.value.match(/^http.*/)) { + var helpAElem = this.dok.createElement("a"); + wholeURL = inputBox.value; + helpAElem.setAttribute("href", wholeURL); + var paramsArr = helpAElem.search.replace(/^\?/, '').split('&'); + // get ID# + var params = {}, s = []; + paramsArr.forEach(function(par, idx, arr) { + s = par.split('='); + params[s[0]] = s[1]; + }); + if (params.id) { + externalBugID = parseInt(params.id, 10); + inputBox.value = externalBugID; + } + // get host and bugzillaName + var bugzillaName = this.getBugzillaName(helpAElem.hostname); + this.selectOption("external_id", bugzillaName); + } else if (!isNaN(inputBox.value)) { + externalBugID = parseInt(inputBox.value, 10); + var bugzillaID = this.dok.getElementById("external_id").value; + wholeURL = this.getWholeURL(bugzillaID, externalBugID); + } else { + // no inputBox.value -- maybe there is an external bug from + // the previous commit? + } + + // It is not good to close bug as UPSTREAM, if there is no reference + // to the upstream bug. + if ((externalBugID > 0) || (refs.length > 2)) { + this.addTextToTextBox("comment", msgStrs.sentUpstreamString.replace( + "§§§", wholeURL)); + this.selectOption("bug_status", "CLOSED"); + this.selectOption("resolution", "UPSTREAM"); + } else { + console.log("No external bug specified among the External References!"); + } +}; + +/** + * Insert a row of buttons before the marked element + * + * @param anchor + * element before which the row of buttons will be inserted + * @param array + * array of data for buttons to be generated * @return none */ -BzPage.prototype.generateToolBar = function(anchor,array) { - for (var i=0; i<array.length; i++) { - var butt = array[i]; - this.addNewButton(anchor, butt.idx, - butt.msg, butt.string, butt.state, butt.parameter, - butt.submit); - } +BzPage.prototype.generateToolBar = function(anchor, array) { + for ( var i = 0; i < array.length; i++) { + var butt = array[i]; + this.addNewButton(anchor, butt.idx, butt.msg, butt.string, butt.state, + butt.parameter, butt.submit); + } }; /** * Generalized function for all actions - * - * @param addString string to be added as new comment - * @param nextState string signifying next state of the bug - * (whatever is in Bugzilla + "NEEDINFO" meaning - * NEEDINFO(Reporter)) - * @param secondParameter string with label on the subbutton - * for reason of closing the bug + * + * @param addString + * string to be added as new comment + * @param nextState + * string signifying next state of the bug (whatever is in Bugzilla + + * "NEEDINFO" meaning NEEDINFO(Reporter)) + * @param secondParameter + * string with label on the subbutton for reason of closing the bug * @return none */ -BzPage.prototype.generalPurposeCureForAllDisease = function - (addString,nextState,secondParameter) { - var verNo = this.getVersion(); - - if (addString.length >0) { - this.addTextToTextBox("comment",addString); - } - - if (nextState === "CLOSED") { - if (secondParameter === "UPSTREAM") { - this.addClosingUpstream(); - } else if (secondParameter === "SOMERELEASE") { - // for RAWHIDE close as RAWHIDE, - // if active selection -> CURRENTRELEASE - // and put the release version to - // "Fixed in Version" textbox - // otherwise -> NEXTRELEASE - this.selectOption("bug_status", nextState); - var text = ""; - if (jetpack.selection.text) { - text = jetpack.select.text.trim(); - } - if (text.length > 0) { - this.selectOption("resolution","CURRENTRELEASE"); - this.dok.getElementById("cf_fixed_in").value = text; - } else if (verNo === 999) { - this.selectOption("resolution","RAWHIDE"); - } else { - this.selectOption("resolution","NEXTRELEASE"); - } - } else if (secondParameter.length > 0) { - this.selectOption("bug_status", nextState); - this.selectOption("resolution",secondParameter); - return 0; - } else { - throw "Missing resolution for CLOSED status."; - } - } - - // Now closing bugs is done, what about the rest? - if (nextState === "NEEDINFO") { - this.setNeedinfoReporter(); - } else if (nextState === "ADDKEYWORD") { - if (secondParameter.length === 0) { - throw "Keyword has to be defined"; - } - this.addKeyword(secondParameter); - } else if (nextState === "ASSIGNED") { - // Now we lie completely, we just set keyword Triaged, - // this is not just plain ASSIGNED, but - // modified according to - // https://fedoraproject.org/wiki/BugZappers/Meetings/Minutes-2009-Oct-27 - // and - // http://meetbot.fedoraproject.org/fedora-meeting/2009-11-24\ - // /fedora-meeting.2009-11-24-15.11.log.html - // and - // http://meetbot.fedoraproject.org/fedora-meeting/2009-11-24\ - // /fedora-meeting.2009-11-24-15.11.log.html - // for F13 and later, ASSIGNED is "add Triaged keyword" (as well) - // for <F13 it is "add both" (ASSIGNED status and Triaged keyword) - if (!isInList(this.maintCCAddr, this.CCList)) { - this.dok.getElementById("newcc").textContent = this.maintCCAddr; - } - if ((!this.isRHEL()) && (verNo < TriagedDistro)) { - this.selectOption("bug_status", nextState); - } - this.setKeyword("Triaged"); - } else if (nextState === "QUERYSEL") { - this.queryForSelection(); - } else if (nextState === "SENDUPSTREAM") { - this.sendBugUpstream(); - } else if (nextState === "SETDEFASS") { - if (secondParameter.length > 0) { - this.changeOwner(secondParameter); - } - } else if (nextState === "CHIPMAGIC") { - var splitArr = secondParameter.split("\t"); - this.fillInWhiteBoard(splitArr[0],splitArr[1]); - } else if (nextState.length >0) { - this.selectOption("bug_status", nextState); - } - - if (secondParameter === "ADDSELFCC") { - this.dok.getElementById("addselfcc").checked = true; - } else if (secondParameter === "NODEFAULTASSIGNEE") { - this.dok.getElementById("set_default_assignee"). - removeAttribute("checked"); - } +BzPage.prototype.generalPurposeCureForAllDisease = function(addString, + nextState, secondParameter) { + var verNo = this.getVersion(); + + if (addString.length > 0) { + this.addTextToTextBox("comment", addString); + } + + if (nextState === "CLOSED") { + if (secondParameter === "UPSTREAM") { + this.addClosingUpstream(); + } else if (secondParameter === "SOMERELEASE") { + // for RAWHIDE close as RAWHIDE, + // if active selection -> CURRENTRELEASE + // and put the release version to + // "Fixed in Version" textbox + // otherwise -> NEXTRELEASE + this.selectOption("bug_status", nextState); + var text = ""; + if (jetpack.selection.text) { + text = jetpack.select.text.trim(); + } + if (text.length > 0) { + this.selectOption("resolution", "CURRENTRELEASE"); + this.dok.getElementById("cf_fixed_in").value = text; + } else if (verNo === 999) { + this.selectOption("resolution", "RAWHIDE"); + } else { + this.selectOption("resolution", "NEXTRELEASE"); + } + } else if (secondParameter.length > 0) { + this.selectOption("bug_status", nextState); + this.selectOption("resolution", secondParameter); + return 0; + } else { + throw "Missing resolution for CLOSED status."; + } + } + + // Now closing bugs is done, what about the rest? + if (nextState === "NEEDINFO") { + this.setNeedinfoReporter(); + } else if (nextState === "ADDKEYWORD") { + if (secondParameter.length === 0) { + throw "Keyword has to be defined"; + } + this.addKeyword(secondParameter); + } else if (nextState === "ASSIGNED") { + // Now we lie completely, we just set keyword Triaged, + // this is not just plain ASSIGNED, but + // modified according to + // https://fedoraproject.org/wiki/BugZappers/Meetings/Minutes-2009-Oct-27 + // and + // http://meetbot.fedoraproject.org/fedora-meeting/2009-11-24\ + // /fedora-meeting.2009-11-24-15.11.log.html + // and + // http://meetbot.fedoraproject.org/fedora-meeting/2009-11-24\ + // /fedora-meeting.2009-11-24-15.11.log.html + // for F13 and later, ASSIGNED is "add Triaged keyword" (as well) + // for <F13 it is "add both" (ASSIGNED status and Triaged keyword) + if (!isInList(this.maintCCAddr, this.CCList)) { + this.dok.getElementById("newcc").textContent = this.maintCCAddr; + } + if ((!this.isRHEL()) && (verNo < TriagedDistro)) { + this.selectOption("bug_status", nextState); + } + this.setKeyword("Triaged"); + } else if (nextState === "QUERYSEL") { + this.queryForSelection(); + } else if (nextState === "SENDUPSTREAM") { + this.sendBugUpstream(); + } else if (nextState === "SETDEFASS") { + if (secondParameter.length > 0) { + this.changeOwner(secondParameter); + } + } else if (nextState === "CHIPMAGIC") { + var splitArr = secondParameter.split("\t"); + this.fillInWhiteBoard(splitArr[0], splitArr[1]); + } else if (nextState.length > 0) { + this.selectOption("bug_status", nextState); + } + + if (secondParameter === "ADDSELFCC") { + this.dok.getElementById("addselfcc").checked = true; + } else if (secondParameter === "NODEFAULTASSIGNEE") { + this.dok.getElementById("set_default_assignee").removeAttribute( + "checked"); + } }; /** - * + * */ -BzPage.prototype.parseBacktrace = function (ret) { - var splitArray = ret.split("\n"); - var i = 0, ii = splitArray.length; - var outStr = "", curLine = "", numStr = ""; - var lineCounter = 0, endLineNo = 0; - - while ( i < ii ) { - if (signalHandlerRE.test(splitArray[i])) { - break; - } - i++; - } - - if (i < ii) { - lineCounter = parseInt(frameNoRE.exec(splitArray[i])[1],10); - endLineNo = lineCounter + NumberOfFrames; - curLine = splitArray[i]; - while ((lineCounter < endLineNo) && - (curLine.trim().length >0) && (i < ii)) { - outStr += curLine + '\n'; - numStr = frameNoRE.exec(curLine); - if (numStr) { - lineCounter = parseInt(numStr[1],10); - } - i++; - curLine = splitArray[i]; - } - } - return outStr; -} +BzPage.prototype.parseBacktrace = function(ret) { + var splitArray = ret.split("\n"); + var i = 0, ii = splitArray.length; + var outStr = "", curLine = "", numStr = ""; + var lineCounter = 0, endLineNo = 0; + + while (i < ii) { + if (signalHandlerRE.test(splitArray[i])) { + break; + } + i++; + } + + if (i < ii) { + lineCounter = parseInt(frameNoRE.exec(splitArray[i])[1], 10); + endLineNo = lineCounter + NumberOfFrames; + curLine = splitArray[i]; + while ((lineCounter < endLineNo) && (curLine.trim().length > 0) + && (i < ii)) { + outStr += curLine + '\n'; + numStr = frameNoRE.exec(curLine); + if (numStr) { + lineCounter = parseInt(numStr[1], 10); + } + i++; + curLine = splitArray[i]; + } + } + return outStr; +}; /** * Main executable functioning actually building all buttons on the page -- - * separated into function, so that - * it could be called from onload method of the XMLHttpRequest. - * - * @param jsonList Array created from JSON + * separated into function, so that it could be called from onload method of the + * XMLHttpRequest. + * + * @param jsonList + * Array created from JSON * @return none */ -BzPage.prototype.buildButtons = function (above,below) { - //Generate a list of <input> elements in the page - this.addNewButton(this.dok.getElementById("commit_middle"), - "changeOwnerbtn","Mark Triaged","","ASSIGNED","NODEFAULTASSIGNEE"); - - // THE MAIN BUTTON ROWS - var commentBox = this.dok.getElementById("comment"); - var brElement = this.dok.createElement("br"); - commentBox.parentNode.normalize(); - commentBox.parentNode.insertBefore(brElement,commentBox); -// this.generateToolBar(commentBox.previousSibling,above); - this.generateToolBar(brElement,above); - this.generateToolBar(this.originalButton,below); - - var commentArea = this.dok.getElementById("comment_status_commit"); - var brElementPlacer = commentArea.getElementsByTagName("br")[0]; - - if (queryButtonAvailable || upstreamButtonAvailable) { - brElementPlacer.parentNode.insertBefore(this.dok.createElement("br"), - brElementPlacer); - } - - if (queryButtonAvailable) { - // Add query search button - this.addNewButton(brElementPlacer,"newqueryintab", - "Query for string","","QUERYSEL","", false); - } - // Button for upstreaming - if (upstreamButtonAvailable) { - this.addNewButton(brElementPlacer,"sendupstream", - "Send upstream","","SENDUPSTREAM","", false); - } - -// var brElement2BMoved = this.dok.querySelector("#comment_status_commit br:last-of-type"); -// var brWhereMove = this.dok.getElementsByClassName("status")[0]; -// brWhereMove.parentNode.insertBefore(brElement2BMoved.cloneNode(true), -// brWhereMove); -// brElement2BMoved.parentNode.removeChild(brElement2BMoved); - - // TODO Get compiz bugs as well - if ((chipIDsGroupings.length >0) && - this.maintCCAddr === "xgl-maint@redhat.com") { - // Add find chip magic button - var whiteboard_string = this.dok.getElementById("status_whiteboard").value; - if (!/card_/.test(whiteboard_string)) { - this.fillInChipMagic(); - } - } - - // Add setting default assignee - if ((this.defaultAssignee.length > 0) && - (this.defaultAssignee !== this.owner)) { - this.addNewButton(this.dok.getElementById("bz_assignee_edit_container"), - "setdefaultassigneebutton","Def. Assignee", - "","SETDEFASS",this.defaultAssignee,false,true); - } -}; - -BzPage.prototype.addLogRecord = function () { - var rec = {}; - rec.date = new Date(); - rec.bugId = this.bugNo; - rec.title = this.title; - var comment = jetpack.tabs.focused.contentWindow. - prompt("Enter comments for this comment").trim(); - if (comment.length > 0) { - rec.comment = comment; - var recKey = getISODate(rec.date)+"+"+rec.bugId; - var clearLogAElem = this.dok.getElementById("clearLogs"); - clearLogAElem.style.color = FullLogsColor; - clearLogAElem.style.fontWeight = "bolder"; - if (myStorage.logs[recKey]) { - myStorage.logs[recKey].comment += "<br/>\n"+comment; - } else { - myStorage.logs[recKey] = rec; - } - jetpack.storage.simple.sync(); - } else if (comment === null) { - return null; - } -}; - -BzPage.prototype.timeSheetRecordsPrinter = function (body,records) { - // sort the records into temporary array - var tmpArr = []; - - for (var i in records){ - if (records.hasOwnProperty(i)) { - tmpArr.push([i,records[i]]); - } - } - tmpArr.sort(function(a,b){ return a[0]>b[0]?1:-1; }); - - var currentDay = ""; - // now print the array - tmpArr.forEach(function (rec) { - var x = rec[1]; - var dayStr = getISODate(x.date); - if (dayStr != currentDay) { - currentDay = dayStr; - body.innerHTML += "<hr/><p><strong>" + currentDay + - "</strong></p>"; - } - body.innerHTML += "<p><em><a href='https://bugzilla.redhat.com/show_bug.cgi?id="+ - x.bugId + "'>Bug "+x.title+"</a>"+ - " </em>\n<br/>" + x.comment + "</p>"; - }); -}; - -BzPage.prototype.generateTimeSheet = function (body) { - var doc = body.ownerDocument; - this.timeSheetRecordsPrinter(body,myStorage.logs); -}; - -/////////////////////////////////////////////////////////////////////////////// +BzPage.prototype.buildButtons = function(above, below) { + // Generate a list of <input> elements in the page + this.addNewButton(this.dok.getElementById("commit_middle"), + "changeOwnerbtn", "Mark Triaged", "", "ASSIGNED", + "NODEFAULTASSIGNEE"); + + // THE MAIN BUTTON ROWS + var commentBox = this.dok.getElementById("comment"); + var brElement = this.dok.createElement("br"); + commentBox.parentNode.normalize(); + commentBox.parentNode.insertBefore(brElement, commentBox); + // this.generateToolBar(commentBox.previousSibling,above); + this.generateToolBar(brElement, above); + this.generateToolBar(this.originalButton, below); + + var commentArea = this.dok.getElementById("comment_status_commit"); + var brElementPlacer = commentArea.getElementsByTagName("br")[0]; + + if (queryButtonAvailable || upstreamButtonAvailable) { + brElementPlacer.parentNode.insertBefore(this.dok.createElement("br"), + brElementPlacer); + } + + if (queryButtonAvailable) { + // Add query search button + this.addNewButton(brElementPlacer, "newqueryintab", "Query for string", + "", "QUERYSEL", "", false); + } + // Button for upstreaming + if (upstreamButtonAvailable) { + this.addNewButton(brElementPlacer, "sendupstream", "Send upstream", "", + "SENDUPSTREAM", "", false); + } + + // var brElement2BMoved = this.dok.querySelector("#comment_status_commit + // br:last-of-type"); + // var brWhereMove = this.dok.getElementsByClassName("status")[0]; + // brWhereMove.parentNode.insertBefore(brElement2BMoved.cloneNode(true), + // brWhereMove); + // brElement2BMoved.parentNode.removeChild(brElement2BMoved); + + // TODO Get compiz bugs as well + if ((chipIDsGroupings.length > 0) + && this.maintCCAddr === "xgl-maint@redhat.com") { + // Add find chip magic button + var whiteboard_string = this.dok.getElementById("status_whiteboard").value; + if (!/card_/.test(whiteboard_string)) { + this.fillInChipMagic(); + } + } + + // Add setting default assignee + if ((this.defaultAssignee.length > 0) + && (this.defaultAssignee !== this.owner)) { + this.addNewButton( + this.dok.getElementById("bz_assignee_edit_container"), + "setdefaultassigneebutton", "Def. Assignee", "", "SETDEFASS", + this.defaultAssignee, false, true); + } +}; + +BzPage.prototype.addLogRecord = function() { + var rec = {}; + rec.date = new Date(); + rec.bugId = this.bugNo; + rec.title = this.title; + var comment = jetpack.tabs.focused.contentWindow.prompt( + "Enter comments for this comment").trim(); + if (comment.length > 0) { + rec.comment = comment; + var recKey = getISODate(rec.date) + "+" + rec.bugId; + var clearLogAElem = this.dok.getElementById("clearLogs"); + clearLogAElem.style.color = FullLogsColor; + clearLogAElem.style.fontWeight = "bolder"; + if (myStorage.logs[recKey]) { + myStorage.logs[recKey].comment += "<br/>\n" + comment; + } else { + myStorage.logs[recKey] = rec; + } + jetpack.storage.simple.sync(); + } else if (comment === null) { + return null; + } +}; + +BzPage.prototype.timeSheetRecordsPrinter = function(body, records) { + // sort the records into temporary array + var tmpArr = []; + + for ( var i in records) { + if (records.hasOwnProperty(i)) { + tmpArr.push( [ i, records[i] ]); + } + } + tmpArr.sort(function(a, b) { + return a[0] > b[0] ? 1 : -1; + }); + + var currentDay = ""; + // now print the array + tmpArr + .forEach(function(rec) { + var x = rec[1]; + var dayStr = getISODate(x.date); + if (dayStr != currentDay) { + currentDay = dayStr; + body.innerHTML += "<hr/><p><strong>" + currentDay + + "</strong></p>"; + } + body.innerHTML += "<p><em><a href='https://bugzilla.redhat.com/show_bug.cgi?id=" + + x.bugId + + "'>Bug " + + x.title + + "</a>" + + " </em>\n<br/>" + x.comment + "</p>"; + }); +}; + +BzPage.prototype.generateTimeSheet = function(body) { + var doc = body.ownerDocument; + this.timeSheetRecordsPrinter(body, myStorage.logs); +}; + +// ///////////////////////////////////////////////////////////////////////////// function BzPage(doc) { - this.dok = doc; - var that = this; - this.originalButton = this.dok.getElementById("commit"); - - var loginArr = this.dok. - querySelector("#header ul.links li:last-of-type"). - textContent.split("\n"); - this.login = loginArr[loginArr.length-1].trim(); - - if (myStorage.BZpassword) { - this.password = myStorage.BZpassword; - } else { - var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] - .getService(Components.interfaces.nsIPromptService); - var password = {value: ""}; // default the password to pass - var check = {value: true}; // default the checkbox to true - var result = prompts.promptPassword(null, - "Title", "Enter password:", password, null, check); - // result is true if OK was pressed, false if cancel was pressed. password.value is - // set if OK was pressed. The checkbox is not displayed. - if (result) { - this.password = password.value; - myStorage.BZpassword = this.password; - jetpack.storage.simple.sync(); - } - } - - var bugNoTitle = this.dok.querySelector("#title > p").textContent.trim(); - this.bugNo = new RegExp("[0-9]+").exec(bugNoTitle)[0]; - - this.reporter = this.getReporter(); - this.product = this.getOptionValue("product"); - this.component = this.getOptionValue("component"); - this.version = this.getVersion(); - this.title = this.dok.getElementById("short_desc_nonedit_display"). - textContent; - var ITbutton = this.dok.getElementById("cf_issuetracker"); - this.its = ITbutton ? ITbutton.value.trim() : ""; - this.CCList = Array.map(this.dok.getElementById("cc"), - function (item) { return item.value; } - ); - // TODO be careful about this, seems breaking for non-RH BugZappers, - // but I cannot see why - this.owner = this.dok.getElementById("bz_assignee_edit_container"). - getElementsByClassName("fn")[0].textContent; - this.defaultAssignee = filterByRegexp(defAssigneeList, - this.component).toLowerCase(); - this.maintCCAddr = filterByRegexp(AddrArray,this.component).toLowerCase(); - - this.XorgLogAttList = []; - this.XorgLogAttListIndex = 0; - this.attachments = []; - this.reqCounter=0; - var atts = this.dok.getElementById("attachment_table"). - getElementsByTagName("tr"); - for (var i = 1, ii = atts.length-1; i < ii; i++) { - this.attachments.push(this.parseAttachmentLine(atts[i])); - } - - var badAttachments = this.attachments.filter(function (att,idx,arr) { - return (isInList(att[2],badMIMEArray)); - }); - - if (badAttachments.length > 0) { - var titleElement = this.dok. - getElementsByClassName("bz_alias_short_desc_container")[0]; - titleElement.style.backgroundColor = "olive"; - titleElement.appendChild(this.createFixAllButton(badAttachments)); - badAttachments.forEach(function (x,i,a) { - this.addTextLink(x); - },this); - } - - // Dig out backtrace - this.btSnippet = ""; - - if (AbrtRE.test(this.title)) { - - var notedLabel = this.dok.querySelector("label[for='newcc']"); - while (notedLabel.firstChild) { - var node = notedLabel.removeChild(notedLabel.firstChild); - notedLabel.parentNode.insertBefore(node,notedLabel); - } - notedLabel.parentNode.removeChild(notedLabel); - - var mainTitle = this.dok. - getElementsByClassName("bz_alias_short_desc_container")[0]; - var abrtButton = this.dok.createElement("a"); - abrtButton.setAttribute("accesskey","a"); - abrtButton.setAttribute("href",abrtQueryURL); - abrtButton.textContent = "Abrt bugs"; - mainTitle.appendChild(abrtButton); - // FIXME trac# 29 ... possibility of switching to ID lob_newqueryname ??? - var develWhiteboardElem = this.dok.getElementById("cf_devel_whiteboard"); - // This is just a security for bug pages without cf_devel_whiteboard element - var develWhiteboard = develWhiteboardElem ? develWhiteboardElem. - value : "btparsed"; - - if (!(this.hasKeyword("Triaged") || (/btparsed/.test(develWhiteboard)))) { - var btAttachments = this.attachments.filter(function (att,idx,arr) { - return (/backtrace/.test(att[0])); - }); - // TODO we need to go through all backtrace attachments, but - // just the first one will do for now, we would need to do async parsing - btAttachments.forEach(function (x) { - attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" + x[1]; - console.log("attURL = " + attURL); - console.log("btSnippet = " + this.btSnippet); - if (!this.btSnippet) { - var btRaw = loadText(attURL,function (ret) { - this.btSnippet = this.parseBacktrace(ret); - if (this.btSnippet) { - this.addTextToTextBox("comment",this.btSnippet); - this.addTextToTextBox("cf_devel_whiteboard","btparsed"); - } - },this); - } - },this); - } - } - - // Take care of signature for Fedora bugzappers - if (signatureFedoraString.length > 0) { - this.dok.forms.namedItem("changeform").addEventListener("submit", - function () { - that.addTextToTextBox("comment", signatureFedoraString); - } - , false); - } - - this.setBranding(); - this.checkComments(); - this.buildButtons(topRow,bottomRow); - - // UI for the customization JSON URL - var additionalButtons = this.dok.getElementById("bugzilla-body"). - getElementsByClassName("related_actions")[0]; - var customJSONURLUI = this.dok.createElement("li"); - customJSONURLUI.innerHTML = "\u00A0-\u00A0<a href='#' id='customJSONbutton'>" + - "BugZap config</a>"; - additionalButtons.appendChild(customJSONURLUI); - this.dok.getElementById("customJSONbutton"). - addEventListener("click",function () { - var newURL = jetpack.tabs.focused.contentWindow. - prompt("URL for your JSON customization file"); - if (newURL) { - myStorage.JSONURL = newURL; - jetpack.storage.simple.sync(); - jetpack.tabs.focused.contentWindow.location.reload(); - } - }, false); - - // set default assignee on change of the component - this.dok.getElementById("component").addEventListener("change", - function (){ - that.component = that.getOptionValue("component"); - that.changeOwner(filterByRegexp(defAssigneeList, that.component). - toLowerCase()); - }, false); - - // offline-capable submit - this.dok.forms.namedItem("changeform"). - addEventListener('submit', function (evt) { - that.submitCallback.call(that, evt);}, - false); - - // logging all submits for timesheet - console.log("logSubmits = " + logSubmits); - if (logSubmits) { - this.dok.forms.namedItem("changeform").addEventListener("submit", - function (evt) { - if (that.addLogRecord() === null) { - // FIXME doesn't work ... still submitting' - evt.stopPropagation(); - evt.preventDefault(); - } - } - ,false); - - var generateTimeSheetUI = this.dok.createElement("li"); - generateTimeSheetUI.innerHTML = - "\u00A0-\u00A0<a href='#' id='generateTSButton'>" + - "Generate timesheet</a>"; - additionalButtons.appendChild(generateTimeSheetUI); - this.dok.getElementById("generateTSButton"). - addEventListener("click",function (evt) { - createBlankPage.call(that,"TimeSheet",that.generateTimeSheet); - evt.stopPropagation(); - evt.preventDefault(); - }, false); - - var clearLogsUI = this.dok.createElement("li"); - clearLogsUI.innerHTML = - "\u00A0-\u00A0<a href='#' id='clearLogs'>" + - "Clear logs</a>"; - additionalButtons.appendChild(clearLogsUI); - var clearLogAElem = this.dok.getElementById("clearLogs"); - clearLogAElem.addEventListener("click", - function () { - myStorage.logs = {}; - jetpack.storage.simple.sync(); - this.style.color = EmptyLogsColor; - clearLogAElem.style.fontWeight = "normal"; - console.log("mystorage.logs wiped out!"); - }, false); - - if (!myStorage.logs) { - console.log("No myStorage.logs defined!"); - myStorage.logs = {}; - } - - if (myStorage.logs) { - clearLogAElem.style.color = FullLogsColor; - clearLogAElem.style.fontWeight = "bolder"; - } else { - clearLogAElem.style.color = EmptyLogsColor; - clearLogAElem.style.fontWeight = "normal"; - } - } + this.dok = doc; + var that = this; + this.originalButton = this.dok.getElementById("commit"); + + var loginArr = this.dok.querySelector("#header ul.links li:last-of-type").textContent + .split("\n"); + this.login = loginArr[loginArr.length - 1].trim(); + + if (myStorage.BZpassword) { + this.password = myStorage.BZpassword; + } else { + var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + var password = { + value : "" + }; // default the password to pass + var check = { + value : true + }; // default the checkbox to true + var result = prompts.promptPassword(null, "Title", "Enter password:", + password, null, check); + // result is true if OK was pressed, false if cancel was pressed. + // password.value is + // set if OK was pressed. The checkbox is not displayed. + if (result) { + this.password = password.value; + myStorage.BZpassword = this.password; + jetpack.storage.simple.sync(); + } + } + + var bugNoTitle = this.dok.querySelector("#title > p").textContent.trim(); + this.bugNo = new RegExp("[0-9]+").exec(bugNoTitle)[0]; + + this.reporter = this.getReporter(); + this.product = this.getOptionValue("product"); + this.component = this.getOptionValue("component"); + this.version = this.getVersion(); + this.title = this.dok.getElementById("short_desc_nonedit_display").textContent; + var ITbutton = this.dok.getElementById("cf_issuetracker"); + this.its = ITbutton ? ITbutton.value.trim() : ""; + this.CCList = Array.map(this.dok.getElementById("cc"), function(item) { + return item.value; + }); + // TODO be careful about this, seems breaking for non-RH BugZappers, + // but I cannot see why + this.owner = this.dok.getElementById("bz_assignee_edit_container") + .getElementsByClassName("fn")[0].textContent; + this.defaultAssignee = filterByRegexp(defAssigneeList, this.component) + .toLowerCase(); + this.maintCCAddr = filterByRegexp(AddrArray, this.component).toLowerCase(); + + this.XorgLogAttList = []; + this.XorgLogAttListIndex = 0; + this.attachments = []; + this.reqCounter = 0; + var atts = this.dok.getElementById("attachment_table") + .getElementsByTagName("tr"); + for ( var i = 1, ii = atts.length - 1; i < ii; i++) { + this.attachments.push(this.parseAttachmentLine(atts[i])); + } + + var badAttachments = this.attachments.filter(function(att, idx, arr) { + return (isInList(att[2], badMIMEArray)); + }); + + if (badAttachments.length > 0) { + var titleElement = this.dok + .getElementsByClassName("bz_alias_short_desc_container")[0]; + titleElement.style.backgroundColor = "olive"; + titleElement.appendChild(this.createFixAllButton(badAttachments)); + badAttachments.forEach(function(x, i, a) { + this.addTextLink(x); + }, this); + } + + // Dig out backtrace + this.btSnippet = ""; + + if (AbrtRE.test(this.title)) { + + var notedLabel = this.dok.querySelector("label[for='newcc']"); + while (notedLabel.firstChild) { + var node = notedLabel.removeChild(notedLabel.firstChild); + notedLabel.parentNode.insertBefore(node, notedLabel); + } + notedLabel.parentNode.removeChild(notedLabel); + + var mainTitle = this.dok + .getElementsByClassName("bz_alias_short_desc_container")[0]; + var abrtButton = this.dok.createElement("a"); + abrtButton.setAttribute("accesskey", "a"); + abrtButton.setAttribute("href", abrtQueryURL); + abrtButton.textContent = "Abrt bugs"; + mainTitle.appendChild(abrtButton); + + if (this.idContainsWord("cf_devel_whiteboard", 'btparsed')) { + this.addTextToTextBox('status_whiteboard', 'btparsed'); + } + + if (!(this.isTriaged() || this.idContainsWord("status_whiteboard", + 'btparsed'))) { + var btAttachments = this.attachments + .filter(function(att, idx, arr) { + return (/backtrace/.test(att[0])); + }); + // TODO we need to go through all backtrace attachments, but + // just the first one will do for now, we would need to do async + // parsing + btAttachments.forEach(function(x) { + attURL = "https://bugzilla.redhat.com/attachment.cgi?id=" + + x[1]; + console.log("attURL = " + attURL); + console.log("btSnippet = " + this.btSnippet); + if (!this.btSnippet) { + var btRaw = loadText(attURL, function(ret) { + this.btSnippet = this.parseBacktrace(ret); + if (this.btSnippet) { + this.addTextToTextBox("comment", this.btSnippet); + this.addTextToTextBox("status_whiteboard", + "btparsed"); + } + }, this); + } + }, this); + } + } + + // Take care of signature for Fedora bugzappers + if (signatureFedoraString.length > 0) { + this.dok.forms.namedItem("changeform").addEventListener("submit", + function() { + that.addTextToTextBox("comment", signatureFedoraString); + }, false); + } + + this.setBranding(); + this.checkComments(); + this.buildButtons(topRow, bottomRow); + + // UI for the customization JSON URL + var additionalButtons = this.dok.getElementById("bugzilla-body") + .getElementsByClassName("related_actions")[0]; + var customJSONURLUI = this.dok.createElement("li"); + customJSONURLUI.innerHTML = "\u00A0-\u00A0<a href='#' id='customJSONbutton'>" + + "BugZap config</a>"; + additionalButtons.appendChild(customJSONURLUI); + this.dok.getElementById("customJSONbutton").addEventListener( + "click", + function() { + var newURL = jetpack.tabs.focused.contentWindow + .prompt("URL for your JSON customization file"); + if (newURL) { + myStorage.JSONURL = newURL; + jetpack.storage.simple.sync(); + jetpack.tabs.focused.contentWindow.location.reload(); + } + }, false); + + // set default assignee on change of the component + this.dok.getElementById("component").addEventListener( + "change", + function() { + that.component = that.getOptionValue("component"); + that + .changeOwner(filterByRegexp(defAssigneeList, + that.component).toLowerCase()); + }, false); + + // offline-capable submit + this.dok.forms.namedItem("changeform").addEventListener('submit', + function(evt) { + that.submitCallback.call(that, evt); + }, false); + + // logging all submits for timesheet + console.log("logSubmits = " + logSubmits); + if (logSubmits) { + this.dok.forms.namedItem("changeform").addEventListener("submit", + function(evt) { + if (that.addLogRecord() === null) { + // FIXME doesn't work ... still submitting' + evt.stopPropagation(); + evt.preventDefault(); + } + }, false); + + var generateTimeSheetUI = this.dok.createElement("li"); + generateTimeSheetUI.innerHTML = "\u00A0-\u00A0<a href='#' id='generateTSButton'>" + + "Generate timesheet</a>"; + additionalButtons.appendChild(generateTimeSheetUI); + this.dok.getElementById("generateTSButton").addEventListener( + "click", + function(evt) { + createBlankPage.call(that, "TimeSheet", + that.generateTimeSheet); + evt.stopPropagation(); + evt.preventDefault(); + }, false); + + var clearLogsUI = this.dok.createElement("li"); + clearLogsUI.innerHTML = "\u00A0-\u00A0<a href='#' id='clearLogs'>" + + "Clear logs</a>"; + additionalButtons.appendChild(clearLogsUI); + var clearLogAElem = this.dok.getElementById("clearLogs"); + clearLogAElem.addEventListener("click", function() { + myStorage.logs = {}; + jetpack.storage.simple.sync(); + this.style.color = EmptyLogsColor; + clearLogAElem.style.fontWeight = "normal"; + console.log("mystorage.logs wiped out!"); + }, false); + + if (!myStorage.logs) { + console.log("No myStorage.logs defined!"); + myStorage.logs = {}; + } + + if (myStorage.logs) { + clearLogAElem.style.color = FullLogsColor; + clearLogAElem.style.fontWeight = "bolder"; + } else { + clearLogAElem.style.color = EmptyLogsColor; + clearLogAElem.style.fontWeight = "normal"; + } + } } -var callback = function (doc) { - var curPage = new BzPage(doc); +var callback = function(doc) { + var curPage = new BzPage(doc); }; var options = {}; -options.matches = [ - "https://bugzilla.redhat.com/show_bug.cgi" -]; +options.matches = [ "https://bugzilla.redhat.com/show_bug.cgi" ]; jetpack.pageMods.add(callback, options); |