@@ -16,12 +16,27 @@ var codeInput = {
1616 */
1717 observedAttributes : [
1818 "value" ,
19- "name" ,
20- "placeholder" ,
21- "lang" ,
19+ "placeholder" ,
20+ "lang" ,
2221 "template"
2322 ] ,
2423
24+ /**
25+ * A list of attributes that will be moved to
26+ * the textarea after they are applied on the
27+ * code-input element.
28+ */
29+ textareaSyncAttributes : [
30+ "value" ,
31+ "name" ,
32+ // Form validation - https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation
33+ "required" ,
34+ "minlength" , "maxlength" ,
35+ "min" , "max" ,
36+ "type" ,
37+ "pattern"
38+ ] ,
39+
2540 /* ------------------------------------
2641 * ------------Templates---------------
2742 * ------------------------------------ */
@@ -417,12 +432,16 @@ var codeInput = {
417432 textarea . value = value ;
418433 textarea . setAttribute ( "spellcheck" , "false" ) ;
419434
420- if ( this . getAttribute ( "name" ) ) {
421- textarea . setAttribute ( "name" , this . getAttribute ( "name" ) ) ; // for use in forms
422- }
423-
424- textarea . addEventListener ( 'input' , ( evt ) => { textarea . parentElement . update ( textarea . value ) ; textarea . parentElement . syncScroll ( ) ; } ) ;
425- textarea . addEventListener ( 'scroll' , ( evt ) => textarea . parentElement . syncScroll ( ) ) ;
435+ // Synchronise attributes to textarea
436+ codeInput . textareaSyncAttributes . forEach ( ( attribute ) => {
437+ if ( this . hasAttribute ( attribute ) ) {
438+ textarea . setAttribute ( attribute , this . getAttribute ( attribute ) ) ;
439+ }
440+ } ) ;
441+
442+ textarea . addEventListener ( 'input' , ( evt ) => { textarea . parentElement . update ( textarea . value ) ; textarea . parentElement . sync_scroll ( ) ; } ) ;
443+ textarea . addEventListener ( 'scroll' , ( evt ) => textarea . parentElement . sync_scroll ( ) ) ;
444+
426445 this . append ( textarea ) ;
427446
428447 // Create result element
@@ -485,7 +504,7 @@ var codeInput = {
485504 * to `codeInput.CodeInput.attributeChangedCallback` when modified.
486505 */
487506 static get observedAttributes ( ) {
488- return codeInput . observedAttributes ;
507+ return codeInput . observedAttributes . concat ( codeInput . textareaSyncAttributes ) ;
489508 }
490509
491510 /**
@@ -503,13 +522,6 @@ var codeInput = {
503522 case "value" :
504523 this . update ( newValue ) ;
505524 break ;
506-
507- case "name" :
508- if ( this . querySelector ( "textarea" ) !== null ) {
509- this . querySelector ( "textarea" ) . setAttribute ( "name" , newValue ) ;
510- }
511- break ;
512-
513525 case "placeholder" :
514526 this . querySelector ( "textarea" ) . placeholder = newValue ;
515527 break ;
@@ -554,6 +566,11 @@ var codeInput = {
554566
555567 this . update ( this . value ) ;
556568
569+ break ;
570+ default :
571+ if ( codeInput . textareaSyncAttributes . includes ( name ) ) {
572+ this . querySelector ( "textarea" ) . setAttribute ( name , newValue ) ;
573+ }
557574 break ;
558575 }
559576 }
@@ -578,6 +595,18 @@ var codeInput = {
578595 } else {
579596 this . querySelector ( "textarea" ) . addEventListener ( "selectionchange" , boundCallback , options ) ;
580597 }
598+ } else if ( evt_name == "invalid" ) {
599+ if ( thirdParameter === null ) {
600+ this . querySelector ( "textarea" ) . addEventListener ( "invalid" , boundCallback ) ;
601+ } else {
602+ this . querySelector ( "textarea" ) . addEventListener ( "invalid" , boundCallback , thirdParameter ) ;
603+ }
604+ } else if ( evt_name == "input" ) {
605+ if ( thirdParameter === null ) {
606+ this . querySelector ( "textarea" ) . addEventListener ( "input" , boundCallback ) ;
607+ } else {
608+ this . querySelector ( "textarea" ) . addEventListener ( "input" , boundCallback , thirdParameter ) ;
609+ }
581610 } else {
582611 super . addEventListener ( type , listener , options ) ;
583612 }
@@ -635,7 +664,40 @@ var codeInput = {
635664 return this . setAttribute ( "placeholder" , val ) ;
636665 }
637666
638- /**
667+ /* Form validation */
668+ get validity ( ) {
669+ return this . querySelector ( "textarea" ) . validity ;
670+ }
671+ get validationMessage ( ) {
672+ return this . querySelector ( "textarea" ) . validationMessage ;
673+ }
674+ setCustomValidity ( error ) {
675+ return this . querySelector ( "textarea" ) . setCustomValidity ( error ) ;
676+ }
677+ checkValidity ( ) {
678+ return this . querySelector ( "textarea" ) . checkValidity ( ) ;
679+ }
680+ reportValidity ( ) {
681+ return this . querySelector ( "textarea" ) . reportValidity ( ) ;
682+ }
683+
684+
685+ /* Sync all attributes that can be set on the `code-input` element to the `textarea` element */
686+ setAttribute ( qualifiedName , value ) {
687+ super . setAttribute ( qualifiedName , value ) ; // code-input
688+ this . querySelector ( "textarea" ) . setAttribute ( qualifiedName , value ) ; // textarea
689+ }
690+
691+ getAttribute ( qualifiedName ) {
692+ if ( this . querySelector ( "textarea" ) == null ) {
693+ return super . getAttribute ( qualifiedName ) ;
694+ }
695+ return this . querySelector ( "textarea" ) . getAttribute ( qualifiedName ) ; // textarea
696+ }
697+
698+ pluginData = { } ; // For plugins to store element-specific data under their name, e.g. <code-input>.pluginData.specialChars
699+
700+ /**
639701 * Allows plugins to store data in the scope of a single element.
640702 * Key - name of the plugin
641703 * Value - object of data to be stored; different plugins may use this differently.
0 commit comments