I'm having issues with an absolutely positioned custom drop down, in IE7 the div is sitting behind a normal textbox which is not position in any special way.
I've already read this topic: IE7 puts absolutely positioned div underneath, ignores z-index but the solutions didn't help me.
The difference between my code and the person who asked the above question is that my div is being created through javascript using document.write and adding it through appendChild
addEvent(document.getElementById("storeDown"), "click", showRegions);
var showRegions = function(e) {
var dd = getTarget(e);
if(document.getElementById("regionOptions")) {
dd.parentNode.removeChild(document.getElementById("regionOptions"));
regionsShowing = false;
} else {
var ddNode = document.createElement("div");
ddNode.id = "regionOptions";
ddNode.style.backgroundColor = offColor;
var optNode;
for(var region in storeList) {
optNode = document.createElement("div");
optNode.innerHTML = region;
ddNode.appendChild(optNode);
}
dd.parentNode.appendChild(ddNode);
regionsShowing = true;
}
cancelEvent(e);
}
My parent div has a z-index of 500 and is positioned relative and regionOptions is positioned absolute and I tried to also add a z-index to it but it didn't make a difference.
Okay finally figured it out, I changed where it appends so it's appended in a div at the bottom of the page after all the textboxes (in my case, a buttons div), so instead of dd.parentNode.appendChild(ddNode), it's now document.getElementbyId("buttons").appendChild(ddNode), but also had to change the CSS so it's absolute positioned in relative to the page wrapper rather than the specific div, and it seems to have fixed it.
Related
I'm working on a hobby project similar to markup.io where you can load in any website and annotate it. I can't figure out how to add an annotation that behaves like it does in markup.io:
Doesn't interrupt the styling or layout of the website you are annotating
The annotation keeps the correct position when scrolling and resizing the window
From what I can see they place an absolute positioned div inside the element that you clicked on. From my understanding by reading the docs that div would position itself based on the closest positioned ancestor. How would you calculate the correct top and left values to position the annotation to where the user clicked? Is there a better way to do this?
I'm using React if that matters.
Things that I have tried:
Append the following bit of html to the element that was clicked:
<div style="width:0px; height:0px; position:relative;">
<div style="width:50px;height:50px;position:absolute; ">this is the annotation </div>
</div>
Problem: This would mess with the page layout because of the relative positioned div that is not ignored by the document flow.
Create fixed overlay over the entire page. Get the css selector of the clicked element. Draw annotation on the fixed overlay at the x,y position of the element.
Problem: Whenever the user would scroll or resize the window the annotation would need to be redrawn at the new position of the element. I used getBoundintClientRect to get the new position and this would cause a reflow and caused the whole website to have severe perfomance issues when dealing with 100+ annotations.
Hopefully someone can point me in the right direction!
The general idea is as follows:
Find the parent of the element that you clicked on
Check if they are positioned (anything other than static)
If it is static search for the closest element that is positioned.
Set the new badge/annotation top and left position to that of the mouse minus the top and left of the element that you're going to append it to (in this case called parent).
Also account for the width and height by subtracting half of each to perfectly center your annotation.
// In my case I put the webpage in an Iframe. If this is your own page
// you can just use document.
iframe.contentWindow.document.addEventListener(
'click',
(e: MouseEvent) => {
// step 1: find the parent.
let parent = e.target.parentElement;
let computedStyle = window.getComputedStyle(parent);
// step 2 & 3: Look up the first positioned element and make this the
// the element that you're going to append your badge/annotation to.
while (
computedStyle.position === 'static' &&
parent.parentElement !== null
) {
parent = parent.parentElement;
computedStyle = window.getComputedStyle(parent);
}
// style the annotation the way you want to
const badge = document.createElement('div');
const { top, left } = parent.getBoundingClientRect();
badge.style.position = 'absolute';
// step 4 and 5 get the mouse position through e.clientX and Y and
// subtract the appropriate value like below to place it exactly at the mouse position
badge.style.top = `${e.clientY - top - 5}px`;
badge.style.left = `${e.clientX - left - 5}px`;
badge.style.backgroundColor = 'red';
badge.style.width = '10px';
badge.style.height = '10px';
badge.style.borderRadius = '50%';
badge.style.zIndex = '9999';
parent.appendChild(badge);
}
);
Some background: I have a div in which elements of different height will be added to and I'm in need of achieving the following:
The div has a max-height property, when the different elements that are added to the Div overlap such height, I can't have the div "overflowing (putting a scrollbar on it)". Instead, I need to detect when this happens, so I can create ANOTHER div in which I could put the rest of the elements. Attached is an image that I hope illustrates what I'm trying to do.
Use jQuery:
var maxHeight = $(".someElement").css("max-height");
var height = 0;
$(".elements").each(function(){
height += $(this).height();
if(height >= maxHeight){
//create new div here and put the rest of the elements there
height = 0; //so you can continue with the loop and creating more divs.
}
});
I have a pseudo function below that I think could get you started on the right track. You will have to fill in the appropriate information for it.
$(elements).each(function() {
var currentDiv = $(currentDiv);
if($(currentDiv ).height() > MAX_HEIGHT)
{
$(currentDiv).insertAfter(newDiv);
currentDiv = $(newDiv);
}
$(currentDiv).append(element);
});
You'll have to keep track of the current div you are adding info to. Just add info like normal but when it overflows you should insertAfter it a new div and change the current div variable to be that one and then continue appending again.
To test if a div is currently overflowing, compare it's scrollHeight to its height.
With jQuery
if ($(obj)[0].scrollHeight > $(obj).height()) {
// do stuff
}
In this case though, you'll probably want to test against the css max-height before adding content. To do this (again in jQuery) load the content you plan to add into a variable so you can check its height before adding it to the document.
var content = // your content here
if ($(container).height() + content.height() > parseInt($(container).css("max-height"), 10)) {
// this means it would overflow, so do stuff
} else {
// no overflow here
$(container).append(content);
}
Here's a quick fiddle. http://jsfiddle.net/k0g47xdr/2/
edit:
the parseInt call around .css("max-height") is to convert from the text format it comes in to a regular number. As written it assumes the value is in px, not em or percent.
in function below i'm trying to add div block, but i can't set left position. alert function show message '600px'. on my screen this block has another position.
function show(){
if(document.getElementById('div1') == null){
var div1 = document.createElement('div');
div1.style.left = '600px';
document.body.appendChild(div1);
alert(div1.style.left);
}
}
my first question here. so i don't know how to add code style
You're not going to see anything visual on the page with your example for a couple reasons. First, your div does not contain anything, so it has no height or width. And second, you cannot position an element in the manner you are trying because it does not have display attribute absolute or relative. Try something like this:
function show(){
if(document.getElementById('div1') == null){
var div1 = document.createElement('div');
div1.innerHTML = 'hi there';
div1.style.left = '600px';
div1.style.position = 'absolute';
document.body.appendChild(div1);
}
}
The left property only applies to elements which are positioned. For an element to be positioned, it must have a position property with a value other than static (which is the default).
Set it to relative, fixed or absolute as per your needs.
Your div will have 0 height/width as there is no child content. Use textContent or innerHTML to add content to the div.
Also, the left property will not apply unless you set the positioning to relative or absolute. This also goes for the other sides (right, top and bottom).
I'm writing some javascript code to move all absolutely positioned elements down 60 pixels (below a 60 pixel heigh div I'm displaying at the top of other pages on my proxy). Here's the code I have right now (mostly borrowed from another question on stackoverflow):
function getStyle(el, prop)
{
var doc = el.ownerDocument;
var view = doc.defaultView;
if (view && view.getComputedStyle)
{
return view.getComputedStyle(el, '')[prop];
}
return el.currentStyle[prop];
}
function runAfterLoad()
{
var all = document.getElementsByTagName('*');
var i = all.length;
while (i--)
{
var topOffset = parseInt(all[i].offsetTop, 10);
if (getStyle(all[i], 'position') === 'absolute')
{
all[i].style.top = isNaN(topOffset) ? '60px' : (topOffset + 60) + 'px';
}
}
}
Unfortunately this moves all absolute positioned elements down 60 pixels. As it turns out, I found out that absolute positioning isn't actually absolute to the browser window, but absolute to a parent that meets some specific rules. Here's a quote from another answer on here:
This works because "position: absolute" means something like "use top, right, bottom, left" to position yourself in relation to the nearest ancestor who has "position: absolute" or "position: relative"."
So I'm looking for help on how to adjust my current code to only find the elements with absolute position that don't have a parent that is also absolute or relative positioned. Any help is highly appreciated.
Another option would be to use that fact to your advantage. If you were to wrap your entire page in a div which you positioned absolutely (or relatively) with top: 60px, you would essentially move the entire page down 60px at once.
This would also move non-absolute elements. If this is not desired then this won't work.
I have a div element which I'm using as a pop-over search field which I want to have appear under the element which is being filtered. However, it seems that I cannot use the style.bottom and style.left of the element I want the field to be relative to as this element is static.
Example is here: http://www.is-epic.co.uk/example/example.html
Clicking the Header 2 link will have the input box appear, in the top-left corner of the table. I would like it to appear roughly where Data 1.2 is. How do I achieve this?
(Code in example.html is on one page, in live dev CSS and JS are in separate files)
Set the element you wish to position the other element with respect to to position: relative.
This will make it the containing block for any descendants that are position: absolute (unless an element between the two is also position: not static).
this works in FF and Google-Chrome
var head = document.getElementById("header_2");
var filter = document.getElementById("search_filter");
filter.style.display = "";
filter.style.left = head.offsetLeft + 'px';
filter.style.top = head.offsetTop + head.offsetHeight + 'px';
it should work with IE as well..
i used variables filter and head to cut down on typing :)
The problem is that for header_2 both style.left and style.bottom are 0, so that
document.getElementById("search_filter").style.left =
document.getElementById("header_2").style.left;
document.getElementById("search_filter").style.top =
document.getElementById("header_2").style.bottom;
is equivalent to
document.getElementById("search_filter").style.left = 0;
document.getElementById("search_filter").style.top = 0;
which is exactly what happens. You have to find out header_2's actual position, e.g. using jQuery.