From d28ca61d634511a6bf693b8b4e3da1ef18dcd503 Mon Sep 17 00:00:00 2001 From: Bill Erickson <berick@esilibrary.com> Date: Fri, 30 Sep 2011 16:01:22 -0400 Subject: [PATCH] TPac: Facets on results page Show search facets along the left side of the results page. Clicking on a facet re-runs the current search with the new facet appeneded. Selected facets are styled to indicate they are selected. Clicking on a selected facet removes that facet from the set of selected facets (i.e. it backs out the facet). TODO: update CSS to match default Evergreen skin Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Dan Scott <dscott@laurentian.ca> --- .../perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm | 4 +- .../perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm | 22 +++-- .../src/templates/opac/parts/result/facets.tt2 | 95 +++++++++++++++++++++ Open-ILS/src/templates/opac/parts/result/table.tt2 | 4 +- Open-ILS/web/css/skin/default/opac/style.css | 73 ++++++++++++++++ Open-ILS/web/images/adv_search_minus_btn.png | Bin 0 -> 1292 bytes Open-ILS/web/images/adv_search_plus_btn.png | Bin 0 -> 1388 bytes Open-ILS/web/images/facet_box_bg.png | Bin 0 -> 449 bytes Open-ILS/web/images/facet_box_bg_bottom.png | Bin 0 -> 308 bytes 9 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 Open-ILS/src/templates/opac/parts/result/facets.tt2 create mode 100644 Open-ILS/web/images/adv_search_minus_btn.png create mode 100644 Open-ILS/web/images/adv_search_plus_btn.png create mode 100644 Open-ILS/web/images/facet_box_bg.png create mode 100644 Open-ILS/web/images/facet_box_bg_bottom.png diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm index 635678b982..37fa582254 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm @@ -168,7 +168,7 @@ sub load_rresults { } my $page = $cgi->param('page') || 0; - my $facet = $cgi->param('facet'); + my @facets = $cgi->param('facet'); my $limit = $self->_get_search_limit; my $loc = $cgi->param('loc') || $ctx->{aou_tree}->()->id; my $offset = $page * $limit; @@ -229,7 +229,7 @@ sub load_rresults { # Stuff these into the TT context so that templates can use them in redrawing forms $ctx->{processed_search_query} = $query; - $query = "$query $facet" if $facet; # TODO + $query .= " $_" for @facets; $logger->activity("EGWeb: [search] $query"); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm index 6af3a7a9fe..3b72dbc556 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm @@ -201,13 +201,23 @@ sub get_records_and_facets { # gather up the unapi recs $ses->session_wait(1); - my $facets; + my $facets = {}; if ($facet_key) { - $facets = $facet_req->gather(1); - $facets->{$_} = { - cmf => $self->ctx->{get_cmf}->($_), - data => $facets->{$_} - } for keys %$facets; # quick-n-dirty + my $tmp_facets = $facet_req->gather(1); + for my $cmf_id (keys %$tmp_facets) { + + # sort highest to lowest match count + my @entries; + my $entries = $tmp_facets->{$cmf_id}; + for my $ent (keys %$entries) { + push(@entries, {value => $ent, count => $$entries{$ent}}); + }; + @entries = sort { $b->{count} <=> $a->{count} } @entries; + $facets->{$cmf_id} = { + cmf => $self->ctx->{get_cmf}->($cmf_id), + data => \@entries + } + } } else { $facets = undef; } diff --git a/Open-ILS/src/templates/opac/parts/result/facets.tt2 b/Open-ILS/src/templates/opac/parts/result/facets.tt2 new file mode 100644 index 0000000000..c4a719d6b4 --- /dev/null +++ b/Open-ILS/src/templates/opac/parts/result/facets.tt2 @@ -0,0 +1,95 @@ +<div class="facet_box_wrapper"> +[% + +close_facets = CGI.param('close_facet') || []; +selected_facets = CGI.param('facet') || []; + +# collect facet type labels for easier sorting +labels = []; +FOR facet IN ctx.search_facets.values; + labels.push(facet.cmf.label); +END; + +FOR facet_label IN labels.sort; + FOR facet IN ctx.search_facets.values; + IF facet.cmf.label == facet_label; + fclass = facet.cmf.field_class; + fname = facet.cmf.name; + close_key = fclass _ fname %] + + <div class="facet_box_temp"> + <div class="header"> + <div class="title">[% facet.cmf.label %]</div> + <div class="button"> + + [% IF close_facets.grep(close_key).0; + new_close = []; + FOR fct IN close_facets; + IF fct != close_key; + new_close.push(fct); + END; + END + %] + <a href="[% mkurl('', {close_facet => new_close}) %]"><img + src="[% ctx.media_prefix %]/images/adv_search_plus_btn.png" alt="[% l('Expand') %]" /></a> + [% ELSE %] + <a href="[% mkurl('', {close_facet => close_facets.merge([close_key])}) %]"><img + src="[% ctx.media_prefix %]/images/adv_search_minus_btn.png" alt="[% l('Collapse') %]" /></a> + [% END %] + </div> + <div class="clear"> </div> + </div> + [% IF !close_facets.grep(close_key).0 %] + <div class="box_wrapper"> + <div class="box"> + [% FOR facet_data IN facet.data; + display_value = facet_data.value | html; + param_string = fclass _ '|' _ fname _ '[' _ facet_data.value _ ']'; + new_facets = []; + this_selected = 0; + FOR selected IN selected_facets; + IF selected == param_string; + this_selected = 1; + ELSE; + new_facets.push(selected); + END; + END; + IF this_selected; + # This facet is already selected by the user. + # Link removes the facet from the set of selected facets. + %] + <div class="facet_template facet_template_selected"> + <div class="facet"> + [% IF new_facets.size == 0 %] + <a href="[% mkurl('', {}, ['facet']) %]">[% display_value %]</a> + [% ELSE %] + <a href="[% mkurl('', {facet => new_facets}) %]">[% display_value %]</a> + [% END %] + </div> + <div class="count">([% facet_data.count %])</div> + <div class="clear"> </div> + </div> + [% + ELSE; + # This facet is not currently selected. If selected, + # append this facet to the list of currently active facets. + %] + <div class="facet_template"> + <div class="facet"> + <a href='[% mkurl('', {facet => selected_facets.merge([param_string])}) %]'>[% display_value %]</a> + </div> + <div class="count">([% facet_data.count %])</div> + <div class="clear"> </div> + </div> + [% END %] + [% END %] + </div> + <div class="clear"> </div> + </div> <!-- box_wrapper --> + [% END %] + </div> <!-- facet_box_temp --> + [% END %] + [% END %] +[% END %] +</div> <!-- facet_box_wrapper --> + diff --git a/Open-ILS/src/templates/opac/parts/result/table.tt2 b/Open-ILS/src/templates/opac/parts/result/table.tt2 index 0706ef6766..b60e647d72 100644 --- a/Open-ILS/src/templates/opac/parts/result/table.tt2 +++ b/Open-ILS/src/templates/opac/parts/result/table.tt2 @@ -19,8 +19,8 @@ <table cellpadding="0" cellspacing="0" border="0" width="100%"> <tr> <td valign="top" width="1" style="padding-right:20px;"> - <div style="width:174px;" class="hide_me"> - SIDEBAR TODO + <div style="width:174px;"> + [% INCLUDE 'opac/parts/result/facets.tt2' %] </div> </td> <td class='opac-auto-015' width="1"></td> diff --git a/Open-ILS/web/css/skin/default/opac/style.css b/Open-ILS/web/css/skin/default/opac/style.css index 368dad5a5c..e90a0ef82a 100644 --- a/Open-ILS/web/css/skin/default/opac/style.css +++ b/Open-ILS/web/css/skin/default/opac/style.css @@ -886,6 +886,7 @@ div.select-wrapper:hover { } /* some facet styling */ +/* .facetClassContainer { margin: 2px; border: 1px solid #CCC; } .facetClassLabelContainer { border: 1px solid #CCC; } .facetClassLabel { font-weight: bold; text-align: center; } @@ -897,6 +898,77 @@ div.select-wrapper:hover { .facetField { border-top: 1px solid #CCC; } .facetFields { padding-left: 5px; } .facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; } +*/ + +.facet_box_temp { + padding-bottom:3px; + width:180px; + overflow:hidden; +} + +.facet_box_temp .header { + width:180px; + height:31px; + overflow:hidden; + background:url('/images/facet_box_bg.png') no-repeat; + font-weight:bold; + color:#074079; + padding-top:4px; +} + +.facet_box_temp .header .title { + float:left; + padding-top:6px; + padding-left:12px; + width:134px; + overflow:hidden; +} + +.facet_box_temp .header .button { + float:right; + padding-right:6px; +} + +.facet_box_wrapper .box_wrapper { + position:relative; + top:-4px; + margin-bottom:-5px; + *margin-bottom:-6px; +} + +.facet_box_wrapper .box_wrapper .box { + width:166px; + border-top:1px solid #7ebee5; + border-left:1px solid #f3f3f3; + border-right:1px solid #f3f3f3; + background:white; + padding-left:12px; + padding-top:6px; +} + +.facet_box_wrapper .box_wrapper .bottom { + background:url('/images/facet_box_bg_bottom.png') no-repeat; +} + +.facet_template { + padding-bottom:5px; +} + +.facet_template .facet { + float:left; + width:124px; +} + +.facet_template .count { + float:right; + color:#818080; + padding-right:11px; +} + +.facet_template_selected { + background-color: #d7d7d7; +} + #footer-wrap { background: linear-gradient(lightGreen, #252525); background: -moz-linear-gradient(lightGreen, #252525); @@ -904,6 +976,7 @@ div.select-wrapper:hover { background: -webkit-linear-gradient(lightGreen, #252525); background-color: lightGreen; } + #footer { padding-top:5px; padding-bottom: 10px; diff --git a/Open-ILS/web/images/adv_search_minus_btn.png b/Open-ILS/web/images/adv_search_minus_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..40505959f724a7c2d45f0a390d65beb419bfe97f GIT binary patch literal 1292 zcmV+n1@roeP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$u1Q2eRCwB?R$WM2XBa+zNls3TF->Mt zU3FT}u?xEk>#k(9W$b1*yDCf=DJv63H|UhDP&#|JB8)-lD&4$t6mP~ZhC`e%!(;{5 zIbmX}m4Qu0oj*yeCOPNi{AACYo|7JR)2Ig?&dHbW`=0N8-oKAMbEcE2@bLg%>&;p) zfdZfaawVGx`~1%VK_F1UTm#qw(ty4v;l#w`u0LQok%R%hLIr4E4Nwhah#318_q7m2 zBvr&(c$kM&2>}xJdID18e+ezJ6M*O(_j)DQ<;y*1o10I*>GgU~5?GdX<@5RZLZPsn zOeV$#2frRmBp&CT%V;m`nRJq}6g0M^_>MX)({+QpdiC15Q>R|-;d#DE(=^5~j1o#3 z@;t+F9OH7iXe<$rPh7ck=k^~Mb4p3U^tUZ9-_+E|EG;E$pM~sMg@VT4x;5}|OH1oD zRaJvPiO4j~@=o+kV|0*Wu^4D=ZGF45^L1%zYHC_hWIJ$N!~>38*+NVAm+Sx`vYR)* z>WN097ZpW0kOM_gWb*mkcr5nrM{c*vmXfS{3@bIx8VK5CBx7&yC+8xO$VK?5WW_;1 zYus+n8~y!Xbkkn8>#T@p>;b=(#3s)RZusm|S_qjA1(LtMzW%+owzjanuNAdCXGJ8v zi<)Mzmo9yH7JfN#P|J1#r2g~g-|0dWbC#q8iGH~4Q>d!KH8nNArR(~kt+PR-!C<g6 zmy-pDl^(&0qEg7pvf^^P-7h;M@hA`Wdd1}usP@|VDF}`tOySMpbjO^8*=&{>8X98u zi&me{$HZbW#^doY&r_?woj(0qXm0M$w3VBz;0Rmfl+J-nKo!{*<_!%EOfHw(ld!tF zx>N{us)M2+8ivVOghj!s?4?<-&O~&kQM#h#QUvm@uC7u=*|Sxk0Aw<mU4-}U{kjHe zZ66xj2(i5m2@{Yd>Rhz8wst5VZf$KPR##W$#>NK2Qn8fyh37fQ7v|^Ze?DqT*jQQl zXG#zRmFGFb;!ufDvzn*r^@_^y@bH){%ju)01tiu-Mn=AaoQfkY%1K!olq8>;NGvVS z%*@<9s&$Kti$9K!|MUPxs5Tk3DbCSC3{iCJe!qY7`t`nVlgZ@dVXZ^(JnHNF>`SD| zhR-M2E|bgciFy^i={Gbt6h+l1Cx4l3Z*OnG0bV=^Svs9wym906E32z3k0Oy5Hj!53 zE)5*2vv@PsfCdTlaQN8f)2ADMUAPeIou2;vE((HNK`GPc=H`Cr?tcG+hYugjqO5IH zRaI$L7L;#v<pxX-zUeePNKNFOioPh1j*iaWzyDjjuCA^K9|sTw0cYqVjg}V{7RCn# zZubuke)B!nB|@Q4=J@f5?K{<Znc8;6aNKLCzH+HlhF@P_7qi)1HLMJxV)$W=*wN7u zkt9io$Ky{>7!;6fp=Of5Hfw8Z^Py1C&bz|So7*lz2eDu`<@NOxpGu`Y@T~{oE>QWi zs*r)))ln$aU@)N8)C3TCA`zI>-4ApT#sVFrbW$!H4w(RLkj>@tEQr}>b=FgaRZa`& z+xV~hXhk<~Yax*uAm^TS1&IZi9V9fjqMr7z00RJcefI{e-${-D0000<MNUMnLSTaI C({lI# literal 0 HcmV?d00001 diff --git a/Open-ILS/web/images/adv_search_plus_btn.png b/Open-ILS/web/images/adv_search_plus_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..7f1ae93a71e04ee4874f68acbfa38616daaf4144 GIT binary patch literal 1388 zcmV-y1(W)TP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%4oO5oRCwB)R$oY4R~WzllH4T5cui)k zt~zyS*@NAKwNIjL8GG5wo(dC2%F2||4La>skUq+axR=t^cJoOXGLSuNib!FG$qKG> z4-;Fh3~VgTqUKLEf9_50z1jEOo)fRp#B>*a<mTLSzTf$N-=A~XbLYC4G9MejPJUSe z9gqRYfOI)Vgk!#Q014nOW3C3+14IF8Ny7R0g+m{}b0qNs_%ap1c~yW)Kn#h&ZthqQ zfe5AYk%j-~K~+2e2iST6q*_rzLUs}$n#b*ShvnL}f%DDHE$`dy_7()ovX)dTwVKIf zLYtexx$*Ju=7PazDf2S41vWR$q%0;4l@#7<&7P^M#tjYKym0#Ty8}GWH)XR~M$<F{ zhK4-Pa2&^2EEXIK1_JXp?%%)r7mS&u#AJF-<>i~28kvoaAdQ)a&dOx6{GB^vU$nNi z-Bc7s0vJTPuIDY`JC5N-a=Dzlt*!0DuC8v!;^N|xET?JWSda%el6en_?r+fqL9*Mo zza6Npt-UPE@@oZ96h$VLN<Q%WKmOcmwNNS1yJz5KmLmfaB|{kp2fw`F^Z71Aj0`Ud z5s5^YXf%4{H(X=2+TI%(`KAwT(a@2MXXt>76tT|pf)!%+6)pssj>P2TBr`QNRrEW` zUteGUNqc*{m)a#+%X1_n@i&*vYV6gkpPh%eoIGmx6eu%fCsS$;kh(5j{HPb^aYRyt z1OHg*E)+%PnwpwFP*t_)?h*7UH3vy0N$N@_(}KxMn?SP2u#!&87OT~I%AAR%p5x|$ zt#>RI0edg4PeCv>VN7ohc2{jSlt?6)iHQlOFkA8e=;&zvztibt{C+=Uv)P#a(#mjW z&YbnEto$7%waE&mw1t{dIUp0DiyTPvhK2?vnM~%#LZJ|YbD(VUW0jSaMk6Tn8k&Nr zX*xp)a{}q?I*Ex6*%^h_mA8b3dwYA0jzXW|;bCJV{r&y>M+G#1SS)sk@ZrPXw?SGO zL+t<|m{&o<Ajnc{UbMZvePoQn;c&?q?(OXbx3;#@jg1W&QPC*;%zh2>nbp<RUrVJs z^?+t#DTKrSE((I6@I0px4h0Fb<nYw(c2S0+o=d0G(NZZ7>29FZ9FSO@o}QipIb~B> zWQ^ub3ZG|LUWX$_YiW5~gidj`n6aLo9tOIIk-^30tgo;Ca_`>QkJZ)Et|;2jp)B-L znG)iFMG*KLG;V!nW@e+iyZaPmUSpBi7-Yqscs%~}`t`vf@Gj)>NHWRL6r32kL5OD+ zA?87IO_mjPVd1ysj*gC2m&^5LDd`FUO?~~=t*>uvZH1rud~bkvBK1x&H*bavWFd~K z*IT{&@@4#=OPBnEOG|(L01Y9191$dmy0WtJb6?-5SDrk1ybLjpS5#DFNfqR8bom1q zA9%;z@Ib1A3<}7bo}Hate)Q;%KwVv3&f##nK_<6ZK9DxFwzl?QZ0zpH`1tof!MdQw z<B6R(;Zta4nlDoat{A3!4fa<q5{dCUJ3C?`k*owSCFmF~@J8(H?DRPt4j~W-ynx1l zG1`Nk8FxAzyEQd6DTo`byG-HD?GT}fSfGdU&Q64nM4~o`tqsy$!1hPFkOsA@LZeV5 z$*ojXxiyFx66kokzt%+<7N|gqJLSAyj}AZsiDWXx0x|ol&)Ra}mDvM)*N(c6mUZ(c u3z1X<a_-fs;9vnv0SV46>rDGkfB^talgXLwY7NZ*0000<MNUMnLSTZ>Bckj8 literal 0 HcmV?d00001 diff --git a/Open-ILS/web/images/facet_box_bg.png b/Open-ILS/web/images/facet_box_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..996f0a8331a6212ed0953d938326b63231733e9a GIT binary patch literal 449 zcmeAS@N?(olHy`uVBq!ia0vp^TYy-ZgAGX9u2VP(q$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1Ffb;2x;TbZ+<J3oqt{^vi31;Zdw2O-YorJ`3a~F+-MnD2 zUBlvp=X&e*HTo~~%hT)XUzp71*wXY!LG8v3t!r$PWA?26$Q!fnPyL5hv&YBh7hFE6 zanj}gyKQ@SU9<cq-MdcUkZ^<bDW&u0<$r%?uf8pvoEf)b_VSA_y`O!*<f*A8#?pSH z;qU=r@3W6`vQrm6pZ&kr;`29lwX_4K-<WN3w+HRsmYOP`x$O2DHa+Ru?hpDID=pIx z6duh#5_I*rK!RG|l`h$YX#yr3QVJOj3mBW&9GO{o1xy?+FgP}YxDatiAQvhQRrb&D zh1cs(y`cwEOAk-wjjHE+#2v;oz4!8yQ`>UhH-+(EEWL8`4(IcxYny`Ny1yO}O`W*> z@Q<ILo@}T#sqwW-seQw7=FIGkhQHTv@@bx_nOSLWJn<Xb|F1`%eTlkjm8MtFqWxy- i;$3}K+xOSANH93OOh`HZC@B&cCk&phelF{r5}E)M9L2o= literal 0 HcmV?d00001 diff --git a/Open-ILS/web/images/facet_box_bg_bottom.png b/Open-ILS/web/images/facet_box_bg_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..fc776c3304e5c31da66d5c352a32fe27e428726b GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^TR?0MHXzBs;nEKzB}-f*N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrH1%UGsEt45_&F=B7Q@Ap;S%g3DT$l+rF-jCFTU|E|-Qrzdwn zdPg<GM<%|m;{|Kg3xuPxbVdL3<OY9MXb!LV_4mQVGxG8e9b1A{Sx4tSmSQNLT<6VI zyv=;Mj<d{xyEPh1n<XAhUvQzpiFv^V1`QJiF5ddM7hbPFwP`dM-+tJ|wO0OmLAyu8 z=5!(16{q#~UV8pOg2(N#-{sHMeUE>2u<y|5w(&fCx^C|by~`H6xObOTq%D!uDwZ{5 zRBoL)UGmr4y6*L{yAn_PlsC?4XzaSi6a8w=J9$PnhIt1~d7T#Jo&kl1r>mdKI;Vst E0I+|0bpQYW literal 0 HcmV?d00001 -- 2.11.0