Thursday 23 July 2015

Semantic UI form validation on SalesForce

I spent a couple of hours trying to figure this out this morning so I though it would be worth documenting. When you use apex:inputText within SalesForce there are all sorts of extra stuff added to the id and name, as long as you use apex:outputLabels with the correct for and value values then all is gravy as the labels and inputs match. So markup like this:

<div class="two fields">
    <div class="eight wide field">
        <apex:outputLabel for="firstName" value="First Name"/>
        <apex:inputText value="{!firstName}" id="firstName"/>
    </div>
    <div class="eight wide field">
        <apex:outputLabel for="lastName" value="Last Name"/>
        <apex:inputText value="{!lastName}" id="lastName"/>
    </div>
</div>

Will produce this HTML:

<div class="two fields">
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:firstName">First Name</label>
        <input id="somePageName:someTemplate:someForm:firstName" type="text" name="somePageName:someTemplate:someForm:firstName"/>
    </div>
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:lastName">Last Name</label>
        <input id="somePageName:someTemplate:someForm:lastName" type="text" name="somePageName:someTemplate:someForm:lastName" />
    </div>
</div>

Which is cool for most things as, if you need to reference the field with jQuery you can use:

$("input[id$='firstName']")

Or in regular JavaScript:

document.querySelector("input[id$='firstName']")

But Semantic UI form validation matches against either the name, id or the data-validate attributes. I know from experience that, coming from doing lots of jQuery, I wanted to get the id and add that... perhaps using something like this:

document.querySelector("input[id$='firstName']").id

To pass the generated id to the validation rules for the identifier... don't go that route though, it'll only lead to madness!!!

Rather use the data-validate by adding html-data-validate to the apex:inputText. It's much more readable and will make things ever-so-much easier on you:

<div class="two fields">
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:firstName">First Name</label>
        <input id="somePageName:someTemplate:someForm:firstName" type="text" name="somePageName:someTemplate:someForm:firstName" html-data-validate="firstName"/>
    </div>
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:lastName">Last Name</label>
        <input id="somePageName:someTemplate:someForm:lastName" type="text" name="somePageName:someTemplate:someForm:lastName" html-data-validate="lastName"/>
    </div>
</div>

Really, it's much easier doing it this way and it will save you no end of headaches trying to remember the somePageName and someTemplate values.

Wednesday 15 July 2015

Testing JavaScript Switch and Object speeds

I've been sort-of anti switch for a while now, initially in terms of JavaScript after reading about a great alternative which uses an object of functions which meant I could create a variable with all my switch conditions in it and test that rather than falling through a switch control, but more latterly for PHP where a similar approach can be used.

Earlier this week I was casting my eye over someone else's code and I started waxing lyrical about alternatives to switch and re-wrote his code to do implement the alternative. He, quite rightly, asked if it was quicker than using a switch... which left me stumped. You see I'd looked at the elegance of the code rather than its efficiency, a question of style over substance, so last night I thought I'd work up some tests to see if it really was as slow as I feared:

// Recording Object
var times = {
    "switch": "",
    "object": ""
};

// Testing array
var a = ["0", "1", "2", "0", "1", "2", "0", "1", "2", "0", "1", "2", "0", "1", "2"];

// Switch test
var start_switch = new Date().getTime();
var return_switch = "";
for (var b = 0; b < 50000; ++b) {
    for (var x = 0; x < a.length; x++) {
        switch (a[x]) {
            case "2":
                return_switch += "two";
                break;
            case "1":
                return_switch += "one";
                break;
            default:
                return_switch += "zero";
                break;
        }
    }
}
var end_switch = new Date().getTime();
times["switch"] = end_switch - start_switch;

// Object test
var switch_replacement = {
    "1": function () {
        return "one";
    },
    "2": function () {
        return "two";
    }
};
var start_object = new Date().getTime();
var return_object = "";
for (var c = 0; c < 50000; ++c) {
    for (var y = 0; y < a.length; y++) {
        return_object += (switch_replacement[a[y]]) ? switch_replacement[a[y]]() : "zero";
    }
}
var end_object = new Date().getTime();
times.object = end_object - start_object;

// Results
alert(JSON.stringify(times));

Most of the time the object approach takes about a third again longer than the switch, though every-so-often the object is significantly quicker... though I'm at a loss for how to explain that. In terms of breaking the code down though, it is much more readable, so I think that I'll stick with it despite it being slightly slower.

Thursday 2 July 2015

Udemy's Aws Certified Developer Associate DynamoDB scripts

I've been plowing through this course from Udamy and enjoying it loads but I'm also aware that the AWS SDK for PHP has recently been updated. I cloned the files from GitHub but they failed, and failed silently.

After checking the errors with the judicious use of:

<?php
    // Find out what the issues are:
    ini_set('display_errors',1);
    ini_set('display_startup_errors',1);
    error_reporting(-1);
    // Rest of the code

I discovered that a version is now required and that a TimeZone is also wanted so I altered the code to include these requirements.

<?php
    // Find out what the issues are:
    ini_set('display_errors',1);
    ini_set('display_startup_errors',1);
    error_reporting(-1);

    // Date now needs to be set, which I guess is a good thing!
    date_default_timezone_set('Europe/London');
   
    require '/var/www/html/vendor/autoload.php';
    use Aws\DynamoDb\DynamoDbClient;
    
    $client = DynamoDbClient::factory(array(
        'region' => 'eu-west-1',  // replace with your desired region
        'version' => '2012-08-10' // Now needs a version
    ));
    // Rest of the code

However the waitUntilTableExists method was still causing issues so after a little research I changed it.

    // Rest of the code
    foreach($tableNames as $tableName) {
        echo "Waiting for table $tableName to be created." . PHP_EOL;
        $client->waitUntil('TableExists', array('TableName' => $tableName)); // Changed from v2
        echo "Table $tableName has been created." . PHP_EOL;
    }
?>

The script for loading data also required the version and TimeZone so I altered that as well. Adapted source available on GitHub and Pull Request submitted.