Busted Mug

A blog that documents solutions to the most frustrating problems that occur during development in technologies such as Java, XML, AJAX, SQL, CSS and others that make me want to throw my coffee mug against the cube wall.

Tuesday, December 12, 2006

Dynamically assigned onclick event never executed when clicking link - Javascript / DHTML / Ajax

I just conquered an issue I was having with adynamically assigned onclick event never executed when clicking a link (click me for details). Essentially what I ended up coming up with and highly recommend to others is that if, for some insane crazy reason inexplicable even by cold Vulcan logic, your dynamically assigned event handler just WON'T go - do something like this:
    for (var i=0;i<arr.length;i++)
 a = _bsn.DOM.createElement("div", { bgColor:"white" });
= "<a href=\"#\" onclick=\"selVal(document.getElementById('"+pointer.fld.id+"'),"+arr[i]+");\">"+arr[i]+"</a>";
        var li 
= _bsn.DOM.createElement(  "li", {}, a  );
        ul.appendChild(  li  );

Colorized by: CarlosAg.CodeColorizer That is to say, write out a div and fill the innerHTML (even though that a little off standard ;( ) with the element and explicitly write out the event handler. Then it will take for sure. Though that seems kinda common sense to me looking back on it, many hours of eye strain when into coming to that solution.

Monday, December 11, 2006

IE Select z-index bug (w/select-free layer and autosuggest)

Recently I ran into one of the biggest nasties I've ever seen. It is in IE (fixed in 7 thankfully). When you've got any element over a select box, the select box breaks through and shows on the top. It is a real bugger to fix. This page INCORRECTLY throws in the towel and says you can't fix it so just alter your design. To it's credit, it does sum up the problem pretty well and has a nice pic: I ran into this while implementing Autosuggest which I think is a great UI add-on. However, you'll run into issues when you autosuggest overtop of a select. No good. The solution to the select popping over is called Select-free layer. It is very interesting. Don't be confusing by the dragginess of their example. All it does is filter a hidden iframe though to cover any selects, since an iframe doesn't suffer the bug (unless you have selects on that, then heaven help you). In a nutshell they use this css:
<style> .select-free { position:absolute; z-index:10;/*any value*/ overflow:hidden;/*must have*/ width:33em;/*must have for any value*/; } .select-free iframe { display:none;/*sorry for IE5*/ display/**/:block;/*sorry for IE5*/ position:absolute;/*must have*/ top:0;/*must have*/ left:0;/*must have*/ z-index:-1;/*must have*/ filter:mask();/*must have*/ width:3000px;/*must have for any big value*/ height:3000px/*must have for any big value*/; } .select-free .bd{border:solid 1px #aaaaaa;padding:12px;} </style> <div class="select-free" id="dd3"><div class="bd"> your content here </div><!--[if lte IE 6.5]><iframe></iframe><![endif]--></div>
I had the agonizing task of integrating this with autosuggest. It isn't fun. Some css had to be changed:
<style type="text/css"> /* =========================== styling for autosuggest =========================== */ .autosuggest{ position:absolute; z-index:10;/*any value*/ overflow:hidden;/*must have*/ width:100px;/*must have for any value*/; } .autosuggest .bd{border:solid 0px #aaaaaa;padding:0px;} .autosuggest #mask{ border: 0px; margin: 0px; display:none;/*sorry for IE5*/ display/**/:block;/*sorry for IE5*/ position:absolute;/*must have*/ top:0;/*must have*/ left:0;/*must have*/ z-index:-1;/*must have*/ filter:mask();/*must have*/ width:3000px;/*must have for any big value*/ height:3000px/*must have for any big value*/; } ul.autosuggest { //position: absolute; list-style: none; margin: 0; padding: 0; //overflow-y: auto; } ul.autosuggest li { text-align: left; border-bottom: 1px solid blue; border-left: 1px solid blue; border-right: 1px solid blue; } ul.autosuggest li a:link, ul.autosuggest li a:visited { display: block; padding: 0px; text-decoration: none; text-color: black; background-color: #EEEEEE; } ul.autosuggest li a:hover, ul.autosuggest li a:active { color: #fff; background-color: green; } ul.autosuggest li.highlight a:link, ul.autosuggest li.highlight a:visited { color: #fff; background-color: green; } </style>
(mask is the id of my iframe btw) and then I had to change some of BSN's javascript to support select-free layer:
_bsn.AutoSuggest.prototype.createList = function(arr) { // clear previous list // this.clearSuggestions(); // create and populate ul // var ulWrap = _bsn.DOM.createElement("div", { id:this.idAs, className:this.oP.className }); var ulCont = _bsn.DOM.createElement("div", { id:"inner", className:"bd" }); var ul = _bsn.DOM.createElement("ul", {id:this.idAs+"ul", className:this.oP.className}); var pointer = this; for (var i=0;i<arr.length;i++) { var a = _bsn.DOM.createElement("a", { href:"#" }, arr[i]); a.onclick = function () { pointer.setValue( this.childNodes[0].nodeValue ); return false; } var li = _bsn.DOM.createElement( "li", {}, a ); ul.appendChild( li ); } var pos = _bsn.DOM.getPos(this.fld); ulWrap.style.overflow = "hidden"; ulWrap.style.left = pos.x + "px"; ulWrap.style.top = ( pos.y + this.fld.offsetHeight ) + "px"; ulWrap.onmouseover = function(){ pointer.killTimeout() } ulWrap.onmouseout = function(){ pointer.resetTimeout() } ul.style.width = this.fld.offsetWidth + "px"; ulCont.style.width = this.fld.offsetWidth + "px"; ulWrap.style.width = this.fld.offsetWidth + "px"; ulCont.style.height = ((ul.childNodes.length-1) * (this.fld.offsetHeight+2)+6); ulWrap.style.height = ((ul.childNodes.length-1) * (this.fld.offsetHeight+2)+6); ulCont.appendChild(ul); ulWrap.appendChild(ulCont); ulWrap.innerHTML += "<!--[if lte IE 6.5]><iframe id=\"mask\"></iframe><![endif]-->"; //document.getElementsByTagName("body")[0].appendChild(ul); document.getElementsByTagName("body")[0].appendChild(ulWrap);
In the end it was a real bugger to get going but sure enough my auto suggest is no longer broken by IE's stupid bug. I hope this helps any other poor souls that face this task. If you suffer from IE's select bug at all I highly recommend select-free layer. If I wasn't doing autosuggest too it would have been an easy patch to apply. I hate IE btw ;) They made me play DHTM-Hell for a few days this time.

Wednesday, December 06, 2006

Javascript date sorting using regular expressions

First off, let me say that this guy is awesome. I've referenced many of his articles over the years and they're all very helpful. Specifically, I used his Date Sort article today. I was dealing with an array of dates in javascript and needed to order them. The functions he lists use a regular expression. These are rather funky to look at:
var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4})/;
but extremely useful and elegant. He also offers functions like:
function mdyOrdA(a, b){ a = a.replace(dateRE,"$3$1$2"); b = b.replace(dateRE,"$3$1$2"); if (a > b) return 1; if (a < b) return -1; return 0; }
that you can use with Array's sort method to elegantly sort like so:
dateArray = new Array('15/10/2000','28/05/1999', '17/09/2005','06/12/2004','02/01/1998'); dateArray.sort( mdyOrdA ); document.write('Ascending : ' + dateArray + '
Bravo, Mr. Chapman! Very elegant.

JS Array hax: Push Pop Shift and Unshift

These incredibly useful array methods are often overlooked and under utilized. When used properly, if for some reason you need to change your code from appending an array to pre-pending it, you just change from push() to unshift(). It should take all of two seconds. Without using these functions you'll end up writing 10 lines or so that are SOOOOOO boring you'll want to barf. Here's a quick reference of what they do: push() - add element to the end of the array pop() - remove and return the element at the end shift() - remove and return the element at the beginning unshift() - add element to the beginning of the array pushing the others down 1 Shift and unshift seem to me to save the most time.

Tuesday, December 05, 2006

JavaScript undefined Property

JavaScript undefined Property - when you need to see if a variable has been defined you can just check if it is equal to the undefined keyword I.E. if (t1==undefined). This is good to use when you have optional parameters to a function.

Monday, December 04, 2006

Ajax auto-suggest / auto-complete | BrandSpankingNew

I was working on a site enhancement and came across this JS/CSS front end for an AJAX auto complete text box. This is huge as far as the user experience goes. The front end probably needs some UI tweaking and there's no back end (of course, you'll need to make that use specific) but it's a good start down the road.

Friday, December 01, 2006

Clearing all options from a select

OUCH! I wrote this post to only later learn that doing anything like this:
if (this.selectedDates.length == 0) document.getElementById(this.listName).options[0] = new Option("","");
is just dumb. A million times better solution is:
document.getElementById(this.listName).length = 0;
Don't you hate when an answer is blindingly obvious? I just figured that length would be read only. Oh well.