Oh my god. It's full of code!

jQuery

Salesforce Orchestra CMS Controller Extensions

So I’ve been working with Orchestra CMS for Salesforce recently, and for those who end up having to use it, I have a few tips.

1) If you intend on using jQuery (a newer version than the one they include) include it, and put it in no conflict mode. Newer versions of jQuery will break the admin interface (mostly around trying to publish content) so you absolutely must put it in no conflict mode. This one took me a while to debug.

2) While not official supported, you can use controller extensions in your templates. However the class, and all contained methods MUST be global. If they are not, again you will break the admin interface. This was kind of obvious after the fact, but took me well over a week to stumble across how to fix it. The constructor for the extension takes a cms.CoreController object. As an alternative if you don’t want to mess with extensions what you can do is use the apex:include to include another page that has the controller set to whatever you want. the included page does not need to have the CMS controller as the primary controller, so you can do whatever you want there. I might actually recommend that approach as Orchestra’s official stance is that they do not support extensions, and even though I HAD it working, today I am noticing it act a little buggy (not able to add or save new content to a page).

3) Don’t be araid to use HTML component types in your pages (individual items derived from your page template) to call javascript functions stored in your template. In fact I found that you cannot call remoting functions from within an HTML component directly, but you can call a function which invokes a remoting function.

So if we combine the above techniques we’d have a controller that looks like this

global class DetailTemplateController
{
    global DetailTemplateController(cms.CoreController stdController) {

    }

    @remoteAction
    global static list<user> getUsers()
    {
        return [select id, name, title, FullPhotoUrl from user ];
    }
}

And your  template might then look something like this

<apex:page id="DetailOne" controller="cms.CoreController" standardStylesheets="false" showHeader="false" sidebar="false" extensions="DetailTemplateController" >
	<apex:composition template="{!page_template_reference}">
		<apex:define name="header"> 
			<link href="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.3/themes/smoothness/jquery-ui.min.css" rel='stylesheet' />

			<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
			<script> var jqNew = jQuery.noConflict();</script> 
			<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script> 

			<script>
        	        var website = new Object();
			jqNew( document ).ready(function() {
				console.log('jQuery loaded');
			});

			website.buildUserTable = function()
			{
				//remoting request
				Visualforce.remoting.Manager.invokeAction(
					'{!$RemoteAction.DetailTemplateController.getUsers}', 
					function(result, event){
						if (event.type === 'exception') 
						{
							console.log(event.message);
						} 
						else 
						{
							var cols = 0;

							var tbl = jqNew('#bioTable > tbody');
							var tr;
							for(var i = 0; i < result.length; i++)
							{
								if(cols == 0){tr = jqNew('<tr></tr>');}                              

								var td = jqNew('<td></td>');

								var img = jqNew('<img class="profilePhoto">');
								img.attr('src',result[i].FullPhotoUrl);
								img.attr('title',result[i].Title);
								img.attr('alt',result[i].Name);
								img.data("record", result[i]);
								img.attr('id',result[i].Id);

								td.append(img);

								tr.append(td);

								if(cols == 2 || i == result.length-1){
									tbl.append(tr);
									cols = -1;
								}
								cols++;

							}

						}
					})			
			}
			</script>
		</apex:define>
		<apex:define name="body">
			<div class="container" id="mainContainer">
				<div class="pageContent">
					<div id="header">
						<apex:include pageName="Header"/>
						<div id="pageTitle">
							<cms:Panel panelName="PageTitle" panelController="{!controller}" panelheight="50px" panelwidth="200px"/>
						</div>
					</div>
					<div id="pageBody">
						<p>
							<cms:Panel panelName="PageContentArea" panelController="{!controller}"  panelheight="200px" panelwidth="400px" />
						</p>
						<div class="clearfloat"></div>
					</div>

					<!-- end .content --> 
				</div>
			</div>
			<div id="footer_push"></div>
			<div id="footer">
				<apex:include pageName="Footer"/>
			</div>
		</apex:define>
	</apex:composition>
</apex:page>

Then in our page we can add an HTML content area and include

<table id="bioTable">
	<tbody></tbody>
</table>
<script>website.buildUserTable();</script>

So when that page loads it will draw that table and invoke the website.buildUserTable function. That function in turns calls the remoting method in our detailTemplateController extension that we created. The query runs, returns the user data, which is then used to create the rows of the table that are then appended to the #bioTable’s body. It’s a pretty slick approach that seems to work well for me. Your mileage may vary, but at least rest assured you can use your own version of javascript, and you can use controller extensions, which I wasn’t sure about when I started working it. Till next time.


Saltybot – A descent into salty, salty madness

*Article below was written pertaining to Saltybat as it was in September 2013, I have no idea the current standing of the website or if the techniques below are still applicable/required (looking now it seems that the fighter names are available right next to the bet buttons, so the whole needing an OCR scanner to extract the names is no longer required. Bummer that made me feel so smart too)

I. CAN’T. STOP. SALTYBETTING.

I don’t even care about the bucks, it’s about solving the problem. I know that somewhere in the chaos there is data that will allow me to get every bet correct and ‘solve’ the problem. But wait, let me back up a step. First, what the hell is Saltybet? It’s an online video feed of your favorite characters new and old fighting it out controlled by computer AI. You bet on the matches and get ‘saltybucks’ if you win based on a weighted odds system. Before they duke it out both characters stand on screen for about 45 seconds allowing you to consider whom to bet on. After that window betting closes the screen blanks out for a moment, then the fight begins. At that point all you can do is sit and watch (and bitch in the chat window). No you can’t do anything with the money and there is very little rhythm or reason to what makes a good character (one of the best, if not the best currently is an interpretation of Ronald McDonald). It’s pretty addictive to watch and I’ve been having a good time just keeping it on my spare monitor during my work day.

THEN

IT

HIT

ME

I could write a small program, just a little javascript bookmarklet that could take the names of the fighters and using past data tell me who is most likely to win. Hell maybe I could even automate some of it. Overcome with excitement I pushed the major technical challenges out of my mind so not to kill my motivation. I just wanted to try to see what I could do. So my last weeks obsession began.

The Bot

First off, I just got this working no more than like 45 minutes ago so I’m pretty excited about it. That does mean that though some of the code I show you and approaches I use may not be the best, as they are mostly just POC to see if my architecture works. I don’t intent to release this final product so it may never get totally cleaned up. That aside, please find below my decent into madness as I write one of the most complicated cobbled` together things I’ve ever even heard of.

I needed data. A lot of it. For an analytic engine you need data points. Thankfully if you are willing to pitch in a few bucks for server costs you get access to all the characters win loss record and access to the results of every match you have bet on. So not only could you calculate win percentage if you know who various characters won and lost against you could implement a rating system like they use in chess (ELO) or maybe even Glicko. The issue here though was that of course that data was not presented in any kind of API, it was just an HTML table. So the first challenge was trying to get that HTML data into some kind of actual data structure. After a little bit of ajax and jQuery magic I was able to convert the table into a javascript object keyed by the fighters name. I ran their name though a simple regex to remove spaces, make it lower case to make matching easier. I was making progress, now typing in the two fighters name would net me their win loss percents, which are powerful numbers but of course don’t tell the whole story (a person with a 1-0 record might have a 100% win loss, but that isn’t nearly as good someone with a 30-5 record even though they’d have a lower win percent).

Next up was trying to implement a real rating system. I know there are systems out there that could tell you the true strength of a player based on their previous matches and who they won and lost against. Chess ratings implement this kind of system as well as various competitive online games. I knew that something like that could go a long way toward getting me to real odds. The problem is that you can only see the record of who a fighter won and lost against if you bet on that match. There was no way I’d have time to sit around and bet on every match, nor did I want to. I knew I’d have to setup some kind of automated betting to just put in small bets for me to gather data while I was doing other things. First though, I wanted to get the rating system in place so as data came in I could see it affect the results of the equation. After some research and consideration I decided on the ELO system (mostly because I am a bit familiar with it, and its fairly easy to implement and I found some sample code so I didn’t have to write it myself XD ). The basic idea is that every character starts at a rating of 1200, then based on who they win or lose against their rating changes. The more matches they go through the higher the confidence of the result. The simple function for calculating the change in score looks like this.

function CalculateEloRatingChange(player1Score,player2Score,result,gamesPlayed) 
{ 

	var Elo1 = player1Score; 
	var Elo2 = player2Score; 
	var K = Math.round(800/gamesPlayed); 
	var EloDifference = Elo2 - Elo1; 
	var percentage = 1 / ( 1 + Math.pow( 10, EloDifference / 400 ) ); 
	var win = Math.round( K * ( 1 - percentage ) ); 
	var draw = Math.round( K * ( .5 - percentage ) ); 
	if (win > 0 ) win = "+" + win; 
	if (draw > 0 ) draw = "+" + draw; 

	if(result == 'win')
	{
		return parseInt(win,10);
	}
	else
	{
		return parseInt(Math.round( K * ( 0 - percentage ) ),10); 
	}
}

Like I said this was pulled from another source, so I’m not 100% certain on the logic used, but it seems solid and it’s been returning what seem to be reasonable numbers for me. So now all I had to do is pull the betting history table and iterate over it back start to finish, each time feeding the result of the match into this function and recording the new ELO score for that character. Of course since I only have access to the data for matches I have bet on, this is not perfect or absolute, but it is better than nothing and as I keep gathering more data it will just get more and more accurate (addendum: later on I started farming results from other players. Offering them access to the tool in exchange for their betting history which I could feed into my engine).

Now I was able to get a win percent and an ELO score. I was well on the way to having some meaningful data that could point me in the right direction. Both these facts left out something that I thought was pretty crucial though. If this EXACT matchup has happened before the results of that are likely to be repeated and should definitely be taken into consideration. So In the betting history I also decided to look to see if this same match had happened before. If so I initially just printed out a warning to my utility to let me know. I knew that that should have it’s own numerical meaning as well but I couldn’t find any formula like that online so i decided to brew my own. I really don’t have much a background in probability and stats or anything like that so I am really not sure about the weights that I assigned the various outcomes. Maybe someone with those skills could help me tweak this. Overall my scoring formula looks like this

function calculateProjectedWinner(player1Name,player2Name)
{
	//find players rating difference and record
	fighterCareers[player1Name].ratingDiff = fighterCareers[player1Name].eloScore - fighterCareers[player2Name].eloScore;
	fighterCareers[player2Name].ratingDiff = fighterCareers[player2Name].eloScore - fighterCareers[player1Name].eloScore;

	//calculate their win probabilities. The Elo system has it's own function for calculating win probability
	//based on scores, so I just use that as my 'baseline' probabilities. Then I modify it using my other data later on.
	fighterCareers[player1Name].eloWinProbability = parseInt(calculateEloWinOddsPercent(fighterCareers[player1Name].ratingDiff) * 100,10);
	fighterCareers[player2Name].eloWinProbability = parseInt(calculateEloWinOddsPercent(fighterCareers[player2Name].ratingDiff) * 100,10);

	//calculate custom their win probabilities starting at ELO
	fighterCareers[player1Name].computedWinProbability = fighterCareers[player1Name].eloWinProbability;
	fighterCareers[player2Name].computedWinProbability = fighterCareers[player2Name].eloWinProbability;

	//now we need to see if these two players have had any previous matches together. If so we iterate over them
	//and modify their win probabilities accordingly.
	var prevMatches = findPreviousMatch(player1Name,player2Name)		

	for(var i = 0; i < prevMatches.length; i++)
	{
		var winner = prevMatches[i].winner;
		var loser = prevMatches[i].loser;

		//we don't want to make their probability much higher than 95 because we can never be that sure and also
		//anything over 100 is totally meaningless. I decided a factor of 8 percent per win seems about decent. Maybe
		//it should be a little more? I don't know it's still something I'm kind of playing with. 
		if(fighterCareers[winner].computedWinProbability < .92)
		{
			fighterCareers[winner].computedWinProbability = fighterCareers[winner].computedWinProbability + 0.08;
		}
		if(fighterCareers[loser].computedWinProbability > .08)
		{
			fighterCareers[loser].computedWinProbability = fighterCareers[loser].computedWinProbability - 0.08;
		}
	}

	//their win loss percent can be a good statistic if it is composed of enough data points to be meaningful.
	//here is where I wish I had more prob and stats background because I really don't know how many matches it would
	//take for this percent to be actually significant. I'm guessing at 10, so I decided to go with that. If both chars
	//have more than 10 matches under their belt, then lets include their win loss percents in our calculation.
	if(fighterCareers[player1Name].total >= 10 && fighterCareers[player2Name].total >= 10)
	{
		//get the difference between the two win percents. So if we had p1 with 50 and p2 with 75 the difference is 25
		//yes I know ternaries are hard to read, but its cleaner than a stupid one line if statment. Just know that this
		//will return a positive amount that is the difference in win percent between the two.
		var winPercentDifference = fighterCareers[player1Name].winPercent > fighterCareers[player2Name].winPercent ? fighterCareers[player1Name].winPercent - fighterCareers[player2Name].winPercent : fighterCareers[player2Name].winPercent - fighterCareers[player1Name].winPercent;

		//multiple that difference by how confident we are (total number of matches) topping out at. So a number from 20 to 100
		var confidenceScore = fighterCareers[player1Name].total + fighterCareers[player2Name].total > 100 ? 100 : fighterCareers[player1Name].total + fighterCareers[player2Name].total;

		var adjustment = Math.round((winPercentDifference) * (confidenceScore/100)/2);

		//make the actual adjustments to the players probabilities
		console.log('Proposed modifying win perceny by +/- '+ adjustment);
		if(fighterCareers[player1Name].winPercent > fighterCareers[player2Name].winPercent)
		{
			fighterCareers[player1Name].computedWinProbability += adjustment;
			fighterCareers[player2Name].computedWinProbability += adjustment*-1;	
		}
		else
		{
			fighterCareers[player1Name].computedWinProbability += adjustment*-1;
			fighterCareers[player2Name].computedWinProbability += adjustment;			
		}
	}

	//find the winner name
	var projWinner = fighterCareers[player1Name].computedWinProbability > fighterCareers[player2Name].computedWinProbability ? player1Name : player2Name;

	//dream mode is 'intelligently making the stupid bet'. Because long shot bets have such high payouts they can be worth betting on 
	//if you have nothing to lose. Since you are always given 'bailout' cash if you end up with 0 or in the hole, it makes sense to 
	//bet on super long shots. If they win you get a TON of cash. If they lose you are just right back to where you started. Of course
	//that's up to the player though if they want to use that mentality so I made it optional. Also most players would only want to make stupid bets
	//if they have under a certain amount to keep from losing their fortune, and because at higher dollar values you can bet a large enough
	//percent of the total pot to still make good returns.
	if(dreamMode && saltyBucks < dreamModeDisabledAtAmount)
	{
		var winPercentDifference = fighterCareers[player1Name].computedWinProbability > fighterCareers[player2Name].computedWinProbability ? fighterCareers[player1Name].computedWinProbability - fighterCareers[player2Name].computedWinProbability : fighterCareers[player2Name].computedWinProbability - fighterCareers[player1Name].computedWinProbability;
		if(winPercentDifference > dreamModePercentThreshold)
		{
			$('#statusDiv').html('Bet on the dream!');
			 projWinner = fighterCareers[player1Name].computedWinProbability < fighterCareers[player2Name].computedWinProbability ? player1Name : player2Name;
		}
	}
	$('#statusDiv').html('Projected winner is ' + projWinner);
	return projWinner;
}

Great, now I had pretty confidently who was going to win and lose. But I was still short on data and betting manually all the time was getting to be a pain. My bot could auto bet, but not know who was fighting, or I could manually bet and have to actually enter names to do it. At this point you are probably saying, ‘well just extract the character names from somewhere, feed them into the formula and be done with it!’. I wish it was that simple. The stream of the fight is an embedded flash object and the names of the characters do not appear anywhere. The names are simply not available by any conventional means. It seriously seemed like the author went out of his way to make the names not available to prevent this kind of thing. I knew I’d have to solve that problem but, for the time being I needed to collect data. I settled on just having a stupid bot bet small amounts on someone at random so I could harvest that sweet sweet result data.

Even with that decision it wasn’t totally easy. Because it’s an embedded flash object how would I know when the betting window is open? I’ve only got about 45 seconds from when betting opens to when it closes, so whatever I do has to be reasonably quick. I then realized that the status text below the video changes to ‘Betting is Now open’ when you can bet. I simply told my bot to keep on a DOM transform onchange function to that. When that element changes evaluate the text and figure out if it says betting is now open. If so, wait about 40 seconds (so I have time to enter a manual bet if I want to) and then if no bet has been placed enter one. Using that same technique I know when the fight starts, ends, and payouts have been distributed. That ended up working out pretty well, though occasionally there seemed to be some sever delays that prevented entering a bet if I was too close to the deadline.

What my javascript bookmarklet looks like

What my javascript bookmarklet looks like

Using the same kind of trick I was able to extract the players current saltybuck total so i could deduce how to bet a small percent amount of their total, instead of just some static amount. Things were coming together well. I could just leave the bot on all night and it would bet for me. There were one or two mornings i came back and it had won me over 100K (randomly of course, it had no idea who it was betting on at this point). I build a nice little interface using jQuery UI that could be launched via my bookmarklet and if i entered the names I could get some decent odds data. I even rigged up an auto complete on the fighter names based on all the known fighters from the win/loss totals table. I added a few more fun little features, a hotkey combination to show and hide the window. I even added a sound effect ‘Oh yeah‘ if the bot wins a big amount of money (currently defined as over 10K, though I should probably make it to something like over 200% of your current total topping out at like 50K or something). When I actually paying attention and betting I was doing well, and if I walked away the bot would take over and place small bets to keep that sweet data stream coming in.

I knew that this was about as far as I could take the bot running as just a javascript thing bookmarklet thing. If I wanted more (centralized data so ELO and such didn’t have to be recalculated every fight), potentially to actually know who is fighting, I’d have to step out and really tread into unknown territory. I was going to need to somehow get a screenshot of who was fighting during the betting time. I was going to need to extract the names from the image. I’d have to feed that into some kind of optical character recognition engine (OCR). Then I’d have to take those results and make them available via a web service. I’d have to modify the bot to reach out to that webservice to trigger the reading and get the names. This couldn’t be done in the browser so I was going to need to develop some kind of server mechanism. I’d also need about 5 pots of coffee.

The Server

I decided I’d tackle what I considered to the easier part first to keep my spirits up and keep me from quitting when I reached the part which i knew would be most difficult (the OCR). The server had a fairly simple job to do in my mind. I needed to listen for a call from the client (since the client knew when the betting screen was open, it could make the callout, where as the server would have no idea because that monitoring functionally was still built into the client part. I’d have to refactor this later). When it got the request it would need to take a screenshot of the browser window which would also have to be running on the server. Ideally it would extract just name of the fighters, and save those images. It would then trigger the OCR engine to read the files. When that was done it would then read out the resulting data back to the requester (huh, now that I type that out it sound kind of hard, but regardless it wasn’t really too bad). I decided the easiest and lightest weight answer for a server would be a node js instance. I have some experience with node and it’s quick to get running so it seemed like the natural candidate.

After a bit of reading to get back up to speed on how to setup node and getting my basic hello world up and running I found a library that would allow node to execute commands on the server (yeah I know that’s dangerous, but this is all local, so whatever). I just rigged it up to listen for a specific page request, and once it got that it would run a batch file which would handle the screenshot, image processing and OCR work. Once it got word the batch file had run it would read the contents of the two text files that were hosted on the server as well that would hold the names of the current fighters. Here is the node code.

var express = require('express');
var sh = require('execSync');
var app = express.createServer() ;
var fs = require('fs');

var port = process.env.PORT || 80;
//configure static content route blah
app.configure(function(){
  app.use(express.methodOverride());
  app.use(express.bodyParser());
  app.use(express.static(__dirname + '/public'));
  app.use(express.errorHandler({
    dumpExceptions: true, 
    showStack: true
  }));
  app.use(app.router);
});

app.listen(port, function() {
  console.log('Listening on ' + port);
});

app.get('/getFighters', function(request, response){

	console.log('Request made to get fighter data');
	var result = sh.exec('cmd /C screenshot.bat');

	console.log('Command ran ' + result.stdout);
 	fs.readFile( 'public\\fighter1Name.txt', "utf-8", function (err, fighter1) {
		if (err) console.log( err );
		fs.readFile( 'public\\fighter2Name.txt', "utf-8", function (err, fighter2) {
		  if (err) console.log( err );
		  var fighters = new Object();
		  fighters.fighter1 = fighter1.trim();
		  fighters.fighter2 = fighter2.trim();

		  response.send(request.query.callback+'('+JSON.stringify(fighters)+');');
		});
	});
});

Not too bad eh? As you can see the results are wrapped using a JSONP style callback system so this can be invoked from anywhere. Once that was up and running now I had to write the batch file that actually did all the hard work.

The Bat File

The node server pretty much has a black box kind of process. It just calls some batch file and expects results. Not that it really matters, but the execute process is async and so the server didn’t know when that process had completed (ended up having to have a loop that attempts to read the contents until it succeeds, shitty I know). It has no idea of course how the bat file does what it does, and honestly neither did I when i first started building it. I knew the bat file would have to take a screenshot, extract the names of the fighters from that screenshot, and invoke the OCR engine. At this point i knew I was at least going to use Tesseract for my OCR engine, and that ImageMagick (a suite a command line tools for image processing) where likely going to be how I did the image processing. For capturing the screenshot I found a simple utility on google code called screenshot-cmd that would take a screenshot of the primary monitor. I figured then I could use imagemagick  to crop down the un-needed stuff (since the video is in the exact same place on my screen every time I could use coordinate based cropping). Then with the images cleaned up I could forward them onto Tesseract.

After a bit of messing around I managed to get the screenshot and get ImageMagick to extract just the names of the fighters from the betting screen image. Later on I had a sudden moment of clarity and realized I could remove the background from the names if I just deleted everything that wasn’t the red color for the player 1 name, and the blue color for the player 2 name (since they are always exactly the same color). Also I decided to archive the old captures so I’d have them to help train the OCR engine. The final batch script looks like this

@ECHO OFF

FOR %%I IN ("public\screens\*.png") DO (
  SET lmdate=%%~tI
  SETLOCAL EnableDelayedExpansion
  SET lmdate=!lmdate:~6,4!-!lmdate:~3,2!-!lmdate:~0,2! !lmdate:~11,2!-!lmdate:~14,2!
  MOVE "%%I" "public\screens\old\!lmdate!-%%~nxI"
  ENDLOCAL
)

::Take screenshot of primary monitor at full resolution
screenshot-cmd 0 0 1920 1080 -o public\screens\fighters.png

::ImageMagick shave off the left 478 pixels and the top 135 pixels to cleanup the image
convert -shave 478x135  public\screens\fighters.png public\screens\fighters.png

::ImageMagick remove the bottom and right borders
convert public\screens\fighters.png -gravity South  -chop  0x150  public\screens\fighters.png

::Now we have a screenshot with just the fighters. Now we have to extract the names of the fighters and put them in separate files

::Extract fighter1 name by cropping out an 800px X 40px swatch from the top of the image
convert public\screens\fighters.png -crop 800x40+60+0 public\screens\name1.png

::Remove all colors except for the red used by the font
convert public\screens\name1.png -matte ( +clone -fuzz 4600 -transparent #e3522d ) -compose DstOut -composite public\screens\name1.png

::Extract fighter1 name by cropping out an 800px X 40px swatch from the bottom of the image
convert public\screens\fighters.png -crop 800x40+200+618 public\screens\name2.png

::Remove all colors except for the red used by the font
convert public\screens\name2.png -matte ( +clone -fuzz 4600 -transparent #2798ff ) -compose DstOut -composite public\screens\name2.png

::Feed the player names into tesseract for OCR scanning.Write results to two different text files. One for each fighter
tesseract public\screens\name1.png public\fighter1Name -l salty
tesseract public\screens\name2.png public\fighter2Name -l salty

The commands took a bit of time to get just right (what with having to find just the right offsets and messing with the color removing fuzz factor). The final output is pretty damn good actually. Check this out.
name1name2

All things considered I’d say those are some damn fine extractions from a screenshot of a flash video. Now all that was left is the final part, tackling the Tesseract OCR training process to teach it about this strange font.

Tesseract OCR

Tesseract is pretty much the premier freeware OCR engine. There really isn’t anything else that competes with it. It’s hard as hell to figure out and takes a ton of time to get setup properly for new languages but I had heard when it works, it works pretty damn well. I know next to nothing of OCR, so I knew tackling this was going to be a challenge. The basic outline breaks out like this

1) Gather samples of your new font. At least a few occurrences of every possible character.

2) Create a ‘box’ file which is basically just a coordinate mapping of where each character starts and stops and what it represents. (finding a functional tool for this part took forever, because it turns out I was using a bad image that caused them all to have problems or act very slowly. Pro tip, when saving your TIF file to feed into a box editor, if using photoshop discard the layer data. It makes the file way too big and slow to use).

3) Train Tesseract using the box file

4) Generate the rest of the weird files it needs that I don’t know what do.

5) Package all the files and see if your new language works.

eng.salty.exp0The shortcut method here is create your training image with all your chars, use jTessBoxEditor to do your modifications to the box file. Then use SerakTesseractTrainer to do the training and create the files. Honestly if i had known about those two things right off the bat, my life would have been a lot easier. Over half my battle was just trying to find what tools to use and getting them to work right.

Also retraining it after I was able to remove the backgrounds from the names made it about a billion times more accurate. I would highly recommend that approach if you have the ability to. Good training data makes all the difference. Trying to train it with crummy data with backgrounds and weird shit going on makes it next to impossible. On the right you can see what my training data looked like and it ended up working out pretty well. It’s still lacking some numeric characters, but I’ll have to add those in later.

I was amazed to find it actually worked. The names were being read properly and written to the file. The node server was grabbing the contents of the file and returning it to the requesting bot. The bot took the names and fed them into the scoring system and placed bets accordingly. It was a beautiful symphony built from a total clusterfuck. I am almost sad now because I have solved my project. Sure i can make a little better, implement a database, maybe tweak the scoring engine some, but overall it’s been solved. All that’s left to do now is sit back and watch the salt roll in. Later on I did a bit of re-factoring, moving the calculation onto the server and out of the client (where it belongs). I also created an extension just for the server that would invoke the screen reading process instead of accepting the request for the normal client (since I figured I may end up distributing the code I didn’t want everyone’s clients telling my server to constantly try to re-read the screen and such). Eventually the client got dumbed down to just polling the server when it detected that bets were open until it got back the fight odds and it then could set a suggested bet amount for the player. I also ended up adding a few other features to the client like ‘dream mode’ where in if the odds against a character were so insane as to make payout on the favorite nominal but the payouts for underdog amazing, bet on the underdog in hopes of a huge payout. You could set some variables like always bet in dream mode until you reached a certain threshold. You could also bet all in mode which would automatically bet all your money until a certain threshold since payouts at lower levels of betting were always so minimal. This is what the ‘final’ version of the client ended up looking like.

saltyclient final

As a postscript to this story to gather more data I ended up offering a trade to other players. If they could provide my their betting history data and enough of it was unique (I didn’t already have the results of that fight, which I identified by timestamp I would give them access to the tool). With their betting data added onto mine I ended up having an accuracy rate of around 85% which isn’t too bad. The overall results were somewhat disappointing though because for whatever reason the SaltyBet community was really good at guessing as well and the odds would end up so heavily staked in the winners favor that usually my payouts were pretty small.

Right now the Saltybot server isn’t running and the data is probably badly out of date, but hey if you want to download the source and get it running again, knock yourself out. You can download the source here

https://drive.google.com/file/d/0B04fc3zIG4iyMURsemloR040NFE/edit?usp=sharing

I don’t remember the exact setup steps, but I believe you’ll want to drop all the server files in a directory on your machine. Spin up a node.js console and launch core.js. Open up saltybet.com and keep it fullscreen. Then on your server install the saltyBotServerExtension into chrome. That should watch for fight changes and do the OCR process and put the results into the public folder. You’ll want to setup a web server where the public folder is available for your client to get at. Then install the client extension in your machine you intend to use as your ‘betting’ machine and point it at your webserver (yeah you’ll probably have to modify the source, thankfully in chrome you can just modify the source and load the unpacked extension). That should get you pretty close. If you have questions, feel free to ask, I’ll do what I can to help. I am interested in seeing where this goes, I’m just too lazy right now to do much with it myself. If there is interest maybe I’ll try and get it running again.


Floating/Sticky Headers For Visualforce PageBlockTable

So this is it. This is going to be the definitive guide for how to get some floating headers on your Visualforce page block table. I know there are many approaches, lots of debates about how to do it, but what I’ve got here is likely the best, simplest way to do it. It’s a jQuery plugin that will make the headers of a page block table stick to the top of the tables parent div. Check out a demo here

http://xerointeractive-developer-edition.na9.force.com/partyForce/floatingHeaders

You can download the plugin here.

https://www.box.com/s/lr73ibecfvo4bi0qzzbn

Upload it as a static resource, or just copy paste the contents into your visualforce page. Either way is fine. Also, in your visualforce page you’ll need to include the css class .floatingStyle and set it’s position to relative. So just

<style>      
.floatingStyle 
{ 
    position:relative; 
} 
</style>

To use it, simply put your pageblocktable inside a div or apex:outputpanel (with layout set to block). Give that container a height. Invoke the plugin on the table either by class or id. So if my pageblock tables had the styleClass of ‘floatingHeaderTable’ I could invoke it this way.

    <script>
    $(document).ready(function() {
        $('.floatingHeaderTable').vfFloatingHeaders();
    });
    </script> 

and that’s it. You are good to go. Here is a full sample page.

Visualforce Page

<apex:page controller="floatingHeadersController">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
    <script src="{!URLFOR($Resource.jquery_vfFloatingHeaders)}"></script>

    <style>
        .tableContainer
        {
            height:290px; 
            width: 100%;
            overflow: auto;
        }       
        .floatingStyle 
        { 
            position:relative; 
        } 
    </style>

    <script>
    $(document).ready(function() {
        $('.floatingHeaderTable').vfFloatingHeaders();
    });
    </script>   

    <apex:pageBlock >
        <apex:outputPanel styleClass="tableContainer" layout="block">
            <apex:pageBlockTable value="{!contactList}" var="item" title="Contact List" styleclass="floatingHeaderTable" >
                <apex:column value="{!item.firstname}"/>
                <apex:column value="{!item.lastname}"/>
                <apex:column value="{!item.email}"/>
                <apex:column value="{!item.phone}"/>
            </apex:pageBlockTable>
        </apex:outputPanel>
    </apex:pageBlock>
</apex:page>

Apex Class

public class floatingHeadersController 
{
    public list<contact> contactList
    {
        get
        {
          if (contactList == null)
          {
              contactList = [select firstname, lastname, email, phone from contact];
          }  
          return contactList;
        }
        set;
    }
}

I should totally mention that the bulk of this code came from the blog at

http://rajputyh.blogspot.com/2011/12/floatingfixed-table-header-in-html-page.html

I just wrapped it up and modified it a bit to work with page block tables since their table headers didn’t originally have ids, and put it into a nifty plugin.


Lets Build a Tree (From Salesforce.com Data Categories)

Salesforce Data categories. If you’ve had to code around then on the Salesforce.com platform, you are probably aware of the complexity, and how much of a pain they can be. If you havn’t worked with them much, you are fortunate 😛 They are essentially a way to provide categories for any sObject in Salesforce. They are most frequently used with knowledge articles. The Apex calls, describes and schema for them is unlike anything else in the Salesforce schema. Categories are their own objects and they can be nested to infinite complexity. In short, they are complicated and take a while to really get your head around them (I still don’t know if I really do). Thankfully I’ve done a bunch of hard work and discovery so that you don’t have to. For this particular project, we are going to build a nifty tree style selector that allows a user to select any data category for a given sObject type. You can then do whatever you want with that info. Yes I know there are some built in visualforce components for handling data categories, but they aren’t super flexible and this is just a good leaning experience. In the end, you’ll have an interactive tree that might look something like this.

treeDemoWord of Warning: I had to live modify some of code I posted below to remove sensitive information that existed in the source project. I haven’t used the EXACT code below, but very very close. So please let me know if something doesn’t quite work and I’ll try to fix up the code in the post here. The idea works, it’s solid, but there might be a rough syntax error or something.

Our application is going to consist of a visualforce page that displays the tree. A component that contains the reusable tree code, a static resource that contains the javascript libraries, css file and images for the tree structure. Of course we will also have an apex class that will handle some of the heavy lifting of getting category data, and returning it to our visualforce page. We’ll use javascript/apex remoting to communicate with that Apex class. First off, lets grab the static resource and get that uploaded into your org. You can snag it here

https://www.box.com/s/04u0cd8xjtm0z84tbhid

upload that, make it public, call it jsTree. Next we’ll need our Apex class. It looks like this.

global class CaseSlaController
{
    //constructors for component and visualforce page extension
    public CaseSlaController() {}
    public CaseSlaController(ApexPages.StandardController controller) {}

    //gets category data and returns in JSON format for visualforce pages. Beware that since we end up double JSON encoding the return 
    //(once from the JSON.serialize, and another time because that's how data is returned when moved over apex remoting) you have to fix
    //the data on the client side. We have to double encode it because the built in JSON encoder breaks down when trying to serialize
    //the Schema.DescribeDataCategoryGroupStructureResult object, but the explicit call works.
    @remoteAction 
    global static string getCategoriesJson(string sObjectType)
    {
        return JSON.serialize(CaseSlaController.getCategories(sObjectType));
    }

    public static  list<Schema.DescribeDataCategoryGroupStructureResult> getCategories(string sObjectType)
    {

        //the describing of categories requires pairs of sObject type, and category name. This holds a list of those pairs.
        list<Schema.DataCategoryGroupSObjectTypePair> pairs = new list<Schema.DataCategoryGroupSObjectTypePair>();

        //list of objects to describe, for this app we only take 1 sObject type at a time, as passed into this function.
        list<string> objects = new list<string>();
        objects.add(sObjectType);

        //describe the categories for this object type (knowledgeArticleVersion)
        List<Schema.DescribeDataCategoryGroupResult> describeCategoryResult =  Schema.describeDataCategoryGroups(objects);

        //add the found categories to the list.
        for(Schema.DescribeDataCategoryGroupResult s : describeCategoryResult)
        {
            Schema.DataCategoryGroupSObjectTypePair thisPair = new Schema.DataCategoryGroupSObjectTypePair();
            thisPair.sObject = sObjectType;
            thisPair.dataCategoryGroupName = s.getName();
            pairs.add(thisPair);            
        }

        //describe the categories recursivly
        list<Schema.DescribeDataCategoryGroupStructureResult> results = Schema.describeDataCategoryGroupStructures(pairs,false);

        return results;
    }    
    private static DataCategory[] getAllCategories(DataCategory [] categories)
    {
        if(categories.isEmpty())
        {
            return new DataCategory[]{};
        } 
        else
        {
            DataCategory [] categoriesClone = categories.clone();
            DataCategory category = categoriesClone[0];
            DataCategory[] allCategories = new DataCategory[]{category};
            categoriesClone.remove(0);
            categoriesClone.addAll(category.getChildCategories());
            allCategories.addAll(getAllCategories(categoriesClone));
            return allCategories;
        }
    }
}

So there are three functions there and two constructors. The constructors are for later on when we use this thing in a component and a visualforce page, so don’t really worry about them. Next is the getCategoriesJson, that is the remote function we will call with our javascript to get the category data. It just invokes the getCategories function since that returns an object type that Salesforce can’t serialize with it’s automatic JSON serializer without blowing up (in my real app I had to use getCategories for another reason, hence why I didn’t just combine the two functions into one that always returns JSON). The last one is just a private function for spidering the data category description. Other than that, you can check out the comments to figure out a bit more about what it’s doing. In short it describes the categories for the given sObject type. It then creates dataCategoryGroupSobjectTypePairs from those categories and describes those and returns the huge complicated chunk.

Alright, so we got the back end setup, let’s actually make it do something. For that we need our component and visualforce page. First up, the component. Wrapping this picker in a component makes it easy to use on lots of different visualforce pages. It’s not required but it’s probably a better design practice.

<apex:component Controller="CaseSlaController">
    <!---- Two parameters can be passed into this component ---->
    <apex:attribute name="sObjectType" type="string" description="the sObject type to get data category tree for" />
    <apex:attribute name="callback" type="string" description="Name of javascript function to call when tree drawing is complete" />

    <!--- include the required libraries --->
    <link rel="stylesheet" href="{!URLFOR($Resource.jsTree, 'css/jquery.treeview.css')}" />
    <apex:includeScript value="{!URLFOR($Resource.jsTree, 'js/jquery.min.js')}" />
    <apex:includeScript value="{!URLFOR($Resource.jsTree, 'js/jquery.treeview.js')}" />

    <script>
        //put jQuery in no conflict mode
        j$=jQuery.noConflict();     

        //object to hold all our functions and variables, keep things organized and dont pollute the heap
        var categorySelect = new Object();

        //invokes the getCategoriesJson function on the apex controller. Returns to the callback function with the
        //fetched data
        categorySelect.getCategoryData = function(sObjectType,callback)
        {
            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.CaseSlaController.getCategoriesJson}', 
                sObjectType,
                function(result, event){
                   callback(result,event);
                }, 
                {escape: true}
            );          
        }    

        //as soon as the dom has loaded lets get to work
        j$(document).ready(function() {

            //first off, find all the data category data for the given sObject type.       
            categorySelect.getCategoryData('{!sObjectType}',function(result,event)
            {
                //the json data we get back is all screwed up. Since it got JSON encoded twice quotes become the html
                //&quote; and such. So we fix the JSON and reparse it. I know its kind of hacky but I dont know of a better way

                var fixedJson = JSON.parse(categorySelect.htmlDecode(result));         

                //lets create the series of nested lists required for our tree plugin from the json data.
                var html = categorySelect.buildTreeHtml(fixedJson);                          

                //write the content into the dom
                j$('#categoryTree').html(html);              

                //apply the treeview plugin
                j$("#categoryTree").treeview({
                    persist: "location",
                    collapsed: true,
                    unique: true
                });  

                //if the string that was passed in for callback is actually representative of a function, then call it
                //and pass it the categoryTree html.
                if(typeof({!callback}) == "function")
                {
                    {!callback}(j$("#categoryTree"));                                               
                }
            });    
        });

        //function that is meant to be called recursivly to build tree structure html
        categorySelect.buildTreeHtml = function(category)
        {
            var html = '';     

            //iterate over the category data  
            j$.each(category,function(index,value)
            {
                //create list item for this item.
                html+='<li><a href="#" category="'+value.name+'" class="dataCategoryLink" title="Attach '+value.label+' SLA to Case">'+value.label+'</a>';

                //check to see if this item has any topCategories to iterate over. If so, pass them into this function again after creatining a container               
                if(value.hasOwnProperty('topCategories') && value.topCategories.length > 0)
                {
                    html += '<ul>';
                    html += categorySelect.buildTreeHtml(value.topCategories);                    
                    html +='</ul>';                 
                }   
                //check to see if this item has any childCategories to iterate over. If so, pass them into this function again after creatining a container                           
                else if(value.hasOwnProperty('childCategories')  && value.childCategories.length > 0)
                {
                    html+='<ul>';                   
                    html += categorySelect.buildTreeHtml(value.childCategories);
                    html+='</ul>';
                }
                html += '</li>';
            });
            return html;                
        }

        //fixes the double encoded JSON by replacing html entities with their actual symbol equivilents
        //ex: &quote; becomes "
        categorySelect.htmlDecode = function(value) 
        {
            if (value) 
            {
                return j$('<div />').html(value).text();
            } 
            else
            {
                return '';
            }
        }            
    </script>
    <div id="categoryTreeContainer">
        <ul id="categoryTree">

        </ul>
    </div>
</apex:component>

Now then finally we need a visualforce page to invoke our component and rig up our tree items to actually do something when you click them. We wanted to keep the component simple, just make the interactive tree cause different pages might want it to do different things. That is where that included callback function comes in handy. The visualforce page can invoke the component and specify a callback function to call once the component has finished its work so we know we can start manipulating the tree. Our page might look like this.

<apex:page sidebar="false" standardController="Case" showHeader="false" extensions="CaseSlaController">
    <c:categorySelect callback="knowledgePicker.bindTreeClicks" sObjectType="KnowledgeArticleVersion"/>

    <script>           
        var knowledgePicker = new Object();

        knowledgePicker.bindTreeClicks = function(tree)
        {
            j$('.dataCategoryLink').click(function(event,ui){
                event.preventDefault();
                alert('clicked ' + j$(this).attr('category'));
            }); 
        }                           
    </script>   
</apex:page>

We invoke the component passing it a callback function name and the type of sObject we want to make the category tree of. We then create a function with the same name as the callback. Inside that function we simple attach an onclick event handler to the tree category links that sends us an alert of which one the user clicked. Of course we could then do anything we wanted, make another remoting call, update an object, whatever.

Anyway, I hope this was helpful. I know I was a bit frustrated as the lack of sample code for dealing with categories so hopefully this helps some other developers out there who might be trying to do the same kind of thing. Till next time!

-Kenji/Dan


Javascript Console

So I just wrapped up another Cloudspokes challenge.I spent way too much time on this. Really it’s just a dumb little $300 dollar challenge, and I think I put like 10 or so hours into this, but whatever, it was fun. I probably went overboard, but I think I made something actually kind of useful. First, before I get too deep into it, check out the challenge details.

http://www.cloudspokes.com/challenges/1999

The basic idea being that they wanted a way to run javascript on a web page, similar to Firebug or the Chrome developer tools. They also suggested adding a list of the user/developer defined functions and maybe an auto complete system to make entering the code to run easier. I wanted to take it a step further and build it all as pure javascript so that it could be turned into a bookmarklet. With it all delivered as a bookmarklet that means you can inject this console on any webpage anywhere without needing access to the source and start running functions on it. You don’t need to include any additional libraries or hooks or anything. You need NO access to the source code of the webpage for this to work, which is what really makes it cool.

It does this by using javascript to dynamically inject jQuery, jQuery UI, and bootstrap (only if needed, it’s smart enough not to double include libraries), and builds the console directly by inserting it into the DOM. It uses some tricky looping and evaluation to find all exisitng functions, list them, and get the function bodies as well. It creates an input area where javascript code can be entered, and the results are displayed in a console using intelligent return type handling. Using a bit of bootstrap for autocomplete, buttons, and the collapsible side list view it creates a simple yet powerful interface. As a neat side effect I found what is probably the end all, be all way to inject scripts that may or may not be present and rely on each other. I’m hoping to make a blog post out of that technique pretty soon. It uses some neat recursion and callbacks to work it’s magic and the end result is very efficient and reliable.

Anyway, check out the video for a better understanding/demo of what it can do.

http://www.screencast.com/t/jVUo5Qsh5 <- Demo video

To try it out, make a bookmark a new bookmark, and set it’s path to this. Sorry I can’t make a bookmarklet link here for you, wordpress keeps killing the link.  It might take a little bit of time to load on very complicated pages. Also it does support pressing up and down in the input box to flip between previously entered commands.

javascript: (function(){var jsCode=document.createElement('script');jsCode.setAttribute('src','https://dl.dropbox.com/u/65280390/jsConsoleScript.js');document.body.appendChild(jsCode);}());

Building a mobile site on Salesforce site.com, with cool menu to mobile list code!

Mobile. Mobile mobile mobile. Seems like the only word you here these days when it comes to technology. That, or social. Point being if you don’t have a mobile site most of the world will figure your company is way behind the times. Problem is designing mobile websites sucks. So many different devices and resolutions, features and capabilities. It’s worse than regular web design by a long shot when it comes to trying to make a website that works correctly across all browsers/devices/configurations. It can really be a nightmare even for the most skilled designers.

Thankfully jQuery mobile is here to help. While not perfect (its definitely still getting some issues worked out) it makes creating mobile websites infinitely more bearable. It takes care of the styling and such for you creating a nice interface and handling most of the junk you don’t want to deal with as far as writing event handlers, dealing with CSS adjustments, creating the various input widgets etc. I’ve used it a fair amount and after the initial learning curve I can safely say it’s way better than trying to do it all yourself.

Site.com is another technology offered by Salesforce that is supposed to make building websites easier. It is mostly used for small websites with limited interactivity (seeing as it doesn’t support sessions, and there is no server side language access aside from a few minimalistic  apex connectors). Great for marketing websites, mini sites, etc. It makes it very easy for your non technical team to create and edit content. It has a great WYSIWYG editor, various automated tools (such as a navigation menu, which we’ll talk about shortly) and some other goodies that generally make it a fairly competent CMS.

So here we are. We want to build a mobile site. We want to use site.com to do it. We would also like our mobile site to take full advantage of the features of site.com including the menu generator/site map. The idea also here is that the same content can be used for both our mobile site and our regular site. Really hoping to utilize that ‘write once, run everywhere’ mentality that I love so much (I don’t care what all the native platform fans say, it can be done!). We’ll need to architect our site in a way that allows for this. That means keeping in mind that our content could be loaded on any kind of device. We’ll also want to try and keep things light weight for our mobile friends lest their little smart phones choke trying to handle our content. I’ve come up with a solution for this, which I like pretty well and I’ll outline below but I’m not claiming it’s the best way by any means.

There are two basic approaches I’ve used for building things on site.com:

One  is to have a single page which contains all the headers, footers, standard elements, etc (I’ll call this the framework page). Then using a bit of javascript to transform all the links into ajax links which load the content from the requested page into a div within the same page. By transforming the links using javascript you ensure that non javascript browsers don’t try and use ajax to load content, and your marketing team doesn’t have to worry about trying to write any javascript either. It’s also good for SEO since the crawlers will load your page and be able to follow the links since they won’t run javascript. Just select all links on the page with a certain class, and enhance them (code for this below). When the content is loading, we run that same script again to enhance all those new links and the cycle continues. This is nice because because the ajax loading is faster and looks slick. Also if you are willing to have a javascript only (as in you aren’t interested in graceful degradation for non javascript client, which there really aren’t any) then your content pages can contain JUST the relevant content. As in no headers, footers, CSS, anything like that. You just grab the page and inject it into your framework page’s content area and you’re done. The problem with this approach is that since the detail pages do not have styling if they are directly linked to, the user will just see plain text and images on a white page. This is bad news unless you have some kind of auto redirect script to get users back to the index page if they have loaded just a detail page. You’ll also have to worry about bookmarking, direct linking, browsers back button, and other such things. I have a post detailing how to deal with these located at https://iwritecrappycode.wordpress.com/2012/07/06/experimental-progressively-enhance-links-for-ajax-with-bookmarking-and-back-button-support/ with the basic idea being your ajax links cause a hash change in the url. That hash change results in a unique URL that users can bookmark and share. Your site just needs to check the URL for any after hash content and try to load the specified page on page load into the content frame instead of whatever your default page is.

Option two is a little safer. Every page has all the headers and footers, and again you have a special div where all the real content goes. Again using javascript to ajax enahnce the links. When the page is requested you ajax load the page, grab the content from just that div (on the fetched page) and inject it. That way if javascript isn’t enabled your link just functions like a regular link, taking the user to that page. You don’t have to worry about the user accidentally getting to a plain detail page without the headers, footers and styles because every page has them. If javascript is enabled the link is enhanced and turns into a ajax loading link. The requested page gets fetched via ajax and the relevant content is extracted from the DOM and inserted into your framework page. Not as a fast and clean as having just the content on your sub pages, but it’s a bit safer. I’m using this approach for now while I decide if I want to use the other.

 

Okay, so we’ve come this far. You’ve decided on a site architecture, created some content and are ready to make it mobile. For example, mine looks like this.

Capture

You can see I’ve got my main menu system with a few sub categories. Also, I have the directions sub menu minimized to make the image smaller, but there are several entries e

First thing is you’ll have to setup your jQuery mobile home page. Just find a basic tutorial online that explains how to get it up and running, not much to it. A special meta tag, include the CSS and JS, create a home page div on your page and you are up and running. jQuery mobile actually has this fairly interesting idea that all content will be contained within a single page, it make it more ‘app like’. It by default uses ajax requests to load content and just shows and hides the stuff relevant to what the user wants to see. So as a user clicks a link to load content, an ajax request fetches it, a new ‘page’ is created on your template and the users view is shifted to it. But how do we build that navigation? We want it to by dynamic so when someone from marketing creates a new page, it just shows up on your site. You also want to maybe use the build in jQuery mobile list view for it, since this is a simple site and list views provide easy navigation on mobile sites.

Site.com as we know does include an automatic menu generator, but it just generates a lame unordered list or ugly dropdown system. How can we use that to build our jQuery mobile list view? Using their built in list maker, from the content above, it’s going to generate code that looks like this.

CaptureYou can see it creates a div, inside of which is an unordered list. Each sub menu is another unordered list inside of a list element. Seems like we could probably use a little jQuery magic to spruce this list up and turn it into a jQuery mobile list. For those who just want the functioning JS, just copy and paste this into a JS file, upload it to site.com and include it in your mobile index page. Make sure your mobile menu has a css class called ‘ajaxMenu’. That is how jQuery finds the menu to enhance.

$(document).ready(function () {
    console.log('Document ready fired');
    sfMenuTojQueryList();
    markupLinks();

    $( document ).live( 'pagecreate',function(event){
        markupLinks();
        setFooters();
    });

});

function sfMenuTojQueryList()
{
    //Special stuff for the mobile site. Enchace the navigation menu into a list few, and turn it's links into ajax links
    $('.ajaxMenu a[href]').each(function(){

        if($(this).parent().children().length == 1)
        {
            $(this).addClass('ajaxLink');
        }
    });
    $('.ajaxMenu > ul').listview({
        create: function(event, ui) { 

        }
    });    
}

function markupLinks() {

    $('.ajaxLink').each(function (index) {
        if($(this).attr('href') != null)
        {
            $(this).attr('href', $(this).attr('href').replace('/', '#'));
        }
    });

    $('.ajaxLink').bind('click', function (event,ui) {
        event.preventDefault();
        loadLink($(this).attr('href'));        
    });
}

function loadLink(pageUrl) {

    console.log('Loading Ajax Content');
    pageId = 'jQm_page_'+pageUrl.replace(/[^a-zA-Z 0-9]+/g,'');
    pageUrl = decodeURIComponent(pageUrl).replace('#','');

    console.log(pageUrl + ' ' + pageId);
    if($('#'+pageId).length == 0)
    {
        console.log('Creating New Page');
        $.get(pageUrl, function (html) {
            //in this case the content I actually want is held in a div on the loaded page called 'rightText'. If you are just loading all your content             //you can just use $(html).html() instead of $(html).find("#fightText").html(). 
            $('body').append('<div id="'+pageId+'" data-role="page"><div data-role="header"><h2>'+pageUrl+'</h2></div><div data-role="content">'+$(html).find("#rightText").html()+'</div></div>');                                

            $.mobile.initializePage();

            $.mobile.changePage( '#'+pageId, { transition: "slideup"}, false, true);    

        }).error(function () {
            loadLink('pageNotFound');
        });
    }
    else
    {
        console.log('Changing to Existing Page #'+pageId);
        $.mobile.changePage( '#'+pageId, { transition: "slideup"} );    
    }

}

So here is what happens. When the page loads, it’s going to find your menu. It will call the jQuery mobile list view on it, to make it into a nifty list view that can be clicked. It looks like this now.

Capture
Each of those things can be clicked, at which time if it has a sub menu the contents of that sub menu will be displayed. If the item is actually a link, the content is loaded via ajax and new jQuery mobile page is created and injected into your main page, which it then changes to. If it finds that the page has already been loaded once, instead of fetching it again, it just changes page to it. It’s a pretty slick system that will allow a very fast loading website since the content is loaded on the fly and pulled completely via ajax.

You now have a mobile version of your website with a dynamic hierarchy enabled menu system that can be totally managed by your marketing team. Cool eh?


New Cloudspokes Entry – Salesforce Global Search

Hey everyone,

I’m just wrapping up my entry for the CloudSpokes Salesforce global search utility challenge, codename Sherlock. I’m fairly pleased with how it turned out and figured I’d post the video for all to enjoy. I can’t post the code since this is for a challenge, but feel free to ask any questions about it.

http://www.screencast.com/t/GrYnfBlJFM

Features:

  • Fast operation using JS remoting. No page reloads. Ajax style searching.
  • Search any objects. Not limited to a single object type search
  • Smart formatting adjusts search result display based on data available about the object
  • Easy customization using callbacks and jQuery binds
  • Flexible, can be modified to suit many different requirements
  • Easy to use jQuery plugin based installation
  • Efficient each search consumes only one database query
  • Reliable return type makes processing search results easy
  • CSS based design makes styling results quick and easy
  • Structured namespaced code means smaller memory footprint and less chance of collisions
  • Deployable package makes for easy install
  • Over 90% code coverage with asserts provides assurance of functionality

You can check out the full documentation and feature list here

https://docs.google.com/document/d/17-SUja_SO_Enhh8LrjzDMB7VIX6S87TmPr9yBW5z-yo/edit

I don’t know why exactly they wanted such a thing, but it was certainly fun to write!