package EPrints::Plugin::InputForm::Component::Field::Subject; use EPrints; use EPrints::Plugin::InputForm::Component::Field; @ISA = ( "EPrints::Plugin::InputForm::Component::Field" ); use Unicode::String qw(latin1); use strict; sub new { my( $class, %opts ) = @_; my $self = $class->SUPER::new( %opts ); $self->{name} = "Subject"; $self->{visible} = "all"; $self->{visdepth} = 1; return $self; } sub update_from_form { my( $self, $processor ) = @_; my $field = $self->{config}->{field}; my $ibutton = $self->get_internal_button; if( $ibutton =~ /^(.+)_add$/ ) { my $subject = $1; my %vals = (); $vals{$subject} = 1; my $values = $self->{dataobj}->get_value( $field->get_name ); foreach my $s ( @$values ) { $vals{$s} = 1; } my @out = keys %vals; $self->{dataobj}->set_value( $field->get_name, \@out ); $self->{dataobj}->commit; } if( $ibutton =~ /^(.+)_remove$/ ) { my $subject = $1; my %vals = (); my $values = $self->{dataobj}->get_value( $field->get_name ); foreach my $s ( @$values ) { $vals{$s} = 1; } delete $vals{$subject}; my @out = keys %vals; $self->{dataobj}->set_value( $field->get_name, \@out ); $self->{dataobj}->commit; } return; } sub render_content { my( $self, $surround ) = @_; my $session = $self->{session}; my $field = $self->{config}->{field}; my $eprint = $self->{workflow}->{item}; ( $self->{subject_map}, $self->{reverse_map} ) = EPrints::DataObj::Subject::get_all( $session ); my $out = $self->{session}->make_element( "div" ); $self->{top_subj} = $field->get_top_subject( $session ); # populate selected and expanded values $self->{expanded} = {}; $self->{selected} = {}; my @values = @{$field->get_value( $eprint )}; foreach my $subj_id ( @values ) { $self->{selected}->{$subj_id} = 1; my $subj = $self->{subject_map}->{ $subj_id }; next if !defined $subj; my @paths = $subj->get_paths( $session, $self->{top_subj} ); foreach my $path ( @paths ) { foreach my $s ( @{$path} ) { $self->{expanded}->{$s->get_id} = 1; } } } my @sels = (); foreach my $subject_id ( sort keys %{$self->{selected}} ) { push @sels, $self->{subject_map}->{ $subject_id }; } if( scalar @sels ) { $out->appendChild( $self->_format_subjects( table_class => "ep_subjectinput_selections", subject_class => "ep_subjectinput_selected_subject", button_class => "ep_subjectinput_selected_remove", button_text => $self->phrase( "remove" ), button_id => "remove", subjects => \@sels ) ); } # Render the search box $self->{search} = undef; if( $session->param( $self->{prefix}."_searchstore" ) ) { $self->{search} = $session->param( $self->{prefix}."_searchstore" ); } if( $session->internal_button_pressed ) { my $ibutton = $self->get_internal_button; if( $ibutton eq "clear" ) { delete $self->{search}; } if( $ibutton eq "search" ) { $self->{search} = $session->param( $self->{prefix}."_searchtext" ); } } if( $self->{search} eq "" ) { delete $self->{search}; } $out->appendChild( $self->_render_search ); if( $self->{search} ) { my $search_store = $session->render_hidden_field( $self->{prefix}."_searchstore", $self->{search} ); $out->appendChild( $search_store ); my $results = $self->_do_search; if( !$results->count ) { $out->appendChild( $self->html_phrase( "search_no_matches" ) ); } else { my $whitelist = {}; foreach my $subj ( $results->get_records ) { foreach my $ancestor ( @{$subj->get_value( "ancestors" )} ) { $whitelist->{$ancestor} = 1; } } $out->appendChild( $self->_render_subnodes( $self->{top_subj}, 0, $whitelist ) ); } } else { # render the treeI $out->appendChild( $self->_render_subnodes( $self->{top_subj}, 0 ) ); } return $out; } sub _do_search { my( $self ) = @_; my $session = $self->{session}; # Carry out search my $subject_ds = $session->get_repository->get_dataset( "subject" ); my $searchexp = new EPrints::Search( session=>$session, dataset=>$subject_ds ); $searchexp->add_field( $subject_ds->get_field( "name" ), $self->{search}, "IN", "ALL" ); $searchexp->add_field( $subject_ds->get_field( "ancestors" ), $self->{top_subj}->get_id, "EQ" ); return $searchexp->perform_search; } # Params: # table_class: Class for the table # subject_class: Class for the subject cell # button_class: Class for the button cell # button_text: Text for the button # button_id: postfix for the button name # subjects: array of subjects # hide_selected: If 1, hides any already selected subjects. sub _format_subjects { my( $self, %params ) = @_; my $session = $self->{session}; my $table = $session->make_element( "table", class=>$params{table_class} ); my @subjects = @{$params{subjects}}; if( scalar @subjects ) { my $first = 1; foreach my $subject ( @subjects ) { next if( !defined $subject ); # need a warning? my $subject_id = $subject->get_id(); next if ( $params{hide_selected} && $self->{selected}->{ $subject_id } ); my $prefix = $self->{prefix}."_".$subject_id; my $tr = $session->make_element( "tr" ); my $td1 = $session->make_element( "td" ); my $remove_button = $session->render_button( class=> "ep_subjectinput_remove_button", name => "_internal_".$prefix."_".$params{button_id}, value => $params{button_text} ); $td1->appendChild( $remove_button ); my $td2 = $session->make_element( "td" ); $td2->appendChild( $subject->render_description ); my @td1_attr = ( $params{subject_class} ); my @td2_attr = ( $params{button_class} ); if( $first ) { push @td1_attr, "ep_first"; push @td2_attr, "ep_first"; $first = 0; } $td1->setAttribute( "class", join(" ", @td1_attr ) ); $td2->setAttribute( "class", join(" ", @td2_attr ) ); $tr->appendChild( $td1 ); $tr->appendChild( $td2 ); $table->appendChild( $tr ); } } return $table; } sub _render_search { my( $self ) = @_; my $prefix = $self->{prefix}; my $session = $self->{session}; my $bar = $self->html_phrase( "search_bar", input=>$session->render_noenter_input_field( class=>"ep_form_text", name=>$prefix."_searchtext", type=>"text", value=>$self->{search}, onKeyPress=>"return EPJS_enter_click( event, '_internal_".$prefix."_search' )" ), search_button=>$session->render_button( name=>"_internal_".$prefix."_search", id=>"_internal_".$prefix."_search", value=>$self->phrase( "search_search_button" ) ), clear_button=>$session->render_button( name=>"_internal_".$prefix."_clear", value=>$self->phrase( "search_clear_button" ) ), ); return $bar; } sub _render_subnodes { my( $self, $subject, $depth, $whitelist ) = @_; my $session = $self->{session}; my $node_id = $subject->get_value( "subjectid" ); my @children = (); if( defined $self->{reverse_map}->{$node_id} ) { @children = @{$self->{reverse_map}->{$node_id}}; } my @filteredchildren; if( defined $whitelist ) { foreach( @children ) { next unless $whitelist->{$_->get_value( "subjectid" )}; push @filteredchildren, $_; } } else { @filteredchildren=@children; } if( scalar @filteredchildren == 0 ) { return $session->make_doc_fragment; } my $ul = $session->make_element( "ul", class=>"ep_subjectinput_subjects" ); foreach my $child ( @filteredchildren ) { my $li = $session->make_element( "li" ); $li->appendChild( $self->_render_subnode( $child, $depth+1, $whitelist ) ); $ul->appendChild( $li ); } return $ul; } sub _render_subnode { my( $self, $subject, $depth, $whitelist ) = @_; my $session = $self->{session}; my $node_id = $subject->get_value( "subjectid" ); # if( defined $whitelist && !$whitelist->{$node_id} ) # { # return $self->{session}->make_doc_fragment; # } my $has_kids = 0; $has_kids = 1 if( defined $self->{reverse_map}->{$node_id} ); my $expanded = 0; $expanded = 1 if( $depth < $self->{visdepth} ); $expanded = 1 if( defined $whitelist && $whitelist->{$node_id} ); # $expanded = 1 if( $self->{expanded}->{$node_id} ); $expanded = 0 if( !$has_kids ); my $prefix = $self->{prefix}."_".$node_id; my $id = "id".$session->get_next_id; my $r_node = $session->make_doc_fragment; my $desc = $session->make_element( "span" ); $desc->appendChild( $subject->render_description ); $r_node->appendChild( $desc ); my @classes = (); if( $self->{selected}->{$node_id} ) { push @classes, "ep_subjectinput_selected"; } if( $has_kids && !defined $whitelist ) { my $toggle; $toggle = $self->{session}->make_element( "a", href=>"#", class=>"ep_only_js ep_subjectinput_toggle" ); my $hide = $self->{session}->make_element( "span", id=>$id."_hide" ); $hide->appendChild( $self->{session}->make_element( "img", alt=>"-", src=>"/style/images/minus.png", border=>0 ) ); $hide->appendChild( $self->{session}->make_text( " " ) ); $hide->appendChild( $subject->render_description ); $hide->setAttribute( "class", join( " ", @classes ) ); $toggle->appendChild( $hide ); my $show = $self->{session}->make_element( "span", id=>$id."_show" ); $show->appendChild( $self->{session}->make_element( "img", alt=>"+", src=>"/style/images/plus.png", border=>0 ) ); $show->appendChild( $self->{session}->make_text( " " ) ); $show->appendChild( $subject->render_description ); $show->setAttribute( "class", join( " ", @classes ) ); $toggle->appendChild( $show ); push @classes, "ep_no_js"; if( $expanded ) { $toggle->setAttribute( "onclick", "EPJS_blur(event); EPJS_toggleSlide('${id}_kids',true,'block');EPJS_toggle_type('${id}_hide',true,'inline');EPJS_toggle_type('${id}_show',false,'inline');return false" ); $show->setAttribute( "style", "display:none" ); } else # not expanded { $toggle->setAttribute( "onclick", "EPJS_blur(event); EPJS_toggleSlide('${id}_kids',false,'block');EPJS_toggle_type('${id}_hide',false,'inline');EPJS_toggle_type('${id}_show',true,'inline');return false" ); $hide->setAttribute( "style", "display:none" ); } $r_node->appendChild( $toggle ); } $desc->setAttribute( "class", join( " ", @classes ) ); if( !$self->{selected}->{$node_id} && (!defined $whitelist || $whitelist->{$node_id}) ) { if( $subject->can_post ) { my $add_button = $session->render_button( class=> "ep_subjectinput_add_button", name => "_internal_".$prefix."_add", value => $self->phrase( "add" ) ); my $r_node_tmp = $session->make_doc_fragment; $r_node_tmp->appendChild( $add_button ); $r_node_tmp->appendChild( $session->make_text( " " ) ); $r_node_tmp->appendChild( $r_node ); $r_node = $r_node_tmp; } } if( $has_kids ) { my $div = $session->make_element( "div", id => $id."_kids" ); my $div_inner = $session->make_element( "div", id => $id."_kids_inner" ); if( !$expanded && !defined $whitelist ) { $div->setAttribute( "class", "ep_no_js" ); } $div_inner->appendChild( $self->_render_subnodes( $subject, $depth, $whitelist ) ); $div->appendChild( $div_inner ); $r_node->appendChild( $div ); } return $r_node; } sub get_state_params { my( $self ) = @_; my $params = ""; foreach my $id ( "_internal_".$self->{prefix}."_search", "_internal_".$self->{prefix}."_clear", $self->{prefix}."_searchstore", $self->{prefix}."_searchtext", ) { my $v = $self->{session}->param( $id ); next unless defined $v; $params.= "&$id=$v"; } return $params; } 1;