Junkfood

Food and Junk.

All | Food | Junk | Work

20050127 Thursday January 27, 2005

Roller: Navigation Bar Improvement

The current behavior of the Navigation Bar (the one on my page, at the right, that starts with "Sun Bloggers" and "Weblog") is that if a Roller user logs into the system, the Navigation Bar also contains "New Entry", "Settings", and "Logout". It makes sense if I (the page owner) am the one looking at this page. However, for other Roller users who happen to see this on my page, it may be somewhat confusing. Similarly, when I am logged in and look at other users' pages, I see a "New Entry" link which is confusing for me.

The improved behavior is that "New Entry", "Settings", and "Logout" is seen in the Navigation Bar only when I (the page owner) am logged in. Other logged-in users don't see these links. Non-logged in users see a link to "Login". The below macro contains the fix. It overrides an existing Roller macro.

#macro( showNavBar2 $vertical $delimiter $useCSS)
    #set( $container = "div" )
    #if ( $useCSS ) #set( $container = "ul" ) #end
    #set( $rawUrl = "$ctxPath/page/$userName" )
    <$container class="rNavigationBar">
    #if ($siteName=="Main")
        #set( $mainUrl = "$ctxPath?rmk=tabbedmenu.main&amp;rmik=tabbedmenu.main" )
        #printNavLink( $mainUrl $text.get("navigationBar.main") $useCSS $vertical "" )
    #else
        #printNavLink( "$ctxPath/" $siteName $useCSS $vertical "" )
    #end
    #if( $website )
        #foreach( $iPage in $pages )
            #set( $invisible = $iPage.Name.startsWith("_") )
            ## Again, there is no "break" in Velocity
            #if( !$invisible )
                #set( $isSelected = false )
                #if( $page && $iPage.Id == $page.Id && 
!$editorui) #set($isSelected = true) #end

                #if( !$isSelected )
                    #printNavLink( "$rawUrl/$iPage.Link" $iPage.Name 
$useCSS $vertical $delimiter )
                #else
                    #if( $useCSS )<li class="rNavItem">
                    #elseif( $vertical ) <br />
                    #else $delimiter
                    #end
                    $iPage.Name
                #end
            #end
        #end
    #end

    ## strutsUrlHelper( useIds, isAction, path, val1, val2)
    #if ($req.getUserPrincipal())
        ## // The person looking at the page is logged into Roller.
        #if ($req.getUserPrincipal().getName().equals($userName))
            ## // The person looking at the page is this blog's owner
            ## // who is also currently logged in.
            #set( $editUrl = $rawUrl )
            #set( $editUrl = $pageHelper.strutsUrlHelper(false, true, 
"weblogCreate", "tabbedmenu.weblog", "tabbedmenu.weblog.newEntry") )
            #printNavLink( $editUrl $text.get("navigationBar.newEntry") 
$useCSS $vertical $delimiter )

            #set( $editUrl = $rawUrl )
            #set( $editUrl = $pageHelper.strutsUrlHelper(false, true, 
"editWebsite", "tabbedmenu.website", "tabbedmenu.website.settings") )
            #printNavLink( $editUrl $text.get("navigationBar.settings") 
$useCSS $vertical $delimiter )
            #set( $editUrl = $rawUrl )
            #set( $editUrl = $pageHelper.strutsUrlHelper(false, true, 
"logout-redirect", "", "") )
            #printNavLink( $editUrl $text.get("navigationBar.logout") 
$useCSS $vertical $delimiter )
        #else
            ## // The person looking at the page is the owner of a
            ## // different blog.  They are logged in.
        #end
    #else
        ## // The user is not logged into Roller.
        #set( $editUrl = $pageHelper.strutsUrlHelper(false, true, "login-redirect", 
"", "") )
        #printNavLink( $editUrl $text.get("navigationBar.login") $useCSS $vertical 
$delimiter )

        #if ($req.getAttribute("allowNewUsers"))
            #set( $registerUrl = $pageHelper.strutsUrlHelper(false, true, 
"registerUser", "", "") )
            #printNavLink( $registerUrl $text.get("navigationBar.register") $useCSS 
$vertical $delimiter )
        #end
    #end
    </$container >
#end

(Some long lines have been broken into separate lines, so you may need to join them back together manually.)

(2005-01-27 13:00:00.0) Permalink | Comments [1]

20050125 Tuesday January 25, 2005

Example of Improved Permalink Format

(2005-01-25 09:40:49.0) Permalink |

Roller: Improved Permalink Format

In most blogs I've seen, a Permalink for an entry is a URL that points to a page containing just that entry, along with that entry's comments. However, Roller uses Permalink URLs that contain a date and point to a page containing all entries from that date and earlier (containing the entry specified, along with a whole bunch of other entries). This is so, even though Roller already has the capability to generate pages that look like "standard" Permalink pages.

If you look at the URL for any Roller blog entry's "Comments" page, you'll see that it is very similar to a "standard" Permalink URL. And, if you follow the Comments link, the resulting page looks very much like a "standard" Permalink page. In fact, if we take a Roller comments page URL and simply remove the "#comments" anchor from the end, it makes a pretty good alternate Permalink.

The below macro overrides the standard Roller macro for generating Permalink URLs, to use the alternate format. The diff is also below. Because I do not know whether overriding the Permalink URL format might have any side effects (within Roller or for outside agents/aggregators), I have not implemented it on my blog. (I have tested it, and it appears to work just fine.) This macro needs to be put in the "_day" template. Putting it in the "Weblog" template does not work.

#macro( showEntryPermalink $entry )
    <a href="$ctxPath/page/$userName/$page.link/$utilities.encode($entry.anchor)"
        title="$text.get( "macro.weblog.entrypermalink.title" )"
        class="entrypermalink">Permalink</a>
    #if ($pageHelper.isUserAuthorizedToEdit())
        [<a href="$pageHelper.getEntryEditUrl($entry)">
        $text.get( "macro.weblog.entrypermalink.edit" )</a>]
    #end
#end

2c2
<     <a href="$baseURL$entry.permaLink"
---
>     <a href="$ctxPath/page/$userName/$page.link/$utilities.encode($entry.anchor)"

(2005-01-25 09:24:00.0) Permalink | Comments [3]

20050124 Monday January 24, 2005

Roller: Re-ordering the Category Bar

The following macro allows you to re-order Categories shown by the showWeblogCategoryChooser macro. Specifically, it alphabetically sorts Categories by their Descriptions. I don't think that the Description field is used elsewhere, so it is probably safe to use it as a sorting key.

#macro( showWeblogSubcategoryChooser2 $parentCategory $divider )
    #set( $rawUrl = "$ctxPath/page/$userName/$page.link" )

    <div class="rWeblogCategoryChooser">
    #set( $weblogUrl = $rawUrl )
    #set( $chosenCat = "" )
    #if( $req.getParameter( $WEBLOGCATEGORYNAME_KEY ) )
        #set( $chosenCat = $req.getParameter( $WEBLOGCATEGORYNAME_KEY ) )
        <span class="rUnchosenCategory"><a href="$weblogUrl">
        $text.get( "macro.weblog.allcategories" )</a></span>
    #else
        <span class="rChosenCategory">$text.get( "macro.weblog.allcategories" )</span>
    #end

    #if ( $req.getParameter($PAGEID_KEY)  )
        #set( $pageParam = "&$PAGEID_KEY=$req.getParameter($PAGEID_KEY)" )
    #end
    #set( $rawcats = $pageModel.getWeblogCategories($parentCategory) )
    ## // Sort categories by description, using a bubble sort.
    ## // The "All" category is not sorted; it's always first.
    #set( $cats = [] )
    #foreach( $rawcat in $rawcats )
       #set ($curcat = $rawcat)
       #set ($catcounter = 0)
       #foreach ($cat in $cats)
            #if ($curcat.description.compareTo($cat.description) < 0)
                #set ($curcat = $cats.set($catcounter, $curcat))
            #end
            #set ($catcounter = $catcounter + 1)
        #end
        #if ($cats.add($curcat))
        #end
    #end
    #foreach( $cat in $cats )
        ## $pageHelper.strutsUrlHelper() wasn't working, so do it manually
        #set( $catParam = "?$WEBLOGCATEGORYNAME_KEY=$utilities.encode($cat.path)" )
        #set( $weblogUrl = "$rawUrl$catParam$!pageParam" )
        $divider
        #if( $chosenCat == $cat.path )
            <span class="rChosenCategory">$cat.Name</span>
        #else
            <span class="rUnchosenCategory"><a href="$weblogUrl">$cat.Name</a></span>
        #end
    #end
    </div>
#end

The macro does not change category order anywhere else. Specifically, it does not change it in the Search drop-down menu or in the New Weblog Entry category drop-down menu (and therefore the default category for new entries is also unchanged). It also doesn't change the position of the "All" category (which is always in the first position).

I'm not sure how Roller orders categories by default. It's either reverse alphabetical order by name or reverse of the order that the categories were added.

(2005-01-24 13:00:00.0) Permalink |

20050121 Friday January 21, 2005

Girl Scout Cookie Equivalency Chart

Revised for 2004.

There are two baking companies licensed to produce Girl Scout cookies, ABC Bakers (Interbake Foods LLC) and Little Brownie Bakers. Each company must produce three mandatory cookie types and can offer up to five more. Currently, there are five common cookie types that are produced by both companies. Confusingly, the same cookies have different names, depending on the baking company. This chart shows which cookies are equivalent.

ABC/Interbake Foods Little Brownie Bakers
Mandatory:
Thin Mints Thin Mints
Peanut Butter Patties Tagalongs
Classic Shortbread Trefoils
Optional:
Caramel deLites Samoas
Peanut Butter Sandwich Do-Si-Dos
Reduced Fat Lemon Pastry Cremes (no equivalent)
Animal Treasures (no equivalent)
Iced Berry Pinatas (no equivalent)
(no equivalent) All Abouts
(no equivalent) Lemon Coolers
(no equivalent) Double Dutch

Between 2003 and 2004, Pinatas replaced Friendship Circles, and Lemon Coolers and Double Dutch replaced Ole Ole's and Aloha Chips.

References:

(2005-01-21 13:00:00.0) Permalink | Comments [2]

20050120 Thursday January 20, 2005

Roller: Macro Customization and Hacking

Most Roller customization documents I've read seem to deal with customizing the look of the weblog by editing page templates or CSS stylesheets. However, they are not helpful if what you want to change is output produced by Roller macros. Here are some tips for writing/customizing Roller macros (levels 4 and 5 of the Levels of Roller Customization below).

Levels of Roller Customization (from high to low-level):

  1. Edit CSS stylesheets to customize styles.
  2. Edit page templates to add/delete/move page elements and Roller macros.
  3. Select different theme packages to get different base page templates and CSS stylesheets.
  4. Create and use new macros.
  5. Override existing Roller macros.
  6. Change Roller configuration and installation.
  7. Change Apache configuration.
  8. Edit Roller source code.

Unfortunately, the documentation you need is scattered across many different sites. Specifically, you need documentation on Roller macros, Roller templates, Roller Java source code, the Velocity Template Language, and the Java programming language.

  1. The Roller source code can be downloaded at: https://roller.dev.java.net/servlets/ProjectDocumentList?folderID=2525&expandFolder=2525&folderID=0
    1. The Roller Velocity macros are in roller/web/WEB-INF/classes/*.vm
    2. The themes are in roller/web/themes/*. They are useful to see what can be done by simply editing CSS and page templates.
    3. The Java source code is in roller/src/*. You need it to be able to discover the many useful (but undocumented) Roller variables. You'll also want to see how the hardcoded functions work. The most interesting classes are:
      • org.roller.pojos.CommentData
      • org.roller.pojos.PageData
      • org.roller.pojos.RefererData
      • org.roller.pojos.WeblogCategoryData
      • org.roller.pojos.WeblogEntryData
      • org.roller.pojos.WebsiteData
      • org.roller.presentation.velocity.PageHelper
      • org.roller.presentation.velocity.PageModel
      • org.roller.business.RefererManagerImpl
      • org.roller.business.WeblogManagerImpl
      • org.roller.util.*
  2. Roller documentation is available at:
    1. User Guide (incomplete, but an okay start): http://www.rollerweblogger.org/wiki/Wiki.jsp?page=UserGuide
    2. Macro and Variable Reference (very incomplete): http://www.rollerweblogger.org/wiki/Wiki.jsp?page=RollerMacros
  3. Velocity documentation is needed to learn how to program in the Velocity Template Language. Specifically, you'll need:
    1. User Guide: http://jakarta.apache.org/velocity/user-guide.html
    2. Reference Guide (really, it's the second half of the User Guide): http://jakarta.apache.org/velocity/vtl-reference-guide.html
  4. Java documentation is needed to find out what can be done with Velocity objects. You will probably need to know how to program in the Java language. Documentation is at: http://java.sun.com/j2se/1.4.2/docs/api/index.html. The most useful classes are:
    1. java.lang.String
    2. java.util.ArrayList
    3. java.util.Map

Customization at this level is really just programming: writing new macros and re-writing the Roller macros. This requires knowledge of the Velocity Template Language (which is a programming language). It also requires knowledge of Java since Velocity is designed to interface with Java. Its basic variable types (String, ArrayList, Map) are Java objects whose methods are available to be used (if you know how). Roller is written in Java, and its objects, variables, and methods can also be used. Unfortunately, Roller is poorly documented and reading/interpreting its Java source code is necessary.

Some tips:

  • Create a (possibly hidden) test page which is a duplicate of your main Weblog page. Do all your experimentation on the test page. When things work right, you can copy the changes over to the Weblog page.
  • Removing the stylesheet from your test page may be helpful to prevent CSS from affecting how changes appear.
  • Velocity seems to be very picky about how lines are indented. Be sure to indent all lines properly (following the Roller macros as examples), with 4 spaces per indent. I've found that mis-indented lines can cause mysterious errors.
  • If you make a change to a template macro and the resulting page is blank, you've made a mistake that prevents the macro from running. Try commenting out lines in the macro to see where the problem lies.
  • Velocity control operators and data structures are very primitive. You will probably need to write programs that do things the hard way to work around this.
  • Starting with page templates, drill down through the macros to see how things work and how the Roller developers did things.
  • Instead of making a few big changes, make many small changes.
  • Reload the test page after each change you make. This will help to identify problems as soon as they are introduced.
  • Be sure to save copies of your page templates offline. You may want to save a copy each time you make a major change.
  • Velocity macros take space-separated arguments, but Java methods take comma-separated arguments.
  • The showWeblogEntries macro and its sub-macros contain most of the "guts" of how Roller works for weblog entries, comments, and search pages. It is the main "black box" whose contents can be overridden and customized.

Good luck!

(2005-01-20 13:00:00.0) Permalink | Comments [2]

20050119 Wednesday January 19, 2005

Nashua Furniture Store Food

There is strong competition among furniture stores in my area. The stores in Nashua all serve free food of some sort.

Jordan's Furniture serves free soda, coffee, hot chocolate, pellet ice cream, and freshly-baked cookies. They also used to have goldfish crackers and pretzels, but I'm not sure whether they still do. The pellet ice cream served is Dippin' Dots. (The two major brands of pellet ice cream are Dippin' Dots which has a 10% butterfat content and Mini Melts which has 14% butterfat.) They serve you from a counter in the front of the store. There are also free balloons for kids. The sales staff appear to work on some sort of shared-commission system, so they aren't aggressive.

Bob's Discount Furniture serves free lemonade, iced tea, coffee, popcorn, freshly-baked cookies, ice cream, and an assortment of penny candy. They serve you from a counter in the back of the store. Sugar-free penny candy is also available from behind the counter. Bob's also has a small video arcade with a Golden Tee machine, among others. The sales staff appear to take turns assigning themselves to people who walk through the door. My salesperson sort of followed me around the store, hoping to secure a sale.

Bernie & Phyl's serves free coffee, cookies, and lemonade. They have a good selection of kooky furniture, like chairs shaped like hands. The sales staff appear to work on some sort of shared-commission system, so they aren't aggressive. In fact, nobody spoke to me when I was touring the store (which was fine by me).

Furniture World serves just bottled water and coffee. However, the coffee served is Green Mountain coffee, brewed in individual Keurig K-Cups. The system is pretty neat. Inside the sealed K-Cup is coffee in a cone filter. In the machine, pressurized hot water is injected through the top of the cup and through the coffee and filter. The coffee comes out of the bottom of the cup. (http://www.keurig.com/AW/magic.html) The sales staff hang out watching the front door and take turns assigning themselves to people who walk through the door. However, they did not follow me around the store.

(2005-01-19 13:00:00.0) Permalink |

20050118 Tuesday January 18, 2005

Roller: Customizing Comment Details

Through experimentation, I've found that you can write macros that override the default implementation by Roller. On comments pages, email addresses (or IP addresses, if no email is provided) and websites are displayed by default. I don't like this behavior, so I wrote a macro that overrides it. The macro gets added to the top of the Weblog file, just after the DOCTYPE line.

#macro( showCommentDetails $comment $showPermalink )
    $dateFormatter.applyPattern($text.get( "macro.weblog.datepattern" ))
    #set($email = $utilities.hexEncode($comment.email))
    <p class="comment-details">
    $text.get("macro.weblog.postedby")
    #if (!$stringUtils.isEmpty($comment.name))
        <b>$comment.name</b>
    #else
        <b>Anonymous</b>
    #end
    $text.get("macro.weblog.on") $dateFormatter.format($comment.postTime)
    #if( $showPermalink )
    <a href=
"${ctxPath}/comments/${userName}/${page.link}/${entry.anchor}#comment${velocityCount}"
       class="entrypermalink"
       title="$text.get( "macro.weblog.commentpermalink.title" )">#</a>
    #end
    </p>
#end

The macro is intended for use with Roller 1.0. I'm not sure whether it works with other versions.

(2005-01-18 08:00:00.0) Permalink | Comments [2]

20050114 Friday January 14, 2005

Monster Thickburger

The Hardee's burger chain introduced a new "Monster Thickburger" menu item:

  • Two 1/3 lb. Angus beef patties
  • Three slices of cheese
  • Four slices of bacon
  • Served with mayonnaise and on a buttered sesame seed bun
  • 1,420 calories
  • 107 grams of fat
  • Costs $5.49 (and for the meal with fries and soda, it's $7.09)
  • http://www.monsterthickburger.com/

I think that the nearest Hardee's is in Pennsylvania, near Harrisburg.

(2005-01-14 13:00:00.0) Permalink |

20050112 Wednesday January 12, 2005

The Tomb

In Boston, there's a new interactive walkthrough game called Tomb. It's sort of an Egyptian-themed haunt where players have to solve puzzles and perform actions. It's from a new company with a stupid name spelled "5W!TS", and they anticipate having different shows in the future.

I visited on Saturday October 24, 2004-- they are in the Fenway district of Boston. When I got there, I discovered that someone I knew was also there by coincidence. His sister had recruited a group trip. The price was $16.80 (with tax), the weekend matinee price. Our group consisted of 11 people.

Without giving away any spoilers, I found Tomb to be interesting. Visually, the theming was very beautiful and realistic-looking -- you can almost imagine that you are in an Egyptian pyramid. The special effects and lighting were also really good. The audio was very clear-- no crappy haunt sound here. As for the puzzles and tasks, some were cheesy/easy and others were very difficult.

The replayability of this show is suspect-- I don't think that anyone would go more than once, unless you "die" and are unable to complete the game the first time. I seem to recall reading that if you "die" you might get a discount coupon for future visits. I recommend going with a group of people-- an intact group with no strangers. I believe that the optimal group size is 6-8 people, though I think that it will also work acceptably with a group of 4-10. It will also work best if there is no group waiting to go after yours, so you aren't as rushed. You'll probably want your group to be made up of friends and family, though it could be argued that the stress of the experience could be a friendship-breaker.

Because of the replayability factor, I have to question whether this company will stay in business long. The place seemed empty when I went, with the exception of our large group, and the staff looked bored. (However, my friend went by a few hours later and found the place to be crowded.) They have a year lease for this space.

In conclusion, Tomb was an interesting experience, and I'm glad I went. I do recommend it, with some reservation.

http://www.5-wits.com/

(2005-01-12 13:49:54.0) Permalink | Comments [1]

20050111 Tuesday January 11, 2005

Movie Review: Polar Express

Summary: It's okay. Polar Express is not a good movie, but it is a visual spectacle worth seeing if (and only if) you can see it in an IMAX 3D theater.

You could tell that the movie was intended to be viewed in 3D. Most of the "camera" angles and shots were 3D-centric, and because of this the movie probably will look a bit strange in a regular theater. If you've ever seen a 3D movie on a 2D screen (like seeing Jaws 3 or Friday the 13th Part 3 on television) you'll know what I mean. Some of the sound (mostly rumbling of the train) also seemed to have been designed for IMAX theaters. For these reasons, I think that the movie is worth seeing only in an IMAX 3D theater.

The story itself was dull, and the movie seemed to be made of unrelated action sequences strung together. Parts of the plot didn't make sense. Visually interesting, but soul-less. I guess it is what comes of trying to turn a 29-page picture book into 2-hour movie.

Some people have said that the movie is scary for kids, but I didn't think so. It's not as bad as Wizard of Oz or Charlie and the Chocolate Factory. It's true that Santa is somewhat stern and unsmiling, but it's nothing compared to the Santa in City of Lost Children.

Even though the movie isn't that great, it is a visual spectacle worth seeing, and I suspect that Polar Express will become a movie that families go to see every year at the IMAX.

I saw Polar Express in the Jordan's furniture store in Reading on Saturday [November 20, 2004]. I was able to get a walk-in ticket to the 10:00am show, but by noon all of the other showings, except for the 10:00pm show, had sold out. I noticed on the ticket web site, that by Saturday night all of Sunday's shows had also sold out, except for the final, 8:30pm show. If you are going to see it on a weekend, I recommend advance ticket purchase.

Update: I saw Polar Express again last Saturday, accompanying someone who had not yet seen it. So, even though it isn't that great a movie, the IMAX 3D version is something that can be enjoyed multiple times, like a theme park roller coaster.

(2005-01-11 14:57:56.0) Permalink | Comments [1]

Calendar

« January 2005 »
SunMonTueWedThuFriSat
      
1
2
3
4
5
6
7
8
9
10
13
15
16
17
22
23
26
28
29
30
31
     
Today

Recent Entries

Search

Navigation



XML