I have a variable placement that can be set to the following values: top, top-left, top-right, bottom, bottom-left, bottom-right, right, right-top, right-bottom, left, left-top, left-bottom.
I have another variable const trigger = triggerRef.current.getBoundingClientRect(); so I can determine where the trigger element is, and based on that, set the placement variable accordingly.
I am currently using a lot of if else statements. For instance:
if (placement === "top" && trigger.top < 75 && windowWidth - trigger.right > 75 && trigger.left > 175)
{ placement = "bottom";
} else if ( placement === "top" && windowWidth - trigger.right < 75 && windowHeight - trigger.bottom > 75 && trigger.top < 75)
{ placement = "left-top"; }
...and the code goes on and on
What's a "DRY-er" way of doing this?
Consolidate the logic in these tests and only check once. Assign a variable if instead of repeating the same calculations:
if (placement === "top" && trigger.top < 75 ) {
const triggerFromWidth = windowWidth - trigger.right;
if (triggerFromWidth > 75 && trigger.left > 175) {
placement = "bottom";
} else if (triggerFromWidth < 75 && windowHeight - trigger.bottom > 75) {
placement = "left-top";
}
}
Related
I don't think there's any such method in the DOM API like element.doesOverlap(otherElement), so I think I have to calculate this by hand, right? Not sure if there are any shortcuts.
If not, what is the method for this? It seems like there's so many ways something could overlap....it would be so many conditionals. Is there a concise way of writing this?
In pseudo code, I have this:
if (
((A.top < B.bottom && A.top >= B.top)
|| (A.bottom > B.top && A.bottom <= B.bottom))
&&
((A.left < B.right && A.left >= B.left)
|| (A.right > B.left && A.right <= B.right))) {
// elements A and B do overlap
}
^Is this the simplest way?
This is essentially and x,y comparison problem. You essentially need to compare the two element by there x,y positions at all boundaries ( top, right, bottom and left ) if they overlap anywhere.
A simple method would be, to test that they don't overlap.
Two items could be considered to overlap if none of the following are true:
- box1.right < box2.left // too far left
- box1.left > box2.right // too far right
- box1.bottom < box2.top // too far above
- box1.top > box2.bottom // too far below
Only really a slight change to what you had.
function checkOverlap(elm1, elm2) {
e1 = elm1.getBoundingClientRect();
e2 = elm2.getBoundingClientRect();
return e1.x <= e2.x && e2.x < e1.x + e1.width &&
e1.y <= e2.y && e2.y < e1.y + e1.height;
}
window.onload = function() {
var a = document.getElementById('a');
var b = document.getElementById('b');
var c = document.getElementById('c');
console.log("a & b: "+checkOverlap(a,b));
console.log("a & c: "+checkOverlap(a,c));
console.log("b & c: "+checkOverlap(b,c));
}
<div id="a" style="width:120px;height:120px;background:rgba(12,21,12,0.5)">a</div>
<div id="b" style="position:relative;top:-30px;width:120px;height:120px;background:rgba(121,211,121,0.5)">b</div>
<div id="c" style="position:relative;top:-240px;left:120px;width:120px;height:120px;background:rgba(211,211,121,0.5)">c</div>
There isn't an easier way. The correct code is this, covering all possible ways two elements can overlap:
const doElementsOverlap = (elementA: any, elementB: any) => {
const A = elementA.getBoundingClientRect();
const B = elementB.getBoundingClientRect();
return (
((A.top < B.bottom && A.top >= B.top)
|| (A.bottom > B.top && A.bottom <= B.bottom)
|| (A.bottom >= B.bottom && A.top <= B.top))
&&
((A.left < B.right && A.left >= B.left)
|| (A.right > B.left && A.right <= B.right)
|| (A.left < B.left && A.right > B.right))
);
};
I've got three elements - every element is hidden from the start. If user scrolls onto them, they show up. I wrote a function that checks if element named bubbles is inside viewport. If it is, then function should show the rest of the elements.
But it doesn't. Element boxes is higher than element bubbles, and it also fires a function. But it shouldn't. I have no idea where the problem is.
document.addEventListener("scroll", checkViewport);
function checkViewport() {
var bubbles = document.getElementsByClassName("bubble-chat");
var boxes = document.getElementsByClassName("boxes");
var avatar = document.getElementsByClassName("msg-avatar");
for (let i = 0; i < avatar.length; i++) {
var bounding = bubbles[i].getBoundingClientRect();
if (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
) {
avatar[i].style.opacity = "1";
bubbles[i].style.opacity = "1";
(function(i) {
setTimeout(function() {
bubbles[i].style.display = "none";
boxes[i].style.opacity = "1";
}, 3000);
})(i);
}
}
}
you should also consider the scrolling positioning as the bounding box is relative to that.
Fixed code:
bounding.top >= document.documentElement.scrollTop &&
bounding.left >= 0 &&
bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
bounding.bottom <= document.documentElement.scrollTop + (window.innerHeight || document.documentElement.clientHeight)
Well, I feel stupid. The code was okay all the time. I just commented one of the msg-text divs, and turns out, that it was the reason for the code to break.
I want some script for my app to change the font-size of a title depending on number of characters and the resolution, so to use different font-sizes in the script depending on window resolution and the number of characters of the title.
This is what I have right now:
$(document).ready(function () {
$(".boxes.concierto h2.nombreartista span a").each(function () {
var numChars = $(this).text().length;
if ((numChars >= 1) && (numChars < 20)) {
$(this).css("font-size", "20px");
}
else if ((numChars >= 20) && (numChars < 30)) {
$(this).css("font-size", "18px");
$(this).css("line-height", "20px");
}
else if ((numChars >= 30) && (numChars < 60)) {
$(this).css("font-size", "15px");
$(this).css("line-height", "18px");
}
else if ((numChars >= 100) && (numChars < 140)) {
$(this).css("font-size", "0.9em");
}
else {
$(this).css("font-size", "0.8em");
}
});
});
I have tried to add:
if($(window).width() >= 1300){
// do your stuff
}
at the begining and end of my script but is not working.
Any idea how can I join this two functions correctly?
Thank you so much
you probably want to create a condition where either the number of characters or the resolution change the text size.
use the or-operator || in your if condition
if ( ((numChars >= 20) && (numChars < 30)) || $(window).width() >= 1300 ) {
$(this).css("font-size", "20px");
}
a better way
the conditions might get quite complex. a better way would be to setup a formula like:
var textSize = 1/numChars * $(window).width() * factor;
if you want the text size to change in steps you can do something like this:
var stepSize = 3;
var steppedTextSize = Math.floor(textSize/stepSize) * stepSize;
the steppedTextSize will have values in increments of 3. like: 12, 15, 18, ...
I have a script which shows different content depending on the screen size, it looks like this:
if ((window.innerWidth < 1250 )) {
//Do something
}
I am trying to set a greater than value as well as a less than value. I thought the follwoing would work:
if ((window.innerWidth < 1250 && > 750)) {
//Do something
}
Can anyone help me out?
When using Boolean operators (&&, ||, etc), each side must be a completely valid Boolean expression on its own. && > 750 is not a valid expression, since > 750 cannot be evaluated as True or False.
What you want is :
if (window.innerWidth < 1250 && window.innerWidth > 750) {
As both window.innerWidth < 1250 and window.innerWidth > 750 are valid expressions and can be resolved independently.
Close:
if (window.innerWidth < 1250 && window.innerWidth > 750) {
You need to repeat the comparison argument after the && to check with new value.
Use like this:
if (window.innerWidth < 1250 && window.innerWidth > 750) {
function between(val, min, max)
{
return val >= min && val <= max;
}
if (between(window.innerWidth,750,1250)) {
//your code!!!
}
So basically what I have is a function called createBoxBoundary, which, when the player position is within certain limits, sets boundary variables to true. Pretty straightforward. However, when I call this function more than once in the main game loop, only the one most recently called works. Below is a sampling of my code
//It should be noted the player deminsions are 40x80
function createBoxBoundary(x,y,width,height){
//right boundaries
if(playerXPos + 40 == x && playerYPos + 80 >= y && playerYPos < y + height){
boundaryRight = true;
} else{boundaryRight = false;}
//bottom boundaries
if(playerYPos == y + height && playerXPos + 40 >= x && playerXPos <= x + width){
boundaryTop = true;
} else{boundaryTop = false;}
//left boundaries
if(playerXPos == x + width && playerYPos + 80 >= y && playerYPos <= y + height){
boundaryLeft = true;
} else{boundaryLeft = false;}
//bottom boundaries
if(playerYPos + 80 == y && playerXPos + 40 >= x && playerXPos < x + width){
boundaryBottom = true;
} else{boundaryBottom = false;}
}
I've also set up a fiddle with the full game code. And if anyone has advice on a better way to do collisions/boundaries in javascript, I'm open to that as well. Any help is appreciated!
The problem is that you are not checking if boundaryRight is already set to true before checking what is value is for the second boundary.
Something like this should work:
boundaryRight = ( boundaryRight || ( playerXPos + 40 == x && playerYPos + 80 >= y && playerYPos < y + height );
I have also done some other tweaks in this jsFiddle that add some more flexibility of defining boundaries and other things. Also adds the ability to move in more than one direction.
http://jsfiddle.net/petersendidit/QdCMG/7/