Filling a hypeDocument.customData array efficiently

I'm building a jigsaw-puzzle based Hype. The code works, but looking back at it I can't help feeling that a really proficient JavaScripter would have written far fewer lines. And this bugs me. Here is one example. I'm filling a global customData property called dropPlaces with the initial (x,y) positions of the 24 jigsaw pieces, arranged by rows and columns, having already stored the elementIDs of those pieces in another customData property called pieces, also arranged in rows and columns. Here's my code for this bit. As you can see, it looks massively repetitive and seems to be crying out for some sort of for loop, but I can't think of a suitable syntax. Is there one?

hypeDocument.customData.dropPlaces = [
[{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][1],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][1],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][2],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][2],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][3],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][3],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][4],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][4],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][5],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][5],'top')}],
[{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][0],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][0],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][1],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][1],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][2],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][2],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][3],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][3],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][4],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][4],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][5],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][5],'top')}],
[{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][0],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][0],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][1],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][1],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][2],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][2],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][3],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][3],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][4],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][4],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][5],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][5],'top')}],
[{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][0],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][0],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][1],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][1],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][2],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][2],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][3],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][3],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][4],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][4],'top')},
{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][5],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][5],'top')}]
];

Thanks, guys.

Heh, can you wait a month?

https://photics.com/free-template-tuesday-33-tumult-hype-jigsaw/
That's scheduled to be released on April 21, 2020.

Chapter #50 of A Book About Hype is dedicated to creating a Jigsaw puzzle.

Video preview — 📘 A Book About Hype (2020 Print Edition) - #31 by Photics

1 Like

If the above code does what you want it to, then it is perfect, but maybe if you can give us more a visual impression of how this works and what the purpose of the code is we can help out.

I did notice that the forum messed up your code since you didn't place it within a code block:

hypeDocument.customData.dropPlaces = [
    [{
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][1], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][1], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][2], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][2], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][3], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][3], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][4], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][4], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][5], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][5], 'top')
        }
    ],
    [{
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][0], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][0], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][1], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][1], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][2], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][2], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][3], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][3], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][4], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][4], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][5], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[1][5], 'top')
        }
    ],
    [{
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][0], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][0], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][1], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][1], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][2], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][2], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][3], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][3], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][4], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][4], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][5], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[2][5], 'top')
        }
    ],
    [{
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][0], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][0], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][1], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][1], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][2], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][2], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][3], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][3], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][4], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][4], 'top')
        },
        {
            x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][5], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[3][5], 'top')
        }
    ]
];

This doesn't really help?

If he can't wait, I could send it to him :wink:

Thanks for that. Looks very interesting, but I’m not really looking for guidance on coding a jigsaw right now (I’ve got that working) but rather on how to fill complicated repetitive array-like properties.

...but that's what it does. :man_shrugging:t2:

OK, Daniel. I've got a two-dimensional array of elementIDs, corresponding to the rows [i] and columns [j] of the jigsaw pieces. That is accessed via something like

elementID = hypeDocument.customData.pieces[i][j];

I want to create a property/array within customData called dropPlaces that holds the initial 'left' and 'top' properties of all these pieces (that I've called 'x' and 'y') so they can be accessed by something like

xValue = hypeDocument.customData.dropPlaces[i][j]["x"];

It's the initial filling of the dropPlaces property/array that is represented by the block of code in my original post. In a single statement I'm inserting 48 numbers (x and y values for 24 pieces) into dropPlaces. I've used the syntax

hypeDocument.customData.dropPlaces = [ ,,, ... ];

where each represents a row of data and contains {x:value1, y:value2}, {x:value3, y:value4} ...
and each x-y value-pair inside the { } for given piece is coded by something like

{x:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0],'left'),y:hypeDocument.getElementProperty(hypeDocument.customData.pieces[0][0],'top')},

So, dropPlaces is an indexed array of arrays, where each of those inner arrays is an array of two-element key:value pairs.

Yeah, it's complicated. I'm almost certain that I could have coded it better and different, but, in solving this problem, it has made me realise that I can't see a neat way to pack, in effect, a multi-dimensional array into a customData property. Just looking at the code in my original post (thanks for smartening it up, btw) it's just bulging with repetitive code and looks like its crying out for something like for .. each or what?

It's not a real problem, rather just something bugging me, so don't spend time on it if you can't see what I'm driving at.

Thanks anyway.

I don’t know about the data structure you are using given I’d need to know more context. But if you just want to construct it with fewer lines you can just loop.

hypeDocument.customData.dropPlaces = [];
for(var i = 0; i < 4; i++) {
	var arr = []; // unclear on a good name for this based on missing context, rename
	for(var j = 0; j < 6; j++) {
		arr.push({
			x: hypeDocument.getElementProperty(hypeDocument.customData.pieces[i][j], 'left'),
            y: hypeDocument.getElementProperty(hypeDocument.customData.pieces[i][j], 'top')
		});
	}
	hypeDocument.customData.dropPlaces.push(arr);
}

(I have not tested this code)

2 Likes

This looks promising, Jonathan. It’s the sort of thing I was looking for. I’ll give it a whirl. Thanks.

1 Like

It works, Jonathan! Brilliant. I’d forgotten about things like push and pop and shift. I don’t think I’ve ever used them. Doesn’t change the outcome (it all still works as before), but it saves a massive chunk of code so it looks much neater. The user may not see any difference, but I feel better, and that must be good.

Many thanks.

2 Likes

Looks like we got the same answer...

 window.pieces = document.getElementsByClassName("piece");
 window.starting = [];
 for (i = 0; i < pieces.length; i++) {
      var x = hypeDocument.getElementProperty(hypeDocument.getElementById(pieces[i].id), 'left');
      var y = hypeDocument.getElementProperty(hypeDocument.getElementById(pieces[i].id), 'top');
      starting.push([pieces[i].id, x, y]);
      hypeDocument.getElementById(pieces[i].id + "_hype_pat").childNodes[0].setAttribute("width", w);
      hypeDocument.getElementById(pieces[i].id + "_hype_pat").childNodes[0].setAttribute("height", h);

 }

The main differences are that you use the "hypeDocument.customData" API and that my pieces use vector shapes. Automatically selecting the pieces by class name is a little bit more involved.

But, it is most certainly is tested now. You can try it yourself...