プログラミング/Materialize の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- プログラミング/Materialize へ行く。
- プログラミング/Materialize の差分を削除
[[公開メモ]] * validate の方法 [#baca2da5] これとか、 https://codepen.io/tdurant72/pen/vgyBjZ これとかのようにするみたい。 http://demo.geekslabs.com/materialize-v1.0/form-validation.html jQuery.validate はこちら。 https://jqueryvalidation.org/validate/ ** Validation ルール [#i324aa63] https://jqueryvalidation.org/documentation/#link-list-of-built-in-validation-methods 標準的なルール: - required – Makes the element required. - remote – Requests a resource to check the element for validity. - minlength – Makes the element require a given minimum length. - maxlength – Makes the element require a given maximum length. - rangelength – Makes the element require a given value range. - min – Makes the element require a given minimum. - max – Makes the element require a given maximum. - range – Makes the element require a given value range. - step – Makes the element require a given step. - email – Makes the element require a valid email - url – Makes the element require a valid url - date – Makes the element require a date. - dateISO – Makes the element require an ISO date. - number – Makes the element require a decimal number. - digits – Makes the element require digits only. - equalTo – Requires the element to be the same as another one その他のルール: https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/additional-methods.js を読めば使える。 https://github.com/jquery-validation/jquery-validation/tree/master/src/additional - accept - additional - alphanumeric - bankaccountNL - bankorgiroaccountNL - bic - cifES - cpfBR - creditcard - creditcardtypes - currency - dateFA - dateITA - dateNL - extension - giroaccountNL - greaterThan - greaterThanEqual - iban - integer - ipv4 - ipv6 - lessThan - lessThanEqual - lettersonly - letterswithbasicpunc - maxfiles - maxsize - maxsizetotal - mobileNL - mobileUK - netmask - nieES - nifES - nipPL - notEqualTo - nowhitespace - pattern - 正規表現 - phoneNL - phonePL - phoneUK - phoneUS - phonesUK - postalCodeCA - postalcodeBR - postalcodeIT - postalcodeNL - postcodeUK - require_from_group - skip_or_fill_minimum - statesUS - strippedminlength - time - time12h - url2 - vinUS - zipcodeUS - ziprange 例えば、 LANG:javascript $.validator.addMethod( "ipv4", function( value, element ) { return this.optional( element ) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test( value ); }, "Please enter a valid IP v4 address." ); こんな感じで独自ルールを追加できるので、とても便利だ。 ** jQuery.validate の中味 [#n5de8f94] $('form#id').validate( options ) は、 LANG:javascript // https://jqueryvalidation.org/validate/ validate: function( options ) { を呼び出す。 すでに form が validator を持っていると何もしないので注意。 LANG:javascript validator = new $.validator( options, this[ 0 ] ); として validator が作られる。 作られた validator は $.data( form, "validator", validator ) のように form に保持される。 *** コンストラクタ [#q048c609] LANG:javascript // Constructor for validator $.validator = function( options, form ) { this.settings = $.extend( true, {}, $.validator.defaults, options ); this.currentForm = form; this.init(); }; options は validator.settings に保存される。 init() は、 LANG:javascript $.extend( $.validator, { ... prototype: { init: function() { ... rules = this.settings.rules; $.each( rules, function( key, value ) { rules[ key ] = $.validator.normalizeRule( value ); } ); ... $( this.currentForm ) .on( "focusin.validate focusout.validate keyup.validate", ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate ) // Support: Chrome, oldIE // "select" is provided as event.target when clicking a option .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate ); のようにして currentForm 以下の各種入力フィールドにイベントハンドラを結びつける LANG:javascript var currentForm = this.currentForm ... function delegate( event ) { // Set form expando on contenteditable if ( !this.form && this.hasAttribute( "contenteditable" ) ) { this.form = $( this ).closest( "form" )[ 0 ]; this.name = $( this ).attr( "name" ); } // Ignore the element if it belongs to another form. This will happen mainly // when setting the `form` attribute of an input to the id of another form. if ( currentForm !== this.form ) { return; } var validator = $.data( this.form, "validator" ), eventType = "on" + event.type.replace( /^validate/, "" ), settings = validator.settings; if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) { settings[ eventType ].call( validator, this, event ); } } settings[ eventType ] のデフォルト値は、 LANG:javascript onfocusin: function( element ) { this.lastActive = element; // Hide error label and remove error class on focus if enabled if ( this.settings.focusCleanup ) { if ( this.settings.unhighlight ) { this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); } this.hideThese( this.errorsFor( element ) ); } }, onfocusout: function( element ) { if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { this.element( element ); } }, onkeyup: function( element, event ) { // Avoid revalidate the field when pressing one of the following keys // Shift => 16 // Ctrl => 17 // Alt => 18 // Caps lock => 20 // End => 35 // Home => 36 // Left arrow => 37 // Up arrow => 38 // Right arrow => 39 // Down arrow => 40 // Insert => 45 // Num lock => 144 // AltGr key => 225 var excludedKeys = [ 16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 45, 144, 225 ]; if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { return; } else if ( element.name in this.submitted || element.name in this.invalid ) { this.element( element ); } }, onclick: function( element ) { // Click on selects, radiobuttons and checkboxes if ( element.name in this.submitted ) { this.element( element ); // Or option elements, check parent select in that case } else if ( element.parentNode.name in this.submitted ) { this.element( element.parentNode ); } }, this.element( element ) は、 LANG:javascript // https://jqueryvalidation.org/Validator.element/ element: function( element ) { var cleanElement = this.clean( element ), checkElement = this.validationTargetFor( cleanElement ), v = this, result = true, rs, group; if ( checkElement === undefined ) { delete this.invalid[ cleanElement.name ]; } else { this.prepareElement( checkElement ); this.currentElements = $( checkElement ); // If this element is grouped, then validate all group elements already // containing a value group = this.groups[ checkElement.name ]; if ( group ) { $.each( this.groups, function( name, testgroup ) { if ( testgroup === group && name !== checkElement.name ) { cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) ); if ( cleanElement && cleanElement.name in v.invalid ) { v.currentElements.push( cleanElement ); result = v.check( cleanElement ) && result; } } } ); } rs = this.check( checkElement ) !== false; result = result && rs; if ( rs ) { this.invalid[ checkElement.name ] = false; } else { this.invalid[ checkElement.name ] = true; } if ( !this.numberOfInvalids() ) { // Hide error containers on last error this.toHide = this.toHide.add( this.containers ); } this.showErrors(); // Add aria-invalid status for screen readers $( element ).attr( "aria-invalid", !rs ); } return result; }, this.check( element ) は、 LANG:javascript check: function( element ) { element = this.validationTargetFor( this.clean( element ) ); var rules = $( element ).rules(), rulesCount = $.map( rules, function( n, i ) { return i; } ).length, ... for ( method in rules ) { rule = { method: method, parameters: rules[ method ] }; try { result = $.validator.methods[ method ].call( this, val, element, rule.parameters ); ... 初めに呼ばれている $( element ).rules() は、 LANG:javascript rules: function( command, argument ) { var element = this[ 0 ], ... data = $.validator.normalizeRules( $.extend( {}, $.validator.classRules( element ), $.validator.attributeRules( element ), $.validator.dataRules( element ), $.validator.staticRules( element ) ), element ); ... return data; } } ); classRules により、element の class に、 - required: { required: true }, - email: { email: true }, - url: { url: true }, - date: { date: true }, - dateISO: { dateISO: true }, - number: { number: true }, - digits: { digits: true }, - creditcard: { creditcard: true } が含まれている場合にチェックする。 attributeRules により、element の attr に、$.validator.methods に含まれる名前が含まれていればチェックする。 dataRules により、element が data-ruleRequired などを含む場合にチェックする。 staticRules により、validator.settings.rules[ element.name ] に含まれるチェックをする。 LANG:javascript // https://jqueryvalidation.org/Validator.showErrors/ showErrors: function( errors ) { if ( errors ) { var validator = this; // Add items to error list and map $.extend( this.errorMap, errors ); this.errorList = $.map( this.errorMap, function( message, name ) { return { message: message, element: validator.findByName( name )[ 0 ] }; } ); // Remove items from success list this.successList = $.grep( this.successList, function( element ) { return !( element.name in errors ); } ); } if ( this.settings.showErrors ) { this.settings.showErrors.call( this, this.errorMap, this.errorList ); } else { this.defaultShowErrors(); } }, ** select にうまく効かない [#ne2d8a7b] https://github.com/Dogfalo/materialize/issues/1861 Materialize では select 本体が非表示になっているので validation がスキップされてしまう 上記を参考に LANG:javascript $('.select-wrapper > select').css({ LANG:coffee $('.select-wrapper > select').css display: 'inline', position: 'absolute', float: 'left', padding: 0, margin: 0, border: '1px solid rgba(255,255,255,0)', height: 0, width: 0, top: '2em', left: '3em', opacity: 0 }); として無理矢理表示すれば validation はかかるのだけれど、、、 Materialize の css では .select-wrapper に .invalid を付けないとハイライトされない LANG:javascript LANG:coffee highlight: (element, errorClass, validClass)-> target = if element.type == 'radio' @findByName( element.name ) else if element.type == 'select-one' or element.type == 'select-multiple' $( element ).closest('div.select-wrapper') else $( element ) target.addClass( errorClass ).removeClass( validClass ) unhighlight: (element, errorClass, validClass)-> target = if element.type == 'radio' @findByName( element.name ) else if element.type == 'select-one' or element.type == 'select-multiple' $( element ).closest('div.select-wrapper') else $( element ) target.removeClass( errorClass ).addClass( validClass ) こうしないとダメだった こういうのは、 LANG:javascript LANG:coffee $.extend $.validator.defaults, errorClass: 'invalid' highlight: (element, errorClass, validClass)-> target = if element.type == 'radio' @findByName( element.name ) else if element.type == 'select-one' or element.type == 'select-multiple' $( element ).closest('div.select-wrapper') else $( element ) target.addClass( errorClass ).removeClass( validClass ) unhighlight: (element, errorClass, validClass)-> target = if element.type == 'radio' @findByName( element.name ) else if element.type == 'select-one' or element.type == 'select-multiple' $( element ).closest('div.select-wrapper') else $( element ) target.removeClass( errorClass ).addClass( validClass ) errorPlacement: (error, element)-> $(element) .closest('form') .find("label[for='#{ element.attr('id') }']") .attr('data-error', error.text()) なんて書いてやれば毎回書く必要がなくなるみたい。 さらに、click や change イベントが起きないので、 LANG:javascript LANG:coffee @on 'mount', -> $('li', @root).on 'click', -> $('select', @root).click() のようにして、li の click で select の click を呼び出すようにした。 ** autocomplete が日本語でうまく動かない [#r57e663c] keyup で引っかけているので ime の確定時にも keyup を呼んでやる必要がある LANG:coffee $('input', @root).on 'compositionend', -> $('input', @root).keyup()
Counter: 4001 (from 2010/06/03),
today: 2,
yesterday: 3