|
Creating deep URL structure using getChildElement() and transient HopObjects
Shows how to create a URL space on Gong that displays pages by date of last modification.
The code in this example can be downloaded as zip file: [HopMacro error in file: java.lang.RuntimeException: Error retrieving Node: java.sql.SQLException: General error message from server: "Can't open file: 'AV_FILE.MYI' (errno: 145)"]
/**
* Called by Helma when resolving the request path.
* Return a new root level DateFolder object for child id "byDate",
* otherwise get the actual child object.
*/
function getChildElement(name) {
if (name == "byDate")
return new DateFolder();
return this.get(name);
}
Listing for root/getChildElement.js
// scope constants telling the DateFolder object
// whether it's a root, year, month or day folder
DateScope = {
ROOT: 0,
YEAR: 1,
MONTH: 2,
DAY: 3
};
/**
* DateFolder constructor. If called without arguments, it's a root folder,
* otherwise, a folder with the given date and scope is constructed.
*
* @param Date A date specifying this folder's location in time
* @param Int A DateScope constant specifying this folder's type (ROOT/YEAR/MONTH/DAY)
*/
function constructor(date, scope) {
this.date = date;
if (!scope)
this.scope = DateScope.ROOT;
else
this.scope = scope;
if (date) {
this.year = date.getFullYear();
this.month = date.getMonth()+1;
this.day = date.getDate();
}
}
/**
* Get a child element by id.
* @param String the name of the child element
*/
function getChildElement(name) {
// Loop through pages and see if we have a matching child element.
// For the root/year/month scopes, we check if there is at least
// one page where the corresponding date field matches the name.
// For the day scope, match the names of pages contained in that day.
var l = root.list();
for (var i in l) {
var date = root[i].modifytime;
switch (this.scope) {
case DateScope.ROOT:
case DateScope.YEAR:
case DateScope.MONTH:
if (this.containsDate(date) && this.getChildId(date) == name)
return new DateFolder(date, this.scope+1);
case DateScope.DAY:
if (this.containsDate(date) && root[i].name == name)
return root[i];
}
}
}
/**
* Main action. Provides a listing of contained objects. For
* root folders, that's a list of years, for year folders a list of
* months, for month folders a list of days, and for day folders a list
* of gong pages.
*/
function main_action() {
res.data.title = this.getHeader();
// start body with a link to the parent folder
res.data.body = "<a href='"+path.href()+"..'>[up]</a><br />";
var l = root.list();
// seenIds is used to prevent double listing of child years/months/days
var seenIds = new Object();
var id = null;
// loop through children and add to listing in res.data.body.
for (var i in l) {
var date = root[i].modifytime;
switch (this.scope) {
// create listing to child DateFolders
case DateScope.ROOT :
case DateScope.YEAR :
case DateScope.MONTH :
if (this.containsDate(date) && !seenIds[this.getChildId(date)]) {
id = this.getChildId(date);
seenIds[id] = id;
res.data.body += "<a href='"+path.href(id.toString())+"'>";
res.data.body += this.getChildName(date)+"</a><br />";
}
break;
// create listing to child pages
case DateScope.DAY :
if (this.containsDate(date)) {
res.data.body += "<a href='"+path.href(root[i].name)+"'>";
res.data.body += root[i].name+"</a><br />";
}
}
}
renderSkin("main");
}
/**
* Get the title for the current folder, depending on its scope and date.
*/
function getHeader() {
switch (this.scope) {
case DateScope.ROOT:
return "Listing items by date";
case DateScope.YEAR:
return "Listing for "+this.date.format("yyyy");
case DateScope.MONTH:
return "Listing for "+this.date.format("yyyy/MMM");
case DateScope.DAY:
return "Listing for "+this.date.format("yyyy/MMM/d");
}
}
/**
* Check if the current folder contains the given date.
* @param Date The date to be checked.
* @return Boolean true if the date is contained in this DateFolder
*/
function containsDate(date) {
if (this.scope > DateScope.ROOT && date.getFullYear() != this.year)
return false;
if (this.scope > DateScope.YEAR && date.getMonth()+1 != this.month)
return false;
if (this.scope > DateScope.MONTH && date.getDate() != this.day)
return false;
return true;
}
/**
* Extract the child id from the given date. For root folders that's the year,
* for years the month, for months the day.
*/
function getChildId(date) {
switch (this.scope) {
case DateScope.ROOT:
return date.getFullYear();
case DateScope.YEAR:
return (date.getMonth()+1).format("00");
case DateScope.MONTH:
return date.getDate().format("00");
case DateScope.DAY:
throw "Calling getChildId() on day folder is not supported!"
}
}
/**
* Format the child label for the given date.
*/
function getChildName(date) {
switch (this.scope) {
case DateScope.ROOT:
return date.format("yyyy");
case DateScope.YEAR:
return date.format("yyyy/MMM");
case DateScope.MONTH:
return date.format("yyyy/MMM/dd");
case DateScope.DAY:
throw "Calling getChildName() on day folder is not supported!"
}
}
Listing for DateFolder/functions.js
... comment
Page last modified on 2005-10-30 09:20 by czv
|