Django, Javascript: Form injected into DOM via javascript innerHtml crashes google chrome tab on submit. Works in IE

僤鯓⒐⒋嵵緔 提交于 2020-01-13 16:23:29

问题


I have written a bookmarklet that receives a Django form and inserts it into the Dom via the innerHtml of a new div element created via javascript and appended to the body of an existing html document. The first submit is an ajax request (works fine), if the form is rejected by Django due to an unknown user, the submit function is unbound from ajax and resubmitted without ajax to a pop-up window to authenticate the user without CORS. The process works flawlessly in IE but crashes the chrome tab when the submit button is clicked.

Tests: I thought maybe it was the initial ajax submit that was causing the issue. However, if i use the same process without ajax upon injection, submit fails as well. If i copy the html code from the browser after my injection is complete and create a new html document then open it in chrome everything works fine. Also if i delete the div containing the form fields prior to injection the submit button works. This leads me to believe that it has something to do with injecting the form after the Dom on the existing page has loaded. Is there a way to reload the Dom without a page refresh or force the innerHtml to properly register in the Dom on injection?

No console errors, just an aww, snap! Somethng went wrong while displaying this webpage.

To replicate the issue follow these steps: (I am on windows 8 with Chrome Version 23.0.1271.64 m)
(step 1) goto an immage url: itsblackcurrent.com/wp-content/uploads/2012/07/what-hi.png
(step 2) go to chrome console and enter the following code:

o = document.createElement("div");
o.setAttribute("id", "overlay");
o.innerHTML = '<div class="modal fade" id="new-pin"><div class="modal-header"><h3>New Pin</h3></div><form action="" enctype="multipart/form-data" method="get" id="ajaxform" name="pin_form" class="form-horizontal"><div class="modal-body"><div id="div_id_url" class="control-group"><label class="control-label" for="id_url">URL</label><div class="controls"><input type="text" name="url" id="id_url" /></div></div><div id="div_id_image" class="control-group"><label class="control-label" for="id_image">or Upload</label><div class="controls"><input type="file" name="image" id="id_image" /></div></div><div id="div_id_description" class="control-group"><label class="control-label" for="id_description">Description</label><div class="controls"><textarea id="id_description" rows="10" cols="40" name="description"></textarea></div></div><div id="div_id_tags" class="control-group"><label class="control-label" for="id_tags">Tags</label><div class="controls"><input type="text" name="tags" id="id_tags" /></div></div></div><div class="modal-footer"><div class="messageContainer"></div><button id="btnsubmit" type="submit" class="btn btn-primary">Submit</button><a id="cancel" onclick="removeOverlay()" data-toggle="modal" class="btn">Cancel</a></div></form></div>'; 
document.body.appendChild(o);

(step 3) Click submit and see Chrome crash!

(step 4) If the exact same code is loaded prior to DOM loading it works. Paste the following into a new text document and save as .html.

<body>
<script>
Copy and paste all the code from step 2 here
</script>
</body>

(step 5) Open the .html file with chrome and submit will not crash.


回答1:


I figured out how to prevent the crash in chrome and also works in IE! So we can call this a cross browser way to inject a form after the dom loads without causing a crash in chrome.

$('#form').submit(function () {
    formData = $("#form").serialize()
    window.location = "http:url.to.submitdata/?"+formData;
    return false;
});

First we have to create a custom submit function by capturing the submit() with jQuery. Then serialize the form data, and manually append the form data to the url where you want to submit the form. Finally & most importantly return false stops the normal submit function and prevents chrome from crashing!

IF YOU FOLLOWED THE INSTRUCTIONS TO REPLICATE THE ISSUE IN MY ORIGINAL QUESTION, HERE IS HOW YOU CAN TEST THE WORKAROUND FOR CHROME:

(step 6) complete steps 1 & 2 from my original question.
(step 7) enter the following code in the chrome console:

s = document.createElement("script")
s.src = src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"
document.body.appendChild(s);
jQueryCheckLoad();

function jQueryCheckLoad() {
    if( window.$) {
        console.warn("jquery is ready");
        jqReady();
    } else {
        window.setTimeout( jQueryCheckLoad, 10 );
    }
}
function jqReady() {
    $( '#ajaxform' ).submit(function () {
        formData = $( "#ajaxform" ).serialize()
        window.location = "http://url.to.submitdata/?"+formData;
        return false;
    });
}

(step 8) You will see "jQuery Ready" warning in the console, then click submit and BOOM! NO CRASH!

All we did was prevent the normal submit() from firing by creating a custom jQuery submit() that returns false. First we injected jQuery, then used jQueryCheckLoad() to wait for jQuery to be ready. Then bound our jQuery submit().

*If anybody has any idea what is causing the crash in chrome i would still love to know. The strangest part is that when i first did the unbind and submitted the form it worked very consistently for about 2 hours of testing then just mysteriously started crashing constantly. There is a small chance i modified my injection order and did not clear the cache on the bookmarklet, and when i did it started crashing. This leads me to believe that there is a way to successfully reload the DOM without a page refresh.



来源:https://stackoverflow.com/questions/13363111/django-javascript-form-injected-into-dom-via-javascript-innerhtml-crashes-goog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!