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.
Related
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";
}
}
I've created an algorithm to determine which pieces have been killed in a game of Go. For my algorithm, pieces are stored in a 2D array of rows and columns (from 0-8, as I am using a 9x9 board). Each piece is also an array, where:
piece[0] is the color of the piece, either "empty", "black", or "white".
piece[1] is irrelevant.
piece[2] is a boolean of whether or not it has liberty (initially set to true if an empty square and false if there is a piece there).
piece[3] is whether or not it has been iterated over in the algorithm yet. All pieces start with this as true.
Here is the algorithm for discerning which pieces have liberty:
let oldBoard = 0;
while (board != oldBoard) {
oldBoard = board;
for (let row = 0; row < 9; row++) {
for (let col = 0; col < 9; col++) {
if (board[row][col][2] && !board[row][col][3]) {
board[row][col][3] = true;
if (row != 0 && (board[row][col][0] == "empty" || board[row][col][0] == board[row-1][col][0])) { board[row-1][col][2] = true; }
if (row != 8 && (board[row][col][0] == "empty" || board[row][col][0] == board[row+1][col][0])) { board[row+1][col][2] = true; }
if (col != 0 && (board[row][col][0] == "empty" || board[row][col][0] == board[row][col-1][0])) { board[row][col-1][2] = true; }
if (col != 8 && (board[row][col][0] == "empty" || board[row][col][0] == board[row][col+1][0])) { board[row][col+1][2] = true; }
}
}
}
}
Afterwards, it removes all pieces that are marked as not having liberty (piece[2] == false).
Everything works fine, unless the air spaces are to the bottom/right. For instance, if you put down this configuration:
Then the X-ed out piece will be captured, which it shouldn't be. But, if you put down this configuration:
Then no piece will be captured, which is the expected result.
As best as I can tell from my investigations of the bug, it seems to be that any piece that was marked as having liberty from a piece to its bottom or right is unable to give any adjacent pieces liberty.
You can find the full repository here.
I might be late on this one, but here's my idea.
As I commented, you should look at the stones as a group, instead of looking at it individually.
#maraca 's comment was very helpful. Since adjacent stones to the updated stone is affected, you could check all four adjacent pieces from the updated stone, then check each of those stones' adjacent stones and so on... until it ends. The function can look something like this.
function isGroupAlive(x, y) {
let stack = [];
let alive = false;
const check = (x, y) => {
stack.push([x, y].toString());
let cell = board[x][y];
if (x !== 0 && board[x-1][y][0] === null) alive = true;
else if (x !== 0 && board[x-1][y][0] === cell[0] && stack.includes([x-1, y].toString)) check(x-1, y);
if (x !== size-1 && board[x+1][y][0] === null) alive = true;
else if (x !== size-1 && board[x+1][y][0] === cell[0] && stack.includes([x+1, y].toString)) check(x+1, y);
if (y !== 0 && board[x][y-1][0] === null) alive = true;
else if (y !== 0 && board[x][y-1][0] === cell[0] && stack.includes([x, y-1].toString)) check(x, y-1);
if (y !== size-1 && board[x][y+1][0] === null) alive = true;
else if (y !== size-1 && board[x][y+1][0] === cell[0] && stack.includes([x, y+1].toString)) check(x, y+1);
}
check(x, y);
return alive;
}
I used a stack to keep track of already iterated stones' coordinates, but you could do something else too.
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>
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, ...
1. I want ratingClass = 'fresh' if rating > 59 OR if audience_rating > 70. How?
I tried with
if (rating > 59) || (audience_rating > 70) {
var ratingClass = 'fresh';
Here's the code:
if (rating > 59) {
var ratingClass = 'fresh';
} else if (rating > 0){
var ratingClass = 'rotten';
} else {
var ratingClass = 'na';
}
if (audience_rating > 59) {
var audienceClass = 'fresh';
} else if (audience_rating > 0){
var audienceClass = 'rotten';
} else {
var audienceClass = 'na';
}
$parentEl.addClass(ratingClass);
2. In line 114 of http://pastebin.com/UN8wcB7b I get Uncaught TypeError: Cannot read property 'length' of undefined every ~3 seconds when hideRotten = true. Is it easily fixed and/or do I need to worry about it at all?
I am new to JavaScript coding, currently I am trying to learn by doing. Can you recommend any resources to learn writing Chrome Extensions with JavaScript?
Thanks :-)
it's because you are trying to read the length of a null element. So put a condition to test if movies are null in your if statement on line 114 so it says something like
if(data.movies && data.movies.length > 0)
Though if you're setting some data in this if statement that will be used other places in the code you may have to put checks like this in other places as well to completely avoid this type of problems.
The error definitely means
typeof data.movies === "undefined"
to avoid this I will recommend
...
$.getJSON(movieUrl, function(data){
// data can be undefined becoz of various reasons and so is data.movies
if(!(typeof data === "undefined") && !(typeof data.movies === "undefined")) {
//put similar checks in ur code
...
1) the condition after the if must always be completely surrounded in brackets:
// wrong
if (rating > 59) || (audience_rating > 70) {
// has to be:
if ( rating > 59 || audience_rating > 70 ) {
or if you are unsure about the operator precedence:
if ( (rating > 59) || (audience_rating > 70) ) {
2) You have to check first, if the movies attribute exists in your data respone (Because if it doesn't, you also can't call length on it):
// can throw error if data.movies === undefined
data.movies.length > 0
// the safe way, check data.movies first:
if (data.movies && data.movies.length > 0)
this is pretty much equivalent to the long version*:
if (typeof(data.movies) === `undefined` && data.movies.length > 0)
* Not exactly, read this article why