Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fields breaking after Upgrade to JQuery 3.5.1

I have a table that is created using javascript based on what is put in a list. This works fine in Jquery 3.4, but when I upgrade to 3.5 I am seeing this break.

HTML

    <h5>Questions</h5>
    <table id="questionTable" class="table q">
        <thead>
        </thead>
        <tbody id="qTable"></tbody>
    </table>
    
    <div id="questionDiv">
        <input type="button" value="Add Question" onclick="AddNewQuestion()" class="btn btn-primary"/>
    </div>
    
    <hr />

<div id="questionDiv">
    <input type="submit" value="Submit" class="btn btn-primary" />
</div>

Javascript

 <script type="text/javascript">
    
            $(document).ready(function () {
                $(function () {
                    AddCurrentQuestions();
                });
            });
    
            var table = document.getElementById("qTable");
            var rowCount = table.rows.length;
            var counter = rowCount.length;
    
            function AddCurrentQuestions() {
    
                var status = @Html.Raw(Json.Encode(Model.isNull));
    
                if (status == false) {
    
                    @{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
                    var questionItems = JSON.parse('@Html.Raw(Json.Encode(@Model.QuestionList))');
    
                    for (var i = 0; i < questionItems.length - 1; i++) {
                        var qItem = questionItems[i];
                        var questionDetail = qItem.Question;
    
                        //Create fields
                        var qTextCell = "<td><textarea id='QuestionList_" + i + "_Question' name='QuestionList[" + i + "].Question' class='Questions' /></td>";
                        var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + i + "' /></td>";
                        var removeCell = "<td align='center'><input id='btnDelLine'" + i + "type='button' value='Remove' onclick=\"removeRow('" + i + "')\" class='btn btn-primary' /></td>";
    
                        var newRow = "<tr id='qLineItem" + i + "'>" + indexCell + qTextCell + removeCell + "</tr>";
    
                        //Add row to table
                        $('#qTable').append(newRow);
    
                        //Add Values
                        $('#QuestionList_' + i + "_Question").val(questionDetail)
    
    
                        counter = i;
                    };
                } else {
                    counter = 0;
                    AddNewQuestion();
                }
            };
    
            function AddNewQuestion() {
                @{ Model.QuestionList.Add(new Performance_Planning.ViewModel.QuestionViewModel.Questions());}
    
                counter++;
    
                //Create field
                var indexCell = "<td style='display:none'> <input name='QuestionList.Index' type='hidden' value='" + counter + "' /></td>";
                var qTextCell = "<td><textarea id='QuestionList_" + counter + "_Question' name='QuestionList[" + counter + "].Question' class='Questions' /></td>";
                var removeCell = "<td align='center'><input id='btnDelLine'" + counter + "type='button' value='Remove' onclick=\"removeRow('" + counter + "')\" class='btn btn-primary' /></td>";
    
                var newRow = "<tr id='qLineItem" + counter + "'>" + indexCell + qTextCell + removeCell + "</tr>";
    
                $('#qTable').append(newRow);
            };
    
            function removeRow(id) {
                var rowId = "qLineItem" + id;
                var row = document.getElementById(rowId);
                row.parentNode.removeChild(row);
            };
    
        </script>
        
        } 

What I end up seeing is that the remove button is treated as text in 3.5.1 but this doesn't occur with 3.4. I am unsure how to solve this issue or if I will need to figure out another way to write this page.

When I view the webpage and inspect the field I see it do the following:

<textarea id="QuestionList_0_Question" name="QuestionList[0].Question" class="Questions">
  "</td><td align='center'><input id='btnDelLine'0type='button' value='Remove' onclick="removeRow('0')" class='btn btn-primary' /></td></tr></tbody></table>"
like image 257
Rygar Avatar asked Jan 24 '23 21:01

Rygar


1 Answers

The textarea element should have a separate close tag. It is not allowed to self-close. So this is not valid HTML:

<textarea />

But this is:

<textarea></textarea>

Apparently, jQuery 3.5 is more strict in this. An inspection of the 3.5 changelog reveals that this is a consequence of the security fix they applied:

The main change in this release is a security fix, and it’s possible you will need to change your own code to adapt. Here’s why: jQuery used a regex in its jQuery.htmlPrefilter method to ensure that all closing tags were XHTML-compliant when passed to methods. For example, this prefilter ensured that a call like jQuery("<div class='hot' />") is actually converted to jQuery("<div class='hot'></div>"). Recently, an issue was reported that demonstrated the regex could introduce a cross-site scripting (XSS) vulnerability.

The HTML parser in jQuery <= 3.4.1 usually did the right thing, but there were edge cases where parsing would have unintended consequences. The jQuery team agreed it was necessary to fix this in a minor release, even though some code relies on the previous behavior and may break. The jQuery.htmlPrefilter function does not use a regex in 3.5.0 and passes the string through unchanged.

One can see how before 3.5, jQuery would actually change <textarea /> to <textarea></textarea> on the fly, thereby fixing the error you made. But now with version 3.5 jQuery no longer does that, and so your HTML remains invalid, leading to an unintended rendering where everything after <textarea /> ends up as content to that text area element.

like image 91
trincot Avatar answered Feb 01 '23 06:02

trincot