November 21, 2008

Pages


Search Site


Topics



Archives

Tweets

Windows Tip: No to All

September 20 2008 by Adam

Everyone agrees that Microsoft is not the really best when it comes to usability, right?

We've probably all looked at this dialogue at some point during our lives and said, "How about a No to All button, Microsoft?"

No To All, where are you?

But did you know it's possible? Hold the shift key while you click the "No" button, and Windows will act as if there were a "No to All" button and you clicked it.

You're welcome.

Posted in Misc | 4 comments

Ask a Grokker: Why can't I activate an inactive Plugin in Mango?

September 15 2008 by Adam

Hey, everyone else is doing it. Why not me?

Mark asks,

I have been getting a lot of comment spam on one of my mango installs. I took a look and the captcha is not showing up anymore. The plug in's page says it's deactivated, however trying to activate it says it's already active? Have you see this before?

In fact, I have seen this before. I'm not sure what causes it, but what happens is somehow one of Mango's preferences files gets out of sync. Luckily, it's fairly easy to fix.

Open up the file pluginprefs.cfm, which should be in the root of your Mango install. Look (or search) for:

<entry key="userPlugins" ...

…and take a look at the value. There, you'll find the plugin listed that you're having difficulty activating. Remove it from the list, save the file, and try again to activate the plugin. In this case, the value to remove is "LylaCaptcha", as this is the plugin that can't be activated.

Posted in Ask a Grokker | Mango | 0 comments

ColdSpring 1.2 released, website updated

September 12 2008 by Adam

Along with the long awaited 1.2 release of ColdSpring, the worlds best CFC IoC/AOP framework has a brand spanking new website, which looks great; and includes a total overhaul of the online documentation.

Congratulations to Chris Scott — manager of the Philadelphia CFUG, and project lead for ColdSpring — and the rest of the ColdSpring team. Looks like a job well done!

Posted in Frameworks | 0 comments

Related Entries plugin for Mango Blog

September 10 2008 by Adam

This plugin has been a long time in the making. It's something I knew from the outset that I would want in Mango, but after getting my feet wet by writing a few other small plugins, I knew I could do it. I made it as simple as I could, but there are still a couple of things you will need to know; one of which is that you might need to modify your theme to broadcast a new event in a couple of places. This new event is going to be a part of future versions of Mango, so there isn't any worry about future-compatability and worries when upgrading.

First of all, though you need a small update to the core of Mango. Even if you've got the latest version of Mango (1.1)! Laura posted a comment on the plugin ideas page with a link to the update zip file, and an explanation that it included a new plugin (home page chooser), some core modifications that were needed to support that plugin, and most importantly, some bug fixes — one of which is necessary for back-linking of related entries to work correctly. So before you do anything else, make sure you grab and install that update!

Once you've got the Mango update installed, go ahead and download my Related Entries plugin.

Now about that event. It's really simple to add. Open up your theme's index.cfm and post.cfm files (and archives, and other places you may want to show related entries…). The code to broadcast the event is really simple:

<mango:Event name="beforePostContentEnd" />

Simple, right? And where do you put it? Anywhere, really… within reason. It uses contextual information to look up related entries data for the current post, so you must broadcast it inside of a (custom tag) block. So for example, here's the relevant information from my theme's index.cfm template:

<mango:Posts count="5">
<mango:Post>
...
<mango:Event name="beforePostContentEnd" />
<p class="date">Posted in ...</p>
...
</mango:Post>
</mango:Posts>

 

That's almost it! After you install the plugin, and add the event broadcast to your theme, there's just 2 more things.

First, relate a couple of entries. Edit a post, and look at the bottom of the form.

This new section should be displayed at or toward the bottom of the form. As it explains, you select a category from the left column to see its entries from the selected categories (use control to select multiple). Then click on any entries from the center column that you want to relate to the current entry; they will be displayed in the right column. (This is all done with jQuery ajax!) To remove an entry from the right column, double click it. When you submit the form, the posts in the right column will be marked as related to the current entry; and in addition to that, the current entry will be related to those posts.

When you submit the form, if you get an error that looks like this, then you didn't install the update!:

If you don't get the above error, then your data should be good to go. Now, you just need to style it.

When you've got related entries data, the event you're broadcasting is going to be replaced with some code along this line:

<div class="related">
<h2 id="RelatedEntries">Related Entries:</h2>
<ul>
<li><a href="http://server/post/your-post">Post Title</a></li>
<li><a href="http://server/post/your-post">Post Title</a></li>
<li><a href="http://server/post/your-post">Post Title</a></li>
</ul>
</div>

So, you can define some css rules for .related, #RelatedEntries (or .related h2), and .related ul, .related ul li, .related ul li a.

That's it. Enjoy!

One note for the future: The update I talk about above should be included in Mango 1.2, so if you've got 1.2 (or later) installed, don't worry about the update.

In case you missed the link before, you can Download my Related Entries Mango Blog Plugin right here.

Posted in AJAX | ColdFusion | JavaScript | My projects | Mango | 7 comments

Tracking the storm… Redux

September 06 2008 by Adam

A couple of days ago I used Rays code for tracking hurricane distance from your local zip code to add tracking of Hurricane Hanna to my family blog. Then my father in law was kind enough to point out that it was wrong. Way wrong! It was reporting distances of over 3,000 miles, when we're really less than 300 miles from it.

Closer inspection of the code showed that Ray accidentally swapped the order of latitude and longitude assignments from the NHC feed; and wasn't accounting for Southern and Western hemispheres being represented as a negative number. Ray posted about some changes he made in a comment on his post to fix these problems (if only I had seen those before now!).

Ray is going to post his updated script soon, but mine is below.

In addition to the same fixes, I've added a touch of encapsulation (though I did remove the zip lookup stuff once I knew the lat/long for my zip — because this was easily the slowest part of the whole script) and setup caching with a forced refresh, and refreshing if the previous attempt had any problems. Here's my entire script:

<!--- catch previous hit found no data --->
<cfif structKeyExists(application, "hannaData") and findNoCase("check back later", application.hannaData)>
   <cfset application.hannaData = getHannaData() />
   <cfset application.hannaDataUpdated = now() />   
</cfif>
<!--- allow force cache refresh --->
<cfif structKeyExists(url, "updateHanna")>
   <cfset application.hannaData = getHannaData() />
   <cfset application.hannaDataUpdated = now() />   
</cfif>
<!--- catch first hit of application lifecycle --->
<cfif not structKeyExists(application, "hannaData") or not structKeyExists(application, "hannaData")>
   <cfset application.hannaData = getHannaData() />
   <cfset application.hannaDataUpdated = now() />   
</cfif>
<!--- catch cache outdated --->
<cfif structKeyExists(application, "hannaDataUpdated") and dateCompare(now(), application.hannaDataUpdated, "n") gt 10>
   <cfset application.hannaData = getHannaData() />
   <cfset application.hannaDataUpdated = now() />   
</cfif>

<cfoutput>
   #application.hannaData#<br/>
   <small><em>Updated: #timeFormat(application.hannaDataUpdated, "h:MM tt")#</em></small>
</cfoutput>

<cfscript>
/**
* Calculates the distance between two latitudes and longitudes.
* This funciton uses forumlae from Ed Williams Aviation Foundry website at http://williams.best.vwh.net/avform.htm.
*
* @param lat1     Latitude of the first point in degrees. (Required)
* @param lon1     Longitude of the first point in degrees. (Required)
* @param lat2     Latitude of the second point in degrees. (Required)
* @param lon2     Longitude of the second point in degrees. (Required)
* @param units     Unit to return distance in. Options are: km (kilometers), sm (statute miles), nm (nautical miles), or radians. (Required)
* @return Returns a number or an error string.
* @author Tom Nunamaker (&#116;&#111;&#109;&#64;&#116;&#111;&#115;&#104;&#111;&#112;&#46;&#99;&#111;&#109;)
* @version 1, May 14, 2002
*/
function LatLonDist(lat1,lon1,lat2,lon2,units)
{
   // Check to make sure latitutdes and longitudes are valid
   if(lat1 GT 90 OR lat1 LT -90 OR
      lon1 GT 180 OR lon1 LT -180 OR
      lat2 GT 90 OR lat2 LT -90 OR
      lon2 GT 280 OR lon2 LT -280) {
      Return ("Incorrect parameters");
   }

   lat1 = lat1 * pi()/180;
   lon1 = lon1 * pi()/180;
   lat2 = lat2 * pi()/180;
   lon2 = lon2 * pi()/180;
   UnitConverter = 1.150779448; //standard is statute miles
   if(units eq 'nm') {
      UnitConverter = 1.0;
   }

   if(units eq 'km') {
      UnitConverter = 1.852;
   }

   distance = 2*asin(sqr((sin((lat1-lat2)/2))^2 + cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)); //radians

   if(units neq 'radians'){
      distance = UnitConverter * 60 * distance * 180/pi();
   }

   Return (distance);
}
</cfscript>
<cffunction name="logit" output="false" returnType="void">
<cfargument name="str" type="string" required="true">
<cflog file="hurricane_hanna" text="#arguments.str#">
</cffunction>
<cffunction name="getHannaData" returntype="string" output="false">
   <cfset var dst = 0/>
   <cfset var long = 0/>
   <cfset var longdir = "" />
   <cfset var lat = 0/>
   <cfset var latdir = "" />
   <cfset var hannaXML = "http://www.nhc.noaa.gov/nhc_at3.xml">
   <cfset var results = "" />
   <cfset var match = "" />
   <cfset var regex = "" />
   <cfset var text = ""/>
   
   <cffeed source="#hannaXML#" query="results">
   
   <cfif not results.recordCount>
      <cfset logit("Error - no feed entries")>
      <cfreturn "Unable to track hurricane Hanna (no data provided), check back later." />
   </cfif>
   
   <!--- find "Public Advisory" --->
   <cfquery name="pa" dbtype="query" maxrows="1">
      select rsslink, content, title
      from results
      where title like '%HANNA Public Advisory Number%'
   </cfquery>
   
   <cfif not pa.recordCount>
      <cfset logit("Error - cound't find a matching entry")>
      <cfreturn "Couldn't find information on hurricane Hanna, check back later." />
   </cfif>
   
   <cfhttp url="#pa.rsslink#" result="results">
   <cfset text = results.fileContent>
   
   <!--- strip extra white space --->
   <cfset text = reReplace(text, "[\r\n]+", " ", "all")>
   
   <cfset regex = "CENTER OF TROPICAL STORM HANNA WAS LOCATED NEAR LATITUDE ([[:digit:]\.]+)[[:space:]]*([NORTH|SOUTH|EAST|WEST]+)...LONGITUDE ([[:digit:]\.]+)[[:space:]]*([NORTH|SOUTH|EAST|WEST]+)">
   
   <!--- now look for: THE CENTER OF TROPICAL STORM HANNA WAS LOCATED NEAR LATITUDE 19.1 NORTH...LONGITUDE 74.4 WEST --->
   <cfset match = reFind(regex, text, 1, true)>
   <cfif arrayLen(match.pos) is 5>
    <cfset lat = mid(text, match.pos[2], match.len[2])>
    <cfset latdir = mid(text, match.pos[3], match.len[3])>
    <cfset long = mid(text, match.pos[4], match.len[4])>
    <cfset longdir = mid(text, match.pos[5], match.len[5])>
    <cfif longdir eq "WEST"><cfset long = -1 * long /></cfif>
    <cfif latdir eq "SOUTH"><cfset lat = -1 * lat /></cfif>
   <cfelse>
    <cfset logit("Error - couldn't find my matches in the string")>
      <cfreturn "Couldn't find lat/long location info for hurricane Hanna, check back later." />
   </cfif>

   <cfset dst = latLonDist(lat,long,39.98,-75.82,"sm")>
   
   <cfset logit("distance:" & dst)>
   <cfset rtn = "" />
   <cfset rtn &= "<strong>Distance:</strong> " & numberFormat(dst,',9.99') & " miles<br /><small>As of: <a " />
   <cfset rtn &= "href='" />
   <cfset rtn &= pa.rsslink />
   <cfset rtn &= "'><strong>#replaceNoCase(pa.title, 'Tropical Storm HANNA Public ', '')#</strong></a><br />" />
   <cfset rtn &= "Hanna Lat: #lat# #latdir#<br />Hanna Long: #long# #longdir#</small>" />
   <cfreturn rtn />
</cffunction>

Posted in ColdFusion | 1 comments