09/11/2009

Uri Extension Method: AbsolutePathNoFile()

How often do you want to determine the absolute URI from any url without the specific file reference and without the query string variables. This is especially useful in many SharePoint tasks.

Here is a little extension method that can do just that. Pop this in a static class and try calling it on your Uri object:

public static UriExtensions {

public static string AbsolutePathNoFile(this Uri theUri)
{
string retVal = "http://" + theUri.Host + (theUri.Port == 80 ? "" : ":" + theUri.Port.ToString());
for (int intCnt = 0; intCnt < theUri.Segments.Length-1; intCnt++) {
retVal += theUri.Segments[intCnt];
}
return retVal;
}
}

// somewhere else:

Uri u = new Uri(Request.Url);
MessageBox.Show(u.AbsolutePathNoFile());

Over and Out

02/11/2009

Google Wave Is Here: But I have no Friends

I am online with the Google Wave beta. It is cool, takes a bit of getting use to. But this is NOT going to replace my normal email account anytime soon - This is no Tsunami. I do however hope it does replace my email account ASAP - Especially on my iPhone!

The most major thing I don't understand about Google Wave is: How can I message people that do not have Google Wave accounts? Wouldn't this be the obvious way to get other people on board (is this merely not happening because this is a VERY early preview version)? Right now I can't so this means I can't use it for much (start playing little violin here).

My main contacts did not jump at the chance to subscribe to the Beta so I am now sitting in an ocean waiting to catch a wave.

Stay tuned for Google Wave invitation give away. I have nominated 20 of my closest digital friends for Google Wave accounts and am waiting for google to lick the stamps.

And so goes the life of a surfer.

Over and Out.

16/10/2009

Comments Open To Everyone

As an experiment I have decided to open my comments to everyone to see if it impacts my site traffic. This will be a fun experiment.

Happy Birthday To Me

My birthday is today, was yesterday, is tomorrow or is at some point next / last week.

I wanted to wish myself a Happy Birthday on my blog ... so ... Happy Birthday to me ...

06/10/2009

SharePoint Tips: Content Type Visibility on NewMenu

I've built a solution with a few custom ContentTypes in a list definition. Now, removing these from the NewMenu has to be easy right? Just add a HideCustomAction definition to your instance file. Not so easy to find the ID's that will be used for those content types is it? Well, here is a solution that will remove the ContentTypes from the NewMenu but allow them to hang around for use in defining whatever it is your heart desires.

To specify visibility on the Microsoft.SharePoint.StandardMenu.NewMenu in a document library, try changing the RequiredClientRenderingOnNew option to false, and update the content type definition as below:

The correct solution for document libraries is the following:

SPWeb web = SPContext.Current.Site.RootWeb;
web.AllowUnsafeUpdates = true;// if done on get
SPList list = web.Lists["LIST NAME LIST NAME PUT LIST NAME OR GUID HERE"];

foreach (SPContentType ct in list.ContentTypes)
{
if (ct.Name == "Content Type Name")
{
ct.Hidden = true;
ct.RequireClientRenderingOnNew = false;
ct.Update();
}
}
web.AllowUnsafeUpdates = false;// if done on get

I'm doing this in a feature receiver and it works by design. If done in AllItems.aspx (or any GET request it seems) you need to refresh the page twice for this to work by design (one refresh appears to set the value in content type but this is done after it's read into the display).

The other thing I've got in that habit of doing is force deleting lists when I make changes. I'm not sure how "required" this is but in order to get stability in my test results this seems to make a difference.

Here is how I was force deleting the offending lists:

stsadm -o forcedeletelist -url http://SERVERNAME:PORT/Lists/LISTNAMELISTURLNAMELISTURLNAME


Wish SharePoint would work as advertised ... sigh ...

18/09/2009

Reassign bugs to gays.

This summary is not available. Please click here to view the post.

14/08/2009

Clear | Remove Query Strings From Post Backs (ASP.Net, SharePoint)

As part of an unorthodox request I was asked to make a TabStrip component SEO friendly. My first thought was to completely rewrite the control to make use of GET requests rather than continuing to POST the data back to the server.

Immediately I ran into a problem with this approach as the developers of this site have implemented the majority of these TabStrip controls inside the ASP.Net UpdatePanel (don't get me started with these) which does not recognize GET requests as Async events.

The architect of this site (actually a SharePoint site) failed to recognize that the SharePoint indexing service would not be able to index information on any tab other than the default one (as subsequent requests for tab data are done using Asynchronous Events). When project management asked him to modify the tabs for accessibility he told them it was impossible without a complete redesign.

As a solution to this problem I modified the TabStrip control such that it renders an anchor tag rather than a link button and added some fancy JavaScript to cancel the Anchor tag click event and trigger the appropriate __doPostBack option. I now have a crawl able anchor tag, which works like a link button, and triggers the appropriate update.

Moreover, when the TabStrip is initialized (OnInit) it looks for a specific query string variable indicating the ID of the selected tab. This is when the real problem starts:
  1. Indexing service crawls the anchor and builds a GET string reference to the selected tab id.
  2. Page is loaded into browser.
  3. User selects different tab.
  4. TabStrip is initialized finding the previous (last selected tab) tab id.
  5. TabStrip raises MenuItem Click event ignoring the actual new selected tab id.
The problem then becomes: How do I Clear The Query String From Subsequent Post Back Operations?

My quest turned to the Google.

First I found this approach which actually removes the query string VIA triggering a post back and is therefore too wasteful to be my solution.

I then found the following approach which unfortunately fails to load as it uses the ugly document.all JavaScript method which isn't available until after page load (therefore causes a client side exception - even when registered properly as a StartupScript).

I put together a slightly different JavaScript routine that looks like this:

if(window.onload != null) {
var wol = window.onload;
window.onload = function(e) {
wol(e);
document.forms[0].action = "Index.aspx";
}
} else {
window.onload = function() {
document.forms[0].action = "Index.aspx";
}
}


This JavaScript Method then rolls nicely into an ASP.Net Server Control like so:
///
/// Attempt to remove the tab id from the query string
///

private void AddRemoveTabIdQueryString()
{
const string key = "REMOVETABIDQUERYSTRING";
if (!Page.ClientScript.IsStartupScriptRegistered(GetType(), key))
{
Page.ClientScript.RegisterStartupScript(this.GetType(), key,
string.Format("if(window.onload != null) {{var wol = window.onload;window.onload = function(e) {{wol(e);{0};}}}} else {{window.onload = function() {{document.forms[0].action = \"{0}\";;}}}}", GetRequestPageName()), true);
}

// Get the page Name of the request
private string GetRequestPageName()
{
string rawUrl = Page.Request.RawUrl;
int pos = rawUrl.LastIndexOf("/");
int qpos = rawUrl.LastIndexOf("?");
return qpos > -1 ? rawUrl.Substring(pos + 1, qpos - pos - 1) :
rawUrl.Substring(pos + 1, rawUrl.Length - pos - 1);
}

I hope this is helpful to others.

Over and Out

13/08/2009

SPJobDefinition Quirks For Developers

I wanted to write a quick heads up on a couple quirks relating to the SPJobDefinition and wiring up Timer Jobs (may be relevant for deployments where the Timer Jobs are modified). We are building our solutions on Windows 2003 Server with MOSS 2007.

To debug SPJobDefinitions attach VS debugger to OWSTIMER.exe process after following install instructions below.

OWSTIMER is caching the SPJobDefinition somewhere and is tricking Visual Studio into thinking we are actually debugging the most recent compiled version when we are debugging the last loaded version.

To fix this, kill the OWSTIMER process in process explorer (or restart the Windows Sharepoint Services Timer by typing the following at the command prompt: net stop sptimerv3 & net start sptimerv3) and then refresh the portal you are performing development on (this will force a restart of OWSTIMER.EXE and clear the cache).

Between tests ensure you completely remove the SharePoint feature (deactivate + uninstall) from Sharepoint (see below). Then kill the OWSTIMER process, iisreset, rebuild the solution and reinstall / activate the solution again (see below).

Here are a couple batch files convenient for removing / installing the jobs (where ProvisioningVX is the name of the feature you are trying to install):

Uninstall Batch File

@ECHO OFF

set SPAdminTool=%CommonProgramFiles%\Microsoft Shared\web server extensions\12\BIN\stsadm.exe
set TargetUrl=http://servername/sites/name

echo "Deactivating Feature"
"%SPAdminTool%" -o deactivatefeature -name ProvisioningVX -url %TargetUrl% -force

echo "Uninstalling Feature"
"%SPAdminTool%" -o uninstallfeature -name ProvisioningVX -force

iisreset

PAUSE

Installing and activating the feature

@ECHO OFF

set SPAdminTool=%CommonProgramFiles%\Microsoft Shared\web server extensions\12\BIN\stsadm.exe
set TargetUrl=http://servername/sites/name

echo "installing feature"
"%SPAdminTool%" -o installfeature -name ProvisioningVX -force

echo "activating feature"
"%SPAdminTool%" -o activatefeature -name ProvisioningVX -url %TargetUrl% -force

iisreset

PAUSE

12/08/2009

How To: Debug SPJobDefinition in Visual Studio

The solution is remarkably simple.

Click Debug -> Attach To Process

Note: At this point, ensure the checkbox "Select processes from all users" is selected.

Select OWSTIMER.EXE from the list.

Setup a breakpoint on the Execute override method.

Be patient and wait for the timed job to execute.

06/08/2009

My First Zune Badge: A Lesson in mediocrity

I finally got my first Zune badge today and with it, a lesson in mediocrity. Microsoft may want to rethink their strategy as to how these badges are issued as I now feel that I listen to a bunch of kindof sortof artists..

The Bronze Artist Power Listener award! Wooo Hooo. Are you kidding me? Thanks for this bronze mediocre accomplishment. What if it was a Platinum Artist Power Listener award? Does that mean I've listened to the most commercial music possible - that I am a power listener of platinum artists? What about, Gold. What about Silver.

Either way, I'm still happy that Microsoft has finally allowed me to create a Zune account. Thanks for the good work.

Over and Out

26/06/2009

Setup Visual Studio To Easily Pull PublicKeyTokens

Interesting article here: http://blogs.msdn.com/kaevans/archive/2008/06/18/getting-public-key-token-of-assembly-within-visual-studio.aspx

The article explains a couple tricks as to how to get PublicKeyTokens out of your signed assemblies in a quick and simple manner.

Enjoy.

Over And Out

18/06/2009

Apple Is Spamming Me

Every time I get an email from Apple I:

1) Feel like I'm dumb.

2) Ignore it.

3) Get annoyed and unsubscribe from the mailing list.

Only I continue to get at least one email from Apple every two days that I do not want. Has anyone else had this problem? Does anyone know how to make it so Apple never contacts me again?

If so, please enlighten me!

Over And Out

17/06/2009

Bing.com is Amazing!

I’ve been using Bing for one week to see if it can replace Google.

I can now say that Bing does 100% replace Google and in many circumstances I’ve found it not only easier to use, but faster, and more relevant.

Try switching your search engine to Bing and give it a test – I’d love to see what other people think!

Feel free to leave hateful comments, it's all part of the game.

Over and Out

29/05/2009

WANTED: Windows Error Collage

I need new desktop wallpaper.

And you know you're a nerd when you have a vision that this wallpaper should be a collage of all the worst Windows error prompts imaginable.

Ideally the collage would have a background with a Windows Blue screen.

Then, as if this ask makes absolutely no sense already I want as many verbose Windows Error dialog messages stacked on top of the blue screen as possible.

The idea is that the log on dialog should be obscured by the plethora or other error messages.

This collage should look so horrible that it will be a deterrent for anyone to use the computer.

This is a moronic idea - but if anyone has seen something like this, please leave a comment.

Over And Out

22/05/2009

WARNING - DO NOT BUY SOFTWARE FROM: Websupergoo.com

I would rec against buying software from this company. I've now logged four bugs in their PDF product.

I'm sure it's useful for some things - but it is very inconsistent, buggy and if I had a choice, I'd never use it again. Unfortunately it's the only product on the market that can render SVG inside a PDF - so I'm stuck with it.

The following bugs were initially denied by ABCpdf support. I was wrong, they were right type of issue resolution. To their credit they managed to fix 1 of the issues, but they deny the existence of all other issues:

Fatal ExecutionExceptions
1) ABCpdf6 is crashing the .Net Runtime with Fatal ExecutionExceptions. If anyone has encountered an ExecutionException they know this is about as bad as it gets - it crashes the .Net runtime, it crashes the web server etc. etc. etc. Websupergoo support denied the existence of this issue for months. To reproduce this issue, download ABCpdf6, download .Net 3.5 SP1, run a project in VS2008 and hit stop button half way through some long process. Restart the application ... kaboom explosion ... Well guess what - they figured it out and fixed it in ABCpdf7.

Line Counts Fail
2) ABCpdf7 is not capable of counting the number of lines of text that have been written to a text area. Moreover, Websupergoo support denies this is an issue -> actually suggesting I use the line counts for another VERY important part of my application. I've uploaded an example of the incorrect line counts at my live space here:
http://cid-cd836a97f80e0c35.skydrive.live.com/self.aspx/Public/HeightProblemExample.zip

Text Height Methods Fail
3) ABCpdf7 is not capable of determining with accuracy the dimensions of text that has been written to a text area (esp when line spacing is specified). Moreover, Websupergoo support denies this is an issue -> they suggest I use line counts (which are also broken) to determine the height of a text area. They are morons, they don't read their support requests, and they are incapable of resolving any problems in what would be considered a reasonable amount of time. I've uploaded an example of the height calculation issues at my live space here:
http://cid-cd836a97f80e0c35.skydrive.live.com/self.aspx/Public/HeightProblemExample.zip

Cache is Completely Broken
4) ABCpdf6 is not capable of clearing it's cache properly, moreover, cache settings that Websupergoo claims to do things - do not do what they say they do. Websupergoo support denies this issue, are insulting by pointing users to obvious documentation - but even when all the settings are setup precisely to their requirements we still have to reboot the webserver to clear the cache. Unfortunately I don't have an example of this behavior - but you can see for yourself by going to their site and merely running the cache examples. It does not work consistently at all.

As to not complain complain complain - I assume idiots will always be idiots and business people will sell pretty much anything any idiot (like me) are willing to buy at the highest cost possible.

Solution To Text Height issues:
I'm providing a solution to accurately predict the height of text in ABCpdf7. Websupergoo is incapable of doing this - therefore - I've been forced to apply some really ugly inefficient methodolgy to correct their issue. I've uploaded an example of the fix to my live space here:
http://cid-cd836a97f80e0c35.skydrive.live.com/self.aspx/Public/TextHeightSolution.zip

I am purposely blasting this group as they have provided such low quality support. Every reply is insulting and the only way to get them to take your requests seriously is to kick and scream, kick and scream, kick and scream. May be at some point I'll get to chat with their top level support people - but even at that - these people deny the issues in their application and do not help users move forward.

If you don't believe me take a look at the examples they provide with the ABCpdf7 trial download. 1988 called and they want their coding conventions back!

Over And Out

06/05/2009

.Net Custom Panel Control with Transparent Background (no png's, css hacks, or problems)

I'm making a really quick post on how you can wrap the jQuery fadeBack control into a .Net Web Custom Control. If you haven't read the article on the fadeBack control, you will have to go here and grab the source.

Save the scripts in a script folder inside your Web Site / Web Application.

To use this control you need to add a reference to the Web Server Control project you have built the code in.

To use this control in your WebForm please Register the Web Server Control dll and namespace on the page like:
<%@ Register Assembly="<<NAME OF WEB SERVER CONTROL PROJECT DLL>>" Namespace="<< THE NAME OF THE NAMESPACE>>" TagPrefix="ctl" %>

Then you can start using the control like so:

<ctl:TransBackPanel ID="backTest" runat="server"
Width="400px" Opacity="20" BackColor="Aquamarine"
BorderColor="Red" BorderWidth="10px" BorderStyle="Solid">
<ctl:TransBackPanel ID="TransBackPanel1" runat="server"
Width="300px" Opacity="20" BackColor="Red"
BorderColor="Green" BorderWidth="10px" BorderStyle="Solid">
<div>Hello World!</div>
</ctl:TransBackPanel>
</ctl:TransBackPanel>

Below is the source code for the .Net Web Custom Control, add this to a Web Server Control project and build:

[ToolboxData("<{0}:TransBackPanel runat=server></{0}:TransBackPanel>")]
public class TransBackPanel : Panel
{

// the jQuery script reference
public const string JQUERY_KEY = "jquery-1.3.2.min.js";
public const string JQUERY_URL = "script/jquery-1.3.2.min.js";

// the transparent background plugin reference
public const string TRANSBACKPANEL_KEY = "jQuery.fadeBack.js";
public const string TRANSBACKPANEL_URL = "script/jQuery.fadeBack.js";

/// <summary>
/// Declare a local variable with the default opacity
/// </summary>
private int _Opacity = 20;

/// <summary>
/// Get / Set opacity to an int - 100 to 0 with 100 being a completely transparent background.
/// </summary>
public int Opacity { get { return _Opacity; } set { _Opacity = value; } }

/// <summary>
/// Override the create child controls method and add the scripts from our constants
/// </summary>
protected override void CreateChildControls()
{

// Register jQuery like so
if (!Page.ClientScript.IsClientScriptIncludeRegistered(JQUERY_KEY))
Page.ClientScript.RegisterClientScriptInclude(JQUERY_KEY, JQUERY_URL);

// Register the fade back external script
if (!Page.ClientScript.IsClientScriptIncludeRegistered(TRANSBACKPANEL_KEY))
Page.ClientScript.RegisterClientScriptInclude(TRANSBACKPANEL_KEY, TRANSBACKPANEL_URL);

base.CreateChildControls();
}

/// <summary>
/// Render the panel control
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{

// Register the startup script to fade the background to another color
if (!Page.ClientScript.IsStartupScriptRegistered(this.ID))
Page.ClientScript.RegisterStartupScript(typeof(string), this.ID, GetOnloadScript(), true);

base.Render(writer);

}

/// <summary>
/// Produce a jQuery on load thingy to geter done.
/// </summary>
/// <returns></returns>
private string GetOnloadScript()
{
return "$(document).ready(function() {\n" +
"$('#" + this.ClientID + "').fadeBack({opacity:" + Convert.ToDouble(Opacity) / 100 + "});\n" +
"});";
}

}

JavaScript: jQuery Plugin to fade Background but not Content: no css hacks, no *.png files, no problems ...

UPDATE: the toNum method must be changed to this:

function toNum(strNum) {
if (strNum && strNum != "") {
var i = parseFloat(strNum);
if (i.toString() == "NaN")
return 0;
else
return i;
}
return 0;
};


I scoured the web in search of a jQuery plugin that allows me to fade the background but not the contents of a div. I found this article: Cross Browser Transparent Background with jQuery, no css hacks, no *.png files by Mihaistancu and noted that there were a lot of problems with the plugin. It didn't work for me -> but I'm sure it's great code once I figure out the particulars.

I decided to write my own plugin that can take some of these issues into account. The below jQuery plugin has been tested in IE7, Firefox, Opera and Safari and it works.

It takes padding and borders into account so your padding will be enforced and so will your background borders (background can have borders!!). Infact, anything that is not a child element will be applied to the background fade.

How it works:
1) Get the dimensions of TheDiv we want to fade (top, left, height, width - if these are not set in css it will default to the default style for that html element type).
2) Get the inner html of TheDiv and add it to a NewDiv (with id: TheDiv.id + "_content"), and append that NewDiv to TheDiv's parent.
3) Fade TheDiv out ...

Give it a shot and let me know what you think.

You can call the plugin like so:

$(document).ready(function() {
$("#outer").fadeBack();
});

You can download a zip file example /plugin from my Windows Live Space here.

You can see the raw plugin source code below:

(function($) {


$.fn.fadeBack = function(options) {

var _s = $.extend($.fn.fadeBack.defaultOptions, options);

return this.each(function() {

var t = $(this);
var oh = t.height();
var ow = t.width();
var ih = t.html();
var p = t.parent();
var tl = t.position();
var id = t[0].id + "_content";

t.css({ height: oh, width: ow }).html("").fadeTo("fast", _s.opacity);

var padding = dimSum(getPadding(t), getBorderSizes(t));

var ncss = { top: tl.top, left: tl.left,
position: "absolute", height: oh, width: ow,
paddingTop: padding.top, paddingBottom: padding.bottom,
paddingLeft: padding.left, paddingRight: padding.right };

$("
" + ih + "
").css(ncss).appendTo(p);

});

function dimSum(dim1, dim2) {
return { top: dim1.top + dim2.top,
bottom: dim1.bottom + dim2.bottom,
left: dim1.left + dim2.top,
right: dim1.right + dim2.right
}
};

function getBorderSizes(sel) {
return {
top: toNum(sel.css("borderTopWidth")),
bottom: toNum(sel.css("borderBottomWidth")),
left: toNum(sel.css("borderLeftWidth")),
right: toNum(sel.css("borderRightWidth"))
};
};

function getPadding(sel) {
return { top: toNum(sel.css("paddingTop")),
bottom: toNum(sel.css("paddingTop")),
left: toNum(sel.css("paddingLeft")),
right: toNum(sel.css("paddingRight"))
};
};

function toNum(strNum) {
if (strNum && strNum != "") {
var i = parseFloat(strNum);
if (i.toString() == "NaN")
return 0;
else
return i;
}
return 0;
};

}

})(jQuery);

$.fn.fadeBack.defaultOptions = { opacity: 0.4 }

Over and Out

01/05/2009

JavaScript: Chaining Cancelable Events - If you're not first, you're last

Another quick post on cancelable events in JavaScript. An example of a cancelable event is the keydown method. If I return false from a keydown method JavaScript will not allow the action of that keydown event to proceed. For example, I could return false on a document keydown event to cancel the ctrl+c behaviour etc. etc.

The following is a nice method I've built and tested only in IE 7 which allows users to chain JavaScript events together.

Obviously this could be compressed significantly.

addToObject: the HtmlElement we want to attach the cancelable event to.

eventName: the name of the event we want to trap.

methodDelegate: a JavaScript function delegate / closure for the JavaScript method to attach to the event.

order: First or Last. You can build on this however you want.

Enjoy,

function AddCancelableEvent(addToObject, eventName, methodDelegate, order) {
if (addToObject[eventName] != null) {
var oe = addToObject[eventName];
if (order == "first")
addToObject[eventName] = function(e) {
var r = methodDelegate(e);
if (r == false) return false;
return oe(e);
};
else // "if you're not first you're last" - Ricky Bobby
addToObject[eventName] = function(e) {
var r = oe(e);
if (r == false) return false;
return methodDelegate(e);
};

} else {
addToObject[eventName] = methodDelegate;
}
};


Over And Out

30/04/2009

JavaScript: Overloading Window onload

Quick post on a very common methodology I've been using to chain events to the window.onload event in pure JavaScript:

if (window.onload == null) {
window.onload = loadAutoSubmitScript;
} else {
var ol = window.onload;
window.onload = function() { ol(); loadProc(); }
}

function loadProc() { alert("The window is loaded"); }

This should work for pretty much every page you use.

Over and Out

03/04/2009

Google Street View Coming To Toronto

I had the privilege of witnessing the Google's street view car as it canvassed downtown Toronto yesterday.

Although I have a feeling the Google's street view car was stalking me, I will still grant Google the rights to use my image on their street view.

Here are the precise details of where I should appear in Toronto. Let's keep our fingers crossed for now!


View Larger Map

01/04/2009

Blackberry AppWorld Released

Here is the Blackberry AppWorld:

http://www.blackberry.com/select/appworld/

Here is a list of the featured applications:

http://na.blackberry.com/eng/services/appworld/featured.jsp

12/03/2009

Windows 7 Release Facts

Windows Vista called on memory ~14,000 times during boot-up. A source inside Microsoft tells me Microsoft has been able to get that number down to 2000 calls to memory. I certainly see a major speed improvement as my 32 bit Windows 7 dual boot starts up much faster than it's 64bit Vista counterpart.

Moreover, it seems the only thing holding back the Windows 7 release is a Direct Connect feature, which allows users to connect to their business or home networks from any internet connection.

My source tells me Microsoft is preparing a Windows 7 release for July 2009 - which probably means September.

Moreover, I've managed to install the Windows 7 beta on a laptop I bought in 1999 with a 933 single core Intel processor and 1GB of (upgraded) ram. Sure, it doesn't have Aero effects, but it has no problem running Windows 7. I'm calling this a NetBook - and it's sweet.

If Windows 7 is released this summer, If it does run on legacy hardware without any issues and it really is as good as everyone says - this could be a huge win for Microsoft - and a big loss for Hardware Mfg's as users do not need to upgrade their XP hardware.

Tell me what you think!

Over and Out

11/03/2009

The Great Recession??? = Laughable???

In other words: The great normal downturn in the business cycle … The GREAT significant decline in economic activity spread across the country, lasting more than a few months … don’t even think of calling this a depression ... everyone knows that a depression has to last at least 25% longer than this … everyone knows we need another 20% of the worlds wealth to be destroyed before we can really call this a depression ... with over 50% of the worlds wealth being destroyed (March 10th, 2009) we can OBVIOUSLY still lose another 50% ...

The Great Recession - Reuters

I wonder how many Great Recession’s we’ve had since the Great Depression.

This is a Great Recession!

Over and Out

22/01/2009

Let me Google That For You

It drives me crazy when my friends / coworkers ask me to Google something.

How hard is it to type: www.google.com and a couple keywords.

http://letmegooglethatforyou.com is the perfect solution. Try it yourself or allow me To Google That For You.

If you haven't already figured this out this site shows the user an animation explaining exactly how easy it is to Google that keyword on your own.

Over and Out

07/01/2009

JavaScript: Cancel Event Bubbling

Another common tidbit of JavaScript code:

Cancel event bubbling:

function stopEvent(evt){
evt = evt || window.event;
if (evt.stopPropagation){
evt.stopPropagation();
evt.preventDefault();
}else if(typeof evt.cancelBubble != "undefined"){
evt.cancelBubble = true;
evt.returnValue = false;
}
return false;
}

JavaScript: Create Open Below Pop Ups (Ex// auto complete text box)

This is a simple method to open popups below text inputs (or any Html Element at that) using JavaScript. Please let me know if things are missing ... The intent of this script is to open a small pop up below a text box for use in a custom auto complete. As this is an ASP.Net control, and ASP.Net creates element ID's based on containers we need something to base our element id's on so we can do stuff with them. In this example I use a text box as the naming pivot upon which all other client ID's are based on.

// the previous document click event handler we've stored when we change the event.
// This implies when the pop up is open you'll need to cancel all click events therein so the popup doesn't close
var orignDocClick = null;
// the active pop up id. In another method I haven't provided here we determine if there is an active pop up and close it before we open a second.
var activePopId = null;

// the id of this element is provided VIA ASP.Net control but in this example is hard coded
// we want to show a Pop Under directly below this text box.
var inputTypeText = document.getElementById("ourTextBox");

// create the pop under by calling show pop.
var myNewPopUnder = ShowPop(inputTypeText.id + "_PopUp", inputTypeText);

myNewPopUnder.innerHTML = "Hello World";
// OR
myNewPopUnder.appendChild(document.createElement("br"));
// OR ....


function ShowPop(strPopUpId, objTextBox) {
// get the existing div control and remove it (it is merely a placeholder with ID's aligned as per ASP.Net Crap)
var popEl = document.getElementById(strPopUpId);
var parent = popEl.parentNode;
parent.removeChild(popEl);

// create a new pop up control and append it to the parent of the old auto complete pop up.
var newPop = document.createElement("div");
newPop.id = strPopUpId;
newPop.className = "AutoCompletePop";
parent.appendChild(newPop);

// determine the left and top positions for the pop under
var curleft = 0;
var curtop = parseFloat(objTextBox.offsetHeight);
var top = objTextBox;
do {
curleft += top.offsetLeft;
curtop += top.offsetTop;
} while (top = top.offsetParent);
newPop.style.top = curtop + "px";
newPop.style.left = curleft + "px";
newPop.style.display = "block";

// trap some document events to ensure we can close auto complete
orignDocClick = document.body.onclick;
document.body.onclick = DocHidePop;
activePopId = strPopUpId;

return newPop;
};

function DocHidePop() {
if (activePopId != null) {
HidePop(document.getElementById(activePopId));
}
};

function HidePop(objPopContainer) {
objPopContainer.style.display = "none";
document.body.onclick = orignDocClick;
activePopId = null;
};

JavaScript: Event Target

A simple way to get the element that starts an event. I'm using this to ascertain which text box is calling the KeyPress event in pure JavaScript:

function KeyPress(event) {
var srcElement = getElement(event);
alert(srcElement.id);
}

function getElement(evt) {
if (window.event)
return window.event.srcElement;
else
return evt.currentTarget;
};

Another variation of this script could be written as such (note, this get's the object that triggers the event):

function getTargetElement(evt){
if (window.event)
return window.event.srcElement;
else
return evt.target;
}

Over and Out

JavaScript: Sorting Complex Arrays

I wasn't aware that JavaScript text sorting was case sensitive (well on ie7 I've verified it is). So, Here is a simple example of sorting an Object Array taking into account case sensitivity.

for (var i in searchList) {
var indexOfTerm = WordStartsWith(searchList[i].Text, searchPhrase);
if (indexOfTerm > -1) {
results[results.length] = { Item: searchList[i],
IndexOf: indexOfTerm,
toString: function() { return this.Item.Text.toUpperCase(); }
};
}
}

results.sort();

By overloading the toString method we can convert our sort key to upper case and boom sorting works properly.

P.S.,
WordStartsWith is a method that returns the index of a search term in a text string.
searchList is a JSON structure with a bunch of data for use by a custom auto complete.

Each item in the results array is an object thus I've overridden the toString method to return an upper case copy of the text item for use in sorting (The JavaScript array calls toString to get sortable data).

Over and Out