SuperSatellite ||

Subscribe (?) Subscribe to RSS

Posts Tagged ‘macro’

Extending the pageContent() Macro in dotCMS

Published on September 19th, 2008 in No Comments »

Here’s my latest nugget of info to help you extend dotCMS.  This isn’t anything complex by any stretch of the mind, but it should be a little time saver for those of you looking into doing blogs, archives, or anything else where you have several pages of content to flip through.  By default, dotCMS comes with a nice little macro called pageContent() that allows you to pull in a list of content, and get a set grouping of results based on where they fall in the sort order.  The only failing was that you had to write your own way to go back and forth with results.

No longer!  With this simple, handy macro, you can automatically get forward and backward navigation after you’ve written your foreach() loop for the pageContent() results.  It makes use of a few of the variables that are created when you run pageContent().  You can supply your own text for the navigation links, as well as give it a custom class name that will automatically be applied to all the elements so that you can format it as you wish.  The code for the macro itself follows below the example.  Here’s a sample of it in use, and what it looks like:
#set($showPageNum = "true")
#set($pageLinkVar = "year=${yearVar}&")
#pageContentNavigation("$page")

Example of the navigation macro

Example of the navigation macro

Here’s the code to get you going.  Just paste it into your /[$DOTCMSROOT]/dotCMS/WEB-INF/velocity/dotcms_library_ext.vm file, or wherever else you’re loading your custom macros, restart the server (if needed), and get going.  There are any number of ways you can modify it to suit your needs, so go nuts!  You can copy the code below, or download the pageContentNavigation_macro.vm file.

  1. ## Macro:       pageContentNavigation()
  2. ## Author:      Michael Fienen
  3. ## Date:        08.09.19
  4. ## Version:     1.0
  5. ## E-mail:      fienen@gmail.com
  6. ## Website:     http://www.supersatellite.com/
  7. ## Description: Creates a "Previous/Next" style navigation after calling the pageContent() macro
  8. ##
  9. ## Required Parameters:
  10. ##     $currentPage  - Integer value for the current page number.
  11. ##
  12. ## Optional Parameters:
  13. ##     $prevPageTxt  - Text for the previous page link. Default: "« Previous Page"
  14. ##     $nextPageTxt  - Text for the next page link. Default: "Next Page »"
  15. ##     $showPageNum  - Show the page number between the navigation links. Default: "false"
  16. ##     $pageLinkVar  - Any necessary parameters to pass to the page for the query. Should end with an "&".
  17. ##     $pageVarName  - Variable name in the URI (Uniform Resource Identifier) for the page number. Default: "page"
  18. ##     $pageNavClass - Customizable CSS (Cascading Style Sheets) class name for the navigation and its elements. Default: "pageContentNav"
  19. ##
  20. #macro(pageContentNavigation $currentPage)
  21.   #if(!$UtilMethods.isSet($pageVarName))
  22.     #set($pageVarName = "page")
  23.   #end
  24.   #if(!$UtilMethods.isSet($prevPageTxt))
  25.     #set($prevPageTxt = "« Previous Page")
  26.   #end
  27.   #if(!$UtilMethods.isSet($nextPageTxt))
  28.     #set($nextPageTxt = "Next Page »")
  29.   #end
  30.   #if(!$UtilMethods.isSet($pageNavClass))
  31.     #set($pageNavClass = "pageContentNav")
  32.   #end
  33. <div class="${pageNavClass}">
  34.   #if($hasPreviousPage == "true")
  35.     #set($prevPage = $math.sub($currentPage,1))
  36.   <span class="${pageNavClass}Link ${pageNavClass}Prev"><a href="$VTLSERVLET_URI?$!{pageLinkVar}&amp;${pageVarName}=${prevPage}">$prevPageTxt</a></span>
  37.   #end
  38.   #if($showPageNum == "true")
  39.   <span class="${pageNavClass}Num">$currentPage of $totalPages</span>
  40.   #end
  41.   #if($hasNextPage == "true")
  42.     #set($nextPage = $math.add($currentPage,1))
  43.   <span class="${pageNavClass}Link ${pageNavClass}Next"><a href="$VTLSERVLET_URI?$!{pageLinkVar}${pageVarName}=${nextPage}">$nextPageTxt</a></span>
  44.   #end
  45. </div>
  46. #end

Gettin’ Your Macro On

Published on July 29th, 2008 in 2 Comments »

I think it’s time to rock out with another dotCMS blog, and dig into some basic stuff that can be very useful to people getting started in the content management system.  There was a topic recently on the mailing list that was asking about where to look to see some examples of macros, and where you can save your own.  This looked to be a good topic to cash in on (speaking of cash, wanna loan me some?).

Macro output on a page

Macro output on a page

In dotCMS, a macro is basically like it is in other applications: it’s a collection of code one calls to reproduce complex processes in a simple, and straightforward fashion.  You know, to help stupid people out.  To put it in other terms, it’s effectively what one might call a function in other languages.  You give it a name, set parameters it can take, and define some output.  dotCMS comes out of the box with a lot of macros you can readily use, sometimes without even realizing it.  These include things like the commonly used pullContent(), and fancier tools like videoPlayer().  Naturally, dotCMS has a list of these built in macros, and how to use them.  If you want to take a look at example code, the built in macros are stored in /[dotcmsroot]/dotCMS/WEB-INF/velocity/dotCMS_library.vm.  Don’t mess with those though, because odds are you’ll break stuff.  Just trust me on this.

There are a couple ways to approach writing your own macros.  The first is to write a second .vm file, and store it with the default one in the velocity folder.  It will be loaded when the server starts, but requires a server restart when you change or update them, because they are cached in the system when it starts.  Conventionally, the file name dotCMS_library_ext.vm is recommended.  By convention, I just mean that’s what the dotMarketing programmer folks have recommended to me.  The other way is to use a static container, which you include first thing in all the templates you want the macros to be available to.  Macros edited and saved this way do not require server restarts to use, but naturally you must make sure you’ve included the container in EVERY template where you suspect your macros might be used (and also ones where they might not. Trust me, never underestimate the stupidity of your users).  Neither method is right or wrong, and you should just choose the way that fits your development style best.  I’m still looking for a solution that would qualify as chaotic neutral, however.

Okay, so naturally you need to have something of a working knowledge of Velocity code to write a macro, so if you’ve never taken the time to learn some, I suggest you go do that.  Mr. Falzone has talked about this issue, so go get yourself some learnin’ and stop trying to run before you can walk.  Now, get off my lawn. If you already know Velocity stuff, go anyway, he’s a nice guy and worked hard, so you owe it to him to read it and pretend like you’re new to the subject.  Don’t worry, it’ll be our little secret.  But, assuming you understand the basics, this should be pretty straightforward.  So, starting up, we need to define the macro.  I’ll use as an example the macro I wrote that pulls in a list of events from the calendar by a tag:

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   - Changes the number of results to return
  4. ##    $listTitle  - Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.  
  7. #end

So, we start by calling the macro() function, naming it, and giving it a list of variables to expect.  You can have more than one variable, just list them one after the other (no commas or anything).  As you can see, before I open the macro, I list a couple variables in comments that aren’t required, but can be set before you use pullEventListByTag() and they’ll be pulled in later.  Next, I’m going to set three variables that I’ll use when querying for events, then I’ll build out the query and set it as a variable, and set how I want it ordered (date1 is the event start date).

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   - Changes the number of results to return
  4. ##    $listTitle  - Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.   #set($eventListPast= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),0)))
  7.   #set($eventListToday= $date.format(’MM/dd/yyyy’, $date.getDate()))
  8.   #set($eventListFuture= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),80)))
  9.  
  10.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  11.   #set($orderBy = ‘date1 asc’)
  12.  
  13. #end

Okay, next up I’m going to check for those optional variables, and if they aren’t set, it will give some default values.  After that, I’ll call the pullContent() macro (as you can see, you can call other macros within macros), and save the results in its own list variable.

  1. #macro(pullEventListByTag $eventTag)
  2.  
  3.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  4.   #set($orderBy = ‘date1 asc’)
  5.  
  6.   #if(!($UtilMethods.isSet($eventNum)))
  7.     #set($eventNum = 10)
  8.   #end
  9.   #if(!($UtilMethods.isSet($listTitle)))
  10.     #set($listTitle = ‘Related Events’)
  11.   #end
  12.  
  13.   #pullContent("$query" "$eventNum" "$orderBy")
  14.   #set($eventMacroList = $list)
  15.  
  16. #end

That takes care of the heavy lifting.  Next I’ll start the output.  In this case I’ll build out a <div> to hold the contents, pump out a header, and start a standard foreach() loop for the results in $eventMacroList just as we would when using the pullContent() macro like any other time.  I told you this wasn’t hard.

  1. #macro(pullEventListByTag $eventTag)
  2.  
  3.   #pullContent("$query" "$eventNum" "$orderBy")
  4.   #set($eventMacroList = $list)
  5. <div class="small">
  6.   #foreach($eventMacroEntry in $eventMacroList)
  7. <div style="margin:.5em 1em"><strong>$date.format(’MMM dd’, $eventMacroEntry.startDate) |</strong> #if($UtilMethods.isSet($eventMacroEntry.description)) <a href="/calendar/index.dot?id=$eventMacroEntry.identifier">$eventMacroEntry.title</a> #else $eventMacroEntry.title #end</div>
  8. #end</div>
  9. <div style="text-align:right"><a href="/calendar/?tag=$webapi.encodeURL($eventTag)"><small>More "$eventTag" Events $raquo;</small></a></div>
  10. <!— end eventsTagged —>
  11. #end

And believe it or not, that’s it. Once this is saved and initiated in the manner you choose, you can call your custom macro with the parameters you’ve set, and it will execute the code. In this case, you could call pullEventListByTag(”football”) to return all events tagged football. On another page you could call pullEventListByTag(”baseball”) and get a different set, but still get the same structured output.  Such is the nature of macros.  Any process you would need to do over and over again, or need to simplify for less savvy users are prime candidates for macroification.  In simple terms, this example is nothing more than a macro to automate a pullContent() call and foreach() loop.  If you look at the default macro file in dotCMS, you’ll see how much more complex you can get with them.

So, the complete macro for this example would be as follows.  Feel free to copy and modify it to fit your own needs, or to play around with to get used to the process.  I’d be happy to see how you improve or modify it.  You can also discuss it in the forums, or share your own creations.

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   - Changes the number of results to return
  4. ##    $listTitle  - Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.   #set($eventListPast= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),0)))
  7.   #set($eventListToday= $date.format(’MM/dd/yyyy’, $date.getDate()))
  8.   #set($eventListFuture= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),80)))
  9.  
  10.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  11.   #set($orderBy = ‘date1 asc’)
  12.  
  13.   #if(!($UtilMethods.isSet($eventNum)))
  14.     #set($eventNum = 10)
  15.   #end
  16.   #if(!($UtilMethods.isSet($listTitle)))
  17.     #set($listTitle = ‘Related Events’)
  18.   #end
  19.  
  20.   #pullContent("$query" "$eventNum" "$orderBy")
  21.   #set($eventMacroList = $list)
  22. <div class="small">
  23.   #foreach($eventMacroEntry in $eventMacroList)
  24. <div style="margin:.5em 1em"><strong>$date.format(’MMM dd’, $eventMacroEntry.startDate) |</strong> #if($UtilMethods.isSet($eventMacroEntry.description)) <a href="/calendar/index.dot?id=$eventMacroEntry.identifier">$eventMacroEntry.title</a> #else $eventMacroEntry.title #end</div>
  25. #end</div>
  26. <div style="text-align:right"><a href="/calendar/?tag=$webapi.encodeURL($eventTag)"><small>More "$eventTag" Events $raquo;</small></a></div>
  27. <!— end eventsTagged —>
  28. #end
Click to Download This Theme

Login/Register

Sign in with OpenID
Don't have OpenID? Get one here.
(What is OpenID?)
My Vidoop More secure than passwords.

My Tweets

Enjoying...

2001 ManiacsCabin Fever

The Sound Of Madness Limited Fan Club EditionIt's Not News, It's Fark: How Mass Media Tries to Pass Off Crap As News

My Stuff



Archives

My Zimbio Buddhist Blogs >