Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Merge pull request #110 from notwaldorf/character-counter
Browse files Browse the repository at this point in the history
Add a character counter to paper-input-decorator
  • Loading branch information
addyosmani committed Feb 2, 2015
2 parents b8de922 + 0eb1e05 commit fba3cd6
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 6 deletions.
35 changes: 35 additions & 0 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<link href="paper-autogrow-textarea.html" rel="import">
<link href="paper-input-decorator.html" rel="import">
<link href="paper-input.html" rel="import">
<link href="paper-char-counter.html" rel="import">

<style shim-shadowdom>

Expand Down Expand Up @@ -163,6 +164,40 @@

</section>

<section>

<div>Character counter</div>

<paper-input-decorator label="input with visible character counter">
<input id="i1" is="core-input" maxlength="5">
<paper-char-counter class="counter" target="i1"></paper-char-counter>
</paper-input-decorator>

<br>

<paper-input-decorator label="input with character counter and custom error"
error="maximum characters exceeded">
<input id="i2" is="core-input" maxlength="10">
<paper-char-counter class="counter" target="i2"></paper-char-counter>
</paper-input-decorator>

<br>

<paper-input-decorator label="input with hidden character counter"
error="maximum characters exceeded">
<input id="i3" is="core-input" maxlength="10">
<paper-char-counter class="counter" showCounter="false" target="i3"></paper-char-counter>
</paper-input-decorator>

<paper-input-decorator label="autogrowing text area with character counter">
<paper-autogrow-textarea>
<textarea id="t1" maxlength="100"></textarea>
</paper-autogrow-textarea>
<paper-char-counter class="counter" target="t1"></paper-char-counter>
</paper-input-decorator>

</section>

<section>

<div>Auto-Validation</div>
Expand Down
121 changes: 121 additions & 0 deletions paper-char-counter.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!--
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
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
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
-->

<!--
Material Design: <a href="http://www.google.com/design/spec/components/text-fields.html#text-fields-character-counter">Character counter</a>
`paper-char-counter` adds a character counter for paper input fields with a character restriction in place.
Example:
<paper-input-decorator>
<input id="input1" is="core-input" maxlength="5">
<paper-char-counter class="footer" target="input1"></paper-char-counter>
</paper-input-decorator>
Theming
-------
`paper-char-counter` uses `paper-input-decorator`'s error `core-style` for global theming.
@group Paper Elements
@element paper-char-counter
@homepage github.io
-->
<link href="../polymer/polymer.html" rel="import">
<link href="../core-style/core-style.html" rel="import">

<core-style id="paper-char-counter">
:host(.invalid) {
color: {{g.paperInput.invalidColor}};
}
</core-style>

<polymer-element name="paper-char-counter">

<template>

<style>
:host {
display: inline-block;
float: right;
color: #757575;
font-size: 0.75em;
padding: 0.5em 0 0.5em 0.5em;
}
</style>

<core-style ref="paper-char-counter"></core-style>

<div class="counter-text" aria-hidden="true" hidden?="{{!showCounter || !_maxChars}}">
<span>{{_charCount}} / {{_maxChars}}</span>
</div>

</template>

<script>

Polymer({

publish: {
/**
* The id of the textinput or textarea that should be monitored.
*
* @attribute target
* @type string
* @default null
*/
target: null,

/**
* If false, don't show the character counter. Used in conjunction with
* `paper-input-decorator's` `error` field.
*
* @attribute showCounter
* @type boolean
* @default true
*/
showCounter: true
},

/* Number of characters in the current input */
_charCount: 0,

/* Equal to the target element's maxLength attribute. */
_maxChars: 0,

/* True if the number of characters in the input exceeds _maxChars */
_isCounterInvalid: false,

ready: function() {
if (!this.target)
return;
var targetElement = document.getElementById(this.target);
this._maxChars = targetElement.maxLength;
targetElement.addEventListener('input', this.inputAction.bind(this));
},

inputAction: function(e) {
this._charCount = e.target.value.length;
this._isCounterInvalid = this._maxChars && this._charCount >= this._maxChars;
},

_isCounterInvalidChanged: function() {
debugger
this.classList.toggle('invalid', this._isCounterInvalid);
this.fire('char-counter-error',
{"hasError": this._isCounterInvalid,
"hideErrorIcon": this.showCounter});
}
});

</script>

</polymer-element>
24 changes: 19 additions & 5 deletions paper-input-decorator.html
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
on-transitionEnd="{{transitionEndAction}}" on-webkitTransitionEnd="{{transitionEndAction}}"
on-input="{{inputAction}}"
on-down="{{downAction}}"
on-tap="{{tapAction}}">
on-tap="{{tapAction}}"
on-char-counter-error="{{charCounterErrorAction}}">

<template>

Expand All @@ -195,7 +196,7 @@
<span id="labelText" class="label-text" invisible?="{{!_labelVisible}}" animated?="{{labelAnimated}}">{{label}}</span>
</div>

<content></content>
<content select="*:not(.counter)"></content>

</div>

Expand All @@ -204,9 +205,14 @@
<div id="focusedUnderline" class="focused-underline" fit invisible?="{{!underlineVisible}}" animated?="{{underlineAnimated}}"></div>
</div>

<div class="error" layout horizontal center hidden?="{{!isInvalid}}">
<div class="error-text" flex auto role="alert" aria-hidden="{{!isInvalid}}">{{error}}</div>
<core-icon class="error-icon" icon="warning"></core-icon>
<div class="footer" layout horizontal end-justified>
<div class="error" flex layout horizontal center hidden?="{{!isInvalid}}">
<div class="error-text" flex auto role="alert" aria-hidden="{{!isInvalid}}">{{error}}</div>
<core-icon id="errorIcon" class="error-icon" icon="warning"></core-icon>
</div>
<div aria-hidden="true">
<content select=".counter"></content>
</div>
</div>

</template>
Expand Down Expand Up @@ -522,6 +528,14 @@
if (this._labelVisible) {
this.input.placeholder = this.label;
}
},

charCounterErrorAction: function(e) {
this.isInvalid = e.detail.hasError;

// If the allowed characters have been exceeded, show either the error
// icon, or the character counter, but not both.
this.$.errorIcon.hidden = e.detail.hideErrorIcon;
}

});
Expand Down
55 changes: 54 additions & 1 deletion test/paper-input-decorator.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<link href="../paper-input-decorator.html" rel="import">
<link href="../paper-autogrow-textarea.html" rel="import">
<link href="../paper-char-counter.html" rel="import">

<style>
paper-input-decorator {
Expand Down Expand Up @@ -80,6 +81,14 @@
<br>
</template>

<template id="char-counter">
<paper-input-decorator label="character counter">
<input is="core-input" maxlength="5">
<paper-char-counter class="counter"></paper-char-counter>
</paper-input-decorator>
<br>
</template>

<script>

var fake = new Fake();
Expand Down Expand Up @@ -170,6 +179,50 @@
});
});

test('char-counter is visible', function() {
var nodes = cloneAndAppendTemplate('char-counter');
var counter = nodes.d.querySelector('.counter');
assert.ok(nodes.i.maxLength != 0);
assert.ok(nodes.d.error == "");

nodes.i.id="input";
counter.target = "input";
counter.ready();

flush(function() {
assert.ok(!counter.shadowRoot.querySelector('.counter-text').hidden);
});
});

test('char-counter is invalid when input exceeds maxLength', function() {
var nodes = cloneAndAppendTemplate('char-counter');
var counter = nodes.d.querySelector('.counter');
assert.ok(nodes.i.maxLength == 5);

nodes.i.id = "input";
counter.target = "input";
counter.ready();


flush(function() {
nodes.i.value = "nanananabatman";
var e = new Event('input', {
bubbles: true
});
nodes.i.dispatchEvent(e);

flush(function() {
assert.ok(counter._isCounterInvalid);
assert.ok(nodes.d.isInvalid);

assert.strictEqual(
CoreStyle.g.paperInput.invalidColor,
counter.shadowRoot.querySelector('.counter-text').color);
done();
});
});
});

suite('a11y', function() {

test('aria-label set on input', function() {
Expand All @@ -184,4 +237,4 @@
</script>

</body>
</html>
</html>

0 comments on commit fba3cd6

Please sign in to comment.