When it comes to software development, there are only two rules that apply.
- There is no wrong way, as long as it works.
- There is ALWAYS a better way.
May 29th, 2009 — Software Development
When it comes to software development, there are only two rules that apply.
March 1st, 2009 — jQuery
A really nice way to enhance user experience, when working with HTML forms, is to “highlight” the background color of the element that contains the form field that has focus. With jQuery, this can be achieved very easily using its event handlers and :input filter. What makes this approach very convenient is that you don’t have to modify any HTML to enable this functionality. Click the image below to see the example:
Javascript:
$(document).ready(function() {
$(':input:not([type="submit"])').each(function() {
$(this).focus(function() {
$(this).parent().addClass('formFieldFocus');
}).blur(function() {
$(this).parent().removeClass('formFieldFocus');});
});
});
HTML:
<div> <label for="text_field">Text</label> <input type="text" id="text_field" name="some_text" /> </div>
January 24th, 2009 — Flex
Michael Schultz asks:
Can I update a DataGrid based on data captured from within a Map’s InfoWindow?
The answer is yes and it’s surprisingly easy. Click the image to view the example. The source can be viewed by right clicking the flex application.
To accomplish this, you’ll have to think about what you need to make this happen:
When you click on the map to add a marker, the following objects are created:
//marker object var marker:Marker = new Marker(e.latLng); //value object that represents the person var personInfo:PersonVO = new PersonVO(); //custom view component for the marker's info window var nameInput:NameInput = new NameInput();
You then have to pass the personInfo object to nameInput, which is the custom component for the marker’s info window:
//pass a reference of the person object to the info window's custom component nameInput.setPersonInfo(personInfo);
Then:
//append data to the array collection
acMarkers.addItem({label: label, marker: marker, personInfo:personInfo});
//add event listenter for when the marker is clicked
marker.addEventListener(MapMouseEvent.CLICK, function(e:Event):void {
//open info widow
marker.openInfoWindow(new InfoWindowOptions({customContent:nameInput, width:300, drawDefaultFrame:true}));
});
//add maker overlay to the map
map.addOverlay(marker);
When you update a name in the marker’s info window, it appears in the data grid. How does this happen?
When you set the data grid’s dataProvider attribute, you’re simply passing a reference to an already existing array collection. When the array collection is updated, the change is reflected in the data grid, but only because our array collection is bindable.
Each time a marker is created, a value object called personInfo is created from a bindable class called PersonVO. This object is then added to: 1) the array collection that populates the data grid and 2) the component (nameInput) that makes up the content of marker’s info window. Neither the array collection nor the component actually hold instances of personInfo; what they do is reference it - they only contain pointers to its location in memory. Since it’s bindable, when changes occur to this object, those changes are reflected everywhere it’s referenced. Thus, when you update a person’s name from the info window, the change occurs in the data grid because it references the same location in memory.
January 24th, 2009 — JavaScript
I’ve written a function, with MooTools, that will inject inline messages into a form. View the example.
function showErrorMessage(field, errorMessage) {
var fieldGroup = $(field).getParent(); //form field's parent element
var errorElement = new Element('div');//error message element
if (!fieldGroup.getFirst().hasClass('errorMessage')) {
//add error message to error message element
errorElement.appendText(errorMessage);
//add class to error message element
errorElement.addClass('errorMessage');
// add class to the form field's parent element
fieldGroup.addClass('error');
//inject error message into form field's parent
errorElement.inject(fieldGroup, 'top');
}
}
This function, showErrorMessage(), can be used with either client-side or server-side validation.
If you’re using showErrorMessage() with client-side validation, there is a companion hideErrorMessage() function you can use for when validation passes.
function hideErrorMessage(field) {
var fieldGroup = $(field).getParent(); //form field's parent element
var errorElement = '';
if (fieldGroup.getFirst().hasClass('errorMessage')) {
errorElement = fieldGroup.getFirst();//error message element
//destroy error message element
errorElement.destroy();
//remove class from form field's parent
fieldGroup.removeClass('error');
}
}
January 11th, 2009 — ColdFusion
Have you ever wanted to stay away from using mixed mode authentication in SQL Server 2005, but were told that you had to enable for SQL Server to work with ColdFusion? Forget what you’ve been told! You actually can use windows/integrated authentication with ColdFusion and SQL Server 2005. Please be reminded that ColdFusion must be running on windows for this to work.
The following shows how to enable this on a CF single server installation. If you are running ColdFusion 8 Enterprise on a mulit-server installation, please be aware that your folder paths *will* be different.
<!–more–>
Step 1- Download the JDBC driver.
Download the SQL Server 2005 JDBC driver and extract it.
Step 2 - Place the files on the server.
There are two files you want to place on the server. The first file is the JDBC driver. It’ll be located at extracted_folder\sqljdbc_1.2\enu\sqljdbc.jar. You’ll want to put this somewhere on the server. I’ve placed mine in the following location - C:\ColdFusion8\lib\thirdpartytools\JDBC\SQLSERVER2005\1.2\.
The second file you’ll want to place on your server is called sqljdbc_auth.dll. This file can be found in extracted_folder\sqljdbc_1.2\enu\auth\x86\sqljdbc_auth.dll (Please note that this folder path is platform specific). Put this file on your server in C:\WINDOWS\system32\. This is the library that the JDBC driver uses to perform integrated authentication.
Step 3 - Add the JDBC class path to ColdFusion
You will be reminded to restart ColdFusion for the changes to take effect. You’ll want to actually reboot your server since we placed the sqljdbc_aut.dll file in C:\WINDOWS\system32\.
Step 4 - Add a user to SQL Server.
The user you’ll want to use for authentication will be the user that the ColdFusion service runs under. By default, ColdFusion runs under the Local System account (you or your system administrator may have changed this). While whether or not this is the best account for CF to run under is up for debate, you can still use it to authenticate to SQL Server as long as it’s the account that ColdFusion is running under. The use this account, the user you’ll want to specify is in the format of DOMAIN\SERVERNAME$ - make sure you use the $ on the end. Obviously, Windows performs some magic on the backend to map this to the Local System account for the server you’re authenticating from.
Step 5 - Add a datasource to ColdFusion.
You should now be done and have a successful connection.
January 11th, 2009 — Flex
private function createButtonEventListeners():void
{
btnContinue.addEventListener(MouseEvent.CLICK, processForm);
btnCancel.addEventListener(MouseEvent.CLICK, cancelForm);
}
January 11th, 2009 — ColdFusion
Have you ever looped through a large amount of records only to insert them into a dabase table? Something similar to this?
<cfloop query=“routing_numbers”> <cfquery datasource=“routing_numbers”> INSERT INTO routing_numbers (routing_number, customer_name) VALUES (#routing_numbers.routing_number#, ‘#routing_numbers.customer_name#‘) </cfquery> </cfloop>
I use the above code as part of a nightly scheduled task. It parses 20,000 records from a text file and inserts them into a database. It is slow. If you’re doing something similar, there’s a good chance you can increase the performance by 500% or more by wrapping your INSERT loop inside a <CFTRANSACTION> block.
<cftransaction isolation=“serializable” action=“begin”> <cftry> <cfloop query=“routing_numbers”> <cfquery datasource=“routing_numbers”> INSERT INTO routing_numbers (routing_number, customer_name) VALUES (#routing_numbers.routing_number#, ‘#routing_numbers.customer_name#‘) </cfquery> </cfloop> <cfcatch type=“database”> <cftransaction action=“rollback”/> </cfcatch> </cftry> <cftransaction action=“commit” /> </cftransaction>
Please note that the <cftransaction action=”commit” /> on the end is optional, depending on your RDBMS. Some require it, some don’t, so please check your documentation.
What’s the difference?
In the first code example, an implicit transaction is performed with each insert. That’s a lot of transactions for a redundant task and takes a lot of time as the DB opens the data file, inserts a record, and then closes it.
In the second example, there is no longer an implicit transaction with each INSERT. All the INSERT statements are grouped together in a single transaction. Thus, the data file only has to be opened and closed once.
January 11th, 2009 — ColdFusion
I recently worked on an application where I needed to display the name of the bank after a user entered their bank’s routing number. After some googling, I found a couple vendors who offered products. One offered a packaged database of routing numbers. This is no good as the list of numbers is dynamic and can change frequently. Another vendor offered an API-ish XML feed of routing numbers for a small fee. I didn’t like either one of these options.
Our financial institution pointed us in the direction of a downloadable text file of routing number provided by Federal Reserve Financial Services at no charge.
I decided to write a ColdFusion component to dowload and parse out bank routing numbers and their data and place them into and return a query object. The CFC is available on RIAForge at http://routingnumberscfc.riaforge.org/.
Since the file is so large and takes a considerable amount of time for the server to download and parse, I utilize the CFC as part of a scheduled task that loops through and stores the data returned from the CFC’s findAll() function into a database. In my application, I then simply just query against the data in the database.
January 10th, 2009 — Flex
If you’re using a ComboBox, and want to make sure the user has selected an item in the list, you can peform a quick and dirty validation with Flex’s NumberValidator. This is under the assumption that you do not want to allow the first item in the list to be a legitimate selection.
The idea is that you validate against the ComboBox’s selectedIndex property. The default selection will set selectedIndex to 0. If a different value is selected in the ComboxBox, selectedIndex will change to represent the numerical position of the value in the list. By using NumberValidator to validate against selectedIndex and not allowing a value less than 1, we know that the default selection will always be invalid.
<mx:Script>
<![CDATA[
import mx.controls.Alert;
]]>
</mx:Script>></code>
<mx:Array id=”colors”>
<mx:String>Select…</mx:String>
<mx:String>Blue</mx:String>
<mx:String>Red</mx:String>
<mx:String>Green</mx:String>
<mx:String>Orange</mx:String>
<mx:String>Black</mx:String>
</mx:Array>
<mx:NumberValidator
id=”vColor”
trigger=”{btnValidate}”
triggerEvent=”click”
minValue=”1";
lowerThanMinError=”Please select a color.”
source=”{color}”
property=”selectedIndex”
invalid=”Alert.show(vColor.lowerThanMinError)”
valid=”Alert.show(’Congratulations! You selected a color.’)”/>
<mx:VBox>
<mx:ComboBox id=”color” dataProvider=”{colors}”/>
<mx:Button id=”btnValidate” label=”Validate”/>
</mx:VBox>