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

Commit

Permalink
fix(textfloat): added support for label/hint expressions
Browse files Browse the repository at this point in the history
Updated unit tests.
Closes #462
  • Loading branch information
ThomasBurleson committed Oct 28, 2014
1 parent c012f99 commit 3674a51
Show file tree
Hide file tree
Showing 2 changed files with 257 additions and 41 deletions.
15 changes: 9 additions & 6 deletions src/components/textField/textField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @description
* Form
*/
angular.module('material.components.textField', ['material.core'])
angular.module('material.components.textField', ['material.core', 'material.services.theming'])
.directive('mdInputGroup', [ mdInputGroupDirective ])
.directive('mdInput', ['$mdUtil', mdInputDirective ])
.directive('mdTextFloat', [ '$mdTheming', mdTextFloatDirective ]);
Expand Down Expand Up @@ -42,6 +42,7 @@ function mdTextFloatDirective($mdTheming) {
replace: true,
scope : {
fid : '@?',
label : '@?',
value : '=ngModel'
},
compile : function() {
Expand All @@ -53,21 +54,23 @@ function mdTextFloatDirective($mdTheming) {
scope.isDisabled = true;
}

// transpose the `label` value
scope.label = attrs.label || "";
// transpose the `label`, type, and fid properties
scope.fid = scope.fid || scope.label;

scope.inputType = attrs.type || "text";
element.removeAttr('type');

// transpose optional `type` and `class` settings
element.attr('type', attrs.type || "text");
element.attr('class', attrs.class );

},
post: $mdTheming
};
},
template:
'<md-input-group ng-disabled="isDisabled" tabindex="-1">' +
' <label for="{{fid}}" tabindex="-1">{{label}}</label>' +
' <md-input id="{{fid}}" ng-model="value"></md-input>' +
' <label for="{{fid}}" >{{label}}</label>' +
' <md-input id="{{fid}}" ng-model="value" type="{{inputType}}"></md-input>' +
'</md-input-group>'
};
}
Expand Down
283 changes: 248 additions & 35 deletions src/components/textField/textField.spec.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,257 @@
xdescribe('mdInputGroup directive', function() {
describe('Text Field directives', function() {
beforeEach(module('material.components.textField'));

function setup(inputAttrs) {
describe('- mdInputGroup', function() {
var scope;

beforeEach(function() {
scope = {
user : {
firstName: 'Thomas',
lastName: 'Burleson',
email: 'ThomasBurleson@gmail.com',
password: 'your password is incorrect'
}
}
});

it('should set input class for focus & blur', function() {
var expressions = {label:"Firstname", model:"user.firstName"},
el = setupInputGroup( expressions, scope),
input = el.find('input');

input.triggerHandler('focus');
expect(el.hasClass('md-input-focused')).toBe(true);
input.triggerHandler('blur');
expect(el.hasClass('md-input-focused')).toBe(false);
});

it('should set input class for input event', function() {
var expressions = {label:"email", model:"user.email", type:"email"},
el = setupInputGroup( expressions, scope),
input = el.find('input');

expect(el.hasClass('md-input-has-value')).toBe(true);

input.val('');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(false);

input.val('ThomasBurleson@gmail.com');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(true);
});

it('should set input class for ngModel render', function() {
var expressions = {label:"Firstname", model:"user.firstName"},
el = setupInputGroup( expressions, scope),
input = el.find('input');

expect(el.hasClass('md-input-has-value')).toBe(true);

input.scope().$apply('user.firstName = ""');
expect(el.hasClass('md-input-has-value')).toBe(false);

input.scope().$apply('user.firstName = "Thomas"');
expect(el.hasClass('md-input-has-value')).toBe(true);
});

});

describe(' - mdTextFloat', function() {
var model;
beforeEach(function() {
model = {
labels : {
firstName: 'FirstName',
lastName: 'LastName',
email: 'eMail',
password: 'Password'
},
user : {
firstName: 'Andrew',
lastName: 'Joslin',
email: 'AndrewJoslin@drifty.com',
password: 'public'
}
}
});

it('should set input type `password` properly', function() {
var el = setupTextFloat( { type:"password" }, model);
expect( el.find('input').attr('type')).toBe("password");
expect( el.find('input').val()).toBe("");
});
it('should set input type `email` properly', function() {
var el = setupTextFloat( { type:"email" }, model);
expect( el.find('input').attr('type')).toBe("email");
expect( el.find('input').val()).toBe("");
});

it('should set a static label properly', function() {
var el = setupTextFloat( { label:"motto" }, model);
expect( el.find('label').text() ).toBe("motto");

expect( el.find('input').attr('type')).toBe("text");
expect( el.find('input').val()).toBe("");
});
it('should update a label from model changes.', function() {
var markup ='<md-text-float ' +
' label="{{labels.firstName}}" ' +
' ng-model="user.firstName" >' +
'</md-text-float>';
var el = buildElement( markup, model);

expect( el.find('input').val() ).toBe("Andrew");
expect( el.find('label').text() ).toBe("FirstName");

// Change model value of the `firstName` [field] label
// then check if the dom is updated

var val2 = "Corporate Title:";
el.find('label').scope().$apply(function(){
model.labels.firstName = val2;
});
expect( el.find('label').text() ).toBe( val2 );

});
it('should update an input value from model changes.', function() {
var markup ='<md-text-float ' +
' label="{{labels.firstName}}" ' +
' ng-model="user.firstName" >' +
'</md-text-float>';
var el = buildElement( markup, model);
var input = el.find('input');

expect( input.val() ).toBe("Andrew");

var name = "AngularJS";
input.scope().$apply(function(){
model.user.firstName = name;
});
expect( input.val() ).toBe( name );

});
it('should update a model value from input changes.', function() {
var markup ='<md-text-float ' +
' label="{{labels.firstName}}" ' +
' ng-model="user.firstName" >' +
'</md-text-float>';
var el = buildElement( markup, model);
var input = el.find('input');

expect( input.val() ).toBe( model.user.firstName );

input.val( "AngularJS" );
input.triggerHandler('input');
expect( model.user.firstName ).toBe( "AngularJS" );

});

it('should set input class for focus & blur', function() {
var expressions = {label:"Firstname", model:"user.firstName"},
el = setupTextFloat( expressions, model),
input = el.find('input');

input.triggerHandler('focus');
expect(el.hasClass('md-input-focused')).toBe(true);
input.triggerHandler('blur');
expect(el.hasClass('md-input-focused')).toBe(false);
});
it('should set input class for input event', function() {
var expressions = {label:"password", model:"user.password", type:"password"},
el = setupTextFloat( expressions, model),
input = el.find('input');

expect(el.hasClass('md-input-has-value')).toBe(true);

input.val('');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(false);

input.val('ThomasBurleson@gmail.com');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(true);
});

it('should set input class for ngModel changes', function() {
var expressions = {label:"Password", model:"user.password", type:"password"},
el = setupTextFloat( expressions, model),
input = el.find('input');

expect(el.hasClass('md-input-has-value')).toBe(true);

input.scope().$apply(function(){ model.user.password = ""; });
expect(el.hasClass('md-input-has-value')).toBe(false);

input.scope().$apply(function() { model.user.password = "hiddenValley"; });
expect(el.hasClass('md-input-has-value')).toBe(true);
});

});

// ****************************************************************
// Utility `setup` methods
// ****************************************************************

var templates = {
md_text_float : '<md-text-float ' +
' type="{{type}}" ' +
' label="{{label}}" ' +
' ng-model="{{model}}" >' +
'</md-text-float>',

md_input_group: '<div class="md-input-group" tabindex="-1">' +
' <label>{{label}}</label>' +
' <md-input id="{{id}}" type="{{type}}" ng-model="{{model}}"></md-input>' +
'</div>'
};

/**
* Build a text float group using the `<md-input-group />` markup template
*/
function setupInputGroup(expressions, values) {
values = angular.extend({},{type:"text", id:''},values||{});

return buildElement( templates.md_input_group, values, angular.extend({}, expressions||{}));
}

/**
* Build a text float group using the `<md-text-float />` markup template
*/
function setupTextFloat(expressions, values) {
values = angular.extend({ modelValue:"",type:'text' }, values || {});

var defaults = {model:"modelValue", label:""};
var tokens = angular.extend({}, defaults, expressions||{} );

return buildElement( templates.md_text_float, values, tokens );
}

/**
* Use the specified template markup, $compile to the DOM build
* and link both the bindings and attribute assignments.
* @returns {*} DOM Element
*/
function buildElement( template, scope, interpolationScope ) {
var el;
inject(function($compile, $rootScope) {
el = $compile('<div class="md-input-group md-input-group-theme-light-blue">' +
'<label for="ftitle">Title</label>' +
'<md-input id="ftitle" type="text" '+(inputAttrs||'')+'>' +
'</div>')($rootScope.$new());

inject(function($compile, $interpolate, $rootScope) {
scope = angular.extend( $rootScope.$new(), scope || {});

// First substitute interpolation values into the template... if any
if ( interpolationScope ) {
template = $interpolate( template )( interpolationScope );
}

// Compile the template using the scope model(s)
el = $compile( template )( scope );
$rootScope.$apply();

});
return el;
}
it('should set input class for focus & blur', function() {
var el = setup();
var input = el.find('input');
input.triggerHandler('focus');
expect(el.hasClass('md-input-focused')).toBe(true);
input.triggerHandler('blur');
expect(el.hasClass('md-input-focused')).toBe(false);
});

it('should set input class for input event', function() {
var el = setup();
var input = el.find('input');
input.val('cat');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(true);
input.val('');
input.triggerHandler('input');
expect(el.hasClass('md-input-has-value')).toBe(false);
});

it('should set input class for ngModel render', function() {
var el = setup('ng-model="something"');
var input = el.find('input');
expect(el.hasClass('md-input-has-value')).toBe(false);
input.scope().$apply('something = "123"');
expect(el.hasClass('md-input-has-value')).toBe(true);
input.scope().$apply('something = ""');
expect(el.hasClass('md-input-has-value')).toBe(false);
});
});


0 comments on commit 3674a51

Please sign in to comment.