When you click the tag category name on the left part, the
tag's info belonging to the related category will be displayed on the right
side. The right part is the rather complex part in the tag system, where we
cannot use the simple connecting string to meet the requirement of rendering
the page. In this case, we will fall back upon the XSLT technique to transform
the XML structured data into the HTML code form.
This above task is performed with page ListNotes.aspx, where
the SQL Server's special FOR XML clause is used to help finish the database
query. As you maybe have already known, a SQL query with a FOR XML sub clause
will return the XML formatted data, which in combination with the XmlReader
class in .NET platform will easily achieve the aim of outputting data in the
XML format. Listing 6 indicates the behind-code of page ListNotes.aspx.
Listing 6
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Params["sid"] != null)
{
// Get the tag category id
int iSectionId = Convert.ToInt32(Request.Params["sid"]);
//create the database access object
SqlDatabase db = DatabaseFactory.CreateDatabase
("DatabaseConnectionString") as SqlDatabase;
// SQL clause: note the use of the FOR XML sub clause
string sqlCommand =
"SELECT id, title, link, description, html, [order] " +
"FROM note WHERE section_id = " + iSectionId.ToString() +
" ORDER BY [order] FOR XML AUTO, ELEMENTS";
//create the SQL Command object according to the above sql clause
DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
XmlReader reader = null;
StringBuilder sb = new StringBuilder();
try
{
//obtain the XML styled data reader
reader = db.ExecuteXmlReader(dbCommand);
}
finally
{
if (dbCommand.Connection != null)
{
dbCommand.Connection.Close();
}
}
// xslt transformation
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Server.MapPath("~/xsl/notes.xsl"));
// render the result via xslt transformation
XmlWriter writer = new XmlTextWriter(Response.Output);
xslt.Transform(reader, writer);
}
}
Note that accessing page ListNotes.aspx requires an input
parameter sid, which just corresponds to the tag
category id. Another point you should take notice of is that file notes.xsl
here is the XSLT transformation style file, which plays the role of transforming
the XML data returned from the database query into the HTML code and render it
onto the page. However, for brevity, we will not list the long content of file
notes.xsl.
Next, in the client side JavaScript code two tasks need to
be finished: one is add the onclick event handler for the items inside the tag
category list, the other is put the output HTML code from page ListNotes.aspx
inside the corresponding <div/> element on the main page.
To achieve the target of adding the onclick event handler for
the items inside the tag category list, we can recur to the "Event.observe"
method provided by Prototype. This is done using the code in Listing 7.
Listing 7
function InitSection(xmlhttp) {
// Show tag category list
$("sections").innerHTML = xmlhttp.responseText;
// mark the start and end orders during the course of the dragging respectively
var start_order, end_order;
var sort = Sortable.create("section_list",
{
//ghosting: true,
constraint: false,
starteffect: function(element) {
// mark the initial order before dragging
start_order = Element.FindIndexOf("section_list", element);
start_order = parseInt(start_order) + 1;
},
endeffect: function(element) {
// mark the result order after dragging
end_order = Element.FindIndexOf("section_list", element);
end_order = parseInt(end_order) + 1;
//invoke the page MoveSection.aspx in the Ajax
//mode to move the tag section
var pars = "oid=" + start_order + "&noid=" + end_order;
new Ajax.Request("MoveSection.aspx",
{mothed: "GET", parameters: pars});
}
});
// add onclick response
$A($("sections").childNodes).each(
function(element, index) {
Event.observe(element, "click", ListNotes, false);
}
);
}
function ListNotes(event) {
// remove "li_" before each id,can convert it to section id
var section_id = Event.element(event).id.getId();
$("selSection").value = section_id;
new Ajax.Request(
"ListNotes.aspx", {
parameters: "sid=" + section_id,
onComplete: ShowNotes
}
);
}
function ShowNotes(xmlhttp) {
$("rightArea").innerHTML =
xmlhttp.responseText;
…… (omitted)
In the above code, we again used the iterate-through
function of the enumerable objects to loop through all the sub nodes within the
<div/> element representing the tag category list to attach the onclick
event handler to them.
By examining further, you may find that the onclick event
handler function is specified as ListNotes. Inside the function ListNotes, we
use the "Ajax.Request" class to send asynchronous request to page
ListNotes.aspx.
However, before sending out the request to page
ListNotes.aspx, one question should be tackled out: how to grab the id of the
current tag category? In essence, during the previous course of displaying the
tag category and tag info, we have already made preparation for this. Acute
readers may have found out that in the tag category and tag lists related HTML code,
the naming of the element ids are in well regularity: they are all ended with
the symbol underscore plus the id number. Therefore, if we obtain the id of the
onclick event source, we can easily get the id's of the tag categories and
tags. For this, we should fall back on the extension function getid
of the String object, which can acquire the sub string after the last symbol
underscore. Here is the related code.
Listing 8
String.prototype.getId=function(){
Return this.substr( this.lastIndexOf("_")+1);
}
Up to now, we have nearly finished the task of displaying
the tag info. The last small function that requires adding to this part is the unfold/collapse
support to each tag info block. You may have already noticed that at the upper
left corner of each tag rectangle there are small triangle icons through which
we wish to add the tag info unfold/collapse function. Please look at the
following script code.
Listing 9
function ShowNotes(xmlhttp) {
…… (omitted)
$$(".showHide").each(
function(item) {
Event.observe(item, "click",
function(event) {
var target =
event.target ? event.target : event.srcElement;
var id = target.id.getId();
Effect.toggle("content_" + id, "appear",
{
transition: Effect.Transitions.full,
duration: 0.2,
afterFinish: function (effect) {
$("img_" + id).src =
effect.element.visible() ?
"images/hideMod.gif" :
"images/showMod.gif";
}
});
}, false
);
}
);
…… (omitted)
}
Here, we again used the Event.observe method to attach the
onclick event handler to the <img> elements. Morever, we rested on the
special effect (in this case the Effect.toggle method) provided by the
script.aculo.us framework to achieve the aim of displaying and hiding the tag
info.
The last detail you need to notice is that we used the CSS
selector support of Prototype to grab all the sets with the CSS class named "showHide,"
and then attached the corresponding onclick event handlers to each of the
items. The following two figures show the unfolding and collapsing effect of
the tag info blocks, respectively.
Figure 3 - Hiding the tag info block
Figure 4 - Displaying the tag info block