NiceForms with even nicer select September 11, 2005
Posted by Slobodan Kovacevic in : Programming , trackbackUPDATE 31-Jan-2007: There’s a new version of Niceforms. For more info see this post.
Few months ago I stumbled upon a great piece of JavaScript called NiceForms by Lucian Slatineanu. The idea of script is to replace all form elements with visually much nicer and more controllable elements. Great thing about it is that it replaces all form elements automatically, meaning that you don’t need to make any changes to your form. As a consequence if JavaScript is turned off it just degrade to ordinary form.
NiceForms still has some problems - for example with accessibility such as tab element switching, with changing text size manually in FireFox, etc. (for more info visit Lucian’s site).
One particular problem it has is with select elements:
- You can only open select by clicking on right arrow
- It doesn’t close automatically (i.e. when you click somewhere else), you either need to select an option or click right arrow again. This can create some strange effects, for example you can have more then one drop down option list open at the time.
- When first loaded it has some default text instead of currently selected option, which can lead to problems if you have pre-selected an option in HTML.
So, I had some time and decided to try to fix this. Hopefully these fixes will be included in following versions.
If you don’t want to read all the details you can just see modified NiceForms in action or download a ZIP containing the whole modified NiceForms example.
If you want to read everything, then here is what I did…
Beside one new function I created all changes are inside replaceSelects() function. First addresses the problem with removing default text and putting actual selected option as a default value. Original code took this value from global var:
This can be simply replaced with:
Next change tries to solve the two biggest problems - opening option list by clicking anywhere on select and closing by clicking anywhere. Instead of using just a link (right arrow), as original code did, I had to use events. So the final code looks like this:
{
//these are for Mozilla
eval("selectArea.addEventListener(’click’, function (e) { e.stopPropagation(); if(isAnyOptionVisible() != "+i+" && isAnyOptionVisible() >= 0) { showOptions(isAnyOptionVisible());} showOptions("+i+"); }, true)");
document.addEventListener(‘click’, function (e) { showOptions(isAnyOptionVisible());}, false);
}
else if(document.attachEvent)
{
//these are for IE
eval("selectArea.attachEvent(’onclick’, function (e) { if (!e) var e = window.event; e.cancelBubble = true; if(isAnyOptionVisible() != "+i+" && isAnyOptionVisible() >= 0) { showOptions(isAnyOptionVisible());} showOptions("+i+"); } )");
document.attachEvent(‘onclick’, function (e) { showOptions(isAnyOptionVisible());});
}
I wanted to close option list user clicks on select element and anywhere in the window. The trick was that it user clicked another select box it needed to close one that’s already open and open the one it has just clicked.
So the first line adds an event listener for click on a select element. What it does (when clicked) is stopping event propagation; checks if any other option list is open (other then the one being clicked on) and if so closes it; and finally it opens/closes the select being clicked on (if the select is already open it will close it).
Second line adds an event listener to whole document, so if the user clicks anywhere else it will close any option list that might be open.
The key here is event propagation - different browsers use different methods (read more about Event Order). Either way, if user clicked on select (for example to open the option list) I had to stop event propagation, because inevitably it would propagate all the way up to the document which would close any open option list.
The last change is related to user choosing an option. Original code was:
Problem here is again with propagation. Since this is ordinary link (and I didn’t want to change that) the following would happen: user will click it; on click event is generated; it propagates up to document which closes the option list; then JS in href is executed which opens option list again and calls selectMe(). So, the option list will remain open. All that was needed to change is to remove showOptions() call from link, since it will be automatically closed.
That’s about it. If you missed here is the link where you can see this in action or you can download a ZIP containing the whole example. Also don’t forget to visit NiceForms site where you can find the original post and probably future versions of NiceForms.
Comments»
My form has an onChange event that doesn’t work:
Any help is welcome
Hi Josoroma,
You should call submit function like this:
this.form.submit()
It should work that way.
Hi Basti!
I used this.form.submit() but the error still happen
Error: selectField has no properties
Source File: http://www.domainname.com/t…
Line: 215
Thnaks in advanced.
I’m just rying to help josoroma with his problem, and indeed you scripts seem to mess around with events - the onChange handler of the selectbox remains intact (as checked with a simple ‘alert(document.getElementById(’mySelect1′).onchange)’ )’ ), yet the event handler simply gets ignored, so i guess you intercept some events, and forgot to pass them on afterwards.
scratch my previous comment - i guess it’s simply because the ‘onChange’ handler doesnt really make sense with the items you replace the form with, and thus dont get handled.
I want to know how i can set-up this globally in tne onclick event in the JS, because to me is not a problem if globally this executes the form?
Thanx
Hi!
Is there a way to submit the form from a select field? for me is not a problem if this is done globally in the JS. I can’t do that in the “click” handler, i don’t know how? Any help is welcome.
Thanx.
Hi!
#1
Is there a way to submit the form from a select field? for me is not a problem if this is done globally in the JS. I can’t do that in the “click” handler, i don’t know how? Any help is welcome.
#2
Theres a way to set different widths for select fields?
Thanx.
I presume that you can fix the script so it submits from select field, but I am not sure. It would probably require in-depth examination of the NiceForm script. Same goes for the width of the select fields.
Since I don’t know all the details about the script (i.e. I only used it and modified it slightly) I suggest that you try to contact NiceForms author and see if he can help you.
I did quick fix for teh drop down select fields to illustrate the way in which you could get events like onchange working.
//start basti
//optionLink.href = “javascript:showOptions(”+i+”); selectMe(’”+selects[i].id+”‘,”+j+”,”+i+”);”;
optionLink.href = “javascript:selectMe(’”+selects[i].id+”‘,”+j+”,”+i+”);”;
if (selects[i].onchange) {
var funcStr = selects[i].onchange.toString();
optionLink.href += selects[i].onchange + (funcStr.indexOf(’onchange’) >= 0 ? “; onchange();” : “; anonymous();”);
}
//end basti
I have simply added the if code with the if statement.
I just found the place where they do the function call for when the select occurs, and both appended the onchange function and a call to it after there call.
Note that this ws a 5 minute hack just to help out, and help people along.
Enjoy.
I want to add just onChange using simple one line code. Is it possible?
Yes, if you apply the fix above (to the niceforms.js), then in your html pages just specify your onchange normally (as an attribute on your select.
Hey thanks, was desparate for this piece of code. Thanks a lot
i have fixed the radio button problem:

i’ve added a event listener to the DIV Layer above the radio and checkboxes, but found out it doensnt do anything.
on debugging i found out, that the click on the label changes the checked radiobutton/checkbox, but the click on the div element doesnt so.
so i chenged the called functons a little bit
its not tested in IE right now. please do that for me
You can download my mod: http://zserv.dyndns.org:8080/robig/niceforms.js
robig
thanks for the change
that’s work great on ie.
before, that was the only reason i don’t use this apllication.
Thanks again
David
i just discovered your script after searching (hours) for a working release of niceforms. thanks to yo and Lucian for providing this excelent script to us.
One correction i have made for my self is that i changed Line 147 and 252 from options[..].value); to options[..].text). I think the displayed text shoud contain the label text and not the value. Submitting the form shows that
the Value is still correct.
On detail i missed in this solution is the tab-selection of the select and its values. The values shoud be selectable by Up/down-Arrows, so that the form can completly be filled in by keyboard.
Great Robig, the buttons works well, but just another fix, if you click two times on the same radiobutton it became unchecked… like a checkbox.
Interesting
I think unchecking the radio button is a feature that sort of upgraded what lot’s of developers wanted.
What happened if you clicked on a radio box by mistake for example, think about it. Now you have the possibility of unchecking it and therefore having a new functionality, if the field is mandatory then you are going to need a filter anyways.
Excellent Web Site! Very professional and full of great information. I am greatly enjoying it. Your enthusiasm is wonderful!!!
I have a problem.
I put this code in niceforms.js //start basti
//optionLink.href = “javascript:showOptions(”+i+”); selectMe(’”+selects[i].id+”‘,”+j+”,”+i+”);”;
optionLink.href = “javascript:selectMe(’”+selects[i].id+”‘,”+j+”,”+i+”);”;
if (selects[i].onchange) {
var funcStr = selects[i].onchange.toString();
optionLink.href += selects[i].onchange + (funcStr.indexOf(’onchange’) >= 0 ? “; onchange();” : “; anonymous();”);
}
//end basti
My problem is that it work but, the “style” it lose, i try to say that this code above convert the select to a normal select
sorry but i don’t speak english
someone can help me?
i need to add just onChange but keep the style of the select…
Colega - you may have to change the ‘ and ” characters if you copied and pasted from this website.
[…] Over a year ago I wrote about an excellent script called Niceforms and little fix I wrote (see NiceForms with even nicer select). Now a final version has been released - Niceforms 1.0 which solves a lot of problems from previous version. […]
Thank you, I just wanted to give a greeting and tell you I like your website very much.
hey there,
I wonder if you could help me out, have been trying for days. I’m trying to add nicejforms to my Ruby on Rails application, but whatever i try, the textinput and submit buttons aren’t displayed. First I thought it might have been due to a conflict between the prototype en jquery libraries, but when I ran niceforms by itself, it had the exact same problem. What am I not seeing?
Thanks in advance.
Jeroen
Hi Slobodan,
Very nice work. Thanks for sharing this.
To use this for a layout that is centered in the browser always, when dropping down the select box it stays at an absolute position and doesn’t line up with the top piece if the user were to change window size when the dropdown is down.
Do you or anyone know of a way to fix this?
Thanks!!!!
hi.
Its an nice work but in IE browsers if we type more characters in the textbox it will broken and gone away..
Hi all,
I’ve been trying to add in a time delay function on the drop-downs, I’m after the menus to revert back to normal position if the user doesn’t choose an option - so after say 10 seconds the drop-down list disappears.
Anyone help with this
Works great but in the selected state, in IE, the radio will only go half way down showing half of each state of the radio button.
Is the problem on select options using Niceforms already solved? Since I’m using FF I can’t make use of Niceforms so far unless the problems on tab element switching and changing text size manually in FireFox aren’t solved yet.
HI, I really like your script, excellent mod to Lucian’s original! I have been using the pulldown menus fine up until today when I tried to paste them into a page with existing js on it. I had a simple mouseover event which breaks and breaks the menus if I try and leave the code on the page. It also breaks if I try and incorporate into niceforms.js and call the body onload function from niceforms.js as well instead of putting it in the body of the page. I can’t get either script to work at the same time now when they work just fine separately. I have read the onChange comments above but that doesn’t apply here as onChange is not in the js…
Any ideas anyone?