flexxui / pscript

Python to JavaScript compiler
http://pscript.readthedocs.io
BSD 2-Clause "Simplified" License
256 stars 25 forks source link

Coerce NodeList into Array to make it iterable #45

Open Konubinix opened 4 years ago

Konubinix commented 4 years ago

I don't know whether this is the good place to make this request.

Using flexx to create an application, I from time to time need to find all the elements inside a node. I wish I could write the following for element in self.node.querySelectorAll("a"): .... Unfortunately, this iteration assigns the indexes into element (1, 2, 3...), then I need to write the code as

links = self.node.querySelectorAll("a")
for index in links:
     do something with links[index]

This does not feel very pythonic.

IIUC, the transpiling happens in Parser2._make_iterable, the iteration is converted in

    stub1_seq = this.node.querySelectorAll("a");
    if ((typeof stub1_seq === "object") && (!Array.isArray(stub1_seq))) { stub1_seq = Object.keys(stub1_seq);}
    for (stub2_itr = 0; stub2_itr < stub1_seq.length; stub2_itr += 1) {
      do something with stub1_seq[stub2_itr];
    }

I don't know how NodeList could be taken into account here, I guess that ideally, the condition isArray could be extended to find out other known types that can coerce to Array if(NodeList.prototype.isPrototypeOf(stub1_seq)){stub1_seq = Array.from(stub1_seq);}. I don't know of a more generic way of doing. I python, I would do something like :

try:
    Array.from(stub1_seq)
except ValueError:
    stub1_seq = fallback
almarklein commented 4 years ago

Good question! The trouble with node-list objects is that they do not behave properly as arrays and their behavior may depend per browser. Auto-converting to an array is an option, but adding a test at every for-loop to check whether the iterate is a nodelist is expensive ... That's why it's as it is now.

I could imagine that a user could explicitly cast it to a list somehow. Maybe just with list()? In PScript we'd then have to do the check when list() is called.