0

im trying to loop through my HTML Collections as

const nodeItems = document.getElementsByClassName('image-inside')

I tried to loop like

for(let node of nodeItems) {
     console.log('im node ', node)                
     console.log('im node url' , node.src)
     return writer.createAttributeElement( 'img', {
            src: node.src,
            style: `width:${node.style.width};
                    height:${node.style.height};`,
                    class: 'image-inside'
     } , { priority: 7 } )
}

but only the first node were logged TWICE not the second one. enter image description here Any thoughts guys? Any help would be very appreciated. Thanks for reading

UPDATE: So i have tried to convert to array. which is okay the logging is good. But the prototype of it is Array, what i should return is Nn ( due to writer.createAttributeElement() ). I dont even think i can achieve this temp[0] The array

UPDATE2: So currently the array is loaded correctly now enter image description here But when get the data from CKEditor5 through editor.getData() its still taking the last element enter image description here

Still thank you guys so much for reading

  • 3
    `return` returns from your function, the loop ends there. – tevemadar Dec 30 '20 at 10:41
  • I'd think it would break the code since a return statement isn't valid in a for...of statement. – Kitanga Nday Dec 30 '20 at 10:43
  • Try removing the `return` inside the loop, allowing all items to be targeted – Teknotica Dec 30 '20 at 10:44
  • @KitangaNday it's perfectly valid code, you can return from inside a loop. – tevemadar Dec 30 '20 at 10:45
  • Press F12 and give it a try. You'll get a syntax error. It isn't a loop it's a for..of loop , this should be breaking – Kitanga Nday Dec 30 '20 at 10:47
  • @tevemadar then how can i return all value inside the loop, if the loop is breaking why is it logging twice hm? – mrpuzzy2010 Dec 30 '20 at 10:48
  • I cant do array and push element, same for the HTML Collections – mrpuzzy2010 Dec 30 '20 at 10:50
  • You can convert the `nodeItems` list to an array using `Array.from` and then use `map` instead of `for..of` loop. – Kitanga Nday Dec 30 '20 at 10:50
  • I can post an answer to show you btw – Kitanga Nday Dec 30 '20 at 10:51
  • @KitangaNday `console.log((function(){for(let i of [1,2,3])return i;})());`. Also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of#Closing_iterators : *In `for...of` loops, abrupt iteration termination can be caused by `break`, `throw` or `return`.*. You had a syntax error, but that wasn't the `return`. – tevemadar Dec 30 '20 at 11:00
  • @mrpuzzy2010: you could describe what you are trying to do, because it's likely doable, but not necessarily this way. – tevemadar Dec 30 '20 at 11:03
  • @tevemadar the reason that `return` is working is because it's in a function. Run it without being wrapped in a function and it fails. The for..of loop isn't returning, the function is. – Kitanga Nday Dec 30 '20 at 11:04
  • @KitangaNday give it up, perhaps. It was obvious that this code is in a function. – tevemadar Dec 30 '20 at 11:05
  • i have provided some more picture in update. Thank you guys for answering me. – mrpuzzy2010 Dec 30 '20 at 11:06
  • @tevemadar no, not really. Haven't touched react/vue code in a while. But yea, good to learn this. – Kitanga Nday Dec 30 '20 at 11:08
  • @KitangaNday the question was not "why this is syntax error", but "why it runs only once". That's how it's obvious that the `return` was not in top-level code. – tevemadar Dec 30 '20 at 11:09
  • @mrpuzzy2010 what exactly are you trying to achieve, is it that you want whatever the writer creates to be stored somewhere, or do you just want to use the writer (as in, don't store anything). If that is true, then remove `map` and put `forEach`. – Kitanga Nday Dec 30 '20 at 11:10
  • @tevemadar I know that much I read the question, my question was how was this running, never knew a return statement could be used inside of a for..of/in loop and it returns the function itself. It's like having a return inside of a switch statement and that returns for the function that holds it. Doesn't make any sense. Now I'm curious if that would work as well XD – Kitanga Nday Dec 30 '20 at 11:11
  • I have tried forEach but still doesnt work. `writer` is an engine of CKEditor5, https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_writer-Writer.html – mrpuzzy2010 Dec 30 '20 at 11:15
  • Yea, i just saw your update to the question, it shouldn't work. You want the type to be the same as prototype. Just out of curiosity, why do you want the type to be Nn? – Kitanga Nday Dec 30 '20 at 11:25
  • @KitangaNday array methods like `find()`, `some()`, `every()` could all be implemented via returning an item/true/false in the middle of an iteration. Returning from inside a `switch` is perfectly viable too, for example if you write a function for encoding control characters to `\t`, `\n`, `\r` and the like, you could write `switch(c){case '\t':return '\\t';case '\n':return '\\n';case '\r':return '\\r';}return c;` – tevemadar Dec 30 '20 at 12:08
  • @tevemadar I know that about the Array's methods but for..of returning a value for an array, I never thought that would work. I thought only if..else statements were given that privilege. Yea I already tested to check if you can do the same with switch, which is funny cause I tested this and it never worked (obviously because it wasn't in a function). But yea I know now, more tools for the arsenal. – Kitanga Nday Dec 30 '20 at 12:15
  • @tevemadar issue now is that the OP now wants to extend this api's Element class without using any of the prescribed methods. So now I'm thinking of rewriting the code for him so that he uses Element, but then that's kind of what the methods like `createAttributeElement` are designed for. So I don't know really how to answer this. – Kitanga Nday Dec 30 '20 at 12:17

2 Answers2

3

You are breaking loop with return stmt.

See another answer https://stackoverflow.com/a/11714515/1205171

Oleg Andreyev
  • 647
  • 5
  • 20
  • Then why the first node logging twice? – mrpuzzy2010 Dec 30 '20 at 10:51
  • You have two elements? But I think it’s different topic. You need to provide you HTML code at least :) – Oleg Andreyev Dec 30 '20 at 11:00
  • I don’t know what your `writer` does, but be aware that HTMLCollection is live and mutable https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection – Oleg Andreyev Dec 30 '20 at 11:02
  • Thank you for your answer, the writer is from an engine in ckeditor5 https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_view_writer-Writer.html – mrpuzzy2010 Dec 30 '20 at 11:04
  • @mrpuzzy2010 it may run twice perhaps because you are invoking the function itself again? – tevemadar Dec 30 '20 at 11:07
  • I have no clue how to run it twice in these low level code ` conversion.for('dataDowncast').elementToElement( { model: 'contentImage', view: renderDowncastElement() } )` – mrpuzzy2010 Dec 30 '20 at 11:11
2

EDIT: Use EmptyElement since this is what you end up creating if you extend Element class

As mentioned in the comments you should remove the return statement.

Maybe convert it to an array first and remap the array like so:

let nodeItems = Array.from(document.getElementsByClassName('image-inside'));

nodeItems = nodeItems.map(function(node) {
     console.log('im node ', node)                
     console.log('im node url' , node.src)
     // Instead of creating your own element from Element (i.e. Nn), why not use Empty Element class instead. It will be what you create anyways I'm guessing
     return writer.createEmptyElement( 'img', {
            src: node.src,
            style: `width:${node.style.width};
                    height:${node.style.height};`,
                    class: 'image-inside'
     } , { priority: 7 } )
});
Kitanga Nday
  • 3,517
  • 2
  • 17
  • 29
  • Ive tried like you and still didnt achieve what i want due to the writer. Thank you – mrpuzzy2010 Dec 30 '20 at 11:05
  • @mrpuzzy2010 since you are getting images why not use `createEmptyElement` since it's used for elements that don't have children (e.g. img elements). Check my answer. – Kitanga Nday Dec 30 '20 at 12:19
  • 1
    Hm, the array is loading correctly but when its come to get the data from the editor its still loading only the last element. Check my update, i have capped some more picture. Thank you sir – mrpuzzy2010 Dec 30 '20 at 13:11
  • @mrpuzzy2010 I'm getting confused each time you update the question , but it's fine, have you figured it out? What exactly are you trying to get to. That picture shows two image elements, so what do you mean by it's not taking the second one, do you mean it's not getting into the writer instance – Kitanga Nday Dec 30 '20 at 15:54
  • @mrpuzzy2010 OK, I see, it's still only showing the the first image, is it possible if you can share your updated code again? – Kitanga Nday Dec 30 '20 at 16:08
  • 1
    I have solved the problem, its due to my lack of knowledge about conversion between model and view of CKEditor. I can show you the link of github to my custom build, u want it? – mrpuzzy2010 Dec 31 '20 at 10:11
  • 1
    @mrpuzzy2010 thanks man, but no. I'm just happy that you resolved it. – Kitanga Nday Dec 31 '20 at 17:29