Search code examples
javascriptfunctionloopsforeachsummernote

How to use JavaScript in a loop


I have this javascript

<script>
    $(document).ready(function() {
        $('.summernote1').summernote({
            placeholder: 'start typing',
            lang: 'en-GB',
            height: 300, // set editor height
            minHeight: null, // set minimum height of editor
            maxHeight: null, // set maximum height of editor
            focus: true, // set focus to editable area after initializing summernote
            callbacks: {
                onImageUpload: function(files) {
                    for (var i = 0; i < files.length; i++) {
                        send(files[i]);
                    }
                }
            }
        });
    });

    function send(file) {
        var xhttp;
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                response = JSON.parse(this.responseText);
                const urls = response.url;
                urls.forEach(imgurls);
                function imgurls(item) {
                    $('.summernote1').summernote('insertImage', item);
                }
            }
        };
        var data = new FormData();
        data.append('files[]', file);
        xhttp.open("POST", "/admin/ans-img-upload", true);
        xhttp.send(data);
    }

//second one

  $(document).ready(function() {
            $('.summernote2').summernote({
                placeholder: 'start typing',
                lang: 'en-GB',
                height: 300, // set editor height
                minHeight: null, // set minimum height of editor
                maxHeight: null, // set maximum height of editor
                focus: true, // set focus to editable area after initializing summernote
                callbacks: {
                    onImageUpload: function(files) {
                        for (var i = 0; i < files.length; i++) {
                            send(files[i]);
                        }
                    }
                }
            });
        });
    
        function send(file) {
            var xhttp;
            xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                    response = JSON.parse(this.responseText);
                    const urls = response.url;
                    urls.forEach(imgurls);
                    function imgurls(item) {
                        $('.summernote2').summernote('insertImage', item);
                    }
                }
            };
            var data = new FormData();
            data.append('files[]', file);
            xhttp.open("POST", "/admin/ans-img-upload", true);
            xhttp.send(data);
        }
    </script>

Then I have this html code

  <textarea class="form-control summernote1" id="summernote1" name="af_options[]"></textarea>

  <textarea class="form-control summernote2" id="summernote2" name="af_options[]"></textarea>

Now if I want to upload image in the summernote1, the image will be inserted in the last textarea which is summernote2.

Please how can I resolve this issue and is there anyway I can use 1 javascript code in all the textarea instead of repeating the javascript code because I have a foreach that loops a multiple textarea.

please help

Thanks for the solution....

Now how can I append more field... I have the code below but it is not working with the image insert

function add_more_additional_field() {

        $('#additional_options').append(
            '<textarea class="summernote" id="summernote" name="af_options[]" placeholder="Start typing the answers here"></textarea>'
        );

        $(document).ready(function() {
            $([...document.querySelectorAll('#additional_options .summernote')].pop()).summernote();
        });

    }

 

Solution

  • The second definition of function send(file) is over-writing the first one.

    You should only have one definition of send and add a second parameter to include the correct textarea.

    function send(file, $el) {
        var xhttp;
        xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                response = JSON.parse(this.responseText);
                const urls = response.url;
                urls.forEach(imgurls);
                function imgurls(item) {
                    // Use the passed textarea instead of a hard-coded value
                    $el.summernote('insertImage', item);
                }
            }
        };
        var data = new FormData();
        data.append('files[]', file);
        xhttp.open("POST", "/admin/ans-img-upload", true);
        xhttp.send(data);
    }
    

    To take advantage of this you will also need to update your document.ready callbacks. You won't be able to change the parameters of the onImageUpload callback so you will need to "embed" the correct element. There are a couple of ways to do this but I prefer creating a closure around a variable referencing the correct element as it will make it easy to refactor later.

    $(document).ready(function() {
        $('.summernote1').summernote({
            placeholder: 'start typing',
            lang: 'en-GB',
            height: 300, // set editor height
            minHeight: null, // set minimum height of editor
            maxHeight: null, // set maximum height of editor
            focus: true, // set focus to editable area after initializing summernote
            callbacks: {
                onImageUpload: (() => {
                    let $el = $('.summernote1');
                    return function(files) {
                        for (var i = 0; i < files.length; i++) {
                            send(files[i], $el);
                        }
                    };
               })()
            }
        });
    });
    

    This creates an IIFE that forms a closure around $el and passes this to send() when the onImageUpload callback is triggered.

    You could do the same for .summernote2 in your other document.ready for .summernote2

    There is probably more refactoring that could be done to reduce the duplication of code even further.