View | Details | Raw Unified | Return to bug 7642
Collapse All | Expand All

(-)a/C4/Tags.pm (-43 / +53 lines)
Lines 32-52 use vars qw($ext_dict $select_all @fields); Link Here
32
BEGIN {
32
BEGIN {
33
    $VERSION = 3.08.01.002;
33
    $VERSION = 3.08.01.002;
34
	@ISA = qw(Exporter);
34
	@ISA = qw(Exporter);
35
	@EXPORT_OK = qw(
35
    @EXPORT_OK = qw(
36
		&get_tag &get_tags &get_tag_rows
36
      &get_tag &get_tags &get_tag_rows
37
		&add_tags &add_tag
37
      &add_tags &add_tag
38
		&delete_tag_row_by_id
38
      &delete_tag_row_by_id
39
		&remove_tag
39
      &remove_tag
40
		&delete_tag_rows_by_ids
40
      &delete_tag_rows_by_ids
41
		&rectify_weights
41
      &get_approval_rows
42
		&get_approval_rows
42
      &blacklist
43
		&blacklist
43
      &whitelist
44
		&whitelist
44
      &is_approved
45
		&is_approved
45
      &approval_counts
46
		&approval_counts
46
      &get_count_by_tag_status
47
		&get_count_by_tag_status
47
      &get_filters
48
		&get_filters
48
      stratify_tags
49
	);
49
    );
50
	# %EXPORT_TAGS = ();
50
	# %EXPORT_TAGS = ();
51
	$ext_dict = C4::Context->preference('TagsExternalDictionary');
51
	$ext_dict = C4::Context->preference('TagsExternalDictionary');
52
	if ($debug) {
52
	if ($debug) {
Lines 489-522 sub get_tag ($) { # by tag_id Link Here
489
	return $sth->fetchrow_hashref;
489
	return $sth->fetchrow_hashref;
490
}
490
}
491
491
492
sub rectify_weights (;$) {
492
sub increment_weights {
493
	my $dbh = C4::Context->dbh;
494
	my $sth;
495
	my $query = "
496
	SELECT term,biblionumber,count(*) as count
497
	FROM   tags_all
498
	";
499
	(@_) and $query .= " WHERE term =? ";
500
	$query .= " GROUP BY term,biblionumber ";
501
	$sth = $dbh->prepare($query);
502
	if (@_) {
503
		$sth->execute(shift);
504
	} else {
505
		$sth->execute();
506
	}
507
	my $results = $sth->fetchall_arrayref({}) or return undef;
508
	my %tally = ();
509
	foreach (@$results) {
510
		_set_weight($_->{count},$_->{term},$_->{biblionumber});
511
		$tally{$_->{term}} += $_->{count};
512
	}
513
	foreach (keys %tally) {
514
		_set_weight_total($tally{$_},$_);
515
	}
516
	return ($results,\%tally);
517
}
518
519
sub increment_weights ($$) {
520
	increment_weight(@_);
493
	increment_weight(@_);
521
	increment_weight_total(shift);
494
	increment_weight_total(shift);
522
}
495
}
Lines 593-598 sub add_tag ($$;$$) { # biblionumber,term,[borrowernumber,approvernumber] Link Here
593
	}
566
	}
594
}
567
}
595
568
569
# This takes a set of tags, as returned by C<get_approval_rows> and divides
570
# them up into a number of "strata" based on their weight. This is useful
571
# to display them in a number of different sizes.
572
#
573
# Usage:
574
#   ($min, $max) = stratify_tags($strata, $tags);
575
# $stratum: the number of divisions you want
576
# $tags: the tags, as provided by get_approval_rows
577
# $min: the minumum stratum value
578
# $max: the maximum stratum value. This may be the same as $min if there
579
# is only one weight. Beware of divide by zeros.
580
# This will add a field to the tag called "stratum" containing the calculated
581
# value.
582
sub stratify_tags {
583
    my ( $strata, $tags ) = @_;
584
585
    my ( $min, $max );
586
    foreach (@$tags) {
587
        my $w = $_->{weight_total};
588
        $min = $w if ( !defined($min) || $min > $w );
589
        $max = $w if ( !defined($max) || $max < $w );
590
    }
591
592
    # normalise min to zero
593
    $max = $max - $min;
594
    my $orig_min = $min;
595
    $min = 0;
596
597
    # if min and max are the same, just make it 1
598
    my $span = ( $strata - 1 ) / ( $max || 1 );
599
    foreach (@$tags) {
600
        my $w = $_->{weight_total};
601
        $_->{stratum} = int( ( $w - $orig_min ) * $span );
602
    }
603
    return ( $min, $max );
604
}
605
596
1;
606
1;
597
__END__
607
__END__
598
608
(-)a/koha-tmpl/opac-tmpl/prog/en/css/opac.css (+133 lines)
Lines 2520-2522 span.sep { Link Here
2520
}
2520
}
2521
2521
2522
*/
2522
*/
2523
.authstanza {
2524
    margin-top: 1em;
2525
}
2526
2527
.authstanzaheading {
2528
    font-weight: bold;
2529
}
2530
2531
.authstanza li {
2532
    margin-left: 0.5em;
2533
}
2534
2535
#didyoumean {
2536
    background-color: #EEE;
2537
    border: 1px solid #E8E8E8;
2538
    margin: 0 0 0.5em;
2539
    text-align: left;
2540
    padding: 0.5em;
2541
    border-radius: 3px 3px 3px 3px;
2542
}
2543
2544
.suggestionlabel {
2545
    font-weight: bold;
2546
}
2547
2548
.searchsuggestion {
2549
    padding: 0.2em 0.5em;
2550
    white-space: nowrap;
2551
    display: inline-block;
2552
}
2553
2554
.authlink {
2555
    padding-left: 0.25em;
2556
}
2557
#hierarchies a {
2558
    font-weight: normal;
2559
    text-decoration: underline;
2560
    color: #069;
2561
}
2562
2563
#hierarchies a:hover {
2564
    color: #990033;
2565
}
2566
2567
/* jQuery UI Datepicker */
2568
.ui-datepicker table {width: 100%; font-size: .9em; border : 0; border-collapse: collapse; margin:0 0 .4em; }
2569
.ui-datepicker th { background : transparent none; padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
2570
2571
.ui-datepicker-trigger {
2572
    vertical-align: middle;
2573
    margin : 0 3px;
2574
}
2575
.ui-datepicker {
2576
    -moz-box-shadow: 1px 1px 3px 0 #666;
2577
    -webkit-box-shadow: 1px 1px 3px 0 #666;
2578
    box-shadow: 1px 1px 3px 0 #666;
2579
}
2580
2581
.contents {
2582
    width: 75%;
2583
}
2584
2585
.contentblock {
2586
    position: relative;
2587
    margin-left: 2em;
2588
}
2589
2590
.contents .t:first-child:before {
2591
    content: "→ ";
2592
}
2593
2594
.contents .t:before {
2595
    content: "\A→ ";
2596
    white-space: pre;
2597
}
2598
2599
.contents .t {
2600
    font-weight: bold;
2601
    display: inline;
2602
}
2603
2604
.contents .r {
2605
    display: inline;
2606
}
2607
2608
body#opac-main #opacmainuserblockmobile {
2609
    display: none;
2610
}
2611
2612
.mobile_only {
2613
   display : none;
2614
}
2615
2616
/* different sizes for different tags in opac-tags.tt */
2617
.tagweight0 {
2618
    font-size: 12px;
2619
}
2620
2621
.tagweight1 {
2622
    font-size: 14px;
2623
}
2624
2625
.tagweight2 {
2626
    font-size: 16px;
2627
}
2628
2629
.tagweight3 {
2630
    font-size: 18px;
2631
}
2632
2633
.tagweight4 {
2634
    font-size: 20px;
2635
}
2636
2637
.tagweight5 {
2638
    font-size: 22px;
2639
}
2640
2641
.tagweight6 {
2642
    font-size: 24px;
2643
}
2644
2645
.tagweight7 {
2646
    font-size: 26px;
2647
}
2648
2649
.tagweight8 {
2650
    font-size: 28px;
2651
}
2652
2653
.tagweight9 {
2654
    font-size: 30px;
2655
}
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tt (-21 / +1 lines)
Lines 21-46 Link Here
21
</style>
21
</style>
22
<script type="text/javascript">
22
<script type="text/javascript">
23
//<![CDATA[
23
//<![CDATA[
24
	var fontsizes = new Array (12,14,16,18,20,22,24,26,28,30);
25
	var fontcount = fontsizes.length;
26
	var maxcloudweight = 1;
27
	$(document).ready(function() {
28
		// $('#tagcloud').css('background-color','lightgrey');
29
		// $('#tagcloud .tag').css('border','1px solid black');
30
		$('#tagcloud .tag').each(function() {
31
			if (maxcloudweight < this.title) { maxcloudweight = this.title; }
32
			// have to run through the set of tags once to get the max: cannot be combined w/ 2nd pass
33
		});
34
		$('#tagcloud .tag').each(function(i) {
35
			var pos = this.id;
36
			var weight = this.title;	// "cloudweight"
37
			weight = (! weight) ? 1 : (weight > maxcloudweight) ? maxcloudweight : weight ;
38
			var index = Math.round(fontcount * weight/maxcloudweight) - 1;
39
			index  = (! index ) ? 0 : ( index > fontcount     ) ? fontcount      : index  ;
40
			var newsize = fontsizes[index];
41
			// alert(pos+ " (" +i+ ") weight = " +weight+ " of " +maxcloudweight+ ", fontsize[" +index+ " of " +fontcount+ "] = " +newsize);
42
			$('#' + pos).css({"font-size":(newsize + 'px'), display:"inline"});
43
		});
44
		$("#mytagst").tablesorter({[% IF ( dateformat == 'metric' ) %]
24
		$("#mytagst").tablesorter({[% IF ( dateformat == 'metric' ) %]
45
    dateFormat: 'uk',[% END %]
25
    dateFormat: 'uk',[% END %]
46
            widgets : ['zebra'],
26
            widgets : ['zebra'],
Lines 90-96 Link Here
90
	[% IF ( TAGLOOP ) %]
70
	[% IF ( TAGLOOP ) %]
91
	<div id="tagcloud">
71
	<div id="tagcloud">
92
	[% FOREACH TAGLOO IN TAGLOOP %]
72
	[% FOREACH TAGLOO IN TAGLOOP %]
93
	<span class="tag" id="tag[% loop.count %]" title="[% TAGLOO.cloudweight %]">
73
        <span class="tag tagweight[% TAGLOO.stratum %]" id="tag[% loop.count %]" style="display:inline;">
94
		<a href="/cgi-bin/koha/opac-search.pl?tag=[% TAGLOO.term |url %]&amp;q=[% TAGLOO.term |url %]">
74
		<a href="/cgi-bin/koha/opac-search.pl?tag=[% TAGLOO.term |url %]&amp;q=[% TAGLOO.term |url %]">
95
		[% TAGLOO.term |html %]</a>
75
		[% TAGLOO.term |html %]</a>
96
			<span class="tagweight">[% TAGLOO.weight_total %]</span>
76
			<span class="tagweight">[% TAGLOO.weight_total %]</span>
(-)a/opac/opac-tags.pl (-27 / +2 lines)
Lines 41-47 use C4::Debug; Link Here
41
use C4::Output 3.02 qw(:html :ajax pagination_bar);
41
use C4::Output 3.02 qw(:html :ajax pagination_bar);
42
use C4::Scrubber;
42
use C4::Scrubber;
43
use C4::Biblio;
43
use C4::Biblio;
44
use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag);
44
use C4::Tags qw(add_tag get_approval_rows get_tag_rows remove_tag stratify_tags);
45
45
46
use Data::Dumper;
46
use Data::Dumper;
47
47
Lines 263-296 if ($add_op) { Link Here
263
		$arghash->{biblionumber} = $arg;
263
		$arghash->{biblionumber} = $arg;
264
	}
264
	}
265
	$results = get_approval_rows($arghash);
265
	$results = get_approval_rows($arghash);
266
266
    stratify_tags(10, $results); # work out the differents sizes for things
267
	my $count = scalar @$results;
267
	my $count = scalar @$results;
268
	$template->param(TAGLOOP_COUNT => $count, mine => $mine);
268
	$template->param(TAGLOOP_COUNT => $count, mine => $mine);
269
	# Here we make a halfhearted attempt to separate the tags into "strata" based on weight_total
270
	# FIXME: code4lib probably has a better algorithm, iirc
271
	# FIXME: when we get a better algorithm, move to C4
272
	my $maxstrata = 5;
273
	my $strata = 1;
274
	my $previous = 0;
275
	my $chunk = ($count/$maxstrata)/2;
276
	my $total = 0;
277
	my %cloud;
278
	foreach (reverse @$results) {
279
		my $current = $_->{weight_total};
280
		$total++;
281
		$cloud{$strata}++;
282
		if ($current == $previous) {
283
			$_->{cloudweight} = $strata;
284
			next;
285
		} 
286
		if ($strata < $maxstrata and 
287
			($cloud{$strata} > $chunk or 
288
			$count-$total <= $maxstrata-$strata)) {
289
			$strata++;
290
		}
291
		$_->{cloudweight} = $strata;
292
		$previous = $current;
293
	}
294
}
269
}
295
(scalar @errors  ) and $template->param(ERRORS  => \@errors);
270
(scalar @errors  ) and $template->param(ERRORS  => \@errors);
296
my @orderedresult = sort { uc($a->{'term'}) cmp uc($b->{'term'}) } @$results;
271
my @orderedresult = sort { uc($a->{'term'}) cmp uc($b->{'term'}) } @$results;
(-)a/t/db_dependent/Tags.t (-2 / +52 lines)
Lines 6-14 Link Here
6
use strict;
6
use strict;
7
use warnings;
7
use warnings;
8
8
9
use Test::More tests => 1;
9
use Test::More tests => 30;
10
10
11
BEGIN {
11
BEGIN {
12
        use_ok('C4::Tags');
12
        use_ok('C4::Tags');
13
}
13
}
14
14
15
- 
15
# Simple 'sequential 5' test
16
my $tags = make_tags(1,2,3,4,5);
17
my @strata = (0,1,2,3,4);
18
my ($min, $max) = C4::Tags::stratify_tags(5, $tags);
19
check_tag_strata($tags, \@strata, 'Sequential 5');
20
is($min, 0, 'Sequential 5 min');
21
is($max, 4, 'Sequential 5 max');
22
23
# Reverse test - should have the same results as previous
24
$tags = make_tags(5,4,3,2,1);
25
@strata = (4,3,2,1,0);
26
($min, $max) = C4::Tags::stratify_tags(5, $tags);
27
check_tag_strata($tags, \@strata, 'Reverse Sequential 5');
28
is($min, 0, 'Sequential 5 min');
29
is($max, 4, 'Sequential 5 max');
30
31
# All the same test - should all have the same results
32
$tags = make_tags(4,4,4,4,4);
33
@strata = (0,0,0,0,0);
34
($min, $max) = C4::Tags::stratify_tags(5, $tags);
35
check_tag_strata($tags, \@strata, 'All The Same');
36
is($min, 0, 'Sequential 5 min');
37
is($max, 0, 'Sequential 5 max');
38
39
# Some the same, some different
40
$tags = make_tags(1,2,2,3,3,8);
41
@strata = (0,0,0,1,1,4);
42
($min, $max) = C4::Tags::stratify_tags(5, $tags);
43
check_tag_strata($tags, \@strata, 'All The Same');
44
is($min, 0, 'Sequential 5 min');
45
is($max, 7, 'Sequential 5 max');
46
47
# Runs tests against the results
48
sub check_tag_strata {
49
    my ($tags, $expected, $name) = @_;
50
51
    foreach my $t (@$tags) {
52
        my $w = $t->{weight_total};
53
        my $s = $t->{stratum};
54
        is($s, shift @$expected, $name . " - $w ($s)");
55
    }
56
}
57
58
# Makes some tags with just enough info to test
59
sub make_tags {
60
    my @res;
61
    while (@_) {
62
        push @res, { weight_total => shift @_ };
63
    }
64
    return \@res;
65
}

Return to bug 7642