Thursday, September 10, 2009

Command Prompt Here Registry Hack

Here's how to get a "Command Prompt Here" action added to Windows Explorer so that it will drop to a cmd.exe prompt on any folder you have navigated to.

Copy/paste the below code segment. Save it as CmdPromptHere.reg somewhere, right click on it and choose "Merge" and OK the changes it will make to your registry.

-- CUT ----------------------------------------------

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\Command]
@="Command &Prompt Here"
[HKEY_CLASSES_ROOT\Directory\shell\Command\command]
@="cmd.exe"

-- CUT ---------------------------------------------

This is a simple operation that I end up doing to every machine I have and use.

-shannon norrell

Wednesday, September 9, 2009

Pervasive SQL PSQL v10 Custom Functions

I am having to struggle with hooking into a Pervasive SQL (Btrieve) database and have developed several custom functions that I thought I would share, as I did not find the answers on the internet forums and had to develop them myself. Perhaps I can save someone else a few hours of frustration.

The first, "PadWithZeroes" answers a question posed by many users

----------------------------------------------------------------------------------------------
-- PadWithZeroes(:N Integer, :NZ Integer) - Pad with Zeroes
-- Takes integer :N and returns a string padded with integer :NZ number of zeroes
----------------------------------------------------------------------------------------------
DROP FUNCTION PadWithZeroes;
CREATE FUNCTION PadWithZeroes(:N Integer, :NZ Integer)
RETURNS VARCHAR(25)
AS
BEGIN
DECLARE :retVal VARCHAR(25)
DECLARE :nString VARCHAR(25)
SET :nString = CONVERT(:N,SQL_CHAR)
IF LENGTH(:nString)>:NZ THEN
SET :retVal = :nString;
ELSE
SET :retVal = CONCAT(
RIGHT('0000000000000',:NZ - LENGTH(:nString)),
:nString
);
END IF
RETURN :retVal;
END;

The second ConvertToFOSDate, takes a date stored a long integer which is, in fact the number of days offset from January 1st, 1900 (aka a Julian Date) and converts it into a usable Date object:

----------------------------------------------------------------------------------------------
-- ConvertToFOSDate(:D integer) - converts a date stored like 40026 and converts it to a date
-- Takes NumberOfDays :D since 1900 to get the Date
----------------------------------------------------------------------------------------------
DROP FUNCTION ConvertToFOSDate;
CREATE FUNCTION ConvertToFOSDate(:D integer)
RETURNS DATE
AS
BEGIN
DECLARE :theDate DATE;
SET :theDate = DATEADD(DAY,:D,CONVERT('1899-12-31', SQL_DATE));
RETURN :theDate;
END;

The third takes a number of minutes and returns a string formatted as HH:MM

----------------------------------------------------------------------------------------------
-- ConvertToHHMM(:T integer)
-- Takes NumberOfMinutes :T and returns a string formatted as HH:MM
----------------------------------------------------------------------------------------------
DROP FUNCTION ConvertToHHMM;
CREATE FUNCTION ConvertToHHMM(:T integer)
RETURNS VARCHAR(5)
AS
BEGIN
DECLARE :theTime VARCHAR(5)
IF (:T = 0) THEN
SET :theTime = '00:00';
ELSE
SET :theTime = CONCAT(
CONCAT(PadWithZeroes(CONVERT(FLOOR(:T/60),SQL_INTEGER),2), ':'),
PadWithZeroes(CONVERT(ROUND(MOD(:T,60)/60,1)*60,SQL_INTEGER),2)
);
END IF;
RETURN :theTime;
END;

Here are a couple more. They are not world changing, but may be of help to someone:

----------------------------------------------------------------------------------------------
-- GetTimeInHundredths(:A integer)
-- Returns Minutes as a percentage of a day
----------------------------------------------------------------------------------------------
DROP FUNCTION GetTimeInHundredths;
CREATE FUNCTION GetTimeInHundredths(:A integer)
RETURNS VARCHAR(10)
AS
BEGIN
DECLARE :theTime VARCHAR(10)
IF (:A = 0 ) THEN
SET :theTime = '0';
ELSE
SET :theTime =
CONCAT(
CONCAT( CONVERT( FLOOR(:A/60), SQL_CHAR), '.'),
CONVERT( ROUND(MOD(:A,60)/60,1)*10, SQL_CHAR)
);
END IF;
RETURN :theTime;
END;
----------------------------------------------------------------------------------------------
-- MinutesBetween(:D1 DateTime, :D2 DateTime)
-- Computes the integer numberOfMinutes between Date1 :D1 and Date2 :D2
----------------------------------------------------------------------------------------------
DROP FUNCTION MinutesBetween;
CREATE FUNCTION MinutesBetween(:D1 DateTime, :D2 DateTime)
RETURNS INTEGER
AS
BEGIN
DECLARE :minutesBetween INTEGER;
SET :minutesBetween = CONVERT( DATEDIFF(MINUTE, :D1, :D2), SQL_INTEGER);
RETURN :minutesBetween;
END;


-shannon norrell

Saturday, July 4, 2009

Changing Default Download Folder for Internet Explorer 6

How to Change the Default Download Folder for Internet Explorer 6

I just had the pleaser to use a computer that had IE6 still installed on it. I needed to change the default download directory, which ended up being a "home-made hack" I figured out on my own.

I know this information is a bit useless/out of date inasmuch ad Microsoft is about to release IE8, but there may be someone out there who needs this information.

So here is how to change the default downosd folder for IE6.

1. START/Run/Regedit
2. Navigate to this key: HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer
3. Right click on the right pane.
4. Choose New / String Value (REG_SZ)
5. Name the new key "Download Directory"
6. For the string value, enter the folder you want, in my case "C:\Dropzone"

Make sure to close all instances of IE that may be running for the change to take effect.

Shannon Norrell

Monday, May 18, 2009

Badass Javascript Date Validator.
Useful for Rails.

Haven't posted for a while. I should remember to post cool routines like the one below after I write them as they are useful to many.
I have seen quite a lot of good examples of folks using (and expanding upon) routines I wrote for some of the Gadgets that ship with Vista (to be found in library.js if you have a Vista Box) and for some of AOL's (apparently deprecated) Mac OSX Widgets.
Functions like showOrHide, getLocalizedString, getSpinner (emulates Vista-like spinner image) I have seen in use all over the place.

Here is a somewhat badass Date Validator routine I wrote today that takes in either a string date value or an <INPUT> Element Object and validates the date to be formatted as DD-MM-YYYY.

I wrote it for use by a Ruby on Rails application, but it's pretty handy as a general library function.

Using this (simple) Regex:
var DATE_REGEX = /^(\d{2})-(\d{2})-(\d{4})$/

////////////////////////////////////////////////////////////////////////////////
// //
// validateDate([object|string] oHTMLInputElement) - Validates a date value //
// =============================================== //
// You can pass in the id to an <input> Element, an actual //
// oHTMLInputElement or an actual date value in the form of a string //
// //
////////////////////////////////////////////////////////////////////////////////
function validateDate(oHTMLInputElementOrDateValue) {
var theDateValueToValidate = "";
var theValidatedDateValue = false;
var bIsInputElement = false;
if (typeof(oHTMLInputElementOrDateValue)=="string") {
var oHTMLInputElement = document.getElementById(oHTMLInputElementOrDateValue);
if (oHTMLInputElement && typeof(oHTMLInputElement=="object") && (oHTMLInputElement.tagName=="INPUT")) {
theDateValueToValidate = oHTMLInputElement.value;
bIsInputElement = true;
} else {
// Presumably they just passed in a date string
theDateValueToValidate = oHTMLInputElementOrDateValue;
bIsInputElement = false;
}
} else {
// They have passed in an Object
if (typeof(oHTMLInputElementOrDateValue=="object") && (oHTMLInputElementOrDateValue.tagName=="INPUT")) {
var oHTMLInputElement = oHTMLInputElementOrDateValue;
theDateValueToValidate = oHTMLInputElement.value;
bIsInputElement = true;
}
}
// If we have a date value to actually validate, let's get started
if (theDateValueToValidate != "") {
var theDateValue = theDateValueToValidate.replace(/\//g,"-"); // Ruby-side only accepts hyphens
if (DATE_REGEX.test(theDateValue)) {
theValidatedDateValue = theDateValue;
} else {
if (theDateValue.indexOf('-') > -1) {
var theMonth = theDateValue.split('-')[0];
var theDay = theDateValue.split('-')[1];
var theYear = theDateValue.split('-')[2];
theMonth = parseInt(theMonth).PadWithZero(); // If they've entered a single digit for either Day or Month, pad with zero accordingly
theDay = parseInt(theDay).PadWithZero();
if (theYear.length==2) { theYear = "20" + theYear; } // If they've entered a two-digit year, assume it's in the 21st century
theDateValue = theMonth + "-" + theDay + "-" + theYear; // Rebuild the date. Hopefully this will work
if (DATE_REGEX.test(theDateValue)) {
theValidatedDateValue = theDateValue;
}
}
// If we get to this point and none of our efforts have worked to format the date as "required", throw an error (if they are using an INPUT element)
if (!theValidatedDateValue && bIsInputElement) {
alert("ERROR: Date must be formatted as follows:\n\n\tDD-MM-YYYY\n\nPlease correct before continuing");
oHTMLInputElement.focus();
}
}
}
if (bIsInputElement && theValidatedDateValue) {
oHTMLInputElement.value = theValidatedDateValue;
}
return theValidatedDateValue;
}

Hope you find this one useful as well.

Shannon Norrell


Now on GitHub as well

Monday, April 13, 2009

Rnadom Flex Note - Event handlers Nightmares

It is onerous to say the least to determine which events to handle for many objects.

 

For instance today, I was trying to get an <mx:HSLIDER> control to change the size of something in real time (as the thumb drags around)..

 

Let me explain how I figured out which one to use.

 

Here is how I started out:

 

<mx:HSlider id="mySlider" />

<mx:Text id="foo" text="{mySlider.value}"/>           

 

With this setup, there is some magic that occurs so that when you stop dragging the little thumb, the binding takes into effect and the value in the text box updates.  Easy enough, right?

 

So now, what if I want the value in “foo” to update AS I DRAG THE THUMB.  Should be possible (it is).

 

I counted, and there are no less than 63 events that an HSLIDER control can fire.  Which one to trap?

 

Well, not finding an obvious answer on the internet, I began attaching handlers to events that seemed to make sense:

 

So here is my first iteration:

 

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

 

Notice that with Flex, you always have to pass in the (event) object. 

 

Now in your handler, you have to “handle” the specific type of event that has fired.

 

So let’s say I wrote my handler as follows:

 

    internal function sliderChange(event:StateChangeEvent) : void {

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

 

THIS WILL NOT WORK AS I HAVE NOT USED THE RIGHT EVENT TYPE.

 

There are two ways to determine what type of event to put in your handler.

 

1)       put *something* and let the IDE tell you:

     “Error implicit coercion of a value of type mx.Events.SliderEvent to an unrelated type mx.Events.StateChangeEvent”

So, in this case, it’s telling you to use “SliderEvent”, not “StateChangeEvent”

2)       The second (preferred) way is to simply hover over the “event” part in your line:

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

      *sometimes* a tooltip will appear telling you what event handler type to use

   3) A third way is to launch in debug mode, get an error and then you can hover over stuff and figure out what type of event handler to use:  See Screenshot:

 

 

One would think that this tells me the event type is SliderChange.

 

The actual event handler type is “SliderEvent”

 

The reason I am telling you all of this is that it is extremely frustrating to do some simply shit in the Flex IDE at the moment. Surely there must be a better way.

 

Anyway, moving on.

 

So now we have:

 

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

 

And an event handler

    internal function sliderChange(event:SliderEvent) : void {

      trace(“sliderChange eventg fired”);

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

By adding “trace” calls, when you run in debug mode, the text dumps to the console.

 

So, in this case, guess what?  This event does not fire until the user has released the thumbdrag handle!

 

So I try another event han dler

 

<mx:HSlider id="mySlider" currentStateChange="sliderStateChange(event)"/>

 

Notice I have to use a different handler because (you guessed it), the event fired is different.  So, going through the same agony as before, I determine that the event type being fired is, in fact, called “StateChangeEvent”. (Bascically by trying to run the app, letting it error out and reading the error message.

 

    internal function sliderStageChange(event:StateChangeEvent) : void {

      trace("sliderStageChange");

    }

 

Near as I can tell, this event does not fire.

 

So, thinking that it is not really the “slider” that is changing but the thumbdrag handle, I thought to add an event handler to that one as well:

 

Now, iteration #4:

 

        <mx:HSlider id="mySlider" thumbDrag="thumbDrag(event)" />

        <mx:Text id="foo" text="{mySlider.value}"/>           

 

And writing another event handler:

 

    internal function thumbDrag(event:SliderEvent) : void {

       trace("thumbDrag");

    }

 

 

I can see in my debug window that this is, in fact, the event that fires as you move the thumbDrag thingie around.

 

Therefore, I fix the event handler to read As follows:

    internal function thumbDrag(event:SliderEvent) : void {

       trace("thumbDrag");

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

 

 

GUESS WHAT?  IT STILL DOESN’T WORK!

 

Turns out all you have to do is add “livedragging=”true” to the HSlider control and you do not have to write any event handlers.

 

 

So,

        <mx:HSlider id="mySlider" liveDragging="true"/>

        <mx:Text id="foo" text="{mySlider.value}"/>           

 

Does the trick..

 

 

Why do I tell you all about this?  So hopefully you can share in my pain and perhaps to learn something from my stupidity.

Flex is cool, but there is a pretty steep learning curve.

 

-shannon norrell

 

 

Wednesday, February 25, 2009

Fast JavaScript Max/Min on an Array Taking Arbitrary Number of Arguments

What's the fastest way to find the largest, or smallest, number in an array?

Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};

By using JavaScript's .apply() method on a built-in function you can pass in an array of unlimited arguments.

Shannon Norrell

Friday, September 5, 2008

Line 0 Object Required Internet Explorer Javascript error - aka the dangers of using CSS Expressions

One of my favorite mechanisms to do IE-specific CSS is to use the so-called dynamic properties available to IE5+ browsers. Firefox and Opera ignore these tags, so if, for instance you need a div of id "foo" to be 110 pixels in IE and 100 pixels in all other browsers, you would just do this:

#foo {
width: 100px;
width: expression('110px');
}

I spent the better part of the day trying to track down a Line 0. Object Required Javascript bug that, when hit, required me to close IE using Task Manager. I could not figure this one out and finally resorted to reconstructing the entire page, line-by-line until I found the problem.

I finally determined it occurred only when I added a <textarea> tag to the page. My current project is a Ruby on Rails app, which necessarily indludes the Prototype Library, so I initally wrote off this weirdity to the vagaries of Prototype and its many tens of thousands of lines of code.

In this context, an input type=text tag would do fine, so I switched to that and moved on.

Quite by accident, I stumbled across this section in my CSS file:

.WordBubble textarea {
overflow:hidden;
border:solid 1px lightBlue;
height:30px;
width:expression(document.getElementById('WordBubble').offsetWidth-66);
}

And WHALA, the answer!

Thinking to reuse a WordBalloon construct I had developed, I had modified this CSS to play off of .WordBubble the className vs the original #WordBubble the ID. Therefore, when I used the original:

<div id="WordBubble" class="WordBubble">
<textarea>
</div>

things worked as expected.

However, when using:

<div id="AnotherWordBubble" class="WordBubble">
<textarea>
</div>

The CSS, when evaluating the dynamic property, could not find "WordBubble" as it did not exist.

Although I realize this posting is somewhat confusing (I barely understand it myself), what I am trying to say is "When you get a Line 0, Object Expected" Javascript error and can't figure out where it comes from, check your CSS for Expression use.

Shannon