Moving items between listboxes in ASP.net/PHP example
Ever wanted to move items between two listboxes in ASP.net
(or PHP for that matter)?
Someone wanted the exact same thing on
codeproject.com a while ago but I didn't give much thought
to it, until someone at work asked me how to do it - since he wasn't able to find
a viable solution on the internet.
The solution I scripted wasn't as simple as I thought, nor would have liked it to
be, my feeling was that one would be able to alter the two listboxes easily using
javascript and simply "harvest" the changes (from the Request variables) when its
submitted to the server.
The reality however is that only items selected(or highlighted) in the listboxes,
will be returned to the server, not the state of the listboxes - so we need to somehow
send the state of the listboxes along with the page request.
What I did was, I wrote a javascript script, that serialized the contents of the
listboxes as xml to a hiddenfield on the page - whenever you submit the form to
the server, a xml string containing the state of the listboxes get sent along -
which one can easily process server side (which I will show you just in a while).
You can download the full working source code
here, contains sources for ASP.net(C#
& VB.NET) and PHP source code.
function move(fromID, toID, containerID)
{
var from = document.getElementById(fromID);
var to = document.getElementById(toID);
for (var i = 0; i < from.options.length; i++)
{
if (from.options[i].selected)
{
to.options.add(new Option(from.options[i].text,from.options[i].value))
from.remove(i--);
}
}
var container = document.getElementById(containerID);
container.value = escape("<listboxes>" + serialize(from) + serialize(to) + "</listboxes>");
}
function serialize(dropdown)
{
var value = '<' + dropdown.id + '>';
for (var i = 0; i < dropdown.options.length; i++)
{
value+= '<option><key><![CDATA[' + dropdown.options[i].text + ']]></key><value><![CDATA[' + dropdown.options[i].value + ']]></value></option>';
}
value+='</' + dropdown.id + '>';
return value
}
function unselect(listbox)
{
document.getElementById(listbox).selectedIndex=-1;
}
Tying it all together (javascript with some .net code), you can easily
write yourself an usercontrol, like I did in my example, or create a composite
control.
The .net code below is pretty straighforward, you'll noticed two publicly exposed
ListBox properties (lstFrom, lstTo), giving us easy access to the listboxes.
If you really need to, you can easily add third, forth listboxes (with
slight changes to the javascript code)
The PHP code is quite a bit more involved, I had to create a few classes that give
similiar control of what you would expect from an ASP.NET server side control. There
is a lot easier ways to do this, but I believe this is a fairly manageable approach.
C#
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
public partial class ListPicker : System.Web.UI.UserControl
{
private XmlDocument _xmlDocument = new XmlDocument();
public ListBox fromListBox
{
get
{
return lstFrom;
}
}
public ListBox toListBox
{
get
{
return lstTo;
}
}
private void PopulateListBox(ListBox listBox)
{
listBox.Items.Clear();
XmlNodeList nodes = _xmlDocument.SelectNodes("listboxes/" + listBox.ClientID + "/option");
foreach (XmlNode node in nodes)
{
listBox.Items.Add(new ListItem(node["key"].InnerText, node["value"].InnerText));
}
}
private void PopulateListBoxes()
{
_xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdowns.Value));
PopulateListBox(lstFrom);
PopulateListBox(lstTo);
}
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptInclude("listboxjs", Page.ResolveClientUrl("~/js/listbox.js"));
if (!IsPostBack)
{
String movejs = "move('{0}','{1}','{2}')";
String unselectjs = "unselect('{0}')";
lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstTo.ClientID);
lstTo.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
btnTo.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstTo.ClientID, hdnDropdowns.ClientID);
btnFrom.Attributes["onclick"] = String.Format(movejs, lstTo.ClientID, lstFrom.ClientID, hdnDropdowns.ClientID);
}
else
{
if (!(String.IsNullOrEmpty(hdnDropdowns.Value)))
{
PopulateListBoxes();
}
}
}
}
VB.net
Imports System.Xml
Partial Class ListPicker
Inherits System.Web.UI.UserControl
Private _xmlDocument As New XmlDocument()
Public ReadOnly Property fromListBox() As ListBox
Get
Return lstFrom
End Get
End Property
Public ReadOnly Property toListBox() As ListBox
Get
Return lstTo
End Get
End Property
Private Sub PopulateListBox(ByVal lstBox As ListBox)
lstBox.Items.Clear()
Dim nodes As XmlNodeList = _xmlDocument.SelectNodes("listboxes/" + lstBox.ClientID + "/option")
For Each node As XmlNode In nodes
lstBox.Items.Add(New ListItem(node.Item("key").InnerText, node.Item("value").InnerText))
Next
End Sub
Private Sub PopulateListBoxes()
_xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdowns.Value))
PopulateListBox(lstFrom)
PopulateListBox(lstTo)
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.ClientScript.RegisterClientScriptInclude("listboxjs", Page.ResolveClientUrl("~/js/listbox.js"))
If Not IsPostBack Then
Dim movejs As String = "move('{0}','{1}','{2}')"
Dim unselectjs As String = "unselect('{0}')"
lstFrom.Attributes("onclick") = String.Format(unselectjs, lstTo.ClientID)
lstTo.Attributes("onclick") = String.Format(unselectjs, lstFrom.ClientID)
btnTo.Attributes("onclick") = String.Format(movejs, lstFrom.ClientID, lstTo.ClientID, hdnDropdowns.ClientID)
btnFrom.Attributes("onclick") = String.Format(movejs, lstTo.ClientID, lstFrom.ClientID, hdnDropdowns.ClientID)
Else
If Not String.IsNullOrEmpty(hdnDropdowns.Value) Then
PopulateListBoxes()
End If
End If
End Sub
End Class
PHP
<?php
require_once("controls.php");
require_once("listbox.php");
class listpicker extends controls
{
var $lstFrom;
var $lstTo;
var $deserializable;
function listpicker($id)
{
$this->attributes['id'] = $id;
$this->lstFrom = new listbox($id.'_lstFrom');
$this->lstFrom->attributes['style'] = 'width:200px';
$this->lstFrom->attributes['onclick'] = "unselect('".$id."_lstTo')";
$this->lstTo = new listbox($id.'_lstTo');
$this->lstTo->attributes['style'] = 'width:200px';
$this->lstTo->attributes['onclick'] = "unselect('".$id."_lstFrom')";
if ($_REQUEST[$id.'$hdnDropdowns'])
{
$this->deserializable = true;
$this->xml(urldecode($_REQUEST[$id.'$hdnDropdowns']));
}
}
function render()
{
$id = $this->attributes['id'];
$html='<table>
<tr>
<td>'
.$this->lstFrom->render().
'</td>
<td>
<input id="btnTo" type="button" value=">>" onclick="move(\''.$id.'_lstFrom\',\''.$id.'_lstTo\',\''.$id.'_hdnDropdowns\')" />
<br />
<input id="btnFrom" type="button" value="<<" onclick="move(\''.$id.'_lstTo\',\''.$id.'_lstFrom\',\''.$id.'_hdnDropdowns\')" />
</td>
<td>'
.$this->lstTo->render().
'</td>
</tr>
</table>
<input type="hidden" ID="'.$id.'_hdnDropdowns" name="'.$id.'$hdnDropdowns" />';
return $html;
}
function xml($text)
{
$id = $this->attributes['id'];
$parser = xml_parser_create();
xml_parse_into_struct($parser, $text, $vals);
xml_parser_free($parser);
$tag = "";
for($i = 0; $i < count($vals); $i++)
{
switch($vals[$i]['tag'])
{
case strtoupper($id.'_lstFrom') : $tag = "lstFrom"; break;
case strtoupper($id.'_lstTo') : $tag = "lstTo"; break;
}
if (($tag) && ($vals[$i]['tag'] == "KEY"))
{
$this->{$tag}->addItem($vals[$i]['value'], $vals[$i+1]['value']);
}
}
}
}
?>
Posted by - Christoff Truter
Date - 2008-06-12 17:07:43
Comments
1 2 3 4 Last / 4 Pages (35 Entries)
Post comment