form-disabled-callback.html (5930B)
1 <!DOCTYPE html> 2 <title>formDisabledCallback, and :disabled :enabled pseudo classes</title> 3 <body> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/html/semantics/forms/form-submission-0/resources/targetted-form.js"></script> 7 <script> 8 class MyControl extends HTMLElement { 9 static get formAssociated() { return true; } 10 11 constructor() { 12 super(); 13 this.internals_ = this.attachInternals(); 14 this.internals_.setFormValue('my-control-value'); 15 this.disabledHistory_ = []; 16 } 17 18 formDisabledCallback(isDisabled) { 19 this.disabledHistory_.push(isDisabled); 20 } 21 disabledHistory() { 22 return this.disabledHistory_; 23 } 24 } 25 customElements.define('my-control', MyControl); 26 27 test(() => { 28 const control = new MyControl(); 29 assert_true(control.matches(':enabled')); 30 assert_false(control.matches(':disabled')); 31 32 control.setAttribute('disabled', ''); 33 assert_false(control.matches(':enabled')); 34 assert_true(control.matches(':disabled')); 35 36 control.removeAttribute('disabled', ''); 37 assert_true(control.matches(':enabled')); 38 assert_false(control.matches(':disabled')); 39 40 assert_array_equals(control.disabledHistory(), [true, false]); 41 }, 'Adding/removing disabled content attribute'); 42 43 test(() => { 44 const container = document.createElement('fieldset'); 45 container.innerHTML = '<fieldset><fieldset><my-control></my-control></fieldset></fieldset>'; 46 const middleFieldset = container.firstChild; 47 const control = container.querySelector('my-control'); 48 49 assert_true(control.matches(':enabled')); 50 assert_false(control.matches(':disabled')); 51 52 middleFieldset.disabled = true; 53 assert_false(control.matches(':enabled')); 54 assert_true(control.matches(':disabled')); 55 56 middleFieldset.disabled = false; 57 assert_true(control.matches(':enabled')); 58 assert_false(control.matches(':disabled')); 59 60 container.disabled = true; 61 assert_false(control.matches(':enabled')); 62 assert_true(control.matches(':disabled')); 63 control.remove(); 64 assert_true(control.matches(':enabled')); 65 assert_false(control.matches(':disabled')); 66 67 middleFieldset.appendChild(control); 68 assert_false(control.matches(':enabled')); 69 assert_true(control.matches(':disabled')); 70 71 assert_array_equals(control.disabledHistory(), [true, false, true, false, true]); 72 }, 'Relationship with FIELDSET'); 73 74 test(() => { 75 const form = document.createElement('form'); 76 document.body.appendChild(form); 77 form.innerHTML = '<my-control name="n1" disabled></my-control><input name="n2">' 78 const formData = new FormData(form); 79 assert_equals(formData.get('n1'), null); 80 }, 'A disabled form-associated custom element should not provide an entry for it'); 81 82 promise_test(async t => { 83 let form = populateForm('<my-control name=d disabled></my-control>' + 84 '<my-control name=e></my-control>'); 85 let query = await submitPromise(form, form.previousSibling); 86 assert_equals(query.indexOf('d=my-control-value'), -1); 87 assert_not_equals(query.indexOf('e=my-control-value'), -1); 88 }, 'A disabled form-associated custom element should not submit an entry for it'); 89 90 test(() => { 91 const control = new MyControl(); 92 document.body.appendChild(control); 93 control.setAttribute('tabindex', '0'); 94 control.setAttribute('disabled', ''); 95 control.focus(); 96 assert_not_equals(document.activeElement, control); 97 98 control.removeAttribute('disabled'); 99 control.focus(); 100 assert_equals(document.activeElement, control); 101 }, 'Disabled attribute affects focus-capability'); 102 103 test(() => { 104 const container = document.createElement('div'); 105 document.body.appendChild(container); 106 // inneHTML upgrades my-control at its CEReacions timing. 107 container.innerHTML = '<my-control disabled>'; 108 assert_array_equals(container.firstChild.disabledHistory(), [true]); 109 110 container.innerHTML = '<fieldset disabled><my-control>'; 111 assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); 112 }, 'Upgrading an element with disabled content attribute'); 113 114 test(() => { 115 const container = document.createElement('div'); 116 document.body.appendChild(container); 117 container.innerHTML = '<fieldset disabled><my-control></my-control></fieldset>'; 118 119 const control = container.querySelector('my-control'); 120 control.setAttribute('disabled', ''); 121 control.removeAttribute('disabled'); 122 assert_array_equals(control.disabledHistory(), [true]); 123 }, 'Toggling "disabled" attribute on a custom element inside disabled <fieldset> does not trigger a callback'); 124 125 test(() => { 126 const container = document.createElement('div'); 127 document.body.appendChild(container); 128 container.innerHTML = '<fieldset><my-control disabled></my-control></fieldset>'; 129 130 const fieldset = container.firstElementChild; 131 fieldset.disabled = true; 132 fieldset.disabled = false; 133 assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); 134 }, 'Toggling "disabled" attribute on a <fieldset> does not trigger a callback on disabled custom element descendant'); 135 136 test(() => { 137 const template = document.createElement('template'); 138 template.innerHTML = '<my-control></my-control>'; 139 const container = document.createElement('fieldset'); 140 document.body.appendChild(container); 141 container.disabled = true; 142 container.appendChild(template.content.cloneNode(true)); 143 assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); 144 }, 'Callback triggered during a clone/append operation, with disabled state provided by ancestor'); 145 146 test(() => { 147 const container = document.createElement('div'); 148 document.body.appendChild(container); 149 container.innerHTML = '<fieldset disabled><my-control></my-control></fieldset>'; 150 const clone = container.cloneNode(true); 151 assert_array_equals(container.querySelector('my-control').disabledHistory(), [true]); 152 }, 'Callback triggered during a clone operation, with disabled state provided by ancestor'); 153 </script> 154 </body>