Skip to content
This repository was archived by the owner on May 15, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
"test-fixture": "PolymerElements/test-fixture#^1.0.0",
"web-component-tester": "^4.0.0",
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
},
"resolutions": {
"iron-validatable-behavior": "feature/multipleValidators"
}
}
112 changes: 112 additions & 0 deletions iron-native-validator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="iron-validator-behavior.html">

<!--
`<iron-native-validator>` is a an instantiation of a validator implementing the native
<a href="https://developer.mozilla.org/en-US/docs/Web/API/ValidityState">ValidityState API</a>.

It maps native validators 'required', 'max', 'min', 'step', 'maxlength', 'minlength', 'pattern',
'emailtype'(type=email) and 'urltype' (type=url) to the validity state

<iron-native-validator validator-name="required" message="Please fill in a value" id="instance"></iron-native-validator>
<iron-native-validator validator-name="emailtype" message="Please enter a valid e-mail address"></iron-native-validator>

These native validators need to be instantiated once, so they are ready for use on a global level.
The configured messages will be exposed by the validatable element, and will by default be shown via the paper-input.

# Shimming
When the native ValidityState API doesn't work (yet) in a certain browser, it is possible to provide your own validity
method.

@group Iron Elements
@element iron-native-validator
@hero hero.svg
@demo demo/index.html
-->

<dom-module id="iron-native-validator">

<script>

(function () {

var validityFns = {};

Polymer({

is: 'iron-native-validator',

behaviors: [
Polymer.IronValidatorBehavior
],

properties: {
/**
* Namespace for this validator, override of default 'validator'
*/
validatorType: {
type: String,
value: 'native-validator'
},

/**
* Maps native validity API to native validator names
*/
validityApiMapping: {
type: Object,
readOnly: true,
value: function () {
return {
required: 'valueMissing',
pattern: 'patternMismatch',
max: 'rangeOverflow',
min: 'rangeUnderflow',
step: 'stepMismatch',
maxlength: 'tooLong',
minlength: 'tooShort',
emailtype: 'typeMismatch',
urltype: 'typeMismatch'
};
}
}

},

ready: function () {
// Use native validity API for every validator
var mapping = this.validityApiMapping;
Object.keys(mapping).forEach(function (validator) {
validityFns[validator] = function (value, input) {
return !input.validity[mapping[validator]];
};
}, this);
},

validate: function (value, input) {
return validityFns[this.validatorName](value, input);
},

/* For (globally) overriding the validation method of a native validator.
Should only be used when native validity API doesn't work (yet) in a certain browser
*/
overrideValidationMethod: function (validator, fn) {
validityFns[validator] = fn.bind(this);
}

});

}());

</script>

</dom-module>
101 changes: 60 additions & 41 deletions iron-validator-behavior.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,68 @@

<script>

/**
* Use `Polymer.IronValidatorBehavior` to implement a custom input/form validator. Element
* instances implementing this behavior will be registered for use in elements that implement
* `Polymer.IronValidatableBehavior`.
*
* @demo demo/index.html
* @polymerBehavior
*/
Polymer.IronValidatorBehavior = {

properties: {

/**
* Namespace for this validator.
*/
validatorType: {
type: String,
value: 'validator'
},

/**
* Name for this validator, used by `Polymer.IronValidatableBehavior` to lookup this element.
*/
validatorName: {
type: String,
value: function() {
return this.is;
}
}
/**
* Use `Polymer.IronValidatorBehavior` to implement a custom input/form validator. Element
* instances implementing this behavior will be registered for use in elements that implement
* `Polymer.IronValidatableBehavior`.
*
* @demo demo/index.html
* @polymerBehavior
*/
Polymer.IronValidatorBehavior = {

},
properties: {

ready: function() {
new Polymer.IronMeta({type: this.validatorType, key: this.validatorName, value: this});
},
/**
* Namespace for this validator.
*/
validatorType: {
type: String,
value: 'validator'
},

/**
* Implement custom validation logic in this function.
* @param {Object} values The value to validate. May be any type depending on the validation logic.
* @return {Boolean} true if `values` is valid.
*/
validate: function(values) {
}
};
/**
* Name for this validator, used by `Polymer.IronValidatableBehavior` to lookup this element.
*/
validatorName: {
type: String,
value: function () {
return this.is;
}
},

/**
* Default error message for the validator implementing the IronValidatorBehavior
*/
message: {
type: String,
value: ''
},

/**
* Used to connect the custom validator instance to the desired validatable via the property `validatableId`.
*/
'for': {
type: String,
value: ''
}

},

ready: function () {
var suffix = this.for ? ('--' + this.for) : '';
new Polymer.IronMeta({type: this.validatorType, key: this.validatorName + suffix, value: this});
},

/**
* Implement custom validation logic in this function.
* @param {Object} values The value to validate. May be any type depending on the validation logic.
* @param {HTMLElement} The element validation is being applied to. When a native validation API is present
* (like for instance on the HTMLinputElement), native validation can be used inside the validate function of the validator.
* @return {Boolean} true if `values` is valid.
*/
validate: function (values, input) {
}
};

</script>
4 changes: 3 additions & 1 deletion test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
<script>
WCT.loadSuites([
'iron-validator-behavior.html',
'iron-validator-behavior.html?dom=shadow'
'iron-native-validator.html',
'iron-validator-behavior.html?dom=shadow',
'iron-native-validator.html?dom=shadow'
]);
</script>

Expand Down
102 changes: 102 additions & 0 deletions test/iron-native-validator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>

<title>iron-validatable-behavior tests</title>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">

<script src="../../webcomponentsjs/webcomponents-lite.js"></script>

<script src="../../web-component-tester/browser.js"></script>
<script src="../../test-fixture/test-fixture-mocha.js"></script>

<link rel="import" href="../../test-fixture/test-fixture.html">

<link rel="import" href="../../iron-validatable-behavior/iron-validatable-behavior.html">
<link rel="import" href="../../iron-validator-behavior/iron-validator-behavior.html">

<link rel="import" href="../iron-native-validator.html">


</head>
<body>

<test-fixture id="native-instances">
<template>
<div>
<iron-native-validator validator-name="required" message="required" id="instance"></iron-native-validator>
<iron-native-validator validator-name="max" message="max"></iron-native-validator>
<iron-native-validator validator-name="min" message="min"></iron-native-validator>
<iron-native-validator validator-name="step" message="step"></iron-native-validator>
<iron-native-validator validator-name="maxlength" message="maxlength"></iron-native-validator>
<iron-native-validator validator-name="minlength" message="minlength"></iron-native-validator>
<iron-native-validator validator-name="pattern" message="pattern"></iron-native-validator>
<iron-native-validator validator-name="emailtype" message="emailtype"></iron-native-validator>
<iron-native-validator validator-name="urltype" message="urltype"></iron-native-validator>
</div>
</template>
</test-fixture>

<test-fixture id="inputs">
<template>
<div>
<input validator="required" required value="">
<input validator="max" max="100" type="number" value="200">
<input validator="min" min="50" type="number" value="25">
<input validator="emailtype" type="email" value="nonsense">
<input validator="urltype" type="url" value="nonsense">
<input validator="step" step="3" type="number" value="2" wrong-value="1">
<input validator="pattern" pattern="[A-Za-z]{3}" value="nonsense">
<input validator="minlength" maxlength="2" value="123">
<input validator="maxlength" minlength="2" value="1">
</div>
</template>
</test-fixture>

<script>

suite('basic', function() {

test('registers as type \'native-validator\' ', function() {
var nativeInstance = fixture('native-instances').querySelector('iron-native-validator');
assert.equal(nativeInstance.validatorType, 'native-validator');
});

test('uses native validity API', function() {
var inputs = fixture('inputs');
var nativeValidators = fixture('native-instances');
var mapping = nativeValidators.querySelector('iron-native-validator').validityApiMapping;

Object.keys(mapping).forEach(function (v) {
var validator = nativeValidators.querySelector('[validator-name="' + v + '"]');
var input = inputs.querySelector('[validator="' + v + '"]');
assert.equal(validator.validate(input.value, input), !input.validity[mapping[v]]);
});
});

test('can have overridden validation methods', function() {
var maxlengthValidator = fixture('native-instances').querySelector('[validator-name="maxlength"]');
var newMethod = sinon.spy();
maxlengthValidator.overrideValidationMethod('maxlength', newMethod);
maxlengthValidator.validate();
assert(newMethod.called);
});

});


</script>

</body>
13 changes: 13 additions & 0 deletions test/iron-validator-behavior.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@
</template>
</test-fixture>

<test-fixture id="target-specified">
<template>
<simple-validator for="validatableTarget"></simple-validator>
</template>
</test-fixture>

<script>

suite('basic', function() {
Expand All @@ -40,6 +46,13 @@
assert.ok(new Polymer.IronMeta({type: 'validator'}).byKey('simple-validator'), 'simple-validator found in <iron-meta>');
});

test('registered in <iron-meta> as specific validation', function() {
fixture('target-specified');
assert.ok(new Polymer.IronMeta({
type: 'validator'
}).byKey('simple-validator--validatableTarget'), 'simple-validator found in <iron-meta>');
});

});

</script>
Expand Down