Zim loop problem

the data can't be loop in ZIM.loop,but can loop in for(key in data) why?
iframeRoot

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>iframe root</title>

    <script type="module">
            var iframe = document.createElement('iframe');
            iframe.style = `overflow:hidden;position: absolute;width:1000px;height:600px;border:medium none;top:50%;left:50%;transform:translate(-50%,-50%) ;z-index:1`
            iframe.src = 'iframeChild_v0.html';
            iframe.onload = function () {
                var mapData={'key0':{arr:[1,2,3],text:'string0'},'key1':{arr:[4,5,6],text:'string1'},'key2':{arr:[7,8,9],text:'string2'}}
                var winEvt=new CustomEvent(`sendToPage`, { detail:mapData  })
                window.dispatchEvent(winEvt)
            };
            document.body.appendChild(iframe);

    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />
</head>
<body>
</body>
</html>

iframePage

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>iframe child</title>

    <script type="module">
        import zim from "https://zimjs.org/cdn/018/zim";
        window.parent.addEventListener(`sendToPage`, function (winEvt) {
            var data=winEvt.detail
            zim.zogb('0---',data)
            //iframe  zim.loop bug
            zim.loop(data, function (key, value) {
                zim.zogr(key,value)
            })
            for (var key in data) {
                zim.zogp(key,data[`${key}`])
            }
        })

    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />
</head>

<body>
</body>

</html>

the data can't be loop in ZIM.loop,but can loop in for(key in data)

It worked for me in a single file. Maybe it is a security issue across pages? Maybe try window.postMessage()?

Make sure in your situation it is still an object and not a string or something.

message event data can be loop both ZIM.loop and for(var key in data)
customEvent data can't loop in ZIM.loop but can loop in for(var key in data)
IframeRoot file

<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <title>ZimTest</title>

    <script type="module">
        import zim from "https://zimjs.org/cdn/018/zim";
        window.addEventListener("addIframeEvent",function(evt){
                var width = evt.detail.width ? evt.detail.width : 720;
                var height = evt.detail.height ? evt.detail.height : 1280;
                var iframe =  document.createElement('iframe');
                iframe.style = `overflow:hidden;position: absolute;width:${width * window.innerHeight / 1280}px;height:${height * window.innerHeight / 1280}px;border:medium none;top:50%;left:50%;transform:translate(-50%,-50%) ;z-index:${evt.detail.zIndex}`
                iframe.src = evt.detail.path+evt.detail.name;
                iframe.onload = function() {
                    if(evt.detail.method=='sendMessage'){
                        zogr('send postMessage data in iframe root')
                        var data=evt.detail.initData
                        iframe.contentWindow.postMessage(data);
                    }else if(evt.detail.method=='sendEvent'){
                        zogr('dispatchEvent data in iframe root')
                        var event_data=new CustomEvent('sendToPage',{detail:evt.detail})
                        iframe.contentWindow.dispatchEvent(event_data)
                    }
                };
                document.body.appendChild(iframe);
        })
        new Frame({scaling:'fit',width:1024,height:768, color:clear, outerColor:dark, ready:zimReady,align:'center'});
        function zimReady(F,S){
            var strArr=['a','b','c']
            zogr('IframeRoot data strArr=',strArr,typeof(strArr))
            loop(strArr,(item,i)=>{
                zogr('zim loop in IframeRoot data strArr--',item,i)
            })
            var btn0=new Button({label:'发送-Message',width:300}).center().mov(-200,0)
            .tap(function(){
                var event_zimRole=new CustomEvent("addIframeEvent",{detail:{name: `IframeChild_v1.html`,path: `/yanwenge.com/assets/debugWeb/three材质/`,
                    initData:strArr,method:'sendMessage',zIndex: -1}
                });
                window.dispatchEvent(event_zimRole)
            })
            var btn1=new Button({label:'发送-Event',width:300}).center().mov(200,0)
            .tap(function(){
                var event_zimRole=new CustomEvent("addIframeEvent",{detail:{name: `IframeChild_v1.html`,path: `/yanwenge.com/assets/debugWeb/three材质/`,
                    initData:strArr,method:'sendEvent',zIndex: -1}
                });
                window.dispatchEvent(event_zimRole)
            })


        }
    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />

</head>

<body>
</body>

</html>

Iframe Child file

<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <title>ZimTest</title>
    <script type="module">
       import zim from "https://zimjs.org/cdn/018/zim";
        window.addEventListener('sendToPage',function(winEvt){
            var data=winEvt.detail.initData
            zim.zogb(`data=${data}`,typeof(data))
            loop(data,(item,i)=>{
                zim.zogp('zim loop in IframeChild data--',item,i)
            })
            for (var key in data) {
                zim.zogo(key,data[`${key}`])
            }
        },false)
        window.addEventListener('message', function(winEvt) {
            var data = winEvt.data;//.initData;
            zim.zogb(`data=${data}`,typeof(data))
            loop(data,(item,i)=>{
                zim.zogp('zim loop in IframeChild data--',item,i)
            })
            for (var key in data) {
                zim.zogo(key,data[`${key}`])
            }
        }, false);
    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />

</head>

<body>
    <!-- canvas with id="myCanvas" is made by zim Frame -->
</body>

</html>

Strange... could be tainted data as ZIM is another file reading it. Not sure... is there anything you think we should do? @amihanya @pettis any thoughts?

Not exactly sure where the issue is with ZIM.loop or with JavaScript. But if I use JSON.stringify() and JSON.parse() it works no problems.

In my research I have found that if I compare the object from the mapdata.detail to it's literal object it returns false. zog(data == data_object); . So I wonder if something more is going on in JavaScript and the way ZIM.loop() works can't interpret the data correctly.

data_object = {
  "key0": {
    "arr": [
      1,
      2,
      3
    ],
    "text": "string0"
  },
  "key1": {
    "arr": [
      4,
      5,
      6
    ],
    "text": "string1"
  },
  "key2": {
    "arr": [
      7,
      8,
      9
    ],
    "text": "string2"
  }
}

Are you sure the data load? can you send zog (console.log) of the data before the loop?
I think its didn't load or didn't pass as Object.

Yes in their code they are doing it right here and it logs the data correctly.

...
zim.zogb('0---',data)
...

send print screen for the output.
you pass the data on post massage?

if you JSON.parse(data) instead of just data then it is obviously coming in as string rather than a real object... so that would be the solution.

I think we are fine with that... we don't need to make the loop JSON parse a string... I guess we could - just test with the DOCS - ZIM JavaScript Canvas Framework - Documentation that Ami provide us with at one point, I think... and use the result from there.

@Abstract No he is sending an object in his code.

...
    var mapData={'key0':{arr:[1,2,3],text:'string0'},'key1':{arr:[4,5,6],text:'string1'},'key2':{arr:[7,8,9],text:'string2'}}
    var winEvt=new CustomEvent(`sendToPage`, { detail:mapData  })
    window.dispatchEvent(winEvt)
...

I tested if I sent a string does it work which it does.

...
    var mapData={'key0':{arr:[1,2,3],text:'string0'},'key1':{arr:[4,5,6],text:'string1'},'key2':{arr:[7,8,9],text:'string2'}}
    var winEvt=new CustomEvent(`sendToPage`, { detail:JSON.stringify(mapData)  })
    window.dispatchEvent(winEvt)
...

I make a other test code.
main.html

<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <title>IframeRoot</title>

    <script >
        function sendMessage(){
            var iframe=document.getElementById('area')
            var data=['a','b','c']
            iframe.contentWindow.postMessage(data);
        }
        function sendCustomEvent(){
            var iframe=document.getElementById('area')
            var data=['a','b','c']
            var event=new CustomEvent('sendToPage',{detail:data})
            iframe.contentWindow.dispatchEvent(event)
        }
    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />

</head>

<body>
    <iframe id="area" src="child.html" style="width:100%;height:400px;"></iframe>
    <button onclick="sendMessage()" style="width:45%;color:#00a;">sendMessage ['a','b','c']</button>
    <button onclick="sendCustomEvent()" style="width:45%;color:#0a0;">sendCustomEvent ['a','b','c']</button>
</body>

</html>

child.html

<!doctype html>
<html>

<head>
    <meta charset="utf-8" />
    <title>ZimTest</title>
    <style>
        body {
        display: flex;
        justify-content: flex-start; /* 默认靠左对齐 */
        flex-wrap: wrap; /* 允许换行 */
        }
    </style>
    <script type="module">
        import zim from "https://zimjs.org/cdn/018/zim";
        window.addEventListener('message', function(winEvt) {
            var data = winEvt.data;
            var el=document.getElementById('area1')
            el.innerHTML+=`data=${data}<br>`
            el.innerHTML+=`data type ${typeof(data)}<br><br>`
            zim.loop(data,(item,i)=>{
                el.innerHTML+=`zim loop --${item}-${i}<br>`
            })
            for (var key in data) {
                el.innerHTML+=`for loop --${key}-${data[key]}<br>`
            }
        }, false);
        window.addEventListener('sendToPage',function(winEvt){
            var data=winEvt.detail
            var el=document.getElementById('area2')
            el.innerHTML+=`data=${data}<br>`
            el.innerHTML+=`data type ${typeof(data)}<br><br>`
            zim.loop(data,(item,i)=>{
                el.innerHTML+=`zim loop --${item}-${i}<br>`
            })
            for (var key in data) {
                el.innerHTML+=`for loop --${key}-${data[key]}<br>`
            }
        },false)
    </script>
    <meta name="viewport" content="width=device-width, user-scalable=no" />

</head>

<body>
    <div id="area1" style="color:#ff0;width:50%;height:100%;background-color: #004;"></div>
    <div id="area2" style="color:#f00;width:50%;height:100%;background-color: #040;"></div>
</body>

</html>

Okay - just testing it out. I see why.

There is an array being passed but obj.constructor === Array is false, for some reason. If I make an array with [1,2,3] or new Array(1,2,3) or even JSON.stringify() and JSON.parse() the array, its constructor is Array. But this comes out as false for some reason, even though the obj.constructor appears to be an array function.

We can change the test to be Array.isArray(obj) which reports it as an array.

This has been updated and patched in ZIM 018 - thanks for letting us know.