diff options
author | lpsolit%gmail.com <> | 2005-08-22 03:16:40 +0200 |
---|---|---|
committer | lpsolit%gmail.com <> | 2005-08-22 03:16:40 +0200 |
commit | f4966aeb0e7a655c986aeb285c1a220274ddbfd9 (patch) | |
tree | 70fc81865b58b54e97da10c8cc824ae9fb641672 /quicksearch.js | |
parent | d055246d2010e546bbad8c65d99496d53eee0bff (diff) | |
download | bugzilla-f4966aeb0e7a655c986aeb285c1a220274ddbfd9.tar.gz bugzilla-f4966aeb0e7a655c986aeb285c1a220274ddbfd9.tar.xz |
Bug 70907: QuickSearch: port the JS code to perl (make it server-side) - Patch by Marc Schumann <wurblzap@gmail.com> r=wicked a=myk
Diffstat (limited to 'quicksearch.js')
-rw-r--r-- | quicksearch.js | 740 |
1 files changed, 0 insertions, 740 deletions
diff --git a/quicksearch.js b/quicksearch.js deleted file mode 100644 index 29ab6eb6b..000000000 --- a/quicksearch.js +++ /dev/null @@ -1,740 +0,0 @@ -// -// This is the main JS file for QuickSearch. -// -// Derived from: -// -// * C. Begle's SimpleSearch tool: -// http://www.mozilla.org/quality/help/simplesearch.html -// http://www.mozilla.org/quality/help/bugreport.js -// -// * Jesse Ruderman's bugzilla search page: -// http://www.cs.hmc.edu/~jruderma/s/bugz.html -// -// Created by -// Andreas Franke <afranke@mathweb.org> -// -// Contributors: -// Stephen Lee <slee@uk.bnsmc.com> - - -// Use no_result variable to avoid problems with "undefined" on some browsers - -var no_result="---"; - -// do_unshift(l, s) is equivalent to l.unshift(s), but some browsers do not -// support the built-in function. - -function do_unshift(l, s) { - l.length = l.length + 1; - for (var i=l.length-1; i>0; i--) { - l[i] = l[i-1]; - } - l[0] = s; - return l.length; -} - -// do_shift(l) is equivalent to l.shift(s), but some browsers do not -// support the built-in function. - -function do_shift(l) { - var l0=l[0]; - for (var i=0; i<l.length-1; i++) { - l[i] = l[i+1]; - } - l.length = l.length - 1; - return l0; -} - -function go_to (url) { - // XXX specifying "sidebar" here indicates you want to use a - // function to do the actual loading instead of using the specified - // url directly. bug 236025 covers clarifying this. Pages that specify - // sidebar=1 *must* specify a load_absolute_url function meanwhile. - if ( typeof sidebar != "undefined" && sidebar == 1 ) { - load_absolute_url(url); - } else { - document.location.href = url; - } -} - -function map(l, f) { - var l1 = new Array(); - for (var i=0; i<l.length; i++) { - l1[i] = f(l[i]); - } - return l1; -} - -function isPrefix(s1, s2) { - return (s1.length <= s2.length) && - (s1 == s2.substring(0,s1.length)) -} - -function member(s, l) { - for (var i=0; i<l.length; i++) { - if (l[i] == s) return true; - } - return false; -} - -function add(s, l) { - if (! member(s, l)) { - do_unshift(l,s); - } -} - -function addAll(l1, l2) { - for (var i=0; i<l1.length; i++) { - add(l1[i],l2); - } -} - -function isSubset (l1, l2) { - return (l1.length == 0) - || (member(l1[0],l2) && subset(l1.slice(1),l2)); -} - -// fields - -var f1 = new Array(); -var f2 = new Array(); - -function add_mapping(from,to) { - f1[f1.length] = from; - f2[f2.length] = to; -} - -// Status, Resolution, Platform, OS, Priority, Severity -add_mapping("status", "bug_status"); -add_mapping("resolution", "resolution"); // no change -add_mapping("platform", "rep_platform"); -add_mapping("os", "op_sys"); -add_mapping("opsys", "op_sys"); -add_mapping("priority", "priority"); // no change -add_mapping("pri", "priority"); -add_mapping("severity", "bug_severity"); -add_mapping("sev", "bug_severity"); -// People: AssignedTo, Reporter, QA Contact, CC, Added comment (?) -add_mapping("owner", "assigned_to"); -add_mapping("assignee", "assigned_to"); -add_mapping("assignedto", "assigned_to"); -add_mapping("reporter", "reporter"); // no change -add_mapping("rep", "reporter"); -add_mapping("qa", "qa_contact"); -add_mapping("qacontact", "qa_contact"); -add_mapping("cc", "cc"); // no change -// Product, Version, Component, Target Milestone -add_mapping("product", "product"); // no change -add_mapping("prod", "product"); -add_mapping("version", "version"); // no change -add_mapping("ver", "version"); -add_mapping("component", "component"); // no change -add_mapping("comp", "component"); -add_mapping("milestone", "target_milestone"); -add_mapping("target", "target_milestone"); -add_mapping("targetmilestone", "target_milestone"); -// Summary, Description, URL, Status whiteboard, Keywords -add_mapping("summary", "short_desc"); -add_mapping("shortdesc", "short_desc"); -add_mapping("desc", "longdesc"); -add_mapping("description", "longdesc"); -//add_mapping("comment", "longdesc"); // ??? - // reserve "comment" for "added comment" email search? -add_mapping("longdesc", "longdesc"); -add_mapping("url", "bug_file_loc"); -add_mapping("whiteboard", "status_whiteboard"); -add_mapping("statuswhiteboard", "status_whiteboard"); -add_mapping("sw", "status_whiteboard"); -add_mapping("keywords", "keywords"); // no change -add_mapping("kw", "keywords"); -// Attachments -add_mapping("attachment", "attachments.description"); -add_mapping("attachmentdesc", "attachments.description"); -add_mapping("attachdesc", "attachments.description"); -add_mapping("attachmentdata", "attachments.thedata"); -add_mapping("attachdata", "attachments.thedata"); -add_mapping("attachmentmimetype", "attachments.mimetype"); -add_mapping("attachmimetype", "attachments.mimetype"); - -// disabled because of bug 30823: -// "BugsThisDependsOn" --> "dependson" -// "OtherBugsDependingOnThis"--> "blocked" -//add_mapping("dependson", "dependson"); -//add_mapping("blocked", "blocked"); - -// Substring search doesn't make much sense for the following fields: -// "Attachment is patch" --> "attachments.ispatch" -// "Last changed date" --> "delta_ts" -// "Days since bug changed" --> "(to_days(now()) - to_days(bugs.delta_ts))" -//"groupset" -//"everconfirmed" -//"bug","bugid","bugno" --> "bug_id" -// "votes" --> "votes" -// "votes>5", "votes>=5", "votes=>5" works now, see below -// "votes:5" is interpreted as "votes>=5" - -function findIndex(array,value) { - for (var i=0; i<array.length; i++) - if (array[i] == value) return i; - return -1; -} - -function mapField(fieldname) { - var i = findIndex(f1,fieldname); - if (i >= 0) return f2[i]; - return no_result; -} - -// `keywords' is defined externally - -function is_keyword(s) { - return member(s, keywords); -} - -// `platforms' is defined externally - -function is_platform(str) { - return member (str.toLowerCase(),platforms); -} - -// `severities' is defined externally - -function is_severity(str) { - return member(str.toLowerCase(),severities); -} - -// `product_exceptions' is defined externally - -function match_product(str) { - var s = str.toLowerCase(); - return (s.length > 2) && (! member(s,product_exceptions)); -} - -// `component_exceptions are defined externally - -function match_component(str) { - var s = str.toLowerCase(); - return (s.length > 2) && (! member(s,component_exceptions)); -} - -var status_and_resolution = ""; // for pretty debug output only; these vars -var charts = ""; // always hold the data from the last query - -// derived from http://www.mozilla.org/quality/help/bugreport.js - -function make_chart(expr, field, type, value) { - charts += "<tr>" + - "<td><tt>" + expr + "</tt></td>" + - "<td><tt>" + field + "</tt></td>" + - "<td><tt>" + type + "</tt></td>" + - "<td><tt>" + value + "</tt></td>" + - "</tr>"; - return "&field" + expr + "=" + field + - "&type" + expr + "=" + type + - "&value" + expr + "=" + escape(value).replace(/[+]/g,"%2B"); -} - -// returns true if at least one of comparelist had the prefix, false otherwise -function addPrefixMatches(prefix, comparelist, resultlist) { - var foundMatch = false; - for (var i=0; i<comparelist.length; i++) { - if (isPrefix(prefix,comparelist[i])) { - foundMatch = true; - add(comparelist[i],resultlist); - } - } - return foundMatch; -} - -function prefixesNotFoundError(prefixes,statusValues,resolutionValues) { - var txt; - if (prefixes.length == 1) { - txt = "is not a prefix "; - } else { - txt = "are not prefixes "; - } - alert(prefixes + "\n" + txt + - "of one of these status or resolution values:\n" + - statusValues + "\n" + resolutionValues + "\n"); -} - -function make_query_URL(url, input, searchLong) { - - status_and_resolution = ""; - charts = ""; - - // declare all variables used in this function - - var searchURL = url; // bugzilla + "buglist.cgi" (or "query.cgi") - var abort = false; // global flag, checked upon return - - var i,j,k,l; // index counters used in 'for' loops - var parts,input2; // escape "quoted" parts of input - - var word; // array of words - // (space-separated parts of input2) - var alternative; // array of parts of an element of 'word' - // (separated by '|', sometimes by comma) - var comma_separated_words; // array of parts of an element of 'alternative' - var w; // current element of one of these arrays: - // word, alternative, comma_separated_words - - var w0; // first element of 'word' - var prefixes; // comma-separated parts of w0 - // (prefixes of status/resolution values) - - var expr; // used for 'priority' support - var n,separator; // used for 'votes' support - - var colon_separated_parts, fields,values,field; - // used for generic fields:values notation - - var chart,and,or; // counters used in add_chart - var negation; // boolean flag used in add_chart - - // `statuses_open' and `statuses_resolved' are defined externally - var statusOpen = statuses_open; - var statusResolved = statuses_resolved; - var statusAll = statusOpen.concat(statusResolved); - - // `resolutions' is defined externally - var bug_status = statusOpen.slice().reverse(); //reverse is just cosmetic - var resolution = new Array(); - - // escape everything between quotes: "foo bar" --> "foo%20bar" - parts = input.split('"'); - if ((parts.length % 2) != 1) { - alert('Unterminated quote'); - abort = true; - return no_result; - } - for (i=1; i<parts.length; i+=2) { - parts[i] = escape(parts[i]); - } - input2 = parts.join('"'); - - // abort if there are still brackets - if (input2.match(/[(]|[\)]/)) { - alert('Brackets (...) are not supported.\n' + - 'Use quotes "..." for values that contain special characters.'); - abort = true; - return no_result; - } - - // translate " AND "," OR "," NOT " to space,comma,dash - input2 = input2.replace(/[\s]+AND[\s]+/g," "); - input2 = input2.replace(/[\s]+OR[\s]+/g,"|"); - input2 = input2.replace(/[\s]+NOT[\s]+/g," -"); - - // now split into words at space positions - word = input2.split(/[\s]+/); - - // determine bug_status and resolution - // the first word may contain relevant info - - // This function matches the given prefixes against the given statuses and - // resolutions. Matched statuses are added to bug_status, matched - // resolutions are added to resolution. Returns true if and only if - // some matches were found for at least one of the given prefixes. - function matchPrefixes(prefixes,statuses,resolutions) { - var failedPrefixes = new Array(); - var foundMatch = false; - for (var j=0; j<prefixes.length; j++) { - var ok1 = addPrefixMatches(prefixes[j],statuses,bug_status); - var ok2 = addPrefixMatches(prefixes[j],resolutions,resolution); - if ((! ok1) && (! ok2)) { - add(prefixes[j],failedPrefixes); - } else { - foundMatch = true; - } - } - //report an error if some (but not all) prefixes didn't match anything - if (foundMatch && (failedPrefixes.length > 0)) { - prefixesNotFoundError(failedPrefixes,statuses,resolutions); - abort = true; - } - return foundMatch; - } - - if (word[0] == "ALL") { - // special case: search for bugs regardless of status - addAll(statusResolved,bug_status); - do_shift(word); - } else if (word[0] == "OPEN") { - // special case: search for open bugs only - do_shift(word); - } else if (word[0].match("^[+][A-Z]+(,[A-Z]+)*$")) { - // e.g. +DUP,FIX - w0 = do_shift(word); - prefixes = w0.substring(1).split(","); - if (! matchPrefixes(prefixes,statusResolved,resolutions)) { - do_unshift(word,w0); - } - } else if (word[0].match("^[A-Z]+(,[A-Z]+)*$")) { - // e.g. NEW,ASSI,REOP,FIX - bug_status = new Array(); // reset - w0 = do_shift(word); - prefixes = w0.split(","); - if (! matchPrefixes(prefixes,statusAll,resolutions)) { - do_unshift(word,w0); - bug_status = statusOpen.reverse(); //reset to default bug_status - } - } else { - // default case: - // search for unresolved bugs only - // uncomment this to include duplicate bugs in the search - // add("DUPLICATE",resolution); - } - if (resolution.length > 0) { - resolution = resolution.reverse(); - do_unshift(resolution,"---"); - addAll(statusResolved,bug_status); - } - bug_status = bug_status.reverse(); - bug_status = map(bug_status,escape); - searchURL += "?bug_status=" + bug_status.join("&bug_status="); - status_and_resolution += 'Status: <tt>'+bug_status+'</tt>'; - - if (resolution.length > 0) { - resolution = map(resolution,escape); - searchURL += "&resolution=" + resolution.join("&resolution="); - status_and_resolution += '<br>'+'Resolution: <tt>'+resolution+'</tt>'; - } - - // end of bug_status & resolution stuff - - chart = 0; - and = 0; - or = 0; - - negation = false; - - function negate_comparison_type(type) { - switch(type) { - case "substring": return "notsubstring"; - case "anywords": return "nowords"; - case "regexp": return "notregexp"; - default: - // e.g. "greaterthan" - alert("Can't negate comparison type: `" + type + "'"); - abort = true; - return "dummy"; - } - } - - function add_chart(field,type,value) { - // undo escaping for value: '"foo%20bar"' --> 'foo bar' - var parts = value.split('"'); - if ((parts.length % 2) != 1) { - alert('Internal error: unescaping failure'); - abort = true; - } - for (var i=1; i<parts.length; i+=2) { - parts[i] = unescape(parts[i]); - } - var value2 = parts.join(''); - - // negate type if negation is set - var type2 = type; - if (negation) { - type2 = negate_comparison_type(type2); - } - searchURL += make_chart(chart+"-"+and+"-"+or,field,type2,value2); - or++; - if (negation) { - and++; - or=0; - } - } - - for (i=0; i<word.length; i++, chart++) { - - w = word[i]; - - negation = false; - if (w.charAt(0) == "-") { - negation = true; - w = w.substring(1); - } - - switch (w.charAt(0)) { - case "+": - alternative = w.substring(1).split(/[|,]/); - for (j=0; j<alternative.length; j++) - add_chart("short_desc","substring",alternative[j]); - break; - case "#": - alternative = w.substring(1).replace(/[|,]/g," "); - add_chart("short_desc","anywords",alternative); - if (searchLong) - add_chart("longdesc","anywords",alternative); - break; - case ":": - alternative = w.substring(1).split(","); - for (j=0; j<alternative.length; j++) { - add_chart("product","substring",alternative[j]); - add_chart("component","substring",alternative[j]); - } - break; - case "@": - alternative = w.substring(1).split(","); - for (j=0; j<alternative.length; j++) - add_chart("assigned_to","substring",alternative[j]); - break; - case "[": - add_chart("short_desc","substring",w); - add_chart("status_whiteboard","substring",w); - break; - case "!": - add_chart("keywords","anywords",w.substring(1)); - break; - default: - alternative=w.split("|"); - for (j=0; j<alternative.length; j++) { - - w=alternative[j]; - - // votes:xx ("at least xx votes") - if (w.match("^votes[:][0-9]+$")) { - n = w.split(/[:]/)[1]; - add_chart("votes","greaterthan",String(n-1)); - continue; - } - // generic field1,field2,field3:value1,value2 notation - if (w.match("^[^:]+[:][^:\/][^:]*$")) { - colon_separated_parts = w.split(":"); - fields = colon_separated_parts[0].split(/[,]+/); - values = colon_separated_parts[1].split(/[,]+/); - for (k=0; k<fields.length; k++) { - field = mapField(fields[k]); - if (field == no_result) { - alert("`"+fields[k]+"'"+ - " is not a valid field name."); - abort = true; - return no_result; - } else { - for (l=0; l<values.length; l++) { - add_chart(field,"substring",values[l]); - } - } - } - continue; - } - comma_separated_words=w.split(/[,]+/); - for (k=0; k<comma_separated_words.length; k++) { - w=comma_separated_words[k]; - - // platform - if (is_platform(w)) { - add_chart("rep_platform","substring",w); - continue; - } - // priority - if (w.match("^[pP][1-5](,[pP]?[1-5])*$")) { - expr = "["+w.replace(/[p,]/g,"")+"]"; - add_chart("priority","regexp",expr); - continue; - } - if (w.match("^[pP][1-5]-[1-5]$")) { - expr = "["+w.substring(1)+"]"; - add_chart("priority","regexp",expr); - continue; - } - // severity - if (is_severity(w)) { - add_chart("bug_severity","substring",w); - continue; - } - // votes>xx - if (w.match("^votes>[0-9]+$")) { - n = w.split(">")[1]; - add_chart("votes","greaterthan",n); - continue; - } - // votes>=xx, votes=>xx - if (w.match("^votes(>=|=>)[0-9]+$")) { - separator = w.match("^votes(>=|=>)[0-9]+$")[1]; - n = w.split(separator)[1]; - add_chart("votes","greaterthan",String(n-1)); - continue; - } - // really default case - if (match_product(w)) { - add_chart("product","substring",w); - } - if (match_component(w)) { - add_chart("component","substring",w); - } - if (is_keyword(w)) { - add_chart("keywords","substring",w); - if (w.length > 2) { - add_chart("short_desc","substring",w); - add_chart("status_whiteboard","substring",w); - } - } else { - add_chart("short_desc","substring",w); - add_chart("status_whiteboard","substring",w); - } - if (searchLong) - add_chart("longdesc","substring",w); - - // URL field (for IP addrs, host.names, scheme://urls) - if (w.match(/[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+/) - || w.match(/^[A-Za-z]+([.][A-Za-z]+)+/) - || w.match(/[:][\/][\/]/) - || w.match(/localhost/) - || w.match(/mailto[:]?/) - // || w.match(/[A-Za-z]+[:][0-9]+/) //host:port - ) - add_chart("bug_file_loc","substring",w); - } - } - } - and = 0; - or = 0; - } - - //searchURL += "&cmdtype=doit"; - - if (abort == false) { - return searchURL; - } else { - return no_result; - } -} - -function unique_id () { - return (new Date()).getTime(); -} - -function ShowURL(mode,input) { - var searchURL = make_query_URL(bugzilla+"buglist.cgi", input, false); - if (searchURL != no_result) { - var pieces = searchURL.replace(/[\?]/g,"\n?").replace(/[\&]/g,"\n&"); - if (mode == "alert") { - alert(pieces); - } else { - var table = "<table border=1>" + - "<thead>" + - "<tr>" + - "<th>Chart-And-Or</th>" + - "<th>Field</th>" + - "<th>Type</th>" + - "<th>Value</th>" + - "</tr>" + - "</thead>" + - "<tbody>" + charts + "</tbody>" + - "</table>"; - var html = '<html>' + - '<head>' + - '<title>' + input + '</title>' + - '</head>' + - '<body>' + - '<a href="' + searchURL + '">' + - 'Submit Query' + - '</a>' + - '<p>' + status_and_resolution + - '<p>' + table + - '<pre>' + - pieces.replace(/[\n]/g,"<br>") + - '</pre>' + - '</body>' + - '</html>'; - var w = window.open("","preview_"+unique_id()); - w.document.write(html); - w.document.close(); - } - } -} - -// -// new interface: -// searchLong is a boolean now (not a checkbox/radiobutton) -// -function Search(url, input, searchLong) { - var inputstring = new String(input); - var word = inputstring.split(/[\s]+/); - - // Check for empty input - if ( word.length == 1 && word[0] == "" ) - return; - - // Check for potential Bugzilla-busting intensive queries - if ((searchLong!=false) && word.length > 4) { - var message = "Searching Descriptions for more than four words " + - "will take a very long time indeed. Please choose " + - "no more than four keywords for your query."; - alert(message); - return; - } - var searchURL = make_query_URL(url, inputstring, searchLong); - if (searchURL != no_result) { - go_to(searchURL); - //window.open(searchURL, "other" ); - } else { - return; - } -} - -// -// original interface, untested -// -//function SearchForBugs (input, searchRadio) { -// if (searchRadio[0].checked) { -// return Search(bugzilla + "buglist.cgi", input, false); -// } else { -// return Search(bugzilla + "buglist.cgi", input, true); -// } -//} - -// derived from http://www.cs.hmc.edu/~jruderma/s/bugz.html - -// QuickSearch combines lookup-by-bug-number and search -// in a single textbox. -// -// type nothing: -// --> go to bugzilla front page -// type a number: -// --> go to that bug number -// type several numbers, separated by commas: -// --> go to a buglist of just those bug numbers -// type anything else: -// --> search summary, product, component, keywords, status whiteboard -// (and URL if it's an IP address, a host.name, or an absolute://URL) - -function QuickSearch (input) -{ - //remove leading and trailing whitespace - input = input.replace(/^[\s]+/,"").replace(/[\s]+$/,""); - - if (input == "") - { - //once this _is_ on http://bugzilla.mozilla.org, it should just return; - go_to(bugzilla); - } - else if (input.match(/^[0-9, ]*$/)) - { - if (input.indexOf(",") == -1) { - // only _one_ bug number --> show_bug - go_to(bugzilla+"show_bug.cgi?id="+escape(input)); - } else { - // comma-separated bug numbers --> buglist - go_to(bugzilla+"buglist.cgi?bug_id="+escape(input) - + "&bugidtype=include&order=bugs.bug_id"); - } - } - else - { - Search(bugzilla+"buglist.cgi",input,false); - } - return; -} - -function LoadQuery(input) { - //remove leading and trailing whitespace - input = input.replace(/^[\s]+/,"").replace(/[\s]+$/,""); - - Search(bugzilla+"query.cgi",input,false); - return; -} - |