Created
January 28, 2016 22:33
-
-
Save MeoMix/4241564ebe32eeb725ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.input { | |
} | |
.textInput { | |
width: 100%; | |
/* | |
This needs to be 7px because of 1px border-bottom, otherwise I get into odd-pixel math. | |
I need 1px border-bottom due to a bug in Chrome: http://stackoverflow.com/questions/26951053/jumpy-transition-when-only-modifying-box-shadow-looks-fine-with-box-shadow-bo | |
*/ | |
padding: 8px 0 7px 0; | |
font: inherit; | |
color: inherit; | |
background-color: transparent; | |
border-top: none; | |
border-right: none; | |
border-left: none; | |
border-bottom-width: 1px; | |
outline: none; | |
transition: box-shadow .1s cubic-bezier(.39,.575,.565,1), border .1s cubic-bezier(.39,.575,.565,1); | |
margin-bottom: 8px; | |
border-bottom-color: rgba(0, 0, 0, .26); | |
font-size: 16px; | |
line-height: 16px; | |
height: 36px; | |
} | |
.textInput:not(.isInvalid):focus { | |
border-bottom-color: rgb(66,133,244); | |
box-shadow: inset 0 -1px rgb(66,133,244); | |
} | |
.isInvalid:focus { | |
border-bottom-color: rgb(219, 68, 55); | |
box-shadow: inset 0 -1px rgb(219, 68, 55); | |
} | |
.isInvalid:focus + .characterCountHint { | |
color: rgb(219,68,55); | |
} | |
.inputWrapper.hasValue .placeholder { | |
transform: translate(-12.5%, 0) scale(0.75); | |
} | |
.placeholder { | |
font-size: 16px; | |
/* 12px because when scaled down by 0.75 it's 12px tall. */ | |
line-height: 12px; | |
color: rgba(0, 0, 0, .54); | |
display: inline-block; | |
transform: translate(0, 25px) scale(1); | |
transition: transform .2s cubic-bezier(.39, .575, .565, 1); | |
pointer-events: none; | |
} | |
.inputWrapper { | |
display: flex; | |
flex-direction: column; | |
padding-top: 16px; | |
} | |
.characterCount { | |
height: 14px; | |
font-size: 12px; | |
composes: darkSecondary from 'color'; | |
cursor: default; | |
text-align: right; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Model } from 'backbone'; | |
import _ from 'lodash'; | |
export default Model.extend({ | |
defaults: { | |
placeholder: '', | |
value: '', | |
maxLength: -1, | |
isValid: false, | |
isRequired: false, | |
isMultiline: false | |
}, | |
initialize() { | |
this.on('change:value', this._onChangeValue); | |
}, | |
setInitialValues(initialValues) { | |
_.forOwn(initialValues, (value, key) => { | |
if (!_.isUndefined(value) && !_.isNaN(value)) { | |
this.set(key, value); | |
} | |
}); | |
}, | |
_onChangeValue(model, value) { | |
let isValid = value.length > 0; | |
const maxLength = this.get('maxLength'); | |
if (isValid && maxLength >= 0) { | |
isValid = value.length <= maxLength; | |
} | |
this.set('isValid', isValid); | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LayoutView } from 'marionette'; | |
import template from './input.hbs!'; | |
import styles from './input.css!'; | |
import Input from './input'; | |
import _ from 'lodash'; | |
const InputView = LayoutView.extend({ | |
tagName: 'streamus-input', | |
className: styles.input, | |
template, | |
templateHelpers: { | |
styles: styles | |
}, | |
ui: { | |
input: 'input', | |
inputWrapper: 'inputWrapper', | |
characterCount: 'characterCount' | |
}, | |
events: { | |
'input': '_onInput' | |
}, | |
modelEvents: { | |
'change:value': '_onChangeValue', | |
'change:isValid': '_onChangeIsValid' | |
}, | |
initialize() { | |
this.model.setInitialValues({ | |
placeholder: this.$el.attr('placeholder'), | |
isRequired: this.el.hasAttribute('required'), | |
isMultiline: this.el.hasAttribute('multiline'), | |
value: _.parseInt(this.$el.attr('value')), | |
maxLength: _.parseInt(this.$el.attr('maxlength')) | |
}); | |
}, | |
_onInput() { | |
this.model.set('value', this.ui.input.val()); | |
}, | |
_onChangeValue(model, value) { | |
this.ui.characterCount.text(value.length); | |
this.ui.inputWrapper.toggleClass(styles.hasValue, value.length > 0); | |
if (model.get('isMultiline')) { | |
// If height is not set to 'auto' then input will not shrink on text deletion. | |
if (model.previous('value').length > value.length) { | |
this.ui.value.height('auto'); | |
} | |
this.ui.value.innerHeight(this.ui.value[0].scrollHeight); | |
} | |
}, | |
_onChangeIsValid(model, isValid) { | |
this.ui.input.toggleClass(styles.isInvalid, !isValid); | |
} | |
}); | |
document.registerElement('streamus-input', { | |
prototype: _.extend(Object.create(HTMLElement.prototype), { | |
createdCallback() { | |
const inputView = new InputView({ | |
el: this, | |
model: new Input() | |
}); | |
inputView.render(); | |
this._view = inputView; | |
}, | |
attachedCallback() { | |
this._view.triggerMethod('attach'); | |
}, | |
detachedCallback() { | |
this._view.destroy(); | |
delete this._view; | |
} | |
}) | |
}); | |
export default InputView; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment