jQuery Run function only once on window resize - javascript

I have a function that i have to run only once if specific width is reached.
Function is used to transpose table (columns with rows) only on mobile
What I need:
1. ON LOAD
a. if width <992 run transposeTable (mobiles)
b. if width> 992 do nothing
2. ON RESIZE
a. if width <992 run transposeTable ONLY ONCE BUT if loaded page has a smaller width than 992px do nothing (see 1)
b. if width> 992 run transponseTable ONLY ONCE BUT if loaded page has a width greater than 992px to nothing (see 1)
here's solution (with some modifications) thanks to #Olaf Nankman
var transposed = "desktop";
$(document).ready(function(){
if($(window).width() < 992){
transposed = "mobile"
transposeTable();
}else{
transposed = "desktop"
}
})
$(window).resize(function(){
if($(window).width() < 992 && transposed != "mobile"){
transposed = "mobile"
transposeTable();
}
if($(window).width() > 992 && transposed != "desktop"){
transposed = "desktop"
transposeTable();
}
})

You must store that you've already called the transposeTable function, and you should transpose the table to desktop with another function...
For example:
// Create 2 apart functions, one for mobile, one for desktop
function transposeTableMobile(){
// Transpose to mobile
}
function transposeTableDesktop(){
// Transpose to desktop
}
// Create a variable to check if already transposed
var transposed = "desktop";
$(document).ready(function(){
// On page load
// Transpose the table
// Since this function runs only once,
// we don't need to check if the table
// is transposed
if($(window).width() < 992){
transposed = "mobile"
transposeTableMobile();
}else{
transposed = "desktop"
transposeTableDesktop();
}
})
$(window).resize(function(){
// On page resize
// We check if the table is transposed to mobile,
// if not, but should be, transpose it and store that
// we transposed the table
if($(window).width() < 992 && transposed != "mobile"){
transposed = "mobile"
transposeTableMobile();
}else if(transposed != "desktop"){
transposed = "desktop"
transposeTableDesktop();
}
})

If this can help, work fine for my needs
var x;
$(window).resize(function() {
if ($(this).width() <= 600 && (x === 2 || x === undefined)) {
if(x !== undefined){
//function here
$("body").append('size: small<br/>');
}
x = 1;
}
else if ($(this).width() > 600 && $(this).width() <= 1140 && (x === 1 || x === 3 || x === undefined)){
if(x !== undefined){
//function here
$("body").append('size: medium<br/>');
}
x = 2;
}
else if ($(this).width() > 1140 && (x === 2 || x === undefined)){
if(x !== undefined){
//function here
$("body").append('size: large<br/>');
}
x = 3;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Dry-er Way of Writing a Bunch of If Else Statements

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";
}
}

Check if element is in viewport doesn't work properly

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.

Get Level from Experience points - Level isn't taken into consideration [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
OK, now my issue is that no matter what I do, it will only present the information as Level 1 instead of the designated level that I try. The code is as follows
function XPlevel(XP, level) {
if((XP >= 0 && XP < 300) && level === 1) {
level = 1;
} else if ((XP >= 300 && XP <900) || level === 2) {
level = 2;
} else if ((XP >= 900 && XP <2700) || level ===3) {
level = 3;
} else if ((XP >= 2700 && XP < 6500) || level === 4){
level = 4;
} else if ((XP >= 6500 & XP < 14000) || level === 5){
level = 5;
} else if ((XP >= 14000 && XP < 23000) || level === 6) {
level = 6;
} else if ((XP >= 23000 && XP < 34000) || level === 7) {
level = 7;
} else if ((XP >= 34000 && XP < 48000) || level === 8) {
level = 8;
} else if ((XP >= 48000 && XP < 64000) || level === 9) {
level = 9;
} else if ((XP >= 64000 && XP < 85000) || level === 10) {
level = 10;
} else if ((XP >= 85000 && XP < 100000) || level === 11) {
level = 11;
} else if ((XP >= 100000 && XP < 120000) || level === 12) {
level = 12;
} else if ((XP >= 120000 && XP < 140000) || level === 13) {
level = 13;
} else if ((XP >= 140000 && XP < 165000) || level === 14) {
level = 14;
} else if ((XP >= 165000 && XP < 195000) || level === 15) {
level = 15;
} else if ((XP >= 195000 && XP < 225000) || level === 16) {
level = 16;
} else if ((XP >= 225000 && XP < 265000) || level === 17) {
level = 17;
} else if ((XP >= 265000 && XP < 305000) || level === 18) {
level = 18;
} else if ((XP >= 305000 && XP < 355000) || level === 19) {
level = 19;
} else {
level = 20;
}
return level;
}
XPlevel(XP, level);
So when I plug in a character that is Level 5 for instance, it gives me back level 1 instead.
Any thoughts?
First of all, never code like this, never have multiple if-else statements that make semantically similar checks that could be written using an array or hash table in a few lines.
Your function could be re-written like this:
var xp_required = [0, 300, 900, 2700, 6500]; // ...etc, you fill this table with the XP required to be at Level = index + 1 (indices start at 0 in Arrays).
// XP for level: 1 2 3 4 5 ...
function getLevel(xp) {
for(var level = xp_required.length - 1; level >= 0; --level) {
if(xp >= xp_required[level] {
return level + 1; // The +1 is needed because Array's index starts at 0 but levels start at 1
}
}
console.log("XP value can not be negative. The given value was: " + xp);
return 0;
}
The for loop starts at the highest level and checks if the XP is enough for the player to be considered that level. If it's not, it means that the player is actually a lower level, thus decrementing the level value to be checked (until we reach index 0 which means Level 1). This means that once we get to the first level for which the XP sufficies it means that is indeed the correct level.
As a note, this could be improved by doing a binary search instead of a linear search, but I assume that this function is not called that often so the O(max_level) complexity is good enough.
Also, why is level both an input and output value for your function?
(Beside the XP stuff...) you're basically doing if level == 1 return 1 which is nonsensical.
If you already know the level than logically you don't need to check for the level.
The simplest & fastest way to get a level out of an array of XP values:
function getLevel(XP) {
var LV = 0;
[0, 300, 900, 2700, 6500, 14000].some(function(v, i) {
LV = i; // Level = index
return v > XP; // We have the LV value! Break out of loop (if condition is met)!
});
return LV;
}
Use like
var level = getLevel(2699); // 3
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some

trying to get offsetTop on window.scroll and then traverse the DOM according to the touched slide

I am creating one page site and then trying to get offsetTop on window.scroll, by which i want to traverse the DOM according to the slide.
a lot of tries.. feeling dumb now..
if anyone can help, would be highly appreciable.
thanks
here is the code and fiddle URL:
$(window).scroll(function () {
var y = $(window).scrollTop(),
a = $('#first').offset().top - 200,
b = $('#second').offset().top - 200,
c = $('#third').offset().top - 200,
d = $('#fourth').offset().top - 200;
if (y > a) {
$('h1').html('This is First Slide');
}
if (y > b) {
$('h1').html('This is Second Slide');
}
if (y > c) {
$('h1').html('This is Third Slide');
}
if (y > d) {
$('h1').html('This is Third Slide');
}
else{
$('h1').html('No heading');
}
});
http://jsfiddle.net/A8Hmr/9/
Your logic is correct it's just a miss with the ifs.
I will show the code and explain:
var a = $('#first').offset().top - 200,
b = $('#second').offset().top - 200,
c = $('#third').offset().top - 200,
d = $('#fourth').offset().top - 200;
$(window).scroll(function () {
var y = $(window).scrollTop();
if (y > a && y < b) {
$('h1').text('This is First Slide');
}
else if (y > b && y < c) {
$('h1').text('This is Second Slide');
}
else if (y > c && y < d) {
$('h1').text('This is Third Slide');
}
else if (y > d) {
$('h1').text('This is Third Slide');
}
else{
$('h1').text('No heading');
}
});
Demo
1) You don't need to take the offset of the slides on every scroll, since they don't change, you can put them outside of the scroll event, that way it will improve the performance.
2) The problem in the code was the if. Since they were all ifs (and not if/else if) statements, all of theme were checked if they were true. Meaning that if the first one was true the next one will not be true and it will enter in the else statement automaticaly overwriting the if that was true.
So you have to make them if/else if and since once y > a become true it will always be true (untill it goes to y < a) you must have an additional condition if y < b meaning if y is less then the next slide. Ofcourse once again you can use only if/else but what is the point in checking 5 things if only one is correct ? Performance should be a main thing in every js code. ;)
Version 2:
(function(){
var a = $('#first').offset().top - 200,
b = $('#second').offset().top - 200,
c = $('#third').offset().top - 200,
d = $('#fourth').offset().top - 200,
h1 = $('h1'),
textChange = ['No heading','This is First Slide','This is Second Slide','This is Third Slide', 'This is Third Slide']
$(window).scroll(function () {
var y = $(window).scrollTop();
if (y > a && y < b && h1.text() != textChange[1]) {
h1.text(textChange[1]);
}
else if (y > b && y < c && h1.text() != textChange[2]) {
h1.text(textChange[2]);
}
else if (y > c && y < d && h1.text() != textChange[3]) {
h1.text(textChange[3]);
}
else if (y > d && h1.text() != textChange[4]) {
h1.text(textChange[4]);
}
else if(y <= a && h1.text() != textChange[0]){
h1.text(textChange[0]);
}
});
})();
Demo
What change here?
1) I wrapped the whole thing in self invoking anonymous function (since it's not a good practice to have global variables).
2) We made a variable outside the scroll event that will hold the h1 so we don't have to go in the dom on every scroll event.
3) We made an array that will hold the text that will change. (and updated the values in the text scroll)
4) We changed the if condition in the if statement to check if the text is already the same so we don't have to change it again. So now it will fire only once instead of firing every time we scroll.
5) We changed the else to else if since it would enter once the text is the same an jump to the else.
Pretty much that should increase the performance a lot.

Which of the following is faster?

Which of the following is faster? And, just by the way, which would you personally prefer? (The position variable stores the CSS position of a DIV element.)
1)
if (/(relative|absolute|fixed)/).test(position) { ... }
2)
if (!(/^s/).test(position)) { ... }
3)
if (position == 'relative' || position == 'absolute' || position == 'fixed') { ... }
4)
if (position === 'relative' || position === 'absolute' || position === 'fixed') { ... }
5)
if (position != 'static') { ... }
6)
if (position !== 'static') { ... }
Try it out for your self on http://jsperf.com/
number 5 or 6
Regex have a time complexity of O(mn). 3) and 4) require 3 checks each.
Anyway, you should preform each a 1000 time or so a loop and time them, so you have some experimental evidence on your platform.

Categories