Search

Thursday, July 26, 2007

Prototype.js Add-ons

I came across some add-ons based on Prototype. Here a small list:

TableKit: http://www.millstream.com.au/view/code/tablekit
Create sortable, resizable and editable tables

Control Suite: http://livepipe.net/projects/control_suite/
From the website: "Collection of six high quality widgets and controls for Web 2.0 applications built using the Prototype JavaScript framework"

Tidbits: http://livepipe.net/projects/prototype_tidbits/
Odds and ends for the Prototype framework

Window: http://prototype-window.xilinus.com/
Resizable/model/skinnable overlay window.

LightWindow: http://stickmanlabs.com/lightwindow/
Skinnable overlay window with many possibilities

Tuesday, July 24, 2007

Execute JavaScript with cfSnippetExecutor

This might be a duh! for some but thought I'd blog about it anyway. You can execute JavaScript as well as CF with the cfSnippetExecutor. Here is an example:
<-- Create a textarea for the results to be displayed -->
<textarea id="results" cols="80"></textarea>
<script type="text/javascript">
var htmlString = "<span>test</span>";
// Replace the < and > with their safe counterparts
htmlString = htmlString.replace(/</g, "&amp;lt;");
htmlString = htmlString.replace(/>/g, "&amp;gt;");

// Display the results
document.getElementById('results').innerHTML = htmlString;
</script>
<--- Same code as above but in ColdFusion --->
<cfset html = "<span>test</span>" />
<cfset html = html.replaceall("<", "&amp;lt;") />
<cfset html = html.replaceall(">", "&amp;gt;") />
<cfoutput>
<textarea cols="80">#html#</textarea>
</cfoutput>

Gmail Type Loading Indicator Update

After Brian Love brought up different browsers in my previous post, I thought I'd see what it takes to make my example look exactly like Gmail's status in both IE and Firefox. Here is the updated CSS. It's been tested with Firefox, IE6 and IE7 at 800x600, 1024x768 and 1280x1024. It includes a special margin definition for IE.
<style type="text/css">
div#statusContainer {
 position: absolute;
 left: 0px;
 top: 0px;
 width: 100%;
 height: 10px;
}

div#statusMessageContainer {
 position: absolute;
 background-color: #cc4444;
 color: white;
 width: 60px;
 font-family: Arial, Helvetica, sans-serif;
 font-size: .8em;
 padding: 2px;
 right: 0px;
 margin-right: 15px;
}
</style>
<!--[if IE]>
<style type="text/css" media="all">
div#statusMessageContainer { margin-right: -20px; }
</style>
<![endif]-->

Monday, July 23, 2007

Using Query of Queries to Join Data from Different Sources

The current application I am working on has to have user security based on a employee's badge number. The badge number and the employee name are already stored in an external database (Syteline) which I can access through a SQL driver. When a new employee is added to the application, the application only needs to store the employee's badge number. Other associated data is also stored such as the role the user is in (admin, supervisor, etc.). The problem I ran into was that I needed to get all the data for each employee (badge, name and role). Query of queries to the rescue. With a little help from Ben Nadel (thank you!) here is how I joined both queries:
<!--- Get a list of existing users from the database --->
<cfset existingUsersList = GetUsersList() />

<!--- Get a list of users from Syteline but ignore the users
that already exist in the application --->
<cfquery name="sytelineUsersList" datasource="ECDSiteDB">
select  lcase(Fname) as FirstName,
   lcase(Lname) as LastName,
   ltrim(rtrim("Emp-Num")) as BadgeNumber
from  pub.employee
where    ltrim(rtrim("Emp-Num")) <> ''
   and
   ltrim(rtrim("Emp-Num")) in (#valuelist(existingUsersList.BadgeNumber)#)
order by LastName, FirstName
</cfquery>

<!--- Join the two queries to get the user's name, badge and role name
The existingUsersList.BadgeNumber needs to be cast as a varchar since it's stored as
an interger in the application's Users table --->
<cfquery name="usersList" dbtype="query">
select  FirstName, LastName,
   sytelineUsersList.BadgeNumber,
   existingUsersList.Name as RoleName
from  sytelineUsersList, existingUsersList
where  sytelineUsersList.BadgeNumber = cast(existingUsersList.BadgeNumber as varchar)
order by LastName, FirstName
</cfquery>

Using Reactor to Execute a Join Query

Let's say that you want to create a list of users with associated roles. You have a Users table and a Roles table defined in your database. The link between the two is the RoleID in the Users table that maps to the ID column in the Roles table. Your reactor.xml should have the following to defined the relationship between the Users and the Roles tables:
<object name="Users">
 <hasOne name="Roles">
  <relate from="RoleID" to="ID" />
 </hasOne>
</object>
Inside the users gateway object (UsersGatewaymssql.cfc for the MS SQL Server version) instead of doing this:
<cffunction name="GetUsersList" access="public" output="false" returntype="query">
 <cfset var usersList = 0 />

 <!--- Get a list of users from the database with their associated roles --->
 <cfquery name="usersList" datasource="#_getConfig().getDsn()#">
 select  u.BadgeNumber, r.RoleID, r.Name
 from  dbo.Users as u
    inner join
    dbo.Roles as r
    on
    u.RoleID = r.ID
 </cfquery>

 <cfreturn usersList />
</cffunction>
You define the function as:
<cffunction name="GetUsersList" access="public" output="false" returntype="query">
 <cfset var usersList = 0 />

 <!--- Create a reactor query --->
 <cfset query = this.createquery() />

 <!--- Join the users and the roles tables --->
 <cfset query.join('Users', 'Roles', 'Roles') />

 <!--- Execute the query --->
 <cfset usersList = this.getbyquery(query) />

 <cfreturn usersList />
</cffunction>

Friday, July 20, 2007

cfSnippetExecutor v0.1

How many time have you had to create ColdFusion pages in order to test some simple code. I have a dedicated virtual site to just test snippets. The directory is getting pretty full with random code files. The process so far has been: 1. Open the virtual site 2. Create an empty .cfm file 3. Write my code and save it 4. Go to the browser and run it Well, I'm tired of it! So here is an initial draft to remedy the tedious task of testing cf code snippets. I'm calling it "cfSnippetExecutor". You can download it at http://tech-cats.net/blog/downloads/coldFusion/cfSnippetExecutor.txt The idea is simple. Go to the cf page in your browser, paste in your code and hit "Run". The results of your code will be show up below. The only requirement is Prototype.js.
<cfsetting enablecfoutputonly="yes">
<!--- Setup default parameters and constants --->

<!--- Is this call to the page from javascript (Ajax) --->
<cfparam name="url.isAjaxCall" default="false" />
<cfparam name="url.testScript" default="" />

<cfoutput>
<!---
If this is an ajax call, get the tracking results trackingPageUrl specified above --->
<cfif url.isAjaxCall>
<cfif fileexists(expandpath('testInclude.cfm'))>
<cffile action="delete" file="#expandpath('testInclude.cfm')#" />
</cfif>

<cfsavecontent variable="testInclude">#url.testScript#</cfsavecontent>

<cfset testInclude = testInclude.replaceall("&lt;", "<") />
<cfset testInclude = testInclude.replaceall("&gt;", ">") />

<cffile action="write" file="#expandpath('testInclude.cfm')#" output="#testInclude#" />

<cfinclude template="./testInclude.cfm" />
<cfelse>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript" src="prototype.js"></script>
<style type="text/css">
div##statusContainer { position:absolute;left:0px;top:0px;width:100%;height:10px; }
div##statusMessageContainer { position:absolute;background-color:##000000;color:white;width:80px;font-family:Arial, Helvetica, sans-serif;padding:2px;left:0px;font-weight:700; }
</style>
</head>
<body>
<br /><br />
<!--- This is not an ajax call, so display a form --->
<form id="testForm" name="testForm" method="get">
<input type="hidden" id="isAjaxCall" name="isAjaxCall" value="true" />
<textarea name="testScript" cols="80" rows="10" id="testScript">
<cfset testVar = "yourmom" />
<cfdump var="#testVar#" />
</textarea>
<br />
<input type="submit" id="runScript" name="runScript" value="Run" />
<!-- Status container that will be shown message durring processing --->
<div id="statusContainer" style="display:none;">
<div id="statusMessageContainer">Loading...</div>
</div>
</form>
<br />
<!-- Results container that will be updated with the results of the tracking request --->
<div id="testResults"></div>
<script type="text/javascript">
Ajax.Responders.register({
onCreate: function() {
$('statusContainer').show();
},
onComplete: function() {
$('statusContainer').hide();
}
});

// Add an event observer to the form's submit
Event.observe(
'testForm',
'submit',
function(e){
GetResults('testForm', '#cgi.script_name#', 'testResults');
Event.stop(e);
}
);

/*
Function:  GetTrackingResults
Arguments:
  formID    string - the form id to be used in the request
  pageUrl    string - the page url to call for the results
  resultsContainer string - the container element to display the results in
Return Value: None
Description:
  Retrieves the contents of the results page with Ajax */
function GetResults(formID, pageUrl, resultsContainer)
{
var testScript = $('testScript').value.strip();

if (testScript != '') {
// Serialize the form parameters to pass them along as part of the form submission
var params = $(formID).serialize();

// Disable the form
$(formID).disable();

// Empty the contents of the results container
$(resultsContainer).update('');

// Make an ajax request with the 'get' method, passing it the serialized form
// and using 'ReportError' to show any errors
// and 'ProcessResults' to process the retrieved results
new Ajax.Updater(
 $(resultsContainer),
 pageUrl,
 {
 method: 'get',
 parameters: params,
 onFailure: function(request) { $(formID).enable(); },
 onSuccess: function() { $(formID).enable(); },
 evalScripts: true
 }
);
}
}

$('testScript').focus();
$('testScript').enable();
</script>
</body>
</html>
</cfif>
</cfoutput>
Download cfSnippetExecutor

Non-ColdFusion Document Security on Non-Shared Hosting

Inspired by the blog post by Ben Nadel about Simple Non-ColdFusion Document Security For Shared Hosting Environments, here is a simple solution for non-shared hosting (where you have control over IIS) 1. Setup a virtual directory in IIS 2. Go the the virtual directory properties and under the "main" tab click on the "Configuration" button 3. Add a application extension mapping for ".*" to be processed by the ColdFusion server: "C:\CFusionMX7\runtime\lib\wsconfig\1\jrun.dll" (or whatever your path to CF is) 4. Write some code in Application.cfc (or Application.cfm if you wish) to handle the security for each request.

Now all requests (html, doc, etc.) should be first handed to ColdFusion.

The pitfalls might be: 1. Not very scalable solution 2. Performance

Mega Keyboard Shortcuts List

Came across this list and I thought it was worth sharing:

Developer’s Alarm: 200+ Hotkeys To Boost Your Productivity

Enjoy!

Thursday, July 19, 2007

Prototype.js Show/Hide Element Gotcha

I like using Prototype.js since it's been around for a while and I already know most of it's methods. I mean to experiment with jQuery but have not gotten around it yet (a disclaimer for anybody meaning to flame me about using something else such as jQuery, mooTools or whatever else). Anyway, a consistent gotcha for me is showing hidden elements after a certain action on the page. Lets take for example my statusContainer from the Gmail Style Ajax Status Message post. I want the div to be hidden when the page loads. My two choices are: 1. Hide the div with JavaScript after the page has been loaded. With Prototype.js, I simply do:
$('statusContainer').hide();
or 2. Set the visibility style of the element to hidden:
<div style="visibility: hidden;" id="statusContainer"></div>
I don't really like the first method since I shouldn't need JavaScript to have the element hidden at first. That leaves me with the second choice. The gotcha is that when you try to use Prototype.js to show the element later with:
$('statusContainer').show();
nothing happens. Why not? Doh! I keep forgetting that internally Prototype.js (at least v1.5.1_rc2 and v1.5.1.1) uses the display style property instead of visibility. So the above second option should say:
<div style="display: none;" id="statusContainer"></div>
With that change, using Prototype.js works fine:
$('statusContainer').show();

Wednesday, July 18, 2007

Gmail Style Ajax Status Message

Here is some css with a test bed to mimic Gmail's loading indicator. Hopefully it will be useful to somebody.
<html>
<head>
<style type="text/css">
div#statusContainer {
 position: absolute;
 left: 0px;
 top: 0px;
 width: 100%;
 height: 10px;
}

div#statusMessageContainer {
 position: absolute;
 background-color: #000000;
 color: white;
 width: 80px;
 font-family: Arial, Helvetica, sans-serif;
 padding: 2px;
 left: 0px;
 font-weight: 700;
}
</style>
<script type="text/javascript">
function ToggleStatus() {
 var toggleButton = document.getElementById('toggleButton');

 if (document.getElementById('statusContainer').style.visibility == 'visible') {
  toggleButton.value = 'Show';
  document.getElementById('statusContainer').style.visibility = 'hidden';
 }
 else {
  toggleButton.value = 'Hide';
  document.getElementById('statusContainer').style.visibility = 'visible';
 }
}
</script>
</head>
<body>
<div id="statusContainer" style="visibility: hidden;">
 <div id="statusMessageContainer">Loading...</div>
</div>
<br />
<input type="button" id="toggleButton" name="toggleButton" onclick="ToggleStatus();" value="Show" />
</body>
</html>

Howto lock certain cells in Excel 2003

This is available elsewhere but I had to find it recently, so here it is for later reference:
  1. Select all cells by pressing Ctrl-A
  2. Go to "Format" menu and select cells
  3. Go to the last tab called "Protection" and uncheck the "Locked" checkbox
  4. Select the cells you want to lock (you can select multiple cells by holding Ctrl while click on each cell)
  5. Go to "Format" menu and select cells
  6. Go to the last tab called "Protection" and check the "Locked" checkbox
  7. Go to the "Tools" menu and under the "Protection" submenu select "Protect Sheet" and click "OK"

Tuesday, July 17, 2007

Prototype.js Ajax Responders Gotcha

I was trying to use the following ajax global responder to show/hide a status message container:
Ajax.Responders.register({
 onCreate: function() {
  $('statusContainer').show();
 },
 onComplete: function() {
  $('statusContainer').hide();
 }
});
However, I was calling the ajax updater as follows:
// Make the ajax request for the server content
new Ajax.Updater(
 $(this.resultsContainer),
 ajaxUrl,
 {
 method: 'get',
 onFailure: this.reportError.bindAsEventListener(this),
 onComplete: this.ShowContent.bindAsEventListener(this),
 evalScripts: true
 }
);
The issue was that the status container will show at the beginning of the ajax request but will never get hidden. Can you spot the error? The problem was that the onComplete function in my ajax request was "overriding" the onComplete function in the global ajax responder. So to make this work, simply change the "onComplete" function in the ajax call to "onSuccess". The final code is:
// Make the ajax request for the server content
new Ajax.Updater(
 $(this.resultsContainer),
 ajaxUrl,
 {
 method: 'get',
 onFailure: this.reportError.bindAsEventListener(this),
 onSuccess: this.ShowContent.bindAsEventListener(this),
 evalScripts: true
 }
);

Tuesday, July 03, 2007

Development Methodologies

Some interesting development methodologies:

Asshole Driven development (ADD)
Cognitive Dissonance development (CDD)
Cover Your Ass Engineering (CYAE)
Development By Denial (DBD)
Get Me Promoted Methodology (GMPM)

I got these from
scottberkun.com » Blog Archive » Asshole driven development

Which one does your company practice, he he.
// //]]>