support formmethod
This commit is contained in:
Родитель
c1390194e9
Коммит
bbe8bab175
74
index.js
74
index.js
|
@ -154,6 +154,32 @@ function isConnected(element) {
|
|||
return element.isConnected || document.body.contains(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Event} event
|
||||
*/
|
||||
function findFormSubmitter(event) {
|
||||
if (event.submitter) {
|
||||
return event.submitter;
|
||||
}
|
||||
|
||||
var form = event.target;
|
||||
if (!(form instanceof HTMLFormElement)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var submitter = dialogPolyfill.formSubmitter;
|
||||
if (!submitter) {
|
||||
var target = event.target;
|
||||
var root = ('getRootNode' in target && target.getRootNode() || document);
|
||||
submitter = root.activeElement;
|
||||
}
|
||||
|
||||
if (submitter.form !== form) {
|
||||
return null;
|
||||
}
|
||||
return submitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Event} event
|
||||
*/
|
||||
|
@ -162,32 +188,28 @@ function maybeHandleSubmit(event) {
|
|||
return;
|
||||
}
|
||||
var form = /** @type {!HTMLFormElement} */ (event.target);
|
||||
if (!isFormMethodDialog(form)) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
// We'd have a value if we clicked on an imagemap.
|
||||
var value = dialogPolyfill.useValue;
|
||||
var submitter = dialogPolyfill.formSubmitter || event.submitter;
|
||||
if (!value) {
|
||||
if (!submitter) {
|
||||
var root = ('getRootNode' in form && form.getRootNode() || document);
|
||||
var activeElement = root.activeElement;
|
||||
if (activeElement) {
|
||||
submitter = event.submitter = activeElement;
|
||||
}
|
||||
}
|
||||
if (submitter) {
|
||||
value = submitter.value;
|
||||
}
|
||||
var submitter = findFormSubmitter(event);
|
||||
if (value === null && submitter) {
|
||||
value = submitter.value;
|
||||
}
|
||||
|
||||
const dialog = findNearestDialog(form);
|
||||
// There should always be a dialog as this handler is added specifically on them, but check just
|
||||
// in case.
|
||||
var dialog = findNearestDialog(form);
|
||||
if (!dialog) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prefer formmethod on the button.
|
||||
var formmethod = submitter && submitter.getAttribute('formmethod') || form.getAttribute('method');
|
||||
if (formmethod !== 'dialog') {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
if (submitter) {
|
||||
dialog.close(value);
|
||||
} else {
|
||||
|
@ -795,6 +817,24 @@ if (window.HTMLDialogElement === undefined) {
|
|||
|
||||
}, false);
|
||||
|
||||
/**
|
||||
* Global 'submit' handler. This handles submits of `method="dialog"` which are invalid, i.e.,
|
||||
* outside a dialog. They get prevented.
|
||||
*/
|
||||
document.addEventListener('submit', function(ev) {
|
||||
var form = ev.target;
|
||||
var dialog = findNearestDialog(form);
|
||||
if (dialog) {
|
||||
return; // ignore, handle there
|
||||
}
|
||||
|
||||
var submitter = findFormSubmitter(ev);
|
||||
var formmethod = submitter && submitter.getAttribute('formmethod') || form.getAttribute('method');
|
||||
if (formmethod === 'dialog') {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Replace the native HTMLFormElement.submit() method, as it won't fire the
|
||||
* submit event and give us a chance to respond.
|
||||
|
|
69
suite.js
69
suite.js
|
@ -14,7 +14,6 @@
|
|||
* the License.
|
||||
*/
|
||||
|
||||
|
||||
void function() {
|
||||
|
||||
/**
|
||||
|
@ -789,7 +788,10 @@ void function() {
|
|||
dialog.showModal();
|
||||
|
||||
iframe.addEventListener('load', function() {
|
||||
assert.fail('should not load a new page');
|
||||
var href = iframe.contentWindow.location.href;
|
||||
if (href !== 'about:blank') {
|
||||
assert.fail('should not load a new page: ' + href);
|
||||
}
|
||||
});
|
||||
button.click();
|
||||
|
||||
|
@ -801,6 +803,69 @@ void function() {
|
|||
done();
|
||||
}, 50);
|
||||
});
|
||||
test('form submit with formmethod', function(done) {
|
||||
const iframeName = 'formmethod_test_frame';
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('name', iframeName);
|
||||
document.body.append(iframe);
|
||||
cleanup(iframe);
|
||||
|
||||
var form = document.createElement('form');
|
||||
form.setAttribute('method', 'dialog');
|
||||
form.setAttribute('target', iframeName);
|
||||
form.setAttribute('action', '/test-invalid.html');
|
||||
dialog.append(form);
|
||||
dialog.show();
|
||||
|
||||
var button = document.createElement('button');
|
||||
button.setAttribute('formmethod', 'get');
|
||||
form.append(button);
|
||||
button.value = '123';
|
||||
button.textContent = 'Long button';
|
||||
|
||||
var timeout = window.setTimeout(function() {
|
||||
assert.fail('page should load (form submit with formmethod)');
|
||||
}, 500);
|
||||
iframe.addEventListener('load', function() {
|
||||
window.clearTimeout(timeout);
|
||||
assert.isTrue(dialog.open);
|
||||
done();
|
||||
});
|
||||
button.click();
|
||||
});
|
||||
test('form method="dialog" prevented outside dialog', function(done) {
|
||||
const iframeName = 'outside_dialog_test';
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('name', iframeName);
|
||||
document.body.append(iframe);
|
||||
cleanup(iframe);
|
||||
|
||||
var form = document.createElement('form');
|
||||
form.setAttribute('method', 'dialog');
|
||||
form.setAttribute('target', iframeName);
|
||||
form.setAttribute('action', '/test-invalid.html');
|
||||
document.body.append(form);
|
||||
cleanup(form);
|
||||
|
||||
iframe.addEventListener('load', function() {
|
||||
if (iframe.contentWindow.location.href !== 'about:blank') {
|
||||
assert.fail('should not load a new page: ' + iframe.contentWindow.location.href);
|
||||
}
|
||||
});
|
||||
|
||||
form.submit();
|
||||
|
||||
// Try with an actual button, too.
|
||||
var button = document.createElement('button');
|
||||
form.append(button);
|
||||
button.click();
|
||||
|
||||
var timeout = window.setTimeout(function() {
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
suite('order', function() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче