Friday, May 25, 2012

Converting Letters in Phone Numbers to Their Corresponding Digits

In a recent post, I mentioned that the feature that allows a user to tap on a phone number in their smartphone web browser and dial that number doesn't work if the phone number contains letters.  Well, some of the phone numbers in the database tables I'm working with contain letters (usually to spell out building abbreviations) so I needed to convert those letters into the corresponding digits on American phones (apparently it's not an international standard).

Before writing my own function to do this, I did some Googling and was a bit surprised to find that while folks have written routines in CFML to strip out dashes and such, no one had really written (and then published) a routine for this task.  So here's mine:

(Shrug) Nothing fancy, but it works. If you need to do additional adjustments to the phone number (like I did), you can just add them to this function or put them in separate functions (which is probably better).

Sunday, May 20, 2012

Post-cf.Objective() Thoughts

Just got back home from cf.Objective().  During the plane trip home, I wrote down a few paragraphs about the sessions I attended that I'll share now before kicking back for the rest of the day:

  • Marc Esher's session on threads and concurrency was excellent.  If you implement or plan to implement concurrent code execution in your CFML applications, you need to look at the CFConcurrent library he developed (available on RIAForge and GitHub).  The library utilizes the Java Concurrency Framework (JCF) and makes it possible to return results/data from with a thread (something you can't do with <cfthread>), schedule/defer threaded actions, and set up "threading within threading."

  • Nathan Strutz provided so much information and so many examples of using LESS to manage and generate CSS that I missed a few things trying to take notes.  No worries, though: he put up everything from his presentation on GitHub, including a number of examples and demos that show you some best practices on how to add LESS compilation into your development and production workflow.  And not long after the session, Matt Gifford made his own contribution to the LESS toolset:  a CF Builder extension that lets you do the compiling within the IDE.

  • Curt Gratz's session on mocking covered the reasons why you should mock data and objects when you unit testing, then showed attendees how MockBox makes it easy to mock function calls and their results on the fly.  As someone still finding his way regarding unit testing, I found his one walkthrough on how to make sure you're always testing a single function, and not a parent or dependent function, very helpful.  And even though MockBox is part of the ColdBox family of projects, it can be run as a standalone product, so you can make it part of your unit testing strategy regardless of what framework you use.

  • Billy Cravens also did an excellent job with his session on authenticating users via social networks.  Adding Google, Facebook, and Twitter-based authentication to your site is really now just a matter of getting an API and private key for your site from those services and making use of the available.  His demo code, available on GitHub, shows examples for all three service providers within a simple application built with the FW/1 framework.

  • I attended Denard Springle's multi-factor authentication workflow session mostly out of curiosity, as it's not something I can really implement with my particular user base.  But he showed us his technique of securing URL and form variables submissions, which involves hashing the variable names and encypting the variable values.  That's something I've never seen anyone else do.  Slides from his demo that illustrate that technique are available from his collection of presentation slide decks (look for the "Multi-Factor Authentication" one).

  • A room for conducting ad-hoc discussions or coding sessions was provided, and I ended up hosting a half-hour session on CFML applications in higher education.  The seven or so of us described some of the applications we've worked on, and as I suspected there was quite a diversity of applications, mostly built in support of the administrative processes at our schools rather than the educational process itself.  But I did learn that a few of us use (or are in the process of implementing) the Jasig CAS single sign-on tool, and that there would be interest in having some kind of robust form/survey tool (possibly with plugins like one to handle online payments) that we could set up such that non-programmers could create what they needed from it.  The question was raised as to whether it would make sense to augment Mura CMS to create such a thing.  We didn't discuss or make any further plans beyond that, so whether the discussion will continue in some form (move further forward) online remains to be seen.

As my conclusion, I will say that the conference was excellent as always (hardly a unique opinion, I know).  I've been to cf.Objective() before (in 2008), but this was my first time attending at the current venue, which is the Nicolett Mall area of Minneapolis.  It's a very pedestrian-friendly area of the city, and with the near-perfect weather we had it was quite lively.  It gave us a lot of options for dining and socializing after the sessions, and being able to hang out with other members of the community is one of the great benefits of the conference.

Thursday, May 3, 2012

Simple Technique For Creating Multiple Twitter Bootstrap Popovers

One of the JavaScript/jQuery plugins that comes with Twitter Bootstrap is the Popover plugin, which lets you create windows of content that appear when you hover over or focus on a DOM element.  They behave like tool tips but are larger and better suited to support styled content.

As noted in the documentation, the title and content of an individual popover can be coded in one of three ways:  via HTML attributes within the DOM element that triggers the popover, by assiging text values to the title and content properties when applying popover functionality to the DOM element, or by assigning functions that return markup to those title and content properties.  Here's an example of the last of those options:

$("#pop1".popover(
    {
        title: getPopTitle(),
        content: getPopContent()
    }
);

function getPopTitle() {
    return "Title 1";
};
		
function getPopContent() {
    return "Content 1";
}

The page I was working on needed to have several popovers, and the popover content included styled text: paragraphs, bolded text, etc. I didn't want to have to put that content into HTML attributes or long string values, nor did I want to code several different invocations of the popover function.

So what I decided to do was to create hidden blocks of HTML to hold the popover content and associate each set of "content" (title and content) with a unique id:

<style>
    .popSourceBlock {
        display:none;
    }
</style>

<div id="pop1_content" class="popSourceBlock">
    <div class="popTitle">
        Title 1
    </div>
    <div class="popContent">
        <p>This is the content for the <strong>first</strong> popover.</p>
    </div>
</div>

<div id="pop2_content" class="popSourceBlock">
    <div class="popTitle">
        Title 2
    </div>
    <div class="popContent">
        <p>This is the content for the <strong>second</strong> popover.</p>
    </div>
</div>


Then I assigned ids to the DOM objects that would trigger the popups when hovered over and gave them a CSS class of "pop". I opted to use one of the icons provide by Bootstrap to trigger the various popovers:

<i id="pop1" class="icon-question-sign pop"></i>
...
<i id="pop2" class="icon-question-sign pop"></i>


Finally, I used jQuery's each() function to loop through all the DOM elements with a class of "pop", grab the id value and use that to locate the matching content to associate with each popover:

$(".pop").each(function() {
    var $pElem= $(this);
    $pElem.popover(
        {
          title: getPopTitle($pElem.attr("id")),
          content: getPopContent($pElem.attr("id"))
        }
    );
});
				
function getPopTitle(target) {
    return $("#" + target + "_content > div.popTitle").html();
};
		
function getPopContent(target) {
    return $("#" + target + "_content > div.popContent").html();
};

With this code in place, I can add new popovers by creating additional hidden HTML blocks and DOM elements with the "pop" CSS class and an id that follows the pattern I've established.

Another nice aspect to this is that, down the road, I could put the page with the HTML blocks in a directory where a web designer or even a client with some basic HTML skills could edit the content, and I could call that file into my page programmatically. So long as they didn't add new content blocks, they could tweak the wording of the content without having to call me to do it (assuming I can trust them not to mess up the HTML formatting).