An overview of his favorite techniques for applying COPE (Create Once, Publish Everywhere) for both content and formats. Includes Velocity and Web Services sample code.
16. • [getBlock type="xhtml"
path="/absolute/path/to/block" site=“siteName"]
• [getBlock type="xhtml"
path="/absolute/path/to/block" site="siteName"
replace="textreplacement1 textreplacement2"
textreplacement1="value to display #1"
textreplacement2="value to display #2”]
(will replace the string "[|[textreplacement1]|]" in the block with
"value to display #1" and "[|[textreplacement2]|]" with "value to
display #2”)
• http://bit.ly/cuc15-shortcode (GitHub)
COPE, of course, stands for “Create Once, Publish Everywhere,” one of the core reasons to use a content management system, especially Cascade Server. Today, I want to look at some key concepts and techniques that have helped me COPE with content over the years.
If everything works correctly, I’ll be posting links throughout the session with the hashtag #COPEtricks, so feel free to follow along or check those out afterwards
This is going to be part historical, part technical, as I explore some of the key techniques I’ve discovered or developed to re-use content--whether that content be traditional web page content or system assets like formats. It’s a mix of concepts, techniques, and code, so I hope there will be a little something for everyone. Please feel free to stop me at any time with questions, and I hope we can have some time at the end for you to share your own favorite COPEing mechanisms.
To start off, let me share a little about my context to explain why this has been so critical for me. I’m Web Developer at Sauk Valley Community College. Here’s a picture of our campus, which looks pretty rural, but if we zoom out a little bit….it looks even more rural. We’re definitely one of the smaller Cascade sites.
[twitter]Follow #CUC15 or #COPETricks for related links (if it works right!)[/twitter]
To start off, let me share a little about my context to explain why this has been so critical for me. I’m Web Developer at Sauk Valley Community College. Here’s a picture of our campus, which looks pretty rural, but if we zoom out a little bit….it looks even more rural. We’re definitely one of the smaller Cascade sites.
So I wear several different hats--webmaster, campus display signage, mobile app, document imaging system, other duties as assigned--which comes with some challenges and benefits. Since I touch so many areas, I have an ability to look for where content can be re-used. But I also have a real need to make that process as efficient as possible. In larger institutions, you still have a need to be efficient and re-use content, but with the added need to share that content among several developers and departments.
When I started using Cascade Server, back in version 4.7 (which boasted Internet Explorer 7 support!), I remember being frustrated by how complicated it was to build a simple web page. So, I love coffee, perhaps a little too much, and roast my own. If I have roasted some coffee beans and want to give you some, the easiest way is for me to put it in a bag and give it to you. Right? No need for any other steps.
But we do have some limitations, don’t we? We have to be nearby. We need to be able to carry the package. So, if I have 100,000 pounds of coffee to distribute nationwide, I’m going to need to add some steps. If that coffee comes from a hundred different sources, more steps. I’m going to need a warehouse, a distribution center.
One of the key realizations for me was when I stopped thinking of Cascade Server as a program to make web pages and started thinking of it as a data warehouse. I’m going to be collecting data from a lot of different sources--user generated in Cascade, XML feeds, APIs, user generated from outside Cascade, wherever I can get it. Some of that will need to be repackaged, transformed, filtered, then I can send it out to wherever it needs to go.
In one sense, this is hardly revolutionary, but looking at Cascade this way is a key to unlocking Cascade’s full potential.
First is “Smart Fields” in Data Definitions. In addition to making Data Definitions much easier to use for the end user, having the ability to hide part of a form makes it easier to reuse that Data Definition elsewhere. The general idea is that you can show or hide sections of a form based on a <select> box, checkbox, or radio button. Again, this makes life much easier for content creators, and since you have to select whether a particular section is shown or hidden, you can easily show or hide that section in your Velocity or XSLT Format based on that value.
[twitter]Content Type publish sets: idea http://bit.ly/cuc15-ctpublishidea, code http://bit.ly/cuc15-ctpublishcode #CUC15 #COPETricks[/twitter]
Second up is Content Types. Many of you may not been around for the dark ages before the Content Type, but the ability to group together all of a particular type of page regardless of their location is great. So, once you have a content type, you can use a Content Type Index Block or the Query API to get a list of all assets and further filter and display them. I have a listing of committees and their minutes in our Intranet; before Content Types, I had to remember to manually add each index page to the publish set every time a new committee was added. Now, it’s a Committee Index Content Type, and I can use Web Services to update the publish set automatically whenever a new committee is added. There’s also an idea in the Idea Exchange to make this an option in the native Publish Set, so a shameless plug to vote for that idea and make my Web Services script obsolete.
Third is a technique I learned from Jay Mercer in my first ever User Conference session. He talked about XSLT Page Transforms and his “Identity Transform.” This has eliminated much of my need to write new templates by essentially giving access to the entire page from within the DEFAULT page region. The Identity Transform just loops through and replicates the entire XHTML page *after* all the regions have been processed. You can then add whatever templates you want to modify the processed XHTML. For example, if I want to append the current month and year to the <title> element for all news releases, I just add an element with a class=“addToTitle” which I “move” to the <title> element and remove from the DEFAULT region. Or, I can take any link with a class=”proxy” and run that link through EZ-Proxy. Or I can define an element in any region of the document and move it to the document <head> by adding a class of “moveToHead”. This dramatically reduces the number of modifications I need to make to Templates and the number of new Templates I have to make. Jay, thank you, thank you, thank you.
Fourth is too big of a topic to do more than a passing mention, but nothing has supercharged my ability to manage and automate Cascade more than Web Services. There’s just no substitute for being able to set a cron job to create and modify content in batches and daily, weekly, or whatever.
[twitter]Cascade Velocity Tools http://www.hannonhill.com/kb/Script-Formats/ #CUC15 #COPETricks[/twitter]
Finally in my “ultimate set of tools” is Velocity Script Tools, especially Includes, Locator Tool, and Query API. We’ll use this many more times in all the rest of the presentation, but Velocity offers many tools to streamline your code. One of the most useful has been Velocity Includes, allowing me to define code used repeatedly as a Velocimacro in a shared Velocity format. Our course schedules are maintained in Cascade, and include several different filtered views (for example, night classes, friday classes, listing by department) but they’re all displayed in a common format. I used to have to edit each individual Format for every change to that format. Once I rewrote them in Velocity, I can modify that display table code once and update all those pages. Saves a ton of time.
Locator Tool often saves me from needing to include a block as part of the Data Definition. Often, to get additional information, I’d need to include a huge Block in the Data Definition and hide it from end-users. This way, I can have smaller blocks and reference them just in the Format (which also makes them easier to change out). Again, we’ll be coming back and looking at some more examples later.
I haven’t used the Query API much yet, but it similarly has the ability to be a more efficient way to access pages than attaching an index block and another format. Instead, the results can be filtered ahead of time and all from one Format.
One of the things the Locator Tool opened up was the ability to easily open a block from within a script. This means it’s a lot easier to pull in just the block I want. All I need to know is the name and path--which I can reliably predict if I’m using Web Services to create the blocks.
[twitter]Idea - Locator Tool access to Feed Block XML http://bit.ly/cuc15-feedblocks[/twitter]
At the same time, it’s becoming more and more common for web apps to expose data via an API. I’ve seen REST APIs most commonly, and they’re among the easiest to work with, so we’ll use them for a couple examples. REST usually returns XML, JSON, or text. Of course, Cascade is great with XML, text can easily be wrapped in XML tags, and JSON can be pretty easily converted to XML. So all we need to do is use Web Services to access the REST API and store the result in an XML block. Time for another shameless plug: there’s an idea on the Idea Exchange, too, to allow the Locator Tool to access the XML of a Feed Block, which could even eliminate this step in many cases and allow the most up-to-date data at publish time.
[twitter]Import REST API results into Cascade http://bit.ly/cuc15-restapi #CUC15 #COPEtricks[/twitter]
[twitter]Import Acalog course catalog into Cascade http://bit.ly/cuc15-acalog #CUC15 #COPEtricks[/twitter]
[twitter]Hannon Hill Bricks example http://bit.ly/cuc15-brick #CUC15 #COPEtricks[/twitter]