[Rt-commit] r2636 - in rt/branches/PLATANO-EXPERIMENTAL: . html/NoAuth html/Prefs html/Widgets

jesse at bestpractical.com jesse at bestpractical.com
Sat Apr 16 02:41:42 EDT 2005


Author: jesse
Date: Sat Apr 16 02:41:41 2005
New Revision: 2636

Added:
   rt/branches/PLATANO-EXPERIMENTAL/html/Widgets/
   rt/branches/PLATANO-EXPERIMENTAL/html/Widgets/SelectionBox
Modified:
   rt/branches/PLATANO-EXPERIMENTAL/   (props changed)
   rt/branches/PLATANO-EXPERIMENTAL/html/NoAuth/list.js
   rt/branches/PLATANO-EXPERIMENTAL/html/Prefs/MyRT.html
Log:
 r12969 at hualien:  jesse | 2005-04-16 02:16:02 -0400
  r6494 at hualien:  jesse | 2005-03-06 17:46:01 -0500
   r6411 at hualien (orig r2293):  clkao | 2005-03-06 10:10:26 -0500
   Land SelectionBox Widget, which works for both js and cgi.
   Make the frontpage customization UI use SelectionBox.
  
 


Modified: rt/branches/PLATANO-EXPERIMENTAL/html/NoAuth/list.js
==============================================================================
--- rt/branches/PLATANO-EXPERIMENTAL/html/NoAuth/list.js	(original)
+++ rt/branches/PLATANO-EXPERIMENTAL/html/NoAuth/list.js	Sat Apr 16 02:41:41 2005
@@ -7,63 +7,76 @@
  sels : null,
  list : function (src, esrc, name) { this.init(src, esrc, name); },
  read : function () {
-  var i		= 0;
-  if(this.xml.readyState!=4) { setTimeout(this.name+".read()", 100); }
-  else if(this.xml.status!=200) alert("Document not available.");
-  else {
-   var doc	= this.xml.responseXML;
-   var nNode	= null;
-   if(doc.childNodes[0].nodeName=="parseerror") alert("Parse Error.");
-   doc		= doc.getElementsByTagName("list")[0];
-   for(i=0;i<doc.childNodes.length;i++) {
-    if(doc.childNodes[i].childNodes.length>0) {
-     nNode	= document.createElement("option");
-     nNode.appendChild(document.createTextNode(doc.childNodes[i].childNodes[0].nodeValue));
-     this.sels[0].appendChild(nNode);
-    }
-   }
-  }
+     var i		= 0;
+     if(this.xml.readyState!=4) { setTimeout(this.name+".read()", 100); }
+     else if(this.xml.status!=200) alert("Document not available.");
+     else {
+	 var doc	= this.xml.responseXML;
+	 var nNode	= null;
+	 if(doc.childNodes[0].nodeName=="parseerror") alert("Parse Error.");
+	 doc		= doc.getElementsByTagName("list")[0];
+	 for(i=0;i<doc.childNodes.length;i++) {
+	     if(doc.childNodes[i].childNodes.length>0) {
+		 nNode	= document.createElement("option");
+		 nNode.appendChild(document.createTextNode(doc.childNodes[i].childNodes[0].nodeValue));
+		 this.sels[0].appendChild(nNode);
+	     }
+	 }
+     }
  },
-
+     
  init : function (src,esrc,name) {
-  if(!src) return;
-  this.name		= name;
-  this.sels		= new Array();
-  var i			= 0;
-  for(i=0;i<src.childNodes.length;i++) {
-   if(src.childNodes[i].nodeName=="select" || src.childNodes[i].nodeName=="SELECT") {
-    this.sels.push(src.childNodes[i]);
-   } if((src.childNodes[i].nodeName=="input" || src.childNodes[i].nodeName=="INPUT")
-     && (src.childNodes[i].type=="button" || src.childNodes[i].type=="BUTTON")) {
-    if(src.childNodes[i].name=="add") src.childNodes[i].onclick = new Function(this.name+".add();");
-    if(src.childNodes[i].name=="remove") 
-     src.childNodes[i].onclick = new Function(this.name+".remove();");
-    if(src.childNodes[i].name=="moveup") 
-     src.childNodes[i].onclick = new Function(this.name+".moveup();");
-    if(src.childNodes[i].name=="movedown") 
-     src.childNodes[i].onclick = new Function(this.name+".movedown();");
-   } if((src.childNodes[i].nodeName=="input" || src.childNodes[i].nodeName=="INPUT")
-     && (src.childNodes[i].type=="submit" || src.childNodes[i].type=="SUBMIT")) {
-    src.childNodes[i].onclick = new Function(this.name+".selectAll();");
-   }
-  }
-  if (esrc) {
-  this.xml	= (window.navigator.appName!="Microsoft Internet Explorer"
-                   ?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"));
-  this.xml.open("GET", esrc);
-  this.xml.send("");
-  setTimeout(this.name+".read()", 100);
-  }
+     if(!src) return;
+     this.name		= name;
+     this.sels		= new Array();
+     var i			= 0;
+     for(i=0;i<src.childNodes.length;i++) {
+	 if(src.childNodes[i].nodeName=="select" || src.childNodes[i].nodeName=="SELECT") {
+	     this.sels.push(src.childNodes[i]);
+	 } 
+
+	 if((src.childNodes[i].nodeName=="input" || src.childNodes[i].nodeName=="INPUT")
+	    && (src.childNodes[i].name=="fromjs")) {
+	     src.childNodes[i].value = 1;
+	 }
+
+	 if((src.childNodes[i].nodeName=="input" || src.childNodes[i].nodeName=="INPUT")
+	    && (src.childNodes[i].type=="submit" || src.childNodes[i].type=="SUBMIT")) {
+
+	     if(src.childNodes[i].name != "submit") 
+		 src.childNodes[i].type = "button";
+
+	     if(src.childNodes[i].name=="add")
+		 src.childNodes[i].onclick = new Function(this.name+".add();");
+	     if(src.childNodes[i].name=="remove") 
+		 src.childNodes[i].onclick = new Function(this.name+".remove();");
+	     if(src.childNodes[i].name=="moveup") 
+		 src.childNodes[i].onclick = new Function(this.name+".moveup();");
+	     if(src.childNodes[i].name=="movedown") 
+		 src.childNodes[i].onclick = new Function(this.name+".movedown();");
+	     if(src.childNodes[i].type=="submit") {
+		 src.childNodes[i].onclick = new Function(this.name+".selectAll();");
+	     }
+
+	 } 
+     }
+     if (esrc) {
+	 this.xml	= (window.navigator.appName!="Microsoft Internet Explorer"
+			   ?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP"));
+	 this.xml.open("GET", esrc);
+	 this.xml.send("");
+	 setTimeout(this.name+".read()", 100);
+     }
  },
-
+     
  add : function() {
-  var i, j 	= 0;
-  var dNode	= null;
-  for(i=0;i<this.sels[0].length;i++) if(this.sels[0][i].selected) {
-   for(j=0;j<this.sels[1].length;j++) if(this.sels[1][j].value==this.sels[0][i].value) break;
-   if(j==this.sels[1].length) dNode	= this.sels[0][i].cloneNode(true), 
-    this.sels[1].appendChild(dNode);
-  }
+     var i, j 	= 0;
+     var dNode	= null;
+     for(i=0;i<this.sels[0].length;i++) if(this.sels[0][i].selected) {
+	 for(j=0;j<this.sels[1].length;j++) if(this.sels[1][j].value==this.sels[0][i].value) break;
+	 if(j==this.sels[1].length) dNode	= this.sels[0][i].cloneNode(true), 
+					this.sels[1].appendChild(dNode);
+     }
  },
 
  moveup : function() { this.move(-1); },

Modified: rt/branches/PLATANO-EXPERIMENTAL/html/Prefs/MyRT.html
==============================================================================
--- rt/branches/PLATANO-EXPERIMENTAL/html/Prefs/MyRT.html	(original)
+++ rt/branches/PLATANO-EXPERIMENTAL/html/Prefs/MyRT.html	Sat Apr 16 02:41:41 2005
@@ -49,48 +49,20 @@
     Title => $title
 &>
 
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/class.js"></script>
-<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/list.js"></script>
+<& /Widgets/SelectionBox:header &>
 
 <& /Elements/ListActions, actions => \@actions &>
 <a href="<% $ARGS{'referer'} %>"><&|/l&>Go back</&></a><br>
 
 % for my $pane (@panes) {
-<h2><% $pane %></h2>
-<FORM METHOD="POST" ACTION="MyRT.html" name="MyRT-<% $pane %>" id="MyRT-<% $pane %>">
-<input type="hidden" name="referer" value="<%$ARGS{'referer'}%>">
-List of available items:<br>
-<select name="PortletList" multiple >
-% for (@items) {
-<option value="<% $_->[0] %>"><% $_->[1] %></option>
+<& /Widgets/SelectionBox:show, self => $pane &>
 % }
-</select>
-<input name="add" type="button" value="->"/>
-<select name="PortletList-<%$pane%>" multiple>
-% for (@{$current_portlets->{$pane}}) {
-<option value="<% $_ %>"><% $item_map{$_} %></option>
-% }
-</select>
- <input name="moveup" type="button" value="^"/>
- <input name="movedown" type="button" value="v"/>
- <input name="remove" type="button" value="X"/>
- <input name="submit" type="submit" value="submit"/>
-%#<& /Elements/Submit, Caption => loc("Save"), Label => loc('Save'), Name => 'Save' &>
-
-</form>
-% }
-<script type="text/javascript">
-% my $i = 1;
-% for my $pane (@panes) {
-var list<%$i%>	= new list(document.getElementById("MyRT-<% $pane %>"), 0, "list<%$i%>");
-% ++$i;
-% }
-</script>
 <%INIT>
 my @actions;
-$ARGS{'referer'} ||= $ENV{'HTTP_REFERER'};
+
 my $title = loc("Customize").' '.loc("My RT");
 my $user = $session{'CurrentUser'}->UserObj;
+$ARGS{'referer'} ||= $ENV{'HTTP_REFERER'};
 
 unless (exists $session{'my_rt_portlets'}) {
     my ($d_portlets) = RT::System->new($session{'CurrentUser'})->Attributes->Named('My RT');
@@ -130,33 +102,28 @@
 }
 
 my %item_map = map {$_->[0] => $_->[1]} @items;
+my @panes;
+for my $pane ('main', 'right') {
+    push @panes,
+	$m->comp ('/Widgets/SelectionBox:new',
+		  Action => 'MyRT.html',
+		  Name => $pane,
+		  Available => \@items,
+		  OnSubmit =>
+		  sub { my $sel = shift;
+			$portlets->{$pane} =
+			    [map { m/(\w+)-(.*)$}/;
+				   { type => $1,
+				     name => $2,
+				 }} @{$sel->{Current}}];
+			$user->SetPreferences('My RT', $portlets);
+			push @actions, loc ('Preferences saved for [_1].', $pane);
+			delete $session{'my_rt_portlets'};
 
-my @panes = ('main', 'right');
-
-# build
-#if ($ARGS{'Save'}) {
-if ($ARGS{'submit'}) {
-    for my $pane (@panes) {
-	my $this = $ARGS{'PortletList-'.$pane};
-	$this = [$this] unless ref ($this);
-	next unless $ARGS{'PortletList-'.$pane};
-	$portlets->{$pane} =
-	    [map { m/(\w+)-(.*)$}/;
-		   # XXX: CHECK!
-		   { type => $1,
-		     name => $2,
-		 }} @$this];
-    }
-
-    $user->SetPreferences('My RT', $portlets);
-    push @actions, loc ('Preferences saved.');
-    delete $session{'my_rt_portlets'};
+		  },
+		  Selected => [map {join('-',@{$_}{qw/type name/})} @{$portlets->{$pane}}]);
 }
 
-my $current_portlets;
-for my $pane (@panes) {
-    $current_portlets->{$pane}
-	= [map {join('-',@{$_}{qw/type name/})} @{$portlets->{$pane}}];
-}
+$m->comp ('/Widgets/SelectionBox:process', %ARGS, self => $_) for @panes;
 
 </%INIT>

Added: rt/branches/PLATANO-EXPERIMENTAL/html/Widgets/SelectionBox
==============================================================================
--- (empty file)
+++ rt/branches/PLATANO-EXPERIMENTAL/html/Widgets/SelectionBox	Sat Apr 16 02:41:41 2005
@@ -0,0 +1,218 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%# 
+%# COPYRIGHT:
+%#  
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
+%#                                          <jesse at bestpractical.com>
+%# 
+%# (Except where explicitly superseded by other copyright notices)
+%# 
+%# 
+%# LICENSE:
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%# 
+%# 
+%# CONTRIBUTION SUBMISSION POLICY:
+%# 
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%# 
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%# 
+%# END BPS TAGGED BLOCK }}}
+
+%# The SelectionBox Widget
+%# 
+%# SYNOPSIS
+%#
+%# include javascript:
+%# <& /Widgets/SelectionBox:header &>
+%#
+%# <%init>:
+%# my $sel = $m->comp ('/Widgets/SelectionBox:new',
+%#		  Action => me.html',
+%#		  Name => 'my-selection',
+%#		  Available => \@items,
+%#                # you can do things with @{$sel->{Current}} in the 
+%#                # OnSubmit callback
+%#		  OnSubmit => sub { my $sel = shift; },
+%#		  Selected => \@selected);
+%#
+%# $m->comp ('/Widgets/SelectionBox:process', %ARGS, self => $sel)
+%#
+%# where @items is an arrayref, each element is [value, label],
+%# and selected is an arrayref of selected values from @items.
+%#
+%# and in html:
+%# <& /Widgets/SelectionBox:show, self => $sel &>
+%# 
+<%method header>
+<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/class.js"></script>
+<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/list.js"></script>
+</%method>
+
+<%method new>
+
+<%init>
+return \%ARGS;
+</%init>
+</%method>
+
+<%method process>
+<%init>
+unless ($ARGS{$self->{Name}.'-Submit'}) {
+    # init
+    $self->{Current} = $self->{Selected};
+    $self->{Selected} = [];
+    return;
+}
+
+$self->{Selected} = $ARGS{$self->{Name}.'-Selected'};
+$self->{Selected} = [$self->{Selected}] unless ref ($self->{Selected});
+
+if ($ARGS{fromjs}) {
+    $self->{Current} = $self->{Selected};
+}
+else {
+    my $current = $self->{Current} = $ARGS{$self->{Name}.'-Current'};
+    ++$self->{Modified};
+    if ($current && !ref ($current)) {
+	$current = [$current];
+    }
+
+    if ($ARGS{add}) {
+	my $choosed = $ARGS{$self->{Name}.'-Available'};
+	for my $add (ref($choosed) ? @$choosed : $choosed) {
+	    next if grep { $_ eq $add } @$current;
+	    push @$current, $add;
+	}
+    }
+
+    if ($ARGS{remove}) {
+	my $choosed = $ARGS{$self->{Name}.'-Selected'};
+	for my $del (ref($choosed) ? @$choosed : $choosed) {
+	    @$current = map { $_ eq $del ? () : $_ } @$current;
+	}
+    }
+
+    if ($ARGS{moveup} or $ARGS{movedown}) {
+	my $offset = $ARGS{moveup} ? 1 : 0;
+	my $choosed = $ARGS{$self->{Name}.'-Selected'};
+	$choosed = [$choosed] unless ref ($choosed);
+	my $canmove = 0; # not in the cornor
+	for my $i ($ARGS{moveup} ? 0..$#{$current} : reverse 0..$#{$current}) {
+	    if (grep {$_ eq $current->[$i]} @$choosed) {
+		if ($canmove) {
+		    splice (@$current, $i-$offset, 2,
+			    @{$current}[$i+1-$offset,$i-$offset]);
+		}
+	    }
+	    else {
+		++$canmove;
+	    }
+	}
+    }
+
+    $self->{Current} = $current;
+}
+
+# XXX: Verify Current are within $self->{Available} here
+
+if ($ARGS{submit}) {
+    $self->{OnSubmit}->($self);
+    delete $self->{Modified};
+}
+
+</%init>
+<%ARGS>
+$self => undef
+</%ARGS>
+
+</%method>
+
+<%method current>
+% for (@{$self->{Current}}) {
+<input type="hidden" name="<% $self->{Name} %>-Current" value="<%$_%>">
+% }
+<%INIT>
+</%INIT>
+<%ARGS>
+$self => undef
+</%ARGS>
+
+</%method>
+
+<%method show>
+<h2><% $name %></h2>
+<FORM METHOD="POST" ACTION="<%$self->{Action}%>" name="SelectionBox-<% $name %>" id="SelectionBox-<% $name %>">
+<input type="hidden" name="<% $self->{Name} %>-Submit" value="1">
+<& SelectionBox:current, self => $self &>
+<input type="hidden" name="referer" value="<%$ARGS{'referer'}%>">
+<input type="hidden" name="fromjs" value="0">
+Available:
+% if ($self->{Modified}) {
+<b>(Modified, Please save)</b>
+% }
+<br>
+<select name="<%$name%>-Available" multiple >
+% for (@{$self->{Available}}) {
+<option value="<% $_->[0] %>"><% $_->[1] %></option>
+% }
+</select>
+<input name="add" type="submit" value="->"/>
+<select name="<%$name%>-Selected" multiple>
+% for (@{$self->{Current}}) {
+<option value="<% $_ %>"
+% if (exists $selected{$_}) {
+SELECTED
+% }
+><% $item_map{$_} %></option>
+% }
+</select>
+ <input name="moveup" type="submit" value="^"/>
+ <input name="movedown" type="submit" value="v"/>
+ <input name="remove" type="submit" value="X"/>
+ <input name="submit" type="submit" value="Save"/>
+
+%# the save button does not work because it's not direct child of the form element
+%#<& /Elements/Submit, Caption => loc("Save"), Label => loc('Save'), Name => $name.'-Save' &>
+
+</form>
+
+<script type="text/javascript">
+var list_<%$name%> = new list(document.getElementById("SelectionBox-<% $name %>"), 0, "list_<%$name%>");
+</script>
+<%ARGS>
+$self => undef
+</%ARGS>
+<%INIT>
+my $name = $self->{Name};
+my %selected = map {$_ => 1} @{$self->{Selected}};
+my %item_map = map {$_->[0] => $_->[1]} @{$self->{Available}};
+$ARGS{'referer'} ||= $ENV{'HTTP_REFERER'};
+</%INIT>
+
+</%method>


More information about the Rt-commit mailing list