Helma logo
helma.org » Home > docs > examples > Creating deep URL structure using getChildElement() and transient HopObjects

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


Up: Code Snippets
Previous: Sparse XML Parsing

... comment


Page last modified on 2005-10-30 09:20 by czv