Monday, 11 May 2009

Firefox and form tags

Here's one for you.

If you have a table layout with form elements within it, make sure you place the form tags outside the table altogether. Put them just inside the body tag if you can.

I was putting form tags within table tags, and it was causing the form to close itself prematurely.

I was using javascript to render the form elements, and when looking at the generated source, I saw that firefox was closing the form tag early.

It works okay within IE 8, though it breaks in Chrome and Firefox.

Let that be a lesson to you. It certainly was for me!

Friday, 11 April 2008

Fetching and processing POP3 email in C#.NET

This is a problem that plagued the first three hours of my day, and was solved by the incredibly handy OpenPop.NET. I played with two other POP-related products including one entry on TheCodeProject.com, but with not much in the way of luck.

I was really impressed with OpenPop.NET because I was able to create a POP3 solution that:

  1. Connected to a POP server.
  2. Fetched some email.
  3. Checked the attachments for the ContentType of text/xml.
  4. If it was XML, I then processed and saved the XML to disk.

All of the above took a grand total of 60 minutes to complete, and all of this was without any documentation (I think it's a side-project of two developers who haven't gotten around to documenting it yet), which speaks volumes for the simplicity of its design and the properties and methods it exposes.

Source code is below just in case you get stuck. Obviously you'll need to introduce some error trapping.


That URL again - http://sourceforge.net/projects/hpop/!

Friday, 30 November 2007

Dynamically change the cssclass of a div

I can never remember how to do this, so it's definately worth documenting.

You can add runat="server" and an id tag to any control, and you'll be able to access it from the code-behind, just don't expect to get at all of the attributes that the HTML version presents.

In my case, you can't edit the CSS class of a div just by adding an id and a runat="server" tag.

It turns out that you can, but it's not as direct as you may think. Most of the time properties like that come up by default, but not divs! For divs, you have to add the attribute manually:

myDiv.attributes("class") = "myclass"

If you need to do it for a bind method, you can cast the control to a htmlgenericcontrol.

All I can is that it's easy when you know how.

Thursday, 27 September 2007

Premature databinding in a user control

It happens to us all. You go to bind a data repeater to a user control, but it happens far too soon in the event loading process, and you end up with a repeater that doesn't update until you re-refresh the page.

An example of this not working is as follows:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

rptBasket.DataSource = bList
rptBasket.DataBind()

End Sub

The reason this won't work is because the page_load event happens too soon for your repeater to be bound. So use the page_loadcomplete event, right? Wrong. There is no page_loadcomplete event for user controls, so to get your datalist / datarepeater to bind at the right time, you're going to have to use a page_preRender event. It does the same job as the page_loadcomplete event.

Last.FM scrobbling via Creative Zen / Winamp

I know this isn't strictly coding-related, but it's a bit geeky for my other blog, and I know for a fact that there are a lot of deserving people out there who want to scrobble Creative Zen Vision:M tracks on their Last.FM account via Winamp.

The problem is that Winamp grabs the tracks from your player via a http stream which means that audioscrobbler ignores it. The way to get around it is to stop using the latest version of last.fm, and revert to an old version of the audioscrobbler plugin that didn't require the last.fm program.

The version you're looking for is:

audioscrobbler.wa.1.1.11.exe

If you find that, install it instead of your latest plugin, you should be away!

Thursday, 6 September 2007

Element.setAttribute and other strange problems

Heed this.

If you're using javascript events like onmouseover and onmouseout, don't bother using them if you want to do something clever.

My plan for these events was as follows:
  • Your image has an onmouseover and onmouseout state. An on / off state.
  • When clicking this image, the onmouseover and onmouseout state change. So does the source of the image.
The trouble with this is that if you want to modify the onmouseover and onmouseout events dynamically in a javascript function depending on whether the image has been clicked or not, you're out of luck. Firefox supports the element.setAttribute('attribute','property') method, but Internet Explorer versions do not.

Even what Firefox does support seems to be patchy, and doesn't complete my image swapping. The event states didn't want to stick across browser versions.

It turns out that if you want to alter those mouse-related events, you can't do it dynamically in a javascript function. IE won't let you at all, and Firefox's support seems to be buggy.

So how did I get around this?

Our creative girl produced a cascading stylesheet which had images with on/off states in them, and then moved the image depending on what the class of the div surrounding our image was. From there, we could alter the class of the div and therefore alter the hover states.

For example:




Where price_result1 in the stylesheet is:

.price_result1 {
width:44px;
height:12px;
background:url(../images/result_headers/price.gif);
float:left;
}

.price_result1 a {
display:block;
width:44px;
height:12px;
background:url(../images/result_headers/price.gif) 0% 0% no-repeat;
}
.price_result1 a:hover {background-position:0% 75%;}

price_result2 is:

.price_result2 {
width:44px;
height:12px;
background:url(../images/result_headers/price.gif) 0% 75% no-repeat;
float:left;
}
.price_result2 a {
display:block;
width:44px;
height:12px;
background:url(../images/result_headers/price.gif) 0% 75% no-repeat;
}
.price_result2 a:hover {background-position:0% 100%;}





And so on.

I hope this helps. Really I do, because it took me three days to work this out.

The XMLHttpRequest object

This is AJAX related, and likely to cause problems if you're doing what I'm doing.

I use the object to write out some HTML into a div of a page.

The HTML I'm writing is from an ASP file, and so the syntax for the (pre-declared object) looks like this:

url = "searchDBaseAjax.asp?" + savedUrl;
url=url+"&sid="+ Math.random();

xmlHttp.onreadystatechange=caravanSearchStateChanged;
xmlHttp.open("GET",url,true);
xmlHttp.send(null);


Now if youre searchDBaseAjax.asp file contains some javascript that you want to write to that div, and you want it to happen straight away, you'll have problems.

Say you put a hidden input field in your ASP file.

Say that you then want to test this within the function that you write your ASP file from (just below the code mentioned above).

if (document.getElementById('hideHeaders').value == '1') {
document.getElementById('resultsHeader').className = ' none';
}
else {
document.getElementById('resultsHeader').className = 'floatleft paddingtop15';
}

Because this is an asynchronous call, it's likely that the processing of the AJAX method will not be completed by the time that your javascript underneath executes, and therefore your input field will not be tested properly.

One solution was to make this method synchronous. (Change the true in the open method to false). Trouble is, that doesn't work.

So to fix it, I used the xmlHttp.onreadystatechange attribute to specify the method caravanSearchStateChanged which is mentioned in the first code-snippet.

That method now looks like this:

function caravanSearchStateChanged()
{
if (xmlHttp.readyState==4)
{
document.getElementById("ajaxSearchResults").innerHTML=xmlHttp.responseText;

if (document.getElementById('hideHeaders').value == '1') {
document.getElementById('resultsHeader').className = ' none';
}
else {
document.getElementById('resultsHeader').className = 'floatleft paddingtop15';
}
}
}

So basically, the ready state for our open method is 4 and I've checked that this is the case before I fire off my new javascript that tests the input field.

Days of messing about, this took.

For more information, check out the MSDN entry.