I've been browsing about lately, and noticed the numbers of sites with "Beta" attached on the end. It's a stupid trend that I hope to see fall down and die sometime soon.

It all came to a head when a friend of mine showed me a news site - cincinnati.com - which says "BETA", of course in call caps, in a nice sans-serif font, white on a dark background. Like every other site out there. They didn't even bother dressing up the "BETA", it's as if they just looked at a handful of popular sites and copy / pasted it into Photoshop, and had their magic "trendy" logo.

There are two reasons that compromise 90% of "beta" websites out there: either it's some web designer who thinks he's gonna be "cool" like all of the newer sites (gmail was a beta for years! facebook and all those social netwokring sites were betas for a long time! maybe if we add "beta", we'll be popular too!). But, unfortunately, it makes you look like a total idiot. Sorry, dude, but how about trying originality instead? At least understand what "beta" means. Or, if it's not that, it's a cop-out for web developers. It says, "We'll call it a beta, so that if something goes wrong we can smile and say that we expected it, because it is, after all, a beta". It's an excuse pre-planned so that nobody has to take the blame. It's a way to get out of trouble.

It's really tacky.
Pop-up windows are one of the biggest UI blunders ever. They create seperation from your website, they detract from the main content, and they are far from a 'seamless' data entry mechanism.

Let's start from the beginning. One day, some developer thought to himself, 'Hey! I want my user to stay on our website, and stay on the page to he maintains state, but also to enter data. How can I do that?' After a little Javascript tinkering, he created a button / link / something that pops up a window with a form, or with a help section, or something. Fantastic!

But then, some internet advertiser said 'Hey! I want my consumer to see our ads, all ten of them, even if he moves to different sites.' So, he added javascript of his own, and the community responded with pop-up blockers. So, internet advertiser went back to normal banners. However, this left the first developer in a bit of a hard place. His website was developed with those pop-ups in mind... so what now?

First, never, ever, ever have the browser pop up a new window in the first place. Ever. There is absolutely no reason for it, and there are easy ways around it that can avoid pop-up blockers totally screwing your user experience: for example, modal windows. They're an extremely easy mechanism to put in place (you can even use frameworks, like Scriptaculous or components from the Ajax toolkit for .NET), and they get around pop-up blockers. And, not only that- but you don't have the issue of not being able to send commands to your parent window! In this, it lends itself heavily to Ajax applications, in that you can also update content on the main page after submitting data from the modal. Seamless transitions are the best; make your web app behave like a desktop app. You also know that your user won't be messing with anything on the parent, out of order with the pop-up. It fits everything in place and creates a nice flow to the website.

So, please, please remove your pop-up windows and stop keeping your users from having to disable pop-up blockers!

Lately, I've more or less been the go-to guy at work for Javascript issues. Several times daily, I've been helping other people out with Javascript (something I like to do; keeps me sharpened on the art of browser scripting), whether it be an issue with Ajax or something strange with variable initialization (check that your variable's not a keyword! make sure the src is set correctly!). So there I was, thinking myself somewhat of an expert on the subject, as my ego has a habit to coerce me into, until I came upon the Javascript "prototype". Not to be confused with the popular Javasript framework, but rather a method to add methods to objects. Essentially, it is a plausible way to extend current objects and really use Javascript as an object-oriented language. And what with my affinity towards C#, this was perfect.

I decided that I'd first start with my Ajax framework, DeviantAjax. The framework was something I started a while back, beginning with Gevalum's rudimentary system; I took the few base functions and threw them nicely in a file with comments. However, this wasn't exactly anything new or groundbreaking; I wanted to put out a framework that was simple and easy (KISS), but still offered more than any wizened developer could throw together in a matter of minutes.

DA, as we'll call it from here on out, would be different than the other frameworks (the three that come to mind are script.aculo.us, Prototype, and jQuery). It wouldn't include all of the animation stuff and all the extra DOM code of the others; rather, it'd be for Ajax alone. It'd be a way for beginners to use the magic and a way for gurus to get a head start on a project.

So, first things first: I began with a Page object. Pleased with this, I began to add things into it's prototype, like so:

function Page() {
    ajaxes = new Array();
}

Page.prototype = {
    SetAjaxRequestMax: function(ajaxObjectsToCreate){
        ...
    },
    FillElement: function (element,source,postData,ajaxObjectIndex){
        ...
    }
}


Excellent! I could make a new page - var MyPage = new Page(); - and it looked like good ol' C# (well, close enough, anyway.) I could even call MyPage.SetAjaxRequestMax(4)! And that was great, except now I wanted to add functions to FillElement. So, I added a FillElement.prototype block inside of my FillElement, with functions like Set, OnLoad, OnRequestOK, and OnRequestBad. Except... prototype doesn't quite work like that. You can't put the prototype declaration inside the FillElement function, as I found out after several hours.

So, instead, the framework began to look more like:


_ajaxObjectArray = new Array();

function Page() {
   
}

function EvalAjaxPost(){};
function SetAjaxRequestMax(){};

SetAjaxRequestMax.prototype = {
    Set: function(ajaxObjectsToCreate){
        if(window.XMLHttpRequest){
            for(x=0; x<ajaxObjectsToCreate; x++){
                _ajaxObjectArray[x] = new XMLHttpRequest();
            }
        }else if(window.ActiveXObject){
            for(x=0; x<ajaxObjectsToCreate; x++){
                _ajaxObjectArray[x] = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
    }
};

FillElement.prototype = {
    Post: function(element,source,postData,ajaxObjectIndex){
        ...
    },
    ...
}


Page.prototype.SetAjaxRequestMax = new SetAjaxRequestMax();
Page.prototype.FillElement = new FillElement();

Now it started working better. I'd set the AjaxRequestMax on the HTML file it was used in, and then I could initialize and use FillElement objects- FillElement.Post("div1",...);. Cool.

So, the purpose of prototype, and how it works:
Prototype is a way to add methods onto objects. For example, you could add functions onto strings, like so:

function Reverse(){
    for (n=this.length-1;n>=0;n--){
        document.write(this.charAt(n))
    }
}
String.prototype.writeback=Reverse();


And use it like "jack".Reverse(); and get a result. It's Monkeypatching at it's best. It also really lends itself to OO Javascript development, which is always a plus.

The next thing I'm trying to figure out is how to get other functions in the prototype (OnRequestOK, for example) to run on the FillElement object when I run Post and get a certain result. Feel free to leave any ideas in the comments, and otherwise I'll be posting part 2 soon.

Check out my testing page (which may or may not be broken, if I'm working on it) and the zip file for yourself; it's creative commons licensing, so do whatever you want.

Every time I listen to the radio, there's inevitabley a commercial along these lines:

"Are you unhappy in your job? Want to make more money? Be a part of the new and exciting IT Industry! Take our classes and become a Certified Professional..."

It's absolutely disgusting and wrong.

You shouldn't entice people into "the new and exciting IT Industry" by money. People who want to be in IT, should be in IT (sometimes not then, but that's for another topic), and people who think that some magical position in a software company is going to change their entire life, are going to find out the hard way that it won't. People who think to themselves, "I'm going to make a drastic career change because I want more money", are going to fail.

I'm not saying that someone can't learn to be a developer, or a network admin, or any of a variety of careers. I'm saying that you should be in a job that you like to do, and that you have a skill set and a natural disposition for. You can't just go through some distorted MCP bootcamp and expect to make it to the top, or even the bottom. You won't, unless you know what you're doing and you're good at it, and you want to do it for the sake of doing it.

Developing has a personality with it. It's not for everyone; it takes a certain mindset. The person who speeds through certifications for the sake of certifications (the idea of certifications being totally wrong anyway) is going to work horribly with others and is going to feel like an akward part of any team. IT has a certain passion to it that can't be faked, no matter what the radio advertisements will try to tell you in loud voices over techno music.
This one's been floating around the internet (although I appear to be late on the trend). However, here goes:

How old were you when you started programming?
I was in 5th grade, so I was ten, I think.

How did you get started in programming?
My friend Logan and I decided we were going to create Tomb Raider 4, so we each bought copies of "Learn to Program Basic".

We didn't quite make it all the way to that particular game.

What was your first language?
Something InterPlay tried to pass off as Basic. My first profitable language was HTML, when I made a bowling website for my aunt Sue when I was 12.

What was the first real program you wrote?
I made a pretty extensive text-based RPG. It started on BASIC, then moved to my TI-83 during Trig class, and eventually evolved into Gevalum.

What languages have you used since you started programming?
BASIC, TI-83 BASIC, HTML (XHTML), Javascript, CSS, Java, C++, ASP.NET, C#, ActionScript, ASP, PHP, SQL, XML, VB.NET. I wouldn't call myself proficient with several of the aforementioned, but I have used them.

What was your first professional programming gig?
I worked for a little 3-man web shop in Middletown, OH, doing ASP and SQL, mostly administrative back-ends to websites. It was the month after I turned 16.

If you knew then what you know now, would you have started programming?
Absolutely. I probably would have started with something like Java instead of Basic and PHP instead of ASP, though. I love development and wouldn't trade it for any other job.


If there is one thing you learned along the way that you would tell new developers, what would it be?
Learn to use Google.

What's the most fun you've ever had ... programming?
My online game, Gevalum. Although it's been surplanted by something else (a story which I may delve into sometime), I put two years into developing something I thought was fantastic. It went from ASP with frames to PHP with AJAX, and to watch it grow was fantastic.

That's the end of the questions: there you have it.

The Dark Side

| | Comments (0) | TrackBacks (0)
I've finally gone to the dark side, and I'm trying out a dark theme for visual studio. I've used dark themes before, but they never really stuck too long; this time, however, I think I've finally come up with something I like.

Here's a few screenshots, and you can decide for yourself; I've included a zip file with the theme and font I used.

Settings File


Dark .cs file


Dark .ascx file


Dark .css file
I read something interesting today at Gizmodo, a gadget news site I frequent. It was an article about a news reporter who said some pretty rude things to the people standing in line for an iPhone. Someone left a comment about the video:

"Really, what is the difference between this and waiting in line to buy concert tickets or sports team season passes?

That's one thing that bothers me, you're a geek if you dress up as a Star Trek character, but there's nothing wrong if you go to a sporting even with no shirt on with one half of your body painted blue and the other half orange and watch a bunch of grown men make millions of dollars playing a game.

Different strokes for different folks. But why is it socially acceptable to make fun of one but not the other?"

It's an interesting thought to chew on.

After eight (well, seven.. lunch) torturous hours, trying to figure out something so simple, that should have been so easy, I'm finally done. (Spoiler: skip to the bottom to figure out how to fix the paging-control-one-step-behind issue)

My scenario: I had an IList of objects, populated via some nHibernate magic. How I got the data isn't the important thing; just mattered that I had an IList of some object that I needed to put into some kind of paged display. The tricky bit was doing it through the codebehind, rather than setting up an ObjectDataSource for it. I tried several different methods, but kept coming back to one solution: a ListView with the new DataPager control.

It should have been pretty easy; the the DataPager control isn't terribly hard to set up. Just throw in the control, populate the ID, runat, pagesize, and pagedcontrolid (the control that it adds paging to). That was attached to a listview, with an id and runat, and it had a layout template, item template, and alternatingtemplate inside of it. It all looked something like:

<asp:DataPager ID="dpDataPager" runat="server" PageSize="5" PagedControlID="lvItems">

    <Fields>

        <asp:NextPreviousPagerField  NextPageText="next »" ShowFirstPageButton="true" ShowLastPageButton="false" ShowNextPageButton="false" ShowPreviousPageButton="true" />

        <asp:NumericPagerField ButtonCount="10"/>

        <asp:NextPreviousPagerField PreviousPageText="« previous" ShowFirstPageButton="false" ShowLastPageButton="true" ShowNextPageButton="true" ShowPreviousPageButton="false" />

    </Fields>

</asp:DataPager>

<asp:ListView ID="lvItems" runat="server">

    <LayoutTemplate>

        <span id="itemPlaceholder" runat="server"></span>

    </LayoutTemplate>

    <ItemTemplate>

        <li class="even"><%# Eval("Caption") %></li>

    </ItemTemplate>

    <AlternatingItemTemplate>

        <li class="odd"><%# Eval("Caption") %></li>

    </AlternatingItemTemplate>

</asp:ListView> 


And (the important bits) in my code behind:
In the Page_Load, I had

if (!IsPostBack)

{

    bind();

}


And after the Page_Load method, I had

private void bind()

{

    IList<Content> content;

    int id = Int32.Parse(Request.QueryString["id"]);

    FeatureValues fv = FeatureValues.AudioGuestBook;

    content = ContentWrapper.GetContent(id);

    lvItems.DataSource = content;

    lvItems.DataBind();

}




And all was fine, and it rendered nicely. Except when you clicked to change a page, that is.

From there, weirdness ensued; it was out of sync, always one step behind.  If you clicked page 2, nothing happened. If you then clicked page 3, it went to page 2. If you went back to 1, it went to 3... and so on.  This led to a wild chase through several hours and pots of coffee using Google, which finally led me to a forum post.  And there the answer was! It suddenly became clear: a solution which was, in the end, rather simple, if a little obscure. I added:

onpagepropertieschanging="lvItems_PagePropertiesChanging"


to the ListView in the .ascx file, and

protected void lvItems_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)

{

    this.dpDataPager.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);

    bind();

}


in the codebehind. This caused a change in the page to update both the listview and the data shown - something that I had been trying to find in a handler for the paging control, rather than the listview.

So there you have it: How to get a paged listview by using a data source set in the codebehind.

As I was mowing the lawn last night (something I try to avoid as much as popssible, much to the detriment of my relations with the neighbors), I began to think. Why is it that people pirate software, who does it, and why is it bad? Is it bad? There are two answers to my last question. One is based on bias and deceit and twisting statistics, and the other one is truth. You're welcome to discern for yourself, based upon what I have here to present.

The BSA (Business Software Alliance, www.bsa.org) claims that "dollar lossesfrom [sic] piracy rose by $8 billion to nearly $48 billion." That's a huge number! That's 19,200,000 copies of, say, the Adobe CS3 Master Collection, at $2500 a pop. But, what does that really mean? We must examine this claim of "dollar losses". The term implies that that company actually lost money (losses) and went negative; it implies that the software industry in general had a $48 billion loss in 2007. However, this is entirely untrue.

Software companies use money in the development (and later on, time supporting) the software create. There is, from that point, no finite quanitity of items that can be sold; copies can be produced and reproduced indefinitely.

That said, taking one copy, and making five others, does not cost the company money. You're not stealing five iPods from a store that carries 100, which they then have to spend money to replace; there is no "replace" in software. There is no hole left by a "missing" quanitity. The virtual world is far different from the physical; and different ways of thinking must apply.

An argument at this point may be "those five copies were given to people who didn't pay for it, so the company made five sales less than it would have!". Again, from a surface view, this makes sense; in the same way that "the earth is flat" makes sense. It works, and you don't have to think about it. End of story for the BSA, let's just publish the numbers and throw people in lawsuits.

However, in "not thinking", as happens terribly often, you lose something. You must examine the demographic of those "pirates"; looking at the BSA's own report shows that the highest rates of pirates exist in two areas; nations with developing economies, and nations with restrictions on software.

This means that most of the pirates are people who cannot afford, or cannot buy, the software. This means that they are people who would have otherwise never bought the software they pirated. Can a 14-year-old boy in Pakistan who wants to try his hand at design really afford the Adobe CS3 Design Studio, at well over $1000? Of course not. Does he deserve any less because of his unlucky predicament? Of course not. Back to my earlier point, I'm not advocating stealing that BMW because you can't afford it and want out of your Geo Metro, I'm talking about giving opportunites that costs the company absolutely nothing.

As for the rest - that 20% rate in the U.S. - many are people, again, who would have otherwise not bought the product. This is, I'll admit, purely from my own research of people I know personally, but the general age demographic falls between 16-22. High school and college kids, people who are trying to forge a way into an IT industry, but without the means to pay huge sums of money to get started.

I'm not advocating piracy, and I'm not saying that piracy is the best option. Designers can use Gimp, developers can use Notepad++ or Eclipse, anyone can use Linux. However, the software that gets pirated is generally the best of the best. People pirate it because it's the software above all others they choose to use; it's worth risking a lawsuit for. It is, in my opinion, one of software's highest honors to have 500 seeds on a torrent; it means people are going out of their way to give up some of their time, their bandwidth to give what are essentially "extended trials" of your software. They're being downloaded by people who will become professionals in that field, and who will be hired by a company who buys legit copies - or start their own business, and get their own corporate licenses.

Piracy is not a bad thing, for software. It's free publicity, it gets people talking about your product. Free market exposure, which means more long-term sales. Piracy helps sales, not harms it.

I finally made the switch for my blog to our own server, after Don got our new server up and running. We hammered through some DNS fun and then some PHP Horror, and then, after everything was set up, it was Perl time.

What went through my head was a little chant: 'not a PHP install all over again.. not a PHP install all over again.. not a PHP install all over again.. '

And, it wasn't quite that bad. Close, but not quite. The difference was that in the Perl install, most of my guesses were correct. Because, as always, installing any non-Microsoft language on a 2k3 box with IIS is never going to be fun. I unzipped the MovableType (version 4.12) file into my web directory, and set off to configure everything. (I already had IIS and MySQL installed at this point).

That said, the first thing I did was install ActivePerl from ActiveState, version 5.10.0.1003. At the time of writing, this was the latest and greatest. I did the install (something that, if following this as instructions, I urge not to do, at least of that version... follow further down), and everything worked... except that there was no MySQL module to be found. Bummer.

So, after hours of troubleshooting that I won't bore you with, I finally googled around and found out that the 5.8 version (5.8.8.822, to be exact) still had the MySQL module. I uninstalled the old version and installed this older version, set up the extensions (IIS manager -> web site -> right-click, properties -> home directory -> configuration, add .cgi with the extension set to the perl.exe file where you installed perl, with the headers locked down to GET, HEAD, and POST). Basically, I followed this: MT Windows Installation. However, after all that was said and done, I still had the problem of it not working.

The first problem I had was that when I went to check the install by going to mt-check.cgi, it errored out halfway down the page. So, I opened up the ActivePerl Manager and set DBI and DBD-MySQL to reinstall. I also took the -original off of the "mt-config.cgi-original" file name.

The next thing to do is to open up that config file, and comment out all of the data sources you're not using.  Mine looked something like:

##          Movable Type configuration file                   ##
##                                                            ##
## This file defines system-wide settings for Movable Type    ##
## In total, there are over a hundred options, but only those ##
## critical for everyone are listed below.                    ##
##                                                            ##
## Information on all others can be found at:                 ##
## config

################################################################
##################### REQUIRED SETTINGS ########################
################################################################

# The CGIPath is the URL to your Movable Type directory
CGIPath    http://www.crimsondeviations.com/blog/

# The StaticWebPath is the URL to your mt-static directory
# Note: Check the installation documentation to find out
# whether this is required for your environment.  If it is not,
# simply remove it or comment out the line by prepending a "#".
StaticWebPath    http://www.crimsondeviations.com/blog/mt-static

#================ DATABASE SETTINGS ==================
#   REMOVE all sections below that refer to databases
#   other than the one you will be using.

##### MYSQL #####
ObjectDriver DBI::mysql
Database movabletype
DBUser ********
DBPassword *************
DBHost localhost

##### POSTGRESQL #####
#ObjectDriver DBI::postgres
#Database DATABASE_NAME
#DBUser DATABASE_USERNAME
#DBPassword DATABASE_PASSWORD
#DBHost localhost

##### SQLITE #####
#ObjectDriver DBI::sqlite
#Database /path/to/sqlite/database/file

Then again, the mt-wizard page continued to error with "CGI Error. The specified CGI application misbehaved by not returning a complete set of HTTP headers".  After more Googling around, I found out that you have to replace a line in every page in the main directory (luckily, not many: I opened them all in Notepad++ and did a "replace all in opened files"). You have to change:
use lib $ENV{MT_HOME} ? "$ENV{MT_HOME}/lib" : 'lib';
to
use lib $ENV{MT_HOME} ? "$ENV{MT_HOME}/lib" : 'Y:\www\blog\cgi-bin\mt4\lib';
(replacing, of course, with whatever your path is).

Which then fixed my errors of it not finding the right data source, having wrong headers, and it magically worked, and I was on my way to blogdom!