LESS dynamic variables in nested loops - loops

I'm trying to achieve in LESS loops something in JS or PHP would be really simple. Lets say I have 4 levels to loop. Each level height depends on previous level height. Something like:
for (var i; i < 4; i++) {
if (i = 1) {
var height = 100 * i;
} else {
height = height * 3 - i * 20;
}
}
assignFinalHeight(height);
Is it even possible to achieve in LESS?
Tried guarded mixins something like this:
#height: 0;
.count(#lvl) when (#lvl > 1) {
.for(4); .-each(#lvl) {
#height: #height * 3 - #lvl * 20;
}
}
.count(#lvl) when (#lvl = 1) {
#height: 100 * #lvl;
}
.for(4); .-each(#lvl) {
.count(#lvl);
.lvl_#{lvl} {
height: #height;
}
}
Hope you get the idea.
I also tried some other techniques, but I get errors of recursive variable or I get generated CSS with first two levels correct and all other levels the same as second one.
Any help is appreciated
I'm trying to make something like a playoffs scheme - http://i.imgur.com/J8frRVg.png. All marked 2 team holders are div's with some css classes. All these holders are wrapped in one div. Like
<div>
<div class="holder lvl_1 pos_1">
<div class="team_1"></div>
<div class="other stuff"></div>
<div class="team_2"></div>
</div>
<div class="holder lvl_1 pos_2">...</div>
<div class="holder lvl_2 pos_1">...</div>
...
</div>
The only thing left, is the height and positions from top, but these depend on previous level height. Probably I will just make it in JS if it's not possible in LESS :/

Related

Maximum call stack size exceeded from loop

I'm in the early stages of producing a rectangle SVG that uses the rectangle shape. I'm generating the colours of the pixels using a loop that gets all the RGB colours in increments of 8. The returned array has 32,768 <rect /> in it. The code produces the desired outcome however I get an error in:
Chrome
Maximum call stack size exceeded
getTypeSymbol (react_devtools_backend.js:4828)
Firefox
too much recursion
From what I can tell this isn't a recursion problem, the function doesn't appear to be reloading. I think it's related to the size of the array.
Any thoughts on what I should do here, I've never seen this problem before.
function PixelColour() {
console.log("start");
let counter = 0;
let x = 0;
let y = 0;
const colours = [];
for (let red = 0; red < 256; red += 8) {
for (let green = 0; green < 256; green += 8) {
for (let blue = 0; blue < 256; blue += 8) {
counter++;
if (x < 256) {
x++;
} else {
x = 0;
}
if (x === 256) {
y++;
}
colours.push(
<rect
key={counter}
x={x}
y={y}
height="1"
width="1"
style={{ fill: `rgb(${red}, ${green}, ${blue})` }}
/>
);
}
}
}
return <Fragment>{colours}</Fragment>;
}
class Colours extends React.Component {
render() {
return (
<div>
<svg width="256" height="128" style={{ border: "2px solid black" }}>
<PixelColour />
</svg>
</div>
);
}
}
It's not your function reloading (or rerendering) which is the problem per se; you're running into recursion within React itself. Specifically with the way that React devtools tries to reconcile the DOM in order to build a component map.
This is actually not so easy to replicate on codesandbox, since it appears to be using an experimental version of devtools, and this error only crops up when hot-reloading. The stack trace there is scheduleFibersWithFamiliesRecursively but on my local machine with the standard devtools extension installed I get mountFiberRecursively when the component mounts.
I did some digging and came across this github issue, and a PR addressing it which appears to have been abandoned for the time being.
Perhaps if you go and give them a nudge they might take another look:
Getting maximum call stack exceeded on backend.js when rendering many elements.
Refactored backend renderer to remove most of the recursion
All you can do in the meantime is disable the devtools extension. I would add that even with it disabled, this component takes several seconds to mount on my local machine. If you don't take the calculation out of the render cycle (function body) then it is going to be run on every render. You're trying to mount 10s of thousands of DOM nodes which is never going to run performantly - even the PR above only supposes a limit of 15000.
I think a better idea would be to 1) calculate this well in advance if you can, perferably as hard-coded data and nowhere near the UI thread, and 2) draw to a canvas rather than creating nodes in the DOM.

How do I repeat one image a bunch of times to fill up a page in React JSx?

I'm playing around in React and I was interested in creating an interactive background where this ONE image is repeated (and they rotate, but I figured out how to rotate it). I'm pretty sure there is no way for me to use a for loop also, not sure how to make this happen if it is a background image. I figured I would just use z-index to layer it in the end. So far, I just need help repeating it without using .map()
This is what I have (obviously, it's not working with the for loop):
return (
<div>
{
for (var i = 0; i < 100; i++) {
return (
<img
key={i}
src={circle}
alt="circle"
className="rotate"
/>
);
}
}
</div>
);
What am I not getting? Shouldn't there be a way to use map without having to copy an image over and over again manually into an array. I feel like that defeats the purpose.
You should use css for that.
background-repeat property should be a good solution for your problem.
https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat
Also, it is not possible to have for loops within JSX code.
Check out this lesson to better understand what you can put there:
https://egghead.io/lessons/react-understand-and-use-interpolation-in-jsx
If you have a need to use for loop for another purpose this is the way I would suggest doing it:
https://codesandbox.io/s/beautiful-hermann-uoro8?file=/src/App.js
function ElementsList() {
const elements = [];
for (let i = 0; i < 5; i++) {
elements.push(<div key={i}>el {i}</div>);
}
return elements;
}
export default function App() {
return (
<div className="App">
<h1>Generate componets using `for` loop</h1>
<ElementsList />
</div>
);
}

ActionScript 3 sort an array with numbers and letters not working as expected

I'm trying to sort the users cards in a card game, for example all user's aces to stand close to each other.
I'm using this:
p1cards is an array with elements like "c8", "d9", "h1", letters stand from card symbol (Club, Diamond, Hearts) and number is the card value (1 is Ace, 2 is 2, and so on)
p1cards.sort(sortOrder);
function sortOrder(a,b)
{
var aN = parseInt(a.substr(1));
var bN = parseInt(b.substr(1));
if (aN > bN)
{
return 1;
}
else
{
return -1;
}
}
The problem is that sorted card like the 8d, 8c are switching places to 8c, 8d, kind of randomly, when I draw a new card.
Any help will be apreciated.
See in picture below:
http://i.stack.imgur.com/2Ticj.jpg
You don't define in your sort what to do when the values are the same, so depending what item gets slotted in as a and which is b (which you have no control over) will determine the order. Tell your sort function what to do when the items are the same:
function sortOrder(a,b)
{
var aN = parseInt(a.substr(1));
var bN = parseInt(b.substr(1));
if(aN == bN){
//they are the same, so add a secondary sort based off suit
var aS = a.substr(0,1); //grab the first character which is the suit
var bS = b.substr(0,1);
if(aS > bS) return 1;
if(bS > aS) return -1;
return 0;
}
if (aN > bN)
{
return 1;
}
else
{
return -1;
}
}
If you have an undefined behaviour that you are not happy with, simply define the behaviour that you like.
In your case, if both numbers are the same, evaluate the card symbol additionally.
this makes the order of two cards unambigiously clear and the sort operation (for these two cards) idempotent.

hitTestPoint or hitTestObject?

I'm needing to make my character land on a ledge and stay there, but it only keeps going straight through it. Would I create an array for all my different ledges and test whenever my character hits them? Any help would be appreciated.
Thanks.
Collision detection for floors and stuff is actually alot diffrent from hitTesting in the idea that needs to consistently see that the objects are touching. Try something like this!
//loop through all the platform objects to generate the level
var level:Array = new Array();
for (var i=0; i<numChildren; i++)
{
if (getChildAt(i) is platform)
{
level.push(getChildAt(i).getRect(this));
}
}
for (i=0; i<level.length; i++)
{
if (player.getRect(this).intersects(level[i]))
{
if (speedX > 0) ////moving right collision and stuffs
{
player.x = level[i].left-player.width/2;
}
if (speedX < 0) ////moving left collision and stuffs
{
player.x = level[i].right+player.width/2;
}
speedX = 0 //kills the speed
}
}
speedX is the speed at which the characters move horizontally, and "platform" is the name of the variable that you're using as the cliff. Also, "player" can be substituted by whatever you are calling your object that's going onto the ledge. That's how I did it in one of my computer classes anyways :) Hope that helps!

Actionscript 3.0 Get all instances of a class?

I got a ton of movieclips in a class. Is there a more efficient way to apply a function to every instance in the class other than this?
var textArray:Array = [
interludes.interludeIntro.interludeBegin1,
interludes.interludeIntro.interludeBegin2,
interludes.interludeIntro.interludeBegin3,
interludes.interludeIntro.interludeBegin4,
interludes.interludeIntro.interludeBegin5,
interludes.interludeIntro.interludeBegin6,
interludes.interludeIntro.interludeBegin7,
//... ... ...
interludes.interludeIntro.interludeBegin15
];
for each (var interludeText:MovieClip in interludeBeginText)
{
interludeText.alpha = 0 //clear all text first
}
Also for some reason this doesn't work:
interludes.interludeIntro.alpha = 0;
It permanently turns that class invisible, even if I try to make specific instances visible later with:
interludes.interludeIntro.interludeBegin1.alpha = 1;
I have NO idea why the above doesn't work. I want to turn every single instance in the class interludeIntro invisible, but I want to turn specific instances visible later.
(btw I have no idea how to insert code on this website, pressing "code" doesn't do anything, so pardon the bad formatting)
I'm not really sure what you're asking, but what may be useful is that, in ActionScript you can refer to properties by name, like myObject["someProperty"].
Using that, you can iterate over properties if they follow some naming scheme, so for example:
for (var i:int = 1; i <= 15; i ++)
interludes.interludeIntro["interludeBegin" + i].alpha = 0;
That iterates over interludes.interludeIntro.interludeBegin1 through ...15 and sets their alpha properties to 0.
When you do that:
interludes.interludeIntro.alpha = 0;
you turn the movie clip and all its children invisible.
So later when you do that:
interludes.interludeIntro.interludeBegin1.alpha = 1;
You make the movie clip visible, but since its parent is still invisible, you don't see anything. The solution is to loop through the movie clips and make each of them invisible/visible.
// Keep the parent visible at all time
interludes.interludeIntro.alpha = 1;
for (var i:int = 0; i < textArray.length; i++) {
textArray[i].alpha = 0;
}
// Now this will work:
interludes.interludeIntro.interludeBegin1.alpha = 1;

Resources