Monday 19 February 2007

Cut, Copy & Paste the ColdFusion PageContext Buffer

I've been messing about with some localisation stuff lately and I wanted a way to intercept the ColdFusion output buffer so I could mess with it.

Now I know you can sort of use <CFSAVECONTENT> for that. But it's mildy irritating since it only lets you use it on a single page. You can’t (for example) start it on one template and end it on another. Tsk!

So what I needed was a solution. After much poking things with sticks (metaphorical sticks) I found the answer I was looking for.

I’ve knocked up a CFC that gives the ability to manipulate the contents of the output buffer of ColdFusion exposing the following methods: -

  • Cut(item) – Write the buffer contents to variable named item and clear the buffer.
  • Copy(item) – Write the buffer contents to variable named item.
  • Paste(item) – Past the contents of variable named item into the buffer.
  • Get(item) – Get the contents of variable named item
  • Put(item) – Update the contents of variable named item
  • Clear() – Clear the buffer.

Here’s the code: -

Buffer.cfc

<cfcomponent name="buffer" hint="Tools for messing with the ColdFusion string buffer">
<cffunction name="init" hint="I initialise the cfc">
<cfset this.capturedBuffers=structNew()>
<cfreturn this>
</cffunction>

<cffunction name="copy" hint="Copy contents of the buffer to the named item">
<Cfargument name="target" type="string" default="clipboard" hint="Item to copy to. Default is clipboard.">
<cfset tmpBuffer=GetPageContext().getOut().getBuffer().toString()>
<cfset this.capturedBuffers[arguments.target]=duplicate(tmpBuffer)>
</cffunction>

<cffunction name="paste" hint="Paste the selected buffer item to the output stream">
<Cfargument name="source" type="string" default="clipboard">
<cfoutput>#this.capturedBuffers[arguments.source]#</cfoutput>
</cffunction>

<cffunction name="cut" hint="Cut contents of the buffer to the named item">
<Cfargument name="target" type="string" default="clipboard">
<cfset tmpBuffer=GetPageContext().getOut().getBuffer().toString()>
<cfset this.capturedBuffers[arguments.target]=duplicate(tmpBuffer)>
<cfset this.clear()>
</cffunction>

<cffunction name="get" hint="Returns the contents of the named buffer item">
<Cfargument name="source" type="string" default="clipboard">
<cfreturn this.capturedBuffers[arguments.source]>
</cffunction>

<cffunction name="put" hint="Overwrites the contents of the named buffer item">
<Cfargument name="content" type="string" default="" required=true>
<Cfargument name="target" type="string" default="clipboard">
<cfset this.capturedBuffers[arguments.target]=arguments.content>
</cffunction>

<cffunction name="clear" hint="Resets the buffer">
<Cfcontent reset="yes">
</cffunction>
</cfcomponent>

So, how do I use this buffer.cfc thing? - Here’s an example

<!--- create the cfc --->

<cfset bufferObj=createObject("component","buffer").init()>

<!--- clear the buffer --->

<cfset bufferObj.clear()>

<!--- output some text --->

Lorem ipsum dolor sit amet, consectetuer adipiscing elit.

<!--- cut the text from the output buffer --->

<cfset bufferObj.cut("firstBit")>

<!--- output some more text --->

Lorem Ipsum is simply dummy text of the printing and typesetting industry.

<!--- cut the text from the output buffer --->

<cfset bufferObj.cut("secondBit")>

<!--- Retrieve the "secondBit" from the cfc, bold all the e characters, update the cfc data--->

<cfset tmpText=bufferObj.get("secondBit")>

<cfset tmpTextp=replace(tmpText,"e","<strong>e</strong>","all")>

<cfset bufferObj.put(tmpText,"secondBit")>

<!--- Paste secondBit and firstBit back into the stream - but in reverse order --->

<cfset bufferObj.paste("secondBit")>

<cfset bufferObj.paste("firstBit")>

1 comment:

Dave said...

Incidentally, if anybody knows of a handy file hosting thingy I can integrate here that would be dead useful...