## Improved flexcal

Two new additions to flexcal, which is now at version 2.2. See the code and a demo, that uses my new github pages.

### Mouse Wheel

The calendar now responds to wheel events, changing the month with scroll up/down and changing the calendar tab with scroll left/right. I initially tried to throttle it since my trackpad was too sensitive, but that made it too slow. I'm not sure waht to do about that. It works well with an actual mouse wheel, thoug.

### Keith Wood's Calendars

Keith Wood is maintaining the jQuery plugin that eventually became the official jQuery UI datepicker. His version, however, handles multiple calendar systems, much like flexcal (though I like my plugin, of course). His code is on github, and the documentation is on his personal site. He has support for many calendar systems, and I wanted to let flexcal use that. I don't use his datepicker code, just the calendar systems.

I'm using a naming convention of language-calendar, like he-jewish for a calendar localized to hebrew, using a Jewish lunar calendar. It's the opposite of Woods, who uses calendar-language, like islamic-ar for a calendar localized to arabic, using the Islamic lunar calendar. For my names, the default language is en and the default calendar system in gregorian. Thus, islamic would be an English language Islamic calendar, and zh-TW would be a Taiwanese Chinese Gregorian calendar (my parser is smart enough to not be confused by the extra hyphen). The language codes are ISO 639 two-letter codes.

There is a new function, $.ui.flexcal.tol10n(name) that creates a localization object with appropriate language and calendar system. It is designed to be transparent; doing$('input').flexcal({
calendars: ['ar-islamic']
});

will look in the existing $.ui.flexcal.l10n object for 'ar-islamic', then try to find it in the jQuery UI datepicker localizations (if those are loaded) (note that jQuery UI only uses Gregorian calendars), then Woods's calendars if they exist. You can use the bridge directly if you want;$.ui.flexcal.tol10n(name) returns a localization object that you can modify as desired and then pass to flexcal.

To use this, you need to include the necessary script files: jquery.calendars.js for the basic code, jquery.calendars.name.js (like jquery.calendars.islamic.js) for the calendar-system-specific routines (these are all in English), and jquery.calendars.name-language.js (like jquery.calendars.islamic-ar.js)for the language-specific localization, or jquery.calendars.language.js for language-specific localization using the Gregorian calendar.

Of note, the text that is used for the "Next Month" and "Previous Month" is localized for the datepicker, not the underlying calendar system, so if you want that included automatically, also include the jquery.calendars.picker-name.js. I have a little hack in flexcal so you do not have to include the entire jquery.calendars.picker.js package; just include the jquery.calendars.picker-mock.js before including the localization code.
It should be clear which files to include if you look at the list.

### TODO

His calendar code also has some nice formatting options, which flexcal does not have out of the box, though it is possible with some work. I'd like to get a bridge to work with my code as well.
Some other options that would be nice include: setting the first day of the week (now is fixed at Sunday) and having the option of showing or selecting days from other months.

## Creating a PowerShell shortcut

I'm sure there must be an easier way to run a program from PowerShell, but I haven't found anything simpler than

with the ampersand and the full path. I could add "C:\Program Files (x86)\Notepad++" to $env:PATH, but I'd still have to type notepad++.exe file. I wanted some way to make a shortcut to a program name without having to create a new file, either a .LNK or .BAT file. Turns out you can do this with PowerShell functions: function npp { & "C:\Program Files (x86)\Notepad++\notepad++.exe"$args }

lets me run Notepad++ from PowerShell without nearly so much typing. Stuck that in my Profile.ps1 and now I'm happy.
Hope this turns out to be useful to someone.

run: $.post(url, {data: data}).then( function() { return 'Data Saved' }, function() { return new Error('Data Not saved') } ) }); And the output will go to the console rather than to an element on the page. For simple output to the console, this is far more complicated than console.log, but it works with the rest of the status options. Input is with window.prompt, since I don't know how to get input from the console. ## Rethinking$.fn.sendkeys

See the demo.
See the source code, which depends on bililiteRange.

Modern browsers won't let synthetic events (triggered with dispatchEvent) execute their default actions (meaning the action that would occur if the event was triggered by a user action). The Event object has a read-only field called isTrusted that is false for anything but unmodified user-initiated events. These are called "trusted events", and I understand the justification, but they go too far. It makes it impossible to implement a virtual keyboard, since triggering keydown or keypress events aren't trusted and won't insert the character (the default action).

Fortunately, bililiteRange and especially bililiteRange.sendkeys can insert characters and do other manipulations on the page. So I created a jQuery plugin that uses bililiteRange.sendkeys to catch keydown events and implement them as well as possible.
Just include the source code and keydown events get a new default handler (so it can be cancelled by preventDefault) that looks at the key field. If it is a single character, that character is inserted at the selection. If it is more than one character long, it is assumed to be a sendkeys command like ArrowLeft and is sent as sendkeys('{'+key+'}').
I used the modern Event.key rather than Event.which, so I don't have to translate keyCodes. If you need to use the old way, see my keymap plugin.

Thus now, $('textarea').trigger({type: 'keydown', key: 'A'}) will work as expected, as will$('textarea').trigger({type: 'keydown', key: 'Backspace'}).

### The actual plugin

Under the hood, this uses a very simple jQuery plugin that just calls bililiteRange.sendkeys(). It also turns '\n' in the string into '{Enter}', which I thought would be useful but has actually not turned out that way. Putting the '\n' in braces ('{\n}' prevents the replacement.
The plugin itself is:

$.fn.sendkeys = function (x){ x = x.replace(/([^{])\n/g, '$1{enter}'); // turn line feeds into explicit break insertions, but not if escaped
return this.each( function(){
bililiteRange(this).bounds('selection').sendkeys(x).select();
this.focus();
});
};

### Demo

$('.selectoutput').click(function(){$('.output').removeClass('selected');
var index = $(this).parents('th').index();$('.output').eq(index).addClass('selected').focus();
});
$('div.test input:button').click(function(){$('.output.selected').sendkeys($('div.test input:text').val()); });$('div.wrap input:button').click(function(){
var tag = $('div.wrap select').val();$('.output.selected').sendkeys('<'+tag+'>{selection}{mark}</'+tag+'>');
});
$('.phonepad input').click(function(){$('.output.selected').trigger({type: 'keydown', key: this.name || this.value});
});
$('.output').each(function(){ bililiteRange(this); // initialize the selection tracking }).on('keydown', function(evt){ if ($('#overridepad').is(':checked')){
evt.preventDefault();
}
}).on('keypress', function(evt){
$('#keypress').text($('#keypress').text()+' '+evt.which);
}).on('sendkeys', function(evt){
$('#sendkeys').text($('#sendkeys').text()+' '+evt.which);
}).on('focus', function(){
var index = $(this).parents('td').index();$('.output').removeClass('selected');
$('.output').eq(index).addClass('selected')$('.selectoutput').eq(index).attr('checked',true);;
});

<div>
<table style="width: 100%" border="2" id="demo" >
<tr>
<th><label>
<input type="radio" class="selectoutput" name="selectoutput" checked="checked" />
<code>&lt;input&gt;</code>
</label></th>
<th><label>
<code>&lt;textarea&gt;</code>
</label></th>
<th><label>
<code>&lt;div contenteditable&gt;</code>
</label></th>
<th><label>
<code>&lt;div&gt;</code>
</label></th>
</tr>
<tbody>
<tr>
<td><input type="text" class="output selected" /></td>
<td><textarea class="output"></textarea></td>
<td><div class="output" contentEditable="true"></div></td>
<td><div class="output" >This is not editable text</div></td>
</tr>
</tbody>
</table>
<input type="button" name="ArrowLeft" value="&larr;"/><input type="button" name="ArrowRight" value="&rarr;"/><input type="button" name="Backspace" value="BS"/><input type="button" name="selectall" value="All"/><br/>
<input type="button" value="7" /><input type="button" value="8" /><input type="button" value="9" /><br/>
<input type="button" value="4" /><input type="button" value="5" /><input type="button" value="6" /><br/>
<input type="button" value="1" /><input type="button" value="2" /><input type="button" value="3" /><br/>
<input type="button" value="*" /><input type="button" value="0" /><input type="button" value="#" /><input type="button" name="Enter" value="&crarr;"/>
</div>
<div class="test"><input type="text" /><input type="button" value="test"/></div>
<div class="wrap"><select><option>em</option><option>strong</option><option>del</option></select><input type="button" value="Wrap Selection"/></div>

<div id="keypress">keypress event.which:</div>
<div id="sendkeys">sendkeys event.which:</div>
</div>
<div style="clear:both" />

The phone pad keys use $().trigger({type: 'keydown', key: key}). The test button does$().sendkeys(textbox.value). The wrap button does $().sendkeys('<tag>{selection}{mark}</tag>'). Note that the trigger code does not affect the non-editable DIV, while sendkeys does. The "Alert on keydown event" checkbox attaches a handler to the keydown event which calls event.preventDefault, showing that the text entry and keypress events do not occur. ## bililiteRange.sendkeys bililiteRange.text() works well to insert text into ranges, but I wanted to be able to simulate other keys, ala Microsoft's SendKeys. bililiteRange.sendkeys() does exactly that. It basically executes text(string, 'end') but interprets any text between braces ('{key}') as a command representing a special key. For security reasons, the browser won't let you do anything outside of the text of the page itself, but I've implemented the following (the key names are from the proposed DOM3 standard):: Backspace Delete backwards Delete Delete forwards ArrowRight Move the insertion point to the right ArrowLeft Move the insertion point to the left Enter Insert a newline, with bililiteRange.insertEOL(). Warning: In contenteditable elements, Enter is flaky and inconsistent across browsers. This is due to the flakiness of contenteditable itself; I can't figure out what to do about this. For backwards-compatibility with older versions, the following synonyms also work: backspace, del, rightarrow, leftarrow and enter. So, for example, bililiteRange(el).sendkeys('foo') replaces the current range with 'foo' and sets the range to just after that string. bililiteRange(el).sendkeys('foo{Delete}{ArrowLeft}{ArrowLeft}') replaces the current range with 'foo', removes the character just after that string and sets the range to between the 'f' and the 'o'. To manipulate the selection, use the usual bililiteRange methods. Thus, to simulate a backspace key, use bililiteRange(el).bounds('selection').sendkeys('{Backspace}').select(). To insert a '{', use an unmatched brace, bililiteRange(el).sendkeys('this is a left brace: {'), or {{}, as in bililiteRange(el).sendkeys('function() {{} whatever }');. If anyone knows how to implement an up or down arrow, or page up/down, please let me know. ### Other Commands To make life easier for me, there are a few other "keys" that implement specific actions: selectall Select the entire field tab Insert a '\t' character.$().sendkeys('\t') would work just as well, but there are circumstances when I wanted to avoid having to escape backslashes.
newline
Insert a '\n' character, without the mangling that {enter} does.
selection
Inserts the text of the original selection (useful for creating "wrapping" functions, like "<em>{selection}</em>").
mark
Remembers the current insertion point and restores it after the sendkeys call. Thus "<p>{mark}</p>" inserts <p></p> and leaves the insertion point between the tags.

So to wrap the text of a range in HTML tags, use range.sendkeys('<strong>{selection}</strong>'). To create a hyperlink, use range.sendkeys('<a href="{mark}">{selection}</a>') which leaves the range between the quote marks rather than at the end.

### Plugins

Adding new commands is easy. All the commands are in the bililiteRange.sendkeys object, indexed by the name of the command in braces (since that made parsing easier). The commands are of the form function (rng, c, simplechar) where rng is the target bililiteRange, c is the command name (in braces), and simplechar is a function simplechar (range, string) that will insert string into the range. range.data().sendkeysOriginalText is set to the original text of the range, and rng.data().sendkeysBounds is the argument for bililiteRange.bounds() that will be used at the end.

So, for example:

bililiteRange.sendkeys['{tab}'] = function (range, c, simplechar) { simplechar(rng, '\t') };
bililiteRange['{Backspace}'] = function (range, c, simplechar){
var b = rng.bounds();
if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character
rng.text('', 'end'); // delete the characters and update the selection
};
bililiteRange.sendkeys['{selectall}'] = function (range, c, simplechar) { rng.bounds('all') };

So to have a reverse-string command:

bililiteRange['{reverse}'] = function (range, c, simplechar){
simplechar(range, range.sendkeysOriginalText.split('').reverse().join(''));
};

Or, to annoy the anti-WordPress crowd, a Hello, Dolly command:

bililiteRange['{dolly}'] = function (range, c, simplechar){
var lyrics = [
"Hello, Dolly",
"Well, hello, Dolly",
"It's so nice to have you back where you belong",
"You're lookin' swell, Dolly",
"I can tell, Dolly",
"You're still glowin', you're still crowin'",
"You're still goin' strong"];
simplechar (range, lyrics[Math.floor(Math.random() * lyrics.length)];
};

### Events

After each printing character (not the specials, unless they call simplechar) it triggers a keydown event with event.which, event.keyCode and event.charCode set to the Unicode value of the character.
After the entire string is processed, it triggers a custom sendkeys event with event.which set to the original string.

## Rethinking $.keymap Dealing with keydown events is a pain, since the event object has always encoded the key as an arbitrary numeric code, so any program that deals with key-related events has something like: var charcodes = { 32 : ' ', 8 : 'Backspace', 20 : 'CapsLock', 46 : 'Delete', 13 : 'Enter', 27 : 'Escape', 45 : 'Insert', 144 : 'NumLock', 9 : 'Tab' }; And so on. There is a proposal to add a key field that uses standardized names for the keys, but only Firefox and IE implement that right now. The time is ripe for a polyfill to bring Chrome and Safari into the twenty-first century, and I'd already worked on something similar with my$.keymap plugin.

So I updated that plugin to simply implement the key field in keydown and keyup events. Now just include the plugin and you can do things like:

$('textarea').keydown(function(event){ if (event.key == 'Escape') { do something useful } }); ## Scribblish We love playing Scribblish. It's like the old Telephone game but with pictures, with players alternating writing captions for pictures and drawing pictures for the captions. It's most fun as a non-competitive party game, just reading the cartoons at the end of each round. It's useful as well: we taught it to my daughter's then-boyfriend and said not to take so much time on detailed drawings; they should look like XKCD. And he knew what I was talking about! Obviously a perfect match. They were married the next year. Unfortunately no one else seemed to share my family's passion, and the game was discontinued. You can't get replacement pads any more. So I printed my own (it's just a bunch of lines on a sheet of paper cut in thirds). And I wanted to leave it here so I could find it again: Scribblish-style pad ## Running Windows XP in Windows 8 I wanted to run some of my old games (notably Riven) on my shiny new Windows 8.1 machine, but it wouldn't even try to install on a 64-bit operating system. Luckily, Oracle offers VirtualBox to run virtual machines, and Microsoft offers a Windows XP virtual hard drive (.vhd file) through its Windows XP mode for Windows 7. Note that it won't run directly on Windows 8, but you can extract the .vhd file as outlined by lifehacker: Then use 7-Zip open the EXE file as an archive. Within that archive, find the sources/xpm file within it, and extract that folder to your hard drive. Finally, in the extracted xpm file, you'll find a file called VirtualXPVHD. Export it and rename it to VirtualXPVHD.vhd In VirtualBox, create a new virtual machine running Windows XP, and instead of creating a new virtual hard drive, use the one created above. This will give you a new virtual machine that will require you register within 30 days, which you can't do (since Windows XP isn't supported anymore). We'll fix that later. Start up the virtual machine, deal with the craziness of mouse capturing (toggle the right control key to get the mouse back) until you install "Guest Additions": In the "Devices" menu in the virtual machine's menu bar, select "Insert Guest Additions CD image" then run that installer in the virtual machine. Now the mouse should integrate smoothly. In the VirtualBox Manager, in the Network tab, unclick "Cable Connected". You don't want this virus-friendly operating system talking to the internet! To activate Windows XP, you can try the file named KEY in the exe file with the virtual hard drive, but the comments on lifehacker indicate it won't work. I got a new bios from vmlite, and install it as: path\to\VirtualBoxFolder\VBoxManage.exe setextradata your-vm-name "VBoxInternal/Devices/pcbios/0/Config/BiosRom" "path\to\pcbios.bin" And it all seems to work. I don't feel guilty about using a pirated operating system license, since I am running Windows 8 legally, and Microsoft won't sell me XP. Installing CD's is a pain, and Riven wants to keep swapping them, but making them virtual images makes it much easier. Install ISORecorder (the Windows 7 version works with Windows 8) and now the contextual menu (right-click) for CD's includes a "Create Image from CD" option. Save with the iso extension, and VirtualBox will mount them just fine. Unfortunately, I now do not have any time to play anything. ## Setting up git Now that I have my computer working, I want to get back at my github repositories. I could type my password with every push, but it's easier to use SSH with a key pair. Since I'm using Putty for shell access, I use Puttygen that comes with it. The problem is that Puttygen's format is not the right one for git. There are recommendations online to set$GIT_SSH to use plink with Pageant, which does use Puttygen's format, but I read that github won't support that, so I ended up doing the following:

Create a key pair with Puttygen. In the conversion menu, create a file in openSSH format. Create the file ~/.ssh/config:

Host github.com
User git
IdentityFile /path/to/openssh-format-privatekey

At github.com add the public key that you created. Back in Powershell, in the directory with the local repository, do

to use SSH. Now git push origin master will push the local master branch back up to github without needed a password (if you created the private key with a passphrase, you will have to enter that.

In putty, for each host, set Host Name in the Session tab and select the private key (in Puttygen format!) in the Connection->SSH->Auth tab.

## Working with Amazon S3

I use Amazon S3 for static storage, since nearlyfreespeech.net charges for storage. I've written how I've set up my .htaccess and my PHP files to use it. But now my work has decided to block all access to S3 (as "personal storage sites"), so I can't use my bililite.s3.amazonaws.com sites any more.

But I'm smarter than that; I'll just use a CNAME DNS entry to point to the S3 site. They're not blocking cdn.bililite.com. Unfortunately, it's not that simple. Amazon uses the domain to determine the bucket, so cdn.bililite.com has to point to cdn.bililite.com.s3.amazonaws.com. (remember that external CNAME's have to have the extra period at the end!), meaning the bucket called cdn.bililite.com, and I have been using bililite as my bucket name.

You can't rename a bucket. So I have to create a new bucket called cdn.bililite.com, and now I have to copy all the files from the old one. That's also not so simple, since downloading from one bucket and uploading to another takes forever for thousands of small files. Luckily, Amazon has created a command line interface to S3 that lets you do in-the-cloud copying.

aws configure

and enter your AWS keys (you can enter a default region as well). Note that these are kept in plaintext in ~/.aws/credentials, so keep your computer safe!

Then, aws s3 ls will list all of your buckets, and aws s3api get-bucket-location --bucket bucketname will list the region. None as a region name means us-east-1, as far as I can tell.

To copy the entire bucket, do

aws s3 cp s3://source-bucket s3://target-bucket --recursive --region region-of-target-bucket --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers

(if the region is the default region you set up with aws configure, you can leave out the --region option. I wasn't smart enough to include the grants option, which makes the copied objects public (hence read=AllUsers), and I couldn't figure out how to change the permissions with the command line interface, so I had to go back to the online Amazon AWS console and set the permissions there (open the bucket, select all the folders, and select "Make Public"). That took more than an hour, but at least it was in the cloud, not running on my computer.

Now, in order to be able to load things like fonts which obey the cross origin restrictions (why fonts? I don't know. AJAX I can sort-of understand), in the AWS console, under Permissions select Edit CORS Configuration to:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>

Now I have Amazon S3 access that is not blocked!