Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

md-input directive #848

Closed
wants to merge 2 commits into from
Closed
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
101 changes: 101 additions & 0 deletions src/components/input/_input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

$tff-font-size: 0.75em;
$tff-line-height:26px;
$tff-transition: all 0.15s $swift-ease-in-out-timing-function;
// - `label` element (aka hint)
$tff-hint-offset-large : 22px;
$tff-hint-offset-small : 4px;
$ttf-hint-offset-scale : 0.75;
// - `line` element
$tff-line-focused-width: 2px;
$tff-line-disabled-width: 0px;
$tff-line-dot-width: 1px;
$tff-line-dot-size: 3px;
$tff-line-dashed: #cfcfcf;

$tff-margin: 10px 0 (10px - $tff-line-focused-width) 0;

md-input-two {

label {
display: block;
font-size: $tff-font-size;
}

textarea,
input[type="text"],
input[type="password"],
input[type="datetime"],
input[type="datetime-local"],
input[type="date"],
input[type="month"],
input[type="time"],
input[type="week"],
input[type="number"],
input[type="email"],
input[type="url"],
input[type="search"],
input[type="tel"],
input[type="color"] {
display: block;
border-width: 0 0 1px 0;
padding-top: 2px;
line-height: $tff-line-height;
padding-bottom: 1px;

&:focus {
outline: 0;
}
}

input, textarea {
background: none;
}
}

// Light-Theme
md-input-two {
padding-bottom: $tff-line-focused-width;
margin: $tff-margin;

position: relative;
display: block;

label {
font-size: 1em;
z-index: 1;
pointer-events: none;
-webkit-font-smoothing: antialiased;

&:hover {
cursor: text;
}
}

label {
transform: translate3d(0, $tff-hint-offset-large, 0);
transform-origin: left center;
transition: $tff-transition;
}

&.md-input-focused,
&.md-input-has-value {
label {
transform: translate3d(0, $tff-hint-offset-small, 0) scale($ttf-hint-offset-scale);
}
}
&.md-input-focused {
input, textarea {
border-bottom-width: $tff-line-focused-width;
padding-bottom: 0;
}
}

[disabled] {
background-size: $tff-line-dot-width $tff-line-dot-size;
background-position: 0 bottom;
background-size: (1px + 1px) $tff-line-dot-size;
background-repeat: repeat-x;
pointer-events: none;
}
}
5 changes: 5 additions & 0 deletions src/components/input/demoNew/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<md-content ng-init="SHOW=true">
<md-input-two foo="bar" ng-if="SHOW" ng-model="test">
Hello, {{SHOW}}
</md-input-two>
</md-content>
1 change: 1 addition & 0 deletions src/components/input/demoNew/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
angular.module('testNewApp', ['ngMaterial']);
54 changes: 54 additions & 0 deletions src/components/input/input-theme.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
$tff-focus-color: map-get($primary-color-palette, '500') !default;
$tff-text-color: $foreground-primary-color !default;
$tff-hint-small-color: mix($foreground-secondary-color, $foreground-tertiary-color, 40%) !default;
$tff-hint-color: $foreground-tertiary-color !default;
$tff-line-color: $foreground-quarternary-color !default;
$tff-disabled-line-color: mix($foreground-tertiary-color, $foreground-quarternary-color) !default;
$tff-disabled-color: $foreground-quarternary-color !default;

md-input-two.md-#{$theme-name}-theme {
input, textarea {
text-shadow: $foreground-text-shadow;
@include input-placeholder($tff-hint-color);
}

label {
text-shadow: $foreground-text-shadow;
color: $tff-hint-color;
}

input, textarea {
color: $tff-text-color;
border-color: $tff-line-color;
}

&.md-input-focused {
input, textarea {
border-color: $tff-focus-color;
}
label {
color: $tff-focus-color;
}
&.md-input-has-value {
@if $dark-theme {
label {
color: lighten($tff-focus-color, 10%);
}
}
}
}

&.md-input-has-value:not(.md-input-focused) {
label {
color: $tff-hint-small-color;
}
}

&[disabled] {
input, textarea {
border-bottom-color: $tff-disabled-color;
color: $tff-hint-color;
background-image: linear-gradient(to right, $tff-disabled-line-color 0%, $tff-disabled-line-color 50%, rgba(0, 0, 0, 0) 0%);
}
}
}
81 changes: 81 additions & 0 deletions src/components/input/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
angular.module('material.components.input', [])

.directive('mdInputTwo', InputDirective);

function InputDirective($compile, $injector) {
var PRIORITY = 49;
var copyableAttributes = {};

return {
priority: PRIORITY,
compile: compile,
terminal: true
};

function compile(element, attr) {
var label = angular.element('<label>').append(element.contents());
var input = angular.element(angular.isDefined(attr.mdMultiline) ? '<textarea>' : '<input>');

// Copy relevant attributes down to the input element: attrs that either aren't a directive,
// or are a directive that has already run (a directive with higher priority)
// For example, ng-if would NOT be copied down to the input because it has a higher priority
angular.forEach(element[0].attributes, function(data) {
var attrName = data.name;
var attrValue = data.value;

// Cache the test of whether this attribute should be copied, so it only has to
// be run once.
if (!copyableAttributes.hasOwnProperty(attrName)) {
copyableAttributes[attrName] = !attrIsHigherPriority(attrName);
}

if (copyableAttributes[attrName]) {
input[0].setAttribute(attrName, attrValue);
}
});

function attrIsHigherPriority(attrName) {
var injectName = attr.$normalize(attrName) + 'Directive';
var directives = $injector.has(injectName) ? $injector.get(injectName) : [];

return directives.every(function(dir) {
return dir.priority > PRIORITY;
});
}

element.append(label).append(input);

return postLink;
}

function postLink(scope, element, attr) {
$compile(element.contents())(scope);

// Make sure we aren't selecting an input the user might have put inside the label
var input = angular.element(element[0].querySelector(
(angular.isDefined(attr.mdMultiline) ? 'textarea' : 'input') + ':last-of-type'
));
var ngModelCtrl = input.data('$ngModelController');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be:

var ngModelCtrl = input.controller('ngModel');

Or does that look at inherited data too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it does --- but for ng-model that does not seem like an issue, in general

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it looks at inherited data. I just did that incase a parent has a model and the input doesn't.


ngModelCtrl && setupFloatingLabel();

//*********
// Methods
//*********

function setupFloatingLabel() {
scope.$watch(function() {
return ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue);
}, function isEmptyWatch(value) {
element.toggleClass('md-input-has-value', !value);
});

input.on('focus', function() {
element.addClass('md-input-focused');
});
input.on('blur', function() {
element.removeClass('md-input-focused');
});
}
}
}