PDA

View Full Version : [MERGED] DHTML Window Widget: Need onMouseOver Handler Function



twohawks
10-03-2007, 01:28 AM
1) Script Title: DHTML Window widget (v1.03)

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex8/dhtmlwindow/index.htm
(Thank you to the author!)

3) Solution Offered: Figured out how to allow a window to open/close when mouseOver/Out on a relevant link, but keep window open (stick) when clicked - until close button clicked.

Don't know why this was so hard to find a solution for. Seems natural to want to have this Please add your comments as to coding method efficiency and compatability (if you observe any potential issues, conflicts, oversights, etc), and let me/us know if this was helpful to you.

4) My solution theory: capture any relevant onclick event and set a variable value (on/off), then set the onMouseOut event handler to respond to a function that determines if it should react based on that on/off value (i.e., if link 'clicked' then kill mouseout event).

5) The simple code. Edit dhtmlwindow.js and then add your script in your document.

5a) In dhtmlwindow.js Add after ~line 325

} //End dhtmlwindow object
the following code

isclicked=0
function clickCheck(){
if (document.onclick == null)
isclicked = 1
}
function m_out(){
if (isclicked == 0){
ajaxwin.hide(); return true
}
isclicked=0
}

5b) Here is an example of a link from my document:


<a href="http://www-dot-myweb-dot-org/lodge.htm" title="Purification Lodge"
onMouseOver="ajaxwin=dhtmlwindow.open('plodgebox', 'ajax', 'lodge.htm', 'Purification Lodge', 'width=400px,height=400px,left=100px,top=100px,resize=0,scrolling=1'); return false;"
onMouseOut="m_out()"
onClick="clickCheck(); ajaxwin=dhtmlwindow.open('plodgebox', 'ajax', 'lodge.htm', 'Purification Lodge', 'width=400px,height=400px,left=100px,top=100px,resize=0,scrolling=1'); return false;"
>Purification Lodge</a>

I hope someone may find this useful - It took me a while to figure it out.

Cheers,
TwoHawks

PS: The next challenge is to find a simple method for relatively positioning the popup window so it doesn't appear under the cursor, but will appear either... left of it if the cursor is far enough to the right, OR right of it if the cursor is far enough to the left.
!!!! - any direction on that would be much apreciated ;^)

twohawks
10-04-2007, 10:24 PM
Update: POPUP WINDOW LAYER DELAY
I needed to set a timeout for the popwindow to be delayed in appearing as the cursor moves across the screen and may happen to touch links and trigger the windows (annoying), and then also add the ability to cancel the mouseout event trigger that is in progress prior to window appearance otherwise "early mouseout" event cannot capture the window to close it (your mouse goes somewhere else and a moment later the window pops up and stays there! - not good).

To do this I
1) place ajaxwin into a setTimout function (note the escaping for the embedded single quotes),
2) assign that setTimeout function to a variable so I can refer to it in...
3) a clearTimeout function is added to the onmouseout event handler for cancelling and onmouseover timer if the cursor is moved away before the popwindow opens.

Here's how the new link code looks:
<a href="http:// wwwDOTmywebsiteDOTorg /lodge.htm" title="Purification Lodge"
onMouseOver="omotime=setTimeout('ajaxwin=dhtmlwindow.open(\'plodgebox\', \'ajax\', \'lodge.htm\', \'Purification Lodge\', \'width=400px,height=400px,left=100px,top=100px,resize=0,scrolling=1\');', 2000); return false;"
onMouseOut="clearTimeout(omotime);m_out();"
onClick="clickCheck(); ajaxwin=dhtmlwindow.open('plodgebox', 'ajax', 'lodge.htm', 'Purification Lodge', 'width=400px,height=400px,left=100px,top=100px,resize=0,scrolling=1'); return false;"
>Purification Lodge Ajax</a>

Works cleanly afaikt. Maybe this will help someone ;^)
Cheers,
TwoHawks

twohawks
10-05-2007, 06:52 PM
1) Script Title: DHTML Window widget (v1.03)

2) Script URL (on DD):
http://www.dynamicdrive.com/dynamicindex8/dhtmlwindow/index.htm

3) Describe problem:
First of all, thank you for sharing this fine code with us!
...now on to...
-----------------------------------------------------
I have configured the widget to behave in the following manner: onMouseOver/Out the layer shows/hides accordingly, onClick the window layer shows and remains open until the close button is clicked.
The problem I need to solve is.... When the new window layer happens to appear "under the mouse" when triggered via a mouseover event I wish to have the window remain visible, as I have configured it to do for the click event.
What currently happens in this case is the window "flashes continually" because I have onmouseout event for the triggering link set to dismiss the layer.


=========================================
FOLLOWUP EDIT: Possible solution found #1.
I am trying out the following code in init:function section and it seems to work...

t.handle.onmouseout=function() {dhtmlwindow.close(this)}
=========================================

Original post continues.......
-----------------------------------------------------
4) The Details:
Note--I am using the ajax method...
Essentially I thought what will work best is if I can
- 'capture' the onmouseover event for the appearing layer window object I could use it to
- trigger a cancel document.onmouseout event currently in progress,
- thus leaving the window visible if it happened to appear right under the mouse.

Sounds straightforward enough, but after trying about five totally different methods/approaches for doing this I have to admit I am stumped - I have failed to make any of them work!

Most plausable approach???:
Out of all the methods I tried, I thought the simplest and most accessible way might be something along the lines of using the addevent function that is supplied already for doing something like:

this.addEvent(window, function(){ ( isclicked=1 ) }, "mouseover")

...kind of thing in the open:function section. (isclicked is called in my onmouseout kill switch...)

Note that since I already have a function for killing the document.onmouseout in progress, all I think I would need to do for the addEvent function is set my variable isclicked=1 and that should do it. (For more info on that, reference the below link.)

For this addEvent function to work I think there would also need to be a line in the init:function section along the lines of:

t.onmouseover=function(){dhtmlwindow.onmouseover}

!!...but I am uncertain what exactly should be scripted for that to bring it all together. I have tried several variations of code for the addEvent function but I have been unsuccessful in detecting the layer appearing under the mouse.

--------------------------------------------------------

The short description is:
1) OnMouseOver/Out display/hide the layer, using a delay for showing so that simply passing the mouse over the link won't trigger it immediately, but moving the mouse away (i.e., casually passing over a link) cancels the onmouseover event so "delayed window appearance" won't occur either.
2) OnClick display the layer untill the user closes the layer window. I.e, sticky window when link is clicked.

This is the next to last problem I need solve ;^)
After that, I need to make it so that if another (2nd) layer opens the current (1st) one closes.
Later I wish to write something that makes a smart decision to open the layer either to the right or left of the mouse, depending upon how close the mouse is to the left or right of the window - but later for that!

Cheers,
TwoHawks

ddadmin
10-06-2007, 11:04 AM
Please don't start multiple threads on essentially the same question. Just add to the existing thread, which makes it easier for everyone to follow. :)

Regarding your question, if I understand correctly, basically you want to be able to create a link that shows/hide the DHTML window onMouseover and onMouseout, respectively. Clicking on the link though should show the DHTML window until the user explicitly clicks the close button. Sure, try something like this:




<!-- 3) DHTML Window Example 3: -->

<script type="text/javascript">
function openmypage(clickbool){ //Define arbitrary function to run desired DHTML Window widget codes
ajaxwin=dhtmlwindow.open("ajaxbox", "ajax", "windowfiles/external.htm", "#3: Ajax Win Title", "width=450px,height=300px,left=300px,top=100px,resize=1,scrolling=1")
ajaxwin.clickbool=clickbool
ajaxwin.onclose=function(){
this.clickbool=0
return true;
}
}

function hidemypage(){
if (!ajaxwin.clickbool)
ajaxwin.hide()
}

</script>
<ul>
<li><b><a href="#" onMouseover="openmypage(0)" onMouseout="hidemypage()" onClick="openmypage(1); return false">Create/ Open Window 3</a> (in IE, this Ajax demo must be run online!)</b></li>
</ul>

I tested the above, and it works.

twohawks
10-06-2007, 07:20 PM
Please don't start multiple threads on essentially the same question. Just add to the existing thread, which makes it easier for everyone to follow. :)


Okay, sorry about that... I generally would have done so considering how related they are, but I figured that since the issues appear to be technically unique enough that it would be easier for a person to relate to each specific problem, and/or easily find them when searching (3 of them I believe) without one getting muddled with everything else ...as I often see happen in coder forums - and then you have to post again anyway to address 'the other thing', and it all gets very convoluted.
* Just explaining my logic for posting that way. I am, of course, happy to follow your request, and thank you for having me as a member.


Regarding your question, if I understand correctly, basically you want to be able to create a link that shows/hide the DHTML window onMouseover and onMouseout, respectively. Clicking on the link though should show the DHTML window until the user explicitly clicks the close button. Sure, try something like...
YES.. and while dealing with if the layer happens to appear under your mouse ;^) Thanks for your recommendation. I will try your solution out today and report back.

Cheers,
TwoHawks

twohawks
10-07-2007, 12:10 AM
Followup... (all questions appear in red)
This posted code works well and I like the simplicity with setting a boolean value from the event in order to track it (this is the main thing I learned from this, thank you ;); however, in order to deal with the occasion of the newly created window layer suddenly appearing under the mouse (causing the window layer to flash incessantly instead of staying open), there still needs to be something else added, and the method I used in my previous solution is the only thing I can think of.
My only concern there would be that, in my infinite ignorance, is that the right/best way to be doing that?
Discussion follows, and then below that is my reworked solution using an augmentation of your code.

=========================================================
Discussion: testing...
In my previous solution, [summarizing]
I created a t.onmouseover function inside the init function in dhtmlwindow.js to be able to detect a mouseover event for any newly appearing layer. I do not know of another way to do this, or if this is the only way(?), but this detection appears to be necessary for handling a layer appearing under the mouse during document.mouseover events.
Then I create a function for setting a variable value, 'isclicked', for the document.onclick event, which I can then manipulate from the t.onmouseover function. This allows using 'isclicked' in other functions, like for controlling (killing or allowing) a document.onmouseout event in progress ;^).

So taken together the logic goes: "IF the link was clicked (document.click == true) AND IF the Layer appears under the mouse (window.layer.mouseover == true) THEN Kill the mouseout in progress (that automatically occurs if a layer appears inbetween the document and the mouse ;^)

In the case of this/your alternate code, as far as my limited understanding can deduce, since the init or open functions in dhtmlwindow.js cannot access the ajaxwin object/variable [can it?] it is unusable there. And since the "t" (object)variable cannot be accessed directly outside those functions, and it seems to be the only way to access the window.layer.mouseover event [is this correct?], then it would appear that there still needs to be added a t.onmouseover event function variable for detecting this, and then using that in the event handling functions (instead of ajaxwin.clickbool).
???
===========================
So, for instance, this method will work (but is it kosher or best? I do not know):
- Set variable isclicked for the document.onclick event
- Use init funct line: t.onmouseover=function() {isclicked = 1} //to detect mouseover popup layer event
- Then document mouseout event can be cancelled using that variable value
-----------------------
However, this method will not work...
t.onmouseover=function() {ajaxwin.clickbool = 1} //because it would seem that the object.variable is not accessible to the init function, and you cannot set it there,...
============================

=========================================================
So I was able to work out a solution utilizing your method by adjusting the code as follows below...
(Note: I go over these things as well as possible so it can be critiqued by the experts, since I am not the expert and something disasterous could be lurking in the code- unbeknownst to me!! I don't wish to be responsible for unwittingly teaching poor coding methods or logic to anyone ;^)

1) continue to use "t.onmouseover=function() {isclicked = 1}" I made in the init function
2) edit the/your 'boolean' function as follows...

function openmypage(clickbool){ //click (1) event 'handler' only (removed for mouseover)
// ajaxwin.clickbool=clickbool //remove this since it is not used anyway
isclicked = clickbool //i.e. we have to use this instead
ajaxwin.onclose=function(){
this.clickbool=0
isclicked=0
return true;
}
}

function hidemypage(){ //mouseout event 'handler'
if (isclicked == 0){
ajaxwin.hide(); return true
}
isclicked = 0
}

Note that openmypage() is used only for onclick, not for onmouseover, and that ajaxwin.clickbool is not used at all, but instead I am using isclicked.

3) I setup the document linking like this...

<a href="http://www.MYSITE.org/Test1.htm" title="Test1"
onMouseover="ajaxwin=dhtmlwindow.open('test1box', 'ajax', 'test1.htm', 'Open Window Test', 'width=300px,height=300px,left=60px,top=60px,resize=0,scrolling=1');"
onMouseout="hidemypage()"
onClick="ajaxwin=dhtmlwindow.open('test1box', 'ajax', 'test1.htm', 'Open Window Test', 'width=300px,height=300px,left=60px,top=60px,resize=0,scrolling=1'); openmypage(1); return false"><span style="color:yellow;">Create/ Open Window 3</span></a>


NOTE THAT:
1) openmypage(0) previously located in onmouseover is not needed, and its removal allows window.layer.mouseover detection to function correctly.
2) For those following, be sure to check out my second posting in this thread for setting a timeout delay (not shown here) for controlling document responses to the mouseover event (which can otherwise be annoying in certain applications)
3) href and title are used for compatability when the user has javascript turned off in their browser

=======================================
Well that's what I got so far. Is my logic sound? Is the code good?
Thank you very much for the 'setting a variable from the link event' lesson.
I look forward to any further comments. suggestion, corrections, etc ;^)

Cheers,
TwoHawks

ddadmin
10-09-2007, 03:59 AM
Your logic seems correct, but the problem is a little more complicated than that. Apparently when you move the mouse over a link, and a layer (in this case, the DHTML window) appears directly underneath the mouse, to the browser, it still thinks your mouse is over the link itself, and not the layer above the link. Call this a browser behavioural oddity I suppose.

FYI you can detect when the mouse moves over and out of a DHTML window, but the problem with the above messes up what you're trying to do in a way. To detect when those two events happen, you would do something like:


ajaxwin.onmouseover=function(){
document.title="You are currently over the DHTML window!"
}

ajaxwin.onmouseout=function(){
document.title="You moved out of the DHTML window!"
}

Assuming "ajaxwin" is defined obviously.

Taking everything into account, I've tried to come up with a way to:

1) Show the DHTML window when the mouse moves over a link, and hide it when the mouse moves out.
2) However, if the DHTML window happens to be in the way of the mouse cursor when it moves over a link, it is treated as a click instead, and does not go away unless the user clicks on the "close" button.

It's a little buggy still, but better than the first version of my code:


<script type="text/javascript">
function openmypage(clickbool){ //Define arbitrary function to run desired DHTML Window widget codes
ajaxwin=dhtmlwindow.open("ajaxbox", "ajax", "windowfiles/external.htm", "#3: Ajax Win Title", "width=450px,height=300px,left=100px,top=100px,resize=1,scrolling=1")
if (typeof ajaxwin.mouseoverDHTMLWindow=="undefined")
ajaxwin.mouseoverDHTMLWindow=0
ajaxwin.clickbool=clickbool
ajaxwin.onclose=function(){
this.clickbool=0
return true;
}

ajaxwin.onmouseover=function(){
this.mouseoverDHTMLWindow=1
this.moveTo(this.style.left, this.style.top)
}

ajaxwin.onmouseout=function(){
this.mouseoverDHTMLWindow=0
}

}

function hidemypage(){
document.title=ajaxwin.mouseoverDHTMLWindow
if (!ajaxwin.clickbool && !ajaxwin.mouseoverDHTMLWindow)
ajaxwin.hide()
}

</script>
<ul>
<li><b><a href="#" onMouseover="openmypage(0)" onMouseout="hidemypage()" onClick="openmypage(1); return false">Create/ Open Window 3</a> (in IE, this Ajax demo must be run online!)</b></li>
</ul>

Let me know how that works for you.

twohawks
10-09-2007, 06:28 PM
Your logic seems correct, but the problem is a little more complicated than that. Apparently when you move the mouse over a link, and a layer (in this case, the DHTML window) appears directly underneath the mouse, to the browser, it still thinks your mouse is over the link itself, and not the layer above the link. Call this a browser behavioural oddity I suppose.


Actually I don't think that's quite accurate (the quoted part in red). Although I don't understand it well enough to teach it, from what I understand the behavior has to do with continuing event propagation during the bubbling phase.
I think it goes something like ...
1) a mouseover event is 'captured' by the parent document
2) when the mouseover event 'bubbles back' from the parent element (toward the mouse) and then the child dhtml window suddenly appears inbetween the mouse and the parent,
3) then the parent element 'capture-detects' a mouseout event on its own link (!) because it 'finds no mouse there on mouseover's propagated event return',
4) however, the child capture-detects a mouseover (!)
--Hence, in consideration of step three, although the statement that the parent "still thinks the mouse is over it" seems like it would be correct, considering #4 I think its more accurate to state that the parent [i]expects[/] either the mouse to still be there because it was in the past, or that its was moved away ...'but that doesn't necessarily mean within the document' - an important distinction I think.

So therefore, what the intention is with the aforementioned code line

"t.onmouseover=function() {isclicked = 1}" in the init:function of dhtmlwindow.js is to...
1) during the event bubbling phase of the parent mouseover [#2 above], before event propagation has 'reached back to the top' (or the mouse)
2) the child element (the dhtmlwindow) appears under the mouse, and that code line causes the child to 'capture' a mouseover event before the event bubbling of the parent's mouseover is complete, and thus before any mouseout event can be auto-triggered.
3) At this moment a variable is set from the child, 'isclicked', that is [elsewhere] programmed to be caught in the parent's mouseout event function (!), so
4) when the bubble propagation completes and the parent element then captures, or 'sees', no mouse there, parent element's mouseout triggers,
5) however, because the isclicked variable has been reset by the child to appear as when the parent document is 'clicked' (!),
5) thus the parent element's mouseout does not fire... its controlling variable in its function tells it to cancel itself, and the dhtml window stays ;^)

Probably could also approach coding for intercepting and 'killing' the mouseover event propagation during the bubbling phase so no mouseout is ever tirggered at the parent doc. It appears this is what your code is intending to do, but I have to spend soem time and play with it.

So my earlier question about using the "line in the init:function" technique has to do with my not knowing any potential conflict or efficiency issues which, being a non-expert, I would not yet know (how) to look for.
------------------------------------------------------
What's interesting about your new proposal is that it is all done outside of the dhtml init or open functions. And who knows, maybe that's more proper?

I will check your code out and post back, but it probably won't be till thursday, as my schedule allows.

I find this very interesting, and a good learning experience. Thank you for your time looking at this and feeding back, and just generally helping!

-----------------------------------------
BTW, I just found an interesting link that, while it doesn't necessarily explain everything about 'capture' and 'bubble' (which I am sure you are already familiar with) it happens to discuss solving a problem just like this one.
Bursting the Event Bubble (http://www.thefutureoftheweb.com/blog/bursting-the-event-bubble)

I have to look at it some more, but it appears he's doing essentially the same thing, but from yet another angle. He's telling the parent to detect if the mouseout event isn't being triggered directly by the parent, but he's doing it all on the parent end of things. With your code (in dhtmlwindow.js), it seems that since there's already good child detection in place, it makes sense to take advantage of that.

I wonder if your new method, or even his, reflects more proper and/or efficient coding method, or if it matters? If I knew there were no technical caveats and I were more geeky ...I would test the cpu cycles required for each 8^P

All righty then.
Be well.
Cheers,
TwoHawks