PDA

View Full Version : Overlapping Content script



Arsen
08-12-2019, 04:23 AM
1) Script Title: Drop down/ Overlapping Content script

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex5/overlapcontent.htm (https://web.archive.org/web/20061008122920/http://www.dynamicdrive.com/dynamicindex5/overlapcontent.htm)
This is an early version of the script.

3) Describe problem: How to supplement the script so that the menu is hidden by a click outside it?

Usage example jsfiddle (https://jsfiddle.net/Ar7en/z4upnw85/)
Thanks.

molendijk
08-13-2019, 08:54 PM
In the head:
<script type="text/javascript">

/***********************************************
* Drop Down/ Overlapping Content- Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

function getposOffset(overlay, offsettype){
var totaloffset=(offsettype=="left")? overlay.offsetLeft : overlay.offsetTop;
var parentEl=overlay.offsetParent;
while (parentEl!=null){
totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
parentEl=parentEl.offsetParent;
}
return totaloffset;
}

function overlay(curobj, subobjstr, opt_position){
if (document.getElementById){
var subobj=document.getElementById(subobjstr)

subobj.style.visibility=(subobj.style.visibility!="visible")? "visible" : "hidden"
var xpos=getposOffset(curobj, "left")+((typeof opt_position!="undefined" && opt_position.indexOf("right")!=-1)? -(subobj.offsetWidth-curobj.offsetWidth) : 0)
var ypos=getposOffset(curobj, "top")+((typeof opt_position!="undefined" && opt_position.indexOf("bottom")!=-1)? curobj.offsetHeight : 0)
subobj.style.left=xpos+"px"
subobj.style.top=ypos+"px"
return false
}
else
return true
}

function overlayclose(subobj){
document.getElementById(subobj).style.visibility="hidden"

}

</script>

<script>
window.onmousedown=function(e){
if(e.target.className!=='must_be_closed_from_outside')
{
overlayclose('subcontent');
overlayclose('subcontent2');
}
}
</script>
In the body:
<b><a href="search.htm" onclick="return overlay(this, 'subcontent')">Search DD</a></b><br/>

<!--Do not remove outer most DIV tag with id="subcontent"-->

<div class="must_be_closed_from_outside" id="subcontent" style="position:absolute; border: 9px solid orange; background-color: white; width: 300px; padding: 8px; visibility: hidden" >

<p><b>Search Dynamic Drive:</b></p>
<form method="get" action="https://web.archive.org/web/20061008122920/http://search.freefind.com/find.html" id="topform">
<input type="HIDDEN" name="id" size="-1" value="6299074"/>
<input type="HIDDEN" name="pageid" size="-1" value="r"/>
<input type="HIDDEN" name="mode" size="-1" value="ALL"/>
<input type="HIDDEN" name="n" value="0">
<input name="query" maxlength="255" style="width: 150px; " id="topsearchbox" alt="Search"/ >
<input value="Search" class="topformbutton" type="submit"/ >
</form>

</div>


<p style="padding-left: 800px"><b><a href="search.htm" onclick="return overlay(this, 'subcontent2', 'rightbottom')">Show Content</a></b><br/></p>

<!--Do not remove outer most DIV tag with id="subcontent2"-->
<div class="must_be_closed_from_outside" id="subcontent2" style="position:absolute; visibility: hidden; border: 9px solid black; background-color: lightyellow; width: 400px; height: 400px; padding: 8px">

Some content. Some content.

</div>

Arsen
08-14-2019, 08:41 AM
Thanks for the help!
But there are 2 questions.

1. When you try to place the cursor in the Search DD input field, the layer immediately closes.

2. If there are more hidden layers, then each time you need to edit the script?
Adding overlayclose('subcontent3'); overlayclose('subcontent4');..5,6,...
How to avoid this?

molendijk
08-14-2019, 02:41 PM
You can probably solve the two problems you mentioned by replacing the code I gave you with the following:
<head>

<script type="text/javascript">

/***********************************************
* Drop Down/ Overlapping Content- Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

function getposOffset(overlay, offsettype){
var totaloffset=(offsettype=="left")? overlay.offsetLeft : overlay.offsetTop;
var parentEl=overlay.offsetParent;
while (parentEl!=null){
totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
parentEl=parentEl.offsetParent;
}
return totaloffset;
}

function overlay(curobj, subobjstr, opt_position){
if (document.getElementById){
var subobj=document.getElementById(subobjstr)

subobj.style.visibility=(subobj.style.visibility!="visible")? "visible" : "hidden"
var xpos=getposOffset(curobj, "left")+((typeof opt_position!="undefined" && opt_position.indexOf("right")!=-1)? -(subobj.offsetWidth-curobj.offsetWidth) : 0)
var ypos=getposOffset(curobj, "top")+((typeof opt_position!="undefined" && opt_position.indexOf("bottom")!=-1)? curobj.offsetHeight : 0)
subobj.style.left=xpos+"px"
subobj.style.top=ypos+"px"
return false
}
else
return true
}

function overlayclose(subobj){
document.getElementById(subobj).style.visibility="hidden"

}


</script>

<script>
window.onmousedown=function(e){
document.documentElement.className="the_document";
document.body.className="the_document";
if(e.target.className=='the_document')
{
for (i = 0; i < document.getElementsByClassName("must_be_closed_from_outside").length; i++)
{
document.getElementsByClassName("must_be_closed_from_outside")[i].style.visibility='hidden'
}
}
}
</script>

</head>

<body >

<b><a href="search.htm" onclick="return overlay(this, 'subcontent')">Search DD</a></b><br/>

<!--Do not remove outer most DIV tag with id="subcontent"-->

<div class="must_be_closed_from_outside" id="subcontent" style="position:absolute; border: 9px solid orange; background-color: white; width: 300px; padding: 8px; visibility: hidden" >

<p><b>Search Dynamic Drive:</b></p>
<form method="get" action="https://web.archive.org/web/20061008122920/http://search.freefind.com/find.html" id="topform">
<input type="HIDDEN" name="id" size="-1" value="6299074"/>
<input type="HIDDEN" name="pageid" size="-1" value="r"/>
<input type="HIDDEN" name="mode" size="-1" value="ALL"/>
<input type="HIDDEN" name="n" value="0">
<input name="query" maxlength="255" style="width: 150px; " id="topsearchbox" alt="Search"/ >
<input value="Search" class="topformbutton" type="submit"/ >
</form>

</div>


<p style="padding-left: 800px; "><b><a href="search.htm" onclick="return overlay(this, 'subcontent2', 'rightbottom')">Show Content</a></b><br/></p>

<!--Do not remove outer most DIV tag with id="subcontent2"-->
<div class="must_be_closed_from_outside" id="subcontent2" style="position:absolute; visibility: hidden; border: 9px solid black; background-color: lightyellow; width: 400px; height: 400px; padding: 8px">

Some content. Some content.

</div>

</body>

Arsen
08-14-2019, 04:36 PM
Thank you very much, kind man!
Everything works perfectly!

molendijk
08-19-2019, 07:05 PM
Today I was rethinking the script I posted a couple of days ago and it suddenly occurred to me that I had not examined cases where the target of the click event used for closing several opened elements at the same time is a tagged element (<a> ... </a>, <div> ... </div> etc.), not just raw text. Here's the relevant part of the script I proposed:
window.onmousedown=function(e){
document.documentElement.className="the_document";
document.body.className="the_document";
if(e.target.className=='the_document')
{
for (i = 0; i < document.getElementsByClassName("must_be_closed_from_outside").length; i++)
{
document.getElementsByClassName("must_be_closed_from_outside")[i].style.visibility='hidden'
}
}
}As it turns out, this code does not work for tagged elements. So I completely revised the script, see this (http://mesdomaines.nu/eendracht/hide_all_in_one_click/hide_in_one_click.html). You will notice that opened elements not only hide after a click on raw text (the 'Lorem Ipsum' part) but also after a click on the tagged page's title (Closing all opened elements with one click). Moreover, the new script deals with a strange bug(?) on the iPhone / iPad.

Arsen
08-20-2019, 09:13 AM
Arie, thank you very much for noticing this!
The code has been updated a lot. 2 points.

1. I would like to keep the drop down content binding to the link. That also the parameters worked: 'right', 'bottom', 'rightbottom', 'leftbottom', 'lefttop', 'righttop'.
2. The new code does not work in IE 11.0

molendijk
08-20-2019, 09:28 PM
Hello Arsen,
I'm very busy at the moment. I'll come back to you as soon as I can.

molendijk
08-24-2019, 06:24 PM
Hello Arsen,
I'm back and found some time to re-examine the script.
The original DD-script dates from 2006, when people did not visit websites on mobile devices yet. So people surfed the web on wide screens, which might explain the fact that the DD-script has an option for displaying the dropdown to the left of the link. If we put the link far enough from the left, then on wide screens there's room enough indeed for the dropdown to be entirely visible.

But more then 50% (or perhaps a bit less) of the people all over the world visit websites on mobile devices, which offer less (horizontal) room than their big immobile brothers. Moreover, displaying a dropdown at a position of our choice can be done almost entirely without javascript. Css can do this job faster and securer. So I abandoned the idea of simulating the DD-options using javascript.

I made a script that positions the dropdowns at the exact left position of the respective links and a couple of pixels below them. I used modern css media queries for cases where this would cause problems on small devices. You can adapt them to your needs.

As for IE 11.0, nothing can be done to make it work on that browser.

Here's the script:

<!doctype html>
<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Hide All Opened Elements With One Click</title>

<style>
/* all the hidden elements that we want to open and then close with one click must have position: absolute; visibility: hidden, opacity: 0 and max-width: 100% */
.closeable_from_outside {position: absolute; visibility: hidden; opacity: 0; max-width: 100%; z-index: 9999; line-height: 25px; margin-top: 5px; transition: 1s}

body {font-family: arial; font-size: 20px; padding: 10%; padding-top: 15px; padding-bottom: 15px; line-height: 30px; }
</style>

<style>
/* adapt left and width of the hidden elements to the width of the window; just an example */
@media screen and (max-width: 755px) {.closeable_from_outside {max-width: 40%!important}}
@media screen and (max-width: 560px) {.closeable_from_outside {left: 50%!important; transform: translateX(-50%); max-width: 100%!important}}
@media screen and (max-width: 440px) {.closeable_from_outside {left: 50%!important; transform: translateX(-50%); max-width: 70%!important}}
</style>

<script>
function open_element(which)
{/* open a hidden element (a div, for instance) */
document.getElementById(which).style.visibility='visible';
document.getElementById(which).style.opacity=1;
default_position()
}

function default_position()
{/* default left for the hidden elements; the default top is given in the css (margin: top) */
for (i = 0; i < document.getElementsByClassName("the_anchor").length; i++)
{
for (j = i; j < document.getElementsByClassName("closeable_from_outside").length; j++)
{


document.getElementsByClassName('closeable_from_outside')[j].style.left=document.getElementsByClassName("the_anchor")[i].offsetLeft +'px';
}
}
}
window.addEventListener('resize', function (){default_position()}, false);

function close_element(which)
{/* close an opened element (a div, for instance) */
document.getElementById(which).style.visibility='hidden';
document.getElementById(which).style.opacity=0;
}

function detect_scrollbar_width()
{/* we must know the width of the window's scrollbar because we don't want 'window.onclick=function(e)' (below) to fire when the scroll bar is clicked on; see https://davidwalsh.name/detect-scrollbar-width */
var scrollDiv = document.createElement("div");
scrollDiv.style.overflow="scroll";
document.body.appendChild(scrollDiv);
scrollbar_width = scrollDiv.offsetWidth - scrollDiv.clientWidth;
document.body.removeChild(scrollDiv);
}
window.addEventListener('load', function (){detect_scrollbar_width()}, false);

window.onclick=function(e){
/* close all opened elements when some part of the window outside them is clicked on */

/* when we click anywhere except on the vertical scrollbar area */
if(e.offsetX<window.innerWidth - scrollbar_width)
{
for (i = 0; i < document.getElementsByClassName("closeable_from_outside").length; i++)
{
/* if we click anywhere outside elements having class = "closeable_from_outside" and if the clicked part of the document doesn't have class = "the_anchor" (the links to the hidden elements that we want to open and close have this class name) */
if(!e.target.closest(".closeable_from_outside") && e.target.className!="the_anchor")
{

/* close the elements */
document.getElementsByClassName("closeable_from_outside")[i].style.visibility='hidden';
document.getElementsByClassName("closeable_from_outside")[i].style.opacity=0;
}
}
}
}
</script>

</head>

<body >

<h2 style="text-align: center; margin-bottom: 40px">Closing all opened elements with one click</h2>

Hit
<!-- FIRST LINK AND HIDDEN ELEMENT -->

<!-- The link must have class="the_anchor" -->
<b><a href="javascript: void(0)" onclick="open_element('subcontent'); return false" class="the_anchor" >hidden element 1</a></b>

<!-- The hidden element must have class="closeable_from_outside". The id is needed for opening the element with open_element('...') and for hiding it when the close button is clicked on (onclick="close_element('...')") -->
<div class="closeable_from_outside" id="subcontent" style="border: 9px solid orange; background-color: white; width: 250px; padding: 8px; " >
<div style="float: right; font-family: arial; font-size: 25px; padding: 5px; line-height: 1px; cursor: pointer" onclick="close_element('subcontent')">X</div><br>
<b >Search Dynamic Drive:</b>
<form method="get" action="https://web.archive.org/web/20061008122920/http://search.freefind.com/find.html" id="topform" >
<input type="HIDDEN" name="id" size="-1" value="6299074"/>
<input type="HIDDEN" name="pageid" size="-1" value="r"/>
<input type="HIDDEN" name="mode" size="-1" value="ALL"/>
<input type="HIDDEN" name="n" value="0">
<input name="query" maxlength="255" style="width: 150px; " id="topsearchbox" alt="Search"/ >
<input value="Search" class="topformbutton" type="submit"/ >
</form>
</div>

and
<!-- SECOND LINK AND HIDDEN DIV -->
<b><a href="javascript: void(0)" onclick="open_element('subcontent2'); return false" class="the_anchor">hidden element 2</a></b>
<div class="closeable_from_outside" id="subcontent2" style="border: 9px solid black; background-color: lightyellow; width: 400px; height: 400px; overflow: auto; padding: 8px; ">
<div style="float: right; font-family: arial; font-size: 25px; padding: 5px; line-height: 1px; cursor: pointer" onclick="close_element('subcontent2')">X</div><br>
Some content. Some content.<br>
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>


to open two hidden divs, then click somewere outside the opened elements (divs) to make them invisible again. Or use the close buttons inside the elements to hide them separately.<br>View source for code and explanations.

<br><br>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

<br><br>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

<br><br>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

<br><br>
<i>Arie Molendijk, mesdomaines.nu</i>

<script>
/* Safari on the iPhone / iPad does not support event delegation for click events, unless the click takes place on a clickable element. So we make the body clickable.
This must be put at the end of the body section */
var doc_inner=document.body.innerHTML
function make_body_clickable()
{
document.body.innerHTML="<div style='width: 100%; height: 100%' onclick=function(){}>"+doc_inner+"</div>";
}
window.addEventListener('load', function (){setTimeout('make_body_clickable()',0)}, false);
</script>

</body>

</html> Demo here (http://mesdomaines.nu/eendracht/hide_all_in_one_click/hide_in_one_click2.html) (make the screen smaller and wider and see what happens).

Arsen
08-25-2019, 05:26 AM
Thank you very much, Arie.
This option (http://mesdomaines.nu/eendracht/hide_all_in_one_click/hide_in_one_click2.html) is good, but not as we would like.

The original DD script interests me because:
1. Works by click.
2. Binding to a link anywhere on the page.
3. Ability to customize any position of the dropdown content.
4. Cross-browser compatibility.
5. Light, pure JS.

Use - for laptop / desktop.
Sample of use (http://s25.znimg.ru/1566709980/de42vz7ai9.png)

Without JS, it is probably difficult to make dropdown content according to these points. The original script is almost ready. I just wanted to supplement it a little:
1. Make it possible to close by clicking outside the drop-down content area.
2. Add options for the position of the dropdown content: 'righttop' и 'lefttop'.

If the task with closing by clicking outside the area is partially solved, then how to supplement the provisions in the original script: 'righttop' и 'lefttop'?
We probably need to complement this piece of code:

var xpos=getposOffset(curobj, "left")+((typeof opt_position!="undefined" && opt_position.indexOf("right")!=-1)? -(subobj.offsetWidth-curobj.offsetWidth) : 0)
var ypos=getposOffset(curobj, "top")+((typeof opt_position!="undefined" && opt_position.indexOf("bottom")!=-1)? curobj.offsetHeight : 0)
subobj.style.left=xpos+"px"
subobj.style.top=ypos+"px"

molendijk
08-25-2019, 10:27 PM
Hi Arsen,
There seems to have been a misunderstaniding that must be clarified.
1. My script works by click.
2. My dropdowns bind to any link on the page.
3. The position of my dropdowns can be customized (I used css for that, but there's a javascript option, see below).
4. My js isn't that heavy.
5. It is true that my script doesn't work with Internet Explorer (it works with Edge), but that's because of a requirement that was not met by the old DD-script ('hide all opened dropdowns in one click').
6. My own version of the DD-code you mention has been in my script(s) all the time.

Anyhow, this thing is beginning to interest me. I made a new script that produces what you showed in your PNG, see this (http://mesdomaines.nu/arsen.html).
Usage:
onclick="open_element('dropdown ID', 'right_of_link_bottom')"
onclick="open_element('dropdown ID', 'left_of_link_bottom')"
onclick="open_element('dropdown ID', 'right_of_link_top')"
onclick="open_element('dropdown ID', 'left_of_link_top')"

The only (important!) thing that must be achieved yet is to make it so that the dropdowns will not be partially cut off when small mobile devices are used. I can easily do it with CSS3 media queries, but you probably want to do it with javascript.

Arsen
08-26-2019, 01:17 PM
Hi, Arie.
Thanks for the help! Your new script also implements these 5 points, but not as much as we would like.

I clarify your points:
1. Not like the original. In your script, a second click on the link does not close the dropdown content. For IE, there remains one option for closing - a cross.
2. Yes.
3. Not like the original. It is necessary so (http://s24.znimg.ru/1566818580/ghvg114v7n.png). In your script, the right positioning above and below is not accurate (screenshot (http://s24.znimg.ru/1566821220/4tdl7gjoaj.png)).
Update: I see that you have already fixed this moment.

Another disadvantage is that the drop-down content in the body of the page should be located strictly next to the links.
If, for example, drop-down content before </ body>, then the positioning is violated.

4. Yes.
5. If in IE it is not possible to make a general close with one click, then a simple close one at a time is better.
6. Yes.

Media Requests ccs3 for mobile devices let them be, they do not interfere.
p.s. And it would be great if you could implement new additional functions in the original DD script.

molendijk
08-26-2019, 02:03 PM
Hi Arsen,
I already corrected the error you mention in (3). You must have seen the first version of my page. Please go to http://mesdomaines.nu/arsen.html again. I'll take a look at your other remarks soon.

molendijk
08-27-2019, 10:33 PM
Hello again Arsen,

I managed to let javascript make sure that the dropdowns are always entirely visible, whatever the width of the screen, see http://mesdomaines.nu/arsen2.html.

As for your requirement regarding the second click on the link, it can't be done if we want the script to allow us to close all opened elements with one click. I'll explain. A click on any part P of the screen outside the opened dropdowns must close them all, except when the target of the click is a link. If we would not make this exception for the links, then a click on them would never open a hidden element since the links are part of P. The reason why toggling between visible and hidden is possible with the old DD-script is that this script doesn't require what we want.

Arsen
08-28-2019, 05:13 AM
Hello again Arie,


..dropdowns are always entirely visible, whatever the width of the screen.. Yes, this is a good addition. Thank you.


..second click on the link, it can't be done if we want the script to allow us to close all opened elements with one click. I'll explain.. Understand. Another reason to remove this add-on. This is convenient, but not necessary. In practice, you rarely need to open in turn a lot of hidden elements, and then close them with one click. Let a click outside an area close only one open dd-content. And for IE there will be a plus. And let it be possible to close open dd-content with a second click on the link.

It is also necessary that the positioning of hidden elements does not depend on the position in the body of the page. Like in the original DD-script.

I also noticed that when changing the width of the browser window, the page reloads. Is it possible to avoid?

molendijk
08-29-2019, 04:58 PM
I also noticed that when changing the width of the browser window, the page reloads. Is it possible to avoid?
Sure, just remove or comment these lines:
var the_width = window.innerWidth;
window.addEventListener('resize', function (){if(window.innerWidth != the_width){location=location}}, false);

Arsen
09-15-2019, 01:37 PM
Hello Arie,
There is a problem. This page (http://mesdomaines.nu/arsen2.html).
Link 2 was positioned - float: right. 400px width of DD-content - deleted. DD-content - 4 links.

<a href="">Here is some link text 1</a><br>
<a href="">Some link text 2</a><br>
<a href="">Here is some link text 3</a><br>
<a href="">Some link text 4</a>
Links with long text wrap over 2 lines.

How to make width by content? (http://s26.znimg.ru/1568552640/qzqotu6wdo.png) (JavaScript methods). Line breaks only where there are tags < br>.

molendijk
09-16-2019, 10:16 AM
Hi Arsen,
I'm not sure I understand well what your are asking.
If you don't want the links to wrap to two lines, just add

<style>
.the_anchor {white-space: nowrap}
</style>
to the head of your page.

Arsen
09-16-2019, 10:06 PM
Thanks, Arie.
It helps. I wanted the same with JavaScript. More or less like this (given the scroll bar):

DDcontent.style.minWidth = DDcontent.offsetWidth + (DDcontent.offsetWidth - DDcontent.clientWidth) + "px";
Add to code. Is it possible?