[Debtags-commits] [svn] r1527 - central-database/branches/alioth/webfrontend

Enrico Zini enrico at costa.debian.org
Thu Nov 24 15:29:54 UTC 2005


Author: enrico
Date: Thu Nov 24 15:29:52 2005
New Revision: 1527

Modified:
   central-database/branches/alioth/webfrontend/edittemplate.html
   central-database/branches/alioth/webfrontend/maint
   central-database/branches/alioth/webfrontend/search.cgi
   central-database/branches/alioth/webfrontend/searchtemplate.html
   central-database/branches/alioth/webfrontend/widgets.js
Log:
New client-side search.cgi works

Modified: central-database/branches/alioth/webfrontend/edittemplate.html
==============================================================================
--- central-database/branches/alioth/webfrontend/edittemplate.html	(original)
+++ central-database/branches/alioth/webfrontend/edittemplate.html	Thu Nov 24 15:29:52 2005
@@ -90,6 +90,20 @@
   {
 	return "editbox-" + this.facet.name;
   }
+  FacetBox.prototype.contentSignature = function ()
+  {
+	var a = new Array();
+	var f = this.facet;
+	for (var i in f.tags)
+	{
+		var t = f.tags[i]
+		if (tags.has(t.name))
+			a.push("+"+t.name);
+		else
+			a.push("-"+t.name);
+	}
+  	return (open ? "open" : "closed") + '/' + this.facet.name + "/" + a.join(',');
+  }
   FacetBox.prototype.renderOpen = function()
   {
 	var res = "";
@@ -170,6 +184,18 @@
   {
 	return "curtags";
   }
+  CurTags.prototype.contentSignature = function ()
+  {
+	var a = new Array();
+	for (var f in voc.facets)
+		for (var i in voc.facets[f].tags)
+		{
+			var t = voc.facets[f].tags[i];
+			if (tags.has(t.name))
+				a.push(t.name);
+		}
+  	return a.join(',');
+  }
   CurTags.prototype.render = function()
   {
   	var res = "";
@@ -219,6 +245,10 @@
   {
 	return "curpatch";
   }
+  CurPatch.prototype.contentSignature = function ()
+  {
+  	return tags.mkPatch();
+  }
   CurPatch.prototype.render = function()
   {
 	var patch = tags.mkPatch();

Modified: central-database/branches/alioth/webfrontend/maint
==============================================================================
--- central-database/branches/alioth/webfrontend/maint	(original)
+++ central-database/branches/alioth/webfrontend/maint	Thu Nov 24 15:29:52 2005
@@ -185,6 +185,10 @@
 } elsif ($cmd eq 'jsvocab') {
 	Engine::openDB();
 	print q{// Define classes and instances for a global tag vocabulary
+function extractFacet(tag)
+{
+	return tag.slice(0, tag.indexOf("::"));
+}
 
 function Facet(name, sdesc, ldesc)
 {
@@ -216,6 +220,10 @@
 Vocabulary.prototype.get = function(name) {
 	return this[name];
 }
+Vocabulary.prototype.getTag = function(name) {
+	
+	return this[extractFacet(name)][name];
+}
 
 var voc = new Vocabulary();
 

Modified: central-database/branches/alioth/webfrontend/search.cgi
==============================================================================
--- central-database/branches/alioth/webfrontend/search.cgi	(original)
+++ central-database/branches/alioth/webfrontend/search.cgi	Thu Nov 24 15:29:52 2005
@@ -16,7 +16,6 @@
 ## Configuration options
 ##
 
-#my $release="unstable";
 my $max_tags = 6;
 
 ##
@@ -40,107 +39,28 @@
 # Open database connection
 Engine::openDB();
 
-# Load the template file
-my $template = HTML::Template->new(
-	filename => 'searchtemplate.html',
-	die_on_bad_params => 0)
-|| die "Could not open template";
-
 #Web::timing("init");
 
 # Parse input values
 my (@want_tags, @unwant_tags, @ignore_tags, @sel_words);
-my $action = 'begin';
+my $action;
 
 if (my $selwords = param('start'))
 {
-	$action = 'search';
-#	msg "Found: start->%s\n", $selwords;
+	$action = 'start';
 	if ($selwords =~ m/[A-Za-z0-9 ._-]+/)
 	{
 		@sel_words = grep { $_ } split(/\s+/, $selwords);
-		@unwant_tags = ('role::aux:dummy', 'role::content:data', 'role::sw:devel-lib', 'role::sw:shlib');
 		@want_tags = Engine::tagsForSearch($max_tags, {
 				words => \@sel_words,
 				notags => [Engine::tags(@unwant_tags)]
 		});
 	}
-} elsif ($selwords = param('oldstart')) {
-	$action = 'search';
-#	msg "Found: oldstart->%s\n", $selwords;
-	if ($selwords =~ m/[A-Za-z0-9 ._-]+/)
-	{
-		@sel_words = grep { $_ } split(/\s+/, $selwords);
-	}
-
-	if (my $want = param('want'))
-	{
-#		msg "Found: want->%s\n", $want;
-		if ($want =~ m/([a-z0-9\-:.,]+)/)
-		{
-			@want_tags = split(/,/, $1);
-		}
-	}
-	if (my $unwant = param('unwant'))
-	{
-#		msg "Found: unwant->%s\n", $unwant;
-		if ($unwant =~ m/([a-z0-9\-:.,]+)/)
-		{
-			@unwant_tags = split(/,/, $1);
-		}
-	}
-	if (my $ignore = param('ignore'))
-	{
-#		msg "Found: unwant->%s\n", $unwant;
-		if ($ignore =~ m/([a-z0-9\-:.,]+)/)
-		{
-			@ignore_tags = split(/,/, $1);
-		}
-	}
-	if (my $tag = param('addwa'))
-	{
-#		msg "Found: addwa->%s\n", $tag;
-		push @want_tags, $tag if ($tag =~ /^[a-z0-9\-:]+$/);
-		@unwant_tags = grep { $_ ne $tag } @unwant_tags;
-		@ignore_tags = grep { $_ ne $tag } @ignore_tags;
-	}
-	if (my $tag = param('addun'))
-	{
-#		msg "Found: addun->%s\n", $tag;
-		push @unwant_tags, $tag if ($tag =~ /^[a-z0-9\-:]+$/);
-		@want_tags = grep { $_ ne $tag } @want_tags;
-		@ignore_tags = grep { $_ ne $tag } @ignore_tags;
-	}
-	if (my $tag = param('addig'))
-	{
-#		msg "Found: addig->%s\n", $tag;
-		push @ignore_tags, $tag if ($tag =~ /^[a-z0-9\-:]+$/);
-		@want_tags = grep { $_ ne $tag } @want_tags;
-		@unwant_tags = grep { $_ ne $tag } @unwant_tags;
-	}
-	if (my $tag = param('rmwa'))
-	{
-#		msg "Found: rmwa->%s\n", $tag;
-		if ($tag =~ /^[a-z0-9\-:]+$/)
-		{
-			@want_tags = grep { $_ ne $tag } @want_tags;
-		}
-	}
-	if (my $tag = param('rmun'))
-	{
-#		msg "Found: rmun->%s\n", $tag;
-		if ($tag =~ /^[a-z0-9\-:]+$/)
-		{
-			@unwant_tags = grep { $_ ne $tag } @unwant_tags;
-		}
-	}
-	if (my $tag = param('rmig'))
+} elsif (my $want = param('searchbase')) {
+	$action = 'update';
+	if ($want =~ m/([a-z0-9\-:.,]+)/)
 	{
-#		msg "Found: rmig->%s\n", $tag;
-		if ($tag =~ /^[a-z0-9\-:]+$/)
-		{
-			@ignore_tags = grep { $_ ne $tag } @ignore_tags;
-		}
+		@want_tags = split(/,/, $1);
 	}
 }
 
@@ -148,22 +68,6 @@
 {
 	my %seen;
 	@want_tags = Engine::tags(grep { exists $seen{$_} ? undef : $seen{$_} = 1, 1 } @want_tags);
-
-	%seen = ();
-	@unwant_tags = Engine::tags(grep { exists $seen{$_} ? undef : $seen{$_} = 1, 1 } @unwant_tags);
-
-	%seen = ();
-	@ignore_tags = Engine::tags(grep { exists $seen{$_} ? undef : $seen{$_} = 1, 1 } @ignore_tags);
-}
-
-sub linkself (@)
-{
-	return '?'.join('&',
-					'oldstart='.uri_escape(join(' ', @sel_words)),
-					'want='.join(',', map { uri_escape($_->name) } @want_tags),
-					'unwant='.join(',', map { uri_escape($_->name) } @unwant_tags),
-					'ignore='.join(',', map { uri_escape($_->name) } @ignore_tags),
-					@_);
 }
 
 #Web::timing("parms");
@@ -174,257 +78,53 @@
 ## Perform the search
 ##
 
-my %tags;
-my %blacklist = map { $_->name => 1 } (@want_tags, @unwant_tags, @ignore_tags);
-my @ht_pkgs;
-for my $p (Engine::findPackages({
-				tags => \@want_tags,
-#				notags => \@unwant_tags,
-			}))
-{
-	for my $t ($p->tags())
-	{
-		++$tags{$t->name()} if not exists $blacklist{$t->name()} and $t->name() !~ /^special::/;
-	}
-	push @ht_pkgs, {
-		NAME    => $p->name(),
-		SDESC   => uri_escape($p->sdesc()),
-		LDESC   => uri_escape($p->ldesc()),
-		TAGS	=> [ map { { NAME => $_->name } } $p->tags() ],
-		URL     => "edit.cgi?pkg=".uri_escape($p->name()),
-	};
-}
-
-my $pkg_count = scalar @ht_pkgs;
-my @top_tags = sort { $tags{$b} <=> $tags{$a} } keys %tags;
-
-# Move redundant tags to the bottom
-for (my $i = 0; $i < @top_tags; $i++)
-{
-	if ($tags{$top_tags[0]} == $pkg_count)
-	{
-		push(@top_tags, shift @top_tags);
-	}
-}
-
-# Choose the most important ones
- at top_tags = Engine::tags(@top_tags[0 .. $max_tags]);
+my @pkgs = Engine::findPackages({ tags => \@want_tags });
 
-#Navigation::build(@sel_tags, @sel_words);
+my $pkg_count = scalar @pkgs;
 
 #Web::timing("nav");
 
-# Select the facets we want to view
-#my @ht_facets;
-#my $i = 0;
-#foreach (@Navigation::ht_facets)
-#{
-#	last if $i >= $max_facets;
-#	next if not $_->{SELCOUNT} and $hidden_facets{$_->{NAME}};
-#	push(@ht_facets, $_);
-#	$i++;
-#}
-
-my @ht_wtags;
-my @ht_utags;
-my @ht_itags;
-my @ht_ttags;
-
-foreach my $t (@want_tags)
-{
-	# Skip the empty tags
-	#next if not exists $tag_counts{$t->name};
-
-	push @ht_wtags, {
-		NAME => $t->name,
-		FNAME => $t->facet()->name(),
-		FSDESC => $t->facet()->sdesc(),
-		FLDESC => $t->facet()->ldesc(),
-		SDESC => $t->sdesc,
-		LDESC => $t->ldesc,
-#		COUNT => $tag_counts{$t->name},
-		REMURL => linkself("rmwa=".uri_escape($t->name)),
-		IGURL => linkself("addig=".uri_escape($t->name)),
-		UNWURL => linkself("addun=".uri_escape($t->name)),
-	};
-}
-foreach my $t (@unwant_tags)
-{
-	# Skip the empty tags
-	#next if not exists $tag_counts{$t->name};
-
-	push @ht_utags, {
-		NAME => $t->name,
-		FNAME => $t->facet()->name(),
-		FSDESC => $t->facet()->sdesc(),
-		FLDESC => $t->facet()->ldesc(),
-		SDESC => $t->sdesc,
-		LDESC => $t->ldesc,
-#		COUNT => $tag_counts{$t->name},
-		REMURL => linkself("rmun=".uri_escape($t->name)),
-		IGURL => linkself("addig=".uri_escape($t->name)),
-		WAURL => linkself("addwa=".uri_escape($t->name)),
-	};
-}
-foreach my $t (@ignore_tags)
-{
-	# Skip the empty tags
-	#next if not exists $tag_counts{$t->name};
+##
+## Compile template structures
+##
 
-	push @ht_itags, {
-		NAME => $t->name,
-		FNAME => $t->facet()->name(),
-		FSDESC => $t->facet()->sdesc(),
-		FLDESC => $t->facet()->ldesc(),
-		SDESC => $t->sdesc,
-		LDESC => $t->ldesc,
-#		COUNT => $tag_counts{$t->name},
-		REMURL => linkself("rmig=".uri_escape($t->name)),
-		WAURL => linkself("addwa=".uri_escape($t->name)),
-		UNWURL => linkself("addun=".uri_escape($t->name)),
-	};
-}
-foreach my $t (@top_tags)
+if ($action eq 'start')
 {
-	# Skip the empty tags
-	#next if not exists $tag_counts{$t->name};
+	# Load the template file
+	my $template = HTML::Template->new(
+		filename => 'searchtemplate.html',
+		die_on_bad_params => 0)
+	|| die "Could not open template";
 
-	push @ht_ttags, {
-		NAME => $t->name,
-		FNAME => $t->facet()->name(),
-		FSDESC => $t->facet()->sdesc(),
-		FLDESC => $t->facet()->ldesc(),
-		SDESC => $t->sdesc,
-		LDESC => $t->ldesc,
-#		COUNT => $tag_counts{$t->name},
-		WAURL => linkself("addwa=".uri_escape($t->name)),
-		UNWURL => linkself("addun=".uri_escape($t->name)),
-		IGURL => linkself("addig=".uri_escape($t->name)),
-		REDUNDANT => ($tags{$t->name} == $pkg_count),
-	};
-}
+	$template->param('BEGIN' => ($action eq 'begin'));
+	$template->param(CURWORDS => join(' ', at sel_words));
 
-##
-## Compile template structures
-##
+	$template->param(WTAGS => [ map { { NAME => $_->name } } @want_tags ]);
 
-$template->param('BEGIN' => ($action eq 'begin'));
-$template->param(CURWORDS => join(' ', at sel_words));
+	$template->param(PKGS => [ map { {
+		NAME    => $_->name(),
+		SDESC   => uri_escape($_->sdesc()),
+		TAGS	=> [ map { { NAME => $_->name } } $_->tags() ],
+	} } @pkgs ]);
 
-$template->param(WTAGS => \@ht_wtags);
-$template->param(UTAGS => \@ht_utags);
-$template->param(ITAGS => \@ht_itags);
-$template->param(TTAGS => \@ht_ttags);
-$template->param(PKGS => \@ht_pkgs);
+	if ($Web::log)
+	{
+		$template->param(LOG => Web::log_html());
+	}
 
-my $count_pkg = scalar @ht_pkgs;
-if ($count_pkg == 0)
-{
-	$template->param(PKGS_INTRO => "No packages found:");
-} elsif ($count_pkg == 1) {
-	$template->param(PKGS_INTRO => "One package found:");
+	# Finally, output
+	print "Content-Type: text/html\n\n";
+	print $template->output();
 } else {
-	$template->param(PKGS_INTRO => "$count_pkg packages found:");
-}
-#my $count_hf = keys %hidden_facets;
-#if ($count_hf == 1)
-#{
-#	$template->param(UHF_TEXT => "Unhide one hidden facet");
-#} elsif ($count_hf > 1) {
-#	$template->param(UHF_TEXT => "Unhide $count_hf hidden facets");
-#}
-#
-#my $facet_intro;
-#my $c = scalar(keys %Navigation::tag_counts);
-#if ($c == 0)
-#{
-#	$facet_intro = "There is <b>no</b> tag ";
-#} elsif ($c == 1) {
-#	$facet_intro = "There is <b>one</b> tag ";
-#} else {
-#	$facet_intro = "There are <b>$c</b> tags ";
-#}
-#if ($Navigation::count_unselected == 0)
-#{
-#	$facet_intro .= "currently selected."
-#} else {
-#	$c = scalar keys %Navigation::facet_counts;
-#	if ($c == 1)
-#	{
-#		$facet_intro .= "in <b>one</b> facet. ";
-#	} else {
-#		$facet_intro .= sprintf "in <b>%d</b> facets. ", $c;
-#	} 
-#	$c = scalar(@sel_tags);	
-#	if ($c == 0)
-#	{
-#		$facet_intro .= "<b>None</b> is currently selected.";
-#	}
-#	elsif ($c == 1)
-#	{
-#		$facet_intro .= "<b>One</b> is currently selected.";
-#	} else {
-#		$facet_intro .= sprintf "<b>%d</b> are currently selected.", $c;
-#	} 
-#}
-#my $cur_facets = scalar(@ht_facets);
-#if ($cur_facets > 0)
-#{
-#	my $count_active_facets = scalar(@Navigation::ht_facets);
-#	if ($cur_facets == 1)
-#	{
-#		$facet_intro .= "  <b>One</b> facet out of <b>$count_active_facets</b> is currently displayed.";
-#	} else {
-#		$facet_intro .= "  <b>$cur_facets</b> facets out of <b>$count_active_facets</b> are currently displayed.";
-#	}
-#}
-#
-#$template->param(FACET_INTRO => $facet_intro);
-#
-#my $curpkgs_intro;
-#my $curpkgs_also;
-#my $cur = scalar(@Navigation::ht_curpkgs);
-#my $sub = scalar(@Navigation::ht_subpkgs);
-#if ($cur == 0)
-#{
-#	$curpkgs_intro = "There is <b>no</b> package in this group.  ";
-#	$curpkgs_also = '';
-#} elsif ($cur == 1) {
-#	$curpkgs_intro = "There is <b>one</b> package in this group.  ";
-#	$curpkgs_also = ' also';
-#} else {
-#	$curpkgs_intro = "There are <b>$cur</b> packages in this group.  ";
-#	$curpkgs_also = ' also';
-#}
-#if ($sub == 0)
-#{
-#	$curpkgs_intro .= "More packages can be found by further refining the selection."
-#} else {
-#	my $cp_verb;
-#	if ($sub == 1) {
-#		$curpkgs_intro .= "<b>One</b> package from ";
-#		$cp_verb = "is";
-#	} else {
-#		$curpkgs_intro .= "<b>$sub</b> packages from ";
-#		$cp_verb = "are";
-#	}
-#	my $subgroup_count = $Navigation::subgroup_count;
-#	if ($subgroup_count == 1) {
-#		$curpkgs_intro .= "<b>one</b> subgroup $cp_verb$curpkgs_also displayed below.";
-#	} else {
-#		$curpkgs_intro .= "<b>$subgroup_count</b> subgroups $cp_verb$curpkgs_also displayed below.";
-#	}
-#}
-#$template->param(PKGS_INTRO => $curpkgs_intro);
-
-if ($Web::log)
-{
-	$template->param(LOG => Web::log_html());
+	print "Content-Type: text/plain\n\n";
+	for my $p (@pkgs)
+	{
+		printf "%s %s %s\n",
+			$p->name(),
+			uri_escape($p->sdesc()),
+			uri_escape(join(',', map { $_->name } $p->tags()));
+	};
 }
 
-# Finally, output
-print "Content-Type: text/html\n\n";
-print $template->output();
-
 exit 0;
 # vim:set ts=4 sw=4:

Modified: central-database/branches/alioth/webfrontend/searchtemplate.html
==============================================================================
--- central-database/branches/alioth/webfrontend/searchtemplate.html	(original)
+++ central-database/branches/alioth/webfrontend/searchtemplate.html	Thu Nov 24 15:29:52 2005
@@ -53,6 +53,17 @@
 Pkgs.prototype.count = function() {
 	return this.pkgs.length;
 }
+Pkgs.prototype.countVisible = function() {
+	var res = 0;
+	for (var i = 0; i < this.pkgs.length; i++)
+		if (this.pkgs[i].visible)
+			res++;
+	return res;
+}
+Pkgs.prototype.clear = function() {
+	this.pkgs = new Array();
+	this.data = new Object();
+}
 
 var pkgs = new Pkgs();
 
@@ -98,6 +109,12 @@
 {
 	this.searchBase[tagName] = true;
 }
+Search.prototype.updateSearchBase = function()
+{
+	this.searchBase = new Object();
+	for (t in this.wanted.items)
+		this.addSearchBase(this.wanted.items[t]);
+}
 Search.prototype.fitsSearchBase = function()
 {
 	// Returns true if searchBase is a subset of wantedItems
@@ -122,6 +139,7 @@
 Search.prototype.recompute = function()
 {
 	var tagCounts = new Object;
+	var countVisible = 0;
 	for (i in pkgs.pkgs)
 	{
 		// Iterate all packages setting them visible as needed
@@ -135,16 +153,28 @@
 					tagCounts[p.tags[t]] = 1;
 				else
 					++tagCounts[p.tags[t]];
+			++countVisible;
 		}
 	}
 	this.top = new Bucket();
 
+	// Update the cardinality of all tags
+	for (var f in voc.facets)
+		for (var i in voc.facets[f].tags)
+		{
+			var t = voc.facets[f].tags[i];
+			t.card = tagCounts[t.name] ? tagCounts[t.name] : 0;
+		}
+
 	// Fill this.top with the top-hits in tagCounts
 	var arrs = new Array();
 	for (var i in tagCounts)
 	{
-		if (!this.wanted.has(i) && !this.unwanted.has(i) && !this.ignored.has(i))
-			arrs.push(i);
+		if (this.wanted.has(i) || this.unwanted.has(i) || this.ignored.has(i))
+			continue;
+		if (i.substr(0, 9) == 'special::')
+			continue;
+		arrs.push(i);
 	}
 	arrs.sort(function(a, b) {
 		if (tagCounts[b] != tagCounts[a])
@@ -152,6 +182,14 @@
 		else
 			return a < b ? -1 : 1;
 	});
+
+	// Move redundant tags to the bottom
+	for (var i = 0; i < arrs.length; i++)
+		if (tagCounts[arrs[i]] == countVisible)
+			arrs.push(arrs.shift());
+		else
+			break;
+
 	for (var i = 0; i < arrs.length && i < 6; i++)
 		this.top.add(arrs[i]);
 }
@@ -164,39 +202,43 @@
 		this.ignored.del(tagName);
 		this.recompute();
 	}
+	return true;
 }
 Search.prototype.unwant = function(tagName)
 {
 	if (!this.unwanted.has(tagName))
 	{
-		if (this.wanted.del(tagName))
-			if (!this.fitsSearchBase())
-				alert("TODO: we enlarged the search base and must reload");
 		this.unwanted.add(tagName);
 		this.ignored.del(tagName);
+		if (this.wanted.del(tagName))
+			if (!this.fitsSearchBase())
+				return false;
 		this.recompute();
 	}
+	return true;
 }
 Search.prototype.ignore = function(tagName)
 {
 	if (!this.ignored.has(tagName))
 	{
-		if (this.wanted.del(tagName))
-			if (!this.fitsSearchBase())
-				alert("TODO: we enlarged the search base and must reload");
 		this.unwanted.del(tagName);
 		this.ignored.add(tagName);
+		if (this.wanted.del(tagName))
+			if (!this.fitsSearchBase())
+				return false;
 		this.recompute();
 	}
+	return true;
 }
 Search.prototype.reset = function(tagName)
 {
-	if (this.wanted.del(tagName))
-		if (!this.fitsSearchBase())
-			alert("TODO: we enlarged the search base and must reload");
 	this.unwanted.del(tagName);
 	this.ignored.del(tagName);
+	if (this.wanted.del(tagName))
+		if (!this.fitsSearchBase())
+			return false;
 	this.recompute();
+	return true;
 }
 
 var search = new Search();
@@ -210,36 +252,65 @@
 
 function PackageBox()
 {
+	this.state = 'view';
 }
 PackageBox.prototype.name = function()
 {
 	return "packages";
 }
+PackageBox.prototype.setState = function(state)
+{
+	this.state = state;
+	this.loaded = 0;
+}
+PackageBox.prototype.setLoaded = function(amount)
+{
+	this.loaded = amount;
+}
 PackageBox.prototype.render = function()
 {
 	var res = "";
-      	res += "<div class='intro'>\n";
-        res += "  <p><tmpl_var name='PKGS_INTRO'></p>\n";
-      	res += "</div>\n";
-	res += "<div id='curpkgs'>\n";
-    	for (i in pkgs.pkgs)
+	if (this.state == 'view')
 	{
-		var p = pkgs.pkgs[i];
-		if (p.visible)
+		res += "<div class='intro'>\n";
+		var count_pkg = pkgs.countVisible();
+		switch (count_pkg)
+		{
+			case 0:  res += "  <p>No packages found.</p>\n"; break;
+			case 1:  res += "  <p>One package found:</p>\n"; break;
+			default: res += "  <p>"+count_pkg+" packages found:</p>\n"; break;
+		}
+		res += "</div>\n";
+		res += "<div id='curpkgs'>\n";
+		for (i in pkgs.pkgs)
 		{
-			res += "  <a class='pkg' href='<tmpl_var name="URL">'>" + p.name + "</a> - ";
-			res += p.sdesc;
-			res += "<a class='button' href='?start=" + p.name + "'>[similar]</a>";
-			res += "<br />\n";
+			var p = pkgs.pkgs[i];
+			if (p.visible)
+			{
+				res += "  <a class='pkg' href='edit.cgi?pkg="+escape(p.name)+"'>" + p.name + "</a> - ";
+				res += p.sdesc;
+				res += "<a class='button' href='?start=" + escape(p.name) + "'>[similar]</a>";
+				res += "<br />\n";
+			}
 		}
+		res += "</div>\n";
+	} else if (this.state == 'loading') {
+		res += "<blink>Loading... (" + this.loaded + " bytes loaded)</blink>";
 	}
-      	res += "</div>\n";
 	return res;
 }
-PackageBox.prototype.updateView = function()
+PackageBox.prototype.contentSignature = function()
 {
-	node = document.getElementById(this.name())
-	node.innerHTML = this.render();
+	if (this.state == 'view')
+	{
+		var res = new Array();
+		for (i in pkgs.pkgs)
+			if (pkgs.pkgs[i].visible)
+				res.push(i);
+		return this.state + "/" + res.join(",");
+	} else if (this.state == 'loading') {
+		return this.state + "/" + this.loaded;
+	}
 }
 
 // Tag box
@@ -269,6 +340,7 @@
 }
 TagBox.prototype.render = function()
 {
+	var countVisible = pkgs.countVisible();
 	var res = "";
       	res += "<p>" + this.title + ":\n";
 
@@ -294,14 +366,19 @@
 			res += "  <span title='"+t.name+": "+t.ldesc+"'>"+t.sdesc+"</span>\n";
 			res += "</div>\n";
 			res += "<div class='sebuttons'>\n";
-			if (this.index != 0)
-				res += "  <span class='button' onClick='ctl.want(\""+tagName+"\")'>[Want]</span>\n";
-			if (this.index != 1)
-				res += "  <span class='button' onClick='ctl.unwant(\""+tagName+"\")'>[Don't want]</span>\n";
-			if (this.index != 2)
-				res += "  <span class='button' onClick='ctl.ignore(\""+tagName+"\")'>[Ignore]</span>\n";
-			if (this.index != 3)
-				res += "  <span class='button' onClick='ctl.reset(\""+tagName+"\")'>[Remove]</span>\n";
+			if (this.index == 3 && t.card == countVisible)
+			{
+				res += "  (already in all results)\n";
+			} else {
+				if (this.index != 0 && t.card > 0)
+					res += "  <span class='button' onClick='ctl.want(\""+tagName+"\")'>[Want]</span>\n";
+				if (this.index != 1 && t.card < countVisible)
+					res += "  <span class='button' onClick='ctl.unwant(\""+tagName+"\")'>[Don't want]</span>\n";
+				if (this.index != 2)
+					res += "  <span class='button' onClick='ctl.ignore(\""+tagName+"\")'>[Ignore]</span>\n";
+				if (this.index != 3)
+					res += "  <span class='button' onClick='ctl.reset(\""+tagName+"\")'>[Remove]</span>\n";
+			}
 			res += "</div>\n";
 			res += "</li>\n";
 		}
@@ -310,38 +387,116 @@
 	}
 	return res;
 }
-TagBox.prototype.updateView = function()
+TagBox.prototype.contentSignature = function()
 {
-	node = document.getElementById(this.name())
-	node.innerHTML = this.render();
+	var res = new Array();
+	var items = this.items();
+	for (i in items)
+		res.push(items[i]);
+	return res.join(",");
+}
+
+// From http://jibbering.com/2002/4/httprequest.html
+var req = false;
+/*@cc_on @*/
+/*@if (@_jscript_version >= 5)
+// JScript gives us Conditional compilation, we can cope with old IE versions.
+// and security blocked creation of the objects.
+try {
+	req = new ActiveXObject("Msxml2.XMLHTTP");
+} catch (e) {
+	try {
+		req = new ActiveXObject("Microsoft.XMLHTTP");
+	} catch (E) {
+		req = false;
+	}
+}
+ at end @*/
+if (!req && typeof XMLHttpRequest != 'undefined') {
+	req = new XMLHttpRequest();
 }
-
-
 
 
 ///
 /// Controller
 ///
 
+var cbcount;
+Controller.prototype.reloadPackages = function()
+{
+	// Build the new search base
+	var base = new Array();
+	for (var t in search.wanted.items)
+		base.push(search.wanted.items[t]);
+	
+	//alert("TODO: reloading packages after search base changed");
+	req.open("GET", "?searchbase="+escape(base.join(',')),true);
+	cbcount = 0;
+	req.onreadystatechange = function() {
+		switch (req.readyState)
+		{
+			case 4:
+				if (req.status != 200)
+				{
+					alert("Downloading new package informations failed:\n" + req.statusText);
+					break
+				}
+				pkgs.clear();
+				// Decode new package informations
+				var lines = req.responseText.split('\n');
+				for (var line in lines)
+				{
+					var fields = lines[line].split(' ');
+					if (fields.length < 3)
+						continue;
+					var p = new Package(fields[0], unescape(fields[1]), null);
+					var tags = unescape(fields[2]).split(',');
+					for (var tag in tags)
+						p.addTag(tags[tag]);
+					pkgs.add(p);
+				}
+				search.updateSearchBase();
+				search.recompute();
+				ctl.get('packages').setState('view');
+				ctl.updateAll();
+				break;
+			default:
+				ctl.get('packages').setLoaded(req.responseText.length);
+				ctl.updateView('packages');
+				break;
+		}
+	}
+	req.send(null)
+	this.get('packages').setState('loading');
+	this.updateView('packages');
+}
 Controller.prototype.want = function(tagName)
 {
-	search.want(tagName);
-	this.updateAll();
+	if (search.want(tagName))
+		this.updateAll();
+	else
+		this.reloadPackages();
 }
 Controller.prototype.unwant = function(tagName)
 {
-	search.unwant(tagName);
-	this.updateAll();
+	if (search.unwant(tagName))
+		this.updateAll();
+	else
+		this.reloadPackages();
 }
 Controller.prototype.ignore = function(tagName)
 {
-	search.ignore(tagName);
-	this.updateAll();
+	if (search.ignore(tagName))
+		this.updateAll();
+	else
+		this.reloadPackages();
 }
 Controller.prototype.reset = function(tagName)
 {
-	search.reset(tagName);
-	this.updateAll();
+	if (search.reset(tagName))
+		this.updateAll();
+	else
+		this.reloadPackages();
 }
 
 var ctl = new Controller();
@@ -360,17 +515,12 @@
 search.addSearchBase("<tmpl_var name='NAME'>");
 </tmpl_loop>
 
-<tmpl_loop name="UTAGS">
-search.unwanted.add("<tmpl_var name='NAME'>");
-</tmpl_loop>
-
-<tmpl_loop name="ITAGS">
-search.ignored.add("<tmpl_var name='NAME'>");
-</tmpl_loop>
+search.unwanted.add("role::aux:dummy");
+search.unwanted.add("role::content:data");
+search.unwanted.add("role::sw:devel-lib");
+search.unwanted.add("role::sw:shlib");
 
-<tmpl_loop name="TTAGS">
-search.top.add("<tmpl_var name='NAME'>");
-</tmpl_loop>
+search.recompute();
 
   //-->
   </script>

Modified: central-database/branches/alioth/webfrontend/widgets.js
==============================================================================
--- central-database/branches/alioth/webfrontend/widgets.js	(original)
+++ central-database/branches/alioth/webfrontend/widgets.js	Thu Nov 24 15:29:52 2005
@@ -1,10 +1,5 @@
 // Generic functions
 
-function extractFacet(tag)
-{
-	return tag.slice(0, tag.indexOf("::"));
-}
-  
 function Debug(name)
 {
 	this.name = name;
@@ -32,6 +27,7 @@
 function Controller()
 {
 	this.components = new Object();
+	this.signatures = new Object();
 }
 Controller.prototype.place = function(component, opts)
 {
@@ -39,13 +35,26 @@
 	document.write("<div id='"+component.name()+"' " + (opts ? opts : "") + ">\n");
 	document.write(component.render());
 	document.write("</div>\n");
+	this.signatures[component.name()] = component.contentSignature();
 }
 Controller.prototype.get = function(name)
 {
 	return this.components[name];
 }
+Controller.prototype.updateView = function(name)
+{
+	var comp = this.components[name];
+	var newSig = comp.contentSignature();
+	if (this.signatures[comp.name()] != newSig)
+	{
+		var node = document.getElementById(comp.name())
+		node.innerHTML = comp.render();
+		this.signatures[comp.name()] = newSig;
+	}
+
+}
 Controller.prototype.updateAll = function()
 {
-	for (i in this.components)
-		this.components[i].updateView();
+	for (var i in this.components)
+		this.updateView(i);
 }



More information about the Debtags-commits mailing list