Bug 81185, Bug 70605 - very global Bugzilla Search optimisation. See http://wiki.4intra.net/Bugzilla-Search for details
Bug 63855 - Fix quicksearch git-svn-id: svn://svn.office.custis.ru/3rdparty/bugzilla.org/trunk@1295 6955db30-a419-402b-8a0d-67ecbb4d7f56master
parent
d0251edef1
commit
0752e18573
33
Bugzilla.pm
33
Bugzilla.pm
|
@ -690,18 +690,34 @@ sub switch_to_shadow_db {
|
|||
return $class->dbh;
|
||||
}
|
||||
|
||||
sub switch_to_main_db {
|
||||
sub switch_to_main_db
|
||||
{
|
||||
my $class = shift;
|
||||
|
||||
$class->request_cache->{dbh} = $class->dbh_main;
|
||||
return $class->dbh_main;
|
||||
}
|
||||
|
||||
sub messages
|
||||
{
|
||||
my $class = shift;
|
||||
my $lc = $class->cgi->cookie('LANG') || 'en';
|
||||
$lc =~ s/\W+//so;
|
||||
if (!$INC{'Bugzilla::Language::'.$lc})
|
||||
{
|
||||
eval { require 'Bugzilla/Language/'.$lc.'.pm' };
|
||||
if ($@)
|
||||
{
|
||||
$lc = 'en';
|
||||
require 'Bugzilla/Language/en.pm';
|
||||
}
|
||||
}
|
||||
return $Bugzilla::messages->{$lc};
|
||||
}
|
||||
|
||||
sub cache_fields
|
||||
{
|
||||
my $class = shift;
|
||||
my $rc = $class->request_cache;
|
||||
#return _fill_fields_cache($rc->{fields} ||= {});
|
||||
if (!$rc->{fields_delta_ts})
|
||||
{
|
||||
($rc->{fields_delta_ts}) = Bugzilla->dbh->selectrow_array(
|
||||
|
@ -783,7 +799,16 @@ sub get_fields
|
|||
}
|
||||
if ($sort)
|
||||
{
|
||||
@fields = sort { $a->{sortkey} <=> $b->{sortkey} } @fields;
|
||||
# Support sorting on different fields
|
||||
if ($sort eq 'name' || $sort eq 'description')
|
||||
{
|
||||
@fields = sort { $a->{$sort} cmp $b->{$sort} } @fields;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sort = 'sortkey' if $sort ne 'id';
|
||||
@fields = sort { $a->{$sort} <=> $b->{$sort} } @fields;
|
||||
}
|
||||
}
|
||||
return @fields;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ sub get_login_info {
|
|||
my ($self) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
################ return { user_id => $cgi->param('user_id') }; # hack
|
||||
|
||||
my $ip_addr = remote_ip();
|
||||
my $login_cookie = $cgi->cookie("Bugzilla_logincookie");
|
||||
|
|
|
@ -331,13 +331,13 @@ sub sql_group_by {
|
|||
|
||||
my $expression = "GROUP BY $needed_columns";
|
||||
$expression .= ", " . $optional_columns if $optional_columns;
|
||||
|
||||
|
||||
return $expression;
|
||||
}
|
||||
|
||||
sub sql_string_concat {
|
||||
my ($self, @params) = @_;
|
||||
|
||||
|
||||
return '(' . join(' || ', @params) . ')';
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,9 @@ sub bz_last_key {
|
|||
$table, $column);
|
||||
}
|
||||
|
||||
sub bz_check_regexp {
|
||||
# Check a regexp for validity
|
||||
sub bz_check_regexp
|
||||
{
|
||||
my ($self, $pattern) = @_;
|
||||
|
||||
eval { $self->do("SELECT " . $self->sql_regexp($self->quote("a"), $pattern, 1)) };
|
||||
|
|
|
@ -75,6 +75,7 @@ sub new {
|
|||
);
|
||||
|
||||
my $self = $class->db_new($dsn, $user, $pass, \%attrs);
|
||||
$self->{dbd} = 'mysql';
|
||||
|
||||
# This makes sure that if the tables are encoded as UTF-8, we
|
||||
# return their data correctly.
|
||||
|
|
|
@ -71,6 +71,7 @@ sub new {
|
|||
|| 1000 ) * 1024,
|
||||
};
|
||||
my $self = $class->db_new($dsn, $user, $pass, $attrs);
|
||||
$self->{dbd} = 'oracle';
|
||||
# Needed by TheSchwartz
|
||||
$self->{private_bz_dsn} = $dsn;
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ sub new {
|
|||
my $attrs = { pg_enable_utf8 => Bugzilla->params->{'utf8'} };
|
||||
|
||||
my $self = $class->db_new($dsn, $user, $pass, $attrs);
|
||||
$self->{dbd} = 'pg';
|
||||
|
||||
# all class local variables stored in DBI derived class needs to have
|
||||
# a prefix 'private_'. See DBI documentation.
|
||||
|
|
|
@ -192,12 +192,12 @@ use constant DEFAULT_FIELDS => (
|
|||
type => FIELD_TYPE_SINGLE_SELECT, buglist => 1},
|
||||
{name => 'component', desc => 'Component', in_new_bugmail => 1,
|
||||
buglist => 1},
|
||||
{name => 'assigned_to', desc => 'AssignedTo', in_new_bugmail => 1,
|
||||
{name => 'assigned_to', desc => 'Assignee', in_new_bugmail => 1,
|
||||
buglist => 1},
|
||||
{name => 'reporter', desc => 'ReportedBy', in_new_bugmail => 1,
|
||||
{name => 'reporter', desc => 'Reporter', in_new_bugmail => 1,
|
||||
buglist => 1},
|
||||
{name => 'votes', desc => 'Votes', buglist => 1},
|
||||
{name => 'qa_contact', desc => 'QAContact', in_new_bugmail => 1,
|
||||
{name => 'qa_contact', desc => 'QA Contact', in_new_bugmail => 1,
|
||||
buglist => 1},
|
||||
{name => 'cc', desc => 'CC', in_new_bugmail => 1},
|
||||
{name => 'dependson', desc => 'Depends on', in_new_bugmail => 1},
|
||||
|
@ -230,7 +230,7 @@ use constant DEFAULT_FIELDS => (
|
|||
{name => 'deadline', desc => 'Deadline',
|
||||
in_new_bugmail => 1, buglist => 1},
|
||||
{name => 'commenter', desc => 'Commenter'},
|
||||
{name => 'flagtypes.name', desc => 'Flags', buglist => 1},
|
||||
{name => 'flagtypes.name', desc => 'Flag Types', buglist => 1},
|
||||
{name => 'requestees.login_name', desc => 'Flag Requestee'},
|
||||
{name => 'setters.login_name', desc => 'Flag Setter'},
|
||||
{name => 'work_time', desc => 'Hours Worked', buglist => 1},
|
||||
|
@ -239,8 +239,8 @@ use constant DEFAULT_FIELDS => (
|
|||
{name => 'content', desc => 'Content'},
|
||||
{name => 'attach_data.thedata', desc => 'Attachment data'},
|
||||
{name => 'attachments.isurl', desc => 'Attachment is a URL'},
|
||||
{name => "owner_idle_time", desc => "Time Since Assignee Touched"},
|
||||
{name => 'see_also', desc => "See Also",
|
||||
{name => 'owner_idle_time', desc => 'Time Since Assignee Touched'},
|
||||
{name => 'see_also', desc => 'See Also',
|
||||
type => FIELD_TYPE_BUG_URLS},
|
||||
);
|
||||
|
||||
|
|
|
@ -53,16 +53,17 @@ use constant UPDATE_COLUMNS => qw(
|
|||
#### Accessors ######
|
||||
###############################
|
||||
|
||||
sub description { return $_[0]->{'description'}; }
|
||||
sub description { $_[0]->{description} }
|
||||
|
||||
sub bug_count {
|
||||
sub bug_count
|
||||
{
|
||||
my ($self) = @_;
|
||||
return $self->{'bug_count'} if defined $self->{'bug_count'};
|
||||
($self->{'bug_count'}) =
|
||||
Bugzilla->dbh->selectrow_array(
|
||||
'SELECT COUNT(*) FROM keywords WHERE keywordid = ?',
|
||||
undef, $self->id);
|
||||
return $self->{'bug_count'};
|
||||
return $self->{bug_count} if defined $self->{bug_count};
|
||||
($self->{bug_count}) = Bugzilla->dbh->selectrow_array(
|
||||
'SELECT COUNT(*) FROM keywords WHERE keywordid = ?',
|
||||
undef, $self->id
|
||||
);
|
||||
return $self->{bug_count};
|
||||
}
|
||||
|
||||
###############################
|
||||
|
@ -76,25 +77,20 @@ sub set_description { $_[0]->set('description', $_[1]); }
|
|||
#### Subroutines ######
|
||||
###############################
|
||||
|
||||
sub get_all_with_bug_count {
|
||||
sub get_all_with_bug_count
|
||||
{
|
||||
my $class = shift;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $keywords =
|
||||
$dbh->selectall_arrayref('SELECT ' . join(', ', DB_COLUMNS) . ',
|
||||
COUNT(keywords.bug_id) AS bug_count
|
||||
FROM keyworddefs
|
||||
LEFT JOIN keywords
|
||||
ON keyworddefs.id = keywords.keywordid ' .
|
||||
$dbh->sql_group_by('keyworddefs.id',
|
||||
'keyworddefs.name,
|
||||
keyworddefs.description') . '
|
||||
ORDER BY keyworddefs.name', {'Slice' => {}});
|
||||
if (!$keywords) {
|
||||
return [];
|
||||
}
|
||||
my $keywords = $dbh->selectall_arrayref(
|
||||
'SELECT ' . join(', ', DB_COLUMNS) . ', COUNT(keywords.bug_id) AS bug_count' .
|
||||
' FROM keyworddefs LEFT JOIN keywords ON keyworddefs.id = keywords.keywordid ' .
|
||||
$dbh->sql_group_by('keyworddefs.id', 'keyworddefs.name, keyworddefs.description') .
|
||||
' ORDER BY keyworddefs.name', {Slice => {}}
|
||||
);
|
||||
return [] unless $keywords;
|
||||
|
||||
foreach my $keyword (@$keywords) {
|
||||
bless($keyword, $class);
|
||||
bless $keyword, $class;
|
||||
}
|
||||
return $keywords;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,401 @@
|
|||
#!/usr/bin/perl
|
||||
# Internationalisation messages for English Bugzilla
|
||||
|
||||
package Bugzilla::Language::en;
|
||||
|
||||
use strict;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
my $terms = {
|
||||
bug => 'bug',
|
||||
Bug => 'Bug',
|
||||
abug => 'a bug',
|
||||
Abug => 'A bug',
|
||||
aBug => 'a Bug',
|
||||
ABug => 'A Bug',
|
||||
bugs => 'bugs',
|
||||
Bugs => 'Bugs',
|
||||
zeroSearchResults => 'Zarro Boogs found',
|
||||
Bugzilla => 'Bugzilla',
|
||||
};
|
||||
|
||||
$Bugzilla::messages->{en} = {
|
||||
terms => $terms,
|
||||
operator_descs => {
|
||||
not => 'NOT',
|
||||
noop => '---',
|
||||
equals => 'is equal to',
|
||||
notequals => 'is not equal to',
|
||||
anyexact => 'is equal to any of the strings',
|
||||
substring => 'contains the string',
|
||||
casesubstring => 'contains the string (exact case)',
|
||||
notsubstring => 'does not contain the string',
|
||||
anywordssubstr => 'contains any of the strings',
|
||||
allwordssubstr => 'contains all of the strings',
|
||||
nowordssubstr => 'contains none of the strings',
|
||||
regexp => 'matches regular expression',
|
||||
notregexp => 'does not match regular expression',
|
||||
lessthan => 'is less than',
|
||||
lessthaneq => 'is less than or equal to',
|
||||
greaterthan => 'is greater than',
|
||||
greaterthaneq => 'is greater than or equal to',
|
||||
anywords => 'contains any of the words',
|
||||
allwords => 'contains all of the words',
|
||||
nowords => 'contains none of the words',
|
||||
changedbefore => 'changed before',
|
||||
changedafter => 'changed after',
|
||||
changedfrom => 'changed from',
|
||||
changedto => 'changed to',
|
||||
changedby => 'changed by',
|
||||
matches => 'matches',
|
||||
notmatches => 'does not match',
|
||||
insearch => 'matched by saved search',
|
||||
notinsearch => 'not matched by saved search',
|
||||
},
|
||||
field_types => {
|
||||
FIELD_TYPE_UNKNOWN() => 'Unknown Type',
|
||||
FIELD_TYPE_FREETEXT() => 'Free Text',
|
||||
FIELD_TYPE_SINGLE_SELECT() => 'Drop Down',
|
||||
FIELD_TYPE_MULTI_SELECT() => 'Multiple-Selection Box',
|
||||
FIELD_TYPE_TEXTAREA() => 'Large Text Box',
|
||||
FIELD_TYPE_DATETIME() => 'Date/Time',
|
||||
FIELD_TYPE_BUG_ID() => $terms->{Bug}.' ID',
|
||||
FIELD_TYPE_NUMERIC() => 'Numeric',
|
||||
},
|
||||
field_descs => {
|
||||
actual_time => 'Actual Hours',
|
||||
alias => 'Alias',
|
||||
assigned_to => 'Assignee',
|
||||
blocked => 'Blocks',
|
||||
bug_file_loc => 'URL',
|
||||
bug_group => 'Group',
|
||||
bug_id => $terms->{Bug}.' ID',
|
||||
bug_severity => 'Severity',
|
||||
bug_status => 'Status',
|
||||
cc => 'CC',
|
||||
classification => 'Classification',
|
||||
cclist_accessible => 'CC list accessible',
|
||||
commenter => 'Commenter',
|
||||
component_id => 'Component ID',
|
||||
component => 'Component',
|
||||
content => 'Content',
|
||||
'[Bug creation]' => 'Creation date',
|
||||
opendate => 'Creation date',
|
||||
creation_ts => 'Creation date',
|
||||
deadline => 'Deadline',
|
||||
changeddate => 'Changed',
|
||||
delta_ts => 'Changed',
|
||||
dependson => 'Depends on',
|
||||
dup_id => 'Duplicate',
|
||||
estimated_time => 'Orig. Est.',
|
||||
everconfirmed => 'Ever confirmed',
|
||||
keywords => 'Keywords',
|
||||
longdesc => 'Comment',
|
||||
newcc => 'CC',
|
||||
op_sys => 'OS',
|
||||
owner_idle_time => 'Time Since Assignee Touched',
|
||||
percentage_complete => '%Complete',
|
||||
priority => 'Priority',
|
||||
product_id => 'Product ID',
|
||||
product => 'Product',
|
||||
qa_contact => 'QA Contact',
|
||||
remaining_time => 'Hours Left',
|
||||
rep_platform => 'Hardware',
|
||||
reporter => 'Reporter',
|
||||
reporter_accessible => 'Reporter accessible',
|
||||
resolution => 'Resolution',
|
||||
see_also => 'See Also',
|
||||
setting => 'Setting',
|
||||
settings => 'Settings',
|
||||
short_desc => 'Summary',
|
||||
status_whiteboard => 'Whiteboard',
|
||||
target_milestone => 'Target Milestone',
|
||||
version => 'Version',
|
||||
votes => 'Votes',
|
||||
work_time => 'Hours Worked',
|
||||
interval_time => 'Period Worktime',
|
||||
comment0 => 'First Comment',
|
||||
'longdescs.isprivate' => 'Comment is private',
|
||||
'attach_data.thedata' => 'Attachment data',
|
||||
'attachments.description' => 'Attachment description',
|
||||
'attachments.filename' => 'Attachment filename',
|
||||
'attachments.mimetype' => 'Attachment mime type',
|
||||
'attachments.ispatch' => 'Attachment is patch',
|
||||
'attachments.isobsolete' => 'Attachment is obsolete',
|
||||
'attachments.isprivate' => 'Attachment is private',
|
||||
'attachments.isurl' => 'Attachment is a URL',
|
||||
'attachments.submitter' => 'Attachment creator',
|
||||
'flagtypes.name' => 'Flags',
|
||||
'requestees.login_name' => 'Flag Requestee',
|
||||
'setters.login_name' => 'Flag Setter',
|
||||
},
|
||||
};
|
||||
|
||||
__END__
|
||||
#!/usr/bin/perl
|
||||
|
||||
package Bugzilla::Language::en;
|
||||
|
||||
use strict;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
my $terms = {
|
||||
bug => 'bug',
|
||||
Bug => 'Bug',
|
||||
abug => 'a bug',
|
||||
Abug => 'A bug',
|
||||
aBug => 'a Bug',
|
||||
ABug => 'A Bug',
|
||||
bugs => 'bugs',
|
||||
Bugs => 'Bugs',
|
||||
zeroSearchResults => 'Zarro Boogs found',
|
||||
Bugzilla => 'Bugzilla',
|
||||
};
|
||||
|
||||
$Bugzilla::messages->{en} = {
|
||||
terms => $terms,
|
||||
operator_descs => {
|
||||
not => 'NOT',
|
||||
noop => '---',
|
||||
equals => 'is equal to',
|
||||
notequals => 'is not equal to',
|
||||
anyexact => 'is equal to any of the strings',
|
||||
substring => 'contains the string',
|
||||
casesubstring => 'contains the string (exact case)',
|
||||
notsubstring => 'does not contain the string',
|
||||
anywordssubstr => 'contains any of the strings',
|
||||
allwordssubstr => 'contains all of the strings',
|
||||
nowordssubstr => 'contains none of the strings',
|
||||
regexp => 'matches regular expression',
|
||||
notregexp => 'does not match regular expression',
|
||||
lessthan => 'is less than',
|
||||
lessthaneq => 'is less than or equal to',
|
||||
greaterthan => 'is greater than',
|
||||
greaterthaneq => 'is greater than or equal to',
|
||||
anywords => 'contains any of the words',
|
||||
allwords => 'contains all of the words',
|
||||
nowords => 'contains none of the words',
|
||||
changedbefore => 'changed before',
|
||||
changedafter => 'changed after',
|
||||
changedfrom => 'changed from',
|
||||
changedto => 'changed to',
|
||||
changedby => 'changed by',
|
||||
matches => 'matches',
|
||||
notmatches => 'does not match',
|
||||
insearch => 'matched by saved search',
|
||||
notinsearch => 'not matched by saved search',
|
||||
},
|
||||
field_types => {
|
||||
FIELD_TYPE_UNKNOWN => 'Unknown Type',
|
||||
FIELD_TYPE_FREETEXT => 'Free Text',
|
||||
FIELD_TYPE_SINGLE_SELECT => 'Drop Down',
|
||||
FIELD_TYPE_MULTI_SELECT => 'Multiple-Selection Box',
|
||||
FIELD_TYPE_TEXTAREA => 'Large Text Box',
|
||||
FIELD_TYPE_DATETIME => 'Date/Time',
|
||||
FIELD_TYPE_BUG_ID => $terms->{Bug}.' ID',
|
||||
FIELD_TYPE_NUMERIC => 'Numeric',
|
||||
},
|
||||
field_descs => {
|
||||
actual_time => 'Actual Hours',
|
||||
alias => 'Alias',
|
||||
assigned_to => 'Assignee',
|
||||
blocked => 'Blocks',
|
||||
bug_file_loc => 'URL',
|
||||
bug_group => 'Group',
|
||||
bug_id => $terms->{Bug}.' ID',
|
||||
bug_severity => 'Severity',
|
||||
bug_status => 'Status',
|
||||
cc => 'CC',
|
||||
classification => 'Classification',
|
||||
cclist_accessible => 'CC list accessible',
|
||||
commenter => 'Commenter',
|
||||
component_id => 'Component ID',
|
||||
component => 'Component',
|
||||
content => 'Content',
|
||||
'[Bug creation]' => 'Creation date',
|
||||
opendate => 'Creation date',
|
||||
creation_ts => 'Creation date',
|
||||
deadline => 'Deadline',
|
||||
changeddate => 'Changed',
|
||||
delta_ts => 'Changed',
|
||||
dependson => 'Depends on',
|
||||
dup_id => 'Duplicate',
|
||||
estimated_time => 'Orig. Est.',
|
||||
everconfirmed => 'Ever confirmed',
|
||||
keywords => 'Keywords',
|
||||
longdesc => 'Comment',
|
||||
newcc => 'CC',
|
||||
op_sys => 'OS',
|
||||
owner_idle_time => 'Time Since Assignee Touched',
|
||||
percentage_complete => '%Complete',
|
||||
priority => 'Priority',
|
||||
product_id => 'Product ID',
|
||||
product => 'Product',
|
||||
qa_contact => 'QA Contact',
|
||||
remaining_time => 'Hours Left',
|
||||
rep_platform => 'Hardware',
|
||||
reporter => 'Reporter',
|
||||
reporter_accessible => 'Reporter accessible',
|
||||
resolution => 'Resolution',
|
||||
see_also => 'See Also',
|
||||
setting => 'Setting',
|
||||
settings => 'Settings',
|
||||
short_desc => 'Summary',
|
||||
status_whiteboard => 'Whiteboard',
|
||||
target_milestone => 'Target Milestone',
|
||||
version => 'Version',
|
||||
votes => 'Votes',
|
||||
work_time => 'Hours Worked',
|
||||
interval_time => 'Period Worktime',
|
||||
comment0 => 'First Comment',
|
||||
'longdescs.isprivate' => 'Comment is private',
|
||||
'attach_data.thedata' => 'Attachment data',
|
||||
'attachments.description' => 'Attachment description',
|
||||
'attachments.filename' => 'Attachment filename',
|
||||
'attachments.mimetype' => 'Attachment mime type',
|
||||
'attachments.ispatch' => 'Attachment is patch',
|
||||
'attachments.isobsolete' => 'Attachment is obsolete',
|
||||
'attachments.isprivate' => 'Attachment is private',
|
||||
'attachments.isurl' => 'Attachment is a URL',
|
||||
'attachments.submitter' => 'Attachment creator',
|
||||
'flagtypes.name' => 'Flags',
|
||||
'requestees.login_name' => 'Flag Requestee',
|
||||
'setters.login_name' => 'Flag Setter',
|
||||
},
|
||||
};
|
||||
|
||||
__END__
|
||||
#!/usr/bin/perl
|
||||
# Internationalisation messages for English Bugzilla
|
||||
|
||||
package Bugzilla::Language::en;
|
||||
|
||||
use strict;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
my $terms = {
|
||||
bug => 'bug',
|
||||
Bug => 'Bug',
|
||||
abug => 'a bug',
|
||||
Abug => 'A bug',
|
||||
aBug => 'a Bug',
|
||||
ABug => 'A Bug',
|
||||
bugs => 'bugs',
|
||||
Bugs => 'Bugs',
|
||||
zeroSearchResults => 'Zarro Boogs found',
|
||||
Bugzilla => 'Bugzilla',
|
||||
};
|
||||
|
||||
$Bugzilla::messages->{en} = {
|
||||
terms => $terms,
|
||||
operator_descs => {
|
||||
not => 'NOT',
|
||||
noop => '---',
|
||||
equals => 'is equal to',
|
||||
notequals => 'is not equal to',
|
||||
anyexact => 'is equal to any of the strings',
|
||||
substring => 'contains the string',
|
||||
casesubstring => 'contains the string (exact case)',
|
||||
notsubstring => 'does not contain the string',
|
||||
anywordssubstr => 'contains any of the strings',
|
||||
allwordssubstr => 'contains all of the strings',
|
||||
nowordssubstr => 'contains none of the strings',
|
||||
regexp => 'matches regular expression',
|
||||
notregexp => 'does not match regular expression',
|
||||
lessthan => 'is less than',
|
||||
lessthaneq => 'is less than or equal to',
|
||||
greaterthan => 'is greater than',
|
||||
greaterthaneq => 'is greater than or equal to',
|
||||
anywords => 'contains any of the words',
|
||||
allwords => 'contains all of the words',
|
||||
nowords => 'contains none of the words',
|
||||
changedbefore => 'changed before',
|
||||
changedafter => 'changed after',
|
||||
changedfrom => 'changed from',
|
||||
changedto => 'changed to',
|
||||
changedby => 'changed by',
|
||||
matches => 'matches',
|
||||
notmatches => 'does not match',
|
||||
insearch => 'matched by saved search',
|
||||
notinsearch => 'not matched by saved search',
|
||||
},
|
||||
field_types => {
|
||||
FIELD_TYPE_UNKNOWN() => 'Unknown Type',
|
||||
FIELD_TYPE_FREETEXT() => 'Free Text',
|
||||
FIELD_TYPE_SINGLE_SELECT() => 'Drop Down',
|
||||
FIELD_TYPE_MULTI_SELECT() => 'Multiple-Selection Box',
|
||||
FIELD_TYPE_TEXTAREA() => 'Large Text Box',
|
||||
FIELD_TYPE_DATETIME() => 'Date/Time',
|
||||
FIELD_TYPE_BUG_ID() => $terms->{Bug}.' ID',
|
||||
FIELD_TYPE_NUMERIC() => 'Numeric',
|
||||
},
|
||||
field_descs => {
|
||||
actual_time => 'Actual Hours',
|
||||
alias => 'Alias',
|
||||
assigned_to => 'Assignee',
|
||||
blocked => 'Blocks',
|
||||
bug_file_loc => 'URL',
|
||||
bug_group => 'Group',
|
||||
bug_id => $terms->{Bug}.' ID',
|
||||
bug_severity => 'Severity',
|
||||
bug_status => 'Status',
|
||||
cc => 'CC',
|
||||
classification => 'Classification',
|
||||
cclist_accessible => 'CC list accessible',
|
||||
commenter => 'Commenter',
|
||||
component_id => 'Component ID',
|
||||
component => 'Component',
|
||||
content => 'Content',
|
||||
'[Bug creation]' => 'Creation date',
|
||||
opendate => 'Creation date',
|
||||
creation_ts => 'Creation date',
|
||||
deadline => 'Deadline',
|
||||
changeddate => 'Changed',
|
||||
delta_ts => 'Changed',
|
||||
dependson => 'Depends on',
|
||||
dup_id => 'Duplicate',
|
||||
estimated_time => 'Orig. Est.',
|
||||
everconfirmed => 'Ever confirmed',
|
||||
keywords => 'Keywords',
|
||||
longdesc => 'Comment',
|
||||
newcc => 'CC',
|
||||
op_sys => 'OS',
|
||||
owner_idle_time => 'Time Since Assignee Touched',
|
||||
percentage_complete => '%Complete',
|
||||
priority => 'Priority',
|
||||
product_id => 'Product ID',
|
||||
product => 'Product',
|
||||
qa_contact => 'QA Contact',
|
||||
remaining_time => 'Hours Left',
|
||||
rep_platform => 'Hardware',
|
||||
reporter => 'Reporter',
|
||||
reporter_accessible => 'Reporter accessible',
|
||||
resolution => 'Resolution',
|
||||
see_also => 'See Also',
|
||||
setting => 'Setting',
|
||||
settings => 'Settings',
|
||||
short_desc => 'Summary',
|
||||
status_whiteboard => 'Whiteboard',
|
||||
target_milestone => 'Target Milestone',
|
||||
version => 'Version',
|
||||
votes => 'Votes',
|
||||
work_time => 'Hours Worked',
|
||||
interval_time => 'Period Worktime',
|
||||
comment0 => 'First Comment',
|
||||
'longdescs.isprivate' => 'Comment is private',
|
||||
'attach_data.thedata' => 'Attachment data',
|
||||
'attachments.description' => 'Attachment description',
|
||||
'attachments.filename' => 'Attachment filename',
|
||||
'attachments.mimetype' => 'Attachment mime type',
|
||||
'attachments.ispatch' => 'Attachment is patch',
|
||||
'attachments.isobsolete' => 'Attachment is obsolete',
|
||||
'attachments.isprivate' => 'Attachment is private',
|
||||
'attachments.isurl' => 'Attachment is a URL',
|
||||
'attachments.submitter' => 'Attachment creator',
|
||||
'flagtypes.name' => 'Flags',
|
||||
'requestees.login_name' => 'Flag Requestee',
|
||||
'setters.login_name' => 'Flag Setter',
|
||||
},
|
||||
};
|
||||
|
||||
__END__
|
|
@ -88,8 +88,8 @@ sub _init {
|
|||
$sql = "$id_field = ?";
|
||||
@values = ($id);
|
||||
} else {
|
||||
unless (defined $param->{name} || (defined $param->{'condition'}
|
||||
&& defined $param->{'values'}))
|
||||
unless (defined $param->{name} || (defined $param->{condition}
|
||||
&& defined $param->{values}))
|
||||
{
|
||||
ThrowCodeError('bad_arg', { argument => 'param',
|
||||
function => $class . '::new',
|
||||
|
@ -100,14 +100,14 @@ sub _init {
|
|||
$sql = $dbh->sql_istrcmp($name_field, '?');
|
||||
push(@values, $param->{name});
|
||||
}
|
||||
elsif (defined $param->{'condition'} && defined $param->{'values'}) {
|
||||
elsif (defined $param->{condition} && defined $param->{values}) {
|
||||
caller->isa('Bugzilla::Object')
|
||||
|| ThrowCodeError('protection_violation',
|
||||
{ caller => caller,
|
||||
function => $class . '::new',
|
||||
argument => 'condition/values' });
|
||||
$sql = $param->{'condition'};
|
||||
push(@values, @{$param->{'values'}});
|
||||
$sql = $param->{condition};
|
||||
push(@values, @{$param->{values}});
|
||||
}
|
||||
|
||||
map { trick_taint($_) } @values;
|
||||
|
|
4139
Bugzilla/Search.pm
4139
Bugzilla/Search.pm
File diff suppressed because it is too large
Load Diff
|
@ -526,7 +526,7 @@ sub _special_field_syntax {
|
|||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _default_quicksearch_word {
|
||||
|
|
|
@ -306,7 +306,7 @@ sub quoteUrls {
|
|||
# we have to do this in one pattern, and so this is semi-messy.
|
||||
# Also, we can't use $bug_re?$comment_re? because that will match the
|
||||
# empty string
|
||||
my $bug_word = template_var('terms')->{bug};
|
||||
my $bug_word = Bugzilla->messages->{terms}->{bug};
|
||||
my $bug_re = qr/\Q$bug_word\E\s*\#?\s*(\d+)/i;
|
||||
my $comment_re = qr/comment\s*\#?\s*(\d+)/i;
|
||||
$text =~ s~\b($bug_re(?:\s*,?\s*$comment_re)?|$comment_re)
|
||||
|
@ -802,6 +802,35 @@ sub create {
|
|||
|
||||
# Default variables for all templates
|
||||
VARIABLES => {
|
||||
terms => Bugzilla->messages->{terms},
|
||||
field_descs => Bugzilla->messages->{terms},
|
||||
lc_messages => Bugzilla->messages,
|
||||
|
||||
# HTML <select>
|
||||
html_select => sub
|
||||
{
|
||||
my ($name, $values, $valuenames, $selected, $args) = @_;
|
||||
$name = html_quote($name);
|
||||
my $html = '<select name="'.$name.'" id="'.$name.'">';
|
||||
if (ref $valuenames eq 'ARRAY')
|
||||
{
|
||||
$values = [ map { $_->{name} } @$valuenames ];
|
||||
$valuenames = { map { $_->{name} => $_->{title} } @$valuenames };
|
||||
}
|
||||
else
|
||||
{
|
||||
$values ||= [ keys %$valuenames ];
|
||||
}
|
||||
for (@$values)
|
||||
{
|
||||
$html .= '<option value="'.html_quote($_).'"';
|
||||
$html .= ' selected="selected"' if $selected eq $_;
|
||||
$html .= '>'.html_quote($valuenames->{$_}).'</option>';
|
||||
}
|
||||
$html .= '</select>';
|
||||
return $html;
|
||||
},
|
||||
|
||||
# Function for retrieving global parameters.
|
||||
'Param' => sub { return Bugzilla->params->{$_[0]}; },
|
||||
|
||||
|
@ -891,11 +920,6 @@ sub create {
|
|||
|
||||
'feature_enabled' => sub { return Bugzilla->feature(@_); },
|
||||
|
||||
# field_descs can be somewhat slow to generate, so we generate
|
||||
# it only once per-language no matter how many times
|
||||
# $template->process() is called.
|
||||
'field_descs' => sub { return template_var('field_descs') },
|
||||
|
||||
'install_string' => \&Bugzilla::Install::Util::install_string,
|
||||
|
||||
# These don't work as normal constants.
|
||||
|
|
|
@ -1534,6 +1534,7 @@ sub wants_bug_mail {
|
|||
|
||||
# You role is new if the bug itself is.
|
||||
# Only makes sense for the assignee, QA contact and the CC list.
|
||||
# FIXME Это неудобно, потому что неочевидно для пользователя!
|
||||
if ($relationship == REL_ASSIGNEE
|
||||
|| $relationship == REL_QA
|
||||
|| $relationship == REL_CC)
|
||||
|
|
|
@ -32,24 +32,21 @@ use utf8;
|
|||
use strict;
|
||||
|
||||
use base qw(Exporter);
|
||||
@Bugzilla::Util::EXPORT = qw(trick_taint detaint_natural
|
||||
trick_taint_copy
|
||||
detaint_signed
|
||||
html_quote url_quote xml_quote
|
||||
css_class_quote html_light_quote url_decode
|
||||
i_am_cgi correct_urlbase remote_ip
|
||||
lsearch do_ssl_redirect_if_required use_attachbase
|
||||
diff_arrays
|
||||
trim wrap_hard wrap_comment find_wrap_point
|
||||
format_time format_time_decimal validate_date
|
||||
validate_time datetime_from
|
||||
file_mod_time is_7bit_clean
|
||||
bz_crypt generate_random_password
|
||||
validate_email_syntax clean_text
|
||||
stem_text
|
||||
intersect
|
||||
get_text template_var disable_utf8 bz_encode_json
|
||||
xml_element xml_element_quote xml_dump_simple);
|
||||
@Bugzilla::Util::EXPORT = qw(
|
||||
trick_taint detaint_natural trick_taint_copy detaint_signed
|
||||
html_quote url_quote xml_quote css_class_quote html_light_quote url_decode
|
||||
i_am_cgi correct_urlbase remote_ip lsearch
|
||||
do_ssl_redirect_if_required use_attachbase
|
||||
diff_arrays list
|
||||
trim wrap_hard wrap_comment find_wrap_point
|
||||
format_time format_time_decimal validate_date validate_time datetime_from
|
||||
file_mod_time is_7bit_clean
|
||||
bz_crypt generate_random_password
|
||||
validate_email_syntax clean_text
|
||||
stem_text intersect
|
||||
get_text disable_utf8 bz_encode_json
|
||||
xml_element xml_element_quote xml_dump_simple
|
||||
);
|
||||
|
||||
use Bugzilla::Constants;
|
||||
|
||||
|
@ -707,21 +704,21 @@ sub clean_text {
|
|||
return trim($dtext);
|
||||
}
|
||||
|
||||
# Довольно некрасивый хак для бага см.ниже - на багах с длинным числом комментов
|
||||
# quoteUrls вызывает на каждый коммент get_text('term', { term => 'bug' }),
|
||||
# что приводит к ужасной производительности. например, на баге с 703
|
||||
# комментами в 10-15 раз ухудшение по сравнению с Bugzilla 2.x.
|
||||
# Избавляемся от этого.
|
||||
# CustIS Bug 40933 ФАКМОЙМОЗГ! ВРОТМНЕНОГИ! КТО ТАК ПИШЕТ?!!!!
|
||||
# ВОТ он, антипаттерн разработки на TT, ведущий к тормозам...
|
||||
# ALSO CustIS Bug 52322
|
||||
sub get_text {
|
||||
# FUCKMYBRAIN! CustIS Bugs 40933, 52322.
|
||||
# Here is the Template Toolkit development anti-pattern!
|
||||
# Originally, Bugzilla used to call get_text('term', { term => 'bug' })
|
||||
# from quoteUrls() for each comment. This leaded to TERRIBLE performance
|
||||
# on "long" bugs compared to Bugzilla 2.x!
|
||||
|
||||
sub get_text
|
||||
{
|
||||
my ($name, $vars) = @_;
|
||||
my $template = Bugzilla->template_inner;
|
||||
$vars ||= {};
|
||||
$vars->{'message'} = $name;
|
||||
$vars->{message} = $name;
|
||||
my $message;
|
||||
if (!$template->process('global/message.txt.tmpl', $vars, \$message)) {
|
||||
if (!$template->process('global/message.txt.tmpl', $vars, \$message))
|
||||
{
|
||||
require Bugzilla::Error;
|
||||
Bugzilla::Error::ThrowTemplateError($template->error());
|
||||
}
|
||||
|
@ -730,27 +727,6 @@ sub get_text {
|
|||
return $message;
|
||||
}
|
||||
|
||||
sub template_var {
|
||||
my $name = shift;
|
||||
my $cache = Bugzilla->request_cache->{util_template_var} ||= {};
|
||||
my $template = Bugzilla->template_inner;
|
||||
my $lang = Bugzilla->request_cache->{language};
|
||||
return $cache->{$lang}->{$name} if defined $cache->{$lang};
|
||||
my %vars;
|
||||
# Note: If we suddenly start needing a lot of template_var variables,
|
||||
# they should move into their own template, not field-descs.
|
||||
my $output;
|
||||
my $result = $template->process('global/field-descs.none.tmpl',
|
||||
{ vars => \%vars, in_template_var => 1 }, \$output);
|
||||
# Bugzilla::Error can't be "use"d in Bugzilla::Util.
|
||||
if (!$result) {
|
||||
require Bugzilla::Error;
|
||||
Bugzilla::Error::ThrowTemplateError($template->error);
|
||||
}
|
||||
$cache->{$lang} = \%vars;
|
||||
return $vars{$name};
|
||||
}
|
||||
|
||||
sub disable_utf8 {
|
||||
if (Bugzilla->params->{'utf8'}) {
|
||||
binmode STDOUT, ':bytes'; # Turn off UTF8 encoding.
|
||||
|
@ -872,8 +848,15 @@ sub bz_encode_json
|
|||
return $var;
|
||||
}
|
||||
|
||||
1;
|
||||
sub list($)
|
||||
{
|
||||
my ($array) = @_;
|
||||
return () unless defined $array;
|
||||
return ($array) if ref $array ne 'ARRAY';
|
||||
return @$array;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
@ -1147,14 +1130,6 @@ A string.
|
|||
|
||||
=back
|
||||
|
||||
|
||||
=item C<template_var>
|
||||
|
||||
This is a method of getting the value of a variable from a template in
|
||||
Perl code. The available variables are in the C<global/field-descs.none.tmpl>
|
||||
template. Just pass in the name of the variable that you want the value of.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
=head2 Formatting Time
|
||||
|
|
|
@ -584,7 +584,7 @@ sub insert {
|
|||
|
||||
# Operation result to save into session (CustIS Bug 64562)
|
||||
my $session_data = {
|
||||
title => "Attachment ".$attachment->id." added to ".template_var('terms')->{Bug}." ".$attachment->bug_id,
|
||||
title => "Attachment ".$attachment->id." added to ".Bugzilla->messages->{terms}->{Bug}." ".$attachment->bug_id,
|
||||
sent => [$send_results],
|
||||
sent_attrs => {
|
||||
added_attachments => [ {
|
||||
|
|
136
buglist.cgi
136
buglist.cgi
|
@ -801,70 +801,68 @@ if (!$order || $order =~ /^reuse/i) {
|
|||
}
|
||||
}
|
||||
|
||||
if ($order) {
|
||||
# FIXME переместить в Bugzilla::Search
|
||||
my $old_orders = {
|
||||
'' => 'bug_status,priority,assigned_to,bug_id', # Default
|
||||
'bug number' => 'bug_id',
|
||||
'importance' => 'priority,bug_severity,bug_id',
|
||||
'assignee' => 'assigned_to,bug_status,priority,bug_id',
|
||||
'last changed' => 'delta_ts,bug_status,priority,assigned_to,bug_id',
|
||||
};
|
||||
if ($order)
|
||||
{
|
||||
# Convert the value of the "order" form field into a list of columns
|
||||
# by which to sort the results.
|
||||
ORDER: for ($order) {
|
||||
/^Bug Number$/ && do {
|
||||
$order = "bug_id";
|
||||
last ORDER;
|
||||
};
|
||||
/^Importance$/ && do {
|
||||
$order = "priority,bug_severity";
|
||||
last ORDER;
|
||||
};
|
||||
/^Assignee$/ && do {
|
||||
$order = "assigned_to,bug_status,priority,bug_id";
|
||||
last ORDER;
|
||||
};
|
||||
/^Last Changed$/ && do {
|
||||
$order = "delta_ts,bug_status,priority,assigned_to,bug_id";
|
||||
last ORDER;
|
||||
};
|
||||
do {
|
||||
my (@order, @invalid_fragments);
|
||||
if ($old_orders->{lc $order})
|
||||
{
|
||||
$order = $old_orders->{lc $order};
|
||||
}
|
||||
else
|
||||
{
|
||||
my (@order, @invalid_fragments);
|
||||
|
||||
# A custom list of columns. Make sure each column is valid.
|
||||
foreach my $fragment (split(/,/, $order)) {
|
||||
$fragment = trim($fragment);
|
||||
next unless $fragment;
|
||||
my ($column_name, $direction) = split_order_term($fragment);
|
||||
$column_name = translate_old_column($column_name);
|
||||
# A custom list of columns. Make sure each column is valid.
|
||||
foreach my $fragment (split(/,/, $order))
|
||||
{
|
||||
$fragment = trim($fragment);
|
||||
next unless $fragment;
|
||||
my ($column_name, $direction) = split_order_term($fragment);
|
||||
$column_name = translate_old_column($column_name);
|
||||
|
||||
# Special handlings for certain columns
|
||||
next if $column_name eq 'relevance' && !$fulltext;
|
||||
# Special handlings for certain columns
|
||||
next if $column_name eq 'relevance' && !$fulltext;
|
||||
|
||||
# If we are sorting by votes, sort in descending order if
|
||||
# no explicit sort order was given.
|
||||
if ($column_name eq 'votes' && !$direction) {
|
||||
$direction = "DESC";
|
||||
}
|
||||
|
||||
if (exists $columns->{$column_name}) {
|
||||
$direction = " $direction" if $direction;
|
||||
push(@order, "$column_name$direction");
|
||||
}
|
||||
else {
|
||||
push(@invalid_fragments, $fragment);
|
||||
}
|
||||
}
|
||||
if (scalar @invalid_fragments) {
|
||||
$vars->{'message'} = 'invalid_column_name';
|
||||
$vars->{'invalid_fragments'} = \@invalid_fragments;
|
||||
# If we are sorting by votes, sort in descending order if
|
||||
# no explicit sort order was given.
|
||||
if ($column_name eq 'votes' && !$direction)
|
||||
{
|
||||
$direction = "DESC";
|
||||
}
|
||||
|
||||
$order = join(",", @order);
|
||||
# Now that we have checked that all columns in the order are valid,
|
||||
# detaint the order string.
|
||||
trick_taint($order) if $order;
|
||||
};
|
||||
if (exists $columns->{$column_name})
|
||||
{
|
||||
$direction = " $direction" if $direction;
|
||||
push @order, "$column_name$direction";
|
||||
}
|
||||
else
|
||||
{
|
||||
push @invalid_fragments, $fragment;
|
||||
}
|
||||
}
|
||||
if (scalar @invalid_fragments)
|
||||
{
|
||||
$vars->{message} = 'invalid_column_name';
|
||||
$vars->{invalid_fragments} = \@invalid_fragments;
|
||||
}
|
||||
|
||||
$order = join(",", @order);
|
||||
# Now that we have checked that all columns in the order are valid,
|
||||
# detaint the order string.
|
||||
trick_taint($order) if $order;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$order) {
|
||||
# DEFAULT
|
||||
$order = "bug_status,priority,assigned_to,bug_id";
|
||||
}
|
||||
$order = $old_orders->{''} if !$order;
|
||||
|
||||
my @orderstrings = split(/,\s*/, $order);
|
||||
|
||||
|
@ -882,7 +880,7 @@ my $search = new Bugzilla::Search('fields' => \@selectcolumns,
|
|||
'params' => $params,
|
||||
'order' => \@orderstrings);
|
||||
my $query = $search->getSQL();
|
||||
$vars->{'search_description'} = $search->search_description;
|
||||
$vars->{search_description} = $search->search_description_html;
|
||||
|
||||
if (defined $cgi->param('limit')) {
|
||||
my $limit = $cgi->param('limit');
|
||||
|
@ -1131,7 +1129,7 @@ $vars->{'order_dir'} = [ map { s/ DESC$// ? 1 : 0 } @{$vars->{'order_columns'}}
|
|||
$vars->{'caneditbugs'} = 1;
|
||||
$vars->{'time_info'} = $time_info;
|
||||
|
||||
$vars->{query_params} = $params->Vars; # now used only in superworktime
|
||||
$vars->{query_params} = { %{ $params->Vars } }; # now used only in superworktime
|
||||
$vars->{query_params}->{chfieldfrom} = $Bugzilla::Search::interval_from;
|
||||
$vars->{query_params}->{chfieldto} = $Bugzilla::Search::interval_to;
|
||||
|
||||
|
@ -1203,9 +1201,7 @@ if ($dotweak && scalar @bugs) {
|
|||
|
||||
# Convert bug statuses to their ID.
|
||||
my @bug_statuses = map {$dbh->quote($_)} keys %$bugstatuses;
|
||||
my $bug_status_ids =
|
||||
$dbh->selectcol_arrayref('SELECT id FROM bug_status
|
||||
WHERE ' . $dbh->sql_in('value', \@bug_statuses));
|
||||
my $bug_status_ids = $dbh->selectcol_arrayref('SELECT id FROM bug_status WHERE ' . $dbh->sql_in('value', \@bug_statuses));
|
||||
|
||||
# This query collects new statuses which are common to all current bug statuses.
|
||||
# It also accepts transitions where the bug status doesn't change.
|
||||
|
@ -1244,11 +1240,29 @@ if ($dotweak && scalar @bugs) {
|
|||
|
||||
# If we're editing a stored query, use the existing query name as default for
|
||||
# the "Remember search as" field.
|
||||
$vars->{'defaultsavename'} = $cgi->param('query_based_on');
|
||||
$vars->{'query_sql_time'} = sprintf("%.2f", $query_sql_time);
|
||||
$vars->{defaultsavename} = $cgi->param('query_based_on');
|
||||
$vars->{query_sql_time} = sprintf("%.2f", $query_sql_time);
|
||||
|
||||
Bugzilla::Hook::process('after-buglist', { vars => $vars });
|
||||
|
||||
$vars->{abbrev} = {
|
||||
bug_severity => { maxlength => 3, title => "Sev" },
|
||||
priority => { maxlength => 3, title => "Pri" },
|
||||
rep_platform => { maxlength => 3, title => "Plt" },
|
||||
bug_status => { maxlength => 4 },
|
||||
assigned_to => { maxlength => 30, ellipsis => "..." },
|
||||
reporter => { maxlength => 30, ellipsis => "..." },
|
||||
qa_contact => { maxlength => 30, ellipsis => "..." },
|
||||
resolution => { maxlength => 4 },
|
||||
short_short_desc => { maxlength => 60, ellipsis => "..." },
|
||||
status_whiteboard => { title => "Whiteboard" },
|
||||
component => { maxlength => 8, title => "Comp" },
|
||||
product => { maxlength => 8 },
|
||||
op_sys => { maxlength => 4 },
|
||||
target_milestone => { title => "Milestone" },
|
||||
percentage_complete => { format_value => "%d %%" },
|
||||
};
|
||||
|
||||
################################################################################
|
||||
# HTTP Header Generation
|
||||
################################################################################
|
||||
|
|
|
@ -16,7 +16,7 @@ use Bugzilla::Token;
|
|||
my $template = Bugzilla->template;
|
||||
my $user = Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $params = $cgi->Vars;
|
||||
my $params = { %{ $cgi->Vars } };
|
||||
my $vars = {};
|
||||
|
||||
$user->in_group('bz_editcheckers')
|
||||
|
|
|
@ -41,22 +41,25 @@ my $token = $cgi->param('token');
|
|||
|
||||
$cgi->send_header();
|
||||
|
||||
$vars->{field_types} = Bugzilla->messages->{field_types};
|
||||
# List all existing custom fields if no action is given.
|
||||
if (!$action) {
|
||||
if (!$action)
|
||||
{
|
||||
$template->process('admin/custom_fields/list.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
# Interface to add a new custom field.
|
||||
elsif ($action eq 'add') {
|
||||
$vars->{'token'} = issue_session_token('add_field');
|
||||
|
||||
elsif ($action eq 'add')
|
||||
{
|
||||
$vars->{token} = issue_session_token('add_field');
|
||||
$template->process('admin/custom_fields/create.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
elsif ($action eq 'new') {
|
||||
elsif ($action eq 'new')
|
||||
{
|
||||
check_token_data($token, 'add_field');
|
||||
|
||||
my $field = $vars->{'field'} = Bugzilla::Field->create({
|
||||
my $field = $vars->{field} = Bugzilla::Field->create({
|
||||
name => scalar $cgi->param('name'),
|
||||
description => scalar $cgi->param('desc'),
|
||||
type => scalar $cgi->param('type'),
|
||||
|
@ -80,7 +83,8 @@ elsif ($action eq 'new') {
|
|||
$template->process('admin/custom_fields/list.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
elsif ($action eq 'edit') {
|
||||
elsif ($action eq 'edit')
|
||||
{
|
||||
my $name = $cgi->param('name') || ThrowUserError('field_missing_name');
|
||||
my $field = Bugzilla->get_field($name);
|
||||
$field || ThrowUserError('customfield_nonexistent', {'name' => $name});
|
||||
|
@ -91,7 +95,8 @@ elsif ($action eq 'edit') {
|
|||
$template->process('admin/custom_fields/edit.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
elsif ($action eq 'update') {
|
||||
elsif ($action eq 'update')
|
||||
{
|
||||
check_token_data($token, 'edit_field');
|
||||
my $name = $cgi->param('name');
|
||||
|
||||
|
@ -125,7 +130,8 @@ elsif ($action eq 'update') {
|
|||
$template->process('admin/custom_fields/list.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
elsif ($action eq 'del') {
|
||||
elsif ($action eq 'del')
|
||||
{
|
||||
my $name = $cgi->param('name');
|
||||
|
||||
# Validate field.
|
||||
|
@ -144,7 +150,8 @@ elsif ($action eq 'del') {
|
|||
$template->process('admin/custom_fields/confirm-delete.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
elsif ($action eq 'delete') {
|
||||
elsif ($action eq 'delete')
|
||||
{
|
||||
check_token_data($token, 'delete_field');
|
||||
my $name = $cgi->param('name');
|
||||
|
||||
|
@ -161,15 +168,16 @@ elsif ($action eq 'delete') {
|
|||
# Calling remove_from_db will check if field can be deleted.
|
||||
# If the field cannot be deleted, it will throw an error.
|
||||
$field->remove_from_db();
|
||||
|
||||
|
||||
$vars->{'field'} = $field;
|
||||
$vars->{'message'} = 'custom_field_deleted';
|
||||
|
||||
|
||||
delete_token($token);
|
||||
|
||||
$template->process('admin/custom_fields/list.html.tmpl', $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
ThrowUserError('no_valid_action', {'field' => 'custom_field'});
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ if (@categoryActions = grep(/^categoryAction-.+/, $cgi->param())) {
|
|||
exit;
|
||||
}
|
||||
|
||||
if ($action eq 'list') { list(); }
|
||||
if ($action eq 'list') { ft_list(); }
|
||||
elsif ($action eq 'enter') { edit($action); }
|
||||
elsif ($action eq 'copy') { edit($action); }
|
||||
elsif ($action eq 'edit') { edit($action); }
|
||||
|
@ -95,7 +95,7 @@ exit;
|
|||
# Functions
|
||||
################################################################################
|
||||
|
||||
sub list {
|
||||
sub ft_list {
|
||||
my $product = validateProduct(scalar $cgi->param('product'));
|
||||
my $component = validateComponent($product, scalar $cgi->param('component'));
|
||||
my $product_id = $product ? $product->id : 0;
|
||||
|
|
|
@ -398,19 +398,6 @@ CardDropTarget.prototype.onMove = function(pos)
|
|||
else
|
||||
this.element.style.borderRight = '5px solid red';
|
||||
};
|
||||
// Универсальное добавление обработчика события
|
||||
var addListener = function() {
|
||||
if (window.addEventListener) {
|
||||
return function(el, type, fn) { el.addEventListener(type, fn, false); };
|
||||
} else if (window.attachEvent) {
|
||||
return function(el, type, fn) {
|
||||
var f = function() { return fn.call(el, window.event); };
|
||||
el.attachEvent('on'+type, f);
|
||||
};
|
||||
} else {
|
||||
return function(el, type, fn) { element['on'+type] = fn; }
|
||||
}
|
||||
}();
|
||||
// 2 если hash пуст
|
||||
// 1 если в нём один ключ key
|
||||
// 0 если в нём есть ключ, не равный key
|
||||
|
|
|
@ -6,6 +6,7 @@ use strict;
|
|||
use base qw(Bugzilla::Object Exporter);
|
||||
|
||||
use JSON;
|
||||
use Bugzilla::Search;
|
||||
use Bugzilla::Search::Saved;
|
||||
use Bugzilla::Error;
|
||||
|
||||
|
@ -77,9 +78,12 @@ sub refresh_sql
|
|||
fields => [ 'bug_id' ],
|
||||
user => Bugzilla::User->super_user,
|
||||
);
|
||||
my $sql = $search->getSQL();
|
||||
$sql =~ s/ORDER\s+BY.*?$//iso;
|
||||
$sql =~ s/^\s*SELECT.*?FROM//iso;
|
||||
my $terms = Bugzilla::Search::simplify_expression([
|
||||
'AND_MANY', { term => 'bugs.bug_id=?' },
|
||||
$search->{terms_without_security}
|
||||
]);
|
||||
my $sql = $search->get_expression_sql($terms);
|
||||
$sql =~ s/^\s*SELECT.*?FROM/SELECT $self->{id} FROM/;
|
||||
$self->set_sql_code($sql);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/perl
|
||||
# CustIS Bug 68921 - "Предикаты проверки корректности"
|
||||
# - Задаётся сохранённый запрос поиска.
|
||||
# - Принимается что баги, соответствующие (или НЕ соответствующие) этому запросу
|
||||
# - Принимается, что баги, соответствующие (или НЕ соответствующие) этому запросу
|
||||
# до (или после) любых изменений - некорректные, и надо выдать предупреждение или ошибку.
|
||||
# - Выставляется флажок, можно ли всё-таки оставлять комментарии без рабочего времени.
|
||||
|
||||
|
@ -56,8 +56,6 @@ sub check
|
|||
if (($_->flags & $mask) == $flags)
|
||||
{
|
||||
$s = $_->sql_code;
|
||||
$i = $_->id;
|
||||
$s =~ s/^(.*)(GROUP\s+BY)/SELECT $i id FROM $1 AND bugs.bug_id=? $2/iso;
|
||||
push @$sql, $s;
|
||||
push @bind, $bug_id;
|
||||
}
|
||||
|
@ -256,7 +254,14 @@ sub savedsearch_post_update
|
|||
sub install_before_final_checks
|
||||
{
|
||||
Bugzilla->request_cache->{user} = Bugzilla::User->super_user;
|
||||
eval { $_->update } for Bugzilla::Checker->get_all;
|
||||
for (Bugzilla::Checker->get_all)
|
||||
{
|
||||
eval { $_->update };
|
||||
if ($@)
|
||||
{
|
||||
warn $@;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,48 +13,13 @@ sub buglist_static_columns
|
|||
my $columns = $args->{columns};
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
$columns->{dependson} = {
|
||||
name => "(SELECT ".$dbh->sql_group_concat('bugblockers.dependson', "','")." FROM dependencies bugblockers WHERE bugblockers.blocked=bugs.bug_id)",
|
||||
title => "Bug dependencies",
|
||||
};
|
||||
|
||||
$columns->{blocked} = {
|
||||
name => "(SELECT ".$dbh->sql_group_concat('bugblocked.blocked', "','")." FROM dependencies bugblocked WHERE bugblocked.dependson=bugs.bug_id)",
|
||||
title => "Bugs blocked",
|
||||
};
|
||||
|
||||
$columns->{flags} = {
|
||||
name =>
|
||||
"(SELECT ".$dbh->sql_group_concat($dbh->sql_string_concat('col_ft.name', 'col_f.status'), "', '")."
|
||||
FROM flags col_f JOIN flagtypes col_ft ON col_f.type_id=col_ft.id
|
||||
WHERE col_f.bug_id=bugs.bug_id AND (col_ft.is_requesteeble=0 OR col_ft.is_requestable=0))",
|
||||
title => "Flags",
|
||||
};
|
||||
|
||||
$columns->{requests} = {
|
||||
name =>
|
||||
"(SELECT ".
|
||||
$dbh->sql_group_concat(
|
||||
$dbh->sql_string_concat(
|
||||
'col_ft.name', 'col_f.status',
|
||||
'CASE WHEN col_p.login_name IS NULL THEN \'\' ELSE '.
|
||||
$dbh->sql_string_concat("' '", 'col_p.login_name').' END'
|
||||
), "', '"
|
||||
)."
|
||||
FROM flags col_f JOIN flagtypes col_ft ON col_f.type_id=col_ft.id
|
||||
LEFT JOIN profiles col_p ON col_f.requestee_id=col_p.userid
|
||||
WHERE col_f.bug_id=bugs.bug_id AND col_ft.is_requesteeble=1 AND col_ft.is_requestable=1)",
|
||||
title => "Requests",
|
||||
};
|
||||
|
||||
# CustIS Bug 68921 (see also Bugzilla::Search)
|
||||
$columns->{interval_time} = { %{$columns->{work_time}} };
|
||||
$columns->{interval_time}->{title} = 'Period worktime';
|
||||
|
||||
# CustIS Bug 71955 - first comment to the bug
|
||||
$columns->{comment0} = {
|
||||
title => "First Comment",
|
||||
};
|
||||
$columns->{lastcommenter} = {
|
||||
title => "Last Commenter",
|
||||
};
|
||||
|
||||
### Testopia ###
|
||||
$columns->{test_cases} = {
|
||||
|
@ -83,9 +48,28 @@ sub buglist_columns
|
|||
my $columns = $args->{columns};
|
||||
|
||||
# CustIS Bug 71955 - first comment to the bug
|
||||
# FIXME можно сделать JOIN'ом по bug_when=creation_ts
|
||||
# но тогда дополнительно надо COALESCE на подзапрос с isprivate
|
||||
# в случае isprivate.
|
||||
my $hint = '';
|
||||
my $dbh = Bugzilla->dbh;
|
||||
if ($dbh->isa('Bugzilla::DB::Mysql'))
|
||||
{
|
||||
$hint = ' FORCE INDEX (longdescs_bug_id_idx)';
|
||||
}
|
||||
my $priv = (Bugzilla->user->is_insider ? "" : "AND ldc0.isprivate=0 ");
|
||||
$columns->{comment0}->{name} =
|
||||
"(SELECT thetext FROM longdescs ldc0 WHERE ldc0.bug_id = bugs.bug_id ".
|
||||
(Bugzilla->user->is_insider ? "" : "AND ldc0.isprivate=0 ")." ORDER BY ldc0.bug_when LIMIT 1)";
|
||||
"(SELECT thetext FROM longdescs ldc0$hint WHERE ldc0.bug_id = bugs.bug_id $priv".
|
||||
" ORDER BY ldc0.bug_when LIMIT 1)";
|
||||
my $login = 'ldp0.login_name';
|
||||
if (!Bugzilla->user->id)
|
||||
{
|
||||
$login = $dbh->sql_string_until($login, $dbh->quote('@'));
|
||||
}
|
||||
$columns->{lastcommenter}->{name} =
|
||||
"(SELECT $login FROM longdescs ldc0$hint".
|
||||
" INNER JOIN profiles ldp0 ON ldp0.userid=ldc0.who WHERE ldc0.bug_id = bugs.bug_id $priv".
|
||||
" ORDER BY ldc0.bug_when DESC LIMIT 1)";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
[% PROCESS "global/field-descs.none.tmpl" %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
title = 'Изменения не удовлетворяют проверкам' %]
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ package Testopia::Table;
|
|||
use strict;
|
||||
|
||||
use Bugzilla;
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Util qw(!list);
|
||||
use Bugzilla::Error;
|
||||
use Testopia::Util;
|
||||
use Testopia::TestCase;
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Admin Settings for Testopia" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
|
||||
title = "Search by Attachment Number"
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
|
||||
title = "Search by Test Case Number"
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
[%# Testopia Test Case list CSV export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
||||
[% PROCESS testopia/export/csv.caseheader.tmpl %]
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
[%# Testopia Test Case CSV export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% USE date %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#%]
|
||||
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
[%# Testopia Show Test Case XML export template #%]
|
||||
|
||||
[% IF NOT header_done %]
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/export/xml.header.tmpl %]
|
||||
[% END %]
|
||||
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
# Contributor(s): Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
||||
[% FOREACH column = displaycolumns %]
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Create New Test Run Environment" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
|
||||
title = "Search by Test Run Environment Number"
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Delete Environment $environment.name" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Export Environment XML" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Import XML Environment" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Test Environments" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
[%# Testopia Test Case CSV row export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
||||
[% FOREACH column = displaycolumns %]
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
[%# Testopia Test Case CSV column header export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
||||
[% FOREACH column = displaycolumns %]
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
[%# Testopia Test Case XML export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
<testcase author="[% case.author.email FILTER xml %]" priority="[% case.priority FILTER xml %]" automated="[% case.isautomated ? "Automatic" : "Manual" FILTER xml %]" status="[% case.status FILTER xml %]">
|
||||
[% IF case.text.action %]
|
||||
<action>[% case.text.action FILTER replace('<','&testopia_lt;') FILTER replace('>','&testopia_gt;') %]</action>
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
# Contributor(s): Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
[%# PROCESS testopia/style.none.tmpl %]
|
||||
[%# PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[%# title = "Test Plan History for Plan $plan.id: $plan.name" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
# Contributor(s): Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/export/xml.header.tmpl %]
|
||||
[% SET header_done = 1 %]
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
[%# Testopia Test Case list CSV export template #%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
|
||||
[% PROCESS testopia/export/csv.caseheader.tmpl %]
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
[%# Testopia Test Case list XML export template #%]
|
||||
[% IF NOT header_done %]
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/export/xml.header.tmpl %]
|
||||
[% SET header_done = 1 %]
|
||||
[% END %]
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
# Contributor(s): Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/search/variables.none.tmpl %]
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Test run report - Bugs severity status" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Test run report - Bugs detected" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Build Coverage Report for Plan $plan.id: $plan.name" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -19,12 +19,8 @@
|
|||
# Contributor(s): Gervase Markham <gerv@gerv.net>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% y_label = report.type %]
|
||||
|
||||
[% PROCESS "global/field-descs.none.tmpl" %]
|
||||
|
||||
[% col_field_disp = field_descs.$col_field || col_field %]
|
||||
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
# tbl: Name of a hash in data which is the table to be plotted.
|
||||
#%]
|
||||
|
||||
[% PROCESS "global/field-descs.none.tmpl" %]
|
||||
|
||||
[% col_field_disp = field_descs.$col_field || report.col_field %]
|
||||
[% row_field_disp = field_descs.$row_field || report.row_field %]
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
[%# INTERFACE:
|
||||
# See report-table.html.tmpl.
|
||||
#%]
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% colsepchar = user.settings.csv_colsepchar.value %]
|
||||
[% num_bugs = BLOCK %]Number of [% terms.bugs %][% END %]
|
||||
[% tbl_field_disp = field_descs.$tbl_field || report.tbl_field %]
|
||||
|
|
|
@ -46,8 +46,6 @@
|
|||
[% report.row_field = "" %]
|
||||
[% END %]
|
||||
|
||||
[% PROCESS "global/field-descs.none.tmpl" %]
|
||||
|
||||
[% tbl_field_disp = field_descs.$report.tbl_field || report.tbl_field %]
|
||||
[% col_field_disp = field_descs.$report.col_field || report.col_field %]
|
||||
[% row_field_disp = field_descs.$report.row_field || report.row_field %]
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
[%# Template Initialization #%]
|
||||
[%############################################################################%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% title = "Test run report - Test burnout chart" %]
|
||||
|
||||
[%############################################################################%]
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% title = "Create a New Test Run" %]
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
# Greg Hendricks <ghendricks@novell.com>
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
|
||||
[% PROCESS global/header.html.tmpl
|
||||
|
||||
title = "Search by Test Run Number"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
# ...
|
||||
#%]
|
||||
|
||||
[% PROCESS global/variables.none.tmpl %]
|
||||
[% PROCESS testopia/style.none.tmpl %]
|
||||
[% PROCESS testopia/blocks.html.tmpl %]
|
||||
|
||||
|
|
|
@ -18,24 +18,24 @@
|
|||
# Contributor(s): Ed Fuentetaja <efuentetaja@acm.org>
|
||||
#%]
|
||||
[%
|
||||
debug_ext = Param('testopia-debug') == 'ON'
|
||||
? "extensions/testopia/extjs/ext-all-debug.js"
|
||||
debug_ext = Param('testopia-debug') == 'ON'
|
||||
? "extensions/testopia/extjs/ext-all-debug.js"
|
||||
: "extensions/testopia/extjs/ext-all.js"
|
||||
|
||||
|
||||
debug_ext_base = Param('testopia-debug') == 'ON'
|
||||
? "extensions/testopia/extjs/adapter/ext/ext-base-debug.js"
|
||||
: "extensions/testopia/extjs/adapter/ext/ext-base.js"
|
||||
|
||||
debug_testopia = Param('testopia-debug') == 'ON'
|
||||
|
||||
debug_testopia = Param('testopia-debug') == 'ON'
|
||||
? "extensions/testopia/testopia.all.js" : "extensions/testopia/testopia.all.ycomp.js"
|
||||
|
||||
|
||||
style_urls = ["extensions/testopia/extjs/resources/css/ext-all.css",
|
||||
"extensions/testopia/extjs/examples/ux/css/xtheme-gray-extend.css",
|
||||
"extensions/testopia/extjs/examples/grid/grid-examples.css"]
|
||||
%]
|
||||
[% IF Param('testopia-debug') == 'Developer' %]
|
||||
[% IF Param('testopia-debug') == 'Developer' %]
|
||||
[% javascript_urls = [
|
||||
|
||||
|
||||
"extensions/testopia/extjs/adapter/ext/ext-base-debug.js",
|
||||
"extensions/testopia/extjs/ext-all-debug.js",
|
||||
"extensions/testopia/extjs/examples/ux/RowEditor.js",
|
||||
|
|
|
@ -11,7 +11,7 @@ use Bugzilla;
|
|||
use Bugzilla::Util;
|
||||
use Bugzilla::Constants;
|
||||
|
||||
my $args = Bugzilla->cgi->Vars;
|
||||
my $args = { %{ Bugzilla->cgi->Vars } };
|
||||
my $user = Bugzilla->login(~LOGIN_REQUIRED);
|
||||
|
||||
my $ctype = 'text/javascript'.(Bugzilla->params->{utf8} ? '; charset=utf-8' : '');
|
||||
|
|
|
@ -41,7 +41,7 @@ sub add_wt
|
|||
|
||||
# Read buglist from query params
|
||||
my @idlist;
|
||||
my $args = $cgi->Vars;
|
||||
my $args = { %{ $cgi->Vars } };
|
||||
foreach (keys %$args)
|
||||
{
|
||||
if (/^wtime_(\d+)/)
|
||||
|
|
|
@ -20,7 +20,7 @@ use JSON;
|
|||
my $gc_prob = 0.01;
|
||||
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $args = $cgi->Vars;
|
||||
my $args = { %{ $cgi->Vars } };
|
||||
my $check = $args->{ga_check} ? 1 : 0; # если 1 и пользователь не вошёл, входа не требовать
|
||||
|
||||
# требуем входа, если пришёл пользователь (в запросе нет ключа) и в запросе не сказано "не требовать входа"
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 48 B |
|
@ -88,10 +88,8 @@ for (keys %$args)
|
|||
$vars->{bug_tpl} = $bug_tpl;
|
||||
$vars->{name_tr} = $name_tr;
|
||||
|
||||
# FIXME переделать на стандарт
|
||||
# нужно всосать из шаблонов field_descs...
|
||||
# и несколько поменять... ;-/ поганый хак, конечно, а чё делать-то.
|
||||
my $field_descs = { %{ template_var('field_descs') } };
|
||||
# FIXME переделать на стандартные описания полей, берущиеся из базы
|
||||
my $field_descs = { %{ Bugzilla->messages->{field_descs} } };
|
||||
$field_descs->{platform} = $field_descs->{rep_platform};
|
||||
$field_descs->{comment} = $field_descs->{longdesc};
|
||||
for ((grep { /\./ } keys %$field_descs),
|
||||
|
|
129
js/TUI.js
129
js/TUI.js
|
@ -1,26 +1,5 @@
|
|||
/**
|
||||
* FIXME: Kill this and YUI, and replace with jQuery completely
|
||||
*/
|
||||
|
||||
/* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Bugzilla Bug Tracking System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Dennis Melentyev <dennis.melentyev@infopulse.com.ua>
|
||||
* Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
/* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
|
||||
/* This file provides JavaScript functions to be included when one wishes
|
||||
|
@ -29,14 +8,13 @@
|
|||
*
|
||||
* TUI stands for Tweak UI.
|
||||
*
|
||||
* Requires js/util.js and the YUI Dom and Cookie libraries.
|
||||
* Rewritten without YAHOO UI, requires just js/util.js.
|
||||
*
|
||||
* See template/en/default/bug/create/create.html.tmpl for a usage example.
|
||||
*/
|
||||
|
||||
var TUI_HIDDEN_CLASS = 'bz_tui_hidden';
|
||||
var TUI_COOKIE_NAME = 'TUI';
|
||||
|
||||
var TUI_COOKIE_NAME = 'TUI';
|
||||
var TUI_alternates = new Array();
|
||||
|
||||
/**
|
||||
|
@ -46,67 +24,92 @@ var TUI_alternates = new Array();
|
|||
*
|
||||
* @param className The name of the CSS class to hide.
|
||||
*/
|
||||
function TUI_toggle_class(className) {
|
||||
var elements = YAHOO.util.Dom.getElementsByClassName(className);
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
bz_toggleClass(elements[i], TUI_HIDDEN_CLASS);
|
||||
}
|
||||
_TUI_save_class_state(elements, className);
|
||||
_TUI_toggle_control_link(className);
|
||||
function TUI_toggle_class(className)
|
||||
{
|
||||
var hidden = toggleRule('tui_css', '.'+className, 'display: none !important');
|
||||
TUI_store(className, hidden ? '' : '1');
|
||||
TUI_toggle_control_link(className);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that a certain class of items should be hidden by default,
|
||||
* if the user doesn't have a TUI cookie.
|
||||
*
|
||||
*
|
||||
* @param className The class to hide by default.
|
||||
*/
|
||||
function TUI_hide_default(className) {
|
||||
YAHOO.util.Event.onDOMReady(function () {
|
||||
if (!YAHOO.util.Cookie.getSub('TUI', className)) {
|
||||
function TUI_hide_default(className)
|
||||
{
|
||||
addListener(window, 'load', function() {
|
||||
if (!getCookieHash(TUI_COOKIE_NAME)[className])
|
||||
TUI_toggle_class(className);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function _TUI_toggle_control_link(className) {
|
||||
function TUI_toggle_control_link(className)
|
||||
{
|
||||
var link = document.getElementById(className + "_controller");
|
||||
var original_text = link.innerHTML;
|
||||
link.innerHTML = TUI_alternates[className];
|
||||
TUI_alternates[className] = original_text;
|
||||
}
|
||||
|
||||
function _TUI_save_class_state(elements, aClass) {
|
||||
// We just check the first element to see if it's hidden or not, and
|
||||
// consider that all elements are the same.
|
||||
if (YAHOO.util.Dom.hasClass(elements[0], TUI_HIDDEN_CLASS)) {
|
||||
_TUI_store(aClass, 0);
|
||||
}
|
||||
else {
|
||||
_TUI_store(aClass, 1);
|
||||
function getCookieHash(name)
|
||||
{
|
||||
var c = getCookie(name)||'';
|
||||
c = c.split('&');
|
||||
var h = {};
|
||||
var t;
|
||||
for (var i = 0; i < c.length; i++)
|
||||
{
|
||||
t = c[i].split('=', 2);
|
||||
if (t[0].length)
|
||||
h[t[0]] = t[1];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
function _TUI_store(aClass, state) {
|
||||
YAHOO.util.Cookie.setSub(TUI_COOKIE_NAME, aClass, state,
|
||||
{
|
||||
function TUI_store(aClass, state)
|
||||
{
|
||||
var h = getCookieHash(TUI_COOKIE_NAME);
|
||||
h[aClass] = state;
|
||||
var c = [];
|
||||
for (var i in h)
|
||||
c.push(i+'='+h[i]);
|
||||
c = c.join('&');
|
||||
setCookie(TUI_COOKIE_NAME, c, {
|
||||
expires: new Date('January 1, 2038'),
|
||||
path: BUGZILLA.param.cookie_path
|
||||
path: BUGZILLA.param.cookiepath
|
||||
});
|
||||
}
|
||||
|
||||
function _TUI_restore() {
|
||||
var classes = YAHOO.util.Cookie.getSubs(TUI_COOKIE_NAME);
|
||||
for (item in classes) {
|
||||
if (classes[item] == 0) {
|
||||
var elements = YAHOO.util.Dom.getElementsByClassName(item);
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
YAHOO.util.Dom.addClass(elements[i], 'bz_tui_hidden');
|
||||
}
|
||||
_TUI_toggle_control_link(item);
|
||||
function toggleRule(css_id, target, rule)
|
||||
{
|
||||
var s;
|
||||
if (!(s = document.getElementById(css_id)))
|
||||
{
|
||||
s = document.createElement('style');
|
||||
document.getElementsByTagName('head')[0].appendChild(s);
|
||||
s.setAttribute('id', css_id);
|
||||
}
|
||||
ss = s.sheet||s;
|
||||
var f = false;
|
||||
var r = ss.rules||ss.cssRules;
|
||||
for (var i = r.length-1; i >= 0; i--)
|
||||
{
|
||||
if (r[i].selectorText == target)
|
||||
{
|
||||
if (ss.removeRule)
|
||||
ss.removeRule(i);
|
||||
else
|
||||
ss.deleteRule(i);
|
||||
f = true;
|
||||
}
|
||||
}
|
||||
if (f)
|
||||
return false;
|
||||
if (ss.addRule)
|
||||
ss.addRule(target, rule);
|
||||
else
|
||||
s.appendChild(document.createTextNode(target+' { '+rule+' }'));
|
||||
return true;
|
||||
}
|
||||
|
||||
YAHOO.util.Event.onDOMReady(_TUI_restore);
|
||||
|
|
452
js/attachment.js
452
js/attachment.js
|
@ -23,210 +23,211 @@
|
|||
|
||||
function switch_aft(n)
|
||||
{
|
||||
var f = document.getElementById('form_type_file'+n);
|
||||
var u = document.getElementById('form_type_url'+n);
|
||||
var t = document.getElementById('form_type_text'+n);
|
||||
document.getElementById('tr_file'+n).style.display = f && f.checked ? '' : 'none';
|
||||
document.getElementById('tr_text'+n).style.display = t && t.checked ? '' : 'none';
|
||||
if (u)
|
||||
document.getElementById('tr_url'+n).style.display = u.checked ? '' : 'none';
|
||||
var f = document.getElementById('form_type_file'+n);
|
||||
var u = document.getElementById('form_type_url'+n);
|
||||
var t = document.getElementById('form_type_text'+n);
|
||||
document.getElementById('tr_file'+n).style.display = f && f.checked ? '' : 'none';
|
||||
document.getElementById('tr_text'+n).style.display = t && t.checked ? '' : 'none';
|
||||
if (u)
|
||||
document.getElementById('tr_url'+n).style.display = u.checked ? '' : 'none';
|
||||
}
|
||||
|
||||
function validateAttachmentForm(theform) {
|
||||
var desc_value = YAHOO.lang.trim(theform.description.value);
|
||||
if (desc_value == '') {
|
||||
alert(BUGZILLA.string.attach_desc_required);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
function validateAttachmentForm(theform)
|
||||
{
|
||||
var desc = theform.description.value.replace(/^\s+|\s+$/, '');
|
||||
if (desc == '')
|
||||
{
|
||||
alert(BUGZILLA.string.attach_desc_required);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function updateCommentPrivacy(checkbox)
|
||||
{
|
||||
var text_elem = document.getElementById('comment');
|
||||
if (checkbox.checked) {
|
||||
text_elem.className='bz_private';
|
||||
} else {
|
||||
text_elem.className='';
|
||||
}
|
||||
var text_elem = document.getElementById('comment');
|
||||
if (checkbox.checked)
|
||||
text_elem.className = 'bz_private';
|
||||
else
|
||||
text_elem.className = '';
|
||||
}
|
||||
|
||||
function URLFieldHandler()
|
||||
{
|
||||
var field_attachurl = document.getElementById("attachurl");
|
||||
var greyfields = [
|
||||
"data", "ispatch", "autodetect",
|
||||
"list", "manual", "bigfile",
|
||||
"contenttypeselection",
|
||||
"contenttypeentry"
|
||||
];
|
||||
var i, thisfield;
|
||||
if (field_attachurl.value.match(/^\s*$/)) {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.removeAttribute("disabled");
|
||||
var field_attachurl = document.getElementById("attachurl");
|
||||
var greyfields = [
|
||||
"data", "ispatch", "autodetect",
|
||||
"list", "manual", "bigfile",
|
||||
"contenttypeselection",
|
||||
"contenttypeentry"
|
||||
];
|
||||
var i, thisfield;
|
||||
if (field_attachurl.value.match(/^\s*$/)) {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.removeAttribute("disabled");
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DataFieldHandler(AllowAttachUrl)
|
||||
{
|
||||
var field_data = document.getElementById("data");
|
||||
var fd_empty = field_data.value.match(/^\s*$/);
|
||||
var field_description = document.getElementById("description");
|
||||
if (!field_description._changed && !fd_empty)
|
||||
{
|
||||
l = field_data.value.lastIndexOf('/')+1;
|
||||
lw = field_data.value.lastIndexOf('\\')+1;
|
||||
if (lw > l)
|
||||
l = lw;
|
||||
field_description.value = field_data.value.substr(l);
|
||||
}
|
||||
if (!AllowAttachUrl)
|
||||
return;
|
||||
var greyfields = new Array("attachurl");
|
||||
var i, thisfield;
|
||||
if (fd_empty) {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.removeAttribute("disabled");
|
||||
var field_data = document.getElementById("data");
|
||||
var fd_empty = field_data.value.match(/^\s*$/);
|
||||
var field_description = document.getElementById("description");
|
||||
if (!field_description._changed && !fd_empty)
|
||||
{
|
||||
l = field_data.value.lastIndexOf('/')+1;
|
||||
lw = field_data.value.lastIndexOf('\\')+1;
|
||||
if (lw > l)
|
||||
l = lw;
|
||||
field_description.value = field_data.value.substr(l);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.setAttribute("disabled", "disabled");
|
||||
if (!AllowAttachUrl)
|
||||
return;
|
||||
var greyfields = new Array("attachurl");
|
||||
var i, thisfield;
|
||||
if (fd_empty) {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.removeAttribute("disabled");
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < greyfields.length; i++) {
|
||||
thisfield = document.getElementById(greyfields[i]);
|
||||
if (thisfield)
|
||||
thisfield.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearAttachmentFields() {
|
||||
var element;
|
||||
var element;
|
||||
|
||||
document.getElementById('data').value = '';
|
||||
DataFieldHandler();
|
||||
if ((element = document.getElementById('bigfile')))
|
||||
element.checked = '';
|
||||
if ((element = document.getElementById('attachurl'))) {
|
||||
element.value = '';
|
||||
URLFieldHandler();
|
||||
}
|
||||
document.getElementById('description').value = '';
|
||||
/* Fire onchange so that the disabled state of the content-type
|
||||
* radio buttons are also reset
|
||||
*/
|
||||
element = document.getElementById('ispatch');
|
||||
element.checked = '';
|
||||
bz_fireEvent(element, 'change');
|
||||
if ((element = document.getElementById('isprivate')))
|
||||
document.getElementById('data').value = '';
|
||||
DataFieldHandler();
|
||||
if ((element = document.getElementById('bigfile')))
|
||||
element.checked = '';
|
||||
if ((element = document.getElementById('attachurl'))) {
|
||||
element.value = '';
|
||||
URLFieldHandler();
|
||||
}
|
||||
document.getElementById('description').value = '';
|
||||
/* Fire onchange so that the disabled state of the content-type
|
||||
* radio buttons are also reset
|
||||
*/
|
||||
element = document.getElementById('ispatch');
|
||||
element.checked = '';
|
||||
bz_fireEvent(element, 'change');
|
||||
if ((element = document.getElementById('isprivate')))
|
||||
element.checked = '';
|
||||
}
|
||||
|
||||
/* Functions used when viewing patches in Diff mode. */
|
||||
|
||||
function collapse_all() {
|
||||
var elem = document.checkboxform.firstChild;
|
||||
while (elem != null) {
|
||||
if (elem.firstChild != null) {
|
||||
var tbody = elem.firstChild.nextSibling;
|
||||
if (tbody.className == 'file') {
|
||||
tbody.className = 'file_collapse';
|
||||
twisty = get_twisty_from_tbody(tbody);
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
twisty.nextSibling.checked = false;
|
||||
}
|
||||
var elem = document.checkboxform.firstChild;
|
||||
while (elem != null) {
|
||||
if (elem.firstChild != null) {
|
||||
var tbody = elem.firstChild.nextSibling;
|
||||
if (tbody.className == 'file') {
|
||||
tbody.className = 'file_collapse';
|
||||
twisty = get_twisty_from_tbody(tbody);
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
twisty.nextSibling.checked = false;
|
||||
}
|
||||
}
|
||||
elem = elem.nextSibling;
|
||||
}
|
||||
elem = elem.nextSibling;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function expand_all() {
|
||||
var elem = document.checkboxform.firstChild;
|
||||
while (elem != null) {
|
||||
if (elem.firstChild != null) {
|
||||
var tbody = elem.firstChild.nextSibling;
|
||||
if (tbody.className == 'file_collapse') {
|
||||
tbody.className = 'file';
|
||||
twisty = get_twisty_from_tbody(tbody);
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
twisty.nextSibling.checked = true;
|
||||
}
|
||||
var elem = document.checkboxform.firstChild;
|
||||
while (elem != null) {
|
||||
if (elem.firstChild != null) {
|
||||
var tbody = elem.firstChild.nextSibling;
|
||||
if (tbody.className == 'file_collapse') {
|
||||
tbody.className = 'file';
|
||||
twisty = get_twisty_from_tbody(tbody);
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
twisty.nextSibling.checked = true;
|
||||
}
|
||||
}
|
||||
elem = elem.nextSibling;
|
||||
}
|
||||
elem = elem.nextSibling;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
var current_restore_elem;
|
||||
|
||||
function restore_all() {
|
||||
current_restore_elem = null;
|
||||
incremental_restore();
|
||||
current_restore_elem = null;
|
||||
incremental_restore();
|
||||
}
|
||||
|
||||
function incremental_restore() {
|
||||
if (!document.checkboxform.restore_indicator.checked) {
|
||||
return;
|
||||
}
|
||||
var next_restore_elem;
|
||||
if (current_restore_elem) {
|
||||
next_restore_elem = current_restore_elem.nextSibling;
|
||||
} else {
|
||||
next_restore_elem = document.checkboxform.firstChild;
|
||||
}
|
||||
while (next_restore_elem != null) {
|
||||
current_restore_elem = next_restore_elem;
|
||||
if (current_restore_elem.firstChild != null) {
|
||||
restore_elem(current_restore_elem.firstChild.nextSibling);
|
||||
if (!document.checkboxform.restore_indicator.checked) {
|
||||
return;
|
||||
}
|
||||
var next_restore_elem;
|
||||
if (current_restore_elem) {
|
||||
next_restore_elem = current_restore_elem.nextSibling;
|
||||
} else {
|
||||
next_restore_elem = document.checkboxform.firstChild;
|
||||
}
|
||||
while (next_restore_elem != null) {
|
||||
current_restore_elem = next_restore_elem;
|
||||
if (current_restore_elem.firstChild != null) {
|
||||
restore_elem(current_restore_elem.firstChild.nextSibling);
|
||||
}
|
||||
next_restore_elem = current_restore_elem.nextSibling;
|
||||
}
|
||||
next_restore_elem = current_restore_elem.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
function restore_elem(elem, alertme) {
|
||||
if (elem.className == 'file_collapse') {
|
||||
twisty = get_twisty_from_tbody(elem);
|
||||
if (twisty.nextSibling.checked) {
|
||||
elem.className = 'file';
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
if (elem.className == 'file_collapse') {
|
||||
twisty = get_twisty_from_tbody(elem);
|
||||
if (twisty.nextSibling.checked) {
|
||||
elem.className = 'file';
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
}
|
||||
} else if (elem.className == 'file') {
|
||||
twisty = get_twisty_from_tbody(elem);
|
||||
if (!twisty.nextSibling.checked) {
|
||||
elem.className = 'file_collapse';
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
}
|
||||
}
|
||||
} else if (elem.className == 'file') {
|
||||
twisty = get_twisty_from_tbody(elem);
|
||||
if (!twisty.nextSibling.checked) {
|
||||
elem.className = 'file_collapse';
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function twisty_click(twisty) {
|
||||
tbody = get_tbody_from_twisty(twisty);
|
||||
if (tbody.className == 'file') {
|
||||
tbody.className = 'file_collapse';
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
twisty.nextSibling.checked = false;
|
||||
} else {
|
||||
tbody.className = 'file';
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
twisty.nextSibling.checked = true;
|
||||
}
|
||||
return false;
|
||||
tbody = get_tbody_from_twisty(twisty);
|
||||
if (tbody.className == 'file') {
|
||||
tbody.className = 'file_collapse';
|
||||
twisty.firstChild.nodeValue = '(+)';
|
||||
twisty.nextSibling.checked = false;
|
||||
} else {
|
||||
tbody.className = 'file';
|
||||
twisty.firstChild.nodeValue = '(-)';
|
||||
twisty.nextSibling.checked = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_tbody_from_twisty(twisty) {
|
||||
return twisty.parentNode.parentNode.parentNode.nextSibling;
|
||||
return twisty.parentNode.parentNode.parentNode.nextSibling;
|
||||
}
|
||||
function get_twisty_from_tbody(tbody) {
|
||||
return tbody.previousSibling.firstChild.nextSibling.firstChild.firstChild;
|
||||
return tbody.previousSibling.firstChild.nextSibling.firstChild.firstChild;
|
||||
}
|
||||
|
||||
var prev_mode = 'raw';
|
||||
|
@ -235,115 +236,116 @@ var has_edited = 0;
|
|||
var has_viewed_as_diff = 0;
|
||||
function editAsComment(patchviewerinstalled)
|
||||
{
|
||||
switchToMode('edit', patchviewerinstalled);
|
||||
has_edited = 1;
|
||||
switchToMode('edit', patchviewerinstalled);
|
||||
has_edited = 1;
|
||||
}
|
||||
function undoEditAsComment(patchviewerinstalled)
|
||||
{
|
||||
switchToMode(prev_mode, patchviewerinstalled);
|
||||
switchToMode(prev_mode, patchviewerinstalled);
|
||||
}
|
||||
function redoEditAsComment(patchviewerinstalled)
|
||||
{
|
||||
switchToMode('edit', patchviewerinstalled);
|
||||
switchToMode('edit', patchviewerinstalled);
|
||||
}
|
||||
|
||||
function viewDiff(attachment_id, patchviewerinstalled)
|
||||
{
|
||||
switchToMode('diff', patchviewerinstalled);
|
||||
switchToMode('diff', patchviewerinstalled);
|
||||
|
||||
// If we have not viewed as diff before, set the view diff frame URL
|
||||
if (!has_viewed_as_diff) {
|
||||
var viewDiffFrame = document.getElementById('viewDiffFrame');
|
||||
viewDiffFrame.src =
|
||||
'attachment.cgi?id=' + attachment_id + '&action=diff&headers=0';
|
||||
has_viewed_as_diff = 1;
|
||||
}
|
||||
// If we have not viewed as diff before, set the view diff frame URL
|
||||
if (!has_viewed_as_diff) {
|
||||
var viewDiffFrame = document.getElementById('viewDiffFrame');
|
||||
viewDiffFrame.src =
|
||||
'attachment.cgi?id=' + attachment_id + '&action=diff&headers=0';
|
||||
has_viewed_as_diff = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function viewRaw(patchviewerinstalled)
|
||||
{
|
||||
switchToMode('raw', patchviewerinstalled);
|
||||
switchToMode('raw', patchviewerinstalled);
|
||||
}
|
||||
|
||||
function switchToMode(mode, patchviewerinstalled)
|
||||
{
|
||||
if (mode == current_mode) {
|
||||
alert('switched to same mode! This should not happen.');
|
||||
return;
|
||||
}
|
||||
if (mode == current_mode)
|
||||
{
|
||||
alert('switched to same mode! This should not happen.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch out of current mode
|
||||
if (current_mode == 'edit') {
|
||||
hideElementById('editFrame');
|
||||
hideElementById('undoEditButton');
|
||||
} else if (current_mode == 'raw') {
|
||||
hideElementById('viewFrame');
|
||||
if (patchviewerinstalled)
|
||||
hideElementById('viewDiffButton');
|
||||
hideElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
hideElementById('smallCommentFrame');
|
||||
} else if (current_mode == 'diff') {
|
||||
if (patchviewerinstalled)
|
||||
hideElementById('viewDiffFrame');
|
||||
hideElementById('viewRawButton');
|
||||
hideElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
hideElementById('smallCommentFrame');
|
||||
}
|
||||
// Switch out of current mode
|
||||
if (current_mode == 'edit') {
|
||||
hideElementById('editFrame');
|
||||
hideElementById('undoEditButton');
|
||||
} else if (current_mode == 'raw') {
|
||||
hideElementById('viewFrame');
|
||||
if (patchviewerinstalled)
|
||||
hideElementById('viewDiffButton');
|
||||
hideElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
hideElementById('smallCommentFrame');
|
||||
} else if (current_mode == 'diff') {
|
||||
if (patchviewerinstalled)
|
||||
hideElementById('viewDiffFrame');
|
||||
hideElementById('viewRawButton');
|
||||
hideElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
hideElementById('smallCommentFrame');
|
||||
}
|
||||
|
||||
// Switch into new mode
|
||||
if (mode == 'edit') {
|
||||
showElementById('editFrame');
|
||||
showElementById('undoEditButton');
|
||||
} else if (mode == 'raw') {
|
||||
showElementById('viewFrame');
|
||||
if (patchviewerinstalled)
|
||||
showElementById('viewDiffButton');
|
||||
// Switch into new mode
|
||||
if (mode == 'edit') {
|
||||
showElementById('editFrame');
|
||||
showElementById('undoEditButton');
|
||||
} else if (mode == 'raw') {
|
||||
showElementById('viewFrame');
|
||||
if (patchviewerinstalled)
|
||||
showElementById('viewDiffButton');
|
||||
|
||||
showElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
showElementById('smallCommentFrame');
|
||||
} else if (mode == 'diff') {
|
||||
if (patchviewerinstalled)
|
||||
showElementById('viewDiffFrame');
|
||||
showElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
showElementById('smallCommentFrame');
|
||||
} else if (mode == 'diff') {
|
||||
if (patchviewerinstalled)
|
||||
showElementById('viewDiffFrame');
|
||||
|
||||
showElementById('viewRawButton');
|
||||
showElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
showElementById('smallCommentFrame');
|
||||
}
|
||||
showElementById('viewRawButton');
|
||||
showElementById(has_edited ? 'redoEditButton' : 'editButton');
|
||||
showElementById('smallCommentFrame');
|
||||
}
|
||||
|
||||
prev_mode = current_mode;
|
||||
current_mode = mode;
|
||||
prev_mode = current_mode;
|
||||
current_mode = mode;
|
||||
}
|
||||
|
||||
function hideElementById(id)
|
||||
{
|
||||
var elm = document.getElementById(id);
|
||||
if (elm) {
|
||||
elm.style.display = 'none';
|
||||
}
|
||||
var elm = document.getElementById(id);
|
||||
if (elm) {
|
||||
elm.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function showElementById(id, val)
|
||||
{
|
||||
var elm = document.getElementById(id);
|
||||
if (elm) {
|
||||
if (!val) val = 'inline';
|
||||
elm.style.display = val;
|
||||
}
|
||||
var elm = document.getElementById(id);
|
||||
if (elm) {
|
||||
if (!val) val = 'inline';
|
||||
elm.style.display = val;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeComments()
|
||||
{
|
||||
// Remove the unused comment field from the document so its contents
|
||||
// do not get transmitted back to the server.
|
||||
// Remove the unused comment field from the document so its contents
|
||||
// do not get transmitted back to the server.
|
||||
|
||||
var small = document.getElementById('smallCommentFrame');
|
||||
var big = document.getElementById('editFrame');
|
||||
if ( (small) && (small.style.display == 'none') )
|
||||
{
|
||||
small.parentNode.removeChild(small);
|
||||
}
|
||||
if ( (big) && (big.style.display == 'none') )
|
||||
{
|
||||
big.parentNode.removeChild(big);
|
||||
}
|
||||
var small = document.getElementById('smallCommentFrame');
|
||||
var big = document.getElementById('editFrame');
|
||||
if ( (small) && (small.style.display == 'none') )
|
||||
{
|
||||
small.parentNode.removeChild(small);
|
||||
}
|
||||
if ( (big) && (big.style.display == 'none') )
|
||||
{
|
||||
big.parentNode.removeChild(big);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
YAHOO.util.Event.addListener(window, 'load', initControlledFields);
|
||||
/* Functions used to show/hide dependent bug fields and change their select options
|
||||
* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
|
||||
addListener(window, 'load', initControlledFields);
|
||||
|
||||
function initControlledFields()
|
||||
{
|
||||
|
@ -9,7 +14,8 @@ function initControlledFields()
|
|||
function initControlledField(i)
|
||||
{
|
||||
var f = document.getElementById(i);
|
||||
YAHOO.util.Event.addListener(f, 'change', handleControllerField, f);
|
||||
if (f)
|
||||
addListener(f, 'change', handleControllerField_this);
|
||||
}
|
||||
|
||||
function getSelectedIds(sel)
|
||||
|
@ -27,6 +33,11 @@ function getSelectedIds(sel)
|
|||
return opt;
|
||||
}
|
||||
|
||||
function handleControllerField_this(e)
|
||||
{
|
||||
return handleControllerField(e, this);
|
||||
}
|
||||
|
||||
function handleControllerField(e, controller)
|
||||
{
|
||||
var vis, label_container, field_container, id;
|
||||
|
@ -46,13 +57,13 @@ function handleControllerField(e, controller)
|
|||
field_container = document.getElementById('field_container_' + controlled_id);
|
||||
if (vis)
|
||||
{
|
||||
YAHOO.util.Dom.removeClass(label_container, 'bz_hidden_field');
|
||||
YAHOO.util.Dom.removeClass(field_container, 'bz_hidden_field');
|
||||
removeClass(label_container, 'bz_hidden_field');
|
||||
removeClass(field_container, 'bz_hidden_field');
|
||||
}
|
||||
else
|
||||
{
|
||||
YAHOO.util.Dom.addClass(label_container, 'bz_hidden_field');
|
||||
YAHOO.util.Dom.addClass(field_container, 'bz_hidden_field');
|
||||
addClass(label_container, 'bz_hidden_field');
|
||||
addClass(field_container, 'bz_hidden_field');
|
||||
}
|
||||
}
|
||||
var item, controlled, copt, controlled_value;
|
||||
|
@ -89,4 +100,3 @@ function handleControllerField(e, controller)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
415
js/bug.js
415
js/bug.js
|
@ -1,260 +1,273 @@
|
|||
function updateCommentPrivacy(checkbox, id) {
|
||||
var comment_elem = document.getElementById('comment_text_'+id).parentNode;
|
||||
if (checkbox.checked) {
|
||||
if (!comment_elem.className.match('bz_private')) {
|
||||
comment_elem.className = comment_elem.className.concat(' bz_private');
|
||||
/* JS functions used on bug edit page
|
||||
* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
|
||||
function updateCommentPrivacy(checkbox, id)
|
||||
{
|
||||
var comment_elem = document.getElementById('comment_text_'+id).parentNode;
|
||||
if (checkbox.checked)
|
||||
{
|
||||
if (!comment_elem.className.match('bz_private'))
|
||||
comment_elem.className = comment_elem.className.concat(' bz_private');
|
||||
}
|
||||
}
|
||||
else {
|
||||
comment_elem.className =
|
||||
comment_elem.className.replace(/(\s*|^)bz_private(\s*|$)/, '$2');
|
||||
}
|
||||
else
|
||||
comment_elem.className =
|
||||
comment_elem.className.replace(/(\s*|^)bz_private(\s*|$)/, '$2');
|
||||
}
|
||||
|
||||
/* The functions below expand and collapse comments */
|
||||
|
||||
function toggle_comment_display(link, comment_id) {
|
||||
var comment = document.getElementById('comment_text_' + comment_id);
|
||||
var re = new RegExp(/\bcollapsed\b/);
|
||||
if (comment.className.match(re))
|
||||
expand_comment(link, comment);
|
||||
else
|
||||
collapse_comment(link, comment);
|
||||
}
|
||||
|
||||
function toggle_all_comments(action, num_comments) {
|
||||
// If for some given ID the comment doesn't exist, this doesn't mean
|
||||
// there are no more comments, but that the comment is private and
|
||||
// the user is not allowed to view it.
|
||||
|
||||
for (var id = 0; id < num_comments; id++) {
|
||||
var comment = document.getElementById('comment_text_' + id);
|
||||
if (!comment)
|
||||
continue;
|
||||
|
||||
var link = document.getElementById('comment_link_' + id);
|
||||
if (action == 'collapse')
|
||||
collapse_comment(link, comment);
|
||||
function toggle_comment_display(link, comment_id)
|
||||
{
|
||||
var comment = document.getElementById('comment_text_' + comment_id);
|
||||
var re = new RegExp(/\bcollapsed\b/);
|
||||
if (comment.className.match(re))
|
||||
expand_comment(link, comment);
|
||||
else
|
||||
expand_comment(link, comment);
|
||||
}
|
||||
collapse_comment(link, comment);
|
||||
}
|
||||
|
||||
function collapse_comment(link, comment) {
|
||||
link.innerHTML = "[+]";
|
||||
link.title = "Expand the comment.";
|
||||
YAHOO.util.Dom.addClass(comment, 'collapsed');
|
||||
function toggle_all_comments(action, num_comments)
|
||||
{
|
||||
// If for some given ID the comment doesn't exist, this doesn't mean
|
||||
// there are no more comments, but that the comment is private and
|
||||
// the user is not allowed to view it.
|
||||
|
||||
for (var id = 0; id < num_comments; id++)
|
||||
{
|
||||
var comment = document.getElementById('comment_text_' + id);
|
||||
if (!comment)
|
||||
continue;
|
||||
|
||||
var link = document.getElementById('comment_link_' + id);
|
||||
if (action == 'collapse')
|
||||
collapse_comment(link, comment);
|
||||
else
|
||||
expand_comment(link, comment);
|
||||
}
|
||||
}
|
||||
|
||||
function expand_comment(link, comment) {
|
||||
link.innerHTML = "[-]";
|
||||
link.title = "Collapse the comment";
|
||||
YAHOO.util.Dom.removeClass(comment, 'collapsed');
|
||||
function collapse_comment(link, comment)
|
||||
{
|
||||
link.innerHTML = "[+]";
|
||||
link.title = "Expand the comment.";
|
||||
addClass(comment, 'collapsed');
|
||||
}
|
||||
|
||||
function expand_comment(link, comment)
|
||||
{
|
||||
link.innerHTML = "[-]";
|
||||
link.title = "Collapse the comment";
|
||||
removeClass(comment, 'collapsed');
|
||||
}
|
||||
|
||||
/* This way, we are sure that browsers which do not support JS
|
||||
* won't display this link */
|
||||
|
||||
function addCollapseLink(count) {
|
||||
var e = document.getElementById('comment_act_'+count);
|
||||
if (!e)
|
||||
return;
|
||||
e.innerHTML +=
|
||||
' <a href="#" class="bz_collapse_comment"' +
|
||||
' id="comment_link_' + count +
|
||||
'" onclick="toggle_comment_display(this, ' + count +
|
||||
'); return false;" title="Collapse the comment.">[-]<\/a> ';
|
||||
function addCollapseLink(count)
|
||||
{
|
||||
var e = document.getElementById('comment_act_'+count);
|
||||
if (!e)
|
||||
return;
|
||||
e.innerHTML +=
|
||||
' <a href="#" class="bz_collapse_comment"' +
|
||||
' id="comment_link_' + count +
|
||||
'" onclick="toggle_comment_display(this, ' + count +
|
||||
'); return false;" title="Collapse the comment.">[-]<\/a> ';
|
||||
}
|
||||
|
||||
/* Outputs a link to call replyToComment(); used to reduce HTML output */
|
||||
|
||||
function addReplyLink(id, real_id) {
|
||||
var e = document.getElementById('comment_act_'+id);
|
||||
if (!e)
|
||||
return;
|
||||
var s = '[';
|
||||
if (user_settings.quote_replies != 'off')
|
||||
{
|
||||
s += '<a href="#add_comment" onclick="replyToComment(' +
|
||||
id + ',' + real_id + '); return false;">reply<' + '/a>';
|
||||
}
|
||||
s += ', clone to <a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&cloned_comment='+id+'">other</a>';
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.product)+'&cloned_comment='+id+'">same</a>';
|
||||
/* CustIS Bug 69514 */
|
||||
if (bug_info.extprod)
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.extprod)+'&cloned_comment='+id+'">ext</a>';
|
||||
else if (bug_info.intprod)
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.intprod)+'&cloned_comment='+id+'">int</a>';
|
||||
s += ' product]';
|
||||
e.innerHTML += s;
|
||||
function addReplyLink(id, real_id)
|
||||
{
|
||||
var e = document.getElementById('comment_act_'+id);
|
||||
if (!e)
|
||||
return;
|
||||
var s = '[';
|
||||
if (user_settings.quote_replies != 'off')
|
||||
{
|
||||
s += '<a href="#add_comment" onclick="replyToComment(' +
|
||||
id + ',' + real_id + '); return false;">reply<' + '/a>';
|
||||
}
|
||||
s += ', clone to <a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&cloned_comment='+id+'">other</a>';
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.product)+'&cloned_comment='+id+'">same</a>';
|
||||
/* CustIS Bug 69514 */
|
||||
if (bug_info.extprod)
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.extprod)+'&cloned_comment='+id+'">ext</a>';
|
||||
else if (bug_info.intprod)
|
||||
s += '/<a href="enter_bug.cgi?cloned_bug_id='+bug_info.id+'&product='+encodeURI(bug_info.intprod)+'&cloned_comment='+id+'">int</a>';
|
||||
s += ' product]';
|
||||
e.innerHTML += s;
|
||||
}
|
||||
|
||||
function addActionLinks(indexes)
|
||||
{
|
||||
for (var i in indexes)
|
||||
{
|
||||
addReplyLink(indexes[i][0], indexes[i][1]);
|
||||
addCollapseLink(indexes[i][0]);
|
||||
}
|
||||
for (var i in indexes)
|
||||
{
|
||||
addReplyLink(indexes[i][0], indexes[i][1]);
|
||||
addCollapseLink(indexes[i][0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds the reply text to the `comment' textarea */
|
||||
function replyToComment(id, real_id)
|
||||
{
|
||||
var prefix = "(In reply to comment #" + id + ")\n";
|
||||
var replytext = "";
|
||||
if (user_settings.quote_replies == 'quoted_reply')
|
||||
{
|
||||
/* pre id="comment_name_N" */
|
||||
var text_elem = document.getElementById('comment_text_'+id);
|
||||
var text = getText(text_elem);
|
||||
|
||||
/* make sure we split on all newlines -- IE or Moz use \r and \n
|
||||
* respectively.
|
||||
*/
|
||||
text = text.split(/\r|\n/);
|
||||
|
||||
var prev_ist = false, ist = false;
|
||||
for (var i = 0; i < text.length; i++)
|
||||
var prefix = "(In reply to comment #" + id + ")\n";
|
||||
var replytext = "";
|
||||
if (user_settings.quote_replies == 'quoted_reply')
|
||||
{
|
||||
/* CustIS Bug 55876 - ASCII pseudographic tables */
|
||||
ist = text[i].match('^(┌|│|└).*(┐|│|┘)$') ? true : false;
|
||||
if (!ist)
|
||||
{
|
||||
replytext += "> ";
|
||||
replytext += text[i];
|
||||
replytext += "\n";
|
||||
}
|
||||
else if (!prev_ist)
|
||||
replytext += "> (table cut off)\n";
|
||||
prev_ist = ist;
|
||||
/* pre id="comment_name_N" */
|
||||
var text_elem = document.getElementById('comment_text_'+id);
|
||||
var text = getText(text_elem);
|
||||
|
||||
/* make sure we split on all newlines -- IE or Moz use \r and \n
|
||||
* respectively.
|
||||
*/
|
||||
text = text.split(/\r|\n/);
|
||||
|
||||
var prev_ist = false, ist = false;
|
||||
for (var i = 0; i < text.length; i++)
|
||||
{
|
||||
/* CustIS Bug 55876 - ASCII pseudographic tables */
|
||||
ist = text[i].match('^(┌|│|└).*(┐|│|┘)$') ? true : false;
|
||||
if (!ist)
|
||||
{
|
||||
replytext += "> ";
|
||||
replytext += text[i];
|
||||
replytext += "\n";
|
||||
}
|
||||
else if (!prev_ist)
|
||||
replytext += "> (table cut off)\n";
|
||||
prev_ist = ist;
|
||||
}
|
||||
|
||||
replytext = prefix + replytext + "\n";
|
||||
}
|
||||
else if (user_settings.quote_replies == 'simple_reply')
|
||||
replytext = prefix;
|
||||
|
||||
replytext = prefix + replytext + "\n";
|
||||
}
|
||||
else if (user_settings.quote_replies == 'simple_reply')
|
||||
replytext = prefix;
|
||||
if (user_settings.is_insider && document.getElementById('isprivate_' + real_id).checked)
|
||||
document.getElementById('newcommentprivacy').checked = 'checked';
|
||||
|
||||
if (user_settings.is_insider && document.getElementById('isprivate_' + real_id).checked)
|
||||
document.getElementById('newcommentprivacy').checked = 'checked';
|
||||
var textarea = document.getElementById('comment_textarea');
|
||||
textarea.value += replytext;
|
||||
|
||||
var textarea = document.getElementById('comment_textarea');
|
||||
textarea.value += replytext;
|
||||
|
||||
textarea.focus();
|
||||
textarea.focus();
|
||||
}
|
||||
|
||||
function adjustRemainingTime()
|
||||
{
|
||||
// subtracts time spent from remaining time
|
||||
var new_time;
|
||||
var wt = bzParseTime(document.changeform.work_time.value);
|
||||
if (wt === null || wt === undefined || wt != wt)
|
||||
{
|
||||
document.changeform.work_time.style.backgroundColor = '#FFC0C0';
|
||||
document.changeform.remaining_time.style.backgroundColor = '#FFC0C0';
|
||||
wt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.changeform.work_time.style.backgroundColor = null;
|
||||
document.changeform.remaining_time.style.backgroundColor = null;
|
||||
}
|
||||
if (notimetracking)
|
||||
document.changeform.work_time.parentNode.style.backgroundColor = wt != 0 ? '#FFC0C0' : null;
|
||||
// subtracts time spent from remaining time
|
||||
var new_time;
|
||||
var wt = bzParseTime(document.changeform.work_time.value);
|
||||
if (wt === null || wt === undefined || wt != wt)
|
||||
{
|
||||
document.changeform.work_time.style.backgroundColor = '#FFC0C0';
|
||||
document.changeform.remaining_time.style.backgroundColor = '#FFC0C0';
|
||||
wt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
document.changeform.work_time.style.backgroundColor = null;
|
||||
document.changeform.remaining_time.style.backgroundColor = null;
|
||||
}
|
||||
if (notimetracking)
|
||||
document.changeform.work_time.parentNode.style.backgroundColor = wt != 0 ? '#FFC0C0' : null;
|
||||
|
||||
// prevent negative values if work_time > fRemainingTime
|
||||
new_time = Math.max(fRemainingTime - wt, 0.0);
|
||||
// get upto 2 decimal places
|
||||
document.changeform.remaining_time.value =
|
||||
Math.round(new_time * 100)/100;
|
||||
// prevent negative values if work_time > fRemainingTime
|
||||
new_time = Math.max(fRemainingTime - wt, 0.0);
|
||||
// get upto 2 decimal places
|
||||
document.changeform.remaining_time.value =
|
||||
Math.round(new_time * 100)/100;
|
||||
}
|
||||
|
||||
function updateRemainingTime() {
|
||||
// if the remaining time is changed manually, update fRemainingTime
|
||||
fRemainingTime = bzParseTime(document.changeform.remaining_time.value);
|
||||
function updateRemainingTime()
|
||||
{
|
||||
// if the remaining time is changed manually, update fRemainingTime
|
||||
fRemainingTime = bzParseTime(document.changeform.remaining_time.value);
|
||||
}
|
||||
|
||||
function changeform_onsubmit()
|
||||
{
|
||||
var wt = bzParseTime(document.changeform.work_time.value);
|
||||
var awt = wt;
|
||||
if (wt != wt)
|
||||
awt = 0;
|
||||
else if (user_settings.wants_worktime_reminder &&
|
||||
(wt === null || wt === undefined || wt != wt ||
|
||||
notimetracking && wt != 0 || !notimetracking && wt == 0))
|
||||
{
|
||||
awt = prompt("Please, verify working time:", !wt || wt != wt ? "0" : wt);
|
||||
if (awt === null || awt === undefined || (""+awt).length <= 0)
|
||||
var wt = bzParseTime(document.changeform.work_time.value);
|
||||
var awt = wt;
|
||||
if (wt != wt)
|
||||
awt = 0;
|
||||
else if (user_settings.wants_worktime_reminder &&
|
||||
(wt === null || wt === undefined || wt != wt ||
|
||||
notimetracking && wt != 0 || !notimetracking && wt == 0))
|
||||
{
|
||||
document.changeform.work_time.focus();
|
||||
return false;
|
||||
awt = prompt("Please, verify working time:", !wt || wt != wt ? "0" : wt);
|
||||
if (awt === null || awt === undefined || (""+awt).length <= 0)
|
||||
{
|
||||
document.changeform.work_time.focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
document.changeform.work_time.value = awt;
|
||||
adjustRemainingTime();
|
||||
return true;
|
||||
document.changeform.work_time.value = awt;
|
||||
adjustRemainingTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function clears a row from multi-attachment upload form
|
||||
function att_file_clear(e)
|
||||
{
|
||||
e = document.getElementById(e);
|
||||
var ci = e.id.substr(5);
|
||||
e.parentNode.innerHTML = e.parentNode.innerHTML;
|
||||
document.getElementById('del_'+ci).style.display = 'none';
|
||||
document.getElementById('description_'+ci).value = '';
|
||||
document.getElementById('contenttypeselection_'+ci).selectedIndex = 0;
|
||||
e = document.getElementById(e);
|
||||
var ci = e.id.substr(5);
|
||||
e.parentNode.innerHTML = e.parentNode.innerHTML;
|
||||
document.getElementById('del_'+ci).style.display = 'none';
|
||||
document.getElementById('description_'+ci).value = '';
|
||||
document.getElementById('contenttypeselection_'+ci).selectedIndex = 0;
|
||||
}
|
||||
|
||||
// This function handles change events of upload inputs on multi-attachment upload form
|
||||
function att_file_onchange(e)
|
||||
{
|
||||
var ci = e.id.substr(5);
|
||||
document.getElementById('del_'+ci).style.display = e.value ? '' : 'none';
|
||||
if (e.value)
|
||||
{
|
||||
// Fill description from file name if it wasn't changed by user
|
||||
var e1 = document.getElementById('description_'+ci);
|
||||
if (!e1._changed)
|
||||
var ci = e.id.substr(5);
|
||||
document.getElementById('del_'+ci).style.display = e.value ? '' : 'none';
|
||||
if (e.value)
|
||||
{
|
||||
var p = e.value;
|
||||
var slash = p.lastIndexOf('/');
|
||||
var backslash = p.lastIndexOf('\\');
|
||||
var fname;
|
||||
if (slash == -1 && backslash == -1)
|
||||
fname = p;
|
||||
else if (slash > backslash)
|
||||
fname = p.substr(slash+1);
|
||||
else
|
||||
fname = p.substr(backslash+1);
|
||||
e1.value = fname;
|
||||
// Fill description from file name if it wasn't changed by user
|
||||
var e1 = document.getElementById('description_'+ci);
|
||||
if (!e1._changed)
|
||||
{
|
||||
var p = e.value;
|
||||
var slash = p.lastIndexOf('/');
|
||||
var backslash = p.lastIndexOf('\\');
|
||||
var fname;
|
||||
if (slash == -1 && backslash == -1)
|
||||
fname = p;
|
||||
else if (slash > backslash)
|
||||
fname = p.substr(slash+1);
|
||||
else
|
||||
fname = p.substr(backslash+1);
|
||||
e1.value = fname;
|
||||
}
|
||||
// Add a new empty field if there are no empty fields
|
||||
var i = 0;
|
||||
var f;
|
||||
while (f = document.getElementById('data_'+i))
|
||||
{
|
||||
if (!f.value)
|
||||
{
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
// Copy innerHTML of fileX
|
||||
// IE does not like setting innerHTML of regular elements, so create
|
||||
// a div with table and then copy its row
|
||||
var tmp = document.createElement('div');
|
||||
tmp.innerHTML =
|
||||
'<table id="file'+i+'table"><tbody><tr id="file'+i+'">'+
|
||||
document.getElementById('fileX').innerHTML.replace(/_XXX/g, '_'+i)+
|
||||
'</tr></tbody></table>';
|
||||
// div.table.tbody.tr
|
||||
document.getElementById('files').appendChild(tmp.childNodes[0].childNodes[0].childNodes[0]);
|
||||
}
|
||||
}
|
||||
// Add a new empty field if there are no empty fields
|
||||
var i = 0;
|
||||
var f;
|
||||
while (f = document.getElementById('data_'+i))
|
||||
{
|
||||
if (!f.value)
|
||||
{
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
// Copy innerHTML of fileX
|
||||
// IE does not like setting innerHTML of regular elements, so create
|
||||
// a div with table and then copy its row
|
||||
var tmp = document.createElement('div');
|
||||
tmp.innerHTML =
|
||||
'<table id="file'+i+'table"><tbody><tr id="file'+i+'">'+
|
||||
document.getElementById('fileX').innerHTML.replace(/_XXX/g, '_'+i)+
|
||||
'</tr></tbody></table>';
|
||||
// div.table.tbody.tr
|
||||
document.getElementById('files').appendChild(tmp.childNodes[0].childNodes[0].childNodes[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/**
|
||||
* Calendar Script, slightly modified
|
||||
* Creates a calendar widget which can be used to select the date more easily than using just a text box
|
||||
* http://www.openjs.com/scripts/ui/calendar/
|
||||
* License: MIT-like, http://www.openjs.com/license.php
|
||||
*
|
||||
* Example:
|
||||
* <input type="text" name="date" id="date" />
|
||||
* <script type="text/javascript">
|
||||
* Calendar.set("date");
|
||||
* </script>
|
||||
*/
|
||||
var Calendar = {
|
||||
month_names: ["January","February","March","April","May","June","July","Augest","September","October","November","December"],
|
||||
weekdays: ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],
|
||||
sunday: 0,
|
||||
month_days: [31,28,31,30,31,30,31,31,30,31,30,31],
|
||||
//Get today's date - year, month, day and date
|
||||
today : new Date(),
|
||||
opt : {},
|
||||
data: [],
|
||||
|
||||
//Functions
|
||||
/// Used to create HTML in a optimized way.
|
||||
wrt:function(txt) {
|
||||
this.data.push(txt);
|
||||
},
|
||||
|
||||
getPosition:function(ele) {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
while (ele) {
|
||||
x += ele.offsetLeft;
|
||||
y += ele.offsetTop;
|
||||
ele = ele.offsetParent;
|
||||
}
|
||||
if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined") {
|
||||
x += document.body.leftMargin;
|
||||
offsetTop += document.body.topMargin;
|
||||
}
|
||||
|
||||
var xy = new Array(x,y);
|
||||
return xy;
|
||||
},
|
||||
/// Called when the user clicks on a date in the calendar.
|
||||
selectDate:function(year,month,day) {
|
||||
var ths = _calendar_active_instance;
|
||||
var i = document.getElementById(ths.opt["input"]);
|
||||
var t = i.value.split(/\s+/, 2)[1]||'';
|
||||
if (t)
|
||||
t = ' '+t;
|
||||
i.value = year + "-" + month + "-" + day + t; // Date format is :HARDCODE:
|
||||
ths.hideCalendar();
|
||||
},
|
||||
/// Creates a calendar with the date given in the argument as the selected date.
|
||||
makeCalendar:function(year, month, day) {
|
||||
year = parseInt(year);
|
||||
month= parseInt(month);
|
||||
day = parseInt(day);
|
||||
|
||||
//Display the table
|
||||
var next_month = month+1;
|
||||
var next_month_year = year;
|
||||
if(next_month>=12) {
|
||||
next_month = 0;
|
||||
next_month_year++;
|
||||
}
|
||||
|
||||
var previous_month = month-1;
|
||||
var previous_month_year = year;
|
||||
if(previous_month<0) {
|
||||
previous_month = 11;
|
||||
previous_month_year--;
|
||||
}
|
||||
|
||||
this.wrt("<table>");
|
||||
this.wrt("<tr><th><a href='javascript:Calendar.makeCalendar("+(previous_month_year)+","+(previous_month)+");' title='"+this.month_names[previous_month]+" "+(previous_month_year)+"'><</a></th>");
|
||||
this.wrt("<th colspan='5' class='calendar-title'><select name='calendar-month' class='calendar-month' onChange='Calendar.makeCalendar("+year+",this.value);'>");
|
||||
for(var i in this.month_names) {
|
||||
this.wrt("<option value='"+i+"'");
|
||||
if(i == month) this.wrt(" selected='selected'");
|
||||
this.wrt(">"+this.month_names[i]+"</option>");
|
||||
}
|
||||
this.wrt("</select>");
|
||||
this.wrt("<select name='calendar-year' class='calendar-year' onChange='Calendar.makeCalendar(this.value, "+month+");'>");
|
||||
var current_year = this.today.getYear();
|
||||
if(current_year < 1900) current_year += 1900;
|
||||
|
||||
for(var i=current_year-70; i<current_year+10; i++) {
|
||||
this.wrt("<option value='"+i+"'")
|
||||
if(i == year) this.wrt(" selected='selected'");
|
||||
this.wrt(">"+i+"</option>");
|
||||
}
|
||||
this.wrt("</select></th>");
|
||||
this.wrt("<th><a href='javascript:Calendar.makeCalendar("+(next_month_year)+","+(next_month)+");' title='"+this.month_names[next_month]+" "+(next_month_year)+"'>></a></th></tr>");
|
||||
this.wrt("<tr class='header'>");
|
||||
for(var weekday=0; weekday<7; weekday++) this.wrt("<td>"+this.weekdays[weekday]+"</td>");
|
||||
this.wrt("</tr>");
|
||||
|
||||
//Get the first day of this month
|
||||
var first_day = new Date(year,month,1);
|
||||
var start_day = (first_day.getDay()+Calendar.sunday)%7;
|
||||
|
||||
var d = 1;
|
||||
var flag = 0;
|
||||
|
||||
//Leap year support
|
||||
if(year % 4 == 0) this.month_days[1] = 29;
|
||||
else this.month_days[1] = 28;
|
||||
|
||||
var days_in_this_month = this.month_days[month];
|
||||
|
||||
//Create the calender
|
||||
for(var i=0;i<=5;i++) {
|
||||
if(w >= days_in_this_month) break;
|
||||
this.wrt("<tr>");
|
||||
for(var j=0;j<7;j++) {
|
||||
if(d > days_in_this_month) flag=0; //If the days has overshooted the number of days in this month, stop writing
|
||||
else if(j >= start_day && !flag) flag=1;//If the first day of this month has come, start the date writing
|
||||
|
||||
if(flag) {
|
||||
var w = d, mon = month+1;
|
||||
if(w < 10) w = "0" + w;
|
||||
if(mon < 10)mon = "0" + mon;
|
||||
|
||||
//Is it today?
|
||||
var class_name = '';
|
||||
var yea = this.today.getYear();
|
||||
if(yea < 1900) yea += 1900;
|
||||
|
||||
if(yea == year && this.today.getMonth() == month && this.today.getDate() == d) class_name = " today";
|
||||
if(day == d) class_name += " selected";
|
||||
|
||||
class_name += " " + this.weekdays[j].toLowerCase();
|
||||
|
||||
this.wrt("<td class='days"+class_name+"'><a href='javascript:Calendar.selectDate(\""+year+"\",\""+mon+"\",\""+w+"\")'>"+w+"</a></td>");
|
||||
d++;
|
||||
} else {
|
||||
this.wrt("<td class='days'> </td>");
|
||||
}
|
||||
}
|
||||
this.wrt("</tr>");
|
||||
}
|
||||
this.wrt("</table>");
|
||||
this.wrt("<input type='button' value='Cancel' class='calendar-cancel' onclick='Calendar.hideCalendar();' />");
|
||||
|
||||
document.getElementById(this.opt['calendar']).innerHTML = this.data.join("");
|
||||
this.data = [];
|
||||
},
|
||||
|
||||
/// Display the calendar - if a date exists in the input box, that will be selected in the calendar.
|
||||
showCalendar: function() {
|
||||
var input = document.getElementById(this.opt['input']);
|
||||
|
||||
//Position the div in the correct location...
|
||||
var div = document.getElementById(this.opt['calendar']);
|
||||
var xy = this.getPosition(input);
|
||||
var width = input.clientWidth||input.offsetWidth;
|
||||
div.style.left=(xy[0]+width+10)+"px";
|
||||
div.style.top=xy[1]+"px";
|
||||
|
||||
// Show the calendar with the date in the input as the selected date
|
||||
var existing_date = new Date();
|
||||
var date_in_input = input.value.replace(/\s+.*$/, ''); //Remove time
|
||||
if(date_in_input) {
|
||||
var selected_date = false;
|
||||
var date_parts = date_in_input.split("-");
|
||||
if(date_parts.length == 3) {
|
||||
date_parts[1]--; //Month starts with 0
|
||||
selected_date = new Date(date_parts[0], date_parts[1], date_parts[2]);
|
||||
}
|
||||
if(selected_date && !isNaN(selected_date.getYear())) { //Valid date.
|
||||
existing_date = selected_date;
|
||||
}
|
||||
}
|
||||
|
||||
var the_year = existing_date.getYear();
|
||||
if(the_year < 1900) the_year += 1900;
|
||||
this.makeCalendar(the_year, existing_date.getMonth(), existing_date.getDate());
|
||||
document.getElementById(this.opt['calendar']).style.display = "block";
|
||||
_calendar_active_instance = this;
|
||||
},
|
||||
|
||||
/// Hides the currently show calendar.
|
||||
hideCalendar: function(instance) {
|
||||
var active_calendar_id = "";
|
||||
if(instance) active_calendar_id = instance.opt['calendar'];
|
||||
else active_calendar_id = _calendar_active_instance.opt['calendar'];
|
||||
|
||||
if(active_calendar_id) document.getElementById(active_calendar_id).style.display = "none";
|
||||
_calendar_active_instance = {};
|
||||
},
|
||||
|
||||
/// Setup a text input box to be a calendar box.
|
||||
set: function(input_id) {
|
||||
var input = document.getElementById(input_id);
|
||||
if(!input) return; //If the input field is not there, exit.
|
||||
|
||||
if(!this.opt['calendar']) this.init();
|
||||
|
||||
var ths = this;
|
||||
input.onclick=function(){
|
||||
ths.opt['input'] = this.id;
|
||||
ths.showCalendar();
|
||||
};
|
||||
},
|
||||
|
||||
/// Will be called once when the first input is set.
|
||||
init: function() {
|
||||
if(!this.opt['calendar'] || !document.getElementById(this.opt['calendar'])) {
|
||||
var div = document.createElement('div');
|
||||
if(!this.opt['calendar']) this.opt['calendar'] = 'calender_div_'+ Math.round(Math.random() * 100);
|
||||
|
||||
div.setAttribute('id',this.opt['calendar']);
|
||||
div.className="calendar-box";
|
||||
|
||||
document.getElementsByTagName("body")[0].insertBefore(div,document.getElementsByTagName("body")[0].firstChild);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +1,29 @@
|
|||
/*# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is the Bugzilla Bug Tracking System.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Pascal Held.
|
||||
#
|
||||
# Contributor(s): Pascal Held <paheld@gmail.com>
|
||||
#
|
||||
*/
|
||||
/* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Bugzilla Bug Tracking System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Pascal Held.
|
||||
*
|
||||
* Contributor(s): Pascal Held <paheld@gmail.com>
|
||||
*/
|
||||
|
||||
function initChangeColumns() {
|
||||
function initChangeColumns()
|
||||
{
|
||||
window.onunload = unload;
|
||||
var av_select = document.getElementById("available_columns");
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
YAHOO.util.Dom.removeClass(
|
||||
['avail_header', av_select, 'select_button',
|
||||
'deselect_button', 'up_button', 'down_button'], 'bz_default_hidden');
|
||||
var l = ['avail_header', av_select, 'select_button',
|
||||
'deselect_button', 'up_button', 'down_button'];
|
||||
for (var i = 0; i < l.length; i++)
|
||||
removeClass(l[i], 'bz_default_hidden');
|
||||
switch_options(sel_select, av_select, false);
|
||||
sel_select.selectedIndex = -1;
|
||||
updateView();
|
||||
|
@ -51,14 +52,16 @@ function switch_options(from_box, to_box, selected)
|
|||
from_box.options[i].selected = sel[i];
|
||||
}
|
||||
|
||||
function move_select() {
|
||||
function move_select()
|
||||
{
|
||||
var av_select = document.getElementById("available_columns");
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
switch_options(av_select, sel_select, true);
|
||||
updateView();
|
||||
}
|
||||
|
||||
function move_deselect() {
|
||||
function move_deselect()
|
||||
{
|
||||
var av_select = document.getElementById("available_columns");
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
switch_options(sel_select, av_select, true);
|
||||
|
@ -117,7 +120,8 @@ function move_down()
|
|||
updateView();
|
||||
}
|
||||
|
||||
function updateView() {
|
||||
function updateView()
|
||||
{
|
||||
var select_button = document.getElementById("select_button");
|
||||
var deselect_button = document.getElementById("deselect_button");
|
||||
var up_button = document.getElementById("up_button");
|
||||
|
@ -128,41 +132,44 @@ function updateView() {
|
|||
down_button.disabled = true;
|
||||
var av_select = document.getElementById("available_columns");
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
for (var i = 0; i < av_select.options.length; i++) {
|
||||
if (av_select.options[i].selected) {
|
||||
for (var i = 0; i < av_select.options.length; i++)
|
||||
{
|
||||
if (av_select.options[i].selected)
|
||||
{
|
||||
select_button.disabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < sel_select.options.length; i++) {
|
||||
if (sel_select.options[i].selected) {
|
||||
for (var i = 0; i < sel_select.options.length; i++)
|
||||
{
|
||||
if (sel_select.options[i].selected)
|
||||
{
|
||||
deselect_button.disabled = false;
|
||||
up_button.disabled = false;
|
||||
down_button.disabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sel_select.options.length > 0) {
|
||||
if (sel_select.options[0].selected) {
|
||||
if (sel_select.options.length > 0)
|
||||
{
|
||||
if (sel_select.options[0].selected)
|
||||
up_button.disabled = true;
|
||||
}
|
||||
if (sel_select.options[sel_select.options.length - 1].selected) {
|
||||
if (sel_select.options[sel_select.options.length - 1].selected)
|
||||
down_button.disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function change_submit() {
|
||||
function change_submit()
|
||||
{
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
for (var i = 0; i < sel_select.options.length; i++) {
|
||||
for (var i = 0; i < sel_select.options.length; i++)
|
||||
sel_select.options[i].selected = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function unload() {
|
||||
function unload()
|
||||
{
|
||||
var sel_select = document.getElementById("selected_columns");
|
||||
for (var i = 0; i < sel_select.options.length; i++) {
|
||||
for (var i = 0; i < sel_select.options.length; i++)
|
||||
sel_select.options[i].selected = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,558 @@
|
|||
/* Functions for dynamically adding Boolean Charts fields
|
||||
* onto the Bugzilla Advanced Search Form.
|
||||
* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
|
||||
function chart_add_second(btn)
|
||||
{
|
||||
var n = btn.id.substr(5, btn.id.length-9);
|
||||
// Transform <div> to <fieldset>
|
||||
var d = document.getElementById('chart'+n);
|
||||
d.id = 'divchart'+n; // prevent id collisions
|
||||
btn.id = 'btnchart'+n; // prevent id collisions
|
||||
var op = (n != 'R' && n.indexOf('-') < 0 ? 'and' : 'or');
|
||||
// Create <fieldset>
|
||||
var f = document.createElement('fieldset');
|
||||
f.id = 'chart'+n;
|
||||
f.className = 'chart _'+op;
|
||||
var legend_html = op.toUpperCase()+' '+
|
||||
'<input type="button" value="+" class="chart_add_button" id="chart'+n+'-btn" onclick="chart_add(this.id)" />';
|
||||
if (op == 'and')
|
||||
{
|
||||
// Move [NOT] to the legend for 'AND' charts
|
||||
var neg = document.getElementById('negate'+n);
|
||||
legend_html +=
|
||||
'<input type="button" value="NOT" class="chart_not_'+(neg.value ? 'c' : 'u')+'"'+
|
||||
' style="font-size: 85%" id="negate'+n+'-btn" onclick="chart_neg(this)" />';
|
||||
if (neg.value)
|
||||
f.className += ' _neg';
|
||||
neg = document.getElementById('negate'+n+'-btn');
|
||||
neg.parentNode.removeChild(neg);
|
||||
}
|
||||
// Create <legend>
|
||||
var l = document.createElement('legend');
|
||||
l.className = '_'+op;
|
||||
l.innerHTML = legend_html;
|
||||
f.appendChild(l);
|
||||
d.parentNode.insertBefore(f, d);
|
||||
btn.parentNode.removeChild(btn);
|
||||
d.parentNode.removeChild(d);
|
||||
while (d.childNodes.length)
|
||||
f.appendChild(d.childNodes[0]);
|
||||
// Add an operand
|
||||
chart_add('chart'+n+'-btn');
|
||||
}
|
||||
|
||||
function chart_add_btn(d, s)
|
||||
{
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.id = d.id+'-btn';
|
||||
i.onclick = chart_add_second_event;
|
||||
i.value = s;
|
||||
d.appendChild(document.createTextNode(' '));
|
||||
d.appendChild(i);
|
||||
}
|
||||
|
||||
// Find next available number for div with prefix 'n'
|
||||
function chart_add_div(d, n)
|
||||
{
|
||||
var i, nd;
|
||||
for (i = 0; document.getElementById(n+i); i++);
|
||||
nd = document.createElement('div');
|
||||
nd.id = n+i;
|
||||
nd.className = 'chart';
|
||||
d.appendChild(nd);
|
||||
return nd;
|
||||
}
|
||||
|
||||
// Copy 'fieldx-x-x' or 'typex-x-x' selectbox
|
||||
function chart_copy_select(cp_id, new_id)
|
||||
{
|
||||
var s = document.createElement('select');
|
||||
s.id = s.name = new_id;
|
||||
s.innerHTML = document.getElementById(cp_id).innerHTML;
|
||||
s.selectedIndex = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Add another term into chart when clicked on button with id=btnid
|
||||
function chart_add(btnid)
|
||||
{
|
||||
var d, i, add_and, add_or, n;
|
||||
d = document.getElementById(btnid.substr(0, btnid.length-4)); // chartN-btn
|
||||
if (d.id == 'chartR')
|
||||
add_and = d = chart_add_div(d, 'chart');
|
||||
if (d.id.indexOf('-') < 0)
|
||||
add_or = d = chart_add_div(d, d.id+'-');
|
||||
var cn = d.id.substr(5);
|
||||
for (i = 0; document.getElementById('field'+cn+'-'+i); i++);
|
||||
cn = cn+'-'+i;
|
||||
if (!add_or)
|
||||
d.appendChild(document.createElement('br'));
|
||||
// Append field-type-value inputs
|
||||
d.appendChild(chart_copy_select('field0-0-0', 'field'+cn));
|
||||
d.appendChild(chart_copy_select('type0-0-0', 'type'+cn));
|
||||
s = document.createElement('input');
|
||||
s.id = s.name = "value"+cn;
|
||||
s.size = 40;
|
||||
d.appendChild(s);
|
||||
if (add_and)
|
||||
{
|
||||
chart_add_btn(add_and, 'AND');
|
||||
// Add negate button
|
||||
var n = add_and.id.substr(5);
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.className = 'chart_not_u';
|
||||
i.id = 'negate'+n+'-btn';
|
||||
i.onclick = chart_neg_event;
|
||||
i.value = 'NOT';
|
||||
add_and.appendChild(i);
|
||||
// Add hidden input for negate button
|
||||
i = document.createElement('input');
|
||||
i.type = 'hidden';
|
||||
i.name = i.id = 'negate'+n;
|
||||
document.getElementById('chartR').appendChild(i);
|
||||
}
|
||||
if (add_or)
|
||||
chart_add_btn(add_or, 'OR');
|
||||
}
|
||||
|
||||
function chart_neg(btn)
|
||||
{
|
||||
var n = btn.id.substr(6, btn.id.length-10); // negateN
|
||||
var i = document.getElementById('negate'+n);
|
||||
i.value = i.value ? '' : '1';
|
||||
btn.className = 'chart_not_' + (i.value ? 'c' : 'u');
|
||||
var c = document.getElementById('chart'+n);
|
||||
if (i.value)
|
||||
c.className += ' _neg';
|
||||
else
|
||||
c.className = c.className.replace(/ _neg/, '');
|
||||
}
|
||||
|
||||
function chart_add_second_event()
|
||||
{
|
||||
chart_add_second(this);
|
||||
}
|
||||
|
||||
function chart_neg_event()
|
||||
{
|
||||
chart_neg(this);
|
||||
}
|
||||
function chart_add_second(btn)
|
||||
{
|
||||
var n = btn.id.substr(5, btn.id.length-9);
|
||||
// Transform <div> to <fieldset>
|
||||
var d = document.getElementById('chart'+n);
|
||||
d.id = 'divchart'+n; // prevent id collisions
|
||||
btn.id = 'btnchart'+n; // prevent id collisions
|
||||
var op = (n != 'R' && n.indexOf('-') < 0 ? 'and' : 'or');
|
||||
// Create <fieldset>
|
||||
var f = document.createElement('fieldset');
|
||||
f.id = 'chart'+n;
|
||||
f.className = 'chart _'+op;
|
||||
var legend_html = op.toUpperCase()+' '+
|
||||
'<input type="button" value="+" class="chart_add_button" id="chart'+n+'-btn" onclick="chart_add(this.id)" />';
|
||||
if (op == 'and')
|
||||
{
|
||||
// Move [NOT] to the legend for 'AND' charts
|
||||
var neg = document.getElementById('negate'+n);
|
||||
legend_html +=
|
||||
'<input type="button" value="NOT" class="chart_not_'+(neg.value ? 'c' : 'u')+'"'+
|
||||
' style="font-size: 85%" id="negate'+n+'-btn" onclick="chart_neg(this)" />';
|
||||
if (neg.value)
|
||||
f.className += ' _neg';
|
||||
neg = document.getElementById('negate'+n+'-btn');
|
||||
neg.parentNode.removeChild(neg);
|
||||
}
|
||||
// Create <legend>
|
||||
var l = document.createElement('legend');
|
||||
l.className = '_'+op;
|
||||
l.innerHTML = legend_html;
|
||||
f.appendChild(l);
|
||||
d.parentNode.insertBefore(f, d);
|
||||
btn.parentNode.removeChild(btn);
|
||||
d.parentNode.removeChild(d);
|
||||
while (d.childNodes.length)
|
||||
f.appendChild(d.childNodes[0]);
|
||||
// Add an operand
|
||||
chart_add('chart'+n+'-btn');
|
||||
}
|
||||
|
||||
function chart_add_btn(d, s)
|
||||
{
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.id = d.id+'-btn';
|
||||
i.onclick = chart_add_second_event;
|
||||
i.value = s;
|
||||
d.appendChild(document.createTextNode(' '));
|
||||
d.appendChild(i);
|
||||
}
|
||||
|
||||
// Find next available number for div with prefix 'n'
|
||||
function chart_add_div(d, n)
|
||||
{
|
||||
var i, nd;
|
||||
for (i = 0; document.getElementById(n+i); i++);
|
||||
nd = document.createElement('div');
|
||||
nd.id = n+i;
|
||||
nd.className = 'chart';
|
||||
d.appendChild(nd);
|
||||
return nd;
|
||||
}
|
||||
|
||||
// Copy 'fieldx-x-x' or 'typex-x-x' selectbox
|
||||
function chart_copy_select(cp_id, new_id)
|
||||
{
|
||||
var s = document.createElement('select');
|
||||
s.id = s.name = new_id;
|
||||
s.innerHTML = document.getElementById(cp_id).innerHTML;
|
||||
s.selectedIndex = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Add another term into chart when clicked on button with id=btnid
|
||||
function chart_add(btnid)
|
||||
{
|
||||
var d, i, add_and, add_or, n;
|
||||
d = document.getElementById(btnid.substr(0, btnid.length-4)); // chartN-btn
|
||||
if (d.id == 'chartR')
|
||||
add_and = d = chart_add_div(d, 'chart');
|
||||
if (d.id.indexOf('-') < 0)
|
||||
add_or = d = chart_add_div(d, d.id+'-');
|
||||
var cn = d.id.substr(5);
|
||||
for (i = 0; document.getElementById('field'+cn+'-'+i); i++);
|
||||
cn = cn+'-'+i;
|
||||
if (!add_or)
|
||||
d.appendChild(document.createElement('br'));
|
||||
// Append field-type-value inputs
|
||||
d.appendChild(chart_copy_select('field0-0-0', 'field'+cn));
|
||||
d.appendChild(chart_copy_select('type0-0-0', 'type'+cn));
|
||||
s = document.createElement('input');
|
||||
s.id = s.name = "value"+cn;
|
||||
s.size = 40;
|
||||
d.appendChild(s);
|
||||
if (add_and)
|
||||
{
|
||||
chart_add_btn(add_and, 'AND');
|
||||
// Add negate button
|
||||
var n = add_and.id.substr(5);
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.className = 'chart_not_u';
|
||||
i.id = 'negate'+n+'-btn';
|
||||
i.onclick = chart_neg_event;
|
||||
i.value = 'NOT';
|
||||
add_and.appendChild(i);
|
||||
// Add hidden input for negate button
|
||||
i = document.createElement('input');
|
||||
i.type = 'hidden';
|
||||
i.name = i.id = 'negate'+n;
|
||||
document.getElementById('chartR').appendChild(i);
|
||||
}
|
||||
if (add_or)
|
||||
chart_add_btn(add_or, 'OR');
|
||||
}
|
||||
|
||||
function chart_neg(btn)
|
||||
{
|
||||
var n = btn.id.substr(6, btn.id.length-10); // negateN
|
||||
var i = document.getElementById('negate'+n);
|
||||
i.value = i.value ? '' : '1';
|
||||
btn.className = 'chart_not_' + (i.value ? 'c' : 'u');
|
||||
var c = document.getElementById('chart'+n);
|
||||
if (i.value)
|
||||
c.className += ' _neg';
|
||||
else
|
||||
c.className = c.className.replace(/ _neg/, '');
|
||||
}
|
||||
|
||||
function chart_add_second_event()
|
||||
{
|
||||
chart_add_second(this);
|
||||
}
|
||||
|
||||
function chart_neg_event()
|
||||
{
|
||||
chart_neg(this);
|
||||
}
|
||||
function chart_add_second(btn)
|
||||
{
|
||||
var n = btn.id.substr(5, btn.id.length-9);
|
||||
// Transform <div> to <fieldset>
|
||||
var d = document.getElementById('chart'+n);
|
||||
d.id = 'divchart'+n; // prevent id collisions
|
||||
btn.id = 'btnchart'+n; // prevent id collisions
|
||||
var op = (n != 'R' && n.indexOf('-') < 0 ? 'and' : 'or');
|
||||
// Create <fieldset>
|
||||
var f = document.createElement('fieldset');
|
||||
f.id = 'chart'+n;
|
||||
f.className = 'chart _'+op;
|
||||
var legend_html = op.toUpperCase()+' '+
|
||||
'<input type="button" value="+" class="chart_add_button" id="chart'+n+'-btn" onclick="chart_add(this.id)" />';
|
||||
if (op == 'and')
|
||||
{
|
||||
// Move [NOT] to the legend for 'AND' charts
|
||||
var neg = document.getElementById('negate'+n);
|
||||
legend_html +=
|
||||
'<input type="button" value="NOT" class="chart_not_'+(neg.value ? 'c' : 'u')+'"'+
|
||||
' style="font-size: 85%" id="negate'+n+'-btn" onclick="chart_neg(this)" />';
|
||||
if (neg.value)
|
||||
f.className += ' _neg';
|
||||
neg = document.getElementById('negate'+n+'-btn');
|
||||
neg.parentNode.removeChild(neg);
|
||||
}
|
||||
// Create <legend>
|
||||
var l = document.createElement('legend');
|
||||
l.className = '_'+op;
|
||||
l.innerHTML = legend_html;
|
||||
f.appendChild(l);
|
||||
d.parentNode.insertBefore(f, d);
|
||||
btn.parentNode.removeChild(btn);
|
||||
d.parentNode.removeChild(d);
|
||||
while (d.childNodes.length)
|
||||
f.appendChild(d.childNodes[0]);
|
||||
// Add an operand
|
||||
chart_add('chart'+n+'-btn');
|
||||
}
|
||||
|
||||
function chart_add_btn(d, s)
|
||||
{
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.id = d.id+'-btn';
|
||||
i.onclick = chart_add_second_event;
|
||||
i.value = s;
|
||||
d.appendChild(document.createTextNode(' '));
|
||||
d.appendChild(i);
|
||||
}
|
||||
|
||||
// Find next available number for div with prefix 'n'
|
||||
function chart_add_div(d, n)
|
||||
{
|
||||
var i, nd;
|
||||
for (i = 0; document.getElementById(n+i); i++);
|
||||
nd = document.createElement('div');
|
||||
nd.id = n+i;
|
||||
nd.className = 'chart';
|
||||
d.appendChild(nd);
|
||||
return nd;
|
||||
}
|
||||
|
||||
// Copy 'fieldx-x-x' or 'typex-x-x' selectbox
|
||||
function chart_copy_select(cp_id, new_id)
|
||||
{
|
||||
var s = document.createElement('select');
|
||||
s.id = s.name = new_id;
|
||||
s.innerHTML = document.getElementById(cp_id).innerHTML;
|
||||
s.selectedIndex = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Add another term into chart when clicked on button with id=btnid
|
||||
function chart_add(btnid)
|
||||
{
|
||||
var d, i, add_and, add_or, n;
|
||||
d = document.getElementById(btnid.substr(0, btnid.length-4)); // chartN-btn
|
||||
if (d.id == 'chartR')
|
||||
add_and = d = chart_add_div(d, 'chart');
|
||||
if (d.id.indexOf('-') < 0)
|
||||
add_or = d = chart_add_div(d, d.id+'-');
|
||||
var cn = d.id.substr(5);
|
||||
for (i = 0; document.getElementById('field'+cn+'-'+i); i++);
|
||||
cn = cn+'-'+i;
|
||||
if (!add_or)
|
||||
d.appendChild(document.createElement('br'));
|
||||
// Append field-type-value inputs
|
||||
d.appendChild(chart_copy_select('field0-0-0', 'field'+cn));
|
||||
d.appendChild(chart_copy_select('type0-0-0', 'type'+cn));
|
||||
s = document.createElement('input');
|
||||
s.id = s.name = "value"+cn;
|
||||
s.size = 40;
|
||||
d.appendChild(s);
|
||||
if (add_and)
|
||||
{
|
||||
chart_add_btn(add_and, 'AND');
|
||||
// Add negate button
|
||||
var n = add_and.id.substr(5);
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.className = 'chart_not_u';
|
||||
i.id = 'negate'+n+'-btn';
|
||||
i.onclick = chart_neg_event;
|
||||
i.value = 'NOT';
|
||||
add_and.appendChild(i);
|
||||
// Add hidden input for negate button
|
||||
i = document.createElement('input');
|
||||
i.type = 'hidden';
|
||||
i.name = i.id = 'negate'+n;
|
||||
document.getElementById('chartR').appendChild(i);
|
||||
}
|
||||
if (add_or)
|
||||
chart_add_btn(add_or, 'OR');
|
||||
}
|
||||
|
||||
function chart_neg(btn)
|
||||
{
|
||||
var n = btn.id.substr(6, btn.id.length-10); // negateN
|
||||
var i = document.getElementById('negate'+n);
|
||||
i.value = i.value ? '' : '1';
|
||||
btn.className = 'chart_not_' + (i.value ? 'c' : 'u');
|
||||
var c = document.getElementById('chart'+n);
|
||||
if (i.value)
|
||||
c.className += ' _neg';
|
||||
else
|
||||
c.className = c.className.replace(/ _neg/, '');
|
||||
}
|
||||
|
||||
function chart_add_second_event()
|
||||
{
|
||||
chart_add_second(this);
|
||||
}
|
||||
|
||||
function chart_neg_event()
|
||||
{
|
||||
chart_neg(this);
|
||||
}
|
||||
function chart_add_second(btn)
|
||||
{
|
||||
var n = btn.id.substr(5, btn.id.length-9);
|
||||
// Transform <div> to <fieldset>
|
||||
var d = document.getElementById('chart'+n);
|
||||
d.id = 'divchart'+n; // prevent id collisions
|
||||
btn.id = 'btnchart'+n; // prevent id collisions
|
||||
var op = (n != 'R' && n.indexOf('-') < 0 ? 'and' : 'or');
|
||||
// Create <fieldset>
|
||||
var f = document.createElement('fieldset');
|
||||
f.id = 'chart'+n;
|
||||
f.className = 'chart _'+op;
|
||||
var legend_html = op.toUpperCase()+' '+
|
||||
'<input type="button" value="+" class="chart_add_button" id="chart'+n+'-btn" onclick="chart_add(this.id)" />';
|
||||
if (op == 'and')
|
||||
{
|
||||
// Move [NOT] to the legend for 'AND' charts
|
||||
var neg = document.getElementById('negate'+n);
|
||||
legend_html +=
|
||||
'<input type="button" value="NOT" class="chart_not_'+(neg.value ? 'c' : 'u')+'"'+
|
||||
' style="font-size: 85%" id="negate'+n+'-btn" onclick="chart_neg(this)" />';
|
||||
if (neg.value)
|
||||
f.className += ' _neg';
|
||||
neg = document.getElementById('negate'+n+'-btn');
|
||||
neg.parentNode.removeChild(neg);
|
||||
}
|
||||
// Create <legend>
|
||||
var l = document.createElement('legend');
|
||||
l.className = '_'+op;
|
||||
l.innerHTML = legend_html;
|
||||
f.appendChild(l);
|
||||
d.parentNode.insertBefore(f, d);
|
||||
btn.parentNode.removeChild(btn);
|
||||
d.parentNode.removeChild(d);
|
||||
while (d.childNodes.length)
|
||||
f.appendChild(d.childNodes[0]);
|
||||
// Add an operand
|
||||
chart_add('chart'+n+'-btn');
|
||||
}
|
||||
|
||||
function chart_add_btn(d, s)
|
||||
{
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.id = d.id+'-btn';
|
||||
i.onclick = chart_add_second_event;
|
||||
i.value = s;
|
||||
d.appendChild(document.createTextNode(' '));
|
||||
d.appendChild(i);
|
||||
}
|
||||
|
||||
// Find next available number for div with prefix 'n'
|
||||
function chart_add_div(d, n)
|
||||
{
|
||||
var i, nd;
|
||||
for (i = 0; document.getElementById(n+i); i++);
|
||||
nd = document.createElement('div');
|
||||
nd.id = n+i;
|
||||
nd.className = 'chart';
|
||||
d.appendChild(nd);
|
||||
return nd;
|
||||
}
|
||||
|
||||
// Copy 'fieldx-x-x' or 'typex-x-x' selectbox
|
||||
function chart_copy_select(cp_id, new_id)
|
||||
{
|
||||
var s = document.createElement('select');
|
||||
s.id = s.name = new_id;
|
||||
s.innerHTML = document.getElementById(cp_id).innerHTML;
|
||||
s.selectedIndex = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
// Add another term into chart when clicked on button with id=btnid
|
||||
function chart_add(btnid)
|
||||
{
|
||||
var d, i, add_and, add_or, n;
|
||||
d = document.getElementById(btnid.substr(0, btnid.length-4)); // chartN-btn
|
||||
if (d.id == 'chartR')
|
||||
add_and = d = chart_add_div(d, 'chart');
|
||||
if (d.id.indexOf('-') < 0)
|
||||
add_or = d = chart_add_div(d, d.id+'-');
|
||||
var cn = d.id.substr(5);
|
||||
for (i = 0; document.getElementById('field'+cn+'-'+i); i++);
|
||||
cn = cn+'-'+i;
|
||||
if (!add_or)
|
||||
d.appendChild(document.createElement('br'));
|
||||
// Append field-type-value inputs
|
||||
d.appendChild(chart_copy_select('field0-0-0', 'field'+cn));
|
||||
d.appendChild(chart_copy_select('type0-0-0', 'type'+cn));
|
||||
s = document.createElement('input');
|
||||
s.id = s.name = "value"+cn;
|
||||
s.size = 40;
|
||||
d.appendChild(s);
|
||||
if (add_and)
|
||||
{
|
||||
chart_add_btn(add_and, 'AND');
|
||||
// Add negate button
|
||||
var n = add_and.id.substr(5);
|
||||
var i = document.createElement('input');
|
||||
i.type = 'button';
|
||||
i.className = 'chart_not_u';
|
||||
i.id = 'negate'+n+'-btn';
|
||||
i.onclick = chart_neg_event;
|
||||
i.value = 'NOT';
|
||||
add_and.appendChild(i);
|
||||
// Add hidden input for negate button
|
||||
i = document.createElement('input');
|
||||
i.type = 'hidden';
|
||||
i.name = i.id = 'negate'+n;
|
||||
document.getElementById('chartR').appendChild(i);
|
||||
}
|
||||
if (add_or)
|
||||
chart_add_btn(add_or, 'OR');
|
||||
}
|
||||
|
||||
function chart_neg(btn)
|
||||
{
|
||||
var n = btn.id.substr(6, btn.id.length-10); // negateN
|
||||
var i = document.getElementById('negate'+n);
|
||||
i.value = i.value ? '' : '1';
|
||||
btn.className = 'chart_not_' + (i.value ? 'c' : 'u');
|
||||
var c = document.getElementById('chart'+n);
|
||||
if (i.value)
|
||||
c.className += ' _neg';
|
||||
else
|
||||
c.className = c.className.replace(/ _neg/, '');
|
||||
}
|
||||
|
||||
function chart_add_second_event()
|
||||
{
|
||||
chart_add_second(this);
|
||||
}
|
||||
|
||||
function chart_neg_event()
|
||||
{
|
||||
chart_neg(this);
|
||||
}
|
|
@ -2,22 +2,22 @@
|
|||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
*
|
||||
* The Original Code is the Bugzilla Bug Tracking System.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Mike Shaver <shaver@mozilla.org>
|
||||
* Christian Reis <kiko@async.com.br>
|
||||
* André Batosti <batosti@async.com.br>
|
||||
* André Batosti <batosti@async.com.br>
|
||||
*/
|
||||
|
||||
if (!Node) {
|
||||
|
@ -130,7 +130,7 @@ function duplicated(element) {
|
|||
highlighted = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
highlighted = element;
|
||||
var elem = document.getElementById(element);
|
||||
highlightedclass = elem.className;
|
||||
|
|
362
js/field.js
362
js/field.js
|
@ -18,135 +18,16 @@
|
|||
* Guy Pyrzak <guy.pyrzak@gmail.com>
|
||||
*/
|
||||
|
||||
/* This library assumes that the needed YUI libraries have been loaded
|
||||
already. */
|
||||
|
||||
function createCalendar(name) {
|
||||
var cal = new YAHOO.widget.Calendar('calendar_' + name,
|
||||
'con_calendar_' + name);
|
||||
YAHOO.bugzilla['calendar_' + name] = cal;
|
||||
var field = document.getElementById(name);
|
||||
cal.selectEvent.subscribe(setFieldFromCalendar, field, false);
|
||||
updateCalendarFromField(field);
|
||||
cal.render();
|
||||
}
|
||||
|
||||
/* The onclick handlers for the button that shows the calendar. */
|
||||
function showCalendar(field_name) {
|
||||
var calendar = YAHOO.bugzilla["calendar_" + field_name];
|
||||
var field = document.getElementById(field_name);
|
||||
var button = document.getElementById('button_calendar_' + field_name);
|
||||
|
||||
bz_overlayBelow(calendar.oDomContainer, field);
|
||||
calendar.show();
|
||||
button.onclick = function() { hideCalendar(field_name); };
|
||||
|
||||
// Because of the way removeListener works, this has to be a function
|
||||
// attached directly to this calendar.
|
||||
calendar.bz_myBodyCloser = function(event) {
|
||||
var container = this.oDomContainer;
|
||||
var target = YAHOO.util.Event.getTarget(event);
|
||||
if (target != container && target != button
|
||||
&& !YAHOO.util.Dom.isAncestor(container, target))
|
||||
{
|
||||
hideCalendar(field_name);
|
||||
}
|
||||
};
|
||||
|
||||
// If somebody clicks outside the calendar, hide it.
|
||||
YAHOO.util.Event.addListener(document.body, 'click',
|
||||
calendar.bz_myBodyCloser, calendar, true);
|
||||
|
||||
// Make Esc close the calendar.
|
||||
calendar.bz_escCal = function (event) {
|
||||
var key = YAHOO.util.Event.getCharCode(event);
|
||||
if (key == 27) {
|
||||
hideCalendar(field_name);
|
||||
}
|
||||
};
|
||||
YAHOO.util.Event.addListener(document.body, 'keydown', calendar.bz_escCal);
|
||||
}
|
||||
|
||||
function hideCalendar(field_name) {
|
||||
var cal = YAHOO.bugzilla["calendar_" + field_name];
|
||||
cal.hide();
|
||||
var button = document.getElementById('button_calendar_' + field_name);
|
||||
button.onclick = function() { showCalendar(field_name); };
|
||||
YAHOO.util.Event.removeListener(document.body, 'click',
|
||||
cal.bz_myBodyCloser);
|
||||
YAHOO.util.Event.removeListener(document.body, 'keydown', cal.bz_escCal);
|
||||
}
|
||||
|
||||
/* This is the selectEvent for our Calendar objects on our custom
|
||||
* DateTime fields.
|
||||
*/
|
||||
function setFieldFromCalendar(type, args, date_field) {
|
||||
var dates = args[0];
|
||||
var setDate = dates[0];
|
||||
|
||||
// We can't just write the date straight into the field, because there
|
||||
// might already be a time there.
|
||||
var timeRe = /\b(\d{1,2}):(\d\d)(?::(\d\d))?/;
|
||||
var currentTime = timeRe.exec(date_field.value);
|
||||
var d = new Date(setDate[0], setDate[1] - 1, setDate[2]);
|
||||
if (currentTime) {
|
||||
d.setHours(currentTime[1], currentTime[2]);
|
||||
if (currentTime[3]) {
|
||||
d.setSeconds(currentTime[3]);
|
||||
}
|
||||
}
|
||||
|
||||
var year = d.getFullYear();
|
||||
// JavaScript's "Date" represents January as 0 and December as 11.
|
||||
var month = d.getMonth() + 1;
|
||||
if (month < 10) month = '0' + String(month);
|
||||
var day = d.getDate();
|
||||
if (day < 10) day = '0' + String(day);
|
||||
var dateStr = year + '-' + month + '-' + day;
|
||||
|
||||
if (currentTime) {
|
||||
var minutes = d.getMinutes();
|
||||
if (minutes < 10) minutes = '0' + String(minutes);
|
||||
var seconds = d.getSeconds();
|
||||
if (seconds > 0 && seconds < 10) {
|
||||
seconds = '0' + String(seconds);
|
||||
}
|
||||
|
||||
dateStr = dateStr + ' ' + d.getHours() + ':' + minutes;
|
||||
if (seconds) dateStr = dateStr + ':' + seconds;
|
||||
}
|
||||
|
||||
date_field.value = dateStr;
|
||||
hideCalendar(date_field.id);
|
||||
}
|
||||
|
||||
/* Sets the calendar based on the current field value.
|
||||
*/
|
||||
function updateCalendarFromField(date_field) {
|
||||
var dateRe = /(\d\d\d\d)-(\d\d?)-(\d\d?)/;
|
||||
var pieces = dateRe.exec(date_field.value);
|
||||
if (pieces) {
|
||||
var cal = YAHOO.bugzilla["calendar_" + date_field.id];
|
||||
cal.select(new Date(pieces[1], pieces[2] - 1, pieces[3]));
|
||||
var selectedArray = cal.getSelectedDates();
|
||||
var selected = selectedArray[0];
|
||||
cal.cfg.setProperty("pagedate", (selected.getMonth() + 1) + '/'
|
||||
+ selected.getFullYear());
|
||||
cal.render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Hide input fields and show the text with (edit) next to it */
|
||||
function hideEditableField( container, input, action, field_id, original_value ) {
|
||||
YAHOO.util.Dom.removeClass(container, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(input, 'bz_default_hidden');
|
||||
YAHOO.util.Event.addListener(action, 'click', showEditableField,
|
||||
new Array(container, input));
|
||||
if(field_id != ""){
|
||||
YAHOO.util.Event.addListener(window, 'load', checkForChangedFieldValues,
|
||||
new Array(container, input, field_id, original_value));
|
||||
}
|
||||
/* Hide input fields and show the text with (edit) next to it */
|
||||
function hideEditableField( container, input, action, field_id, original_value )
|
||||
{
|
||||
removeClass(container, 'bz_default_hidden');
|
||||
addClass(input, 'bz_default_hidden');
|
||||
addListener(action, 'click', function(ev) { return showEditableField(ev, [ container, input ]); });
|
||||
if (field_id != "")
|
||||
addListener(window, 'load', function(ev) {
|
||||
return checkForChangedFieldValues(ev, [ container, input, field_id, original_value ])
|
||||
});
|
||||
}
|
||||
|
||||
/* showEditableField (e, ContainerInputArray)
|
||||
|
@ -158,29 +39,31 @@ function hideEditableField( container, input, action, field_id, original_value )
|
|||
* var ContainerInputArray[1]: the input area and label that will be displayed
|
||||
*
|
||||
*/
|
||||
function showEditableField (e, ContainerInputArray) {
|
||||
function showEditableField(e, ContainerInputArray)
|
||||
{
|
||||
var inputs = new Array();
|
||||
var inputArea = YAHOO.util.Dom.get(ContainerInputArray[1]);
|
||||
if ( ! inputArea ){
|
||||
YAHOO.util.Event.preventDefault(e);
|
||||
return;
|
||||
var inputArea = ContainerInputArray[1];
|
||||
if (!inputArea)
|
||||
{
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
YAHOO.util.Dom.addClass(ContainerInputArray[0], 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(inputArea, 'bz_default_hidden');
|
||||
if ( inputArea.tagName.toLowerCase() == "input" ) {
|
||||
addClass(ContainerInputArray[0], 'bz_default_hidden');
|
||||
removeClass(inputArea, 'bz_default_hidden');
|
||||
if (inputArea.tagName.toLowerCase() == "input")
|
||||
inputs.push(inputArea);
|
||||
} else {
|
||||
else
|
||||
inputs = inputArea.getElementsByTagName('input');
|
||||
}
|
||||
if ( inputs.length > 0 ) {
|
||||
if (inputs.length > 0)
|
||||
{
|
||||
// focus on the first field, this makes it easier to edit
|
||||
inputs[0].focus();
|
||||
inputs[0].select();
|
||||
}
|
||||
YAHOO.util.Event.preventDefault(e);
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* checkForChangedFieldValues(e, array )
|
||||
* Function checks if after the autocomplete by the browser if the values match the originals.
|
||||
* If they don't match then hide the text and show the input so users don't get confused.
|
||||
|
@ -189,10 +72,10 @@ function showEditableField (e, ContainerInputArray) {
|
|||
* var ContainerInputArray: An array containing the (edit) and text area and the input being displayed
|
||||
* var ContainerInputArray[0]: the conainer that will be hidden usually shows the (edit) text
|
||||
* var ContainerInputArray[1]: the input area and label that will be displayed
|
||||
* var ContainerInputArray[2]: the field that is on the page, might get changed by browser autocomplete
|
||||
* var ContainerInputArray[2]: the field that is on the page, might get changed by browser autocomplete
|
||||
* var ContainerInputArray[3]: the original value from the page loading.
|
||||
*
|
||||
*/
|
||||
*/
|
||||
function checkForChangedFieldValues(e, ContainerInputArray ) {
|
||||
var el = document.getElementById(ContainerInputArray[2]);
|
||||
var unhide = false;
|
||||
|
@ -207,174 +90,177 @@ function checkForChangedFieldValues(e, ContainerInputArray ) {
|
|||
if ( set_default ) {
|
||||
if(set_default.checked){
|
||||
unhide = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(unhide){
|
||||
YAHOO.util.Dom.addClass(ContainerInputArray[0], 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(ContainerInputArray[1], 'bz_default_hidden');
|
||||
if(unhide)
|
||||
{
|
||||
addClass(ContainerInputArray[0], 'bz_default_hidden');
|
||||
removeClass(ContainerInputArray[1], 'bz_default_hidden');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function hideAliasAndSummary(short_desc_value, alias_value) {
|
||||
function hideAliasAndSummary(short_desc_value, alias_value)
|
||||
{
|
||||
// check the short desc field
|
||||
hideEditableField( 'summary_alias_container','summary_alias_input',
|
||||
'editme_action','short_desc', short_desc_value);
|
||||
hideEditableField(
|
||||
'summary_alias_container','summary_alias_input',
|
||||
'editme_action','short_desc', short_desc_value
|
||||
);
|
||||
// check that the alias hasn't changed
|
||||
var bz_alias_check_array = new Array('summary_alias_container',
|
||||
'summary_alias_input', 'alias', alias_value);
|
||||
YAHOO.util.Event.addListener( window, 'load', checkForChangedFieldValues,
|
||||
bz_alias_check_array);
|
||||
var bz_alias_check_array = [
|
||||
'summary_alias_container', 'summary_alias_input', 'alias', alias_value
|
||||
];
|
||||
addListener(window, 'load',
|
||||
function(ev) { return checkForChangedFieldValues(ev, bz_alias_check_array) }
|
||||
);
|
||||
}
|
||||
|
||||
function showPeopleOnChange( field_id_list ) {
|
||||
for(var i = 0; i < field_id_list.length; i++) {
|
||||
YAHOO.util.Event.addListener( field_id_list[i],'change', showEditableField,
|
||||
new Array('bz_qa_contact_edit_container',
|
||||
'bz_qa_contact_input'));
|
||||
YAHOO.util.Event.addListener( field_id_list[i],'change',showEditableField,
|
||||
new Array('bz_assignee_edit_container',
|
||||
'bz_assignee_input'));
|
||||
function showPeopleOnChange(field_id_list)
|
||||
{
|
||||
for (var i = 0; i < field_id_list.length; i++)
|
||||
{
|
||||
addListener(field_id_list[i], 'change',
|
||||
function(ev) { return showEditableField(ev, [ 'bz_qa_contact_edit_container', 'bz_qa_contact_input' ]) });
|
||||
addListener(field_id_list[i], 'change',
|
||||
function(ev) { return showEditableField(ev, [ 'bz_assignee_edit_container', 'bz_assignee_input']) });
|
||||
}
|
||||
}
|
||||
|
||||
function assignToDefaultOnChange(field_id_list) {
|
||||
showPeopleOnChange( field_id_list );
|
||||
for(var i = 0; i < field_id_list.length; i++) {
|
||||
YAHOO.util.Event.addListener( field_id_list[i],'change', setDefaultCheckbox,
|
||||
'set_default_assignee');
|
||||
YAHOO.util.Event.addListener( field_id_list[i],'change',setDefaultCheckbox,
|
||||
'set_default_qa_contact');
|
||||
function assignToDefaultOnChange(field_id_list)
|
||||
{
|
||||
showPeopleOnChange(field_id_list);
|
||||
for (var i = 0; i < field_id_list.length; i++)
|
||||
{
|
||||
addListener(field_id_list[i], 'change',
|
||||
function(ev) { return setDefaultCheckbox(ev, 'set_default_assignee') });
|
||||
addListener(field_id_list[i], 'change',
|
||||
function(ev) { return setDefaultCheckbox(ev, 'set_default_qa_contact') });
|
||||
}
|
||||
}
|
||||
|
||||
function initDefaultCheckbox(field_id){
|
||||
YAHOO.util.Event.addListener( 'set_default_' + field_id,'change', boldOnChange,
|
||||
'set_default_' + field_id);
|
||||
YAHOO.util.Event.addListener( window,'load', checkForChangedFieldValues,
|
||||
new Array( 'bz_' + field_id + '_edit_container',
|
||||
'bz_' + field_id + '_input',
|
||||
'set_default_' + field_id ,'1'));
|
||||
|
||||
YAHOO.util.Event.addListener( window, 'load', boldOnChange,
|
||||
'set_default_' + field_id );
|
||||
function initDefaultCheckbox(field_id)
|
||||
{
|
||||
addListener('set_default_'+field_id, 'change',
|
||||
function(ev) { return boldOnChange(ev, 'set_default_'+field_id) });
|
||||
addListener(window, 'load',
|
||||
function(ev) { return checkForChangedFieldValues(ev, [
|
||||
'bz_'+field_id+'_edit_container', 'bz_'+field_id+'_input',
|
||||
'set_default_'+field_id, '1' ]) });
|
||||
addListener(window, 'load',
|
||||
function(ev) { return boldOnChange(ev, 'set_default_'+field_id) });
|
||||
}
|
||||
|
||||
function showHideStatusItems(e, dupArrayInfo) {
|
||||
function showHideStatusItems(is_duplicate, initial_status)
|
||||
{
|
||||
var el = document.getElementById('bug_status');
|
||||
// finish doing stuff based on the selection.
|
||||
if ( el ) {
|
||||
if (el)
|
||||
{
|
||||
showDuplicateItem(el);
|
||||
|
||||
// Make sure that fields whose visibility or values are controlled
|
||||
// by "resolution" behave properly when resolution is hidden.
|
||||
var resolution = document.getElementById('resolution');
|
||||
if (resolution && resolution.options[0].value != '') {
|
||||
if (resolution && resolution.options[0].value != '')
|
||||
{
|
||||
resolution.bz_lastSelected = resolution.selectedIndex;
|
||||
var emptyOption = new Option('', '');
|
||||
resolution.insertBefore(emptyOption, resolution.options[0]);
|
||||
emptyOption.selected = true;
|
||||
}
|
||||
YAHOO.util.Dom.addClass('resolution_settings', 'bz_default_hidden');
|
||||
if (document.getElementById('resolution_settings_warning')) {
|
||||
YAHOO.util.Dom.addClass('resolution_settings_warning',
|
||||
'bz_default_hidden');
|
||||
}
|
||||
YAHOO.util.Dom.addClass('duplicate_display', 'bz_default_hidden');
|
||||
|
||||
|
||||
if ( (el.value == dupArrayInfo[1] && dupArrayInfo[0] == "is_duplicate")
|
||||
|| bz_isValueInArray(close_status_array, el.value) )
|
||||
addClass('resolution_settings', 'bz_default_hidden');
|
||||
if (document.getElementById('resolution_settings_warning'))
|
||||
addClass('resolution_settings_warning', 'bz_default_hidden');
|
||||
addClass('duplicate_display', 'bz_default_hidden');
|
||||
if (el.value == initial_status && is_duplicate == "is_duplicate" ||
|
||||
bz_isValueInArray(close_status_array, el.value))
|
||||
{
|
||||
YAHOO.util.Dom.removeClass('resolution_settings',
|
||||
'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass('resolution_settings_warning',
|
||||
'bz_default_hidden');
|
||||
removeClass('resolution_settings', 'bz_default_hidden');
|
||||
removeClass('resolution_settings_warning', 'bz_default_hidden');
|
||||
|
||||
// Remove the blank option we inserted.
|
||||
if (resolution && resolution.options[0].value == '') {
|
||||
if (resolution && resolution.options[0].value == '')
|
||||
{
|
||||
resolution.removeChild(resolution.options[0]);
|
||||
resolution.selectedIndex = resolution.bz_lastSelected;
|
||||
}
|
||||
}
|
||||
|
||||
if (resolution) {
|
||||
if (resolution)
|
||||
bz_fireEvent(resolution, 'change');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showDuplicateItem(e) {
|
||||
function showDuplicateItem(e)
|
||||
{
|
||||
var resolution = document.getElementById('resolution');
|
||||
var bug_status = document.getElementById('bug_status');
|
||||
var dup_id = document.getElementById('dup_id');
|
||||
if (resolution) {
|
||||
if (resolution.value == 'DUPLICATE' && bz_isValueInArray( close_status_array, bug_status.value) ) {
|
||||
if (resolution && dup_id)
|
||||
{
|
||||
if (resolution.value == 'DUPLICATE' && bz_isValueInArray(close_status_array, bug_status.value))
|
||||
{
|
||||
// hide resolution show duplicate
|
||||
YAHOO.util.Dom.removeClass('duplicate_settings',
|
||||
'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass('dup_id_discoverable', 'bz_default_hidden');
|
||||
removeClass('duplicate_settings', 'bz_default_hidden');
|
||||
addClass('dup_id_discoverable', 'bz_default_hidden');
|
||||
// check to make sure the field is visible or IE throws errors
|
||||
if( ! YAHOO.util.Dom.hasClass( dup_id, 'bz_default_hidden' ) ){
|
||||
if (!hasClass(dup_id, 'bz_default_hidden'))
|
||||
{
|
||||
dup_id.focus();
|
||||
dup_id.select();
|
||||
}
|
||||
}
|
||||
else {
|
||||
YAHOO.util.Dom.addClass('duplicate_settings', 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass('dup_id_discoverable',
|
||||
'bz_default_hidden');
|
||||
else
|
||||
{
|
||||
addClass('duplicate_settings', 'bz_default_hidden');
|
||||
removeClass('dup_id_discoverable', 'bz_default_hidden');
|
||||
dup_id.blur();
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.preventDefault(e); //prevents the hyperlink from going to the url in the href.
|
||||
// Prevent the hyperlink from going to the url in the href:
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function setResolutionToDuplicate(e, duplicate_or_move_bug_status) {
|
||||
function setResolutionToDuplicate(duplicate_or_move_bug_status)
|
||||
{
|
||||
var status = document.getElementById('bug_status');
|
||||
var resolution = document.getElementById('resolution');
|
||||
YAHOO.util.Dom.addClass('dup_id_discoverable', 'bz_default_hidden');
|
||||
addClass('dup_id_discoverable', 'bz_default_hidden');
|
||||
status.value = duplicate_or_move_bug_status;
|
||||
bz_fireEvent(status, 'change');
|
||||
resolution.value = "DUPLICATE";
|
||||
bz_fireEvent(resolution, 'change');
|
||||
YAHOO.util.Event.preventDefault(e);
|
||||
if (e.preventDefault) e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function setDefaultCheckbox(e, field_id ) {
|
||||
function setDefaultCheckbox(e, field_id)
|
||||
{
|
||||
var el = document.getElementById(field_id);
|
||||
var elLabel = document.getElementById(field_id + "_label");
|
||||
if( el && elLabel ) {
|
||||
if (el && elLabel)
|
||||
{
|
||||
el.checked = "true";
|
||||
YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'bold');
|
||||
elLabel.style.fontWeight = bold;
|
||||
}
|
||||
}
|
||||
|
||||
function boldOnChange(e, field_id){
|
||||
function boldOnChange(e, field_id)
|
||||
{
|
||||
var el = document.getElementById(field_id);
|
||||
var elLabel = document.getElementById(field_id + "_label");
|
||||
if( el && elLabel ) {
|
||||
if( el.checked ){
|
||||
YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'bold');
|
||||
}
|
||||
else{
|
||||
YAHOO.util.Dom.setStyle(elLabel, 'font-weight', 'normal');
|
||||
}
|
||||
}
|
||||
if (el && elLabel)
|
||||
elLabel.style.fontWeight = el.checked ? 'bold' : 'normal';
|
||||
}
|
||||
|
||||
function updateCommentTagControl(checkbox, form) {
|
||||
if (checkbox.checked) {
|
||||
form.comment.className='bz_private';
|
||||
} else {
|
||||
form.comment.className='';
|
||||
}
|
||||
function updateCommentTagControl(checkbox, form)
|
||||
{
|
||||
form.comment.className = checkbox.checked ? 'bz_private' : '';
|
||||
}
|
||||
|
||||
// A convenience function to generate the "id" tag of an <option>
|
||||
// based on the numeric id that Bugzilla uses for that value.
|
||||
function _value_id(field_name, id) {
|
||||
function _value_id(field_name, id)
|
||||
{
|
||||
return 'v' + id + '_' + field_name;
|
||||
}
|
||||
|
|
94
js/flag.js
94
js/flag.js
|
@ -28,59 +28,61 @@
|
|||
// the user is requesting the corresponding flag.
|
||||
function toggleRequesteeField(flagField, no_focus)
|
||||
{
|
||||
// Convert the ID of the flag field into the ID of its corresponding
|
||||
// requestee field and then use the ID to get the field.
|
||||
var id = flagField.name.replace(/flag(_type)?-(\d+)/, "requestee$1-$2");
|
||||
var requesteeField = document.getElementById(id);
|
||||
if (!requesteeField) return;
|
||||
// Convert the ID of the flag field into the ID of its corresponding
|
||||
// requestee field and then use the ID to get the field.
|
||||
var id = flagField.name.replace(/flag(_type)?-(\d+)/, "requestee$1-$2");
|
||||
var requesteeField = document.getElementById(id);
|
||||
if (!requesteeField) return;
|
||||
|
||||
// Enable or disable the requestee field based on the value
|
||||
// of the flag field.
|
||||
if (flagField.value == "?") {
|
||||
requesteeField.disabled = false;
|
||||
if (!no_focus) requesteeField.focus();
|
||||
} else {
|
||||
requesteeField.disabled = true;
|
||||
}
|
||||
// For combo-boxes
|
||||
var rcombosel = document.getElementById(id+'_s');
|
||||
if (rcombosel && (rcombosel.disabled = requesteeField.disabled))
|
||||
menuforusers_showmulti(id);
|
||||
// Enable or disable the requestee field based on the value
|
||||
// of the flag field.
|
||||
if (flagField.value == "?")
|
||||
{
|
||||
requesteeField.disabled = false;
|
||||
if (!no_focus)
|
||||
requesteeField.focus();
|
||||
}
|
||||
else
|
||||
requesteeField.disabled = true;
|
||||
// For combo-boxes
|
||||
var rcombosel = document.getElementById(id+'_s');
|
||||
if (rcombosel && (rcombosel.disabled = requesteeField.disabled))
|
||||
menuforusers_showmulti(id);
|
||||
}
|
||||
|
||||
// Disables requestee fields when the window is loaded since they shouldn't
|
||||
// be enabled until the user requests that flag type.
|
||||
function disableRequesteeFields()
|
||||
{
|
||||
var inputElements = document.getElementsByTagName("input");
|
||||
var selectElements = document.getElementsByTagName("select");
|
||||
//You cannot update Node lists, so you must create an array to combine the NodeLists
|
||||
var allElements = [];
|
||||
for( var i=0; i < inputElements.length; i++ ) {
|
||||
allElements[allElements.length] = inputElements.item(i);
|
||||
}
|
||||
for( var i=0; i < selectElements.length; i++ ) { //Combine inputs with selects
|
||||
allElements[allElements.length] = selectElements.item(i);
|
||||
}
|
||||
var inputElement, id, flagField;
|
||||
for ( var i=0 ; i<allElements.length ; i++ )
|
||||
{
|
||||
inputElement = allElements[i];
|
||||
if (inputElement.name.search(/^requestee(_type)?-(\d+)$/) != -1)
|
||||
var inputElements = document.getElementsByTagName("input");
|
||||
var selectElements = document.getElementsByTagName("select");
|
||||
// You cannot update Node lists, so you must create an array to combine the NodeLists
|
||||
var allElements = [];
|
||||
for (var i = 0; i < inputElements.length; i++)
|
||||
allElements.push(inputElements.item(i));
|
||||
// Combine inputs with selects
|
||||
for (var i = 0; i < selectElements.length; i++)
|
||||
allElements.push(selectElements.item(i));
|
||||
var inputElement, id, flagField;
|
||||
for (var i = 0; i < allElements.length; i++)
|
||||
{
|
||||
// Convert the ID of the requestee field into the ID of its corresponding
|
||||
// flag field and then use the ID to get the field.
|
||||
id = inputElement.name.replace(/requestee(_type)?-(\d+)/, "flag$1-$2");
|
||||
flagField = document.getElementById(id);
|
||||
if (flagField && flagField.value != "?")
|
||||
{
|
||||
inputElement.disabled = true;
|
||||
// For combo-boxes
|
||||
inputElement = document.getElementById(inputElement.id+'_s');
|
||||
if (inputElement)
|
||||
inputElement.disabled = true;
|
||||
}
|
||||
inputElement = allElements[i];
|
||||
if (inputElement.name.search(/^requestee(_type)?-(\d+)$/) != -1)
|
||||
{
|
||||
// Convert the ID of the requestee field into the ID of its corresponding
|
||||
// flag field and then use the ID to get the field.
|
||||
id = inputElement.name.replace(/requestee(_type)?-(\d+)/, "flag$1-$2");
|
||||
flagField = document.getElementById(id);
|
||||
if (flagField && flagField.value != "?")
|
||||
{
|
||||
inputElement.disabled = true;
|
||||
// For combo-boxes
|
||||
inputElement = document.getElementById(inputElement.id+'_s');
|
||||
if (inputElement)
|
||||
inputElement.disabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
YAHOO.util.Event.addListener(window, "load", disableRequesteeFields);
|
||||
|
||||
addListener(window, "load", disableRequesteeFields);
|
||||
|
|
309
js/global.js
309
js/global.js
|
@ -17,254 +17,191 @@
|
|||
|
||||
var mini_login_constants;
|
||||
|
||||
function show_mini_login_form( suffix ) {
|
||||
function show_mini_login_form( suffix )
|
||||
{
|
||||
var login_link = document.getElementById('login_link' + suffix);
|
||||
var login_form = document.getElementById('mini_login' + suffix);
|
||||
var account_container = document.getElementById('new_account_container'
|
||||
+ suffix);
|
||||
|
||||
YAHOO.util.Dom.addClass(login_link, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(login_form, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(account_container, 'bz_default_hidden');
|
||||
var account_container = document.getElementById('new_account_container' + suffix);
|
||||
addClass(login_link, 'bz_default_hidden');
|
||||
removeClass(login_form, 'bz_default_hidden');
|
||||
addClass(account_container, 'bz_default_hidden');
|
||||
login_form._shown = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function hide_mini_login_form( suffix ) {
|
||||
function hide_mini_login_form( suffix )
|
||||
{
|
||||
var login_link = document.getElementById('login_link' + suffix);
|
||||
var login_form = document.getElementById('mini_login' + suffix);
|
||||
var account_container = document.getElementById('new_account_container'
|
||||
+ suffix);
|
||||
|
||||
YAHOO.util.Dom.removeClass(login_link, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(login_form, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(account_container, 'bz_default_hidden');
|
||||
var account_container = document.getElementById('new_account_container' + suffix);
|
||||
removeClass(login_link, 'bz_default_hidden');
|
||||
addClass(login_form, 'bz_default_hidden');
|
||||
removeClass(account_container, 'bz_default_hidden');
|
||||
return false;
|
||||
}
|
||||
|
||||
function show_forgot_form( suffix ) {
|
||||
function show_forgot_form( suffix )
|
||||
{
|
||||
var forgot_link = document.getElementById('forgot_link' + suffix);
|
||||
var forgot_form = document.getElementById('forgot_form' + suffix);
|
||||
var login_container = document.getElementById('mini_login_container'
|
||||
+ suffix);
|
||||
YAHOO.util.Dom.addClass(forgot_link, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(forgot_form, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(login_container, 'bz_default_hidden');
|
||||
var login_container = document.getElementById('mini_login_container' + suffix);
|
||||
addClass(forgot_link, 'bz_default_hidden');
|
||||
removeClass(forgot_form, 'bz_default_hidden');
|
||||
addClass(login_container, 'bz_default_hidden');
|
||||
return false;
|
||||
}
|
||||
|
||||
function hide_forgot_form( suffix ) {
|
||||
function hide_forgot_form( suffix )
|
||||
{
|
||||
var forgot_link = document.getElementById('forgot_link' + suffix);
|
||||
var forgot_form = document.getElementById('forgot_form' + suffix);
|
||||
var login_container = document.getElementById('mini_login_container'
|
||||
+ suffix);
|
||||
YAHOO.util.Dom.removeClass(forgot_link, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(forgot_form, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(login_container, 'bz_default_hidden');
|
||||
var login_container = document.getElementById('mini_login_container' + suffix);
|
||||
removeClass(forgot_link, 'bz_default_hidden');
|
||||
addClass(forgot_form, 'bz_default_hidden');
|
||||
removeClass(login_container, 'bz_default_hidden');
|
||||
return false;
|
||||
}
|
||||
|
||||
function init_mini_login_form( suffix ) {
|
||||
function init_mini_login_form( suffix )
|
||||
{
|
||||
var mini_login = document.getElementById('Bugzilla_login' + suffix );
|
||||
var mini_password = document.getElementById('Bugzilla_password' + suffix );
|
||||
var mini_dummy = document.getElementById(
|
||||
'Bugzilla_password_dummy' + suffix);
|
||||
// If the login and password are blank when the page loads, we display
|
||||
// "login" and "password" in the boxes by default.
|
||||
if (mini_login.value == "" && mini_password.value == "") {
|
||||
if (mini_login.value == "" && mini_password.value == "")
|
||||
{
|
||||
mini_login.value = mini_login_constants.login;
|
||||
YAHOO.util.Dom.addClass(mini_login, "bz_mini_login_help");
|
||||
YAHOO.util.Dom.addClass(mini_password, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.removeClass(mini_dummy, 'bz_default_hidden');
|
||||
addClass(mini_login, "bz_mini_login_help");
|
||||
addClass(mini_password, 'bz_default_hidden');
|
||||
removeClass(mini_dummy, 'bz_default_hidden');
|
||||
}
|
||||
else {
|
||||
else
|
||||
show_mini_login_form(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the words "login" and "password" from the form when you click
|
||||
// in one of the boxes. We clear them both when you click in either box
|
||||
// so that the browser's password-autocomplete can work.
|
||||
function mini_login_on_focus( suffix ) {
|
||||
var mini_login = document.getElementById('Bugzilla_login' + suffix );
|
||||
var mini_password = document.getElementById('Bugzilla_password' + suffix );
|
||||
var mini_dummy = document.getElementById(
|
||||
'Bugzilla_password_dummy' + suffix);
|
||||
function mini_login_on_focus(suffix)
|
||||
{
|
||||
var mini_login = document.getElementById('Bugzilla_login' + suffix);
|
||||
var mini_password = document.getElementById('Bugzilla_password' + suffix);
|
||||
var mini_dummy = document.getElementById('Bugzilla_password_dummy' + suffix);
|
||||
|
||||
YAHOO.util.Dom.removeClass(mini_login, "bz_mini_login_help");
|
||||
if (mini_login.value == mini_login_constants.login) {
|
||||
removeClass(mini_login, "bz_mini_login_help");
|
||||
if (mini_login.value == mini_login_constants.login)
|
||||
mini_login.value = '';
|
||||
}
|
||||
YAHOO.util.Dom.removeClass(mini_password, 'bz_default_hidden');
|
||||
YAHOO.util.Dom.addClass(mini_dummy, 'bz_default_hidden');
|
||||
removeClass(mini_password, 'bz_default_hidden');
|
||||
addClass(mini_dummy, 'bz_default_hidden');
|
||||
}
|
||||
|
||||
function check_mini_login_fields( suffix ) {
|
||||
var mini_login = document.getElementById('Bugzilla_login' + suffix );
|
||||
var mini_password = document.getElementById('Bugzilla_password' + suffix );
|
||||
if( (mini_login.value != "" && mini_password.value != "")
|
||||
&& mini_login.value != mini_login_constants.login )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
window.alert( mini_login_constants.warning );
|
||||
function check_mini_login_fields(suffix)
|
||||
{
|
||||
var mini_login = document.getElementById('Bugzilla_login' + suffix);
|
||||
var mini_password = document.getElementById('Bugzilla_password' + suffix);
|
||||
if (mini_login.value != "" && mini_password.value != "" &&
|
||||
mini_login.value != mini_login_constants.login)
|
||||
return true;
|
||||
window.alert(mini_login_constants.warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
function set_language( value ) {
|
||||
YAHOO.util.Cookie.set('LANG', value,
|
||||
{
|
||||
function set_language(value)
|
||||
{
|
||||
setCookie('LANG', value, {
|
||||
expires: new Date('January 1, 2038'),
|
||||
path: BUGZILLA.param.cookie_path
|
||||
});
|
||||
window.location.reload()
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
/* template/en/global/menuforusers.html.tmpl */
|
||||
|
||||
function dump(arr,level)
|
||||
{
|
||||
var dumped_text = "";
|
||||
if(!level) level = 0;
|
||||
var level_padding = "";
|
||||
for(var j=0;j<level+1;j++)
|
||||
level_padding += " ";
|
||||
if(typeof(arr) == 'object') {
|
||||
for(var item in arr) {
|
||||
var value = arr[item];
|
||||
if(typeof(value) == 'object') {
|
||||
dumped_text += level_padding + "'" + item + "' ...\n";
|
||||
dumped_text += dump(value,level+1);
|
||||
} else {
|
||||
dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
|
||||
}
|
||||
return dumped_text;
|
||||
}
|
||||
|
||||
function menuforusers_initcombo(id, multi)
|
||||
{
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
var p = sel.parentNode;
|
||||
/* We must move <select> out of its parent element temporarily,
|
||||
because it can be invisible in some cases (i.e. New Bug form),
|
||||
and have offsetWidth=offsetHeight=0 */
|
||||
document.body.appendChild(sel);
|
||||
var w = (sel.offsetWidth-sel.offsetHeight+2);
|
||||
if (w > 400)
|
||||
{
|
||||
w = 400;
|
||||
sel.style.width = (w+sel.offsetHeight-2)+'px';
|
||||
}
|
||||
ed.style.width = w+'px';
|
||||
p.appendChild(sel);
|
||||
ed.style.borderWidth = 0;
|
||||
menuforusers_tocombo(id);
|
||||
if (multi)
|
||||
{
|
||||
YAHOO.util.Event.addListener(document.body, "click", function(ev) {
|
||||
if (!ev) var ev = window.event;
|
||||
var t = ev.target;
|
||||
if (!t) t = ev.srcElement;
|
||||
if (t.nodeType == 3) t = t.parentNode; // Safari bug
|
||||
if (t.id != id && t.id != id+'_b' && t.id != id+'_s' && t.parentNode.id != id+'_s')
|
||||
menuforusers_showmulti(id, false)
|
||||
});
|
||||
YAHOO.util.Event.addListener(document.getElementById(id+'_b'), "click", function(ev) { menuforusers_showmulti(id); });
|
||||
}
|
||||
}
|
||||
|
||||
RegExp.escape = function(text) {
|
||||
if (!arguments.callee.sRE) {
|
||||
var specials = [
|
||||
'/', '.', '*', '+', '?', '|',
|
||||
'(', ')', '[', ']', '{', '}', '\\'
|
||||
];
|
||||
arguments.callee.sRE = new RegExp(
|
||||
'(\\' + specials.join('|\\') + ')', 'g'
|
||||
);
|
||||
}
|
||||
return text.replace(arguments.callee.sRE, '\\$1');
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
var p = sel.parentNode;
|
||||
/* We must move <select> out of its parent element temporarily,
|
||||
because it can be invisible in some cases (i.e. New Bug form),
|
||||
and have offsetWidth=offsetHeight=0 */
|
||||
document.body.appendChild(sel);
|
||||
var w = (sel.offsetWidth-sel.offsetHeight+2);
|
||||
if (w > 400)
|
||||
{
|
||||
w = 400;
|
||||
sel.style.width = (w+sel.offsetHeight-2)+'px';
|
||||
}
|
||||
ed.style.width = w+'px';
|
||||
p.appendChild(sel);
|
||||
ed.style.borderWidth = 0;
|
||||
menuforusers_tocombo(id);
|
||||
if (multi)
|
||||
{
|
||||
addListener(document.body, "click", function(ev) {
|
||||
t = eventTarget(ev);
|
||||
if (t.id != id && t.id != id+'_b' && t.id != id+'_s' && t.parentNode.id != id+'_s')
|
||||
menuforusers_showmulti(id, false)
|
||||
});
|
||||
addListener(document.getElementById(id+'_b'), "click", function(ev) { menuforusers_showmulti(id); });
|
||||
}
|
||||
}
|
||||
|
||||
function menuforusers_tocombo(id, multi)
|
||||
{
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
var nv = [];
|
||||
var v = ed.value.split(/[\s,]+/);
|
||||
var i, j;
|
||||
for (i = 0; i < v.length; i++)
|
||||
{
|
||||
for (j = 0; j < sel.options.length; j++)
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
var nv = [];
|
||||
var v = ed.value.split(/[\s,]+/);
|
||||
var i, j;
|
||||
for (i = 0; i < v.length; i++)
|
||||
{
|
||||
if (sel.options[j].value.toLowerCase().indexOf(v[i].toLowerCase()) >= 0 ||
|
||||
sel.options[j].text.toLowerCase().indexOf(v[i].toLowerCase()) >= 0)
|
||||
{
|
||||
sel.options[j].selected = true;
|
||||
nv.push(sel.options[j].value);
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < sel.options.length; j++)
|
||||
{
|
||||
if (sel.options[j].value.toLowerCase().indexOf(v[i].toLowerCase()) >= 0 ||
|
||||
sel.options[j].text.toLowerCase().indexOf(v[i].toLowerCase()) >= 0)
|
||||
{
|
||||
sel.options[j].selected = true;
|
||||
nv.push(sel.options[j].value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j >= sel.options.length)
|
||||
nv.push(v[i]);
|
||||
if (!multi)
|
||||
break;
|
||||
}
|
||||
if (j >= sel.options.length)
|
||||
nv.push(v[i]);
|
||||
if (!multi)
|
||||
break;
|
||||
}
|
||||
ed.value = nv.join(', ');
|
||||
ed.value = nv.join(', ');
|
||||
}
|
||||
|
||||
function menuforusers_fromcombo(id, multi)
|
||||
{
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
v = [];
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
if (sel.options[i].selected)
|
||||
v.push(sel.options[i].value);
|
||||
ed.value = v.join(', ');
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var ed = document.getElementById(id);
|
||||
if (!sel || !ed)
|
||||
return;
|
||||
v = [];
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
if (sel.options[i].selected)
|
||||
v.push(sel.options[i].value);
|
||||
ed.value = v.join(', ');
|
||||
}
|
||||
|
||||
function menuforusers_showmulti(id, wha)
|
||||
{
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var btn = document.getElementById(id+"_b");
|
||||
if (!sel || !btn)
|
||||
return;
|
||||
var show = sel.style.visibility == 'hidden' && !sel.disabled;
|
||||
if (typeof(wha) != 'undefined')
|
||||
show = wha;
|
||||
sel.style.visibility = show ? '' : 'hidden';
|
||||
btn.src = 'images/dn' + (show ? 'push' : '') + '.gif';
|
||||
}
|
||||
|
||||
/* work time parser: "1,5" or "1:30" (HH:MM) = 1.5, "1.5d" (days) = 12 */
|
||||
function bzParseTime(time)
|
||||
{
|
||||
time = time+"";
|
||||
time = time.replace(',','.');
|
||||
if (m = time.match(/^\s*(-?)(\d+):(\d+)\s*$/))
|
||||
{
|
||||
for (var i = 2; i < 5; i++)
|
||||
{
|
||||
if (!m[i]) m[i] = 0;
|
||||
else m[i] = parseInt(m[i]);
|
||||
}
|
||||
if (!m[1]) m[1] = '';
|
||||
time = Math.floor(parseFloat(m[1] + (m[2] + m[3]/60))*100+0.5)/100;
|
||||
}
|
||||
else if (m = time.match(/^\s*(-?\d+(?:\.\d+)?)d\s*$/))
|
||||
time = parseFloat(m[1])*8;
|
||||
else
|
||||
time = parseFloat(time);
|
||||
return time;
|
||||
var sel = document.getElementById(id+"_s");
|
||||
var btn = document.getElementById(id+"_b");
|
||||
if (!sel || !btn)
|
||||
return;
|
||||
var show = sel.style.visibility == 'hidden' && !sel.disabled;
|
||||
if (typeof(wha) != 'undefined')
|
||||
show = wha;
|
||||
sel.style.visibility = show ? '' : 'hidden';
|
||||
btn.src = 'images/dn' + (show ? 'push' : '') + '.gif';
|
||||
}
|
||||
|
|
|
@ -81,8 +81,9 @@ function showHelp() {
|
|||
return;
|
||||
|
||||
// Get the position and size of the form element in the document
|
||||
var elemY = bz_findPosY(this);
|
||||
var elemX = bz_findPosX(this);
|
||||
var elemPos = findPos(this);
|
||||
var elemX = elemPos[0];
|
||||
var elemY = elemPos[1];
|
||||
var elemH = this.offsetHeight;
|
||||
|
||||
// Update help text displayed in the div
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
*
|
||||
* The Original Code is the Bugzilla Bug Tracking System.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Christian Reis <kiko@async.com.br>
|
||||
*/
|
||||
|
||||
|
@ -52,7 +52,7 @@ function selectClassification(classfield, product, component, version, milestone
|
|||
first_load = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Don't reset first_load as done in selectProduct. That's because we
|
||||
// want selectProduct to handle the first_load attribute.
|
||||
|
||||
|
@ -69,7 +69,7 @@ function selectClassification(classfield, product, component, version, milestone
|
|||
if (!findall) {
|
||||
// Save sel for the next invocation of selectClassification().
|
||||
var tmp = sel;
|
||||
|
||||
|
||||
// This is an optimization: if we have just added classifications to an
|
||||
// existing selection, no need to clear the form elements and add
|
||||
// everything again; just merge the new ones with the existing
|
||||
|
|
|
@ -1,20 +1,4 @@
|
|||
/* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the Bugzilla Bug Tracking System.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
/* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
|
||||
|
@ -66,64 +50,65 @@ respecting this "list of active IDs".
|
|||
*/
|
||||
|
||||
var qfHandling = {};
|
||||
YAHOO.util.Event.addListener(window, 'load', initQueryformFields);
|
||||
addListener(window, 'load', initQueryformFields);
|
||||
|
||||
function initQueryformFields()
|
||||
{
|
||||
for (var i in qfVisibility)
|
||||
{
|
||||
if (!qfHandling[i])
|
||||
handleQueryformField(null, document.getElementById(i));
|
||||
initQueryformField(i);
|
||||
}
|
||||
for (var i in qfVisibility)
|
||||
{
|
||||
if (!qfHandling[i])
|
||||
handleQueryformField(null, document.getElementById(i));
|
||||
initQueryformField(i);
|
||||
}
|
||||
}
|
||||
|
||||
function initQueryformField(i)
|
||||
{
|
||||
var f = document.getElementById(i);
|
||||
YAHOO.util.Event.addListener(f, 'change', handleQueryformField, f);
|
||||
var f = document.getElementById(i);
|
||||
if (f)
|
||||
addListener(f, 'change', handleQueryformField_this);
|
||||
}
|
||||
|
||||
// Get selected IDs of names selected in selectbox sel
|
||||
function getQueryformSelectedIds(sel)
|
||||
{
|
||||
var opt = {};
|
||||
var a;
|
||||
var has_selected;
|
||||
var l2 = sel.id.length+4;
|
||||
// No selection is equivalent to full selection
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
{
|
||||
if (sel.options[i].selected)
|
||||
var opt = {};
|
||||
var a;
|
||||
var has_selected;
|
||||
var l2 = sel.id.length+4;
|
||||
// No selection is equivalent to full selection
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
{
|
||||
has_selected = true;
|
||||
break;
|
||||
if (sel.options[i].selected)
|
||||
{
|
||||
has_selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Iterate over all options
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
{
|
||||
if (sel.options[i].selected || !has_selected)
|
||||
// Iterate over all options
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
{
|
||||
// IDs of options are qf_<SELECTBOX_ID>_1_2_3_...
|
||||
// where 1_2_3 is the list of IDs mapped to this option name
|
||||
// which are currently visible.
|
||||
a = sel.options[i].id.substr(l2).split('_');
|
||||
for (var j in a)
|
||||
opt[a[j]] = true;
|
||||
if (sel.options[i].selected || !has_selected)
|
||||
{
|
||||
// IDs of options are qf_<SELECTBOX_ID>_1_2_3_...
|
||||
// where 1_2_3 is the list of IDs mapped to this option name
|
||||
// which are currently visible.
|
||||
a = sel.options[i].id.substr(l2).split('_');
|
||||
for (var j in a)
|
||||
opt[a[j]] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return opt;
|
||||
return opt;
|
||||
}
|
||||
|
||||
// Get the array with values of options selected in sel selectbox
|
||||
function getPlainSelectedIds(sel)
|
||||
{
|
||||
var o = {};
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
if (sel.options[i].selected)
|
||||
o[sel.options[i].value] = true;
|
||||
return o;
|
||||
var o = {};
|
||||
for (var i = 0; i < sel.options.length; i++)
|
||||
if (sel.options[i].selected)
|
||||
o[sel.options[i].value] = true;
|
||||
return o;
|
||||
}
|
||||
|
||||
// Check visibility of some field or value when it's visible only for ids
|
||||
|
@ -134,105 +119,111 @@ function getPlainSelectedIds(sel)
|
|||
// f({ 2: 1 }, { 1: 1 }) = false
|
||||
function qfCheckVisibility(visible_for_ids, selected_ids)
|
||||
{
|
||||
vis = true;
|
||||
// Visible also if visible_for_ids is an empty hash
|
||||
if (visible_for_ids)
|
||||
{
|
||||
for (var cid in visible_for_ids)
|
||||
vis = true;
|
||||
// Visible also if visible_for_ids is an empty hash
|
||||
if (visible_for_ids)
|
||||
{
|
||||
vis = false;
|
||||
if (selected_ids[cid])
|
||||
{
|
||||
vis = true;
|
||||
break;
|
||||
}
|
||||
for (var cid in visible_for_ids)
|
||||
{
|
||||
vis = false;
|
||||
if (selected_ids[cid])
|
||||
{
|
||||
vis = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vis;
|
||||
return vis;
|
||||
}
|
||||
|
||||
// handleQueryformField on 'this' change
|
||||
function handleQueryformField_this(event)
|
||||
{
|
||||
return handleQueryformField(event, this);
|
||||
}
|
||||
|
||||
// Handle change of selection inside a selectbox 'controller'
|
||||
// Update all dependent fields
|
||||
function handleQueryformField(event, controller)
|
||||
{
|
||||
var controlled, controlled_selected;
|
||||
var vis, item, legal, name2id, name2id_order, valueVD;
|
||||
qfHandling[controller.id] = true; // prevent double-action during init
|
||||
var VD = qfVisibility[controller.id];
|
||||
var visibility_selected = getQueryformSelectedIds(controller);
|
||||
var ids = {};
|
||||
for (var i in VD.fields)
|
||||
ids[i] = true;
|
||||
for (var i in VD.values)
|
||||
ids[i] = true;
|
||||
for (var controlled_id in ids)
|
||||
{
|
||||
controlled = document.getElementById(controlled_id);
|
||||
if (!controlled)
|
||||
continue;
|
||||
if (controlled.nodeName != 'SELECT')
|
||||
var controlled, controlled_selected;
|
||||
var vis, item, legal, name2id, name2id_order, valueVD;
|
||||
qfHandling[controller.id] = true; // prevent double-action during init
|
||||
var VD = qfVisibility[controller.id];
|
||||
var visibility_selected = getQueryformSelectedIds(controller);
|
||||
var ids = {};
|
||||
for (var i in VD.fields)
|
||||
ids[i] = true;
|
||||
for (var i in VD.values)
|
||||
ids[i] = true;
|
||||
for (var controlled_id in ids)
|
||||
{
|
||||
// Just show/hide non-select fields
|
||||
item = document.getElementById(controlled_id+'_cont');
|
||||
if (item)
|
||||
{
|
||||
item.style.display = qfCheckVisibility(
|
||||
VD.fields[controlled_id], visibility_selected
|
||||
) ? '' : 'none';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Save and clear old selection for dependent field:
|
||||
controlled_selected = getPlainSelectedIds(controlled);
|
||||
bz_clearOptions(controlled);
|
||||
// Loop over all legal values and remember currently
|
||||
// visible IDs inside name2id preserving their original
|
||||
// order using name2id_order
|
||||
legal = qfVisibility[controlled_id]['legal'];
|
||||
name2id = {};
|
||||
name2id_order = [];
|
||||
if (qfCheckVisibility(VD.fields[controlled_id], visibility_selected))
|
||||
{
|
||||
var vis_val = VD.values[controlled_id];
|
||||
// Field is visible
|
||||
for (var i in legal)
|
||||
{
|
||||
if (!vis_val || qfCheckVisibility(vis_val[legal[i][0]], visibility_selected))
|
||||
controlled = document.getElementById(controlled_id);
|
||||
if (!controlled)
|
||||
continue;
|
||||
if (controlled.nodeName != 'SELECT')
|
||||
{
|
||||
// Value is visible
|
||||
if (!name2id[legal[i][1]])
|
||||
{
|
||||
name2id[legal[i][1]] = [];
|
||||
name2id_order.push(legal[i][1]);
|
||||
}
|
||||
name2id[legal[i][1]].push(legal[i][0]);
|
||||
// Just show/hide non-select fields
|
||||
item = document.getElementById(controlled_id+'_cont');
|
||||
if (item)
|
||||
{
|
||||
item.style.display = qfCheckVisibility(
|
||||
VD.fields[controlled_id], visibility_selected
|
||||
) ? '' : 'none';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// Save and clear old selection for dependent field:
|
||||
controlled_selected = getPlainSelectedIds(controlled);
|
||||
bz_clearOptions(controlled);
|
||||
// Loop over all legal values and remember currently
|
||||
// visible IDs inside name2id preserving their original
|
||||
// order using name2id_order
|
||||
legal = qfVisibility[controlled_id]['legal'];
|
||||
name2id = {};
|
||||
name2id_order = [];
|
||||
if (qfCheckVisibility(VD.fields[controlled_id], visibility_selected))
|
||||
{
|
||||
var vis_val = VD.values[controlled_id];
|
||||
// Field is visible
|
||||
for (var i in legal)
|
||||
{
|
||||
if (!vis_val || qfCheckVisibility(vis_val[legal[i][0]], visibility_selected))
|
||||
{
|
||||
// Value is visible
|
||||
if (!name2id[legal[i][1]])
|
||||
{
|
||||
name2id[legal[i][1]] = [];
|
||||
name2id_order.push(legal[i][1]);
|
||||
}
|
||||
name2id[legal[i][1]].push(legal[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create options
|
||||
for (var i in name2id_order)
|
||||
{
|
||||
i = name2id_order[i];
|
||||
item = bz_createOptionInSelect(controlled, i, i);
|
||||
/* Save particular selected IDs for the same name
|
||||
for cascade selection of such fields.
|
||||
At the moment, only component, version and target_milestone fields
|
||||
can have many values with the same name, and they do not affect the
|
||||
case of cascade selection when there are no custom fields depending
|
||||
on them. */
|
||||
item.id = 'qf_'+controlled_id+'_'+name2id[i].join('_');
|
||||
if (controlled_selected[i])
|
||||
{
|
||||
// Restore selection
|
||||
item.selected = true;
|
||||
}
|
||||
}
|
||||
handleQueryformField(event, controlled);
|
||||
item = document.getElementById(controlled_id+'_cont');
|
||||
if (item)
|
||||
{
|
||||
// Hide fields with no options
|
||||
item.style.display = controlled.options.length ? '' : 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create options
|
||||
for (var i in name2id_order)
|
||||
{
|
||||
i = name2id_order[i];
|
||||
item = bz_createOptionInSelect(controlled, i, i);
|
||||
/* Save particular selected IDs for the same name
|
||||
for cascade selection of such fields.
|
||||
At the moment, only component, version and target_milestone fields
|
||||
can have many values with the same name, and they do not affect the
|
||||
case of cascade selection when there are no custom fields depending
|
||||
on them. */
|
||||
item.id = 'qf_'+controlled_id+'_'+name2id[i].join('_');
|
||||
if (controlled_selected[i])
|
||||
{
|
||||
// Restore selection
|
||||
item.selected = true;
|
||||
}
|
||||
}
|
||||
handleQueryformField(event, controlled);
|
||||
item = document.getElementById(controlled_id+'_cont');
|
||||
if (item)
|
||||
{
|
||||
// Hide fields with no options
|
||||
item.style.display = controlled.options.length ? '' : 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1105
js/sorttable.js
1105
js/sorttable.js
File diff suppressed because it is too large
Load Diff
642
js/util.js
642
js/util.js
|
@ -1,158 +1,35 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Cross Platform JavaScript Utility Library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Everything Solved.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Max Kanat-Alexander <mkanat@bugzilla.org>
|
||||
* Christopher A. Aillon <christopher@aillon.com>
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Locate where an element is on the page, x-wise.
|
||||
*
|
||||
* @param obj Element of which location to return.
|
||||
* @return Current position of the element relative to the left of the
|
||||
* page window. Measured in pixels.
|
||||
/* Utility functions for Bugzilla scripts
|
||||
* Rewritten without YAHOO UI
|
||||
* License: Dual-license GPL 3.0+ or MPL 1.1+
|
||||
* Contributor(s): Vitaliy Filippov <vitalif@mail.ru>
|
||||
*/
|
||||
function bz_findPosX(obj)
|
||||
{
|
||||
var curleft = 0;
|
||||
|
||||
if (obj.offsetParent) {
|
||||
while (obj) {
|
||||
curleft += obj.offsetLeft;
|
||||
// Get the position of 'obj' from the page top
|
||||
// Returns [x, y], in pixels
|
||||
function findPos(obj)
|
||||
{
|
||||
if (obj.offsetParent)
|
||||
{
|
||||
var r = [ 0, 0 ];
|
||||
while (obj)
|
||||
{
|
||||
r[0] += obj.offsetLeft;
|
||||
r[1] += obj.offsetTop;
|
||||
obj = obj.offsetParent;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else if (obj.x) {
|
||||
curleft += obj.x;
|
||||
}
|
||||
|
||||
return curleft;
|
||||
else if (obj.y)
|
||||
return [ obj.x, obj.y ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate where an element is on the page, y-wise.
|
||||
*
|
||||
* @param obj Element of which location to return.
|
||||
* @return Current position of the element relative to the top of the
|
||||
* page window. Measured in pixels.
|
||||
*/
|
||||
function bz_findPosY(obj)
|
||||
// Checks if a specified value 'val' is in the specified array 'arr'
|
||||
function bz_isValueInArray(arr, val)
|
||||
{
|
||||
var curtop = 0;
|
||||
|
||||
if (obj.offsetParent) {
|
||||
while (obj) {
|
||||
curtop += obj.offsetTop;
|
||||
obj = obj.offsetParent;
|
||||
}
|
||||
}
|
||||
else if (obj.y) {
|
||||
curtop += obj.y;
|
||||
}
|
||||
|
||||
return curtop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full height of an element, even if it's larger than the browser
|
||||
* window.
|
||||
*
|
||||
* @param fromObj Element of which height to return.
|
||||
* @return Current height of the element. Measured in pixels.
|
||||
*/
|
||||
function bz_getFullHeight(fromObj)
|
||||
{
|
||||
var scrollY;
|
||||
|
||||
// All but Mac IE
|
||||
if (fromObj.scrollHeight > fromObj.offsetHeight) {
|
||||
scrollY = fromObj.scrollHeight;
|
||||
// Mac IE
|
||||
} else {
|
||||
scrollY = fromObj.offsetHeight;
|
||||
}
|
||||
|
||||
return scrollY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full width of an element, even if it's larger than the browser
|
||||
* window.
|
||||
*
|
||||
* @param fromObj Element of which width to return.
|
||||
* @return Current width of the element. Measured in pixels.
|
||||
*/
|
||||
function bz_getFullWidth(fromObj)
|
||||
{
|
||||
var scrollX;
|
||||
|
||||
// All but Mac IE
|
||||
if (fromObj.scrollWidth > fromObj.offsetWidth) {
|
||||
scrollX = fromObj.scrollWidth;
|
||||
// Mac IE
|
||||
} else {
|
||||
scrollX = fromObj.offsetWidth;
|
||||
}
|
||||
|
||||
return scrollX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes a block to appear directly underneath another block,
|
||||
* overlaying anything below it.
|
||||
*
|
||||
* @param item The block that you want to move.
|
||||
* @param parent The block that it goes on top of.
|
||||
* @return nothing
|
||||
*/
|
||||
function bz_overlayBelow(item, parent) {
|
||||
var elemY = bz_findPosY(parent);
|
||||
var elemX = bz_findPosX(parent);
|
||||
var elemH = parent.offsetHeight;
|
||||
|
||||
item.style.position = 'absolute';
|
||||
item.style.left = elemX + "px";
|
||||
item.style.top = elemY + elemH + 1 + "px";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specified value is in the specified array.
|
||||
*
|
||||
* @param aArray Array to search for the value.
|
||||
* @param aValue Value to search from the array.
|
||||
* @return Boolean; true if value is found in the array and false if not.
|
||||
*/
|
||||
function bz_isValueInArray(aArray, aValue)
|
||||
{
|
||||
var run = 0;
|
||||
var len = aArray.length;
|
||||
|
||||
for ( ; run < len; run++) {
|
||||
if (aArray[run] == aValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
for (var i = arr.length-1; i >= 0; i--)
|
||||
if (arr[i] == val)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,10 +41,11 @@ function bz_isValueInArray(aArray, aValue)
|
|||
* element.
|
||||
* @return Created option element.
|
||||
*/
|
||||
function bz_createOptionInSelect(aSelect, aTextValue, aValue) {
|
||||
var myOption = new Option(aTextValue, aValue);
|
||||
aSelect.options[aSelect.length] = myOption;
|
||||
return myOption;
|
||||
function bz_createOptionInSelect(aSelect, aTextValue, aValue)
|
||||
{
|
||||
var myOption = new Option(aTextValue, aValue);
|
||||
aSelect.options[aSelect.length] = myOption;
|
||||
return myOption;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,13 +53,11 @@ function bz_createOptionInSelect(aSelect, aTextValue, aValue) {
|
|||
*
|
||||
* @param aSelect Select form control of which options to clear.
|
||||
*/
|
||||
function bz_clearOptions(aSelect) {
|
||||
|
||||
var length = aSelect.options.length;
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
aSelect.removeChild(aSelect.options[0]);
|
||||
}
|
||||
function bz_clearOptions(aSelect)
|
||||
{
|
||||
var length = aSelect.options.length;
|
||||
for (var i = 0; i < length; i++)
|
||||
aSelect.removeChild(aSelect.options[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,14 +67,15 @@ function bz_clearOptions(aSelect) {
|
|||
* before array values are created in it.
|
||||
* @param aArray Array with values to populate select with.
|
||||
*/
|
||||
function bz_populateSelectFromArray(aSelect, aArray) {
|
||||
// Clear the field
|
||||
bz_clearOptions(aSelect);
|
||||
|
||||
for (var i = 0; i < aArray.length; i++) {
|
||||
var item = aArray[i];
|
||||
bz_createOptionInSelect(aSelect, item[1], item[0]);
|
||||
}
|
||||
function bz_populateSelectFromArray(aSelect, aArray)
|
||||
{
|
||||
// Clear the field
|
||||
bz_clearOptions(aSelect);
|
||||
for (var i = 0; i < aArray.length; i++)
|
||||
{
|
||||
var item = aArray[i];
|
||||
bz_createOptionInSelect(aSelect, item[1], item[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,13 +86,12 @@ function bz_populateSelectFromArray(aSelect, aArray) {
|
|||
* @param aSelect The select you're checking.
|
||||
* @param aValue The value that you want to know about.
|
||||
*/
|
||||
function bz_valueSelected(aSelect, aValue) {
|
||||
function bz_valueSelected(aSelect, aValue)
|
||||
{
|
||||
var options = aSelect.options;
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
if (options[i].selected && options[i].value == aValue) {
|
||||
for (var i = 0; i < options.length; i++)
|
||||
if (options[i].selected && options[i].value == aValue)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -226,25 +102,26 @@ function bz_valueSelected(aSelect, aValue) {
|
|||
* @param aSelect The select you're checking.
|
||||
* @param aValue The value you want to know the index of.
|
||||
*/
|
||||
function bz_optionIndex(aSelect, aValue) {
|
||||
for (var i = 0; i < aSelect.options.length; i++) {
|
||||
if (aSelect.options[i].value == aValue) {
|
||||
function bz_optionIndex(aSelect, aValue)
|
||||
{
|
||||
for (var i = 0; i < aSelect.options.length; i++)
|
||||
if (aSelect.options[i].value == aValue)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to fire an event programmatically.
|
||||
*
|
||||
*
|
||||
* @param anElement The element you want to fire the event of.
|
||||
* @param anEvent The name of the event you want to fire,
|
||||
* without the word "on" in front of it.
|
||||
*/
|
||||
function bz_fireEvent(anElement, anEvent) {
|
||||
function bz_fireEvent(anElement, anEvent)
|
||||
{
|
||||
// IE
|
||||
if (document.createEventObject) {
|
||||
if (document.createEventObject)
|
||||
{
|
||||
var evt = document.createEventObject();
|
||||
return anElement.fireEvent('on' + anEvent, evt);
|
||||
}
|
||||
|
@ -254,75 +131,61 @@ function bz_fireEvent(anElement, anEvent) {
|
|||
return !anElement.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a CSS class to an element if it doesn't have it. Removes the
|
||||
* CSS class from the element if the element does have the class.
|
||||
*
|
||||
* Requires YUI's Dom library.
|
||||
*
|
||||
* @param anElement The element to toggle the class on
|
||||
* @param aClass The name of the CSS class to toggle.
|
||||
*/
|
||||
function bz_toggleClass(anElement, aClass) {
|
||||
if (YAHOO.util.Dom.hasClass(anElement, aClass)) {
|
||||
YAHOO.util.Dom.removeClass(anElement, aClass);
|
||||
}
|
||||
else {
|
||||
YAHOO.util.Dom.addClass(anElement, aClass);
|
||||
}
|
||||
}
|
||||
|
||||
/* map { $_ => 1 } %h */
|
||||
function array_hash(ar)
|
||||
{
|
||||
var h = {};
|
||||
if (ar.length == 1 && ar[0].length == 0)
|
||||
var h = {};
|
||||
if (ar.length == 1 && ar[0].length == 0)
|
||||
return h;
|
||||
for (i in ar)
|
||||
h[ar[i]] = 1;
|
||||
return h;
|
||||
for (i in ar)
|
||||
h[ar[i]] = 1;
|
||||
return h;
|
||||
}
|
||||
|
||||
/* [a,b,c], [d,b] ---> {d:1},{a:1,c:1} */
|
||||
/* Calculates the difference between two arrays.
|
||||
from, to ---> added, removed
|
||||
[a,b,c], [d,b] ---> {d:1},{a:1,c:1} */
|
||||
function diff_arrays(a1, a2)
|
||||
{
|
||||
var h1 = array_hash(a1);
|
||||
var h2 = array_hash(a2);
|
||||
var add = {}, rem = {};
|
||||
for (i in a1)
|
||||
if (!h2[a1[i]])
|
||||
rem[a1[i]] = 1;
|
||||
for (i in a2)
|
||||
if (!h1[a2[i]])
|
||||
add[a2[i]] = 1;
|
||||
return [ add, rem ];
|
||||
var h1 = array_hash(a1);
|
||||
var h2 = array_hash(a2);
|
||||
var add = {}, rem = {};
|
||||
for (i in a1)
|
||||
if (!h2[a1[i]])
|
||||
rem[a1[i]] = 1;
|
||||
for (i in a2)
|
||||
if (!h1[a2[i]])
|
||||
add[a2[i]] = 1;
|
||||
return [ add, rem ];
|
||||
}
|
||||
|
||||
/* join ",", grep { $h{$_} } keys %h */
|
||||
function hash_join(h)
|
||||
{
|
||||
var a = [];
|
||||
for (i in h)
|
||||
if (h[i])
|
||||
a.push(i);
|
||||
return a.join(", ");
|
||||
var a = [];
|
||||
for (i in h)
|
||||
if (h[i])
|
||||
a.push(i);
|
||||
return a.join(", ");
|
||||
}
|
||||
|
||||
/* CustIS Bug 64559 - Submit form on Ctrl-Enter */
|
||||
function ctrlEnter(event, formElem) {
|
||||
if((event.ctrlKey) && ((event.keyCode == 0xA)||(event.keyCode == 0xD))) {
|
||||
formElem.commit.click();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
function ctrlEnter(event, formElem)
|
||||
{
|
||||
if (event.ctrlKey && (event.keyCode == 0xA || event.keyCode == 0xD))
|
||||
{
|
||||
formElem.commit.click();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof Node == 'undefined') {
|
||||
/* MSIE doesn't define Node, so provide a compatibility object */
|
||||
window.Node = {
|
||||
TEXT_NODE: 3,
|
||||
ENTITY_REFERENCE_NODE: 5
|
||||
};
|
||||
/* MSIE doesn't define Node, so provide a compatibility object */
|
||||
window.Node = {
|
||||
TEXT_NODE: 3,
|
||||
ENTITY_REFERENCE_NODE: 5
|
||||
};
|
||||
}
|
||||
|
||||
/* Concatenates all text from element's childNodes. This is used
|
||||
|
@ -330,20 +193,20 @@ if (typeof Node == 'undefined') {
|
|||
* innerText is non-standard).
|
||||
*/
|
||||
function getText(element) {
|
||||
var child, text = "";
|
||||
for (var i=0; i < element.childNodes.length; i++) {
|
||||
child = element.childNodes[i];
|
||||
var type = child.nodeType;
|
||||
if (type == Node.TEXT_NODE || type == Node.ENTITY_REFERENCE_NODE) {
|
||||
text += child.nodeValue;
|
||||
} else if (child.nodeName.toLowerCase() == 'br') {
|
||||
text += "\n";
|
||||
} else {
|
||||
/* recurse into nodes of other types */
|
||||
text += getText(child);
|
||||
var child, text = "";
|
||||
for (var i=0; i < element.childNodes.length; i++) {
|
||||
child = element.childNodes[i];
|
||||
var type = child.nodeType;
|
||||
if (type == Node.TEXT_NODE || type == Node.ENTITY_REFERENCE_NODE) {
|
||||
text += child.nodeValue;
|
||||
} else if (child.nodeName.toLowerCase() == 'br') {
|
||||
text += "\n";
|
||||
} else {
|
||||
/* recurse into nodes of other types */
|
||||
text += getText(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
return text;
|
||||
}
|
||||
|
||||
/* Functions for comment preview */
|
||||
|
@ -354,47 +217,264 @@ function getText(element) {
|
|||
window.iframeajax_call = 0;
|
||||
window.iframeajax = function(url, data)
|
||||
{
|
||||
var f = document.createElement('form');
|
||||
var i = document.createElement('iframe');
|
||||
f.target = i.name = i.id = 'iframeajax_'+(window.iframeajax_call++);
|
||||
f.method = 'POST';
|
||||
f.action = url;
|
||||
var d = document.createElement('div');
|
||||
d.id = 'div_'+i.id;
|
||||
data['iframeajaxid'] = i.id.substr(11);
|
||||
for (var k in data)
|
||||
{
|
||||
var n = document.createElement('input');
|
||||
n.type = 'hidden';
|
||||
n.name = k;
|
||||
n.value = data[k];
|
||||
f.appendChild(n);
|
||||
}
|
||||
d.style.display = 'none';
|
||||
d.appendChild(f);
|
||||
d.appendChild(i);
|
||||
document.body.appendChild(d);
|
||||
window.frames[i.id].name = i.id;
|
||||
pushEvent(i, 'load', function() {
|
||||
i.contentWindow.loaded();
|
||||
i.parentNode.removeChild(i);
|
||||
});
|
||||
f.submit();
|
||||
var f = document.createElement('form');
|
||||
var i = document.createElement('iframe');
|
||||
f.target = i.name = i.id = 'iframeajax_'+(window.iframeajax_call++);
|
||||
f.method = 'POST';
|
||||
f.action = url;
|
||||
var d = document.createElement('div');
|
||||
d.id = 'div_'+i.id;
|
||||
data['iframeajaxid'] = i.id.substr(11);
|
||||
for (var k in data)
|
||||
{
|
||||
var n = document.createElement('input');
|
||||
n.type = 'hidden';
|
||||
n.name = k;
|
||||
n.value = data[k];
|
||||
f.appendChild(n);
|
||||
}
|
||||
d.style.display = 'none';
|
||||
d.appendChild(f);
|
||||
d.appendChild(i);
|
||||
document.body.appendChild(d);
|
||||
window.frames[i.id].name = i.id;
|
||||
addListener(i, 'load', function() {
|
||||
i.contentWindow.loaded();
|
||||
i.parentNode.removeChild(i);
|
||||
});
|
||||
f.submit();
|
||||
};
|
||||
window.pushEvent = function(obj, event, handler) {
|
||||
if (obj.addEventListener)
|
||||
obj.addEventListener(event, handler, false);
|
||||
else if (obj.attachEvent)
|
||||
obj.attachEvent('on'+event, handler);
|
||||
};
|
||||
window.findPos = function(obj) { var curtop = 0; if (obj.offsetParent) { do { curtop += obj.offsetTop; } while (obj = obj.offsetParent); return [curtop]; } }
|
||||
window.scrollDocTo = function(obj) { window.scroll(0,findPos(obj)); }
|
||||
window.scrTo = function(id) { scrollDocTo(document.getElementById(id)); }
|
||||
|
||||
window.hidepreview = function() { document.getElementById('wrapcommentpreview').style.display='none'; }
|
||||
window.addListener = function(obj, event, handler)
|
||||
{
|
||||
if (typeof(obj) == 'string')
|
||||
obj = document.getElementById(obj);
|
||||
if (!obj)
|
||||
return;
|
||||
if (obj.addEventListener)
|
||||
obj.addEventListener(event, handler, false);
|
||||
else if (obj.attachEvent)
|
||||
obj.attachEvent('on'+event, handler);
|
||||
};
|
||||
window.removeListener = function(obj, event, handler)
|
||||
{
|
||||
if (typeof(obj) == 'string')
|
||||
obj = document.getElementById(obj);
|
||||
if (!obj)
|
||||
return;
|
||||
if (obj.addEventListener)
|
||||
obj.removeEventListener(event, handler, false);
|
||||
else if (obj.attachEvent)
|
||||
obj.detachEvent('on'+event, handler);
|
||||
};
|
||||
window.eventTarget = function(ev)
|
||||
{
|
||||
if (!ev) var ev = window.event;
|
||||
var t = ev.target;
|
||||
if (!t) t = ev.srcElement;
|
||||
if (t && t.nodeType == 3) t = t.parentNode;
|
||||
return t;
|
||||
};
|
||||
|
||||
window.getElementsByClassName = function(c, nodeName, parent)
|
||||
{
|
||||
if (typeof(parent) == 'string')
|
||||
parent = document.getElementById(parent);
|
||||
parent = parent||document;
|
||||
if (nodeName)
|
||||
nodeName = nodeName.toLowerCase();
|
||||
if (parent.getElementsByClassName)
|
||||
{
|
||||
var l = parent.getElementsByClassName(c);
|
||||
if (!nodeName)
|
||||
return l;
|
||||
else
|
||||
{
|
||||
var l1 = [];
|
||||
for (var i = 0; i < l.length; i++)
|
||||
if (l[i].nodeName.toLowerCase() == nodeName)
|
||||
l1.push(l[i]);
|
||||
return l1;
|
||||
}
|
||||
}
|
||||
var s = [ parent ];
|
||||
var l = [];
|
||||
if (nodeName)
|
||||
{
|
||||
while (s.length)
|
||||
{
|
||||
if (hasClass(s[0], c) && s[0].nodeName.toLowerCase() == nodeName)
|
||||
l.push(s[0]);
|
||||
else
|
||||
for (var i = 0; i < s[0].children.length; i++)
|
||||
s.push(s[0].children[i]);
|
||||
s.shift();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (s.length)
|
||||
{
|
||||
if (hasClass(s[0], c))
|
||||
l.push(s[0]);
|
||||
else
|
||||
for (var i = 0; i < s[0].children.length; i++)
|
||||
s.push(s[0].children[i]);
|
||||
s.shift();
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
/**
|
||||
* addClass : add CSS class to an element
|
||||
* returns (void)
|
||||
* removeClass : remove CSS class from element
|
||||
* returns (modified => true)
|
||||
* hasClass : check if element has the specified CSS class
|
||||
* returns (has class => true)
|
||||
* toggleClass : add / remove CSS class if object doesn't have it / has it.
|
||||
* returns (has class after toggle => true)
|
||||
* FIXME all have jQuery alternatives
|
||||
*
|
||||
* @param anElement/obj The element to toggle the class on
|
||||
* @param aClass/c The name of the CSS class to toggle.
|
||||
*/
|
||||
window.addClass = function(obj, c)
|
||||
{
|
||||
if (typeof(obj) == 'string')
|
||||
obj = document.getElementById(obj);
|
||||
if (obj)
|
||||
obj.className = obj.className+' '+c;
|
||||
};
|
||||
window.removeClass = function(obj, c)
|
||||
{
|
||||
if (typeof(obj) == 'string')
|
||||
obj = document.getElementById(obj);
|
||||
if (!obj)
|
||||
return false;
|
||||
var l = obj.className.split(/\s+/);
|
||||
var l1 = [];
|
||||
for (var i = l.length-1; i >= 0; i--)
|
||||
if (l[i] != c)
|
||||
l1.push(l[i]);
|
||||
obj.className = l1.length ? l1.join(' ') : '';
|
||||
return l1.length != l.length;
|
||||
};
|
||||
window.hasClass = function(obj, c)
|
||||
{
|
||||
if (typeof(obj) == 'string')
|
||||
obj = document.getElementById(obj);
|
||||
var l = obj.className.split(/\s+/);
|
||||
for (var i = l.length-1; i >= 0; i--)
|
||||
if (l[i] == c)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
window.toggleClass = function(anElement, aClass)
|
||||
{
|
||||
if (typeof(anElement) == 'string')
|
||||
anElement = document.getElementById(anElement);
|
||||
if (hasClass(anElement, aClass))
|
||||
{
|
||||
removeClass(anElement, aClass);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
addClass(anElement, aClass);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
window.scrollDocTo = function(obj) { window.scroll(0, findPos(obj)[1]); }
|
||||
window.scrTo = function(id) { scrollDocTo(document.getElementById(id)); }
|
||||
window.hidepreview = function()
|
||||
{
|
||||
document.getElementById('wrapcommentpreview').style.display = 'none';
|
||||
};
|
||||
window.showcommentpreview = function(textarea_id)
|
||||
{
|
||||
document.getElementById('wrapcommentpreview').style.display = '';
|
||||
iframeajax('page.cgi?id=previewcomment.html', { 'comment': document.getElementById(textarea_id || 'comment_textarea').value });
|
||||
scrTo('wrapcommentpreview');
|
||||
document.getElementById('wrapcommentpreview').style.display = '';
|
||||
iframeajax('page.cgi?id=previewcomment.html', { 'comment': document.getElementById(textarea_id || 'comment_textarea').value });
|
||||
scrTo('wrapcommentpreview');
|
||||
};
|
||||
|
||||
RegExp.escape = function(text) {
|
||||
if (!arguments.callee.sRE) {
|
||||
var specials = [
|
||||
'/', '.', '*', '+', '?', '|',
|
||||
'(', ')', '[', ']', '{', '}', '\\'
|
||||
];
|
||||
arguments.callee.sRE = new RegExp(
|
||||
'(\\' + specials.join('|\\') + ')', 'g'
|
||||
);
|
||||
}
|
||||
return text.replace(arguments.callee.sRE, '\\$1');
|
||||
};
|
||||
|
||||
/* Parse time in hours:
|
||||
"1,5" or "1:30" (HH:MM) = 1.5,
|
||||
"1.5d" (days) = 12 */
|
||||
function bzParseTime(time)
|
||||
{
|
||||
time = time+"";
|
||||
time = time.replace(',','.');
|
||||
if (m = time.match(/^\s*(-?)(\d+):(\d+)\s*$/))
|
||||
{
|
||||
for (var i = 2; i < 5; i++)
|
||||
{
|
||||
if (!m[i]) m[i] = 0;
|
||||
else m[i] = parseInt(m[i]);
|
||||
}
|
||||
if (!m[1]) m[1] = '';
|
||||
time = Math.floor(parseFloat(m[1] + (m[2] + m[3]/60))*100+0.5)/100;
|
||||
}
|
||||
else if (m = time.match(/^\s*(-?\d+(?:\.\d+)?)d\s*$/))
|
||||
time = parseFloat(m[1])*8;
|
||||
else
|
||||
time = parseFloat(time);
|
||||
return time;
|
||||
};
|
||||
|
||||
/* Gets named cookie */
|
||||
window.getCookie = function(name)
|
||||
{
|
||||
var matches = document.cookie.match(new RegExp(
|
||||
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
|
||||
));
|
||||
return matches ? decodeURIComponent(matches[1]) : undefined;
|
||||
};
|
||||
|
||||
/* Sets a new cookie name=value
|
||||
props: {expires:, path:, domain:, secure:, httponly:} */
|
||||
window.setCookie = function(name, value, props)
|
||||
{
|
||||
props = props || {};
|
||||
var exp = props.expires;
|
||||
if (typeof exp == "number" && exp)
|
||||
{
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + exp*1000);
|
||||
exp = props.expires = d;
|
||||
}
|
||||
if (exp && exp.toUTCString)
|
||||
props.expires = exp.toUTCString();
|
||||
|
||||
value = encodeURIComponent(value);
|
||||
var updatedCookie = name + "=" + value;
|
||||
for (var propName in props)
|
||||
{
|
||||
updatedCookie += "; " + propName;
|
||||
var propValue = props[propName];
|
||||
if (propValue !== true)
|
||||
updatedCookie += "=" + propValue;
|
||||
}
|
||||
document.cookie = updatedCookie;
|
||||
};
|
||||
|
||||
/* Removes named cookie */
|
||||
window.deleteCookie = function(name)
|
||||
{
|
||||
setCookie(name, null, { expires: -1 });
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,7 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.net/yui/license.txt
|
||||
version: 2.6.0
|
||||
*/
|
||||
YAHOO.namespace("util");YAHOO.util.Cookie={_createCookieString:function(B,D,C,A){var F=YAHOO.lang;var E=encodeURIComponent(B)+"="+(C?encodeURIComponent(D):D);if(F.isObject(A)){if(A.expires instanceof Date){E+="; expires="+A.expires.toGMTString();}if(F.isString(A.path)&&A.path!=""){E+="; path="+A.path;}if(F.isString(A.domain)&&A.domain!=""){E+="; domain="+A.domain;}if(A.secure===true){E+="; secure";}}return E;},_createCookieHashString:function(B){var D=YAHOO.lang;if(!D.isObject(B)){throw new TypeError("Cookie._createCookieHashString(): Argument must be an object.");}var C=new Array();for(var A in B){if(D.hasOwnProperty(B,A)&&!D.isFunction(B[A])&&!D.isUndefined(B[A])){C.push(encodeURIComponent(A)+"="+encodeURIComponent(String(B[A])));}}return C.join("&");},_parseCookieHash:function(E){var D=E.split("&"),F=null,C=new Object();if(E.length>0){for(var B=0,A=D.length;B<A;B++){F=D[B].split("=");C[decodeURIComponent(F[0])]=decodeURIComponent(F[1]);}}return C;},_parseCookieString:function(I,A){var J=new Object();if(YAHOO.lang.isString(I)&&I.length>0){var B=(A===false?function(K){return K;}:decodeURIComponent);if(/[^=]+=[^=;]?(?:; [^=]+=[^=]?)?/.test(I)){var G=I.split(/;\s/g);var H=null;var C=null;var E=null;for(var D=0,F=G.length;D<F;D++){E=G[D].match(/([^=]+)=/i);if(E instanceof Array){H=decodeURIComponent(E[1]);C=B(G[D].substring(E[1].length+1));}else{H=decodeURIComponent(G[D]);C=H;}J[H]=C;}}}return J;},get:function(A,B){var D=YAHOO.lang;var C=this._parseCookieString(document.cookie);if(!D.isString(A)||A===""){throw new TypeError("Cookie.get(): Cookie name must be a non-empty string.");}if(D.isUndefined(C[A])){return null;}if(!D.isFunction(B)){return C[A];}else{return B(C[A]);}},getSub:function(A,C,B){var E=YAHOO.lang;var D=this.getSubs(A);if(D!==null){if(!E.isString(C)||C===""){throw new TypeError("Cookie.getSub(): Subcookie name must be a non-empty string.");}if(E.isUndefined(D[C])){return null;}if(!E.isFunction(B)){return D[C];}else{return B(D[C]);}}else{return null;}},getSubs:function(A){if(!YAHOO.lang.isString(A)||A===""){throw new TypeError("Cookie.getSubs(): Cookie name must be a non-empty string.");}var B=this._parseCookieString(document.cookie,false);if(YAHOO.lang.isString(B[A])){return this._parseCookieHash(B[A]);}return null;},remove:function(B,A){if(!YAHOO.lang.isString(B)||B===""){throw new TypeError("Cookie.remove(): Cookie name must be a non-empty string.");}A=A||{};A.expires=new Date(0);return this.set(B,"",A);},removeSub:function(B,D,A){if(!YAHOO.lang.isString(B)||B===""){throw new TypeError("Cookie.removeSub(): Cookie name must be a non-empty string.");}if(!YAHOO.lang.isString(D)||D===""){throw new TypeError("Cookie.removeSub(): Subcookie name must be a non-empty string.");}var C=this.getSubs(B);if(YAHOO.lang.isObject(C)&&YAHOO.lang.hasOwnProperty(C,D)){delete C[D];return this.setSubs(B,C,A);}else{return"";}},set:function(B,C,A){var E=YAHOO.lang;if(!E.isString(B)){throw new TypeError("Cookie.set(): Cookie name must be a string.");}if(E.isUndefined(C)){throw new TypeError("Cookie.set(): Value cannot be undefined.");}var D=this._createCookieString(B,C,true,A);document.cookie=D;return D;},setSub:function(B,D,C,A){var F=YAHOO.lang;if(!F.isString(B)||B===""){throw new TypeError("Cookie.setSub(): Cookie name must be a non-empty string.");}if(!F.isString(D)||D===""){throw new TypeError("Cookie.setSub(): Subcookie name must be a non-empty string.");}if(F.isUndefined(C)){throw new TypeError("Cookie.setSub(): Subcookie value cannot be undefined.");}var E=this.getSubs(B);if(!F.isObject(E)){E=new Object();}E[D]=C;return this.setSubs(B,E,A);},setSubs:function(B,C,A){var E=YAHOO.lang;if(!E.isString(B)){throw new TypeError("Cookie.setSubs(): Cookie name must be a string.");}if(!E.isObject(C)){throw new TypeError("Cookie.setSubs(): Cookie value must be an object.");}var D=this._createCookieString(B,this._createCookieHashString(C),false,A);document.cookie=D;return D;}};YAHOO.register("cookie",YAHOO.util.Cookie,{version:"2.6.0",build:"1321"});
|
File diff suppressed because one or more lines are too long
|
@ -300,8 +300,8 @@ $vars->{sentmail} = \@all_mail_results;
|
|||
|
||||
if (Bugzilla->usage_mode != USAGE_MODE_EMAIL)
|
||||
{
|
||||
my $title = template_var('terms')->{Bug}.' '.$bug->id.' Submitted – '.$bug->short_desc;
|
||||
my $header = template_var('terms')->{Bug}.' '.$bug->id.' Submitted';
|
||||
my $title = Bugzilla->messages->{terms}->{Bug}.' '.$bug->id.' Submitted – '.$bug->short_desc;
|
||||
my $header = Bugzilla->messages->{terms}->{Bug}.' '.$bug->id.' Submitted';
|
||||
my $ses = {
|
||||
sent => \@all_mail_results,
|
||||
title => $title,
|
||||
|
|
|
@ -719,11 +719,11 @@ elsif (($action eq 'next_bug' or $action eq 'same_bug') && ($bug = $vars->{bug})
|
|||
my $title;
|
||||
if (scalar(@bug_objects) == 1)
|
||||
{
|
||||
$title = template_var('terms')->{Bug} . ' ' . $bug_objects[0]->id . ' processed';
|
||||
$title = Bugzilla->messages->{terms}->{Bug} . ' ' . $bug_objects[0]->id . ' processed';
|
||||
}
|
||||
else
|
||||
{
|
||||
$title = template_var('terms')->{Bugs} . ' processed';
|
||||
$title = Bugzilla->messages->{terms}->{Bugs} . ' processed';
|
||||
}
|
||||
$send_attrs->{nextbug} = $action eq 'next_bug' ? 1 : 0;
|
||||
my $ses = {
|
||||
|
|
395
query.cgi
395
query.cgi
|
@ -42,10 +42,11 @@ use Bugzilla::Field;
|
|||
use Bugzilla::Install::Util qw(vers_cmp);
|
||||
|
||||
my $cgi = Bugzilla->cgi;
|
||||
# Copy hash and throw away tied reference returned by Vars()
|
||||
my $params = { %{ $cgi->Vars } };
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $template = Bugzilla->template;
|
||||
my $vars = {};
|
||||
my $buffer = $cgi->query_string();
|
||||
|
||||
my $user = Bugzilla->login();
|
||||
my $userid = $user->id;
|
||||
|
@ -53,21 +54,26 @@ my $userid = $user->id;
|
|||
# Backwards compatibility hack -- if there are any of the old QUERY_*
|
||||
# cookies around, and we are logged in, then move them into the database
|
||||
# and nuke the cookie. This is required for Bugzilla 2.8 and earlier.
|
||||
if ($userid) {
|
||||
if ($userid)
|
||||
{
|
||||
my @oldquerycookies;
|
||||
foreach my $i ($cgi->cookie()) {
|
||||
if ($i =~ /^QUERY_(.*)$/) {
|
||||
push(@oldquerycookies, [$1, $i, $cgi->cookie($i)]);
|
||||
push @oldquerycookies, [$1, $i, $cgi->cookie($i)];
|
||||
}
|
||||
}
|
||||
if (defined $cgi->cookie('DEFAULTQUERY')) {
|
||||
push(@oldquerycookies, [DEFAULT_QUERY_NAME, 'DEFAULTQUERY',
|
||||
$cgi->cookie('DEFAULTQUERY')]);
|
||||
if (defined $cgi->cookie('DEFAULTQUERY'))
|
||||
{
|
||||
push @oldquerycookies, [DEFAULT_QUERY_NAME, 'DEFAULTQUERY',
|
||||
$cgi->cookie('DEFAULTQUERY')];
|
||||
}
|
||||
if (@oldquerycookies) {
|
||||
foreach my $ref (@oldquerycookies) {
|
||||
if (@oldquerycookies)
|
||||
{
|
||||
foreach my $ref (@oldquerycookies)
|
||||
{
|
||||
my ($name, $cookiename, $value) = (@$ref);
|
||||
if ($value) {
|
||||
if ($value)
|
||||
{
|
||||
# If the query name contains invalid characters, don't import.
|
||||
$name =~ /[<>&]/ && next;
|
||||
trick_taint($name);
|
||||
|
@ -75,11 +81,15 @@ if ($userid) {
|
|||
my $query = $dbh->selectrow_array(
|
||||
"SELECT query FROM namedqueries " .
|
||||
"WHERE userid = ? AND name = ?",
|
||||
undef, ($userid, $name));
|
||||
if (!$query) {
|
||||
$dbh->do("INSERT INTO namedqueries " .
|
||||
"(userid, name, query) VALUES " .
|
||||
"(?, ?, ?)", undef, ($userid, $name, $value));
|
||||
undef, $userid, $name
|
||||
);
|
||||
if (!$query)
|
||||
{
|
||||
$dbh->do(
|
||||
"INSERT INTO namedqueries " .
|
||||
"(userid, name, query) VALUES (?, ?, ?)",
|
||||
undef, $userid, $name, $value
|
||||
);
|
||||
}
|
||||
$dbh->bz_commit_transaction();
|
||||
}
|
||||
|
@ -88,209 +98,168 @@ if ($userid) {
|
|||
}
|
||||
}
|
||||
|
||||
if ($cgi->param('nukedefaultquery')) {
|
||||
if ($userid) {
|
||||
$dbh->do("DELETE FROM namedqueries" .
|
||||
" WHERE userid = ? AND name = ?",
|
||||
undef, ($userid, DEFAULT_QUERY_NAME));
|
||||
}
|
||||
$buffer = "";
|
||||
if ($params->{nukedefaultquery} && $userid)
|
||||
{
|
||||
$dbh->do(
|
||||
"DELETE FROM namedqueries WHERE userid = ? AND name = ?",
|
||||
undef, $userid, DEFAULT_QUERY_NAME
|
||||
);
|
||||
}
|
||||
|
||||
# We are done with changes committed to the DB.
|
||||
$dbh = Bugzilla->switch_to_shadow_db;
|
||||
|
||||
my $userdefaultquery;
|
||||
if ($userid) {
|
||||
$userdefaultquery = $dbh->selectrow_array(
|
||||
"SELECT query FROM namedqueries " .
|
||||
"WHERE userid = ? AND name = ?",
|
||||
undef, ($userid, DEFAULT_QUERY_NAME));
|
||||
if ($userid)
|
||||
{
|
||||
($userdefaultquery) = $dbh->selectrow_array(
|
||||
"SELECT query FROM namedqueries WHERE userid = ? AND name = ?",
|
||||
undef, $userid, DEFAULT_QUERY_NAME
|
||||
);
|
||||
}
|
||||
|
||||
local our %default;
|
||||
my $default = {};
|
||||
|
||||
# We pass the defaults as a hash of references to arrays. For those
|
||||
# Items which are single-valued, the template should only reference [0]
|
||||
# and ignore any multiple values.
|
||||
sub PrefillForm {
|
||||
my ($buf) = (@_);
|
||||
my $cgi = Bugzilla->cgi;
|
||||
$buf = new Bugzilla::CGI($buf);
|
||||
my $foundone = 0;
|
||||
# Nothing must be undef, otherwise the template complains.
|
||||
my @list = qw(
|
||||
bug_status resolution assigned_to
|
||||
rep_platform priority bug_severity
|
||||
classification product reporter op_sys
|
||||
component version chfield chfieldfrom
|
||||
chfieldto chfieldvalue target_milestone
|
||||
email emailtype emailreporter
|
||||
emailassigned_to emailcc emailqa_contact
|
||||
emaillongdesc content
|
||||
changedin votes short_desc short_desc_type
|
||||
longdesc longdesc_type bug_file_loc
|
||||
bug_file_loc_type status_whiteboard
|
||||
status_whiteboard_type bug_id
|
||||
bug_id_type keywords keywords_type
|
||||
deadlinefrom deadlineto
|
||||
x_axis_field y_axis_field z_axis_field
|
||||
chart_format cumulate x_labels_vertical
|
||||
category subcategory name newcategory
|
||||
newsubcategory public frequency
|
||||
);
|
||||
|
||||
# Nothing must be undef, otherwise the template complains.
|
||||
my @list = ("bug_status", "resolution", "assigned_to",
|
||||
"rep_platform", "priority", "bug_severity",
|
||||
"classification", "product", "reporter", "op_sys",
|
||||
"component", "version", "chfield", "chfieldfrom",
|
||||
"chfieldto", "chfieldvalue", "target_milestone",
|
||||
"email", "emailtype", "emailreporter",
|
||||
"emailassigned_to", "emailcc", "emailqa_contact",
|
||||
"emaillongdesc", "content",
|
||||
"changedin", "votes", "short_desc", "short_desc_type",
|
||||
"longdesc", "longdesc_type", "bug_file_loc",
|
||||
"bug_file_loc_type", "status_whiteboard",
|
||||
"status_whiteboard_type", "bug_id",
|
||||
"bug_id_type", "keywords", "keywords_type",
|
||||
"deadlinefrom", "deadlineto",
|
||||
"x_axis_field", "y_axis_field", "z_axis_field",
|
||||
"chart_format", "cumulate", "x_labels_vertical",
|
||||
"category", "subcategory", "name", "newcategory",
|
||||
"newsubcategory", "public", "frequency");
|
||||
# These fields can also have default values (when used in reports).
|
||||
# CustIS Bug 58300 - Add custom field to search filters
|
||||
for my $field (Bugzilla->active_custom_fields)
|
||||
{
|
||||
push @list, $field->name;
|
||||
push @list, $field->name . '_type';
|
||||
}
|
||||
|
||||
foreach my $name (@list) {
|
||||
$default{$name} = [];
|
||||
}
|
||||
|
||||
# we won't prefill the boolean chart data from this query if
|
||||
# there are any being submitted via params
|
||||
my $prefillcharts = (grep(/^field-/, $cgi->param)) ? 0 : 1;
|
||||
|
||||
# Iterate over the URL parameters
|
||||
foreach my $name ($buf->param()) {
|
||||
my @values = $buf->param($name);
|
||||
|
||||
# If the name begins with the string 'field', 'type', 'value', or
|
||||
# 'negate', then it is part of the boolean charts. Because
|
||||
# these are built different than the rest of the form, we need
|
||||
# to store these as parameters. We also need to indicate that
|
||||
# we found something so the default query isn't added in if
|
||||
# all we have are boolean chart items.
|
||||
if ($name =~ m/^(?:field|type|value|negate)/) {
|
||||
$cgi->param(-name => $name, -value => $values[0]) if ($prefillcharts);
|
||||
$foundone = 1;
|
||||
}
|
||||
# If the name ends in a number (which it does for the fields which
|
||||
# are part of the email searching), we use the array
|
||||
# positions to show the defaults for that number field.
|
||||
elsif ($name =~ m/^(.+)(\d)$/ && defined($default{$1})) {
|
||||
$foundone = 1;
|
||||
$default{$1}->[$2] = $values[0];
|
||||
}
|
||||
elsif (exists $default{$name}) {
|
||||
$foundone = 1;
|
||||
push (@{$default{$name}}, @values);
|
||||
}
|
||||
}
|
||||
return $foundone;
|
||||
# These fields can also have default values (when used in reports).
|
||||
# CustIS Bug 58300 - Add custom field to search filters
|
||||
for my $field (Bugzilla->active_custom_fields)
|
||||
{
|
||||
push @list, $field->name;
|
||||
push @list, $field->name . '_type';
|
||||
}
|
||||
|
||||
if (!PrefillForm($buffer)) {
|
||||
# Ah-hah, there was no form stuff specified. Do it again with the
|
||||
foreach my $name (@list)
|
||||
{
|
||||
$default->{$name} = [];
|
||||
}
|
||||
|
||||
if ($params->{nukedefaultquery})
|
||||
{
|
||||
# Don't prefill form
|
||||
}
|
||||
elsif (!PrefillForm($params, $default))
|
||||
{
|
||||
# Ah-hah, there was no form stuff specified. Do it again with the
|
||||
# default query.
|
||||
if ($userdefaultquery) {
|
||||
PrefillForm($userdefaultquery);
|
||||
} else {
|
||||
PrefillForm(Bugzilla->params->{"defaultquery"});
|
||||
}
|
||||
my $buf = new Bugzilla::CGI($userdefaultquery || Bugzilla->params->{defaultquery});
|
||||
PrefillForm({ %{ $buf->Vars } }, $default);
|
||||
}
|
||||
|
||||
if (!scalar(@{$default{'chfieldto'}}) || $default{'chfieldto'}->[0] eq "") {
|
||||
$default{'chfieldto'} = ["Now"];
|
||||
if (!@{$default->{chfieldto}} || $default->{chfieldto}->[0] eq '')
|
||||
{
|
||||
$default->{chfieldto} = [ 'Now' ];
|
||||
}
|
||||
|
||||
# "where one or more of the following changed:"
|
||||
$vars->{chfield} = [ map { $_->name } @{ Bugzilla::Search->CHANGEDFROMTO_FIELDS } ];
|
||||
|
||||
# Boolean charts
|
||||
|
||||
my $opdescs = Bugzilla->messages->{operator_descs};
|
||||
$vars->{chart_types} = Bugzilla::Search->CHART_OPERATORS_ORDER;
|
||||
$vars->{text_types} = Bugzilla::Search->TEXT_OPERATORS_ORDER;
|
||||
|
||||
# Fields for boolean charts
|
||||
$vars->{fields} = [
|
||||
$vars->{chart_fields} = [
|
||||
map { { name => $_->{id}, title => $_->{title} } }
|
||||
sort { $a->{title} cmp $b->{title} }
|
||||
grep { !$_->{nocharts} }
|
||||
values %{ Bugzilla::Search->COLUMNS }
|
||||
];
|
||||
|
||||
# "where one or more of the following changed:"
|
||||
$vars->{chfield} = [ map { $_->name } @{ Bugzilla::Search->CHANGEDFROMTO_FIELDS } ];
|
||||
|
||||
# Another hack...
|
||||
unshift @{$vars->{fields}}, { name => "noop", description => "---" };
|
||||
unshift @{$vars->{chart_fields}}, { id => 'noop', name => '---' };
|
||||
|
||||
# If we're not in the time-tracking group, exclude time-tracking fields.
|
||||
if (!Bugzilla->user->is_timetracker) {
|
||||
foreach my $tt_field (TIMETRACKING_FIELDS) {
|
||||
@{$vars->{fields}} = grep($_->{name} ne $tt_field, @{$vars->{fields}});
|
||||
@{$vars->{chart_fields}} = grep($_->{name} ne $tt_field, @{$vars->{chart_fields}});
|
||||
}
|
||||
}
|
||||
|
||||
# Boolean charts
|
||||
|
||||
# Creating new charts - if the cmd-add value is there, we define the field
|
||||
# value so the code sees it and creates the chart. It will attempt to select
|
||||
# "xyzzy" as the default, and fail. This is the correct behaviour.
|
||||
foreach my $cmd (grep(/^cmd-/, $cgi->param)) {
|
||||
if ($cmd =~ /^cmd-add(\d+)-(\d+)-(\d+)$/) {
|
||||
$cgi->param(-name => "field$1-$2-$3", -value => "xyzzy");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$cgi->param('field0-0-0')) {
|
||||
$cgi->param(-name => 'field0-0-0', -value => "xyzzy");
|
||||
}
|
||||
|
||||
# Create data structure of boolean chart info. It's an array of arrays of
|
||||
# arrays - with the inner arrays having three members - field, type and
|
||||
# value.
|
||||
# Parse boolean charts from the form hash
|
||||
my @charts;
|
||||
for (my $chart = 0; $cgi->param("field$chart-0-0"); $chart++) {
|
||||
my @rows;
|
||||
for (my $row = 0; $cgi->param("field$chart-$row-0"); $row++) {
|
||||
my @cols;
|
||||
for (my $col = 0; $cgi->param("field$chart-$row-$col"); $col++) {
|
||||
my $value = $cgi->param("value$chart-$row-$col");
|
||||
if (!defined($value)) {
|
||||
$value = '';
|
||||
}
|
||||
push(@cols, { field => $cgi->param("field$chart-$row-$col"),
|
||||
type => $cgi->param("type$chart-$row-$col") || 'noop',
|
||||
value => $value });
|
||||
}
|
||||
push(@rows, \@cols);
|
||||
for (keys %$params)
|
||||
{
|
||||
if (/^(field|type|value)(\d+)-(\d+)-(\d+)$/so)
|
||||
{
|
||||
$charts[$2]{rows}[$3][$4]{$1} = $params->{$_};
|
||||
}
|
||||
elsif (/^negate(\d+)$/so)
|
||||
{
|
||||
$charts[$2]{negate} = $params->{$_};
|
||||
}
|
||||
push(@charts, {'rows' => \@rows, 'negate' => scalar($cgi->param("negate$chart")) });
|
||||
}
|
||||
|
||||
$default{'charts'} = \@charts;
|
||||
# Remove empty charts
|
||||
for (@charts)
|
||||
{
|
||||
@$_ = grep { $_->{field} && $_->{field} ne 'noop' && $_->{field} ne '---' } @$_ for @{$_->{rows}};
|
||||
@{$_->{rows}} = grep { @$_ } @{$_->{rows}};
|
||||
}
|
||||
@charts = grep { @{$_->{rows}} } @charts;
|
||||
|
||||
# Add one chart, if we've removed all of them
|
||||
@charts = ( { rows => [ [ { field => 'noop' } ] ] } ) unless @charts;
|
||||
|
||||
$default->{charts} = \@charts;
|
||||
|
||||
# Named queries
|
||||
if ($userid) {
|
||||
$vars->{'namedqueries'} = $dbh->selectcol_arrayref(
|
||||
"SELECT name FROM namedqueries " .
|
||||
"WHERE userid = ? AND name != ? " .
|
||||
"ORDER BY name",
|
||||
undef, ($userid, DEFAULT_QUERY_NAME));
|
||||
if ($userid)
|
||||
{
|
||||
$vars->{namedqueries} = $dbh->selectcol_arrayref(
|
||||
"SELECT name FROM namedqueries " .
|
||||
"WHERE userid = ? AND name != ? " .
|
||||
"ORDER BY name",
|
||||
undef, $userid, DEFAULT_QUERY_NAME
|
||||
);
|
||||
}
|
||||
|
||||
# Sort order
|
||||
my $deforder;
|
||||
my @orders = ('Bug Number', 'Importance', 'Assignee', 'Last Changed', 'relevance');
|
||||
|
||||
if ($cgi->cookie('LASTORDER')) {
|
||||
if ($cgi->cookie('LASTORDER'))
|
||||
{
|
||||
$deforder = "Reuse same sort as last time";
|
||||
unshift(@orders, $deforder);
|
||||
}
|
||||
|
||||
if ($cgi->param('order'))
|
||||
if ($params->{order} && !grep { $_ eq $params->{order} } @orders)
|
||||
{
|
||||
$deforder = $cgi->param('order');
|
||||
if (lsearch(\@orders, $deforder) < 0)
|
||||
{
|
||||
unshift @orders, $deforder;
|
||||
}
|
||||
unshift @orders, $params->{order};
|
||||
}
|
||||
|
||||
$vars->{'userdefaultquery'} = $userdefaultquery;
|
||||
$vars->{'orders'} = \@orders;
|
||||
$default{'order'} = [$deforder || 'Importance'];
|
||||
$vars->{userdefaultquery} = $userdefaultquery;
|
||||
$vars->{orders} = \@orders;
|
||||
$default->{order} = [$deforder || 'Importance'];
|
||||
|
||||
if (($cgi->param('query_format') || $cgi->param('format') || "")
|
||||
eq "create-series") {
|
||||
if (($params->{query_format} || $params->{format} || "") eq "create-series")
|
||||
{
|
||||
require Bugzilla::Chart;
|
||||
$vars->{'category'} = Bugzilla::Chart::getVisibleSeries();
|
||||
$vars->{category} = Bugzilla::Chart::getVisibleSeries();
|
||||
}
|
||||
|
||||
# CustIS Bug 58300 - Add custom fields to search filters
|
||||
|
@ -306,47 +275,97 @@ if (Bugzilla->params->{usestatuswhiteboard})
|
|||
push @{$vars->{freetext_fields}},
|
||||
Bugzilla->active_custom_fields({ type => [ FIELD_TYPE_TEXTAREA, FIELD_TYPE_FREETEXT ] });
|
||||
|
||||
if ($cgi->param('format') && $cgi->param('format') =~ /^report-(table|graph)$/) {
|
||||
if ($params->{format} && $params->{format} =~ /^report-(table|graph)$/)
|
||||
{
|
||||
# Get legal custom fields for tabular and graphical reports.
|
||||
my @custom_fields_for_reports = Bugzilla->active_custom_fields({ type => FIELD_TYPE_SINGLE_SELECT });
|
||||
$vars->{'custom_fields'} = \@custom_fields_for_reports;
|
||||
$vars->{custom_fields} = \@custom_fields_for_reports;
|
||||
}
|
||||
|
||||
$vars->{'known_name'} = $cgi->param('known_name');
|
||||
$vars->{'columnlist'} = $cgi->param('columnlist');
|
||||
($vars->{known_name}) = list $params->{known_name};
|
||||
$vars->{columnlist} = $params->{columnlist};
|
||||
|
||||
# Add in the defaults.
|
||||
$vars->{'default'} = \%default;
|
||||
$vars->{default} = $default;
|
||||
|
||||
$vars->{'format'} = $cgi->param('format');
|
||||
$vars->{'query_format'} = $cgi->param('query_format');
|
||||
$vars->{format} = $params->{format};
|
||||
$vars->{query_format} = $params->{query_format};
|
||||
|
||||
# Set default page to "specific" if none provided
|
||||
if (!($cgi->param('query_format') || $cgi->param('format'))) {
|
||||
if (defined $cgi->cookie('DEFAULTFORMAT')) {
|
||||
$vars->{'format'} = $cgi->cookie('DEFAULTFORMAT');
|
||||
} else {
|
||||
$vars->{'format'} = 'specific';
|
||||
# Set default page to "advanced" if none provided
|
||||
if (!$params->{query_format} && !$params->{format})
|
||||
{
|
||||
if (defined $cgi->cookie('DEFAULTFORMAT'))
|
||||
{
|
||||
$params->{format} = $cgi->cookie('DEFAULTFORMAT');
|
||||
}
|
||||
else
|
||||
{
|
||||
$params->{format} = 'advanced';
|
||||
}
|
||||
}
|
||||
|
||||
# Set cookie to current format as default, but only if the format
|
||||
# one that we should remember.
|
||||
if (defined($vars->{'format'}) && IsValidQueryType($vars->{'format'})) {
|
||||
$cgi->send_cookie(-name => 'DEFAULTFORMAT',
|
||||
-value => $vars->{'format'},
|
||||
-expires => "Fri, 01-Jan-2038 00:00:00 GMT");
|
||||
if (defined $vars->{format} && IsValidQueryType($vars->{format}))
|
||||
{
|
||||
$cgi->send_cookie(
|
||||
-name => 'DEFAULTFORMAT',
|
||||
-value => $vars->{format},
|
||||
-expires => "Fri, 01-Jan-2038 00:00:00 GMT"
|
||||
);
|
||||
}
|
||||
|
||||
# Generate and return the UI (HTML page) from the appropriate template.
|
||||
# If we submit back to ourselves (for e.g. boolean charts), we need to
|
||||
# preserve format information; hence query_format taking priority over
|
||||
# format.
|
||||
my $format = $template->get_format("search/search",
|
||||
$vars->{'query_format'} || $vars->{'format'},
|
||||
scalar $cgi->param('ctype'));
|
||||
my $format = $template->get_format(
|
||||
"search/search",
|
||||
$params->{query_format} || $params->{format},
|
||||
$params->{ctype}
|
||||
);
|
||||
|
||||
$cgi->send_header($format->{'ctype'});
|
||||
$cgi->send_header($format->{ctype});
|
||||
$template->process($format->{template}, $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|
||||
$template->process($format->{'template'}, $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
# We pass the defaults as a hash of references to arrays. For those
|
||||
# Items which are single-valued, the template should only reference [0]
|
||||
# and ignore any multiple values.
|
||||
# This is used only for prefilling full queries, not parts of them,
|
||||
# so we always prefill boolean charts.
|
||||
sub PrefillForm
|
||||
{
|
||||
my ($params, $default) = @_;
|
||||
my $foundone = 0;
|
||||
|
||||
# Iterate over the URL parameters
|
||||
foreach (keys %$params)
|
||||
{
|
||||
# If the name begins with the string 'field', 'type', 'value', or
|
||||
# 'negate', then it is part of the boolean charts. Because
|
||||
# these are built different than the rest of the form, we need
|
||||
# to store these as parameters. We also need to indicate that
|
||||
# we found something so the default query isn't added in if
|
||||
# all we have are boolean chart items.
|
||||
if (m/^(?:field|type|value|negate)/)
|
||||
{
|
||||
$foundone = 1;
|
||||
}
|
||||
# If the name ends in a number (which it does for the fields which
|
||||
# are part of the email searching), we use the array
|
||||
# positions to show the defaults for that number field.
|
||||
elsif (m/^(.+)(\d)$/ && defined $default->{$1})
|
||||
{
|
||||
$foundone = 1;
|
||||
$default->{$1}->[$2] = [ list $params->{$_} ]->[0];
|
||||
}
|
||||
elsif (exists $default->{$_})
|
||||
{
|
||||
$foundone = 1;
|
||||
push @{$default->{$_}}, list $params->{$_};
|
||||
}
|
||||
}
|
||||
|
||||
return $foundone;
|
||||
}
|
||||
|
|
|
@ -58,8 +58,7 @@ my $search = new Bugzilla::Search(
|
|||
user => $user
|
||||
);
|
||||
|
||||
my $sqlquery = $search->getSQL();
|
||||
$sqlquery =~ s/ORDER\s+BY\s+`?bugs`?.`?bug_id`?//so;
|
||||
my $sqlquery = $search->bugid_query;
|
||||
|
||||
my $tz = POSIX::strftime('%z', localtime);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use Bugzilla::Error;
|
|||
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $user = Bugzilla->login;
|
||||
my $args = $cgi->Vars;
|
||||
my $args = { %{ $cgi->Vars } };
|
||||
my $vars = {};
|
||||
|
||||
# Параметры по умолчанию:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue