How to set multiple elements style via getBoundingClientRect() - javascript

I am trying to set elements (children of a container with transform) to fixed position relative to the viewport. I'm attempting to find each of them, and assign to a variable via getBoundingClientRect(), then define style properties from that variable.
<div>
<div class="preview-container">
<div>
<!-- Image -->
</div>
</div>
</div>
<div>
<div class="preview-container">
<div>
<!-- Image -->
</div>
</div>
</div>
<!-- more -->
JS v1
$('.preview-container').each(function(el) {
preview = this.getBoundingClientRect();
console.log(preview);
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
});
This works without the three style lines and console displays all of the .preview-container elements correctly. Adding the style lines produces errors about those style properties not being defined:
jQuery.Deferred exception: Cannot set properties of undefined (setting 'position')
Uncaught TypeError: Cannot set properties of undefined (setting 'position')
I don't understand that because preview is working in console.
JS v2
This attempt works as is, but is less complete. console is producing all of the .preview-container elements, but I haven't been able to incorporate getBoundingClientRect():
document.querySelectorAll(".preview-container").forEach(preview => {
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
console.log(preview);
});
I feel like I am closer with JS v1, and am missing something simple with the style properties. How should I proceed?

You have a problem with the name of your variables, in the first one you call it el and you refer as preview. And to get the values of getBoundingClientRect you need to create another variable.
document.querySelectorAll(".preview-container").forEach(preview => {
previewValues = preview.getBoundingClientRect();
preview.style.position = "fixed";
preview.style.top = "0";
preview.style.left = "0";
console.log(preview);
console.log(previewValues);}
)
<div>
<div class="preview-container">
<div>
<!-- Image -->
</div>
</div>
</div>
<div>
<div class="preview-container">
<div>
<!-- Image -->
</div>
</div>
</div>
<!-- more -->

Looking at the interfaces for DOMRect (there are several), it states that updating properties of a DOMRect updates the position of the element it was called on, as in this example:
"use strict";
$('.preview-container').each(function(el) {
var rect = this.getBoundingClientRect();
this.style.position = "fixed";
// this.style.top = "0";
rect.x = 0;
// this.style.left = "0";
rect.y = 0;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- body-html -->
<div>
<div class="preview-container">
<div>
Image 1
</div>
</div>
</div>
<div>
<div class="preview-container">
<div>
Image 2
</div>
</div>
</div>
Note
this has been used to refer to preview divisions in the each argument function, not el.
Changes to position are made by setting properties of rect, not style, as allowed in the standard, but this is uncommon.
Usually positions are set either in CSS, or using element style objects (the this.style lines commented out above), without calling getBoundingClientRect to obtain a DOMRect first.
However when an element descends from an element with a transform property, the transform element behaves as the containing block for fixed elements below as shown here:
$('.preview-container').each(function(el) {
this.style.position = "fixed";
this.style.top = "0";
this.style.left = "0";
});
/* CSS from https://developer.mozilla.org/en-US/docs/Web/CSS/transform */
div.ancestor {
border: solid red;
transform: translate(30px, 20px) rotate(20deg);
width: 140px;
height: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- body-html -->
<div class="ancestor">
<div class="preview-container">
<div>
Image 1
</div>
</div>
</div>
<div class="ancestor">
<div class="preview-container">
<div>
Image 2
</div>
</div>
</div>
If you want to fix preview container positioning relative to the view port, try moving them out from under the transform ancestor by, say, appending them to the body element. If aspects of the transform operation need to be retained on moved preview containers, a suitable CSS transform would need to be separately applied to them after the move.

Related

JavaScript change background image on-click?

I'm trying to change the background of the body on my HTML doc using some basic JS functions. I have set the function to target a specific ID, and then the style.background tag, if it is the current background image, then set it to another one I specified, else keep the same image. I have tried changing the code countless times now, but still can't seem to get it to change the background. Any help with this would be appreciated.
HTML:
<div class="bg-image"
style="background-image: url('./img/frankie.jpg');
height: 100vh" id="bacgr"> <!--SETS BACKGROUND using id tag to change w/ JS-->
<main role="main" class="container d-flex justify-content-center">
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
</main>
</div>
JS:
let myImage = document.getElementById('bacgr').style.backgroundImage; //have to target specific image(like an array ([0])), put inside div w/ id.
myImage.onclick = function() {
if(myImage === "url('./img/frankie.jpg')") {
myImage == "url('./img/jesus_mobile.jpg')";
} else {
myImage == "url('./img/frankie.jpg')";
}
}
Try this:
const el = document.getElementById('bacgr');
el.onclick = function() {
if(this.style.backgroundImage === "url('./img/frankie.jpg')") {
this.style.backgroundImage = "url('./img/jesus_mobile.jpg')";
} else {
this.style.backgroundImage = "url('./img/frankie.jpg')";
}
}
Here is the example
You are changing only the URL, but that will not be assigned back to the dom element.
const el = document.getElementById('bacgr');
let prev = 'url("https://images.unsplash.com/photo-1570215171323-4ec328f3f5fa")';
el.onclick = function() {
el.style.backgroundImage = prev === el.style.backgroundImage ? 'url("https://images.unsplash.com/photo-1583508915901-b5f84c1dcde1")' : prev;
}
<div class="bg-image" style="background-image: url('https://images.unsplash.com/photo-1570215171323-4ec328f3f5fa');
height: 100vh" id="bacgr">
<main role="main" class="container d-flex justify-content-center">
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
</main>
</div>

random divs horizontally javascript

New here. I am a sys-admin with medium experience with html/css/php. I've worked on modX, Wordpress and Joomla in the past, and now my boss wants something that requires javascript or jquery knowledge (less than basic in my case).
Problem description: .x-container is with fluid height and .x-column also, .ult-new has fixed height 230px with margin set in css (20px) and position relative. x-column has width: 22% and position relative and margin-right: 4%. And i need to display randomly each ult-new inside each x-column (inside each x-container). Those elements are created dynamically with php and shortcodes. So i need to vertically position them in random places in those columns and relative to each other (with 20px margin top and bottom).
As i understand i need to count the height of each x-column and than count the number of .ult-new elements in each of those columns. And than i need to posiotion those elements as absolute and do some math (first will be 0px from the top plus 20px margin, and then second element needs to be 230px from the top plus 20px margin top etc).
How do i translate this to javascript? Is there something else i don't see? :)
<div class"x-container">
<div class="x-column">
<div class="ult-new">
<!--some code here (text, hyperllinks etc)-->
</div>
<div class="ult-new">
</div>
<div class="ult-new">
</div>
<!--some code here (text, hyperllinks etc)-->
</div>
<div class="x-column">
<div class="ult-new">
</div>
<div class="ult-new">
</div>
<div class="ult-new">
</div>
</div>
<!--and many more x-column-->
</div>
<div class"x-container">
<div class="x-column">
<div class="ult-new">
</div>
<div class="ult-new">
</div>
<div class="ult-new">
</div>
</div>
<div class="x-column">
<div class="ult-new">
</div>
<div class="ult-new">
</div>
<div class="ult-new">
</div>
</div>
</div>
<!--and many more x-container-->
I may not fully understand what your doing but the best information i can give you is this jquery. now your gonna have to do some of the work to configure it but i believe in you!
var x; // move horizontal
var y; // move vertical
$('.YOURCLASS').css({"width":"50px","margin","50px","position":"absolute","transform":`translateX(${x})`,"transform":`translateY(${Y})`}) //sets styles
$('.YOURCLASS').css("width") // gives the width of element
var randomnum = Math.floor((Math.random() * 10) + 1); // random number 1-10
y = randomnum
x = randomnum
// use position:absolute then pass x,y in

how to make all elements invisible in javascript?

I'm using the navigo vanilla javascript router library to make a single page application and I'm trying to implement this part.
router
.on('/products/list', function () {
// display all the products... here i need to hide and show
})
.resolve();
I thought the thing I need to do is hide and show some divs so how do i set all divs as invisible or make everything on the page invisible.
<body>
<div id="homepage">
<h1>home</h1>
</div>
<div id="ad">
<h1>advert</h1>
</div>
<div id="errorpage">
<h1>error</h1>
</div>
<div class="state">
<span class="users">?</span> online
</div>
<script
src="https://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/navigo#7.1.2/lib/navigo.min.js"></script>
<script src="script.js"></script>
</body>
Hide DIV using id
<div id="homepage">
<h1>home</h1>
</div>
using JQuery
$('#homepage').hide();//hide
$('#homepage').show();//Show
Using Javascript
document.getElementById('homepage').style.display = 'none'; //hide
document.getElementById('homepage').style.visibility = 'hidden'; // hide
document.getElementById('homepage').style.display = 'block'; // Show
document.getElementById('homepage').style.display = 'inline'; // Show
document.getElementById('homepage').style.display = 'inline-block'; // Show
document.getElementById('homepage').style.visibility = 'visible'; // Show
If you want to hide all the div in page
Using JQuery
$('div').hide();//hide
Using Javascript
var divs = ​document.getElementsByTagName("div");​
for (var i = 0; i < divs.length; i++) {
divs[i].style.display = 'none';
}
The easiest and most efficient way would be putting the products in a container (i.e. div) and set its display (to none and block) or it's visibility, or opacity (whichever floats your boat):
<div id="products">
....
</div>
JS:
to hide:
document.GetElementById("products").style.display = "none";
to show:
document.GetElementById("products").style.display = "block";

Add all elements after first element to a div by using javascript (No jQuery)

I have the following html
<div id="main">
<aside id="list"><p>sometext</p></aside>
<aside id="list-2"><p>sometext</p></aside>
<aside id="list-3"><p>sometext</p></aside>
<aside id="list-4"><p>sometext</p></aside>
</div>
I want to use javascript to make it look like :
<div id="main">
<aside id="list"><p>sometext</p></aside>
<div id="wrap">
<aside id="list-2"><p>sometext</p></aside>
<aside id="list-3"><p>sometext</p></aside>
<aside id="list-4"><p>sometext</p></aside>
</div>
</div>
I have tried insertAdjacentHTML and innerHTML methods :
widgets = document.getElementById('main');
widgets.innerHTML = "<div class='box-class'>" + widgets.innerHTML + "</div>";
But this adds wrapper over "list" too.
There are two big problems with the code you said you tried (three if widgets isn't declared anywhere):
widgets = document.getElementById('main');
widgets.innerHTML = "<div class='box-class'>" + widgets.innerHTML + "</div>";
Using strings means the browser has to go through the elements, build an HTML string for them, and return that string to JavaScript; then when you assign to innerHTML it has to destroy the elements that are already there and build new replacement ones by parsing the HTML string. This will wipe out any event handlers or similar attached to the elements. (Of course, if there aren't any, it doesn't matter much.)
That wraps all of the children, not just the ones after the first child.
(It also wraps them in <div class='box-class'>, not <div id="wrap">, but...)
On all modern browsers, elements have a children list you can use for this. Then just create a wrapper, move the children other than the first into it, and append it.
var main = document.getElementById("main");
var wrapper = document.createElement("div");
wrapper.id = "wrap";
while (main.children.length > 1) {
// Note: Appending the element to a new parent removes it from its original
// parent, so `main.children.length` will decrease by 1
wrapper.appendChild(main.children[1]);
}
main.appendChild(wrapper);
Example:
var main = document.getElementById("main");
var wrapper = document.createElement("div");
wrapper.id = "wrap";
while (main.children.length > 1) {
wrapper.appendChild(main.children[1]);
}
main.appendChild(wrapper);
#wrap {
border: 1px solid blue;
}
<div id="main">
<aside id="list">
<p>sometext</p>
</aside>
<aside id="list-2">
<p>sometext</p>
</aside>
<aside id="list-3">
<p>sometext</p>
</aside>
<aside id="list-4">
<p>sometext</p>
</aside>
</div>
Side note: In your markup, you have </div> where you want </aside>.

Jquery equal Heights

I don't know what am I doing wrong.. but I have 3 columns where I want to apply equal heights
here is my html
<div id="wrapper">
<div class="LeftBG"></div>
<div id="MainBlock">THIS IS A TEST</div>
<div class="RightBG"></div>
<!-- END CONTENT BLOCK -->
</div>
and here is my function and just doesn't work....
var highestCol = Math.max(
$('.LeftBG').height(),
$('.RightBG').height());
$('#MainBlock').height(highestCol);
To see what I am doing click here
Change your code to this to set all three blocks to the same height:
var highestCol = Math.max(
$('.RightBG').height(),
$('.LeftBG').height());
$('#MainBlock, .RightBG, .LeftBG').height(highestCol);
See it here: http://jsfiddle.net/jfriend00/Rv4fr/
What you did fixes the middle column, now apply it to the other classes as well...
var highestCol = Math.max(
$('.RightBG').height(),
$('.LeftBG').height());
$('#MainBlock').height(highestCol);
$('.RightBG').height(highestCol);
$('.LeftBG').height(highestCol);

Categories

Resources