27 Jan 2014

PostCode Anywhere, JSONP and IE7 Cross Domain problems

First off, let me say that I like Postcode Anywhere (PCA), they're a great service.

Today I had to fix a bug with a site using PCA's Bank Account Validation. It was working great generally, but failing for IE7.

IE7! The bane of my life! It doesn't use CORS, doesn't even use IE8's crappy XDomainRequest object. It just plain can't make an AJAX call to an endpoint on a different domain.

This was why the PCA ajax call was failing. I figured the only solution was to use JSONP. However the PCA JSONP docs seemed scant. I couldn't get a JSONP call to work until I got DevTools out and looked at what was being returned from PCA on the JSONP call - it was returning a nice javascript array OK but not wrapping it in a call to a callback function!

OK, here's the meat. To make a JSONP call on PCA, you need to provide an extra parameter to the call. I found this mentioned randomly on this page of the PCA site.

You can either supply CallBackVariable or CallBackFunction in the call querystring, and bob's yer uncle.

Here's my code to show you how I did it.



// Javascript for PCA Bank Lookup Demo
//
// Requires input fields on your page with the following IDs:
//   Bank_AccountNo, Bank_SortCode, Bank_Name, Bank_PayMethod
// For further details of the returned data from PCA, check the contents of the returned array
//  or RTFM here: http://www.postcodeanywhere.co.uk/support/webservices/BankAccountValidation/Interactive/Validate/v2/default.aspx

function LookupBankDetails() {

 var pcaLicenceKey = 'YOUR-KEY-HERE';

 // Note we don't specify HTTP or HTTPS, so it will use the protocol cuurently in play
 var serviceUrl = '//services.postcodeanywhere.co.uk/BankAccountValidation/Interactive/Validate/v2.00/json2.ws?Key=' + pcaLicenceKey;

 // Build the query string
 serviceUrl += '&CallBackFunction=LookupBankDetails_Callback';
 serviceUrl += '&AccountNumber=' + encodeURIComponent($('#Bank_AccountNo').val());
 serviceUrl += '&SortCode=' + encodeURIComponent($('#Bank_SortCode').val());

 $.ajax({
  url: serviceUrl,
  dataType: 'jsonp',
  type: 'GET',
  jsonpCallback: 'LookupBankDetails_Callback',
  error: function (error, data, type) {
   alert(data + ": " + type + "."); 
  }
 });
}

function LookupBankDetails_Callback(response) {

 if (response.length == 1 && typeof (response[0].Error) != "undefined") {
  // Show the error message
  alert(response[0].Description);
 }
 else {
  // Check if there were any items found
  if (response.length == 0)
   alert('Sorry, your bank\'s details could not be located');
  else {

   var jsonResult = response[0];

   if (!jsonResult.IsCorrect) {
    alert('Sorry, your bank\'s details could not be located');
   }
   else {
    $('#Bank_Name').val(jsonResult.Bank);
    $('#Bank_PayMethod').val(jsonResult.FasterPaymentsSupported ? 'Fast' : 'BACS');
   }
  }
 }
}

JQuery Conditional Validation (Yes, the official documentation sucks)

Venting! jQuery Validation is a great plugin but its documentation is crap! So much cool stuff is hidden away for want of decent docs. If enough of you agree with me, I might have to write some! Watch this space. 

Anyway, I just wanted to implement some conditional validation

i.e. MAKE INPUT 'A' REQUIRED ONLY IF INPUT 'B' HAS A VALUE

And so, given two inputs with IDs InputA and InputB, the code is:

    
$(function() {
 $('#YourForm').validate({
  rules: {
   InputA : { 
    required : '#InputB:filled'
   }
  }
 });
});

You can also do this inline in your form by using declarative syntax, which I have found bugger-all documenation on!
 
<input name="InputA" type="text" data-rule-required="#InputB:filled" />
<input name="InputB" id="InputB" type="text" />

Finally, when required status is dependent on something more complicated, you can throw in a function e.g.
 
$('#myForm').validate({
 rules: {
  InputA : {
        required: function (elem) {
              // InputA is required if InputB contains 'AmazingThingy'
              return $('#InputB').val() == 'AmazingThingy';
   }
  }
 }
});

8 Jan 2014

ADODB.Command error '800a0cc1' Item cannot be found in the collection corresponding to the requested name or ordinal.

If you get this error when you're doing classic ASP with an MS Access backend:

ADODB.Command error '800a0cc1' 
Item cannot be found in the collection corresponding to the requested name or ordinal.

And it doesn't make sense.... check that you haven't got that table open in Access. Doh! Stupid error message!
If I helped you out today, you can buy me a beer below. Cheers!