Internet Sales Tax

In case you were wondering, I have decided that I am opposed to the current proposal to tax internet sales transactions.

I am, generally, sympathetic to the problem of lost revenue and competitive advantage given to online vendors over bricks and mortar. It's a distortion in the market that could encourage a death spiral where anyone in my neighborhood has to be driven out of business because they have a structural price disadvantage - at least if you ignore shipping.

However, I note that sales tax is considered to be the most regressive way to get revenue. It makes me a little suspicious when we have Republican support for a tax increase. If they support it, I figure it's going to turn out badly for me.

But, more important is the part where it makes it so that we are all at risk of being involved with any tax authority in the country whenever we do business on the internet. This seems to me a little like searches at airports. Sure, there's a 'reason' but it is actually a checkpoint where you have to ask the government for permission to travel.

I suspect that adding sales tax to the internet will be another way that we put an instrument on the net that will put more of us in a position to be troubled by the government. Unlike a garage sale, the internet keeps a record. That means that the piece of Craig's list crap you sell to someone in Alabama, well, that means the Alabama Dept of Revenue owns a piece of your ass.

If the sums were huge, I might still be swayed in support but, this tax will produce something like $23 billion. That's 5% of the defense budget, not including wars.

That tells me that there is something else going on. I don't know what it is but, when the corporatists in Washington get together to add a tax that will affect everyone that ever wants to sell something using the internet, I am very suspicious.

The Nasty Case of Two Bugs

Here's are the two bugs: The declaration of private was made one of the child classes but not in the parent.

Here's the behavior: A parent class makes an assignment to a property


when accessed by class A, it works fine, by class B, the assignment is not made.

It turns out that, I had tried doing this work in class B before I decided that the better strategy was to put it into the base class (for both A & B). When I abandoned that effort, I inadvertently left the property declaration (private $routeName) in class B. It never was in class A.

The base class already had a property of that name. What I did not know is that, despite the long list of declarations that prove my intention to declare all properties, $routeName was not, in fact, declared.

That means that, from the base class perspective, the property could not be assigned. Incredibly, though I have PHP set to complain about everything, it did not complain about this attempt to assign to a private property. It failed silently and, since I was focused on the base class, inscrutably.

Once I noticed that the property wasn't declared in the base, I did so and it worked.

I experimented and found that, if I removed the declaration from the child class B, it worked. If I changed the declaration to protected, it worked just fine, too. (Much to the consternation of a co-worker who considers it blasphemy to have a declaration in a child class be available to a parent.)

Of course, the correct solution was to remove the declaration from the child, add it to the parent, and get back to work.

Testimonial: SpamSieve Is Awesome!

(I usually focus on programming topics here but, having recently built a new computer and watched the miracle that is SpamSieve's Bayesian filtering, I wanted to make my enthusiasm available to the internet in the hopes that the SpamSieve people enjoy greater success and that some people will stop living in spam hell. It makes more sense here than on any of my other blogs.)
Macintosh using friends, if you are not using SpamSieve, your life can be better.

I have been using the same email address since the middle nineties. I have never concealed it either. I use it to sign up for stuff, on blog posts, everywhere. As a consequence, I get spam. Lots of it. Yesterday, I got 104 spam email messages and that's pretty much every day for me.

But, I use SpamSieve so I never see any of them. Well, almost never. I see one or two every couple of days. Then, I tell SpamSieve that I don't like them and they disappear. Actually, a whole other category of spam disappears. It's amazing.
It's kind of fun, actually. All of a sudden the spamsters will get a new idea and I will see a bunch of spam. Eeek! I say to myself and I will point out their spammyness to SpamSieve. The next day there might still be a couple. Then, none. I'll check the SpamSieve discard folder and, there they are, out of sight.

I review the discard folder every once in awhile to see if it is mad at anyone I like. It does happen. Well, by "does happen", I mean, I can recall some incidents. Like, five times in my life after the first few weeks of a new installation.

Here's another amazing thing. If you set up your email right (imap!), SpamSieve running on your main Mac will remove the spam from your iPhone, too. And your iPad. And you iPod Touch. And your other Macintosh. It is a miracle.

SpanSieve costs thirty bucks but it is the best thirty bucks you will ever spend. If you ever wanted to know if something was worth it, here's one occasion where you can actually know the answer: TQ White II, computer ace, has used this software for years and says, "It works like a miracle."

And that information, my friends, is a gift. Enjoy!

Screwy qTip2 Behavior Bug Report

The qtip is supposed to be pointing to the top left of the word, Terms. Instead it's pointing to the bottom left:

But right next to it, set up in the same way, the word Delivery has it's tooltip correctly placed at the top left of the target:

And if I reorder the display without changing anything else, the tooltip moves to its proper place:

The bad tooltip also flickers, though I suspect that's because the tooltip is placed over the target.

Here is the html table visible in the screenshot:

<table style='width:690px;text-align:center;'><tr>

<td style='width:200px;text-align:center;'><span class='tooltipAbove' title='Call us at xxx/xxx-xxx and we will set you up.'>Refund</span> &bull; <span class='tooltipAbove' title='Information entered is only used to fulfill this order.<br/>It is never shared with anyone. Period.'>Privacy</span></td>

<td id="copyright">&#169; 2012 Ten Sigma. All Rights Reserved.</td>

<td style='width:200px;text-align:center;'>
<span class='tooltipAbove' title='This product is activated using our website<br/>at'>Delivery</span>
<span class='tooltipAbove' title='If you do not wish to pay immediately by credit card,<br/>please contact us at xxx/xxx-xxxx and we will work something out.'>Terms</span>


(Be quiet. I like to make it look good and move the styles to class later.)

Here is how the qTip is activated:

position: {
my: 'bottom left',
at: 'top left'

Any thoughts?

C# Scope

This makes no sense to me. 

The situation:

public OutputType functionName(){

MyDataType myVarName; // <-- proper declaration here

foreach (something in something){ 
if (some condition){
return f(myVarName); // <-- uninitialized local variable error here

I get an error that myVarName on the last line is uninitialized. Stepping through shows that the variable is being assigned correctly in the foreach block. 

I read the web and it says that variables are scoped to the block in which they are declared. Since that's exactly what I have, I am very confused.

For no real reason, I try this:

public OutputType functionName(){
MyDataType myVarName;

myVarName=doodle; // <-- frivolous assignment

foreach (something in something){
if (some condition){
return f(myVarName); // <-- no error

And it works fine.

This tells me that local variables are scoped to the block in which they are first assigned

Even thought that specifically contradicts


Safari Screws Up Dates!

I just spent an annoying hour dealing with the fact that Safari's Javascript engine does not correctly parse standard (ECMA-262) date strings.

Here is a valid date string (coming from my database server):


Creating a date object is simple:

dateObj=new Date('2012-01-31T00:00:00');

and this works great in every browser except Safari. Safari tells you you have an "invalid date".

After screwing around way too much, I found that this works:

dateObj=new Date('2012/01/31');

And so, I changed my code to:

dateString='2012-01-31T00:00:00'.replace(/t.*$/, '').replace(/-/g, '/'); //ie, '2012/01/31'
dateObj=new Date(dateString);

I'm guessing that, if you needed the time, you'd have to split that off the string and use:


but I don't have time, or need, to figure that out now.

sftp/scp fails at connection, but ssh is OK

The brilliant people at Server Grove just helped me solve a nasty problem.

My SFTP access to my Linux (Ubuntu) web server was working fine. Then one night, I was working and it died in the middle of a session. I tried everything I could think of to no avail. 

The next day it worked again for a few minutes. Intermittent sucks even more. Then it died again.

Among the things I note: other user accounts worked fine for SFTP and SSH into the problem account worked correctly.

What I didn't note is that a change I made to .bashrc had a syntax error. I didn't notice this because 1) I always have .bashrc tell me things so the error message was lost in a few lines of other stuff and 2) the error caused no problems.

Turns out that latter statement was wrong. SFTP, as you may know, uses SSH for access. When I SSH into that account, I had .bashrc remind me of some things. SFTP apparently knows how to turn those off and, thus, work ok. It does not turn off error messages.

So, when the erroneous .bashrc was moved out of the directory, SFTP worked. When I fixed it, it worked.

So, if SFTP (or SCP or any other SSH-based utility) fails while SSH is still working, look to .bashrc. I don't know if it's only error messages that cause trouble but they definitely do.

And thanks, Server Grove, for helping me with this. I've always been very happy with their service. Their prices are reasonable and systems good. Going the extra mile to help me is icing on the cake.

A New Mission for the Darkside

My occupation is to create rich internet applications that access business databases. There is no advertising. Search engines are irrelevant. I make tools for business people to enter, examine and update data for various purposes. The results are usually supposed to resemble the dedicated client applications of yesteryear with immediate feedback for errors or lookup data, dynamic entry forms that change in response to user choices, etc. If this sounds like the modern world of AJAX websites, it should. Over the last couple of years, that has become my specialty.

It's not easy, though. As far as the web has come for rich internet applications, there still aren't tools that make this simple. In my old days, I had a gui application that allowed me to drag a data field onto a canvas, open a control panel that allowed me to connect it to a database field or calculation, specify the focus and blur behaviors, and trigger all sorts of events. Even then it was complex but, now that it is done in Javascript, talking to a server in PHP or C#, and using HTML/CSS for presentation, it's a bear.

It turns out that my real world is rarely a 'green field' application. With one exception, I have not been able to design the database. There are incumbent client applications that people are using to address the database. My mission is to, more or less, port certain functions to the internet based on an existing database server. 

I come to this with a bias in favor of browser-based applications. I don't have to worry about IE6. My clients are not allowed to use that. I don't care about search engines. Nobody without a password is ever allowed to use my work. All of my users have Javascript. At most, I support the previous two versions of the main programs and I'm not very fussy about that. Almost everyone I work with uses Safari, Firefox or Chrome. Those update automatically so, again with some exceptions, if it works for me, it works for others. Graceful degradation? Nope. It's my way or the highway and that's the way my clients like it.

I have settled on a simple architectural plan. The server serves data. The user interface is entirely in the browser. Except for the <script> tag that calls the javascript application, my web servers send absolutely no html. AJAX requests ask for data. That returns in JSON. The only exception to this is reports and exports. I have apps that generate a file as a side effect and return, in JSON, a way to retrieve it.

Because of this, my server code is rudimentary. Given that I am mostly working with existing database apps, complex data retrieval and manipulation is already done. My server code accesses that and puts it into JSON. This isn't always trivial, but often is. I do use an MVC framework (.NET MVC or ZEND these days) but it's mostly overkill. There are, for example, only a couple view templates. One for JSON that is used all over the place and another for database manipulation (it does a post to the controller of my choice for debugging).

My main focus is on the UI code in Javascript. For this I also use an MVC framework, JavascriptMVC. It provides numerous utilities that allow me to organize my code into comprehensible files and folders. It also includes good utilities for communicating among classes. It's a pretty sweet product.

I will be talking, for the moment, mostly about two applications. One is a tiny sales contact data entry app. The other is a huge gradebook application for school districts. These represent the extremes of my world. Often, I will pioneer a technique in the small one and then use it in the big one.

As it was when I was learning Windows and C#, this is my lab notebook. Though I am not a novice at this Javascript game as I was with those, I still keep learning things and need a place to write it down.

Sharing Windows 7 files

I run Windows 7 on a Macintosh using Parallels 5. It is an incredibly good thing. It has a display mode called Crystal that entirely hides the Windows desktop and controls. The only thing you see are windows. They appear in the Dock like good little windows. Parallels has settings that allow you to map your command key functions to control key functions so well that I basically never use the actual control key. It does flawless copy/paste and file dragging. Except for the unescapable details (close box on top left, menus inside the window, crappy UI detailsI), it is easy to forget which is which. So much so that I chose a pink colored theme for my Windows windows so that I could distinguish them in Expose.

Anyway, that's all been wonderful but, I still am stuck with the crappy UI details and Visual Studio. Visual Studio is reputed to be great and, I think it is. When I am working on .NET/C# things, it's "Intellisense" is nothing short of wonderful. It knows everything about what I want to do. The "Go To Definition" operation is a dream come true. There are some drawbacks but the benefits are well worth the trouble.

When working on Javascript, not so much. It doesn't fold code well. It is sluggish. It has the annoying UI defects. All the drawbacks and no benefits. I have long wanted to work in my trusty, old bbedit. It's a very clean text editor. No Intellisense but great regular expressions. It's fast as can be. It has all the UI perfection that Apple can offer. It is good.

So, I decided to figure out how to share the javascript project directory so that I can use the tool I prefer and that is the main point of this post.

It wasn't easy. It isn't intuitive. It requires doing things that make no sense. Fortunately for you, I boiled it down into a few simple steps:

1) Navigate to the folder you want to share. Right-click and choose Properties-> Sharing Tab->Advanced Sharing. It will let you type in a name. This is the name that will appear when you log into the sharing server you are about to create. Click Add and Close. For you who know about such things, I believe that you have just created a Mount Point. While you are still looking at the Sharing tab, not the Network path. You can select and copy it if you want. You will need to know the first part, the server name, later.

2) In the Windows control panel, choose Network And Sharing Center.
-- You'll see a little house that says Network next to it. If you have not already done this (and why are you reading this if you have?), it will probably say Work Network underneath that. Whatever it says, click it. You will be presented with three options. I tried Home and Work. Home is the one that worked best.

-- It will show you another page that lets you select your libraries. I don't have or want any of the things it shows so I clicked them Off. (In an early iteration, I selected Documents. It did no good.) Then click Finish.

--It will offer you a random password. I never found a use for it and it is easy to change (Network and Sharing Center->Choose homegroup and sharing options (middle bottom)->change the password. But, as I said, I never found a place where I could type it.

-- Also, since I am working on a virtual machine, I do not keep a password on my Windows login. When I tried to access the new server from my Macintosh with my userId and (blank) password, it said the password had expired. To workaround this, I went to Network and Sharing Center->Change advanced sharing settings (left column - great UI!, not) and clicked "Turn of password protected sharing". If you read carefully, this allows guest access to the shared folder. Since I am, technically, visible on my office network, I also clicked "Turn off network discovery" to reduce my visibility.

3) Back on the folder you want to share, right-click and, about a third of the way down is a selection called Sharing. Do this and choose, homegroup (read/write).

4) On that same tired folder, right-click->properties->Security. Click Edit, then Add. There you will see a place where you can Enter an Object Name. Enter "everyone" (without the quotes). Click Check Names. It should capitalize the word. Then OK. You will see the list of "Group or user names." Make suer 'everyone' is selected and, in the panel below, choose Full Control. Then OK to get out of that property panel.

Back on your Macintosh, go to the find, do command-k (Go->Connect to server). Enter smb\\SERVERNAME (the one I told you to notice in step one). This should present you with a dialog box for your userID and password. If you have a password, use this. Else, choose guest. The system should present you with a list of mount points, the one you made and one called User. Choose the one you made.

I made it so that this pointed at my javascript project. I created a bbedit project for it and have been editing nicely since. Interestingly, if I have editors open on both sides (Visual Studio and bbedit) looking at the same file, it takes care of the potential conflict. If I change it on the Mac side and save, when I click on Visual Studio, it tells me it changed and asks if I want to load the changed version. If I change it on the VS side, bbedit just changes the file I am seeing.

Cool stuff.

IE 8 is no better

Today I spent a long time debugging an error in IE8 that said "Object doesn't support this property or method."  It was in some testing code. The line was:


This works perfectly in Firefox.

The solution? You're gonna love this. "hello" is a reserved word in IE. Change it to:



Oh, but that's not all. IE8 has it's own definition of window.setTimeout(). 

The rest of the world defines it thus:

setTimeout(function, milliseconds, arguments);

The 'arguments' are passed to the function when the 'function' is called after the timeout.


setTimeout(function, milliseconds, language);

Language? It very nicely explains that you can't pass arguments to the callback function. It doesn't explain why it doesn't do this obvious thing that everyone else does.


timeoutProxy= function(func, milliseconds, scope, args) {

    if ($.browser.msie == true) {
            setTimeout(function() {
                        func(scope, args) 
            }, milliseconds);
        else {
            setTimeout(func, 1000, scope, args);


timeoutProxy(setAcceptClicks, 500, this, {});