...

View Full Version : date & time picker issues: form elements show above div-style popup



nilsn
03-03-2006, 08:24 AM
Hi,

I'm probably asking way too much now, but I thought I should give it a try!

I have a page with 2 scripts, a datepicker and a timepicker, both pops up in div-style.

They seems to work fine, but there are a view things I want to change, but don't know how.


They both appear under the form-element <select>
After popping up the timepicker, the popup must also disappear when clicking outside the popup (like the datepicker). Now the popup only disappears when selecting a time.
Although the timpicker works o.k., it causes an js error ("object required") after poping up



Since the example page code is too long I have to link it to a place in my website:

http://www.3dpartij.nl/date-timepicker.htm



Maybe someone can give it a try?
(Glenn, you helped me out before :thumbsup: , you see a challenge :confused: here?


Thanks in advance,

Nils

Beagle
03-06-2006, 10:33 PM
I can tackle one of these I think

You say that the pop-up divs show up below your select elements.

This ONLY happens in IE, you must browser detect for it, and you must use some javascript code to fix this (efficiently anyway).

Select elements are drawn using a separate z-index because IE uses the select boxes inherent in the windows. They basically exist in their own little world, and they punch through everything except other windows. In order to fix this, you must put another window over the select boxes, which can be done using an iframe in your popup.

So what you need to do is, create a new div, put an iframe in there (set the location to about:blank), and then put absolutely position your pop-up inside that div (not the iframe).

The reason you should do this with browser-detecting javascript is that bringing up that iframe takes a good amount of time, and is unnecessarily slow, especially if you don't need it, which you don't in non-ie browsers.

It's a hassle, but if you have some decent OO in your javascript, and a good handle on your elements, adding the iframe shim shouldn't be too big of a deal. If you need sample code, ask, and I'll try to pull up some of my previous work on it.

As for the rest of your questions, hopefully someone else has more time for you.

Roelf
03-07-2006, 12:31 PM
another way of doing this is to hide the select whenever the popup opens. unhide it when the popup closes

Beagle
03-07-2006, 08:25 PM
Heh, right sorry.

That way works great, and is a lot faster, as long as you know exactly where your date picker is being deployed.

My solution came from work on a date picker that was to be deployed in a lot of different places, some we didn't have control over, so we couldn't ensure the boxes would be hidden.

nilsn
03-07-2006, 09:21 PM
Hi there, Beagle and Roelf,

First of all, thanks for replying!

To be honest the code in my example is not mine. I just "borrowed" it ;)
I'm not that good in understanding javascripting.

After all, I think it's better to split the code in 2 (1. datepicker, 2. timepicker)

When I look at the code of the timepicker, as far as I can see it already covers the "hide the selectbox" part. Only it doesn't work!

To be honest (again) I'm not to crazy about the solution of "hiding" & "showing". I prefer the option of just showing the "div" popup above the selectbox.

As I said, I shortened the code:




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled</title>

<script type="text/javascript" language="javascript">
var imagePath='../gfx/';

var ie=document.all;
var dom=document.getElementById;
var ns4=document.layers;
var bShow=false;
var textCtl;

function setTimePicker(t) {
textCtl.value=t;
closeTimePicker();
}

function refreshTimePicker(mode) {

if (mode==0)
{
suffix="";
}
else
{
suffix="";
}

sHTML = "<table border=0 cellpadding=0 cellspacing=0><tr><td><table border=0 cellpadding=0 cellspacing=0 bgcolor='#ffffff'>";
for (i=0;i<=11;i++) {

sHTML+="<tr align=right>";


if (mode==0)
{
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else
{
hr=i+12;
}





for (j=0;j<4;j++) {
sHTML+="<td style='padding-left:4;padding-right:4;cursor:hand;border=\"solid 1px #ffffff\"' onclick='setTimePicker(\""+ hr + ":" + padZero(j*15) + " " + suffix + "\")'><a onmouseover='this.style.color=\"#b22222\";' onmouseout='this.style.color=\"\"' style='text-decoration=none' href='javascript:setTimePicker(\""+ hr + ":" + padZero(j*15) + " " + suffix + "\")'>" + hr + ":"+padZero(j*15) + suffix + "</a></td>";
}

sHTML+="</tr>";
}
sHTML += "</table></td></tr></table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='z-index:+999;position:absolute;visibility:hidden;'><table style='border-width:1px;border-style:solid;border-color:#c5c5c5' bgcolor='#ffffff' cellspacing=0 cellpadding=0><tr><td><table border=0 cellpadding=1 cellspacing=1 width='100%'><tr bgcolor='#ECE9ff'><td align='center' width='50%'><a onmouseover='this.style.color=\"#b22222\";' onmouseout='this.style.color=\"\"' style='text-decoration=none' href='javascript:refreshTimePicker(0);'>A.M.</a></td><td align='center' width='50%'><a onmouseover='this.style.color=\"#b22222\";' onmouseout='this.style.color=\"\"' style='text-decoration=none' href='javascript:refreshTimePicker(1);'>P.M.</a></td></tr></table></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;
var currentCtl

function selectTime(ctl,ctl2) {
var leftpos=21
var toppos=-17

textCtl=ctl2;
currentCtl = ctl
currentCtl.src=imagePath + "clock.gif";

aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
} while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"
hideElement( 'SELECT', document.getElementById("calendar") );
hideElement( 'APPLET', document.getElementById("calendar") );
bShow = true;
}

// hides <select> and <applet> objects (for IE only)
function hideElement( elmID, overDiv ){
if( ie ){
for( i = 0; i < document.all.tags( elmID ).length; i++ ){
obj = document.all.tags( elmID )[i];
if( !obj || !obj.offsetParent ){
continue;
}
// Find the element's offsetTop and offsetLeft relative to the BODY tag.
objLeft = obj.offsetLeft;
objTop = obj.offsetTop;
objParent = obj.offsetParent;
while( objParent.tagName.toUpperCase() != "BODY" )
{
objLeft += objParent.offsetLeft;
objTop += objParent.offsetTop;
objParent = objParent.offsetParent;
}
objHeight = obj.offsetHeight;
objWidth = obj.offsetWidth;
if(( overDiv.offsetLeft + overDiv.offsetWidth ) <= objLeft );
else if(( overDiv.offsetTop + overDiv.offsetHeight ) <= objTop );
else if( overDiv.offsetTop >= ( objTop + objHeight + obj.height ));
else if( overDiv.offsetLeft >= ( objLeft + objWidth ));
else
{
obj.style.visibility = "hidden";
}
}
}
}

//unhides <select> and <applet> objects (for IE only)
function showElement( elmID ){
if( ie ){
for( i = 0; i < document.all.tags( elmID ).length; i++ ){
obj = document.all.tags( elmID )[i];
if( !obj || !obj.offsetParent ){
continue;
}
obj.style.visibility = "";
}
}
}

function closeTimePicker() {
crossobj.visibility="hidden"
showElement( 'SELECT' );
showElement( 'APPLET' );
currentCtl.src=imagePath + "clock.gif"
}

document.onkeypress = function hideTimePicker1 () {
if (event.keyCode==27){
if (!bShow){
closeTimePicker();
}
}
}

// function isDigit(c) {
// return ((c=='0')||(c=='1')||(c=='2')||(c=='3')||(c=='4')||(c=='5')||(c=='6')||(c=='7')||(c=='8')||(c=='9'))
// }

function isNumeric(n) {

num = parseInt(n,10);

return !isNaN(num);
}

function padZero(n) {
v="";
if (n<10){
return ('0'+n);
}
else
{
return n;
}
}



</script>
</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input style="width:50px;text-align:center;" name="fld_start_time" id="fld_start_time" type="text" value="" size="8" maxlength="8">
<a href="#" OnClick="selectTime(this,fld_start_time)">pick starttime</a>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id" style="width:400px;">
<option value="1" >Netherlands</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
</body>
</html>


Roelf, you see that your solution is already in there? But not working?
Beagle, can you give me a closer idea where to put your suggested solution?

Thanks,

Nils

Beagle
03-07-2006, 09:57 PM
crap double-posted

Beagle
03-07-2006, 10:02 PM
Ok, please take this opportunity to make this code your own in some way. I would recommend getting both the hide/show and the iframe shim to work. Use this experience to gain some knowledge and insight in javascript...

...cuz that code is not fun.

if (dom){
document.write ("<div id='timepicker'

You'll need to add a second div inside the time picker div, positioned absolutely using the style attribute. Then, before the second div, inside the first div, you'll need an <iframe src="about:blank"></iframe> and that will need to have the necessary height and width to fully cover the area of the time picker:

<div id='timepicker'...><iframe src="about:blank" style="height: 5px;width: 5px;"></iframe><div id='innerTimePicker'>ALL THE STUFF INSIDE</div></div>

Good luck with this, the code you posted is unorganized and hard to follow. I hope you get either the shim or the hide/show functions working. Like I said, play with this a bit and increase your understanding. Feel free to ask what specific lines of code do, and ask about how to make them better (first provide what you think and what you believe would be an improvement, it'll go better that way)

nilsn
03-09-2006, 11:09 AM
Beagle,

You're right. I had to play with it more. It was too easy to putting it on this forum and hoping that somebody should fix it. Won't do that again.

I've gone through the script more thoroughly and put away all the stuff what wasn't necessary. Also put comments to make sure what it does (what I think it does!).

Since I want to go for your iframe option I tried to put it in. Unfortunately it doesn't work yet. Did I misunderstood it?

If you don't mind I put my cleaned code again, with your suggestion.




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker Example</title>

<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;
var textCtl;

// sets the time and put it in the field, also hides the div popup
function setTimePicker(t) {
textCtl.value=t;
closeTimePicker();
}


// toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function
function refreshTimePicker(mode) {
sHTML = "<table><tr><td><table border=1>";
for (i=0;i<=11;i++) {
sHTML+="<tr align=right>";
if (mode==0) {
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else {
hr=i+12;
}

for (j=0;j<4;j++) {
sHTML+="<td onclick='setTimePicker("+ hr + ":" + padZero(j*15) + "\")'><a href='javascript:setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</a></td>";
}

sHTML+="</tr>";
}
sHTML += "</table></td></tr></table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='z-index:+999;position:absolute;visibility:hidden;'><iframe src='about:blank' style='height: 5px;width: 5px;' ></iframe><div id='innerTimePicker'><table bgcolor='#FFFFFF' border=1><tr><td><table border=1 width='100%'><tr><td align='center' width='50%'><a href='javascript:refreshTimePicker(0);'>A.M.</a></td><td align='center' width='50%'><a href='javascript:refreshTimePicker(1);'>P.M.</a></td></tr></table></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;


// function to fire up the div-popup
function selectTime(ctl,ctl2) {
var leftpos=21
var toppos=-17
textCtl=ctl2;
aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
}
while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"

}

// hides the div-popup
function closeTimePicker() {
crossobj.visibility="hidden"
}


// I'm not sure where tot put this, but it must hides the div-popup when clicking outside the div-popup
//function autoHide(){
// this.autoHideEnabled=true;
//}


// only adds an extra zero when time in minutes is below 10
function padZero(n) {
if (n<10){
return ('0'+n);
}
else {
return n;
}
}



</script>
</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<a href="" OnClick="selectTime(this,fld_start_time);return false;">pick starttime</a>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id">
<option value="1" >This is the first option of the dropdownlist</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
</body>
</html>

nilsn
03-09-2006, 12:15 PM
Additional:

If I change the width & height of the iframe then the iframe pops up above the selectbox but also pushes the div-popup under the iframe.
Is it possible to get the div-popup into the iframe?

nilsn
03-09-2006, 02:08 PM
Hi again,

As far as I can see, I got this thing working, remains 2 issues:

1. a js error when I call the function refreshTimepicker;
toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function

2. I'm trying to close the popup div when selecting outside the div. any suggestions? (I'm still trying myself)

here is my new code:




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker Example</title>

<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;
var textCtl;

// sets the time and put it in the field, also hides the div popup
function setTimePicker(t) {
textCtl.value=t;
closeTimePicker();
}


// toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function
function refreshTimePicker(mode) {
sHTML = "<table border=1 width=100%>";
for (i=0;i<=11;i++) {
sHTML+="<tr align=right>";
if (mode==0) {
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else {
hr=i+12;
}

for (j=0;j<4;j++) {
sHTML+="<td onclick='setTimePicker("+ hr + ":" + padZero(j*15) + "\")'><a href='javascript:setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</a></td>";
}

sHTML+="</tr>";
}
sHTML += "</table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='position:absolute;visibility:hidden;'><iframe src='about:blank' style='height:350px;width:200px;position:absolute;'></iframe><div id='innerTimePicker' style='width:200;height:200;position:absolute;'><table bgcolor='#FFFFFF' border=1 width=200><tr><td><table border=1 width='100%'><tr><td align='center' width='50%'><a href='javascript:refreshTimePicker(0);'>A.M.</a></td><td align='center' width='50%'><a href='javascript:refreshTimePicker(1);'>P.M.</a></td></tr></table></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;


// function to fire up the div-popup
function selectTime(ctl,ctl2) {
var leftpos=21
var toppos=-17
textCtl=ctl2;
aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
}
while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"

}

// hides the div-popup
function closeTimePicker() {
crossobj.visibility="hidden"
}


// I'm not sure where tot put this, but it must hides the div-popup when clicking outside the div-popup
//function autoHide(){
// this.autoHideEnabled=true;
//}


// only adds an extra zero when time in minutes is below 10
function padZero(n) {
if (n<10){
return ('0'+n);
}
else {
return n;
}
}



</script>
</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<a href="#" OnClick="selectTime(this,fld_start_time);return false;">pick starttime</a>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id">
<option value="1" >This is the first option of the dropdownlist</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
</body>
</html>

Beagle
03-09-2006, 03:25 PM
Good job getting the iframe shim working, and commenting and cleaning the code!

This line is messed up. Check the quoting going on here:

sHTML+="<td onclick='setTimePicker("+ hr + ":" + padZero(j*15) + "\")'><a href='javascript:setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</a></td>";

It results in:

<td onclick='setTimePicker(6:15")'>.....

You see the extra quote you have in there? Probably the source of some problems.

As for hiding the div, that's ALWAYS fun. One way you can do it is to have a document.onclick handler close the div, and an onclick handler on the div itself to kill the event. That way, if you click anywhere but the div, it closes, but if you click on the div, the click event doesn't bubble to the document.

But that's just for clicking. One popular solution is to have a timeout for closing the div. the div's onmouseover handler clears the timeout, and the onmouseout sets the time out with a function to close the div in something like 50 milliseconds.

Good luck with that. The solution is highly dependent on your specific document structure.

nilsn
03-10-2006, 09:01 AM
I've been trying and trying, but can't get it work!

I'm able to close it when clicking outside the div, but after that I'm not able to popup the div anymore.

I added this code at the end:



function hideCurrentPopup() {
if(crossobj.visibility) {
document.onclick = closeTimePicker
}
}
document.onclick = hideCurrentPopup;


Any idea what I'm doin' wrong?

Btw, the extra quote thing is solved.

Beagle
03-10-2006, 02:19 PM
Well, once you click on the document, you overwrite the click handler, and therefore it doesn't fire again.

You're question, simply put, looks like this:

var x = 5;
x= 6;
Why doesn't x == 5?

You see, the handler overwrites itself in this case.

I think, not sure, you want:


function hideCurrentPopup() {
if(crossobj.visibility) {
closeTimePicker();
}
}
document.onclick = hideCurrentPopup;

nilsn
03-10-2006, 02:44 PM
I've tried that one too, but when I implement this (at the bottom of the script), the div doesn't popup at all (no errors)

Actually, it opens and inmediately closes the div.

Beagle
03-10-2006, 05:50 PM
Right, that's because you haven't added code to kill the event.

you need this in your onclick handler for the div AND for the function that OPENS the picker:

// *** IE
window.event.cancelBubble = true;

// *** FF
e.stopPropagation()

So example:


var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {
if (!e) e = window.event;
e.stopPropagation;
openChooser();
};

var chooser = document.getElementById('divThatIsTheChooser');

chooser.onclick = function() {
if (!e) e = window.event;
e.stopPropagation;
};

document.onclick = closeChooser();


See this page (the site is good in general) for information:

http://www.quirksmode.org/js/events_order.html

nilsn
03-14-2006, 10:14 AM
Hi Beagle,

I'm sorry to bother you again.
I've been trying and trying, but can't get it work. I stripped the code more to see what it does. Tried with alerts and stuff, no succes.

I post the whole (adjusted) script again, so you can see where I'm trying to implement your solution.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker Example</title>

<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;

// writing the actual div to the screen
if (dom){
document.write ("<div id='timepicker' style='z-index:0;position:absolute;visibility:hidden;'><table border=1><tr><td align=center width=100 height=100>blablabla</td></tr></table></div>");
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;

var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {
if (!e) e = window.event;
e.stopPropagation;
window.event.cancelBubble = true;
// like the example here is to open the div, right?
selectTime(ctl,ctl2);
}

var chooser = document.getElementById('timepicker');

chooser.onclick = function() {
if (!e) e = window.event;
e.stopPropagation;
window.event.cancelBubble = true;
};

// function to fire up the div-popup
function selectTime(ctl,ctl2) {
crossobj.visibility="visible";
}


function closeTimePicker() {
crossobj.visibility="hidden"
}


document.onclick = closeTimePicker();
</script>
</head>
<body>


<table border="0" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<a href="#" OnClick="selectTime(this,fld_start_time);return false;">pick starttime</a>
</td>
</tr>
</form>
</table>
</body>
</html>

Beagle
03-14-2006, 06:28 PM
I don't see any element called "switch" in your document. The "Switch" in my example is your href:

<a href="#" OnClick="selectTime(this,fld_start_time);return false;">pick starttime</a>

Do something like this instead of that link:

<span id="switch">Pick Start Time</span>

You'll need your script to execute AFTER the page draws the span though, so move your script tags to just before the closing body tag.

See where that gets you. Try to understand what each line in your code is doing.



var clickerThatOpenChooser = document.getElementById('switch');

Gets the element with the id "switch" but I don't see one in your document.


clickerThatOpenChooser.onclick = function(e) {

Attaches a function to be used as an event handler for the element, if you're clicking and no alerts are happening, you aren't actually clicking on that element.

You're supposed to be firing off the above function to get the effect you want, yet, you have your HREF with an onclick of a different function.

Just make the changes I recommended and you should start to see what's going on.

nilsn
03-15-2006, 09:13 AM
Hi Beagle,

I know you'r trying to let me understand what I'm actually doing, but don't forget I'm still a novice. I do my best, but I do not understand everything.

I followed your recommendations and got myself a working example, see first code (I've commented out alerts that tells me where I am)



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker 1</title>
</head>
<body>


<table border="0" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input type="text" value="">
<span OnClick="selectTime();" id="switch">Pick Start Time</span>
</td>
</tr>
</form>
</table>

<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;

// writing the actual div to the screen
if (dom){
document.write ("<div id='timepicker' style='z-index:0;position:absolute;visibility:hidden;'><table border=1><tr><td align=center width=100 height=100>blablabla</td></tr></table></div>");
}
var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;

var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {
// alert("only if the element id 'switch' is clicked, here I am");
if (!e) e = window.event;
// alert("I don't know what the if (!e) e = window.event means, but somehow this statement is true");
e.stopPropagation;
window.event.cancelBubble = true;
selectTime();
};


// function to fire up the div-popup
function selectTime() {
// alert("after checking if only element 'switch' is clicked the actual function to call the popup is fired");
crossobj.visibility="visible";
// alert("popup is fired");
}


function closeTimePicker() {
crossobj.visibility="hidden"
}

function hideCurrentPopup() {
// alert("if everything else but element 'switch' is clicked, close the popup if there is");
closeTimePicker();
// alert("popup is closed");
}
document.onclick = hideCurrentPopup;

</script>
</body>
</html>


This example pops up a div when I click the specific element and closes if I click somewhere else. So far so good.

Here comes the difficulty again. If I implement this in the real example which pops up the timepicker. I've got errors like "ct1 is not defined". Which I understand since there is no reference to that anymore. I don't know what the connection to the input field is, yet.

Here my new code with the timepicker functionality and the new errors:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker 2</title>


</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<span style="cursor:hand;" id="switch">Pick Start Time</span>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id">
<option value="1" >This is the first option of the dropdownlist</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;
var textCtl;

// sets the time and put it in the field, also hides the div popup
function setTimePicker(t) {
textCtl.value=t;
closeTimePicker();
}


// toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function
function refreshTimePicker(mode) {
sHTML = "<table border=1 width=100%>";
for (i=0;i<=11;i++) {
sHTML+="<tr align=right>";
if (mode==0) {
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else {
hr=i+12;
}

for (j=0;j<4;j++) {
sHTML+="<td onclick='setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'><a href='javascript:setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</a></td>";
}

sHTML+="</tr>";
}
sHTML += "</table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='position:absolute;visibility:hidden;'><iframe src='about:blank' style='height:350px;width:200px;position:absolute;'></iframe><div id='innerTimePicker' style='width:200;height:200;position:absolute;'><table bgcolor='#FFFFFF' border=1 width=200><tr><td><table border=1 width='100%'><tr><td align='center' width='50%'><a href='javascript:refreshTimePicker(0);'>A.M.</a></td><td align='center' width='50%'><a href='javascript:refreshTimePicker(1);'>P.M.</a></td></tr></table></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;

var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {
// alert("1");
if (!e) e = window.event;
// alert("2");
e.stopPropagation;
window.event.cancelBubble = true;
selectTime();
};

// function to fire up the div-popup
function selectTime() {
alert(ctl);
var leftpos=21
var toppos=-17
textCtl=ctl2;
aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
}
while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"

}

// hides the div-popup
function closeTimePicker() {
crossobj.visibility="hidden"
}


// only adds an extra zero when time in minutes is below 10
function padZero(n) {
if (n<10){
return ('0'+n);
}
else {
return n;
}
}

function hideCurrentPopup() {
if(crossobj.visibility) {
closeTimePicker();
}
}
document.onclick = hideCurrentPopup;
</script>
</body>
</html>


It feels like al these changes is driving me away from the original example. That 's ok, 'cause that code was probably not well-organized.
Also in the original example I was able to put multiple timepickers pointing to multiple fields in 1 form. As far as I can see, it will be difficult in this new situation or am I wrong?

Nils

Beagle
03-15-2006, 06:46 PM
Ok, so you seem like you're pretty close honestly. It's just the variables ctl and ctl2 that are giving you problems. They simply aren't defined in your code.

the function "selectTime" is popping up your time picker. It's aldo determining WHERE to position that time picker, and if you look, it's trying to do so relative to SOMETHING (ctl). That something should probably be the element you click to pop it up, right? You want the picker to show up by the mouse.

So you need to pass ctl into selectTime like so

function selectTime(ctl)

Get rid of the line that references ctl2 since it's never used.

Then, when you call selectTime, you have to pass in a control.

For starters, try using:
selectTime(document.getElementById('switch'));

That will get it to try to position the time picker by the link. But it's not generic. For a generic solution, since you have the event in the handler, you can extract the element that caused the event like so: (from http://www.quirksmode.org/index.html?/js/introevents.html)


if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;


then:

selectTime(targ);

Hopefully you're learning a lot by doing this, and will be able to fight your own way through a lot of this. 2 pages into this thread and you already seem to understand a lot more than when you first posted this problem. ;)

nilsn
03-17-2006, 10:12 AM
Hope you don't get sick of me, 'cause here I am again.
I just want you to know I'm still on it. Every time I have I try to work on it.
Yes, I learn a lot from it and I'm glad you still helping me out :thumbsup:

You're pushing me to get to understand it.

Although I'm absolutely trying to solve the next issues myself, I keep you posted the next issues to solve.

1. the time picked from the timepicker isn't put as a result in the input field. As far as I can see ther is no relation to that field anymore.
2. As you may noticed from the very first timepicker there was a toggle function between A.M & P.M. In the new code clicking on each of them closes the popup, since this exception is excluded.
3. if I put a multiple fields (e.g. pick closing time), how to popup the timepicker next to each field and also put the values in their fields?

code so far:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker 2</title>
</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<span style="cursor:hand;" id="switch">Pick Start Time</span>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id">
<option value="1" >This is the first option of the dropdownlist</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;
var textCtl;



// sets the time and put it in the field, also hides the div popup
function setTimePicker(t) {
// textCtl.value=t;
closeTimePicker();
}


// toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function
function refreshTimePicker(mode) {
sHTML = "<table border=1 width=100%>";
for (i=0;i<=11;i++) {
sHTML+="<tr align=right>";
if (mode==0) {
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else {
hr=i+12;
}

for (j=0;j<4;j++) {
sHTML+="<td style='cursor:hand;' onclick='setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</td>";
}

sHTML+="</tr>";
}
sHTML += "</table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='position:absolute;visibility:hidden;'><iframe src='about:blank' style='height:350px;width:200px;position:absolute;'></iframe><div id='innerTimePicker' style='width:200;height:200;position:absolute;'><table bgcolor='#FFFFFF' border=1 width=200><tr><td><table border=1 width='100%'><tr><td style='cursor:hand;' onclick='refreshTimePicker(0);' align='center' width='50%'>A.M.</td><td style='cursor:hand;' onclick='refreshTimePicker(1);' align='center' width='50%'>P.M.</td></tr></table></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;



var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {




// alert("1");
if (!e) e = window.event;
// alert("2");
e.stopPropagation;
window.event.cancelBubble = true;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
selectTime(targ);
};

// function to fire up the div-popup
function selectTime(ctl) {
// alert(ctl);
var leftpos=21
var toppos=-17
// textCtl=ctl2;
aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
}
while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"

}

// hides the div-popup
function closeTimePicker() {
crossobj.visibility="hidden"
}


// only adds an extra zero when time in minutes is below 10
function padZero(n) {
if (n<10){
return ('0'+n);
}
else {
return n;
}
}

function hideCurrentPopup() {
if(crossobj.visibility) {
closeTimePicker();
}
}
document.onclick = hideCurrentPopup;
</script>
</body>
</html>



As I said before I'm not only sitting and waiting 'till you come back to me, I am trying to find the answers myself as well.

Beagle
03-20-2006, 04:55 PM
ah yes, now you're getting to the difficult questions.

Probably the best way to keep your picker open while you click around is to wrap all of the elements that should NOT close it in a div, so an example would be your am/pm switcher and your text input. if you can wrap those in a div, and add the killEvent function to the onclick of that div, all the clicks within that div will be stopped from going to the document object, which would close the timepicker. Get what I'm saying? Try taking a look at quirksmode.org and reading up on how events work. They bubble up from the source element (the button you clicked) through ALL of the containing elements (so a button in a div in a form in a div in document) and you can catch it at any point in the bubble.

As for getting the timepicker value into the input field, you need to figure out how the user chooses a time. If they click a specific element, add an onclick handler to that elements and get the values you need from whatever fields you have. I don't really know how else to say it. Look into the code for the timepicker itself and see if you can at least alert the values. Once you get there, it's not too hard to get the text input field and set it's value like:
document.getElementById('fld_time_pickr').value = whatever;

And as for opening it up in a different spot everytime, well, you can pass in the element that is being clicked on, and then get it's X and Y offsets, and then adjust the X and Y offsets of the timepicker itself.

element.style.top = '150px';
element.style.left = '250px';

Again, http://www.quirksmode.org/ has a nice explanation of positioning and two functions for getting the X and Y offset of any element in a browser-neutral way.

But if you move the time-picker around, you'll need to change the destination text box as well right? That means that when you open the time picker, you somehow need to make point to the appropriate input box. This could be using a global variable that you set when the element is clicked. You could also create a time-picker object and keep a member variable that points to the appropriate input field. There's a bunch of options.

This is definitely an involved and interesting task. I had something similar. I solved it using object orientation, inheritance, and created my own event handling model as well. It was a little slow though. There's a number of ways to solve it, and I'd rather see what you come up with and learn from you than to tell you to emulate my solution.

No problem about the help. It's my pleasure.

nilsn
03-21-2006, 09:06 AM
Again, you help me a little further. Solved 2 from the 3 issues (see code)
Although I'm not sure if I implement issue 1 correct, it does wat it supposed to do. The second one I already figured out myself :)

Before I go to the 3 one, I have a question:
Isn't it easier to fire from an onclick event from the span next to each field (in my new code I have a starting time and ending time)
So the the code must be more generic and pointing to the span that triggers.

Again I keep on testing & trying (although my little daughter is asking a lot of time from me, haha)

Here is my new code again:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Timepicker 2</title>
</head>
<body>


<table border="1" cellspacing="1" cellpadding="1">
<form action="" method="post" name="frm_admin">
<tr>
<td>
<input name="fld_start_time" id="fld_start_time" type="text" value="">
<span style="cursor:hand;" id="switch">Pick Start Time</span>
</td>
</tr>
<tr>
<td>
<input name="fld_end_time" id="fld_end_time" type="text" value="">
<span style="cursor:hand;" id="switch">Pick End Time</span>
</td>
</tr>
<tr>
<td>
<select name="fld_country_id">
<option value="1" >This is the first option of the dropdownlist</option>
<option value="2" >Other ...</option>
</select>
</td>
</tr>
</form>
</table>
<script type="text/javascript" language="javascript">
var ie=document.all;
var dom=document.getElementById;
var textCtl;



// sets the time and put it in the field, also hides the div popup
function setTimePicker(t) {
document.getElementById('fld_start_time').value = t;
closeTimePicker();
}


// toggling between A.M & P.M. : gives this js error "Expected ')'" only in IE. Not sure where/why it happens, but it doesn't influence the function
function refreshTimePicker(mode) {
sHTML = "<table border=1 width=100%>";
for (i=0;i<=11;i++) {
sHTML+="<tr align=right>";
if (mode==0) {
if (i<=9) {
hr = "0" + i;
}
else {
hr=i;
}
}
else {
hr=i+12;
}

for (j=0;j<4;j++) {
sHTML+="<td style='cursor:hand;' onclick='setTimePicker(\""+ hr + ":" + padZero(j*15) + "\")'>" + hr + ":"+padZero(j*15) + "</td>";
}

sHTML+="</tr>";
}
sHTML += "</table>";
document.getElementById("timePickerContent").innerHTML = sHTML;
}

if (dom){
document.write ("<div id='timepicker' style='position:absolute;visibility:hidden;'><iframe src='about:blank' style='height:350px;width:200px;position:absolute;'></iframe><div id='innerTimePicker' style='width:200;height:200;position:absolute;'><table bgcolor='#FFFFFF' border=1 width=200><tr><td><div id='toggle'><table border=1 width='100%'><tr><td style='cursor:hand;' onclick='refreshTimePicker(0);' align='center' width='50%'>A.M.</td><td style='cursor:hand;' onclick='refreshTimePicker(1);' align='center' width='50%'>P.M.</td></tr></table></div></td></tr><tr><td colspan=2><span id='timePickerContent'></span></td></tr></table></div></div>");
refreshTimePicker(0);
}

var crossobj=(dom)?document.getElementById("timepicker").style : ie? document.all.timepicker : document.timepicker;



var clickerThatOpenChooser = document.getElementById('switch');
clickerThatOpenChooser.onclick = function(e) {

if (!e) e = window.event;
e.stopPropagation;
window.event.cancelBubble = true;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
selectTime(targ);
};

var clickerThatStaysOpen = document.getElementById('timepicker');
clickerThatStaysOpen.onclick = function(e) {

if (!e) e = window.event;
e.stopPropagation;
window.event.cancelBubble = true;
};

// function to fire up the div-popup
function selectTime(ctl) {
// alert(ctl);
var leftpos=21
var toppos=-17
aTag = ctl
do {
aTag = aTag.offsetParent;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
}
while(aTag.tagName!="BODY");
crossobj.left = ctl.offsetLeft + leftpos
crossobj.top = ctl.offsetTop + toppos + ctl.offsetHeight + 2
crossobj.visibility=(dom||ie)? "visible" : "show"

}

// hides the div-popup
function closeTimePicker() {
crossobj.visibility="hidden"
}


// only adds an extra zero when time in minutes is below 10
function padZero(n) {
if (n<10){
return ('0'+n);
}
else {
return n;
}
}

function hideCurrentPopup() {
if(crossobj.visibility) {
closeTimePicker();
}
}
document.onclick = hideCurrentPopup;
</script>
</body>
</html>

Beagle
03-27-2006, 04:41 PM
Ask me a specific question about a specific problem and describe how you attempted to solve. Otherwise, you look like you're going to be fine without too much extra help.



I'm not sure if I implement issue 1 correct


There are no correct implementations, only varying degrees of efficient, clean, extensible implementations that get the job done. However you do it, if it works, is a perfectly reasonable way to do it.

nilsn
04-07-2006, 09:25 AM
Hi Beagle,

sorry for not answering back, yet. My wife took me on an unexpected small holiday. Always fun, don't you think? :)

I leave it as it is, now. At the moment it is working allright. I will try to fix this last issue myself.

For now, thank you very much for your patience, time and advises.
It was very useful.

Nils



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum