dynamically added elements with absolute positioning do not flow with parent - javascript

I am playing around with JavaScript. I am having an issue with page resizing and the position of dynamically created elements. The Parent div is positioned relative and the appended child elements are absolute in relation to the parent they are added to. When I shrink the browser window the parent scales ok but the children's positions do not get updated. How would you handle a situation like this in the real world?
Thanks
PS: keep in mind I am trying to learn this and a lot I'm sure is wrong or unnecessary. I appreciate the correction as well.
<html>
<head>
<!-- <link rel="stylesheet" type="text/css" href="1.css"> -->
<script language="javascript"></script>
<style>
#div1{
postion:relative;
margin:auto auto;
height:400px;
width:400px;
background-color: black;
}
</style>
</head>
<body>
<!-- Goal; -->
<!-- I want a js class that will create itself and manage its own properties
So when I click on the div I fire up a new object button. -->
<div>
<label id = "lblID"></label>
<div id="div1"></div>
</div>
<script>
document.getElementById("div1").addEventListener("click", createchild, false);
function createchild(e)
{
obj1 = new child(this,e);
}
function child(el,e)
{
this.parent = el;
this.parentID = el.id;
// Create the object
this.child = document.createElement('div');
this.parent.appendChild(this.child);
// Set some attributes
var c = this.parent.childElementCount + 1;
this.child.id = "child"+c;
// Set some style
var l = e.clientX - 20;
var t = e.clientY - 20;
var stylestring = "position:absolute;top:"+t+"px;left:"+l+"px;height:40px;width:40px;background-color:red;";
this.child.style.cssText = stylestring;
// Add some eventhandling
this.child.addEventListener("click",getchildcoords,false);
}
function getchildcoords(e)
{
alert(this.id);
e.stopPropagation();
}
</script>
</body>
</html>

There is a missing 'i' in 'position' keyword of #div1 css
Append new divs to the container itself to link their positions
Use offsetX, offsetY for correct placement
<html>
<head>
<!-- <link rel="stylesheet" type="text/css" href="1.css"> -->
<script language="javascript"></script>
<style>
#div1{
position:relative;
margin:auto auto;
height:400px;
width:400px;
background-color: black;
}
</style>
</head>
<body>
<!-- Goal; -->
<!-- I want a js class that will create itself and manage its own properties
So when I click on the div I fire up a new object button. -->
<div>
<label id = "lblID"></label>
<div id="div1"></div>
</div>
<script>
document.getElementById("div1").addEventListener("click", createchild, false);
function createchild(e)
{
obj1 = new child(this,e);
}
function child(el,e)
{
this.parent = el;
this.parentID = el.id;
// Create the object
this.child = document.createElement('div');
// Set some attributes
var c = this.parent.childElementCount + 1;
this.child.id = "child"+c;
// Set some style
var l = e.offsetX - 20;
var t = e.offsetY - 20;
var stylestring = "position:absolute;top:"+t+"px;left:"+l+"px;height:40px;width:40px;background-color:red;";
this.child.style.cssText = stylestring;
el.appendChild(this.child);
// Add some eventhandling
this.child.addEventListener("click",getchildcoords,false);
}
function getchildcoords(e)
{
alert(this.id);
e.stopPropagation();
}
</script>
</body>
</html>

Related

How to get previous state after click event?

This is my code:
$("div").on("click", function() {
$("div a").css("pointer-events", "all");
});
$("div").on("mouseleave", function() {
$("div a").css("pointer-events", "none");
});
div {
padding: 10px;
background-color: yellow;
display: inline-block;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
Wikipedia
</div>
Generally, it works. But only once for every link. Instead of the mouseleave, I would need something like after this click. So after the click, the whole page should work like before, it shouldn't be just a one-way function.
I want to use it for something like this. If you drag there links, they get fired automatically when you stop dragging. Links should only be fired after a click. I want to fix that.
How is it possible to do that? Would be soooo thankful for help! <3
Since a click Event does not actually fire until you press then release, maybe you want to do something along the lines of:
//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q; // for use on other loads
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
let w = within || doc;
return w.querySelector(selector);
}
Q = (selector, within)=>{
let w = within || doc;
return w.querySelectorAll(selector);
}
// tiny library above - magic below can be put on separate page using a load event *(except // end load line)*
const box = I('box'), bS = box.style, goto = I('goto');
let posX, posY;
function touchFun(e){
const b = box.getBoundingClientRect();
e.preventDefault(); posX = e.clientX-b.left; posY = e.clientY-b.top;
}
function moveFun(e){
if(posX !== undefined){
bS.left = e.clientX-posX+'px'; bS.top = e.clientY-posY+'px';
}
}
function stopFun(){
posX = posY = undefined;
}
if(mobile){
box.ontouchstart = goto.ontouchstart = touchFun; ontouchmove = moveFun;
ontouchend = stopFun;
}
else{
box.onmousedown = goto.onmousedown = touchFun; onmousemove = moveFun;
onmouseup = stopFun;
}
}); // end load
//]]>
/* css/external.css */
*{ /* set font individually - may create white space on line breaks */
box-sizing:border-box; font:0; padding:0; margin:0; overflow:hidden;
}
html,body,.full{
width:100%; height:100%;
}
#main{
position:relative;
}
#box{
position:absolute; display:inline-block; background:#ff0; padding:15px; left:100px; top:50px;
}
a{
font-size:22px; white-space:nowrap;
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
<title>Title Here</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script src='js/external.js'></script>
</head>
<body>
<div class='full' id='main'>
<div id='box'><a id='goto' href='https://stackoverflow.com'>Stack Overflow</a></div>
</div>
</body>
</html>

DOM not updating after adding a class to a div?

I'm trying to write a program that collects all class names in a div, stores them in an array and pushes them all back to the DOM with a class called blue at the end, this is the HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>some title</title>
<style>
.blue{
width: 200px;
height: 200px;
background: blue;
}
</style>
</head>
<body>
<div class="someClass otherClass" id="box"></div>
<button id="btn">click</button>
</body>
</html>
The thing is, I know how to get all the class names inside the div and even how to push blue (on btn click) inside of that div together with the other values I have collected but why isn't the blue box showing up? What am I missing?
var domManipulation = function(){
var box = document.querySelector('#box');
var btn = document.querySelector('#btn');
var class_list = [];
if(box.classList.length > 0){
for(var i = 0; i < box.classList.length; i++){
class_list.push(box.classList[i]);
}
}
btn.addEventListener('click', function(){
class_list.push("blue");
box.classList.add(class_list);
console.log(class_list);
});
}();
Here is a JsBin and I can't use jQuery btw.
This is the problem:
box.classList.add(class_list);
You can't add a whole array of classes because they end up being comma-separated.
var domManipulation = function() {
var box = document.querySelector('#box');
var btn = document.querySelector('#btn');
var class_list = [];
if (box.classList.length > 0) {
for (var i = 0; i < box.classList.length; i++) {
class_list.push(box.classList[i]);
}
}
btn.addEventListener('click', function() {
class_list.push("blue");
class_list.forEach(function(e){
box.classList.add(e);
})
console.log(class_list);
});
}();
#box {height: 50px; background: #eee}
#box.blue {background: blue}
<div class="someClass otherClass" id="box"></div>
<button id="btn">click</button>

Communicating between iframes

I'm trying to do something with iframes and am struggling a little bit at the moment. Basically, I have a script that generates a grid of squares (image below) and I want to make it so that when I click on a square, I display something in a different iframe.
So for instance, say I had frame 1 (which contains the grid) and frame 2 (this is the "display" frame). If I click the top left square, then I want to display "index(0,0)" in the display frame. If I click the (1, 1) square, then I want to display "index(1,1)" and so on.
I already know how to do this within the same frame (ie I can display "index(0,0)" within frame 1 if I click on a square in frame 1), but I am just confused on how to do this in a separate frame. I've tried quite a few things but nothing seems to be working.
I will include all of my code below as well as a picture for your reference. Any help is greatly appreciated!
Javascript:
// I know this isnt good coding practice, but I was getting desperate
// trying things xD
var currentDisplay = "display";
function changeSquare() {
var image = document.getElementById(this.id);
// If image is currently green square, change to red, and vice versa
if (image.src.match("http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png")) {
image.src = "http://www.clker.com/cliparts/1/J/s/o/7/y/red-square-button-md.png";
} else {
image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png";
}
currentDisplay = this.id;
};
function printInfo() {
document.write(currentDisplay);
}
// Creates a grid of dimensions width by height
function makeGrid(height, width) {
// Loop over height and width to create black square objects with
// buttons in middle
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
// Outer div is black square
var div = document.createElement("div");
div.className = "square";
div.id = ("div").concat(i,",", j);
var innerDiv0 = document.createElement("div");
innerDiv0.className = "content";
div.id = ("innerDiv0").concat(i,",", j);
div.appendChild(innerDiv0);
// InnerDiv1 & 2 are table structures (necessary for alignment)
var innerDiv1 = document.createElement("div");
innerDiv1.className = "table";
div.id = ("innerDiv1").concat(i,",", j);
innerDiv0.appendChild(innerDiv1);
var innerDiv2 = document.createElement("div");
innerDiv2.className = "table-cell";
div.id = ("innerDiv2").concat(i,",", j);
innerDiv1.appendChild(innerDiv2);
// Add green square image
var image = document.createElement("img");
image.id = ("image").concat(i,",", j);
image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png";
image.className = "rs";
innerDiv2.appendChild(image);
document.body.appendChild(div);
// Add onclick feature
image.onclick = changeSquare;
}
}
};
GridTest.html
<head>
<link rel="stylesheet" type="text/css" href="GridTest.css">
</head>
<body>
<script src="GridTest.js">
</script>
<script>
makeGrid(20, 20);
</script>
</body>
displayPanel.html
<head>
<link rel="stylesheet" type="text/css" href="GridTest.css">
</head>
<body>
<script src="GridTest.js">
</script>
<script>
printInfo();
</script>
</body>
nestTest.html (here is where I create the iframes)
<head>
<link rel="stylesheet" type="text/css" href="GridTest.css">
<script src = "GridTest.js"> </script>
</head>
<iframe id="frame1" scrolling="no" src="GridTest.html">
</iframe>
<iframe id="frame2" scrolling="no" src="displayPanel.html"></iframe>
CSS (probably unnecessary but I'll include it anyways)
.square {
float:left;
position: relative;
width: 5%;
padding-bottom: 2.8125%;
background-color:#1E1E1E;
overflow:hidden;
outline: 1px solid #FFFFFF;
}
.whiteSquare {
float:left;
position: relative;
width: 5%;
padding-bottom: 2.8125%;
background-color:#FFFFFF;
overflow:hidden;
outline: 1px solid #FFFFFF;
}
/*
Aspect ratio | padding-bottom | for 30% width
------------------------------------------------
1:1 | = width | 30%
1:2 | width x 2 | 60%
2:1 | width x 0.5 | 15%
4:3 | width x 0.75 | 22.5%
16:9 | width x 0.5625 | 16.875%
*/
.content {
position:absolute;
height:40%;
width:47%;
padding: 5% 26.5%;
text-align:center;
}
.content .rs{
width:auto;
height:auto;
max-height:90%;
max-width:100%;
}
.table{
display:table;
height:100%;
width:100%;
}
.table-cell{
display:table-cell;
vertical-align:middle;
height:100%;
width:100%;
}
body {
font-size:20px;
font-family: 'Lato',verdana, sans-serif;
color: #000000;
background:#ECECEC;
}
.numbers{
font-weight:900;
font-size:100px;
}
Picture of current result.
In your changeSquare method, try something like this:
var frame2 = $('#frame2', top.document) //Give you top level frame jQuery Object.
for more backwards compatibility, you can use something like:
window.parent.$('#frame2')
Or something like this for no jQuery:
window.parent.getElementById('#frame2')[attributeName]
Once you have the root iFrame object, you can proceed with regular jQuery/DOM manipulation.
EDIT: here is a fully working and tested solution (Safari/Mac OS). Only the changes are highlighted below:
displayPanel.html:
<head>
<link rel="stylesheet" type="text/css" href="GridTest.css">
</head>
<body>
<script src="GridTest.js">
</script>
<script>
printInfo();
</script>
<div id="label1"></div> <!--Added a div for displaying text -->
</body>
GridTest.js:
function changeSquare() {
var image = document.getElementById(this.id);
//First get a reference to the second frame document
var secondFrameDocument = window.top.document.getElementById('frame2').contentWindow.document;
//Now set the value of the Div
secondFrameDocument.getElementById('label1').textContent=this.id;
// If image is currently green square, change to red, and vice versa
if (image.src.match("http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png")) {
image.src = "http://www.clker.com/cliparts/1/J/s/o/7/y/red-square-button-md.png";
} else {
image.src = "http://www.clker.com/cliparts/b/d/4/F/W/N/green-square-button-md.png";
}
currentDisplay = this.id;
};
Depending upon your exact scenario, you may run into security issues, particularly with Chrome. A better solution would be to perhaps use two Divs instead of iFrames.
Here's a screenshot:

Change background color if width is bigger

I want to change the background color if width is bigger than 100.
This is my code but it doesn't work.
Thanks for any help!
<html>
<head>
<style type="text/css">
div#mydiv {
width: 200px;
height: 100px;
background-color: red;
}
</style>
<script language="JavaScript">
function () {
var mydiv = document.getElementById("mydiv");
var curr_width = parseInt(mydiv.style.width);
if (curr_width > 100) {
mydiv.style.BackgroundColor = "blue";
}
}
</script>
</head>
<body>
<div id="mydiv" style=""></div>
</body>
</html>
Change
parseInt(mydiv.style.width);
mydiv.style.BackgroundColor = "blue";
To
mydiv.offsetWidth
mydiv.style.backgroundColor = "blue";
use
var curr_width = mydiv.offsetWidth;
instead
var curr_width = parseInt(mydiv.style.width);
Change:
var curr_width = parseInt(mydiv.style.width);
mydiv.style.BackgroundColor = "blue";
to:
var curr_width = mydiv.offsetWidth;
mydiv.style.backgroundColor = "blue";
I have set up a fiddle here.
Also notice I took it out of the function because it looked like it wasn't being called anywhere. You should also move the script out of the head to the bottom of the body tag or use window.onload.
UPDATE
Another fiddle with everything together
I assume this is a duplicate question.
Anyway, your intialization of curr_width need not include parseInt.
parseInt is for converting a value to integer type and here you doesnt require it.
Your code can be re-written as
<html>
<head>
<style type="text/css">
div#mydiv {
width: 200px;
height: 100px;
background-color: red;
}
</style>
<script language="JavaScript">
function () {
var mydiv = document.getElementById("mydiv");
var curr_width = mydiv.offsetWidth;
if (curr_width > 100) {
mydiv.style.BackgroundColor = "blue";
}
}
</script>
</head>
<body>
<div id="mydiv" style=""></div>
</body>
</html>
Assuming your function to be called onload. Here's the code:
<html>
<head>
<style type="text/css">
#mydiv {
width: 200px;
height: 100px;
background-color: red;
}
</style>
<script language="JavaScript">
function load(){
var mydiv = parseInt(document.getElementById("mydiv").offsetWidth);
if (mydiv > 100) {
document.getElementById("mydiv").style.backgroundColor = "blue";
}
}
</script>
</head>
<body onload="load();">
<div id="mydiv" style=""></div>
</body>
</html>
Changes:
Use offsetWidth to get the width of the div.
Use backgroundColor instead of BackgroundColor.
To get a proper computed width, you need to use the (not enough used) method getBoundingClientRect() https://developer.mozilla.org/en-US/docs/Web/API/element.getBoundingClientRect
Latest browsers have .width property, otherwise you just need to take right - left to get it.
Some comments:
- language="JavaScript" is useless. Like type="text/javascript". It's the default behavior. Seriously.
- you need to execute your code after the div has been created. So using onload or just by calling the code after in the html (like in my example)
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#mydiv {
width: 200px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<div id="mydiv"></div>
<script>
/* run the code after the creation of #mydiv */
var mydiv = document.getElementById("mydiv");
var clientRect = mydiv.getBoundingClientRect()
var curr_width = clientRect.width || (clientRect.right - clientRect.left);
if (curr_width > 100) {
mydiv.style.backgroundColor = "blue";
}
</script>
</body>
</html>
Here is a working example http://jsbin.com/xapet/1/edit
Warning: to do this properly it's recommended that you execute this code each time the browser is resized.
Maybe you can take a look to the "element queries" thing, that will be a nice workaround according to media queries limitations.
https://encrypted.google.com/search?hl=en&q=element%20queries%20css

z-index property not getting retrieved while other properties are getting retrieved by the same helper function

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="20000;http://new-url/" id="meta-refresh">
<style type="text/css">
#test{
width: 100px;
height: 80px;
background-color: yellow;
opacity:0.5;
z-index:3;
}
</style>
<title>Add Properties</title>
<!--link rel="stylesheet" href="qunit-1.12.0.css"-->
</head>
<body>
<div id="test">This is some text</div>
<p>Properties</p>
<script>
function getStyle(el, cssprop){
if (el.currentStyle) //IE
return el.currentStyle[cssprop]
else if (document.defaultView && document.defaultView.getComputedStyle) //Firefox
return document.defaultView.getComputedStyle(el, "")[cssprop]
else //try and get inline style
return el.style[cssprop]
}
console.log("1"+navigator.appVersion);
console.log("2"+navigator.platform);
console.log("3"+history.length);
console.log("4"+parent.top.document.referrer);
metatags = document.getElementsByTagName("meta");
var content = metatags[0].getAttribute("content");
var mr = document.getElementById("meta-refresh");
console.log("Meta Refresh"+ content);
console.log(navigator.plugins);
console.log(navigator.plugins.length);
var mydiv = document.getElementById("test");
console.log(getStyle(mydiv,'width'));
console.log(getStyle(mydiv,'opacity'));
console.log(getStyle(mydiv,'z-index'));
var d = new Date()
var n = d.getTimezoneOffset();
console.log(n);
</script>
</body>
</html>
This is the code and all properties like width opacity show appropriate values but z-index gives out an undefined value.I tried 'z-index' as well as "zindex".Please help me with this problem.
Thanks in advance
Swaraj
I tried z-index as well as zindex
Close, but it's zIndex. Properties of CSSStyleDeclarations (such as returned by .style or getComputedStyle()) are camel-cased. You also could use .getPropertyValue("z-index").

Categories

Resources