Friday, August 21, 2009

Safari Books Online

I recently got a Safari Books subscription from work, and it is awesome. I don't enjoy reading long form content on the computer screen, but having access to concise, correct examples and solutions is a revelation when compared to sifting through the Google.
I loathe subscription fees but access to this technical library would be worth it, even if I had to (ugh) pay for it myself.

Monday, August 17, 2009

Javascript Development Environment

Doing this for a couple weeks, I now have a stable environment for javascript development:

Eclipse 3.5 - Web Tools, XML Tools, Javascript, Subclipse
Firefox - Firebug
Chrome

Development is leagues away from the effortless task of Java development, where Eclipse gives such an enormous lift it's hard to adjust to the basic help you get with dynamic languages. The Javascript editor is very good, but because of the language, there are no sophisticated refactoring tools included. This important, especially when working on a new project, because you learn the specifics of the problem domain as you go. With Java + Eclipse, agile development of sort "get it to work, get it work right, get it work fast" is perfectly natural.

In any case, Firebug is immensely powerful as a debugging tool. Critically, it has mouseover variable information. There are some bridges between Eclipse and Firebug, but I could not get them to reliabily work on Linux, so it's: make a small change in the IDE, switch to Firefox reload, inspect. Firebug has one annoying bug in that it shows errors in red over the top of the text of the line that is causing the problem. If your lines are long you can't read them. So I load the page in Google Chrome and inspect the code in its very pretty but less sophisticated debugging environment, and get the error in the console. Chrome is also damned fast, and formats things slightly different, so it useful if only as a second opinion.

Even if Eclipse had no Javascript editor, context help, large file support, great search capabilities, intuitive diff comparison, unparalleled Team support, SVN integration, or Mylyn task tracking, its ludicrously configurable keybindings have me hooked. I've configured a rational homerow editor navigation scheme that makes all others (emacs, vi, etc) blush in shame:



(I'm happy to send the key prefs to any who request it).

Saturday, August 15, 2009

The house was decorated by an evil dolphin

I now have weapon deletion working (but not with the fancy JQueryUI blind effect I want), but I had to do something weird with my weapons array. Simple remove of the weapon from the array:

chardata.weapons.splice(weapon_idx, 1);

does not "reorder" the array. Eg.,

[{foo}, {bar}, {monkey}].(splice(1))


does not just create [{foo}, {monkey}]. It's stored as

["0":{foo}, "2":{monkey}]

which causes a problem with the way I'm handling the UI. My solution was to copy the array with slice(), then reassign it back to the real chardata object:

chardata.weapons.splice(weapon_idx, 1);
var foo = chardata.weapons.slice();
chardata.weapons = foo;

The indexes are sequential with no gaps. Weird, but it works.

Monday, August 10, 2009

Extracting a JSON array from a cookie

Knowing nothing, I had assumed that when you JSON-ify an array, then parse it back into an object, it comes out exactly as it went in. No so, gentle reader. Arrays are stored as named objects:

 "spells":{"0":{"0":113,"1":135},"1":{},"2":{"0":227},"3":{"0":209,"1":186}}  


This means all arrays must be reconstituted manually:

 // spells     
if (chardata.spells != null) {
char_spells = [];
for (spell_lvl_idx in chardata.spells) {
char_spells.push([]);
for (char_spell in chardata.spells[spell_lvl_idx]) {
char_spells[parseInt(spell_lvl_idx)].push(parseInt(chardata.spells[spell_lvl_idx][char_spell]));
}
}
chardata.spells = char_spells;
}


In this case, a multi-dimensional array of [spell level[spells per level]].

v0.1

After solving a particularly nasty scoping issue (my loop counter i was being used and updated in a nested function), v0.1 is out! Everything basically works, provided you have the right browser and cookie permissions. To circumvent smartphone limitations, I've hosted it on my friends (slow) site:

http://chambery.subfire.org/charmgrjs/edit.html

I created a branch (thanks to dougr for help with this):

http://charactermanager.googlecode.com/svn/branches/v0_1/

The only trick is to create your branches/ directory first in the SVN Repository Explorer, before creating your tag.

Further on down the road:
0.2: Consolidate the separate .html files, make the javascript purely functional (no global data apart from the cookie which is loaded on initialization)
0.3: Implement feats (yikes!)

Along the way, I'll be transcribing the skill and spell data into the DB when I need a thinking break. If anyone would like to help with this simple (though less than rewarding) task, shoot me an email.

Friday, August 7, 2009

Dialog for to show detail info



Got the JQueryUI Dialog working (for some reason this was quite a struggle for me). Clicking a spell, feat, or skill brings up a model dialog containing the full details of the selected element.

The issue was the title. The title is set on creation, and dialog doesn't get recreated on invocation(?), so you have to do some special thing to set it after initialization. In any case, here's the code:

   
content = '';
title = name;

$("#mydialog").html(content);
$('#mydialog').dialog('option', 'title', title);
$("#mydialog").dialog({
modal: true,
autoOpen: false,
title: title
});
$("#mydialog").dialog('open');

Loading and Saving TaffyDB data from cookies

I flopped around a good long time over this one:

I'm using cookies as a datastore, but had an issue with TaffyDB not stringify correctly. The TaffyDB author, Ian Smith provided some critical help, and here is the working (though probably not ideal solution):

 function clone(o) {  
if(typeof(o) != 'object') return o;
if(o == null) return o;
var newO = new Object();
for(var i in o) newO[i] = clone(o[i]);
return newO;
}
function sav(){
var cookieData = clone(chardata);
cookieData.skills = cookieData.skills.get();
cookieData = TAFFY.JSON.stringify(cookieData);
var d = new Date(2020, 02, 02);
document.cookie = 'chardata=' + cookieData + ';expires=' + d.toUTCString();
}
function lod(){
if (document.cookie.length > 0) {
c_start = document.cookie.indexOf("chardata=");
if (c_start != -1) {
c_start = c_start + 9 //c_name.length + 1;
c_end = document.cookie.indexOf(";", c_start);
if (c_end == -1) {
c_end = document.cookie.length;
}
cookie_data = document.cookie.substring(c_start, c_end);
chardata = TAFFY.JSON.parse(unescape(cookie_data));
chardata.skills = TAFFY(chardata.skills);
}
}
}


The biggest stumbling block came from the fact that assigning chardata to a temporary var (and then stringify-ing it) changed my Taffy object into a string. Cloning the db fixed the issue.

Sunday, August 2, 2009

Saturday, August 1, 2009

Edit spells screen


Spells screen loads the available spells for the class, and prevents you from selecting more spells than allowed by the "spells known" table.