Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
bugzilla
Commits
da12cec6
Commit
da12cec6
authored
Nov 22, 2012
by
Byron Jones
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 780820: Allows for multiple custom search criteria to match one field
r=dkl,a=LpSolit
parent
ceafb43c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
333 additions
and
52 deletions
+333
-52
DB.pm
Bugzilla/DB.pm
+4
-2
Oracle.pm
Bugzilla/DB/Oracle.pm
+3
-3
Search.pm
Bugzilla/Search.pm
+45
-26
Clause.pm
Bugzilla/Search/Clause.pm
+6
-1
ClauseGroup.pm
Bugzilla/Search/ClauseGroup.pm
+97
-0
custom-search.js
js/custom-search.js
+157
-17
user-error.html.tmpl
template/en/default/global/user-error.html.tmpl
+11
-0
boolean-charts.html.tmpl
template/en/default/search/boolean-charts.html.tmpl
+10
-3
No files found.
Bugzilla/DB.pm
View file @
da12cec6
...
...
@@ -385,8 +385,10 @@ sub sql_string_until {
}
sub
sql_in
{
my
(
$self
,
$column_name
,
$in_list_ref
)
=
@_
;
return
" $column_name IN ("
.
join
(
','
,
@$in_list_ref
)
.
") "
;
my
(
$self
,
$column_name
,
$in_list_ref
,
$negate
)
=
@_
;
return
" $column_name "
.
(
$negate
?
"NOT "
:
""
)
.
"IN ("
.
join
(
','
,
@$in_list_ref
)
.
") "
;
}
sub
sql_fulltext_search
{
...
...
Bugzilla/DB/Oracle.pm
View file @
da12cec6
...
...
@@ -203,16 +203,16 @@ sub sql_position {
}
sub
sql_in
{
my
(
$self
,
$column_name
,
$in_list_ref
)
=
@_
;
my
(
$self
,
$column_name
,
$in_list_ref
,
$negate
)
=
@_
;
my
@in_list
=
@$in_list_ref
;
return
$self
->
SUPER::
sql_in
(
$column_name
,
$in_list_ref
)
if
$#in_list
<
1000
;
return
$self
->
SUPER::
sql_in
(
$column_name
,
$in_list_ref
,
$negate
)
if
$#in_list
<
1000
;
my
@in_str
;
while
(
@in_list
)
{
my
$length
=
$#in_list
+
1
;
my
$splice
=
$length
>
1000
?
1000
:
$length
;
my
@sub_in_list
=
splice
(
@in_list
,
0
,
$splice
);
push
(
@in_str
,
$self
->
SUPER::
sql_in
(
$column_name
,
\
@sub_in_list
));
$self
->
SUPER::
sql_in
(
$column_name
,
\
@sub_in_list
,
$negate
));
}
return
"( "
.
join
(
" OR "
,
@in_str
)
.
" )"
;
}
...
...
Bugzilla/Search.pm
View file @
da12cec6
...
...
@@ -23,6 +23,7 @@ use Bugzilla::Group;
use
Bugzilla::
User
;
use
Bugzilla::
Field
;
use
Bugzilla::Search::
Clause
;
use
Bugzilla::Search::
ClauseGroup
;
use
Bugzilla::Search::
Condition
qw(condition)
;
use
Bugzilla::
Status
;
use
Bugzilla::
Keyword
;
...
...
@@ -1151,8 +1152,8 @@ sub _translate_join {
die
"join with no table: "
.
Dumper
(
$join_info
)
if
!
$join_info
->
{
table
};
die
"join with no 'as': "
.
Dumper
(
$join_info
)
if
!
$join_info
->
{
as
};
my
$from_table
=
"bugs"
;
my
$from_table
=
$join_info
->
{
bugs_table
}
||
"bugs"
;
my
$from
=
$join_info
->
{
from
}
||
"bug_id"
;
if
(
$from
=~
/^(\w+)\.(\w+)$/
)
{
(
$from_table
,
$from
)
=
(
$1
,
$2
);
...
...
@@ -1557,7 +1558,7 @@ sub _charts_to_conditions {
my
$clause
=
$self
->
_charts
;
my
@joins
;
$clause
->
walk_conditions
(
sub
{
my
(
$condition
)
=
@_
;
my
(
$c
lause
,
$c
ondition
)
=
@_
;
return
if
!
$condition
->
translated
;
push
(
@joins
,
@
{
$condition
->
translated
->
{
joins
}
});
});
...
...
@@ -1577,7 +1578,7 @@ sub _params_to_data_structure {
my
(
$self
)
=
@_
;
# First we get the "special" charts, representing all the normal
# field
s
on the search page. This may modify _params, so it needs to
# field
s
on the search page. This may modify _params, so it needs to
# happen first.
my
$clause
=
$self
->
_special_charts
;
...
...
@@ -1586,7 +1587,7 @@ sub _params_to_data_structure {
# And then process the modern "custom search" format.
$clause
->
add
(
$self
->
_custom_search
);
return
$clause
;
}
...
...
@@ -1617,7 +1618,7 @@ sub _boolean_charts {
my
$identifier
=
"$chart_id-$and_id-$or_id"
;
my
$field
=
$params
->
{
"field$identifier"
};
my
$operator
=
$params
->
{
"type$identifier"
};
my
$value
=
$params
->
{
"value$identifier"
};
my
$value
=
$params
->
{
"value$identifier"
};
$or_clause
->
add
(
$field
,
$operator
,
$value
);
}
$and_clause
->
add
(
$or_clause
);
...
...
@@ -1636,13 +1637,19 @@ sub _custom_search {
my
@field_ids
=
$self
->
_field_ids
;
return
unless
scalar
@field_ids
;
my
$current_clause
=
new
Bugzilla::Search::
Clause
(
$params
->
{
j_top
});
my
$joiner
=
$params
->
{
j_top
}
||
''
;
my
$current_clause
=
$joiner
eq
'AND_G'
?
new
Bugzilla::Search::
ClauseGroup
()
:
new
Bugzilla::Search::
Clause
(
$joiner
);
my
@clause_stack
;
foreach
my
$id
(
@field_ids
)
{
my
$field
=
$params
->
{
"f$id"
};
if
(
$field
eq
'OP'
)
{
my
$joiner
=
$params
->
{
"j$id"
};
my
$new_clause
=
new
Bugzilla::Search::
Clause
(
$joiner
);
my
$joiner
=
$params
->
{
"j$id"
}
||
''
;
my
$new_clause
=
$joiner
eq
'AND_G'
?
new
Bugzilla::Search::
ClauseGroup
()
:
new
Bugzilla::Search::
Clause
(
$joiner
);
$new_clause
->
negate
(
$params
->
{
"n$id"
});
$current_clause
->
add
(
$new_clause
);
push
(
@clause_stack
,
$current_clause
);
...
...
@@ -1681,14 +1688,12 @@ sub _field_ids {
}
sub
_handle_chart
{
my
(
$self
,
$chart_id
,
$condition
)
=
@_
;
my
(
$self
,
$chart_id
,
$c
lause
,
$c
ondition
)
=
@_
;
my
$dbh
=
Bugzilla
->
dbh
;
my
$params
=
$self
->
_params
;
my
(
$field
,
$operator
,
$value
)
=
$condition
->
fov
;
$field
=
FIELD_MAP
->
{
$field
}
||
$field
;
return
if
(
!
defined
$field
or
!
defined
$operator
or
!
defined
$value
);
$field
=
FIELD_MAP
->
{
$field
}
||
$field
;
my
$string_value
;
if
(
ref
$value
eq
'ARRAY'
)
{
...
...
@@ -1719,15 +1724,19 @@ sub _handle_chart {
# on multiple values, like anyexact.
my
%
search_args
=
(
chart_id
=>
$chart_id
,
sequence
=>
$chart_id
,
field
=>
$field
,
full_field
=>
$full_field
,
operator
=>
$operator
,
value
=>
$string_value
,
all_values
=>
$value
,
joins
=>
[]
,
chart_id
=>
$chart_id
,
sequence
=>
$chart_id
,
field
=>
$field
,
full_field
=>
$full_field
,
operator
=>
$operator
,
value
=>
$string_value
,
all_values
=>
$value
,
joins
=>
[]
,
bugs_table
=>
'bugs'
,
table_suffix
=>
''
,
);
$clause
->
update_search_args
(
\%
search_args
);
$search_args
{
quoted
}
=
$self
->
_quote_unless_numeric
(
\%
search_args
);
# This should add a "term" selement to %search_args.
$self
->
do_search_function
(
\%
search_args
);
...
...
@@ -1743,7 +1752,12 @@ sub _handle_chart {
field
=>
$field
,
type
=>
$operator
,
value
=>
$string_value
,
term
=>
$search_args
{
term
},
});
foreach
my
$join
(
@
{
$search_args
{
joins
}
})
{
$join
->
{
bugs_table
}
=
$search_args
{
bugs_table
};
$join
->
{
table_suffix
}
=
$search_args
{
table_suffix
};
}
$condition
->
translated
(
\%
search_args
);
}
...
...
@@ -1899,8 +1913,14 @@ sub _quote_unless_numeric {
}
sub
build_subselect
{
my
(
$outer
,
$inner
,
$table
,
$cond
)
=
@_
;
return
"$outer IN (SELECT $inner FROM $table WHERE $cond)"
;
my
(
$outer
,
$inner
,
$table
,
$cond
,
$negate
)
=
@_
;
# Execute subselects immediately to avoid dependent subqueries, which are
# large performance hits on MySql
my
$q
=
"SELECT DISTINCT $inner FROM $table WHERE $cond"
;
my
$dbh
=
Bugzilla
->
dbh
;
my
$list
=
$dbh
->
selectcol_arrayref
(
$q
);
return
$negate
?
"1=1"
:
"1=2"
unless
@$list
;
return
$dbh
->
sql_in
(
$outer
,
$list
,
$negate
);
}
# Used by anyexact to get the list of input values. This allows us to
...
...
@@ -2653,8 +2673,7 @@ sub _multiselect_term {
my
$term
=
$args
->
{
term
};
$term
.=
$args
->
{
_extra_where
}
||
''
;
my
$select
=
$args
->
{
_select_field
}
||
'bug_id'
;
my
$not_sql
=
$not
?
"NOT "
:
''
;
return
"bugs.bug_id ${not_sql}IN (SELECT $select FROM $table WHERE $term)"
;
return
build_subselect
(
"$args->{bugs_table}.bug_id"
,
$select
,
$table
,
$term
,
$not
);
}
###############################
...
...
Bugzilla/Search/Clause.pm
View file @
da12cec6
...
...
@@ -30,6 +30,11 @@ sub children {
return
$self
->
{
children
};
}
sub
update_search_args
{
my
(
$self
,
$search_args
)
=
@_
;
# abstract
}
sub
joiner
{
return
$_
[
0
]
->
{
joiner
}
}
sub
has_translated_conditions
{
...
...
@@ -71,7 +76,7 @@ sub walk_conditions {
my
(
$self
,
$callback
)
=
@_
;
foreach
my
$child
(
@
{
$self
->
children
})
{
if
(
$child
->
isa
(
'Bugzilla::Search::Condition'
))
{
$callback
->
(
$child
);
$callback
->
(
$
self
,
$
child
);
}
else
{
$child
->
walk_conditions
(
$callback
);
...
...
Bugzilla/Search/ClauseGroup.pm
0 → 100644
View file @
da12cec6
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package
Bugzilla::Search::
ClauseGroup
;
use
5.10.1
;
use
strict
;
use
base
qw(Bugzilla::Search::Clause)
;
use
Bugzilla::
Error
;
use
Bugzilla::Search::
Condition
qw(condition)
;
use
Bugzilla::
Util
qw(trick_taint)
;
use
List::
MoreUtils
qw(uniq)
;
use
constant
UNSUPPORTED_FIELDS
=>
qw(
attach_data.thedata
classification
commenter
component
longdescs.count
product
owner_idle_time
)
;
sub
new
{
my
(
$class
)
=
@_
;
my
$self
=
bless
({
joiner
=>
'AND'
},
$class
);
# Add a join back to the bugs table which will be used to group conditions
# for this clause
my
$condition
=
Bugzilla::Search::
Condition
->
new
({});
$condition
->
translated
({
joins
=>
[{
table
=>
'bugs'
,
as
=>
'bugs_g0'
,
from
=>
'bug_id'
,
to
=>
'bug_id'
,
extra
=>
[]
,
}],
term
=>
'1 = 1'
,
});
$self
->
SUPER::
add
(
$condition
);
$self
->
{
group_condition
}
=
$condition
;
return
$self
;
}
sub
add
{
my
(
$self
,
@args
)
=
@_
;
my
$field
=
scalar
(
@args
)
==
3
?
$args
[
0
]
:
$args
[
0
]
->
{
field
};
# We don't support nesting of conditions under this clause
if
(
scalar
(
@args
)
==
1
&&
!
$args
[
0
]
->
isa
(
'Bugzilla::Search::Condition'
))
{
ThrowUserError
(
'search_grouped_invalid_nesting'
);
}
# Ensure all conditions use the same field
if
(
!
$self
->
{
_field
})
{
$self
->
{
_field
}
=
$field
;
}
elsif
(
$field
ne
$self
->
{
_field
})
{
ThrowUserError
(
'search_grouped_field_mismatch'
);
}
# Unsupported fields
if
(
grep
{
$_
eq
$field
}
UNSUPPORTED_FIELDS
)
{
ThrowUserError
(
'search_grouped_field_invalid'
,
{
field
=>
$field
});
}
$self
->
SUPER::
add
(
@args
);
}
sub
update_search_args
{
my
(
$self
,
$search_args
)
=
@_
;
# No need to change things if there's only one child condition
return
unless
scalar
(
@
{
$self
->
children
})
>
1
;
# we want all the terms to use the same join table
if
(
!
exists
$self
->
{
_first_chart_id
})
{
$self
->
{
_first_chart_id
}
=
$search_args
->
{
chart_id
};
}
else
{
$search_args
->
{
chart_id
}
=
$self
->
{
_first_chart_id
};
}
my
$suffix
=
'_g'
.
$self
->
{
_first_chart_id
};
$self
->
{
group_condition
}
->
{
translated
}
->
{
joins
}
->
[
0
]
->
{
as
}
=
"bugs$suffix"
;
$search_args
->
{
full_field
}
=~
s/^bugs\./bugs$suffix\./
;
$search_args
->
{
table_suffix
}
=
$suffix
;
$search_args
->
{
bugs_table
}
=
"bugs$suffix"
;
}
1
;
js/custom-search.js
View file @
da12cec6
...
...
@@ -28,7 +28,7 @@ function custom_search_new_row() {
var
row
=
document
.
getElementById
(
'custom_search_last_row'
);
var
clone
=
row
.
cloneNode
(
true
);
_cs_fix_ids
(
clone
);
_cs_fix_
row_
ids
(
clone
);
// We only want one copy of the buttons, in the new row. So the old
// ones get deleted.
...
...
@@ -43,13 +43,28 @@ function custom_search_new_row() {
// Always make sure there's only one row with this id.
row
.
id
=
null
;
row
.
parentNode
.
appendChild
(
clone
);
cs_reconfigure
(
row
);
fix_query_string
(
row
);
return
clone
;
}
var
_cs_source_any_all
;
function
custom_search_open_paren
()
{
var
row
=
document
.
getElementById
(
'custom_search_last_row'
);
// create a copy of j_top and use that as the source, so we can modify
// j_top if required
if
(
!
_cs_source_any_all
)
{
var
j_top
=
document
.
getElementById
(
'j_top'
);
_cs_source_any_all
=
j_top
.
cloneNode
(
true
);
}
// find the parent any/all select, and remove the grouped option
var
structure
=
_cs_build_structure
(
row
);
var
old_id
=
_cs_get_row_id
(
row
);
var
parent_j
=
document
.
getElementById
(
_cs_get_join
(
structure
,
'f'
+
old_id
));
_cs_remove_and_g
(
parent_j
);
// If there's an "Any/All" select in this row, it needs to stay as
// part of the parent paren set.
var
old_any_all
=
_remove_any_all
(
row
);
...
...
@@ -66,21 +81,20 @@ function custom_search_open_paren() {
var
not_for_paren
=
new_not
[
0
].
cloneNode
(
true
);
// Preserve the values when modifying the row.
var
id
=
_cs_fix_ids
(
row
,
true
);
var
id
=
_cs_fix_
row_
ids
(
row
,
true
);
var
prev_id
=
id
-
1
;
var
paren_row
=
row
.
cloneNode
(
false
);
paren_row
.
id
=
null
;
paren_row
.
innerHTML
=
'(<input type="hidden" name="f'
+
prev_id
+
'" value="OP">'
;
+
'"
id="f'
+
prev_id
+
'"
value="OP">'
;
paren_row
.
insertBefore
(
not_for_paren
,
paren_row
.
firstChild
);
row
.
parentNode
.
insertBefore
(
paren_row
,
row
);
// New paren set needs a new "Any/All" select.
var
any_all_container
=
document
.
createElement
(
'div'
);
YAHOO
.
util
.
Dom
.
addClass
(
any_all_container
,
ANY_ALL_SELECT_CLASS
);
var
j_top
=
document
.
getElementById
(
'j_top'
);
var
any_all
=
j_top
.
cloneNode
(
true
);
var
any_all
=
_cs_source_any_all
.
cloneNode
(
true
);
any_all
.
name
=
'j'
+
prev_id
;
any_all
.
id
=
any_all
.
name
;
any_all_container
.
appendChild
(
any_all
);
...
...
@@ -92,6 +106,7 @@ function custom_search_open_paren() {
YAHOO
.
util
.
Dom
.
setStyle
(
row
,
'margin-left'
,
new_margin
+
'em'
);
YAHOO
.
util
.
Dom
.
removeClass
(
'cp_container'
,
'bz_default_hidden'
);
cs_reconfigure
(
any_all_container
);
fix_query_string
(
any_all_container
);
}
...
...
@@ -100,7 +115,7 @@ function custom_search_close_paren() {
// We need to up the new row's id by one more, because we're going
// to insert a "CP" before it.
var
id
=
_cs_fix_ids
(
new_row
);
var
id
=
_cs_fix_
row_
ids
(
new_row
);
var
margin
=
YAHOO
.
util
.
Dom
.
getStyle
(
new_row
,
'margin-left'
);
var
int_match
=
margin
.
match
(
/
\d
+/
);
...
...
@@ -110,7 +125,7 @@ function custom_search_close_paren() {
var
paren_row
=
new_row
.
cloneNode
(
false
);
paren_row
.
id
=
null
;
paren_row
.
innerHTML
=
')<input type="hidden" name="f'
+
(
id
-
1
)
+
'" value="CP">'
;
+
'"
id="f'
+
(
id
-
1
)
+
'"
value="CP">'
;
new_row
.
parentNode
.
insertBefore
(
paren_row
,
new_row
);
...
...
@@ -118,6 +133,7 @@ function custom_search_close_paren() {
YAHOO
.
util
.
Dom
.
addClass
(
'cp_container'
,
'bz_default_hidden'
);
}
cs_reconfigure
(
new_row
);
fix_query_string
(
new_row
);
}
...
...
@@ -160,19 +176,17 @@ function redirect_html4_browsers() {
document
.
location
=
url
;
}
function
_cs_fix_
ids
(
parent
,
preserve_values
)
{
function
_cs_fix_
row_ids
(
row
,
preserve_values
)
{
// Update the label of the checkbox.
var
label
=
YAHOO
.
util
.
Dom
.
getElementBy
(
function
()
{
return
true
},
'label'
,
parent
);
var
label
=
YAHOO
.
util
.
Dom
.
getElementBy
(
function
()
{
return
true
},
'label'
,
row
);
var
id_match
=
label
.
htmlFor
.
match
(
/
\d
+$/
);
var
id
=
parseInt
(
id_match
[
0
])
+
1
;
label
.
htmlFor
=
label
.
htmlFor
.
replace
(
/
\d
+$/
,
id
);
// Sets all the inputs in the
parent
back to their default
// Sets all the inputs in the
row
back to their default
// and fixes their id.
var
fields
=
YAHOO
.
util
.
Dom
.
getElementsByClassName
(
'custom_search_form_field'
,
null
,
parent
);
YAHOO
.
util
.
Dom
.
getElementsByClassName
(
'custom_search_form_field'
,
null
,
row
);
for
(
var
i
=
0
;
i
<
fields
.
length
;
i
++
)
{
var
field
=
fields
[
i
];
...
...
@@ -184,15 +198,141 @@ function _cs_fix_ids(parent, preserve_values) {
field
.
value
=
''
;
}
}
// Update the numeric id for the
new
row.
// Update the numeric id for the row.
field
.
name
=
field
.
name
.
replace
(
/
\d
+$/
,
id
);
field
.
id
=
field
.
name
;
}
return
id
;
}
function
_cs_build_structure
(
form_member
)
{
// build a map of the structure of the custom fields
var
form
=
YAHOO
.
util
.
Dom
.
getAncestorByTagName
(
form_member
,
'form'
);
var
last_id
=
_get_last_cs_row_id
(
form
);
var
structure
=
[
'j_top'
];
var
nested
=
[
structure
];
for
(
var
id
=
1
;
id
<=
last_id
;
id
++
)
{
var
f
=
form
[
'f'
+
id
];
if
(
!
f
||
!
f
.
parentNode
.
parentNode
)
continue
;
if
(
f
.
value
==
'OP'
)
{
var
j
=
[
'j'
+
id
];
nested
[
nested
.
length
-
1
].
push
(
j
);
nested
.
push
(
j
);
continue
;
}
else
if
(
f
.
value
==
'CP'
)
{
nested
.
pop
();
continue
;
}
else
{
nested
[
nested
.
length
-
1
].
push
(
'f'
+
id
);
}
}
return
structure
;
}
function
cs_reconfigure
(
form_member
)
{
var
structure
=
_cs_build_structure
(
form_member
);
_cs_add_listeners
(
structure
);
_cs_trigger_j_listeners
(
structure
);
fix_query_string
(
form_member
);
var
j
=
_cs_get_join
(
structure
,
'f'
+
_get_last_cs_row_id
());
document
.
getElementById
(
'op_button'
).
disabled
=
document
.
getElementById
(
j
).
value
==
'AND_G'
;
}
function
_cs_add_listeners
(
parents
)
{
for
(
var
i
=
0
,
l
=
parents
.
length
;
i
<
l
;
i
++
)
{
if
(
typeof
(
parents
[
i
])
==
'object'
)
{
// nested
_cs_add_listeners
(
parents
[
i
]);
}
else
if
(
i
==
0
)
{
// joiner
YAHOO
.
util
.
Event
.
removeListener
(
parents
[
i
],
'change'
,
_cs_j_change
);
YAHOO
.
util
.
Event
.
addListener
(
parents
[
i
],
'change'
,
_cs_j_change
,
parents
);
}
else
{
// field
YAHOO
.
util
.
Event
.
removeListener
(
parents
[
i
],
'change'
,
_cs_f_change
);
YAHOO
.
util
.
Event
.
addListener
(
parents
[
i
],
'change'
,
_cs_f_change
,
parents
);
}
}
}
function
_cs_trigger_j_listeners
(
fields
)
{
var
has_children
=
false
;
for
(
var
i
=
0
,
l
=
fields
.
length
;
i
<
l
;
i
++
)
{
if
(
typeof
(
fields
[
i
])
==
'undefined'
)
{
continue
;
}
else
if
(
typeof
(
fields
[
i
])
==
'object'
)
{
// nested
_cs_trigger_j_listeners
(
fields
[
i
]);
has_children
=
true
;
}
else
if
(
i
==
0
)
{
_cs_j_change
(
undefined
,
fields
);
}
}
if
(
has_children
)
{
_cs_remove_and_g
(
document
.
getElementById
(
fields
[
0
]));
}
}
function
_cs_get_join
(
parents
,
field
)
{
for
(
var
i
=
0
,
l
=
parents
.
length
;
i
<
l
;
i
++
)
{
if
(
typeof
(
parents
[
i
])
==
'object'
)
{
// nested
var
result
=
_cs_get_join
(
parents
[
i
],
field
);
if
(
result
)
return
result
;
}
else
if
(
parents
[
i
]
==
field
)
{
return
parents
[
0
];
}
}
return
false
;
}
function
_cs_remove_and_g
(
join_field
)
{
var
index
=
bz_optionIndex
(
join_field
,
'AND_G'
);
join_field
.
options
[
index
]
=
null
;
join_field
.
options
[
bz_optionIndex
(
join_field
,
'AND'
)].
innerHTML
=
cs_and_label
;
join_field
.
options
[
bz_optionIndex
(
join_field
,
'OR'
)].
innerHTML
=
cs_or_label
;
}
function
_cs_j_change
(
evt
,
fields
,
field
)
{
var
j
=
document
.
getElementById
(
fields
[
0
]);
if
(
j
&&
j
.
value
==
'AND_G'
)
{
for
(
var
i
=
1
,
l
=
fields
.
length
;
i
<
l
;
i
++
)
{
if
(
typeof
(
fields
[
i
])
==
'object'
)
continue
;
if
(
!
field
)
{
field
=
document
.
getElementById
(
fields
[
i
]).
value
;
}
else
{
document
.
getElementById
(
fields
[
i
]).
value
=
field
;
}
}
if
(
evt
)
{
fix_query_string
(
j
);
}
if
(
'f'
+
_get_last_cs_row_id
()
==
fields
[
fields
.
length
-
1
])
{
document
.
getElementById
(
'op_button'
).
style
.
display
=
'none'
;
}
}
else
{
document
.
getElementById
(
'op_button'
).
style
.
display
=
''
;
}
}
function
_cs_f_change
(
evt
,
args
)
{
var
field
=
YAHOO
.
util
.
Event
.
getTarget
(
evt
);
_cs_j_change
(
evt
,
args
,
field
.
value
);
}
function
_get_last_cs_row_id
()
{
return
_cs_get_row_id
(
'custom_search_last_row'
);
}
function
_cs_get_row_id
(
row
)
{
var
label
=
YAHOO
.
util
.
Dom
.
getElementBy
(
function
()
{
return
true
},
'label'
,
row
);
return
parseInt
(
label
.
htmlFor
.
match
(
/
\d
+$/
)[
0
]);
}
function
_remove_any_all
(
parent
)
{
var
any_all
=
YAHOO
.
util
.
Dom
.
getElementsByClassName
(
ANY_ALL_SELECT_CLASS
,
null
,
parent
);
...
...
template/en/default/global/user-error.html.tmpl
View file @
da12cec6
...
...
@@ -1597,6 +1597,17 @@
and the "matches" search can only be used with the "content"
field.
[% ELSIF error == "search_grouped_field_invalid" %]
[% terms.Bugzilla %] does not support using the
"[%+ field_descs.$field FILTER html %]" ([% field FILTER html %])
field with grouped search conditions.
[% ELSIF error == "search_grouped_invalid_nesting" %]
You cannot nest clauses within grouped search conditions.
[% ELSIF error == "search_grouped_field_mismatch" %]
All conditions under a groups search must use the same field.
[% ELSIF error == "search_field_operator_invalid" %]
[% terms.Bugzilla %] does not support using the
"[%+ field_descs.$field FILTER html %]" ([% field FILTER html %])
...
...
template/en/default/search/boolean-charts.html.tmpl
View file @
da12cec6
...
...
@@ -64,6 +64,10 @@
<script type="text/javascript" src="[% 'js/history.js/native.history.js' FILTER mtime %]"></script>
<script type="text/javascript">
redirect_html4_browsers();
[%# These are alternative labels for the AND and OR options in and_all_select %]
var cs_and_label = 'Match ALL of the following:';
var cs_or_label = 'Match ANY of the following:';
cs_reconfigure('custom_search_last_row');
</script>
</div>
...
...
@@ -120,7 +124,8 @@
(
[% indent_level = indent_level + 1 %]
[% ELSIF condition.f == "CP" %]
<input type="hidden" name="f[% cond_num FILTER html %]" value="CP">
<input type="hidden" name="f[% cond_num FILTER html %]"
id="f[% cond_num FILTER html %]" value="CP">
)
[% ELSE %]
<select name="f[% cond_num FILTER html %]" title="Field"
...
...
@@ -164,9 +169,11 @@
<div class="any_all_select">
<select name="[% name FILTER html %]" id="[% name FILTER html %]"
onchange="fix_query_string(this)">
<option value="AND">Match ALL of the following:</option>
<option value="AND">Match ALL of the following
separately
:</option>
<option value="OR" [% ' selected="selected"' IF selected == "OR" %]>
Match ANY of the following:</option>
Match ANY of the following separately:</option>
<option value="AND_G" [% ' selected' IF selected == "AND_G" %]>
Match ALL of the following against the same field:</option>
</select>
[% IF with_advanced_link %]
<a id="custom_search_advanced_controller"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment