Arrow

Posts on this site are never sponsored.

XE Trade USD-CAD exchange rate spread: avoid weekends and holidays!

I’m a fan of XE Trade for making online currency transfers, and most of all for sending money internationally.

If you go to xe.com, you’ll find the mid-rate exchange rates. The rates provided by XE Trade are always “worse” than the rates on xe.com, since XE Trade adds their own margin. I’ve discovered that XE Trade rates are always even worse on weekends; I decided to record the spread on various days for the USD to CAD exchange rate. Here’s a sampling of the exchange rate spread from September 2014 taken on different days at random times of the day.

Date Day of week xe.com XE Trade Spread
September 1 Monday (holiday) 1.08681 1.123 0.03619
September 2 Tuesday 1.09040 1.1066 0.0162
September 3 Wednesday 1.08991 1.106 0.01609
September 4 Thursday 1.08414 1.1008 0.01666
September 5 Friday 1.08857 1.1051 0.01653
September 6 Saturday 1.08815 1.124 0.03585
September 8 Monday 1.09249 1.1086 0.01611
September 9 Tuesday 1.10285 1.1188 0.01595
September 12, 7:32am Pacific Friday 1.10713 1.1235 0.01637
September 12 Friday, 4:40pm Pacific 1.10935 1.1452 0.03585
September 16 Tuesday 1.10195 1.1178 0.01585
September 27 Saturday 1.11545 1.1515 0.03605

Bottom line: use XE Trade only on business days! Also, according to the sample from late on Friday September 12, you should make sure to do any currency trades before markets have closed. Based on my tests, the average spread on business days was 1.622%, whereas on non-business days it was 3.5985%. That’s almost a 2% difference.

On a related note, if you are making USD-CAD currency transfers within a business account in Canada, some of the banks’ currency exchange services might provide better rates than XE Trade. Specifically I’ve found that RBC‘s rates are often better than XE Trade. It’s much more of a pain trying to send money internationally from a business account using RBC, though!

Notepad++ empties and saves file: how to recover

I was using Notepad++ to edit a file in Windows 7 when the program suddenly emptied the file, saved the empty file, and crashed. Nevermind the fact that this was an alarming occurrence for a code editor, but I didn’t want to lose my work. I believe this was caused by its relatively new (in version 6.6.x) “session snapshot & periodic backup feature”, which I hope has since been patched. The problem has not happened since a couple of months ago, only happened once, and a few updates to 6.6.x have since been released. Although, since that occurrence I have been using Notepad++ less.

The good news about the periodic backup feature erasing all my work is that it was also the one that restored my work. I was able to find the folder C:\Users\<my_username>\AppData\Roaming\Notepad++\backup, in which there was a copy of the file just before Notepad++ had emptied it.

If you’re looking for a different code editor for Windows, check out the more fully-featured but not as lightweight Sublime Text or Netbeans.

Logging Varnish variables to a file

Much of the documentation regarding Varnish logging is around varnishlog (makes sense, considering the name), which parses the Varnish request and response logs from system memory. However, what about when you’re building or troubleshooting your VCL configuration file and want to dump specific variables or messages to a file? This is not widely documented but quite easy to do.

The key function is std.syslog. In order to use that function, you simply have to enable the std (standard) Varnish module, which is the only built-in “vmod” and is thus natively available and doesn’t have to be compiled.

To enable the std module, simply put this at the top of your VCL file:

import std;

Then, you can use it in any of the VCL functions like this:

std.syslog( 180, "VARNISH: Invalid cookie found." );

Or, add in some variables to your log message:

std.syslog( 180, "VARNISH: beresp.ttl is " + beresp.ttl );

This will log the message to general system messages log, which is often at /var/log/messages on Linux operating systems. The first parameter, which is 180 in the examples above, is the priority value.

Coast to Coast Hockey Shop review: roller hockey equipment in Vancouver

After having played indoor roller hockey for many years, I needed to replace my rollerblade (or “inline skate”) wheels and the accompanying screws.

I purchased some new wheels and bearings at The Hockey Shop in Surrey and had a good experience there. Unfortunately, my old screws were still coming loose every game. I could either buy some thread lock material to apply to the existing screws or buy some new screws. I waited too long and some of the threads got warped, so I decided to just buy some new screws.

At first, I couldn’t find a store that sold screw and axle kits for rollerblade wheels. In fact, someone at Sportchek told me that I shouldn’t even bother trying, as no one would carry such replacement screws for my old Mission skates anymore.

Thankfully, I found Coast to Coast Hockey Shop, which is a Vancouver-based online store that sells all sorts of inline hockey accessories, including wheels, bearings, bearing lubricant, tape, stick tape, and yes, screw / axle / bolt kits:

Mission roller hockey screws and axles

The owner, Sean, ships fast and even hand delivers sometimes in the Vancouver area (which is what happened to me). He was responsive, friendly, eager to listen to my needs, and seems to really know his stuff about all things roller hockey.

I found the Coast to Coast Hockey Shop website easy to use and full of great prices, and I highly recommend it. Sean is working on opening a retail store in Vancouver at some point soon (Update: Sean is partnering with Shop-Task on Main Street between 1st and 2nd Avenue), which I expect will be a very useful resource for indoor and outdoor inline skaters.

Changing the cursor position in TinyMCE

Many open source content management systems use TinyMCE for rich text / WYSIWYG editing, including WordPress, Drupal, eZ Publish, Joomla, Alfresco, and more.

Inserting custom layouts in TinyMCE can be accomplished by using the custom block feature, or “custom tag” in eZ Publish.

TinyMCE custom block

The problem with the custom block is that if you have multiple custom blocks adjacent to each other, nested custom blocks, or a custom block at the end of the rich text content, your cursor gets “stuck” at the bottom of the custom block. Pressing “Enter” on your keyboard will create a new line or paragraph within a custom block but you cannot create a new line or paragraph outside of the custom block without editing the source HTML or XML.

For eZ Publish, my company wrote a small TinyMCE plugin that will create a new line or paragraph directly after a custom block when “CTRL+Enter” is pressed on the keyboard.

Most of the plugin code is standard and well-documented functionality on how to create a TinyMCE plugin and generally manipulate HTML using JavaScript. The most challenging part was getting the code right to simply place the cursor at the beginning of the new paragraph (so that the user can continue to type and enter content there).

The most popular solution I found when searching was as follows, but it did not work in Chrome and other WebKit browsers: the cursor would simply stay within the custom block.

# ed is the TinyMCE editor instance, or tinymce.Editor
ed.selection.select( newParagraph);
ed.selection.collapse( false );

Other suggested alternatives that I could find were ed.focus(); and ed.selection.setNode( newParagraph );. I even tried a standard jQuery function $( ‘#target’ ).mousemove();

In the end, the solution that works in all standard browsers is to use the very aptly named setCursorLocation function, which appears to be documented only for TinyMCE 4.x, but also exists and works for TinyMCE 3.x.

I’ve pasted the code snippet below, and you can also see the full plugin file here.

ed.onKeyDown.add( function( ed, e )
{
    // Capture CTRL+Enter
    if( ( ( e.keyCode == 13 ) || ( e.keyCode == 10 ) ) && ( e.ctrlKey == true ) )
    {
        var dom = ed.dom;
        
        var parents = dom.getParents( ed.selection.getNode() );
        for( var i=0; i < parents.length; i++ )
        {
            currentNode = parents[i];
            // Insert empty paragraph at the end of the parent of the closest custom tag
            if( currentNode.nodeName == 'DIV' && currentNode.getAttribute( 'type' ) == 'custom' )
            {
                // dom.insertAfter doesn't work reliably
                var uniqueID = dom.uniqueId();
                jQuery( '<p id="' + uniqueID + '"><br /></p>' ).insertAfter( currentNode );
                
                // Move to the new node
                var newParagraph = dom.select( 'p#' + uniqueID )[0];
                ed.selection.setCursorLocation( newParagraph );

                // Don't create an extra paragraph
                e.preventDefault();
                break;
            }
        }
    }
});