Wednesday, March 11, 2009

Title Attributes in Anchor Tags

Here's a random thought. I wish browsers would automatically add missing title attributes to anchor tags.

<a href="google.com">Google</a> becomes <a href="google.com" title="Google">Google</a>

Also, just to clear up some confusion, it's a title attribute, not a title tag. A <title> tag goes in the document <head> and specifies the title of the entire document.

Getting Real

Just in case anybody hasn't read it yet, I recommend Getting Real by 37Signals.

Their blog is a good read too, especially the design decisions.

Thursday, March 5, 2009

Remote Component Variable Injection: Now with Method Replacement!

So I woke up this morning and realized you that since you're able to modify variables outside a component, you should be able to modify methods as well. Here's the updated code that proves it.

Application.cfc

<cfcomponent output="false">

<cfset this.name = "moodswing" />

<cffunction name="onApplicationStart">

<cfset application.person = createObject("component","person").init("sad") />
<cfset application.moodswing = createObject("component","moodswing") />

</cffunction>

<cffunction name="onRequestStart">

<cfif StructKeyExists(url,"init")>
<cfset onApplicationStart() />
</cfif>

</cffunction>

</cfcomponent>


person.cfc

<cfcomponent>

<cffunction name="init" returntype="any">
<cfargument name="mood" required="true" type="string" />

<cfset variables.mood = arguments.mood />

<cfreturn this />

</cffunction>

<cffunction name="getMood" returntype="string">

<cfreturn variables.mood />

</cffunction>

</cfcomponent>


moodswing.cfc

<cfcomponent output="false">

<cffunction name="getHappy" returntype="void">

<cfset application.person.changeVariable = changeVariable />

<cfset application.person.changeVariable("mood","happy") />

<cfset StructDelete(application.person,"changeVariable") />

</cffunction>

<cffunction name="getMad" returntype="void">

<cfset application.person.changeFunction = changeFunction />

<cfset application.person.changeFunction("getMood",getMood) />

<cfset StructDelete(application.person,"changeFunction") />

</cffunction>

<cffunction name="changeVariable" returntype="void">
<cfargument name="key" required="true" />
<cfargument name="value" required="true" />

<cfset variables[arguments.key] = arguments.value />

</cffunction>

<cffunction name="changeFunction" returntype="void">
<cfargument name="key" required="true" />
<cfargument name="value" required="true" />

<cfset this[arguments.key] = arguments.value />

</cffunction>

<cffunction name="getMood" returntype="string">

<cfreturn "mad!!!" />

</cffunction>

</cfcomponent>


default.cfm

<cfoutput>
Current mood: #application.person.getMood()# <br />

#application.moodswing.getHappy()#

<br />
After mood swing: #application.person.getMood()# <br />

#application.moodswing.getMad()#

<br />
After another mood swing: #application.person.getMood()# <br />
</cfoutput>


Again, if you run the above code, you should end up with something like this:

Current mood: sad

After mood swing: happy

After another mood swing: mad!!!


And yes, waking up and immediately thinking about this stuff does make me a huge nerd.

Wednesday, March 4, 2009

Remote Component Variable Injection

While working on creating my own extension of ColdSpring's BeanFactory, I discovered a little trick that allowed me to inject and modify variables in a component without the use of public getters or setters. While it came in pretty handy for what I was doing, I think it might be a little too powerful. I've created a simple example to show what I'm talking about.

Application.cfc:

<cfcomponent output="false">

<cfset this.name = "moodswing" />

<cffunction name="onApplicationStart">

<cfset application.happy = createObject("component","mood").init("happy") />
<cfset application.sad = createObject("component","mood").init("sad") />
<cfset application.moodswing = createObject("component","moodswing") />

</cffunction>

<cffunction name="onRequestStart">

<cfif StructKeyExists(url,"init")>
<cfset onApplicationStart() />
</cfif>

</cffunction>

</cfcomponent>


mood.cfc:

<cfcomponent>

<cffunction name="init" returntype="any">
<cfargument name="mood" required="true" type="string" />

<cfset variables.mood = arguments.mood />

<cfreturn this />

</cffunction>

<cffunction name="currentMood" returntype="string">

<cfreturn variables.mood />

</cffunction>

</cfcomponent>


moodswing.cfc:


<cfcomponent output="false">

<cffunction name="changeMood" returntype="void">

<cfset application.sad.changeVariable = changeVariable />

<cfset application.sad.changeVariable("mood",application.happy.currentMood()) />

<cfset StructDelete(application.sad,"changeVariable") />

</cffunction>

<cffunction name="changeVariable" returntype="void">
<cfargument name="key" required="true" />
<cfargument name="value" required="true" />

<cfset variables[arguments.key] = arguments.value />

</cffunction>

</cfcomponent>


default.cfm:

<cfoutput>
Before mood swing:<br />
happy: #application.happy.currentMood()# <br />
sad: #application.sad.currentMood()#<br />

#application.moodswing.changeMood()#

<br />
After mood swing:<br />
happy: #application.happy.currentMood()# <br />
sad: #application.sad.currentMood()#<br />
</cfoutput>


The code doesn't do a whole lot. I create a happy mood and a sad mood on the application page, as well as a moodswing object. Then I output the current mood of each of the objects, before and after a moodswing.

If you run the above code, you'll get something that looks like this:

Before mood swing:
happy: happy
sad: sad

After mood swing:
happy: happy
sad: happy


If you look at the moodswing object, it's copying a reference to a function into the sad object that allows me to directly access the sad object's variables scope, which lets me change the "mood" variable from "sad" to "happy".

Again, I'm not sure how great of a feature this is since it completely breaks encapsulation, but I thought it was worth mentioning.

Sunday, March 1, 2009

Balsamiq Mockups

Balsamiq Mockups is an awesome tool for web design and development.

http://www.balsamiq.com/products/mockups