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

Enrico Zini enrico at costa.debian.org
Wed Nov 23 15:22:53 UTC 2005


Author: enrico
Date: Wed Nov 23 15:22:52 2005
New Revision: 1524

Modified:
   central-database/branches/alioth/webfrontend/edit.cgi
   central-database/branches/alioth/webfrontend/edittemplate.html
   central-database/branches/alioth/webfrontend/maint
Log:
Refactoring:
 - Download tag data from a static javascript file (that can be easily cached
   and shared among scripts)
 - Refactoed Javascript with a more OOP approach


Modified: central-database/branches/alioth/webfrontend/edit.cgi
==============================================================================
--- central-database/branches/alioth/webfrontend/edit.cgi	(original)
+++ central-database/branches/alioth/webfrontend/edit.cgi	Wed Nov 23 15:22:52 2005
@@ -76,7 +76,7 @@
 my $p;
 my %hidden_facets;
 my $bayesian = 1;
-my %has_tag;
+my @tags;
 my $nav_tags;
 
 #($p) = Engine::package('debtags');
@@ -120,7 +120,7 @@
 			}
 		}
 	}
-	%has_tag = map { $_->name => 1 } $p->tags;
+	@tags = map { $_->name } $p->tags;
 	$bayesian = 0 if not $p->hasBayesian();
 }
 
@@ -128,101 +128,39 @@
 ## Prepare the data for the template
 ##
 
-my @facets;
 
+#for my $f (Engine::allFacets())
+#{
+#	my @tags;
+#	my $maxprob = $bayesian ? -100 : 0;
+#	for my $t ($f->tags())
+#	{
+#		if ($bayesian)
+#		{
+#			my $prob = ($p->tagLikelihood($t) or 0);
+#			$maxprob = $prob if $prob > $maxprob;
+#
+#			$data{PROB} = $prob;
+#			$data{PPROB} = $prob if $prob > 0;
+#			$data{NPROB} = $prob if $prob < 0;
+#		}
+#		push @tags, \%data;
+#	}
+#	push @facets, {
+#		TAGS => [ sort tagsort @tags ],
+#		PROB => $maxprob,
+#	};
+#	$facets[$#facets]{PPROB} = $maxprob if $maxprob > 0;
+#}
+## Sort according to likelyhood
+#sub facetsort ($$)
+#{
+#	return $_[1]->{PROB} <=> $_[0]->{PROB}
+#		if $_[1]->{PROB} != $_[0]->{PROB};
+#	return $_[0]->{SDESC} cmp $_[1]->{SDESC};
+#}
+#@facets = sort facetsort @facets;
 
-sub linkself (@)
-{
-	return 'edit.cgi' if not defined $p;
-	return 'edit.cgi?'.join('&',
-					'tags='.$nav_tags,
-					'pkg='.uri_escape($p->name),
-					'b='.($bayesian ? 'true' : 'false'),
-					'hf='.join(',', map { uri_escape($_) } keys %hidden_facets),
-					@_);
-}
-sub linkself_nohf (@)
-{
-	return 'edit.cgi' if not defined $p;
-	return 'edit.cgi?'.join('&',
-					'tags='.$nav_tags,
-					'pkg='.uri_escape($p->name),
-					'b='.($bayesian ? 'true' : 'false'),
-					@_);
-}
-sub linkself_nob (@)
-{
-	return 'edit.cgi' if not defined $p;
-	return 'edit.cgi?'.join('&',
-					'tags='.$nav_tags,
-					'pkg='.uri_escape($p->name),
-					'hf='.join(',', map { uri_escape($_) } keys %hidden_facets),
-					@_);
-}
-
-for my $f (Engine::allFacets())
-{
-	my @hastags;
-	my @tags;
-	my $maxprob = $bayesian ? -100 : 0;
-	for my $t ($f->tags())
-	{
-		my %data = (
-			NAME => $t->name,
-			SDESC => uri_escape($t->sdesc),
-			LDESC => uri_escape(format_ldesc($t->ldesc)),
-		);
-		if ($bayesian)
-		{
-			my $prob = ($p->tagLikelihood($t) or 0);
-			$maxprob = $prob if $prob > $maxprob;
-
-			$data{PROB} = $prob;
-			$data{PPROB} = $prob if $prob > 0;
-			$data{NPROB} = $prob if $prob < 0;
-		} else {
-			$data{PROB} = 0;
-		}
-
-		if ($has_tag{$t->name})
-		{
-			$data{REMURL} = linkself('del='.uri_escape($t->name));
-			push @hastags, \%data;
-		} else {
-			$data{ADDURL} = linkself('add='.uri_escape($t->name));
-			push @tags, \%data;
-		}
-	}
-	sub tagsort ($$)
-	{
-		return $_[1]->{PROB} <=> $_[0]->{PROB}
-		    if $_[1]->{PROB} != $_[0]->{PROB};
-		return $_[0]->{SDESC} cmp $_[1]->{SDESC};
-			
-	}
-	#msg "%s %s\n", $f->name, $hidden_facets{$f->name} ? "hidden" : "not hidden";
-	push @facets, {
-		NAME => $f->name,
-		SDESC => uri_escape($f->sdesc),
-		LDESC => uri_escape(format_ldesc($f->ldesc)),
-		HASTAGS => [ sort tagsort @hastags ],
-		TAGS => [ sort tagsort @tags ],
-		HIDEURL => linkself('fhide='.uri_escape($f->name)),
-		DELURL => linkself('fdel='.uri_escape($f->name)),
-		HIDDEN => $hidden_facets{$f->name},
-		PROB => $maxprob,
-	};
-	$facets[$#facets]{PPROB} = $maxprob if $maxprob > 0;
-}
-
-# Sort according to likelyhood
-sub facetsort ($$)
-{
-	return $_[1]->{PROB} <=> $_[0]->{PROB}
-		if $_[1]->{PROB} != $_[0]->{PROB};
-	return $_[0]->{SDESC} cmp $_[1]->{SDESC};
-}
- at facets = sort facetsort @facets;
 
 # Build HTML::Template data structures
 #if (@pkg_tags) {
@@ -235,6 +173,7 @@
 #	}
 #}
 
+
 ## Add add links.
 #open(TAGLIST,"<taglist.txt");
 #my $count=0;
@@ -274,8 +213,7 @@
 #$template->param(TAGS => \@ht_tags);
 #$template->param(ADDTAGS => \@ht_alltags);
 
-$template->param(FACETS => \@facets);
-$template->param(UNHIDE => linkself_nohf());
+$template->param(TAGS => [ map { { NAME => $_ } } @tags ]);
 if ($p and $p->hasBayesian)
 {
 	$template->param(SWITCHBAYES => linkself_nob("b=".($bayesian ? "false" : "true")));
@@ -283,7 +221,6 @@
 }
 $template->param(NAVIGATE => "index.cgi?tags=$nav_tags");
 $template->param(NAV_TAGS => $nav_tags);
-$template->param(COUNT_HIDDEN => scalar keys %hidden_facets);
 if (defined $p)
 {
 	$template->param(PKG_NAME => $p->name);

Modified: central-database/branches/alioth/webfrontend/edittemplate.html
==============================================================================
--- central-database/branches/alioth/webfrontend/edittemplate.html	(original)
+++ central-database/branches/alioth/webfrontend/edittemplate.html	Wed Nov 23 15:22:52 2005
@@ -11,88 +11,96 @@
   <link rev="made" href="mailto:erich at debian.org">
   <link rev="made" href="mailto:enrico at debian.org">
   <link href="main.css" rel="stylesheet" type="text/css">
+  <script src="vocabulary.js"></script>
   <script type="text/javascript">
   <!--
-  var facets = new Object();
-  var facetsSorted = new Array();
-  <tmpl_loop name="FACETS">
-	  var f = new Object;
-	  facets["<tmpl_var name='NAME'>"] = f;
-	  f.name = "<tmpl_var name='NAME'>";
-	  f.sdesc = unescape("<tmpl_var name='SDESC'>");
-	  f.ldesc = unescape("<tmpl_var name='LDESC'>");
-	  f.tagsSorted = new Array();
-	  f.tags = new Object();
-	  f.open = true;
-
-	  <tmpl_loop name="HASTAGS">
-		  var t = new Object;
-		  f.tags["<tmpl_var name='NAME'>"] = t;
-		  t.name = "<tmpl_var name='NAME'>";
-		  t.sdesc = unescape("<tmpl_var name='SDESC'>");
-		  t.ldesc = unescape("<tmpl_var name='LDESC'>");
-		  t.origSelected = true;
-		  t.selected = true;
-		  f.tagsSorted.push(t);
-	  </tmpl_loop>
-	  <tmpl_loop name="TAGS">
-		  var t = new Object;
-		  f.tags["<tmpl_var name='NAME'>"] = t;
-		  t.name = "<tmpl_var name='NAME'>";
-		  t.sdesc = unescape("<tmpl_var name='SDESC'>");
-		  t.ldesc = unescape("<tmpl_var name='LDESC'>");
-		  t.origSelected = false;
-		  t.selected = false;
-		  f.tagsSorted.push(t);
-	  </tmpl_loop>
-	  facetsSorted.push(f);
-  </tmpl_loop>
 
-  function getFacet(tag)
+  // Document
+
+  function Tags ()
   {
-  	return tag.slice(0, tag.indexOf("::"));
+	this.tags = new Object;
   }
-  
-  function mkPatch()
-  {
-  	var res = new Array();
-  	for (i = 0; i < facetsSorted.length; i++)
+  Tags.prototype.get = function(name) {
+  	if (!this.tags[name])
 	{
-		var f = facetsSorted[i];
-		for (j = 0; j < facets[f.name].tagsSorted.length; j++)
-		{
-			var t = facets[f.name].tagsSorted[j];
-			if (t.origSelected == true && t.selected == false)
-				res.push("-"+t.name);
-			else if (t.origSelected == false && t.selected == true)
-				res.push("+"+t.name);
-		}
+		this.tags[name] = new Object;
+		this.tags[name].orig = false;
+		this.tags[name].cur = false;
 	}
-	return res.join(', ');
+	return this.tags[name];
   }
-  
-  function hasChanges()
-  {
-  	for (i = 0; i < facetsSorted.length; i++)
-	{
-		var f = facetsSorted[i];
-		for (j = 0; j < facets[f.name].tagsSorted.length; j++)
+  Tags.prototype.add = function(name) {
+  	this.get(name).cur = true;
+  }
+  Tags.prototype.del = function(name) {
+  	this.get(name).cur = false;
+  }
+  Tags.prototype.has = function(name) {
+  	return this.get(name).cur;
+  }
+  Tags.prototype.count = function() {
+	var res = 0;
+  	for (t in this.tags)
+		if (this.tags[t].cur)
+			res++;
+	return res;
+  }
+  Tags.prototype.commit = function() {
+  	for (t in this.tags)
+		this.tags[t].orig = this.tags[t].cur
+  }
+  Tags.prototype.revert = function() {
+  	for (t in this.tags)
+		this.tags[t].cur = this.tags[t].orig
+  }
+  Tags.prototype.mkpatch = function() {
+  	var res = new Array();
+  	for (t in this.tags)
+		if (this.tags[t].orig && !this.tags[t].cur)
 		{
-			var t = facets[f.name].tagsSorted[j];
-			if (t.origSelected != t.selected)
-				return true;
+			res.push("-"+t.name);
+		} else if (!this.tags[t].orig && this.tags[t].cur) {
+			res.push("+"+t.name);
 		}
-	}
+	return res.join(', ');
+  }
+  Tags.prototype.hasChanges = function() {
+  	for (t in this.tags)
+		if (this.tags[t].orig != this.tags[t].cur)
+			return true;
 	return false;
   }
 
-  function mkOpenFacetBox(facet)
+  var tags = new Tags();
+  <tmpl_loop name="TAGS">
+  tags.add("<tmpl_var name='NAME'>");
+  </tmpl_loop>
+  tags.commit();
+
+  function extractFacet(tag)
+  {
+  	return tag.slice(0, tag.indexOf("::"));
+  }
+  
+  // View
+
+  function FacetBox(facetName)
+  {
+	this.facet = voc.get(facetName);
+	this.open = true;
+  }
+  FacetBox.prototype.name = function()
+  {
+	return "editbox-" + this.facet.name;
+  }
+  FacetBox.prototype.renderOpen = function()
   {
 	var res = "";
-	var f = facets[facet];
+	var f = this.facet;
 	res += "\t<div class='facetbuttons'>\n";
-	res += "\t\t<span class='button' onclick='hideFacet(\""+f.name+"\")'>[done with this]</span><br />\n";
-	res += "\t\t<span class='button' onClick='remFacet(\""+f.name+"\")'>[does not apply]</span>\n";
+	res += "\t\t<span class='button' onclick='ctl.get(\""+this.name()+"\").close()'>[done with this]</span><br />\n";
+	res += "\t\t<span class='button' onClick='ctl.remFacet(\""+f.name+"\")'>[does not apply]</span>\n";
 	res += "\t</div>\n";
 	res += "\t<div class='intro'>\n";
 	res += "\t\t<p>\n";
@@ -102,161 +110,169 @@
 	res += "\t\t<p>"+f.ldesc+"</p>\n";
 	res += "\t</div>\n";
 	res += "\t<ul>\n";
-	for (j = 0; j < facets[f.name].tagsSorted.length; j++)
+	// First all selected tags
+	for (i in f.tags)
 	{
-		var t = facets[f.name].tagsSorted[j];
-		if (t.selected == true)
+		var t = f.tags[i]
+		if (tags.has(t.name))
 		{
 			res += "\t<li>\n";
 			res += "\t\t<b>"+t.sdesc+"</b>\n";
 			// res += "\t\t<tmpl_if name="NPROB">(<tmpl_var name="NPROB">%)</tmpl_if>";
-			res += "\t\t<span class='button' onClick='remTag(\""+t.name+"\")'>[remove]</a>\n";
+			res += "\t\t<span class='button' onClick='ctl.remTag(\""+t.name+"\")'>[remove]</a>\n";
 			res += "\t</li>\n";
 		}
 	}
-	for (j = 0; j < facets[f.name].tagsSorted.length; j++)
+	// Then the others
+	for (i in f.tags)
 	{
-		var t = facets[f.name].tagsSorted[j];
-		if (t.selected == false)
+		var t = f.tags[i]
+		if (!tags.has(t.name))
 		{
 			res += "\t<li>\n";
 			res += "\t\t"+t.sdesc+"\n";
 			// res += "\t\t<tmpl_if name="NPROB">(<tmpl_var name="NPROB">%)</tmpl_if>";
-			res += "\t\t<span class='button' onClick='addTag(\""+t.name+"\")'>[add]</a>\n";
+			res += "\t\t<span class='button' onClick='ctl.addTag(\""+t.name+"\")'>[add]</a>\n";
 			res += "\t</li>\n";
 		}
 	}
 	res += "\t</ul>\n";
 	return res;
   }
-  function mkClosedFacetBox(facet)
+  FacetBox.prototype.renderClosed = function()
+  {
+	var f = this.facet;
+	return "<span class='button' onclick='ctl.get(\""+this.name()+"\").reopen()'>[expand "+f.name+": "+f.sdesc+"]</span>";
+  }
+  FacetBox.prototype.render = function()
+  {
+	if (this.open)
+		return this.renderOpen();
+	else
+		return this.renderClosed();
+  }
+  FacetBox.prototype.updateView = function()
   {
-	var f = facets[facet];
-	return "<span class='button' onclick='showFacet(\""+f.name+"\")'>[expand "+f.name+": "+f.sdesc+"]</span>";
+	node = document.getElementById(this.name())
+	node.innerHTML = this.render();
   }
-  function mkCurTags()
+  FacetBox.prototype.reopen = function()
+  {
+	this.open = true;
+	this.updateView();
+  }
+  FacetBox.prototype.close = function()
+  {
+	this.open = false;
+	this.updateView();
+  }
+
+  function CurTags()
+  {
+  }
+  CurTags.prototype.name = function()
+  {
+	return "curtags";
+  }
+  CurTags.prototype.render = function()
   {
   	var res = "";
-	var found = 0;
-  	for (i = 0; i < facetsSorted.length; i++)
+	res += "  <p><b>Currently attached tags:</b>\n";
+        res += "  <ul id='curtags-list'>\n";
+	if (tags.count() > 0)
 	{
-		var f = facetsSorted[i];
-		for (j = 0; j < facets[f.name].tagsSorted.length; j++)
-		{
-			var t = facets[f.name].tagsSorted[j];
-			if (t.selected == true)
+		for (f in voc.facets)
+			for (i in voc.facets[f].tags)
 			{
-				res += "\t<li>"+t.sdesc+" <span class='button' onClick='remTag(\""+t.name+"\")'>[remove]</a></li>\n";
-				++found;
+				var t = voc.facets[f].tags[i];
+				if (tags.has(t.name))
+					res += "    <li>"+t.sdesc+" <span class='button' onClick='ctl.remTag(\""+t.name+"\")'>[remove]</a></li>\n";
 			}
-		}
+	} else {
+		res += "    <li>(no tags are currently attached to this package)</li>\n";
 	}
-	if (found == 0)
-		res += "\t<li>(no tags are currently attached to this package)</li>\n";
-	return res;
-  }
-  function mkCurTagsButtons()
-  {
-  	var res = "";
-	if (hasChanges())
+    	res += "  </ul>\n";
+	res += "  </p>\n";
+	res += "  <div id='curtags-buttons'>\n";
+	if (tags.hasChanges())
 	{
-		res += "<span class='button' onClick='commit()'>[submit]</span>\n";
-		res += "<span class='button' onClick='undoAll()'>[undo all changes]</span>\n";
+		res += "    <span class='button' onClick='ctl.commitChanges()'>[submit]</span>\n";
+		res += "    <span class='button' onClick='ctl.revertChanges()'>[undo all changes]</span>\n";
 	}
+	res += "  </div>\n";
+
+//	node = document.getElementById("curpatch")
+//	var patch = mkPatch();
+//	if (patch.length > 0)
+//		node.innerHTML = "Changes: " + mkPatch();
+//	else
+//		node.innerHTML = "";
+
 	return res;
   }
-  function updateCurTags()
+  CurTags.prototype.updateView = function()
   {
-	node = document.getElementById("curtags-list")
-	node.innerHTML = mkCurTags();
-
-	node = document.getElementById("curpatch")
-	var patch = mkPatch();
-	if (patch.length > 0)
-		node.innerHTML = "Changes: " + mkPatch();
-	else
-		node.innerHTML = "";
-
-	node = document.getElementById("curtags-buttons")
-	node.innerHTML = mkCurTagsButtons();
+	node = document.getElementById(this.name())
+	node.innerHTML = this.render();
   }
 
-  function hideFacet(facet)
+  function Controller()
   {
-	node = document.getElementById("editfacet-"+facet)
-	node.innerHTML = mkClosedFacetBox(facet);
-	facets[facet].open = false;
+	this.components = new Object();
   }
-  function showFacet(facet)
+  Controller.prototype.place = function(component, opts)
   {
-	node = document.getElementById("editfacet-"+facet)
-	node.innerHTML = mkOpenFacetBox(facet);
-	facets[facet].open = true;
+	this.components[component.name()] = component;
+  	document.write("<div id='"+component.name()+"' " + (opts ? opts : "") + ">\n");
+        document.write(component.render());
+    	document.write("</div>\n");
   }
-  function updateFacet(facet)
+  Controller.prototype.get = function(name)
   {
-	node = document.getElementById("editfacet-"+facet)
-	if (facets[facet].open)
-		node.innerHTML = mkOpenFacetBox(facet);
-	else
-		node.innerHTML = mkClosedFacetBox(facet);
+  	return this.components[name];
   }
-
-  function addTag(tag)
+  Controller.prototype.updateAll = function()
   {
-  	facet = getFacet(tag);
-	facets[facet].tags[tag].selected = true;
-	updateFacet(facet);
-	updateCurTags();
+  	for (i in this.components)
+		this.components[i].updateView();
   }
-  
-  function remTag(tag)
+  Controller.prototype.addTag = function(tagName)
   {
-  	facet = getFacet(tag);
-	facets[facet].tags[tag].selected = false;
-	updateFacet(facet);
-	updateCurTags();
+	tags.add(tagName);
+	this.get("editbox-"+extractFacet(tagName)).updateView();
+	this.get("curtags").updateView();
   }
-
-  function remFacet(facet)
-  {
-	var f = facets[facet];
-	for (j = 0; j < f.tagsSorted.length; j++)
-	{
-	        var t = facets[f.name].tagsSorted[j];
-		t.selected = false;
-	}
-	hideFacet(facet);
-	updateCurTags();
-  }
-
-  function updateAll()
+  Controller.prototype.remTag = function(tagName)
   {
-  	updateCurTags();
-  	for (i = 0; i < facetsSorted.length; i++)
-		updateFacet(facetsSorted[i].name);
+	tags.del(tagName);
+	this.get("editbox-"+extractFacet(tagName)).updateView();
+	this.get("curtags").updateView();
   }
-
-  function undoAll()
+  Controller.prototype.remFacet = function(facetName)
   {
-  	for (i = 0; i < facetsSorted.length; i++)
+	var f = voc.get(facetName);
+	for (i in f.tags)
 	{
-		var f = facetsSorted[i];
-		for (j = 0; j < facets[f.name].tagsSorted.length; j++)
-		{
-			var t = facets[f.name].tagsSorted[j];
-			t.selected = t.origSelected;
-		}
+		var t = f.tags[i]
+		if (tags.has(t.name))
+			tags.del(t.name);
 	}
-	updateAll();
+	this.get("editbox-"+facetName).close();
+	this.get("curtags").updateView();
   }
-
-  function commit()
+  Controller.prototype.revertChanges = function()
   {
-	document.patch.patch.value = mkPatch();
+	tags.revert();
+	this.updateAll();
+  }
+  Controller.prototype.commitChanges = function()
+  {
+	document.patch.patch.value = tags.mkPatch();
 	document.patch.submit();
   }
 
+  var ctl = new Controller();
+
   //-->
   </script>
 </head>
@@ -292,9 +308,6 @@
     <a href="<tmpl_var name='NAVIGATE'>">Back to browser</a>
     <a href="http://packages.debian.org/<tmpl_var name='PKG_NAME'>">Debian page</a>
     <a href="http://packages.qa.debian.org/<tmpl_var name='PKG_NAME'>">Debian QA page</a>
-    <tmpl_if name="COUNT_HIDDEN">
-      <a href="<tmpl_var name='UNHIDE'>">[unhide <tmpl_var name="COUNT_HIDDEN"> facets]</a>
-    </tmpl_if>
     <tmpl_if name="SWITCHBAYES">
       <a href="<tmpl_var name='SWITCHBAYES'>">[<tmpl_var name='SWITCHBAYESTXT'>]</a>
     </tmpl_if>
@@ -302,36 +315,23 @@
     </div>
   </div>
 
-  <div id="curtags">
-    <p><b>Currently attached tags:</b>
-    <ul id="curtags-list">
-      <script type="text/javascript">
-        document.write(mkCurTags());
-      </script>
-    </ul>
-    </p>
-    <form name="patch" id="patchForm" method="get">
-    <input type="hidden" name="pkg" value="<tmpl_var name='PKG_NAME'>">
-    <input type="hidden" name="navtags" value="<tmpl_var name='NAV_TAGS'>">
-    <input type="hidden" name="patch" value="">
-    <div id="curtags-buttons">
-      <script type="text/javascript">
-        document.write(mkCurTagsButtons());
-      </script>
-    </div>
-    </form>
-  </div>
+  <script type="text/javascript">
+    ctl.place(new CurTags());
+  </script>
+
+  <form name="patch" id="patchForm" method="get">
+  <input type="hidden" name="pkg" value="<tmpl_var name='PKG_NAME'>">
+  <input type="hidden" name="navtags" value="<tmpl_var name='NAV_TAGS'>">
+  <input type="hidden" name="patch" value="">
+  </form>
 
   <div style="clear: both"></div>
 
   <div id="editfacets">
   <script type="text/javascript">
-  	for (i = 0; i < facetsSorted.length; i++)
+  	for (i in voc.facets)
 	{
-		var name = facetsSorted[i].name;
-		document.write("<div class='editfacet' id='editfacet-"+name+"'>\n");
-		document.write(mkOpenFacetBox(name));
-		document.write("</div>\n");
+		ctl.place(new FacetBox(voc.facets[i].name), "class='editfacet'");
 	}
   </script>
   </div>

Modified: central-database/branches/alioth/webfrontend/maint
==============================================================================
--- central-database/branches/alioth/webfrontend/maint	(original)
+++ central-database/branches/alioth/webfrontend/maint	Wed Nov 23 15:22:52 2005
@@ -188,7 +188,6 @@
 
 function Facet(name, sdesc, ldesc)
 {
-	this = new Object;
 	this.name = name;
 	this.sdesc = sdesc;
 	this.ldesc = ldesc;
@@ -201,7 +200,6 @@
 
 function Tag(name, sdesc, ldesc)
 {
-	this = new Object;
 	this.name = name;
 	this.sdesc = sdesc;
 	this.ldesc = ldesc;
@@ -209,13 +207,15 @@
 
 function Vocabulary()
 {
-	this = new Object;
 	this.facets = new Array();
 }
 Vocabulary.prototype.add = function(facet) {
 	this.facets.push(facet);
 	this[facet.name] = facet;
 }
+Vocabulary.prototype.get = function(name) {
+	return this[name];
+}
 
 var voc = new Vocabulary();
 



More information about the Debtags-commits mailing list