diff --git a/CHANGELOG.md b/CHANGELOG.md
index 421291e25..54042cee0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Ember Paper Changelog
+### 0.2.7 (Aug 11, 2015)
+- [#132](https://github.com/miguelcobain/ember-paper/pull/132) Added autocomplete component.
+- [#144](https://github.com/miguelcobain/ember-paper/pull/144) Fixed paper-icon sizes and added new size md-sm (size="sm").
+- [#146](https://github.com/miguelcobain/ember-paper/pull/146) Upgrade to ember 1.13.7 and ember-cli 1.13.8.
+
### 0.2.6 (Jul 20, 2015)
- [#135](https://github.com/miguelcobain/ember-paper/pull/135) Fix deprecation bug in linear progress indicator.
diff --git a/addon/components/paper-autocomplete-highlight.js b/addon/components/paper-autocomplete-highlight.js
new file mode 100644
index 000000000..aedba4da6
--- /dev/null
+++ b/addon/components/paper-autocomplete-highlight.js
@@ -0,0 +1,35 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'span',
+ flags: '',
+
+ highlight: Ember.computed('searchText', 'label', 'flags', function() {
+ var unsafeText = Ember.Handlebars.Utils.escapeExpression(this.get('label'));
+ var text = unsafeText;
+ var flags = this.get('flags');
+ var regex = this.getRegExp(this.get('searchText'), flags);
+ var html = text.replace(regex, '$&');
+ return new Ember.Handlebars.SafeString(html);
+ }),
+
+ sanitize(term) {
+ if (!term) {
+ return term;
+ }
+ return term.replace(/[\\\^\$\*\+\?\.\(\)\|\{}\[\]]/g, '\\$&');
+ },
+
+ getRegExp(text, flags) {
+ var str = '';
+ if (flags.indexOf('^') >= 1) {
+ str += '^';
+ }
+ str += text;
+ if (flags.indexOf('$') >= 1) {
+ str += '$';
+ }
+ return new RegExp(this.sanitize(str), flags.replace(/[\$\^]/g, ''));
+ }
+
+});
diff --git a/addon/components/paper-autocomplete-item.js b/addon/components/paper-autocomplete-item.js
new file mode 100644
index 000000000..4443c7ec8
--- /dev/null
+++ b/addon/components/paper-autocomplete-item.js
@@ -0,0 +1,25 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'li',
+ attributeBindings: ['tabindex', 'role'],
+ classNameBindings: ['isSelected:selected'],
+ tabindex: 0,
+ role: 'option',
+
+ label: Ember.computed('item', function() {
+ return this.lookupLabelOfItem(this.get('item'));
+ }),
+
+ isSelected: Ember.computed('selectedIndex', function() {
+ return this.get('selectedIndex') === this.get('index');
+ }),
+
+ lookupLabelOfItem(model) {
+ return this.get('lookupKey') ? Ember.get(model, this.get('lookupKey')) : model;
+ },
+
+ click() {
+ this.sendAction('pick', this.get('item'));
+ }
+});
diff --git a/addon/components/paper-autocomplete-list.js b/addon/components/paper-autocomplete-list.js
new file mode 100644
index 000000000..ea9a29e77
--- /dev/null
+++ b/addon/components/paper-autocomplete-list.js
@@ -0,0 +1,108 @@
+import Ember from 'ember';
+
+//TODO Move to constants?
+var ITEM_HEIGHT = 41,
+ MAX_HEIGHT = 5.5 * ITEM_HEIGHT,
+ MENU_PADDING = 8;
+
+export default Ember.Component.extend({
+ util: Ember.inject.service(),
+
+ tagName: 'ul',
+ classNames: ['md-default-theme', 'md-autocomplete-suggestions', 'md-whiteframe-z1'],
+ attributeNameBindings: ['role'],
+ role: 'presentation',
+ stickToElement: null,
+
+ mouseEnter() {
+ this.sendAction('mouse-enter');
+ },
+
+ mouseLeave() {
+ this.sendAction('mouse-leave');
+ },
+
+ mouseUp() {
+ this.sendAction('mouse-up');
+ },
+
+ //TODO reafactor into a computed property that binds directly to dropdown's `style`
+ positionDropdown() {
+ var hrect = Ember.$('#' + this.get('wrapToElementId'))[0].getBoundingClientRect(),
+ vrect = hrect,
+ root = document.body.getBoundingClientRect(),
+ top = vrect.bottom - root.top,
+ bot = root.bottom - vrect.top,
+ left = hrect.left - root.left,
+ width = hrect.width,
+ styles = {
+ left: left + 'px',
+ minWidth: width + 'px',
+ maxWidth: Math.max(hrect.right - root.left, root.right - hrect.left) - MENU_PADDING + 'px'
+ },
+ ul = this.$();
+
+ if (top > bot && root.height - hrect.bottom - MENU_PADDING < MAX_HEIGHT) {
+ styles.top = 'auto';
+ styles.bottom = bot + 'px';
+ styles.maxHeight = Math.min(MAX_HEIGHT, hrect.top - root.top - MENU_PADDING) + 'px';
+ } else {
+ styles.top = top + 'px';
+ styles.bottom = 'auto';
+ styles.maxHeight = Math.min(MAX_HEIGHT, root.bottom - hrect.bottom - MENU_PADDING) + 'px';
+ }
+ ul.css(styles);
+ correctHorizontalAlignment();
+
+ /**
+ * Makes sure that the menu doesn't go off of the screen on either side.
+ */
+ function correctHorizontalAlignment () {
+ var dropdown = ul[0].getBoundingClientRect(),
+ styles = {};
+ if (dropdown.right > root.right - MENU_PADDING) {
+ styles.left = (hrect.right - dropdown.width) + 'px';
+ }
+ ul.css(styles);
+ }
+ },
+
+ observeIndex: Ember.observer('selectedIndex', function() {
+ var suggestions = this.get('suggestions');
+ if (!suggestions || !suggestions.objectAt(this.get('selectedIndex'))) {
+ return;
+ }
+
+ var ul = this.$(),
+ li = ul.find('li:eq('+this.get('selectedIndex')+')')[0],
+ top = li.offsetTop,
+ bot = top + li.offsetHeight,
+ hgt = ul[0].clientHeight;
+ if (top < ul[0].scrollTop) {
+ ul[0].scrollTop = top;
+ } else if (bot > ul[0].scrollTop + hgt) {
+ ul[0].scrollTop = bot - hgt;
+ }
+ }),
+
+ resizeWindowEvent() {
+ this.positionDropdown();
+ },
+
+ didInsertElement() {
+ this._super(...arguments);
+
+ //TODO refactor using ember-wormhole?
+ var ul = this.$().detach();
+ Ember.$('body').append(ul);
+ Ember.$(window).on('resize', Ember.run.bind(this, this.resizeWindowEvent));
+ this.get('util').disableScrollAround(this.$());
+ this.positionDropdown();
+ },
+
+ willDestroyElement() {
+ Ember.$(window).off('resize');
+ this.get('util').enableScrolling();
+ }
+
+});
diff --git a/addon/components/paper-autocomplete.js b/addon/components/paper-autocomplete.js
new file mode 100644
index 000000000..f7282db09
--- /dev/null
+++ b/addon/components/paper-autocomplete.js
@@ -0,0 +1,306 @@
+import Ember from 'ember';
+import HasBlockMixin from '../mixins/hasblock-mixin';
+import { promiseArray } from 'ember-paper/utils/promise-proxies';
+
+function isString(item) {
+ return typeof item === 'string' || item instanceof String;
+}
+
+/**
+ * @name paper-autocomplete
+ *
+ * @description
+ * Provides material design autocomplete.
+ *
+ *
+ * ## Dependencies
+ * - paper-autocomplete-item
+ * - paper-autocomplete-list
+ * - paper-input
+ * - paper-button
+ * - input
+ */
+export default Ember.Component.extend(HasBlockMixin, {
+ util: Ember.inject.service(),
+ constants: Ember.inject.service(),
+
+ tagName: 'md-autocomplete',
+ classNameBindings: ['notFloating:md-default-theme'],
+ attributeBindings: ['floating:md-floating-label', 'showDisabled:disabled'],
+
+
+ // Internal
+ hidden: true,
+ selectedIndex: 0,
+ messages: [],
+ noBlur: false,
+ hasFocus: false,
+ searchText: '',
+ // wrap in a computed property so that cache
+ // isn't shared among autocomplete instances
+ itemCache: Ember.computed(function() {
+ return {};
+ }),
+
+ // Public
+ disabled: null,
+ required: null,
+ lookupKey: null,
+ placeholder: '',
+ delay: 0,
+ minLength: 1,
+ allowNonExisting: false,
+ noCache: false,
+ notFoundMessage: 'No matches found for \'%@\'.',
+
+ init() {
+ this._super(...arguments);
+
+ if (this.get('model')) {
+ this.set('searchText', this.lookupLabelOfItem(this.get('model')));
+ this.searchTextDidChange();
+ }
+ },
+
+ notFloating: Ember.computed.not('floating'),
+ notHidden: Ember.computed.not('hidden'),
+
+ autocompleteWrapperId: Ember.computed('elementId', function() {
+ return 'autocomplete-wrapper-' + this.get('elementId');
+ }),
+
+ sections: {
+ itemTemplate: {isItemTemplate: true},
+ notFoundTemplate: {isNotFoundTemplate: true}
+ },
+
+ notFoundMsg: Ember.computed('searchText', 'notFoundMessage', function() {
+ return Ember.String.fmt(this.get('notFoundMessage'), [this.get('searchText')]);
+ }),
+
+ /**
+ * Needed because of false = disabled='false'.
+ */
+ showDisabled: Ember.computed('disabled', function() {
+ if (this.get('disabled')) {
+ return true;
+ }
+ }),
+
+ showLoadingBar: Ember.computed('loading', 'allowNonExisting', 'debouncingState', function() {
+ return !this.get('loading') && !this.get('allowNonExisting') && !this.get('debouncingState');
+ }),
+
+ enableClearButton: Ember.computed('searchText', 'disabled', function() {
+ return this.get('searchText') && !this.get('disabled');
+ }),
+
+ /**
+ * Source filtering logic
+ */
+
+ searchTextDidChange: Ember.observer('searchText', function() {
+ var searchText = this.get('searchText');
+ if (searchText !== this.get('previousSearchText')) {
+ if (!this.get('allowNonExisting')) {
+ this.set('model', null);
+ } else {
+ this.set('model', searchText);
+ }
+
+ this.sendAction('update-filter', searchText);
+
+ this.set('debouncingState', true);
+ Ember.run.debounce(this, this.setDebouncedSearchText, this.get('delay'));
+ this.set('previousSearchText', searchText);
+ }
+ }),
+
+ setDebouncedSearchText() {
+ var searchText = this.get('searchText');
+ if (this.get('isMinLengthMet')) {
+ this.sendAction('debounced-update-filter', searchText);
+ if (!this.cacheGet(searchText)) {
+ this.sendAction('cache-miss', searchText);
+ } else {
+ this.sendAction('cache-hit', searchText);
+ }
+ this.set('debouncedSearchText', searchText);
+
+ // If the autocomplete is being triggered by a human / not on initial render.
+ if (this.get('hasFocus') || this.get('noBlur')) {
+ this.set('hidden', false);
+ }
+ } else {
+ this.set('hidden', true);
+ }
+ this.set('debouncingState', false);
+ },
+
+ loading: Ember.computed.bool('sourcePromiseArray.isPending').readOnly(),
+
+ //coalesces all promises into PromiseArrays or Arrays
+ sourcePromiseArray: Ember.computed('source', function() {
+ var source = this.get('source');
+ if (source && source.then) {
+ //coalesce into promise array
+ return promiseArray(source);
+ } else if (Ember.isArray(source)) {
+ //return array
+ return Ember.A(source);
+ } else {
+ //Unknown source type
+ Ember.assert('The provided \'source\' for paper-autocomplete must be an Array or a Promise.', !Ember.isPresent(source));
+ return Ember.A();
+ }
+ }).readOnly(),
+
+ suggestions: Ember.computed('debouncedSearchText', 'sourcePromiseArray.[]', function() {
+ var source = this.get('sourcePromiseArray');
+ var lookupKey = this.get('lookupKey');
+ var searchText = (this.get('debouncedSearchText') || '').toLowerCase();
+ var cachedItems = this.cacheGet(searchText);
+ var suggestions;
+
+ if (cachedItems) {
+ //We have cached results
+ suggestions = cachedItems;
+ } else {
+ //no cache
+
+ var data = this.filterArray(source, searchText, lookupKey);
+ if (source.then && source.get('isFulfilled')) {
+ //cache when we have a PromiseArray
+ this.cacheSet(searchText, data);
+ }
+ suggestions = Ember.A(data);
+ }
+ // If we have no item suggestions, and allowNonExisting is enabled
+ // We need to close the paper-autocomplete-list so all mouse events get activated again.
+ if (suggestions.length === 0 && this.get('allowNonExisting')){
+ this.set('hidden', true);
+ }
+ return suggestions;
+ }).readOnly(),
+
+
+ filterArray(array, searchText, lookupKey) {
+ return array.filter(function(item) {
+ Ember.assert('You have not defined \'lookupKey\' on paper-autocomplete, when source contained ' +
+ 'items that are not of type String. To fix this error provide a ' +
+ 'lookupKey=\'key to lookup from source item\'.', isString(item) || Ember.isPresent(lookupKey));
+
+ Ember.assert('You specified \'' + lookupKey + '\' as a lookupKey on paper-autocomplete, ' +
+ 'but at least one of its values is not of type String. To fix this error make sure that every \'' + lookupKey +
+ '\' value is a string.', isString(item) || (Ember.isPresent(lookupKey) && isString(Ember.get(item, lookupKey))) );
+
+ var search = isString(item) ? item.toLowerCase() : Ember.get(item, lookupKey).toLowerCase();
+ return search.indexOf(searchText) === 0;
+ });
+ },
+
+ //TODO move cache to service? Components are not singletons.
+ cacheGet(text) {
+ return !this.get('noCache') && this.get('itemCache')[text];
+ },
+
+ cacheSet(text, data) {
+ this.get('itemCache')[text] = data;
+ },
+
+ shouldHide: Ember.computed.not('isMinLengthMet'),
+
+ isMinLengthMet: Ember.computed('searchText', 'minLength', function() {
+ return this.get('searchText').length >= this.get('minLength');
+ }),
+
+ /**
+ * Returns the default index based on whether or not autoselect is enabled.
+ * @returns {number}
+ */
+ defaultIndex: Ember.computed('autoselect', function() {
+ return this.get('autoselect') ? 0 : -1;
+ }),
+
+ lookupLabelOfItem(model) {
+ return this.get('lookupKey') ? Ember.get(model, this.get('lookupKey')) : model;
+ },
+
+ actions: {
+ clear() {
+ this.set('searchText', '');
+ this.set('selectedIndex', -1);
+ this.set('model', null);
+ this.set('hidden', this.get('shouldHide'));
+ },
+
+ pickModel(model) {
+ this.set('model', model);
+ var value = this.lookupLabelOfItem(model);
+ // First set previousSearchText then searchText ( do not trigger observer only update value! ).
+ this.set('previousSearchText', value);
+ this.set('searchText', value);
+ this.set('hidden', true);
+ },
+
+ inputFocusOut() {
+ this.set('hasFocus', false);
+ if (this.get('noBlur') === false) {
+ this.set('hidden', true);
+ }
+ },
+
+ inputFocusIn() {
+ this.set('hasFocus', true);
+ this.set('hidden', this.get('shouldHide'));
+ },
+
+ inputKeyDown(value, event) {
+ switch (event.keyCode) {
+ case this.get('constants').KEYCODE.DOWN_ARROW:
+ if (this.get('loading')) {
+ return;
+ }
+ this.set('selectedIndex', Math.min(this.get('selectedIndex') + 1, this.get('suggestions').length - 1));
+ break;
+ case this.get('constants').KEYCODE.UP_ARROW:
+ if (this.get('loading')) {
+ return;
+ }
+ this.set('selectedIndex', this.get('selectedIndex') < 0 ? this.get('suggestions').length - 1 : Math.max(0, this.get('selectedIndex') - 1));
+ break;
+ case this.get('constants').KEYCODE.TAB:
+ case this.get('constants').KEYCODE.ENTER:
+ if (this.get('hidden') || this.get('loading') || this.get('selectedIndex') < 0 || this.get('suggestions').length < 1) {
+ return;
+ }
+ this.send('pickModel', this.get('suggestions').objectAt(this.get('selectedIndex')));
+ break;
+ case this.get('constants').KEYCODE.ESCAPE:
+ this.set('searchText', '');
+ this.set('selectedIndex', this.get('defaultIndex'));
+ this.set('model', null);
+ this.set('hidden', this.get('shouldHide'));
+ break;
+ default:
+ break;
+ }
+ },
+
+ listMouseEnter() {
+ this.set('noBlur', true);
+ },
+
+ listMouseLeave() {
+ this.set('noBlur', false);
+ if (this.get('hasFocus') === false) {
+ this.set('hidden', true);
+ }
+ },
+
+ listMouseUp() {
+ this.$().find('input').focus();
+ }
+ }
+
+});
diff --git a/addon/components/paper-button.js b/addon/components/paper-button.js
index 92e558b40..b07b8fadd 100644
--- a/addon/components/paper-button.js
+++ b/addon/components/paper-button.js
@@ -7,8 +7,8 @@ import ColorMixin from 'ember-paper/mixins/color-mixin';
export default BaseFocusable.extend(RippleMixin, ProxiableMixin, ColorMixin, {
attributeBindings: ['target', 'action'],
tagName: 'button',
- classNames: ['md-button','md-default-theme'],
- classNameBindings: ['raised:md-raised', 'icon-button:md-icon-button'],
+ themed: true,
+ classNameBindings: ['raised:md-raised', 'icon-button:md-icon-button', 'themed:md-default-theme', 'themed:md-button'],
/* RippleMixin overrides */
isIconButton: Ember.computed(function() {
diff --git a/addon/components/paper-icon.js b/addon/components/paper-icon.js
index 1ade74475..1d3a9300f 100644
--- a/addon/components/paper-icon.js
+++ b/addon/components/paper-icon.js
@@ -25,6 +25,8 @@ export default Ember.Component.extend(ColorMixin, {
switch(this.get('size')) {
case 'lg':
return ' md-lg';
+ case 'sm':
+ return ' md-sm';
case 2:
return ' md-2x';
case 3:
diff --git a/addon/components/paper-input.js b/addon/components/paper-input.js
index 8ab3280f5..7dd317e2a 100644
--- a/addon/components/paper-input.js
+++ b/addon/components/paper-input.js
@@ -1,12 +1,14 @@
import Ember from 'ember';
import BaseFocusable from './base-focusable';
import ColorMixin from 'ember-paper/mixins/color-mixin';
+import FlexMixin from 'ember-paper/mixins/flex-mixin';
-export default BaseFocusable.extend(ColorMixin, {
+export default BaseFocusable.extend(ColorMixin, FlexMixin, {
tagName: 'md-input-container',
classNames: ['md-default-theme'],
classNameBindings: ['hasValue:md-input-has-value', 'focus:md-input-focused', 'isInvalid:md-input-invalid'],
type: 'text',
+ autofocus: false,
tabindex: -1,
hasValue: Ember.computed.notEmpty('value'),
inputElementId: Ember.computed('elementId', function() {
@@ -63,11 +65,18 @@ export default BaseFocusable.extend(ColorMixin, {
},
actions: {
- focusIn() {
+ focusIn(value) {
+ // We resend action so other components can take use of the actions also ( if they want ).
+ // Actions must be sent before focusing.
+ this.sendAction('focus-in', value);
this.set('focus',true);
},
- focusOut() {
+ focusOut(value) {
+ this.sendAction('focus-out', value);
this.set('focus',false);
+ },
+ keyDown(value, event) {
+ this.sendAction('key-down', value, event);
}
}
});
diff --git a/addon/components/paper-item.js b/addon/components/paper-item.js
index 61d1e9bf3..1c3f4b349 100644
--- a/addon/components/paper-item.js
+++ b/addon/components/paper-item.js
@@ -27,7 +27,7 @@ export default Ember.Component.extend(RippleMixin, ProxyMixin, {
return secondaryItem && (secondaryItem.action || (this.get('action') && this.isProxiedComponent(secondaryItem)));
}),
- secondaryItem: Ember.computed('proxiedComponents.@each', function() {
+ secondaryItem: Ember.computed('proxiedComponents.[]', function() {
var proxiedComponents = this.get('proxiedComponents');
return proxiedComponents.find(function(component) {
return component.classNames.indexOf('md-secondary') !== -1;
diff --git a/addon/mixins/proxiable-mixin.js b/addon/mixins/proxiable-mixin.js
index 997c258b7..422ccae2d 100644
--- a/addon/mixins/proxiable-mixin.js
+++ b/addon/mixins/proxiable-mixin.js
@@ -2,7 +2,7 @@ import Ember from 'ember';
import ProxyMixin from './proxy-mixin';
export default Ember.Mixin.create({
- didInsertElement: function() {
+ didInsertElement() {
this._super(...arguments);
var proxy = this.nearestOfType(ProxyMixin);
diff --git a/addon/utils/promise-proxies.js b/addon/utils/promise-proxies.js
new file mode 100644
index 000000000..37603224d
--- /dev/null
+++ b/addon/utils/promise-proxies.js
@@ -0,0 +1,27 @@
+import Ember from 'ember';
+
+var Promise = Ember.RSVP.Promise;
+
+// See http://emberjs.com/api/data/classes/DS.PromiseArray.html
+var PromiseArray = Ember.ArrayProxy.extend(Ember.PromiseProxyMixin);
+// See http://emberjs.com/api/data/classes/DS.PromiseObject.html
+var PromiseObject = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);
+
+var promiseObject = function(promise, label) {
+ return PromiseObject.create({
+ promise: Promise.resolve(promise, label)
+ });
+};
+
+var promiseArray = function(promise, label) {
+ return PromiseArray.create({
+ promise: Promise.resolve(promise, label)
+ });
+};
+
+export {
+ PromiseArray,
+ PromiseObject,
+ promiseArray,
+ promiseObject
+};
diff --git a/app/components/paper-autocomplete-highlight.js b/app/components/paper-autocomplete-highlight.js
new file mode 100644
index 000000000..0de8d8183
--- /dev/null
+++ b/app/components/paper-autocomplete-highlight.js
@@ -0,0 +1 @@
+export { default } from 'ember-paper/components/paper-autocomplete-highlight';
\ No newline at end of file
diff --git a/app/components/paper-autocomplete-item.js b/app/components/paper-autocomplete-item.js
new file mode 100644
index 000000000..7641a4be4
--- /dev/null
+++ b/app/components/paper-autocomplete-item.js
@@ -0,0 +1 @@
+export { default } from 'ember-paper/components/paper-autocomplete-item';
diff --git a/app/components/paper-autocomplete-list.js b/app/components/paper-autocomplete-list.js
new file mode 100644
index 000000000..5ff0cfea6
--- /dev/null
+++ b/app/components/paper-autocomplete-list.js
@@ -0,0 +1 @@
+export { default } from 'ember-paper/components/paper-autocomplete-list';
\ No newline at end of file
diff --git a/app/components/paper-autocomplete.js b/app/components/paper-autocomplete.js
new file mode 100644
index 000000000..b88975292
--- /dev/null
+++ b/app/components/paper-autocomplete.js
@@ -0,0 +1 @@
+export { default } from 'ember-paper/components/paper-autocomplete';
\ No newline at end of file
diff --git a/app/services/util.js b/app/services/util.js
new file mode 100644
index 000000000..4206687fb
--- /dev/null
+++ b/app/services/util.js
@@ -0,0 +1,108 @@
+import Ember from 'ember';
+
+/* global jQuery */
+
+var Util = Ember.Service.extend({
+
+ // Disables scroll around the passed element.
+ disableScrollAround: function (element) {
+ var $mdUtil = this,
+ $document = jQuery(window.document);
+
+ $mdUtil.disableScrollAround._count = $mdUtil.disableScrollAround._count || 0;
+ ++$mdUtil.disableScrollAround._count;
+ if ($mdUtil.disableScrollAround._enableScrolling) return $mdUtil.disableScrollAround._enableScrolling;
+ var body = $document[0].body,
+ restoreBody = disableBodyScroll(),
+ restoreElement = disableElementScroll();
+
+ return $mdUtil.disableScrollAround._enableScrolling = function () {
+ if (!--$mdUtil.disableScrollAround._count) {
+ restoreBody();
+ restoreElement();
+ delete $mdUtil.disableScrollAround._enableScrolling;
+ }
+ };
+
+ // Creates a virtual scrolling mask to absorb touchmove, keyboard, scrollbar clicking, and wheel events
+ function disableElementScroll() {
+ var zIndex = 50;
+ var scrollMask = jQuery(
+ '
diff --git a/app/templates/components/paper-item.hbs b/app/templates/components/paper-item.hbs
index 8cb2d45a3..328bad11b 100644
--- a/app/templates/components/paper-item.hbs
+++ b/app/templates/components/paper-item.hbs
@@ -1,5 +1,5 @@
{{#if action}}
- {{#paper-button classNames="md-no-style" noink=true action="buttonAction" skipProxy=true}}
+ {{#paper-button class="md-no-style" noink=true action="buttonAction" skipProxy=true}}
{{yield}}
diff --git a/bower.json b/bower.json
index 23294c329..d29c0cc68 100644
--- a/bower.json
+++ b/bower.json
@@ -1,17 +1,17 @@
{
"name": "ember-paper",
"dependencies": {
- "ember": "1.13.5",
+ "ember": "1.13.7",
"ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3",
"ember-cli-test-loader": "ember-cli-test-loader#0.1.3",
"ember-load-initializers": "ember-cli/ember-load-initializers#0.1.5",
- "ember-qunit": "0.4.2",
+ "ember-qunit": "0.4.9",
"ember-qunit-notifications": "0.0.7",
"ember-resolver": "~0.1.18",
"hammerjs": "~2.0.4",
- "jquery": "^1.11.1",
- "loader.js": "ember-cli/loader.js#3.2.0",
- "qunit": "~1.17.1",
+ "jquery": "^1.11.3",
+ "loader.js": "ember-cli/loader.js#3.2.1",
+ "qunit": "~1.18.0",
"prism": "*"
}
}
diff --git a/package.json b/package.json
index aad5f472b..bdf8918b3 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "ember-paper",
"description": "The Ember approach to Material Design.",
- "version": "0.2.6",
+ "version": "0.2.7",
"directories": {
"doc": "doc",
"test": "tests"
@@ -21,31 +21,32 @@
"url": "https://github.com/miguelcobain/ember-paper/issues"
},
"devDependencies": {
- "broccoli-asset-rev": "^2.0.2",
+ "broccoli-asset-rev": "^2.1.2",
"broccoli-merge-trees": "~0.2.1",
"broccoli-static-compiler": "~0.2.1",
- "ember-cli": "1.13.1",
- "ember-cli-app-version": "0.4.0",
+ "ember-cli": "1.13.8",
+ "ember-cli-app-version": "0.5.0",
"ember-cli-content-security-policy": "0.4.0",
- "ember-cli-dependency-checker": "^1.0.0",
+ "ember-cli-dependency-checker": "^1.0.1",
"ember-cli-github-pages": "0.0.4",
"ember-cli-htmlbars": "0.7.9",
- "ember-cli-htmlbars-inline-precompile": "^0.1.1",
+ "ember-cli-htmlbars-inline-precompile": "^0.2.0",
"ember-cli-ic-ajax": "0.2.1",
- "ember-cli-inject-live-reload": "^1.3.0",
- "ember-cli-qunit": "0.3.15",
+ "ember-cli-inject-live-reload": "^1.3.1",
+ "ember-cli-qunit": "^1.0.0",
"ember-cli-release": "0.2.3",
"ember-cli-sass": "4.0.0-beta.5",
- "ember-cli-uglify": "^1.0.1",
+ "ember-cli-sri": "^1.0.3",
+ "ember-cli-uglify": "^1.2.0",
"ember-disable-prototype-extensions": "^1.0.0",
"ember-disable-proxy-controllers": "^1.0.0",
- "ember-export-application-global": "^1.0.2",
+ "ember-export-application-global": "^1.0.3",
"ember-prism": "0.0.5",
"ember-try": "0.0.6"
},
"dependencies": {
"broccoli-autoprefixer": "^3.0.0",
- "ember-cli-babel": "^5.0.0"
+ "ember-cli-babel": "^5.1.3"
},
"keywords": [
"ember-addon",
diff --git a/tests/dummy/app/controllers/autocomplete.js b/tests/dummy/app/controllers/autocomplete.js
new file mode 100644
index 000000000..19e3afa7f
--- /dev/null
+++ b/tests/dummy/app/controllers/autocomplete.js
@@ -0,0 +1,299 @@
+import Ember from 'ember';
+
+var SOME_DATA_FROM_API = Ember.A([
+ {name: 'Computer', id: 1},
+ {name: 'Ham', id: 2},
+ {name: 'Unfair', id: 3},
+ {name: 'Ram', id: 4},
+ {name: 'Test', id: 5},
+]);
+
+export default Ember.Controller.extend({
+ myModel: {name: 'United States', code: 'US'},
+
+ searchText: '',
+
+ /**
+ * This is a sample of data loaded dynamically.
+ * Here we use a fake promise, but this can come directly from the ember-data filter API or e.g. jQuery $.getJSON
+ *
+ * @param searchText Search text from the autocomplete API. Lower cased version.
+ * @returns {Promise}
+ */
+ dataFromPromise: Ember.computed('searchText', function() {
+ var searchText = this.get('searchText');
+
+ // Can also come from e.g. this.store.query('country', {text: searchText}).then( ... );
+ return new Ember.RSVP.Promise(resolve => {
+ // Just wait for 800ms to 2 seconds for a fake progress, so it feels like a query.
+ var waitMS = Math.floor(Math.random() * 1000) + 800;
+
+ Ember.run.later(this, function() {
+ var result = SOME_DATA_FROM_API.filter(function (item) {
+ return item.name.toLowerCase().indexOf(searchText.toLowerCase()) === 0;
+ });
+ resolve(Ember.A(result));
+ }, waitMS);
+
+ });
+ }),
+
+ actions: {
+ updateFilter(str) {
+ this.set('searchText', str);
+ }
+ },
+
+ arrayOfItems: ['Ember', 'Paper', 'One', 'Two', 'Three','Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve'],
+
+ /**
+ * Array of static Objects.
+ * When having objects, use lookupKey="name" on the paper-autocomplete component so it knows to use "name" to search in.
+ */
+ items: Ember.A([
+ {name: 'Afghanistan', code: 'AF'},
+ {name: 'Ă…land Islands', code: 'AX'},
+ {name: 'Albania', code: 'AL'},
+ {name: 'Algeria', code: 'DZ'},
+ {name: 'American Samoa', code: 'AS'},
+ {name: 'AndorrA', code: 'AD'},
+ {name: 'Angola', code: 'AO'},
+ {name: 'Anguilla', code: 'AI'},
+ {name: 'Antarctica', code: 'AQ'},
+ {name: 'Antigua and Barbuda', code: 'AG'},
+ {name: 'Argentina', code: 'AR'},
+ {name: 'Armenia', code: 'AM'},
+ {name: 'Aruba', code: 'AW'},
+ {name: 'Australia', code: 'AU'},
+ {name: 'Austria', code: 'AT'},
+ {name: 'Azerbaijan', code: 'AZ'},
+ {name: 'Bahamas', code: 'BS'},
+ {name: 'Bahrain', code: 'BH'},
+ {name: 'Bangladesh', code: 'BD'},
+ {name: 'Barbados', code: 'BB'},
+ {name: 'Belarus', code: 'BY'},
+ {name: 'Belgium', code: 'BE'},
+ {name: 'Belize', code: 'BZ'},
+ {name: 'Benin', code: 'BJ'},
+ {name: 'Bermuda', code: 'BM'},
+ {name: 'Bhutan', code: 'BT'},
+ {name: 'Bolivia', code: 'BO'},
+ {name: 'Bosnia and Herzegovina', code: 'BA'},
+ {name: 'Botswana', code: 'BW'},
+ {name: 'Bouvet Island', code: 'BV'},
+ {name: 'Brazil', code: 'BR'},
+ {name: 'British Indian Ocean Territory', code: 'IO'},
+ {name: 'Brunei Darussalam', code: 'BN'},
+ {name: 'Bulgaria', code: 'BG'},
+ {name: 'Burkina Faso', code: 'BF'},
+ {name: 'Burundi', code: 'BI'},
+ {name: 'Cambodia', code: 'KH'},
+ {name: 'Cameroon', code: 'CM'},
+ {name: 'Canada', code: 'CA'},
+ {name: 'Cape Verde', code: 'CV'},
+ {name: 'Cayman Islands', code: 'KY'},
+ {name: 'Central African Republic', code: 'CF'},
+ {name: 'Chad', code: 'TD'},
+ {name: 'Chile', code: 'CL'},
+ {name: 'China', code: 'CN'},
+ {name: 'Christmas Island', code: 'CX'},
+ {name: 'Cocos (Keeling) Islands', code: 'CC'},
+ {name: 'Colombia', code: 'CO'},
+ {name: 'Comoros', code: 'KM'},
+ {name: 'Congo', code: 'CG'},
+ {name: 'Congo, The Democratic Republic of the', code: 'CD'},
+ {name: 'Cook Islands', code: 'CK'},
+ {name: 'Costa Rica', code: 'CR'},
+ {name: 'Cote D\'Ivoire', code: 'CI'},
+ {name: 'Croatia', code: 'HR'},
+ {name: 'Cuba', code: 'CU'},
+ {name: 'Cyprus', code: 'CY'},
+ {name: 'Czech Republic', code: 'CZ'},
+ {name: 'Denmark', code: 'DK'},
+ {name: 'Djibouti', code: 'DJ'},
+ {name: 'Dominica', code: 'DM'},
+ {name: 'Dominican Republic', code: 'DO'},
+ {name: 'Ecuador', code: 'EC'},
+ {name: 'Egypt', code: 'EG'},
+ {name: 'El Salvador', code: 'SV'},
+ {name: 'Equatorial Guinea', code: 'GQ'},
+ {name: 'Eritrea', code: 'ER'},
+ {name: 'Estonia', code: 'EE'},
+ {name: 'Ethiopia', code: 'ET'},
+ {name: 'Falkland Islands (Malvinas)', code: 'FK'},
+ {name: 'Faroe Islands', code: 'FO'},
+ {name: 'Fiji', code: 'FJ'},
+ {name: 'Finland', code: 'FI'},
+ {name: 'France', code: 'FR'},
+ {name: 'French Guiana', code: 'GF'},
+ {name: 'French Polynesia', code: 'PF'},
+ {name: 'French Southern Territories', code: 'TF'},
+ {name: 'Gabon', code: 'GA'},
+ {name: 'Gambia', code: 'GM'},
+ {name: 'Georgia', code: 'GE'},
+ {name: 'Germany', code: 'DE'},
+ {name: 'Ghana', code: 'GH'},
+ {name: 'Gibraltar', code: 'GI'},
+ {name: 'Greece', code: 'GR'},
+ {name: 'Greenland', code: 'GL'},
+ {name: 'Grenada', code: 'GD'},
+ {name: 'Guadeloupe', code: 'GP'},
+ {name: 'Guam', code: 'GU'},
+ {name: 'Guatemala', code: 'GT'},
+ {name: 'Guernsey', code: 'GG'},
+ {name: 'Guinea', code: 'GN'},
+ {name: 'Guinea-Bissau', code: 'GW'},
+ {name: 'Guyana', code: 'GY'},
+ {name: 'Haiti', code: 'HT'},
+ {name: 'Heard Island and Mcdonald Islands', code: 'HM'},
+ {name: 'Holy See (Vatican City State)', code: 'VA'},
+ {name: 'Honduras', code: 'HN'},
+ {name: 'Hong Kong', code: 'HK'},
+ {name: 'Hungary', code: 'HU'},
+ {name: 'Iceland', code: 'IS'},
+ {name: 'India', code: 'IN'},
+ {name: 'Indonesia', code: 'ID'},
+ {name: 'Iran, Islamic Republic Of', code: 'IR'},
+ {name: 'Iraq', code: 'IQ'},
+ {name: 'Ireland', code: 'IE'},
+ {name: 'Isle of Man', code: 'IM'},
+ {name: 'Israel', code: 'IL'},
+ {name: 'Italy', code: 'IT'},
+ {name: 'Jamaica', code: 'JM'},
+ {name: 'Japan', code: 'JP'},
+ {name: 'Jersey', code: 'JE'},
+ {name: 'Jordan', code: 'JO'},
+ {name: 'Kazakhstan', code: 'KZ'},
+ {name: 'Kenya', code: 'KE'},
+ {name: 'Kiribati', code: 'KI'},
+ {name: 'Korea, Democratic People\'S Republic of', code: 'KP'},
+ {name: 'Korea, Republic of', code: 'KR'},
+ {name: 'Kuwait', code: 'KW'},
+ {name: 'Kyrgyzstan', code: 'KG'},
+ {name: 'Lao People\'S Democratic Republic', code: 'LA'},
+ {name: 'Latvia', code: 'LV'},
+ {name: 'Lebanon', code: 'LB'},
+ {name: 'Lesotho', code: 'LS'},
+ {name: 'Liberia', code: 'LR'},
+ {name: 'Libyan Arab Jamahiriya', code: 'LY'},
+ {name: 'Liechtenstein', code: 'LI'},
+ {name: 'Lithuania', code: 'LT'},
+ {name: 'Luxembourg', code: 'LU'},
+ {name: 'Macao', code: 'MO'},
+ {name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK'},
+ {name: 'Madagascar', code: 'MG'},
+ {name: 'Malawi', code: 'MW'},
+ {name: 'Malaysia', code: 'MY'},
+ {name: 'Maldives', code: 'MV'},
+ {name: 'Mali', code: 'ML'},
+ {name: 'Malta', code: 'MT'},
+ {name: 'Marshall Islands', code: 'MH'},
+ {name: 'Martinique', code: 'MQ'},
+ {name: 'Mauritania', code: 'MR'},
+ {name: 'Mauritius', code: 'MU'},
+ {name: 'Mayotte', code: 'YT'},
+ {name: 'Mexico', code: 'MX'},
+ {name: 'Micronesia, Federated States of', code: 'FM'},
+ {name: 'Moldova, Republic of', code: 'MD'},
+ {name: 'Monaco', code: 'MC'},
+ {name: 'Mongolia', code: 'MN'},
+ {name: 'Montserrat', code: 'MS'},
+ {name: 'Morocco', code: 'MA'},
+ {name: 'Mozambique', code: 'MZ'},
+ {name: 'Myanmar', code: 'MM'},
+ {name: 'Namibia', code: 'NA'},
+ {name: 'Nauru', code: 'NR'},
+ {name: 'Nepal', code: 'NP'},
+ {name: 'Netherlands', code: 'NL'},
+ {name: 'Netherlands Antilles', code: 'AN'},
+ {name: 'New Caledonia', code: 'NC'},
+ {name: 'New Zealand', code: 'NZ'},
+ {name: 'Nicaragua', code: 'NI'},
+ {name: 'Niger', code: 'NE'},
+ {name: 'Nigeria', code: 'NG'},
+ {name: 'Niue', code: 'NU'},
+ {name: 'Norfolk Island', code: 'NF'},
+ {name: 'Northern Mariana Islands', code: 'MP'},
+ {name: 'Norway', code: 'NO'},
+ {name: 'Oman', code: 'OM'},
+ {name: 'Pakistan', code: 'PK'},
+ {name: 'Palau', code: 'PW'},
+ {name: 'Palestinian Territory, Occupied', code: 'PS'},
+ {name: 'Panama', code: 'PA'},
+ {name: 'Papua New Guinea', code: 'PG'},
+ {name: 'Paraguay', code: 'PY'},
+ {name: 'Peru', code: 'PE'},
+ {name: 'Philippines', code: 'PH'},
+ {name: 'Pitcairn', code: 'PN'},
+ {name: 'Poland', code: 'PL'},
+ {name: 'Portugal', code: 'PT'},
+ {name: 'Puerto Rico', code: 'PR'},
+ {name: 'Qatar', code: 'QA'},
+ {name: 'Reunion', code: 'RE'},
+ {name: 'Romania', code: 'RO'},
+ {name: 'Russian Federation', code: 'RU'},
+ {name: 'RWANDA', code: 'RW'},
+ {name: 'Saint Helena', code: 'SH'},
+ {name: 'Saint Kitts and Nevis', code: 'KN'},
+ {name: 'Saint Lucia', code: 'LC'},
+ {name: 'Saint Pierre and Miquelon', code: 'PM'},
+ {name: 'Saint Vincent and the Grenadines', code: 'VC'},
+ {name: 'Samoa', code: 'WS'},
+ {name: 'San Marino', code: 'SM'},
+ {name: 'Sao Tome and Principe', code: 'ST'},
+ {name: 'Saudi Arabia', code: 'SA'},
+ {name: 'Senegal', code: 'SN'},
+ {name: 'Serbia and Montenegro', code: 'CS'},
+ {name: 'Seychelles', code: 'SC'},
+ {name: 'Sierra Leone', code: 'SL'},
+ {name: 'Singapore', code: 'SG'},
+ {name: 'Slovakia', code: 'SK'},
+ {name: 'Slovenia', code: 'SI'},
+ {name: 'Solomon Islands', code: 'SB'},
+ {name: 'Somalia', code: 'SO'},
+ {name: 'South Africa', code: 'ZA'},
+ {name: 'South Georgia and the South Sandwich Islands', code: 'GS'},
+ {name: 'Spain', code: 'ES'},
+ {name: 'Sri Lanka', code: 'LK'},
+ {name: 'Sudan', code: 'SD'},
+ {name: 'Suriname', code: 'SR'},
+ {name: 'Svalbard and Jan Mayen', code: 'SJ'},
+ {name: 'Swaziland', code: 'SZ'},
+ {name: 'Sweden', code: 'SE'},
+ {name: 'Switzerland', code: 'CH'},
+ {name: 'Syrian Arab Republic', code: 'SY'},
+ {name: 'Taiwan, Province of China', code: 'TW'},
+ {name: 'Tajikistan', code: 'TJ'},
+ {name: 'Tanzania, United Republic of', code: 'TZ'},
+ {name: 'Thailand', code: 'TH'},
+ {name: 'Timor-Leste', code: 'TL'},
+ {name: 'Togo', code: 'TG'},
+ {name: 'Tokelau', code: 'TK'},
+ {name: 'Tonga', code: 'TO'},
+ {name: 'Trinidad and Tobago', code: 'TT'},
+ {name: 'Tunisia', code: 'TN'},
+ {name: 'Turkey', code: 'TR'},
+ {name: 'Turkmenistan', code: 'TM'},
+ {name: 'Turks and Caicos Islands', code: 'TC'},
+ {name: 'Tuvalu', code: 'TV'},
+ {name: 'Uganda', code: 'UG'},
+ {name: 'Ukraine', code: 'UA'},
+ {name: 'United Arab Emirates', code: 'AE'},
+ {name: 'United Kingdom', code: 'GB'},
+ {name: 'United States', code: 'US'},
+ {name: 'United States Minor Outlying Islands', code: 'UM'},
+ {name: 'Uruguay', code: 'UY'},
+ {name: 'Uzbekistan', code: 'UZ'},
+ {name: 'Vanuatu', code: 'VU'},
+ {name: 'Venezuela', code: 'VE'},
+ {name: 'Viet Nam', code: 'VN'},
+ {name: 'Virgin Islands, British', code: 'VG'},
+ {name: 'Virgin Islands, U.S.', code: 'VI'},
+ {name: 'Wallis and Futuna', code: 'WF'},
+ {name: 'Western Sahara', code: 'EH'},
+ {name: 'Yemen', code: 'YE'},
+ {name: 'Zambia', code: 'ZM'},
+ {name: 'Zimbabwe', code: 'ZW'}
+ ]),
+
+});
diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js
index 92a5bf8dc..bdec9313b 100644
--- a/tests/dummy/app/router.js
+++ b/tests/dummy/app/router.js
@@ -7,6 +7,7 @@ var Router = Ember.Router.extend({
Router.map(function() {
this.route('introduction');
+ this.route('autocomplete');
this.route('button');
this.route('card');
this.route('checkbox');
diff --git a/tests/dummy/app/styles/app.scss b/tests/dummy/app/styles/app.scss
index 0a57ac5ae..693730a85 100644
--- a/tests/dummy/app/styles/app.scss
+++ b/tests/dummy/app/styles/app.scss
@@ -124,7 +124,7 @@ ul li:first-child {
body {
- &> .ember-view {
+ &> div.ember-view {
width: 100%;
height: 100%;
}
diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs
index 6e8aa4e1b..7c6089084 100644
--- a/tests/dummy/app/templates/application.hbs
+++ b/tests/dummy/app/templates/application.hbs
@@ -10,9 +10,9 @@
{{/if}}
-{{#paper-nav-container open=drawerOpen classNames="ember-app"}}
+{{#paper-nav-container open=drawerOpen class="ember-app"}}
- {{#paper-sidenav classNames="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true}}
+ {{#paper-sidenav class="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true}}
{{#paper-toolbar}}
@@ -26,6 +26,7 @@
{{#paper-list}}
{{#paper-item action="transitionTo" param="index"}}Introduction{{/paper-item}}
+ {{#paper-item action="transitionTo" param="autocomplete"}}Autocomplete{{/paper-item}}
{{#paper-item action="transitionTo" param="sidenav"}}Sidenav{{/paper-item}}
{{#paper-item action="transitionTo" param="typography"}}Typography{{/paper-item}}
{{#paper-item action="transitionTo" param="list"}}List{{/paper-item}}
diff --git a/tests/dummy/app/templates/autocomplete.hbs b/tests/dummy/app/templates/autocomplete.hbs
new file mode 100644
index 000000000..97de84ac9
--- /dev/null
+++ b/tests/dummy/app/templates/autocomplete.hbs
@@ -0,0 +1,323 @@
+{{#paper-toolbar}}
+
+{{/paper-toolbar}}
+
+{{#paper-content class="md-padding"}}
+
+
+{{#paper-card}}
+{{#paper-card-content}}
+
Basic Usage
+
Use \{{paper-autocomplete}}
to search for matches from local or remote data sources.
+
+ {{paper-autocomplete
+ disabled=firstDisabled
+ placeholder="Select a Country ..."
+ notFoundMessage="Oops country: \"%@\" doesn't exist here."
+ source=items lookupKey="name"
+ model=myModel}}
+
+ {{#if myModel}}
+ Selected country is {{myModel.name}}
+ ({{myModel.code}})
+ {{else}}
+ Nothing selected...
+ {{/if}}
+
+ {{#paper-checkbox checked=firstDisabled}}Disable input{{/paper-checkbox}}
+
+
+
+
Template
+{{#code-block language='handlebars'}}
+\{{paper-autocomplete
+ disabled=firstDisabled
+ placeholder="Select a Country ..."
+ notFoundMessage="Oops country: \"%@\" doesn't exist here."
+ source=items lookupKey="name"
+ model=myModel}}{{/code-block}}
+
+
Allow non existing items
+
Use attribute allowNonExisting=true
for the autocomplete to allow setting model to non existing items in the autocomplete. This is useful for search boxes.
+
+ {{paper-autocomplete minLength=0 allowNonExisting=true placeholder="Type e.g. ember, paper, one, two etc." source=arrayOfItems model=sixthModel}}
+
+ {{#if sixthModel}}
+ Selected thing was: {{sixthModel}}
+ {{else}}
+ Nothing is selected...
+ {{/if}}
+
+
+{{/paper-card-content}}
+{{/paper-card}}
+
+
+{{#paper-card}}
+{{#paper-card-content}}
+
Promise support
+
You may pass a promise to the source
attribute. This means you can use Ember Data async relationships directly, for example.
+ You can even use a computed property that returns a promise.
+ When dealing with Promises that possibly hit the server, the delay
attribute is recommended to set a delay for the search to start.
+ This way we avoid unecessary requests while the user types.
+ Promise values are cached unless noCache
is true
.
+
+
+ {{paper-autocomplete minLength=0 delay=300 placeholder="Type e.g. Ram, Test, etc." source=dataFromPromise lookupKey="name" model=otherModel cache-miss="updateFilter"}}
+
+ {{#if otherModel}}
+ You have selected: {{otherModel.name}} ({{otherModel.id}})
+ {{else}}
+ No Item Selected.
+ {{/if}}
+
+
+
Template
+{{#code-block language="handlebars"}}
+\{{paper-autocomplete minLength=0 delay=300 placeholder="Type e.g. Ram, Test, etc." source=dataFromPromise lookupKey="name" model=otherModel cache-miss="updateFilter"}}{{/code-block}}
+
+
Javascript (Ember-data)
+
+ In the above template we use the variable dataFromPromise
which is a computed property that returns a promise.
+ We are also using the cache-miss
action to update our computed property.
+ Here is a sample configuration:
+
+{{#code-block language="javascript"}}
+ ...
+ // searchText is received from the autocomplete component, this is what the user typed in the input field.
+ dataFromPromise: Ember.computed('filterText', function() {
+ let filterText = this.get('filterText');
+ return this.store.query('country', {
+ name: filterText
+ });
+ }),
+ actions: {
+ updateFilter(str) {
+ this.set('filterText', str);
+ }
+ }
+ ...{{/code-block}}
+
+
+
+{{/paper-card-content}}
+{{/paper-card}}
+
+{{#paper-card}}
+{{#paper-card-content}}
+
Block Custom template
+
Use \{{paper-autocomplete}}
with custom templates to show styled autocomplete results. In this example we also use minLength=0
which allow to see all results if input is empty.
+
+ {{#paper-autocomplete minLength=0 placeholder="Type e.g. ember, paper, one, two etc." source=arrayOfItems model=fourthModel as |searchText item index|}}
+
+ {{paper-icon icon="star"}}
+ {{paper-autocomplete-highlight searchText=searchText label=item}} (index {{index}} )
+
+ {{else}}
+ Whoops! Could not find "{{searchText}}".
+ {{/paper-autocomplete}}
+
+
+ {{#if fourthModel}}
+ Selected thing was: {{fourthModel}}
+ {{else}}
+ Nothing selected...
+ {{/if}}
+
+
+
Template
+{{#code-block language="handlebars"}}
+\{{#paper-autocomplete minLength=0 placeholder="Type e.g. ember, paper, one, two etc." source=arrayOfItems model=fourthModel as |item index searchText|}}}
+ <span class="item-title">
+ \{{paper-icon icon="star"}}
+ <span> \{{paper-autocomplete-highlight searchText=searchText label=item}} </span>
+ </span>
+\{{else}}
+ Whoops! Could not find "\{{searchText}}".
+\{{/paper-autocomplete}}{{/code-block}}
+
+
The custom template receives 3 block parameters (searchText, item and index).
+
+
+
+ - searchText This is the original searchText from the user.
+ - item This is the item directly from the source array. If it is an object you would forexample
+ need to reference it with
\{{item.name}}
. Not defined in the inverse template.
+ - index This is the index of the suggestions that are currently in the list. Not defined in the inverse template.
+
+
+
Blockless Custom template
+
Alternatively you can use the blockless/named componend approach which produces the same result:
+
+{{paper-autocomplete minLength=0 placeholder="Type e.g. ember, paper, one, two etc." source=arrayOfItems model=fourthModelB
+ itemComponent="example-item" notFoundComponent="not-found"}}
+
+
+ {{#if fourthModelB}}
+ Selected thing was: {{fourthModelB}}
+ {{else}}
+ Nothing selected...
+ {{/if}}
+
+
+
Template
+{{#code-block language="handlebars"}}
+\{{paper-autocomplete minLength=0 placeholder="Type e.g. ember, paper, one, two etc." source=arrayOfItems model=fourthModelB
+ itemComponent="example-item" notFoundComponent="not-found"}}{{/code-block}}
+
+{{#code-block language="handlebars"}}
+\{{!-- app/templates/components/not-found.hbs --}}
+Whoops! Could not find "\{{searchText}}".{{/code-block}}
+
+{{#code-block language="handlebars"}}
+\{{!-- app/templates/components/example-item.hbs --}}
+<span class="item-title">
+ \{{paper-icon icon="star"}}
+ <span>\{{paper-autocomplete-highlight searchText=searchText label=item}} (index \{{index}} )</span>
+</span>{{/code-block}}
+
+{{/paper-card-content}}
+{{/paper-card}}
+
+
+
+
+{{#paper-card}}
+{{#paper-card-content}}
+
Floating Label
+
The following example demonstrates floating labels being used as a normal form element.
+ {{paper-autocomplete floating=true placeholder="Select a Country ..." source=items lookupKey="name" model=thirdModel}}
+
+ {{#if thirdModel}}
+ Selected country is {{thirdModel.name}} ({{thirdModel.code}})
+ {{else}}
+ Nothing selected...
+ {{/if}}
+
+
Template
+{{#code-block language="handlebars"}}
+\{{paper-autocomplete floating=true placeholder="Select a Country ..." source=items lookupKey="name" model=thirdModel}}{{/code-block}}
+
+{{/paper-card-content}}
+{{/paper-card}}
+
+
+
Attributes for paper-autocomplete
+
+
+
+
+ Attribute |
+ Type |
+ Description |
+
+
+
+
+ source |
+ mixed |
+ The source attribute is used to look up possible suggestions for the autocomplete.
+ The source attribute accepts:
+
+ - Array of strings: Simple array of strings. Example:
['One', 'Two']
+ - Promise: This is useful if you want to fetch suggestions from the server with e.g. Ember-data or jQuery's $.ajax method. The action
cacheMiss may be useful to update the promise. See promise example above.
+ - Array of objects: If you pass array of objects, paper-autocomplete needs to know what key in each object to search in. Use in combination with
lookupKey . Example if you have provided [{id: 1, name="Car"}] as source, you will also need to configure the lookupKey to lookupKey="name" .
+
+ |
+
+
+ model |
+ mixed |
+ When a user selects item from the suggestions, model will be set and updated. Provide a model so you can do something about the value when user clicks the item. |
+
+
+ placeholder |
+ string |
+ Sets a placeholder for the autocomplete input field. |
+
+
+ minLength |
+ integer |
+ Sets how many characters the user must type before the autocomplete gives suggestions. Default is 1 . |
+
+
+ delay |
+ integer |
+ The delay attribute lets you configure how many milliseconds to wait before we trigger a search, this is
+ useful to avoid mass sending HTTP requests to your backend if you are using Function based source with
+ AJAX calls. Somewhere around 300 ms is good. |
+
+
+ noCache |
+ boolean |
+ Only effective if you use promise as source. This disables the cache of promise loaded suggestions. By default they are cached when loaded the first time. |
+
+
+ floating |
+ boolean |
+ Makes the autocomplete field a normal input field with floating labels. |
+
+
+ autoselect |
+ boolean |
+ When suggestions is being displayed, by default when autoselect is true it will select the first element as selected. Default is false. |
+
+
+ disabled |
+ boolean |
+ Disables the autocomplete. |
+
+
+ required |
+ boolean |
+ Makes the autocomplete a required field. |
+
+
+ allowNonExisting |
+ boolean |
+ allowNonExisting is useful for search boxes. It allows to use items that are not in the autocomplete selection. If you type e.g. "Chees" the model will also be set to "Chees". |
+
+
+ notFoundMessage |
+ string |
+ The message to display if no items was found. Default is: No matches found for "%@". . The %@ part will be replaced by the users input. |
+
+
+
+
+
Actions for paper-autocomplete
+
+
+
+
+ Action |
+ Description |
+
+
+
+
+ update-filter |
+ Triggered as soon as the filter changes. Has searchText as a parameter. |
+
+
+ debounced-update-filter |
+ Triggered delay ms after the filter changes. Has searchText as a parameter. |
+
+
+ cache-miss |
+ Triggered delay ms after the filter changes and there arent't any cached results for this text. Has searchText as a parameter. |
+
+
+ cache-hit |
+ Triggered delay ms after the filter changes and there are cached results for this text. Has searchText as a parameter. |
+
+
+
+
+
+{{/paper-content}}
diff --git a/tests/dummy/app/templates/button.hbs b/tests/dummy/app/templates/button.hbs
index f8055f739..0f4736404 100644
--- a/tests/dummy/app/templates/button.hbs
+++ b/tests/dummy/app/templates/button.hbs
@@ -6,7 +6,7 @@
Buttons
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding demo-buttons"}}
+{{#paper-content class="md-padding demo-buttons"}}
{{#paper-button action="flatButton"}}Button with action{{/paper-button}}
diff --git a/tests/dummy/app/templates/card.hbs b/tests/dummy/app/templates/card.hbs
index 8739aef6f..792929cf9 100644
--- a/tests/dummy/app/templates/card.hbs
+++ b/tests/dummy/app/templates/card.hbs
@@ -7,9 +7,9 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
- {{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+ {{#paper-content class="md-whiteframe-z1 list-demo"}}
{{#paper-card}}
{{#paper-card-content}}
diff --git a/tests/dummy/app/templates/checkbox.hbs b/tests/dummy/app/templates/checkbox.hbs
index 8ae944a0d..4a9a0f460 100644
--- a/tests/dummy/app/templates/checkbox.hbs
+++ b/tests/dummy/app/templates/checkbox.hbs
@@ -6,7 +6,7 @@
Checkboxes
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
{{#paper-checkbox checked=value1}}A checkbox: {{value1}}{{/paper-checkbox}}
{{#paper-checkbox checked=value2}}A checkbox: {{#if value2}}yep{{else}}nope{{/if}}{{/paper-checkbox}}
diff --git a/tests/dummy/app/templates/components/example-item.hbs b/tests/dummy/app/templates/components/example-item.hbs
new file mode 100644
index 000000000..4c7edf671
--- /dev/null
+++ b/tests/dummy/app/templates/components/example-item.hbs
@@ -0,0 +1,4 @@
+
+{{paper-icon icon="star"}}
+{{paper-autocomplete-highlight searchText=searchText label=item}} (index {{index}} )
+
diff --git a/tests/dummy/app/templates/components/not-found.hbs b/tests/dummy/app/templates/components/not-found.hbs
new file mode 100644
index 000000000..55ef0a18d
--- /dev/null
+++ b/tests/dummy/app/templates/components/not-found.hbs
@@ -0,0 +1 @@
+Whoops! Could not find "{{searchText}}".
diff --git a/tests/dummy/app/templates/divider.hbs b/tests/dummy/app/templates/divider.hbs
index f8f86f459..c078ee35a 100644
--- a/tests/dummy/app/templates/divider.hbs
+++ b/tests/dummy/app/templates/divider.hbs
@@ -7,10 +7,10 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Full width dividers
- {{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+ {{#paper-content class="md-whiteframe-z1 list-demo"}}
{{#paper-list}}
{{#each listData as |item|}}
{{#paper-item class="md-3-line"}}
@@ -29,7 +29,7 @@
{{/paper-content}}
Inset dividers
- {{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+ {{#paper-content class="md-whiteframe-z1 list-demo"}}
{{#paper-list}}
{{#each listData as |item|}}
{{#paper-item class="md-3-line"}}
@@ -49,7 +49,7 @@
Template
{{#code-block language='handlebars'}}
-\{{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+\{{#paper-content class="md-whiteframe-z1 list-demo"}}
\{{#paper-list}}
\{{#each listData as |item|}}
\{{#paper-item}}
diff --git a/tests/dummy/app/templates/icons.hbs b/tests/dummy/app/templates/icons.hbs
index bc0dad314..39184f9a8 100644
--- a/tests/dummy/app/templates/icons.hbs
+++ b/tests/dummy/app/templates/icons.hbs
@@ -7,19 +7,22 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding icon-demo"}}
+{{#paper-content class="md-padding icon-demo"}}
Template
Basic Icons
{{#code-block language='handlebars'}}
-\{{paper-icon icon="check"}}{{/code-block}}
-
Larger Icons
+ \{{paper-icon icon="check"}}
+ {{/code-block}}
+
Changing Sizes
{{#code-block language='handlebars'}}
-\{{paper-icon icon="check" size="lg"}}
-\{{paper-icon icon="check" size=2}}
-\{{paper-icon icon="check" size=3}}
-\{{paper-icon icon="check" size=4}}
-\{{paper-icon icon="check" size=5}}{{/code-block}}
+ \{{paper-icon icon="check" size="sm"}}
+ \{{paper-icon icon="check" size="lg"}}
+ \{{paper-icon icon="check" size=2}}
+ \{{paper-icon icon="check" size=3}}
+ \{{paper-icon icon="check" size=4}}
+ \{{paper-icon icon="check" size=5}}
+ {{/code-block}}
Spinners
{{#code-block language='handlebars'}}
\{{paper-icon icon="rotate-right" spin=true}}
diff --git a/tests/dummy/app/templates/index.hbs b/tests/dummy/app/templates/index.hbs
index c8e5a39ef..8c6c1f8bc 100644
--- a/tests/dummy/app/templates/index.hbs
+++ b/tests/dummy/app/templates/index.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Welcome to Ember Paper.
This project aims to bring Google's new Material Design to Ember. The goal is to encapsulate everything possible in Ember components. This project is packaged as an Ember-cli addon.
diff --git a/tests/dummy/app/templates/input.hbs b/tests/dummy/app/templates/input.hbs
index 6aeb4b75a..f4743447c 100644
--- a/tests/dummy/app/templates/input.hbs
+++ b/tests/dummy/app/templates/input.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
- {{paper-input label="Name" value=name}}
diff --git a/tests/dummy/app/templates/list-controls.hbs b/tests/dummy/app/templates/list-controls.hbs
index 9f5d0f2d6..c2d94af47 100644
--- a/tests/dummy/app/templates/list-controls.hbs
+++ b/tests/dummy/app/templates/list-controls.hbs
@@ -7,37 +7,37 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Basic Usage
- {{#paper-content classNames="md-whiteframe-z1 list-demo list-controls-demo"}}
+ {{#paper-content class="md-whiteframe-z1 list-demo list-controls-demo"}}
{{#paper-list}}
- {{#paper-subheader classNames="md-no-sticky"}}Single Action Checkboxes{{/paper-subheader}}
+ {{#paper-subheader class="md-no-sticky"}}Single Action Checkboxes{{/paper-subheader}}
{{#paper-item}}
Checkbox 1
- {{paper-checkbox classNames="md-secondary" checked=checkboxEnabled1}}
+ {{paper-checkbox class="md-secondary" checked=checkboxEnabled1}}
{{/paper-item}}
{{#paper-item}}
Checkbox 2
- {{paper-checkbox classNames="md-secondary" checked=checkboxEnabled2}}
+ {{paper-checkbox class="md-secondary" checked=checkboxEnabled2}}
{{/paper-item}}
{{paper-divider}}
- {{#paper-subheader classNames="md-no-sticky"}}Clickable Items with Secondary Controls{{/paper-subheader}}
+ {{#paper-subheader class="md-no-sticky"}}Clickable Items with Secondary Controls{{/paper-subheader}}
{{#paper-item action="transitionToWifiMenu"}}
{{paper-icon icon="network-wifi"}}
Wi-Fi
- {{paper-switch classNames="md-secondary" checked=wifiEnabled}}
+ {{paper-switch class="md-secondary" checked=wifiEnabled}}
{{/paper-item}}
{{#paper-item action="transitionToBluetoothMenu"}}
{{paper-icon icon="bluetooth"}}
Bluetooth
- {{paper-switch classNames="md-secondary" checked=bluetoothEnabled}}
+ {{paper-switch class="md-secondary" checked=bluetoothEnabled}}
{{/paper-item}}
{{#paper-item action="transitionToDataUsage"}}
@@ -47,7 +47,7 @@
{{paper-divider}}
- {{#paper-subheader classNames="md-no-sticky"}}Checkbox with Secondary Action{{/paper-subheader}}
+ {{#paper-subheader class="md-no-sticky"}}Checkbox with Secondary Action{{/paper-subheader}}
{{#each messageData as |item|}}
{{#paper-item}}
@@ -61,7 +61,7 @@
{{#paper-divider}}{{/paper-divider}}
- {{#paper-subheader classNames="md-no-sticky"}}Clickable Avatars{{/paper-subheader}}
+ {{#paper-subheader class="md-no-sticky"}}Clickable Avatars{{/paper-subheader}}
{{#each listData as |item|}}
{{#paper-item class="md-3-line" param=item action="goToPerson"}}
@@ -76,7 +76,7 @@
{{paper-divider}}
- {{#paper-subheader classNames="md-no-sticky"}}Avatar with Secondary Action Icon{{/paper-subheader}}
+ {{#paper-subheader class="md-no-sticky"}}Avatar with Secondary Action Icon{{/paper-subheader}}
{{#each listData as |item|}}
{{#paper-item class="md-3-line" param=item action="goToPerson"}}
@@ -100,32 +100,32 @@
{{#code-block language='handlebars'}}
\{{#paper-list}}
- \{{#paper-subheader classNames="md-no-sticky"}}Single Action Checkboxes\{{/paper-subheader}}
+ \{{#paper-subheader class="md-no-sticky"}}Single Action Checkboxes\{{/paper-subheader}}
\{{#paper-item}}
<p>Checkbox 1</p>
- \{{paper-checkbox classNames="md-secondary" checked=checkboxEnabled1}}
+ \{{paper-checkbox class="md-secondary" checked=checkboxEnabled1}}
\{{/paper-item}}
\{{#paper-item}}
<p>Checkbox 2</p>
- \{{paper-checkbox classNames="md-secondary" checked=checkboxEnabled2}}
+ \{{paper-checkbox class="md-secondary" checked=checkboxEnabled2}}
\{{/paper-item}}
\{{paper-divider}}
- \{{#paper-subheader classNames="md-no-sticky"}}Clickable Items with Secondary Controls\{{/paper-subheader}}
+ \{{#paper-subheader class="md-no-sticky"}}Clickable Items with Secondary Controls\{{/paper-subheader}}
\{{#paper-item action="transitionToWifiMenu"}}
\{{paper-icon icon="network-wifi"}}
<p>Wi-Fi</p>
- \{{paper-switch classNames="md-secondary" checked=wifiEnabled}}
+ \{{paper-switch class="md-secondary" checked=wifiEnabled}}
\{{/paper-item}}
\{{#paper-item action="transitionToBluetoothMenu"}}
\{{paper-icon icon="bluetooth"}}
<p>Bluetooth</p>
- \{{paper-switch classNames="md-secondary" checked=bluetoothEnabled}}
+ \{{paper-switch class="md-secondary" checked=bluetoothEnabled}}
\{{/paper-item}}
\{{#paper-item action="transitionToDataUsage"}}
@@ -135,7 +135,7 @@
\{{paper-divider}}
- \{{#paper-subheader classNames="md-no-sticky"}}Checkbox with Secondary Action\{{/paper-subheader}}
+ \{{#paper-subheader class="md-no-sticky"}}Checkbox with Secondary Action\{{/paper-subheader}}
\{{#each messageData as |item|}}
\{{#paper-item}}
@@ -149,7 +149,7 @@
\{{#paper-divider}}\{{/paper-divider}}
- \{{#paper-subheader classNames="md-no-sticky"}}Clickable Avatars\{{/paper-subheader}}
+ \{{#paper-subheader class="md-no-sticky"}}Clickable Avatars\{{/paper-subheader}}
\{{#each listData as |item|}}
\{{#paper-item class="md-3-line" param=item action="goToPerson"}}
@@ -164,7 +164,7 @@
\{{paper-divider}}
- \{{#paper-subheader classNames="md-no-sticky"}}Avatar with Secondary Action Icon\{{/paper-subheader}}
+ \{{#paper-subheader class="md-no-sticky"}}Avatar with Secondary Action Icon\{{/paper-subheader}}
\{{#each listData as |item|}}
\{{#paper-item class="md-3-line" param=item action="goToPerson"}}
diff --git a/tests/dummy/app/templates/list.hbs b/tests/dummy/app/templates/list.hbs
index c600bbba8..3214763b1 100644
--- a/tests/dummy/app/templates/list.hbs
+++ b/tests/dummy/app/templates/list.hbs
@@ -7,10 +7,10 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Basic Usage
- {{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+ {{#paper-content class="md-whiteframe-z1 list-demo"}}
{{#paper-list}}
{{#each listData as |item|}}
{{#paper-item class="md-3-line"}}
@@ -30,7 +30,7 @@
Template
{{#code-block language='handlebars'}}
-\{{#paper-content classNames="md-whiteframe-z1 list-demo"}}
+\{{#paper-content class="md-whiteframe-z1 list-demo"}}
\{{#paper-list}}
\{{#each listData as |item|}}
\{{#paper-item class="md-3-line"}}
diff --git a/tests/dummy/app/templates/progress-circular.hbs b/tests/dummy/app/templates/progress-circular.hbs
index bfcb40f67..0fee825b4 100644
--- a/tests/dummy/app/templates/progress-circular.hbs
+++ b/tests/dummy/app/templates/progress-circular.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Basic Usage
Determinate
@@ -25,10 +25,10 @@
Theming
- {{paper-progress-circular classNames="md-hue-2"}}
+ {{paper-progress-circular class="md-hue-2"}}
{{paper-progress-circular accent=true}}
- {{paper-progress-circular accent=true classNames="md-hue-1"}}
- {{paper-progress-circular warn=true classNames="md-hue-3"}}
+ {{paper-progress-circular accent=true class="md-hue-1"}}
+ {{paper-progress-circular warn=true class="md-hue-3"}}
{{paper-progress-circular warn=true}}
diff --git a/tests/dummy/app/templates/progress-linear.hbs b/tests/dummy/app/templates/progress-linear.hbs
index 4b390f5be..1c984ab13 100644
--- a/tests/dummy/app/templates/progress-linear.hbs
+++ b/tests/dummy/app/templates/progress-linear.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Basic Usage
diff --git a/tests/dummy/app/templates/radio.hbs b/tests/dummy/app/templates/radio.hbs
index abaf553a6..9fd5b1ace 100644
--- a/tests/dummy/app/templates/radio.hbs
+++ b/tests/dummy/app/templates/radio.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
- {{#paper-radio}}A radio button{{/paper-radio}}
diff --git a/tests/dummy/app/templates/sidenav.hbs b/tests/dummy/app/templates/sidenav.hbs
index a7551c599..a3a4e605c 100644
--- a/tests/dummy/app/templates/sidenav.hbs
+++ b/tests/dummy/app/templates/sidenav.hbs
@@ -7,13 +7,13 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
Try to resize this webpage.
Template
-{{#code-block language='handlebars'}}\{{#paper-nav-container open=drawerOpen classNames="ember-app"}}
+{{#code-block language='handlebars'}}\{{#paper-nav-container open=drawerOpen class="ember-app"}}
- \{{#paper-sidenav classNames="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true}}
+ \{{#paper-sidenav class="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true}}
\{{#paper-toolbar}}
<div class="md-toolbar-tools">
diff --git a/tests/dummy/app/templates/slider.hbs b/tests/dummy/app/templates/slider.hbs
index 1505425dc..c7a61a530 100644
--- a/tests/dummy/app/templates/slider.hbs
+++ b/tests/dummy/app/templates/slider.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
RGB
@@ -27,7 +27,7 @@
G
- {{paper-slider flex=true min='0' max='255' value=color.green classNames='md-accent'}}
+ {{paper-slider flex=true min='0' max='255' value=color.green class='md-accent'}}
{{input type="number" value=color.green}}
@@ -37,7 +37,7 @@
B
- {{paper-slider flex=true min='0' max='255' value=color.blue classNames='md-primary'}}
+ {{paper-slider flex=true min='0' max='255' value=color.blue class='md-primary'}}
{{input type="number" value=color.blue}}
@@ -91,7 +91,7 @@
<div flex="10" layout layout-align="center center">
<span>G</span>
</div>
- \{{paper-slider flex=true min='0' max='255' value=color.green classNames='md-accent'}}
+ \{{paper-slider flex=true min='0' max='255' value=color.green class='md-accent'}}
<div flex="20" layout layout-align="center center">
\{{input type="number" value=color.green}}
</div>
@@ -101,7 +101,7 @@
<div flex="10" layout layout-align="center center">
<span>B</span>
</div>
- \{{paper-slider flex=true min='0' max='255' value=color.blue classNames='md-primary'}}
+ \{{paper-slider flex=true min='0' max='255' value=color.blue class='md-primary'}}
<div flex="20" layout layout-align="center center">
\{{input type="number" value=color.blue}}
</div>
diff --git a/tests/dummy/app/templates/switch.hbs b/tests/dummy/app/templates/switch.hbs
index 2131ee103..3b9d5f999 100644
--- a/tests/dummy/app/templates/switch.hbs
+++ b/tests/dummy/app/templates/switch.hbs
@@ -7,7 +7,7 @@
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}
{{#paper-switch checked=booleanProp1}} {{booleanProp1}} {{/paper-switch}}
diff --git a/tests/dummy/app/templates/toolbar.hbs b/tests/dummy/app/templates/toolbar.hbs
index 03fd2968d..36625b898 100644
--- a/tests/dummy/app/templates/toolbar.hbs
+++ b/tests/dummy/app/templates/toolbar.hbs
@@ -6,7 +6,7 @@
Toolbars
{{/paper-toolbar}}
-{{#paper-content classNames="md-padding"}}
+{{#paper-content class="md-padding"}}