Slow [Blogging] Start to the New Year

Slow [Blogging] Start to the New Year

I feel like a hamster on a treadwheel here at the beginning of 2011. Lots of activity, but my forward progress – at least, some days – leaves a lot to be desired.

Especially with regard to this blog.

Family and Work have kept me at bay these opening days of the year, but by gum I will be doing a post on how to get to your Facebook Fan Page’s Insights via Facebook Graph in the next few days, come hell or high water.

Or something.

Any way. What was I saying?

A Little Side Project I’m Working On

A Little Side Project I’m Working On

In addition to wrapping ongoing projects and coming up to speed on my new job, I’m also working on a few side projects.

Here is a screen shot of something I think is going to be pretty cool. Stay Tuned!

WeReward for Facebook
Big Time Bug in Facebook Connect for the iPhone

Big Time Bug in Facebook Connect for the iPhone

While working on a new app for a client in Orlando today, we uncovered a significant bug in the Facebook Connect classes from Facebook for the iPhone.

What’s the bug?

Well, if you’re one of the fortunate souls who have a FB user id larger than an int, FB Connect for the iPhone, as it comes from Facebook, will blow up.

Blow up REAL good.

Oh, it may authenticate. But just wait till you check the uid in the session.

HEY! It doesn’t match my real uid!

The big bug is this – the FB Connect code uses library methods meant for integer values… all the while preaching to everyone the importance of Facebook User IDs being 64 bit values; in other words, in Objective-C parlance, long longs.

Too bad, ’cause with FB Connect for iPhone what this turns out to be is “do as I say, not as I do.”

Here’s where the busted code exists in the FBConnect code, and what needs to be done to correct:

FBSession.m

in the -(void)save method, replace the line that has [defaults setInteger:uid] forKey:@"FBUserId"] with the following:

[defaults setObject:[NSString stringWithFormat:@"%qi", _uid] forKey:@"FBUserId"];

in the -(BOOL)resume method, replace the line that has FBUID uid = [defaults intForKey:@"FBUserId"] with the following:

long long uid = 0;
NSString * uidString = [defaults objectForKey:@"FBUserId"];
if (uidString!=nil) {
NSScanner* scanner = [NSScanner scannerWithString:uidString];
if([scanner scanLongLong:&uid] == YES) {}
}

For all the razzing I’m giving Facebook here, really the broken parts of the classes are centered around moving data in and out of the settings bundle. Yeah – the uid’s are integers – big ass integers, to be sure – but the int functions for the settings bundle are no good for long longs – you got to convert them into NSStrings, and then back to long long again (%qi in sprintf-speak) when using the bundle functions.

Hope this helps those of you trying to explain why your iPhone apps work most of the time with Facebook Connect.

Sometimes, it really isn’t you – it IS the software (with apologies to Nick Burns, the Computer Guy).

A Little House Cleaning

A Little House Cleaning

By way of general announcement, I will be removing all Facebook applications that I have written from our servers at the end of the month (December 2009).

Goodbye, LinkedIn Contacts.

Goodbye, Starbucks Near Me.

Goodbye, myGoogleReader.

I’ve made several good friends as a result of my work with Facebook applications.  And I have been engaged for lucrative app development by national brands as a result of these applciations – sometimes for platforms other than Facebook.

This year has seen a marked drop in the interest in the Facebook platform for anything other than games like Farmville, Mob Wars, and the like.

My interest is in finding ways to create useful business applications.

And for that, Facebook has simply not become a business market.  And it never will.

The last five (5) Facebook applications I developed were either “cause” marketing apps, or games.  All for very recognizable brands.  Nothing that would be considered remotely a business application.

And while these were great projects to work upon, I think there has to be something more useful that I can create.

But the Facebook platform isn’t the place where I will do it.

Facebook Connect, on the other hand, seems to be where all the useful types of application development and services are laying claim to their own slice of the social media sphere, outside the Facebook walled garden, while leveraging the social graph and identity of their Facebook presence.

Does this mean that I will stop creating Facebook applications, forever?

No.

But it does mean that as a primary focus for what I do, that ship has sailed – and now it’s on to new things.

New NHL All Star Game Facebook Application

New NHL All Star Game Facebook Application

Vote for your favorite Detroit Red Wing in the NHL All Star Fan Ballot
Vote for your favorite Detroit Red Wing in the NHL All Star Fan Ballot

I know, I know.  But business is business.

Facebook App Here and Voting Here.

LinkedIn Contacts

LinkedIn Contacts

My “twitterpal” Ruth Marie Sylte showed some love for my LinkedIn Contacts Facebook Application in her blog today.

Thanks, Ruth, for a very nice endorsement.

Facebook App Landgrab is Over

Facebook App Landgrab is Over

Custom FBML Dialogs in Facebook Apps

Custom FBML Dialogs in Facebook Apps

There are several examples around on doing custom Facebook dialogs, some which are satisfactory and some which are not. Here is some code that I use to create custom FB dialogs that I can position, color, style at will.

First, let’s look at the FBJS function to invoke a custom dialog. In this case, I have created a dialog that accepts Yes / No answers. By convention, I assume that I will define a dialog somewhere on my page named “question_dialog1”.

// Custom yes / no dialog that we can position
function showYesNoDialog(id, title, content, confirm, cancel) {
document.getElementById(id).setStyle("display", "inline");
if (confirm) {
document.getElementById('yes_button1').removeEventListener('click', confirm, false);
document.getElementById('yes_button1').addEventListener('click', confirm, false);
}
if (cancel) {
document.getElementById('no_button1').removeEventListener('click', cancel, false);
document.getElementById('no_button1').addEventListener('click', cancel, false);
}
document.getElementById("question_title1").setTextValue(title);
document.getElementById("question_content1").setTextValue(content);
}

The first thing I do is display my question dialog, which is initially styled {display: none;}.

Next, I attach a couple of click events – if present – to two buttons, yes and no, for confirmation and cancel (by convention, I use yes_button1 and no_button1, but you can certainly parameterize this or better yet encapsulate in a class).

Finally, I set Title Text and Content Text using the setTextValue method.

A typical call to this dialog might look like the following (I use the built-in FBJS Ajax object):

var yes = function() {
var ajax = new Ajax();
ajax.responseType = Ajax.FBML;
ajax.ondone = function(data) {
document.getElementById("delete_dialog1").setStyle("display", "none");
document.setLocation("http://apps.facebook.com/SomeApp/ThisPage.php");
}
ajax.onerror = function() {document.getElementById("delete_dialog1").setStyle("display", "none");}
newShowDialog("delete_dialog1");
ajax.post('http://apps.facebook.com/SomeApp/performDelete.php?fbid=' + <? echo $user; ?>;
}

showYesNoDialog("question_dialog1", "Delete Record?", "Delete \"" + argRecordDescription + "\"?", yes);

The actual FBML for the question_dialog1 looks something like the code below. You can style this anyway you want; I usually try to get my dialogs to look like the styling of the application to which the dialog belongs, but do whatever floats your boat here.

<div id="question_dialog1" style='display: none; position: absolute; top: 300px; left: 150px;'>
<table>
<tr>

<!-- Transparent border around dialog, like FB built in dialogs-->

<td style="background-image:url('http://app.facebook.com/SomeApp/Images/pop_dialog_border.png');">

<div style='border: 2px solid #8ec73c; background: white; font-size: 18pt; margin: 10px;'>
<div id='question_title1' style='background: white; padding: 2px; color: white; background: #8ec73c; font-weight: bold; font-size: small;'>Title Here...</div>
<div id='question_content1' style='font-weight: bold; font-size: 12pt; padding: 10px 30px 10px 30px; border-bottom: 1px solid #8ec73c;'>Dialog content will go here...</div>

<div style='background: white; text-align: right; padding: 10px; font-size: small; height: 20px;'>

<input id='yes_button1' type='button' value='Yes' onclick='document.getElementById("question_dialog1").setStyle("display", "none");' style='background: #8ec73c; color: white; width: 40px;' />

<input id='no_button1' type='button' value='No' onclick='document.getElementById("question_dialog1").setStyle("display", "none");' style='background: #8ec73c; color: white; width: 30px;' /></diV>
</div>

</td></tr>
</table>
</div>

Finally, a note to code nit-pickers: This example is meant to be illustrative and not a comprehensive way on how best to do Facebook dialogs or write FBJS.

Positioning a dialog on a Facebook Canvas Page

Positioning a dialog on a Facebook Canvas Page

As promised (or threatened) here is a post on some little Facebook development insight gained through some trial, error, blood, sweat, and yes tears.

A problem I was having was accurately determining the x, y position of a given control for popping up informational dialogs. Sure, it was easy enough to use the getAbsoluteTop and getAbsoluteLeft calls to get the absolute positioning (supposed), but after playing around with these calls it became apparent that “absolute” didn’t mean “absolute” in the sense that most web / windows developers would understand. It really is a relative offset – but to what?

After perusing the FBJS docs, and finding no mention of a viewport (which is really what I was trying to determine the offset from), I took a total flier and thought – “well, if I could jet get the root element of my document, and find ITS x and y, I should be home free.

Bingo. That was the trick. Use document.getRootElement() to get the container element.

The code below demonstrates the technique.

var argCtl = document.getElementById(“myForm”);
var newTop = argCtl.getAbsoluteTop();
var newLeft = argCtl.getAbsoluteLeft();
var scrollW = argCtl.getScrollWidth();
var root = document.getRootElement();
var cTop = root.getAbsoluteTop();
var cLeft = root.getAbsoluteLeft();

document.getElementById(“confirm_dialog1”).setStyle(“top”, (newTop – cTop) + “px”);
document.getElementById(“confirm_dialog1”).setStyle(“left”, (newLeft – cLeft) + “px”);

First, grab a reference to an object on the page that you wish to position relative to (in this case, I am using a form named “myForm”). Get its x and y coordinates.

Next, get the container x and y by getting its reference (document.getRootElement()) and then its x and y values (getAbsoluteTop and getAbsoluteLeft).

Finally, to accurately position a dialog where an element exists, take the difference between the container and the element being positioned:

document.getElementById(“confirm_dialog1”).setStyle(“top”, (newTop – cTop) + “px”);
document.getElementById(“confirm_dialog1”).setStyle(“left”, (newLeft – cLeft) + “px”);

Voila. You’ve just positioned a dialog over an element.

In practice, you would want some arbitrary additional offset from the control so that you don’t hide it when you pop up / display your dialog. I’ll leave that as an exercise for the reader.

Perspective and Vantage Point

Perspective and Vantage Point

I read a post this morning concerning OpenSocial and how Facebook was becoming like Microsoft, because they were “closed” and “not compatible” with the “emerging standard” of OpenSocial (as opposed to the “de facto” standard of Facebook).

First of all, if there is a dearth of OpenSocial apps (and there are) and if everyone is paying lip service but putting very few real dollars behind it, how in the hell is OpenSocial an “emerging standard?” If anything, it is a “hoped for” emerging standard for everyone kicking themselves for not being first mover in the market. By the time the OpenSocial folks get their act together, everyone will realize that it is NOT write once, run everywhere, but instead write fifty separate times to SAY you run everywhere – and of course the novelty of widgets long worn off and we’re off to the next thing.

The other thing that got my juices going was reading another blogger parroting the canard that Microsoft is not compatible with itself (probably wrote that on an Apple system, which makes the irony even more laughable). I bet Raymond Chen of MS would have something to say about how compatible MS has been over the years.

In fact, it can be argued that to its detriment MS has clung tenaciously to keeping its systems entirely backward compatible and has forced it to not recognize the right time to jettison old technologies and embrace the new world order (web, mobile, online TV, gaming – at least initially).

I can give a real world personal example of how well MS has kept consistent and compatible with itself. I wrote an MS-DOS C language (version 1 or 2 of the compiler – so long ago I forget) program that did electrical contractor estimating in 1987. It was used to estimate the “new” (at the time) Nashville airport terminal project for the prime contractor.

I wrote my own screen and form handling (replete with direct video memory writes) using the old Btrieve B-tree data handler (not database – schemas were for wusses back then). Pretty cool stuff for the time and fast as well.

Fast forward to 2006. I get a call from the contractor. HE WAS STILL USING THE ORIGINAL PROGRAM. He wanted me to add a few new features. I would have been glad to do so… except after almost 20 years I couldn’t find the original source. Long story short, the project was re-written as an MS Access application by a friend common to me and the customer.

Folks, that is an application that ran for nearly 20 years (!!!) without modification across multiple generations of MS operating systems. And almost spanned a generation of human life.

Look, Microsoft can be said to many things. Many bad things. Most of them true.

But please – if you say that they (Microsoft) are not consistent with themselves, that they break with each generation, you gotta do more than parrot the basement losers who have never held a paying job in their life. Because the fact of the matter is that most companies do a damn good job at remaining as backward compatible as they can to remain as profitable as they can for as long as they can.

I challenge anyone to show me an Apple application that has run continuously on whatever hardware is current at the time with no code changes from 1987 in a working production environment.

I really would like to see it, but I wouldn’t hold my breathe. These are the same guys, remember, that come out with a new iPod the minute you buy one; a new iMac with an OS that is not compatible with the old hardware. The makers of the Newton.

Disclaimer: I have owned both PCs and all generations of the iMac, have two iPhones, and a handful of iPods spanning all generations.

We tend to make ridiculous generalizations because we lack perspective or our vantage point is too close to the ground to see above the horizon (forward and backward pointing).

I’m not saying one’s point of view is only valid after years of experience (though there is much to be said about that assertion), nor am I saying that wisdom comes only with age (it doesn’t).

I am saying that before we make pronouncements about what is standard, what is reality, we should at least try to do a sanity check beyond the view of a couple of years, beyond the span of our echo chamber that is the social media / social graph / web two oh hype machine, beyond our personal knowledge.

Without context, continuity, and perspective all we are doing is generating is comedy. And it’s not even that funny.