[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