angular-shims-placeholder
Advanced tools
Comparing version 0.4.2 to 0.4.3
{ | ||
"name": "angular-shims-placeholder", | ||
"description": "Angular directive to emulate the `placeholder` attribute on text and password input fields for old browsers, such as IE9, IE8, and below", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"homepage": "https://github.com/cvn/angular-shims-placeholder", | ||
@@ -6,0 +6,0 @@ "authors": [ |
@@ -1,218 +0,299 @@ | ||
/*! angular-shims-placeholder - v0.4.2 - 2015-05-11 | ||
/*! angular-shims-placeholder - v0.4.3 - 2015-06-14 | ||
* https://github.com/cvn/angular-shims-placeholder | ||
* Copyright (c) 2015 Chad von Nau; Licensed MIT */ | ||
(function (angular, document, undefined) { | ||
'use strict'; | ||
angular.module('ng.shims.placeholder', []).service('placeholderSniffer', [ | ||
'$document', | ||
function ($document) { | ||
this.emptyClassName = 'empty', this.hasPlaceholder = function () { | ||
var test = $document[0].createElement('input'); | ||
return test.placeholder !== void 0; | ||
}; | ||
} | ||
]).directive('placeholder', [ | ||
'$timeout', | ||
'$document', | ||
'$interpolate', | ||
'$injector', | ||
'placeholderSniffer', | ||
function ($timeout, $document, $interpolate, $injector, placeholderSniffer) { | ||
if (placeholderSniffer.hasPlaceholder()) | ||
return {}; | ||
var documentListenersApplied = false, angularVersion = parseFloat(angular.version.full); | ||
try { | ||
var $animate = $injector.get('$animate'); | ||
} catch (e) { | ||
} | ||
return { | ||
restrict: 'A', | ||
require: '?ngModel', | ||
priority: angularVersion >= 1.2 ? 110 : -10, | ||
link: function (scope, elem, attrs, ngModel) { | ||
var orig_val = getValue(), domElem = elem[0], elemType = domElem.nodeName.toLowerCase(), isInput = elemType === 'input' || elemType === 'textarea', is_pwd = attrs.type === 'password', text = attrs.placeholder, emptyClassName = placeholderSniffer.emptyClassName, hiddenClassName = 'ng-hide', clone; | ||
if (!isInput) { | ||
return; | ||
} | ||
attrs.$observe('placeholder', function (newValue) { | ||
changePlaceholder(newValue); | ||
}); | ||
if (is_pwd) { | ||
setupPasswordPlaceholder(); | ||
} | ||
setValue(orig_val); | ||
elem.bind('focus', function () { | ||
if (elem.hasClass(emptyClassName)) { | ||
elem.val(''); | ||
elem.removeClass(emptyClassName); | ||
domElem.select(); | ||
} | ||
}); | ||
elem.bind('blur', updateValue); | ||
if (!ngModel) { | ||
elem.bind('change', function () { | ||
changePlaceholder($interpolate(elem.attr('placeholder'))(scope)); | ||
}); | ||
} | ||
if (ngModel) { | ||
ngModel.$render = function () { | ||
setValue(ngModel.$viewValue); | ||
if (domElem === document.activeElement && !elem.val()) { | ||
domElem.select(); | ||
} | ||
}; | ||
} | ||
if (!documentListenersApplied) { | ||
$document.bind('selectstart', function (e) { | ||
var elmn = angular.element(e.target); | ||
if (elmn.hasClass(emptyClassName) && elmn.prop('disabled')) { | ||
e.preventDefault(); | ||
} | ||
}); | ||
documentListenersApplied = true; | ||
} | ||
function updateValue(e) { | ||
var val = elem.val(); | ||
if (elem.hasClass(emptyClassName) && val && val === text) { | ||
return; | ||
} | ||
conditionalDefer(function () { | ||
setValue(val); | ||
}); | ||
} | ||
function conditionalDefer(callback) { | ||
if (document.documentMode <= 11) { | ||
$timeout(callback, 0); | ||
} else { | ||
callback(); | ||
} | ||
} | ||
function setValue(val) { | ||
if (!val && val !== 0 && domElem !== document.activeElement) { | ||
elem.addClass(emptyClassName); | ||
elem.val(!is_pwd ? text : ''); | ||
} else { | ||
elem.removeClass(emptyClassName); | ||
elem.val(val); | ||
} | ||
if (is_pwd) { | ||
updatePasswordPlaceholder(); | ||
if ($animate) { | ||
asyncUpdatePasswordPlaceholder(); | ||
} | ||
} | ||
} | ||
function getValue() { | ||
if (ngModel) { | ||
return scope.$eval(attrs.ngModel) || ''; | ||
} | ||
return getDomValue() || ''; | ||
} | ||
function getDomValue() { | ||
var val = elem.val(); | ||
if (val === attrs.placeholder) { | ||
val = ''; | ||
} | ||
return val; | ||
} | ||
function changePlaceholder(value) { | ||
if (elem.hasClass(emptyClassName) && elem.val() === text) { | ||
elem.val(''); | ||
} | ||
text = value; | ||
updateValue(); | ||
} | ||
function setAttrUnselectable(elmn, enable) { | ||
if (enable) { | ||
elmn.attr('unselectable', 'on'); | ||
} else { | ||
elmn.removeAttr('unselectable'); | ||
} | ||
} | ||
function setupPasswordPlaceholder() { | ||
clone = angular.element('<input type="text" value="' + text + '"/>'); | ||
stylePasswordPlaceholder(); | ||
hideElement(clone); | ||
clone.addClass(emptyClassName).bind('focus', hidePasswordPlaceholderAndFocus); | ||
domElem.parentNode.insertBefore(clone[0], domElem); | ||
var watchAttrs = [ | ||
attrs.ngDisabled, | ||
attrs.ngReadonly, | ||
attrs.ngRequired, | ||
attrs.ngShow, | ||
attrs.ngHide | ||
]; | ||
for (var i = 0; i < watchAttrs.length; i++) { | ||
if (watchAttrs[i]) { | ||
scope.$watch(watchAttrs[i], flexibleUpdatePasswordPlaceholder); | ||
} | ||
} | ||
} | ||
function updatePasswordPlaceholder() { | ||
stylePasswordPlaceholder(); | ||
if (isNgHidden()) { | ||
hideElement(clone); | ||
} else if (elem.hasClass(emptyClassName) && domElem !== document.activeElement) { | ||
showPasswordPlaceholder(); | ||
} else { | ||
hidePasswordPlaceholder(); | ||
} | ||
} | ||
function asyncUpdatePasswordPlaceholder() { | ||
if (angularVersion >= 1.3) { | ||
$animate.addClass(elem, '').then(updatePasswordPlaceholder); | ||
} else { | ||
$animate.addClass(elem, '', updatePasswordPlaceholder); | ||
} | ||
} | ||
function flexibleUpdatePasswordPlaceholder() { | ||
if ($animate) { | ||
asyncUpdatePasswordPlaceholder(); | ||
} else { | ||
updatePasswordPlaceholder(); | ||
} | ||
} | ||
function stylePasswordPlaceholder() { | ||
clone.val(text); | ||
clone.attr('class', elem.attr('class') || '').attr('style', elem.attr('style') || '').prop('disabled', elem.prop('disabled')).prop('readOnly', elem.prop('readOnly')).prop('required', elem.prop('required')); | ||
setAttrUnselectable(clone, elem.attr('unselectable') === 'on'); | ||
} | ||
function showElement(elmn) { | ||
if (angularVersion >= 1.2) { | ||
elmn.removeClass(hiddenClassName); | ||
} else { | ||
elmn.css('display', ''); | ||
} | ||
} | ||
function hideElement(elmn) { | ||
if (angularVersion >= 1.2) { | ||
elmn.addClass(hiddenClassName); | ||
} else { | ||
elmn.css('display', 'none'); | ||
} | ||
} | ||
function showPasswordPlaceholder() { | ||
hideElement(elem); | ||
showElement(clone); | ||
} | ||
function hidePasswordPlaceholder() { | ||
hideElement(clone); | ||
showElement(elem); | ||
} | ||
function hidePasswordPlaceholderAndFocus() { | ||
hidePasswordPlaceholder(); | ||
domElem.focus(); | ||
} | ||
function isNgHidden() { | ||
var hasNgShow = typeof attrs.ngShow !== 'undefined', hasNgHide = typeof attrs.ngHide !== 'undefined'; | ||
if (hasNgShow || hasNgHide) { | ||
return hasNgShow && !scope.$eval(attrs.ngShow) || hasNgHide && scope.$eval(attrs.ngHide); | ||
} else { | ||
return false; | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
]); | ||
}(window.angular, window.document)); | ||
(function(angular, document, undefined) { | ||
'use strict'; | ||
angular.module('ng.shims.placeholder', []) | ||
.service('placeholderSniffer', ["$document", function($document){ | ||
this.emptyClassName = 'empty', | ||
this.hasPlaceholder = function() { | ||
// test for native placeholder support | ||
var test = $document[0].createElement("input"); | ||
return (test.placeholder !== void 0); | ||
}; | ||
}]) | ||
.directive('placeholder', ["$timeout", "$document", "$interpolate", "$injector", "placeholderSniffer", function($timeout, $document, $interpolate, $injector, placeholderSniffer) { | ||
if (placeholderSniffer.hasPlaceholder()) return {}; | ||
var documentListenersApplied = false, | ||
angularVersion = parseFloat(angular.version.full); | ||
// load $animate if available, to coordinate with other directives that use it | ||
try { | ||
var $animate = $injector.get('$animate'); | ||
} catch (e) {} | ||
// No native support for attribute placeholder | ||
return { | ||
restrict: 'A', | ||
require: '?ngModel', | ||
// run after ngModel (0) and BOOLEAN_ATTR (100) directives. | ||
// priority order was reversed in Angular 1.2, so we must account for this | ||
priority: (angularVersion >= 1.2) ? 110 : -10, | ||
link: function(scope, elem, attrs, ngModel) { | ||
var orig_val = getValue(), | ||
domElem = elem[0], | ||
elemType = domElem.nodeName.toLowerCase(), | ||
isInput = elemType === 'input' || elemType === 'textarea', | ||
is_pwd = attrs.type === 'password', | ||
text = attrs.placeholder || '', | ||
emptyClassName = placeholderSniffer.emptyClassName, | ||
hiddenClassName = 'ng-hide', | ||
clone; | ||
if (!isInput) { return; } | ||
attrs.$observe('placeholder', function (newValue) { | ||
changePlaceholder(newValue); | ||
}); | ||
if (is_pwd) { setupPasswordPlaceholder(); } | ||
// init | ||
setValue(orig_val); | ||
// on focus, replace auto-label with empty field | ||
elem.bind('focus', function() { | ||
if (elem.hasClass(emptyClassName)) { | ||
elem.val(''); | ||
elem.removeClass(emptyClassName); | ||
domElem.select(); // IE8/9 show text cursor after tabbing in | ||
} | ||
}); | ||
// on blur, show placeholder if necessary | ||
elem.bind('blur', updateValue); | ||
// handler for model-less inputs to interact with non-angular code | ||
if (!ngModel) { | ||
elem.bind('change', function () { | ||
changePlaceholder($interpolate(elem.attr('placeholder') || '')(scope)); | ||
}); | ||
} | ||
// model -> view | ||
if (ngModel) { | ||
ngModel.$render = function() { | ||
setValue(ngModel.$viewValue); | ||
// IE8/9: show text cursor after updating value while | ||
// focused, this happens when tabbing into a field, and the | ||
// deferred keydown handler from the previous field fires | ||
// | ||
// TODO: remove when tab key behavior is fixed in | ||
// angular core | ||
if (domElem === document.activeElement && !elem.val()) { | ||
domElem.select(); | ||
} | ||
}; | ||
} | ||
if (!documentListenersApplied) { | ||
// cancel selection of placeholder text on disabled elements | ||
// disabled elements do not emit selectstart events in IE8/IE9, | ||
// so bind to $document and catch the event as it bubbles | ||
$document.bind('selectstart', function (e) { | ||
var elmn = angular.element(e.target); | ||
if (elmn.hasClass(emptyClassName) && elmn.prop('disabled')) { | ||
e.preventDefault(); | ||
} | ||
}); | ||
documentListenersApplied = true; | ||
} | ||
function updateValue(e) { | ||
var val = elem.val(); | ||
// don't update from placeholder, helps debounce | ||
if (elem.hasClass(emptyClassName) && val && val === text) { return; } | ||
conditionalDefer(function(){ setValue(val); }); | ||
} | ||
function conditionalDefer(callback) { | ||
// IE8/9: ngModel uses a keydown handler with deferrered | ||
// execution to check for changes to the input. this $timeout | ||
// prevents callback from firing before the keydown handler, | ||
// which is an issue when tabbing out of an input. | ||
// the conditional tests IE version, matches $sniffer. | ||
// | ||
// TODO: remove this function when tab key behavior is fixed in | ||
// angular core | ||
if (document.documentMode <= 11) { | ||
$timeout(callback, 0); | ||
} else { | ||
callback(); | ||
} | ||
} | ||
function setValue(val) { | ||
if (!val && val !== 0 && domElem !== document.activeElement) { | ||
// show placeholder when necessary | ||
elem.addClass(emptyClassName); | ||
elem.val(!is_pwd ? text : ''); | ||
} else { | ||
// otherwise set input to actual value | ||
elem.removeClass(emptyClassName); | ||
elem.val(val); | ||
} | ||
if (is_pwd) { | ||
updatePasswordPlaceholder(); | ||
if ($animate) { | ||
asyncUpdatePasswordPlaceholder(); | ||
} | ||
} | ||
} | ||
function getValue() { | ||
if (ngModel) { | ||
// use eval because $viewValue isn't ready during init | ||
// TODO: this might not to work during unit tests, investigate | ||
return scope.$eval(attrs.ngModel) || ''; | ||
} | ||
return getDomValue() || ''; | ||
} | ||
// IE8/9: elem.val() on an empty field sometimes returns the | ||
// placeholder value, so return an empty string instead | ||
// http://stackoverflow.com/q/11208417/490592 | ||
// I believe IE is persisting the field value across refreshes | ||
// TODO: vs `elem.attr('value')` | ||
function getDomValue() { | ||
var val = elem.val(); | ||
if (val === attrs.placeholder) { | ||
val = ''; | ||
} | ||
return val; | ||
} | ||
function changePlaceholder(value) { | ||
if (elem.hasClass(emptyClassName) && elem.val() === text) { | ||
elem.val(''); | ||
} | ||
text = value; | ||
updateValue(); | ||
} | ||
function setAttrUnselectable(elmn, enable) { | ||
if (enable) { | ||
elmn.attr('unselectable', 'on'); | ||
} else { | ||
elmn.removeAttr('unselectable'); | ||
} | ||
} | ||
// IE8: password inputs cannot display text, and inputs cannot | ||
// change type, so create a new element to display placeholder | ||
function setupPasswordPlaceholder() { | ||
clone = angular.element('<input type="text" value="'+text+'"/>'); | ||
stylePasswordPlaceholder(); | ||
hideElement(clone); | ||
clone.addClass(emptyClassName) | ||
.bind('focus', hidePasswordPlaceholderAndFocus); | ||
domElem.parentNode.insertBefore(clone[0], domElem); | ||
// keep password placeholder in sync with original element. | ||
// update element after $watches | ||
var watchAttrs = [ | ||
attrs.ngDisabled, | ||
attrs.ngReadonly, | ||
attrs.ngRequired, | ||
attrs.ngShow, | ||
attrs.ngHide | ||
]; | ||
for (var i = 0; i < watchAttrs.length; i++) { | ||
if (watchAttrs[i]) { | ||
scope.$watch(watchAttrs[i], flexibleUpdatePasswordPlaceholder); | ||
} | ||
} | ||
} | ||
function updatePasswordPlaceholder() { | ||
stylePasswordPlaceholder(); | ||
if (isNgHidden()) { | ||
// force hide the placeholder when element is hidden by | ||
// ngShow/ngHide. we cannot rely on stylePasswordPlaceholder | ||
// above to copy the ng-hide class, because the ngShow/ngHide | ||
// $watch functions apply the ng-hide class with $animate, | ||
// so the class is not applied when our $watch executes | ||
hideElement(clone); | ||
} else if (elem.hasClass(emptyClassName) && domElem !== document.activeElement) { | ||
showPasswordPlaceholder(); | ||
} else { | ||
hidePasswordPlaceholder(); | ||
} | ||
} | ||
// update element after animation and animation-aware directives | ||
function asyncUpdatePasswordPlaceholder() { | ||
if (angularVersion >= 1.3) { | ||
$animate.addClass(elem, '').then(updatePasswordPlaceholder); | ||
} else { | ||
$animate.addClass(elem, '', updatePasswordPlaceholder); | ||
} | ||
} | ||
function flexibleUpdatePasswordPlaceholder() { | ||
if ($animate) { | ||
asyncUpdatePasswordPlaceholder(); | ||
} else { | ||
updatePasswordPlaceholder(); | ||
} | ||
} | ||
function stylePasswordPlaceholder() { | ||
clone.val(text); | ||
// chaining was failing in v1.0.8 | ||
clone.attr('class', elem.attr('class') || '') | ||
.attr('style', elem.attr('style') || '') | ||
.prop('disabled', elem.prop('disabled')) | ||
.prop('readOnly', elem.prop('readOnly')) | ||
.prop('required', elem.prop('required')); | ||
setAttrUnselectable(clone, elem.attr('unselectable') === 'on'); | ||
} | ||
function showElement(elmn) { | ||
if (angularVersion >= 1.2) { | ||
elmn.removeClass(hiddenClassName); | ||
} else { | ||
elmn.css('display', ''); | ||
} | ||
} | ||
function hideElement(elmn) { | ||
if (angularVersion >= 1.2) { | ||
elmn.addClass(hiddenClassName); | ||
} else { | ||
elmn.css('display', 'none'); | ||
} | ||
} | ||
function showPasswordPlaceholder() { | ||
hideElement(elem); | ||
showElement(clone); | ||
} | ||
function hidePasswordPlaceholder() { | ||
hideElement(clone); | ||
showElement(elem); | ||
} | ||
function hidePasswordPlaceholderAndFocus() { | ||
hidePasswordPlaceholder(); | ||
domElem.focus(); | ||
} | ||
function isNgHidden() { | ||
var hasNgShow = typeof attrs.ngShow !== 'undefined', | ||
hasNgHide = typeof attrs.ngHide !== 'undefined'; | ||
if (hasNgShow || hasNgHide) { | ||
return (hasNgShow && !scope.$eval(attrs.ngShow)) || | ||
(hasNgHide && scope.$eval(attrs.ngHide)); | ||
} else { | ||
return false; | ||
} | ||
} | ||
} | ||
}; | ||
}]); | ||
})(window.angular, window.document); |
@@ -1,4 +0,4 @@ | ||
/*! angular-shims-placeholder - v0.4.2 - 2015-05-11 | ||
/*! angular-shims-placeholder - v0.4.3 - 2015-06-14 | ||
* https://github.com/cvn/angular-shims-placeholder | ||
* Copyright (c) 2015 Chad von Nau; Licensed MIT */ | ||
!function(a,b){"use strict";a.module("ng.shims.placeholder",[]).service("placeholderSniffer",["$document",function(a){this.emptyClassName="empty",this.hasPlaceholder=function(){var b=a[0].createElement("input");return void 0!==b.placeholder}}]).directive("placeholder",["$timeout","$document","$interpolate","$injector","placeholderSniffer",function(c,d,e,f,g){if(g.hasPlaceholder())return{};var h=!1,i=parseFloat(a.version.full);try{var j=f.get("$animate")}catch(k){}return{restrict:"A",require:"?ngModel",priority:i>=1.2?110:-10,link:function(f,k,l,m){function n(){var a=k.val();k.hasClass(M)&&a&&a===L||o(function(){p(a)})}function o(a){b.documentMode<=11?c(a,0):a()}function p(a){a||0===a||H===b.activeElement?(k.removeClass(M),k.val(a)):(k.addClass(M),k.val(K?"":L)),K&&(v(),j&&w())}function q(){return m?f.$eval(l.ngModel)||"":r()||""}function r(){var a=k.val();return a===l.placeholder&&(a=""),a}function s(a){k.hasClass(M)&&k.val()===L&&k.val(""),L=a,n()}function t(a,b){b?a.attr("unselectable","on"):a.removeAttr("unselectable")}function u(){F=a.element('<input type="text" value="'+L+'"/>'),y(),A(F),F.addClass(M).bind("focus",D),H.parentNode.insertBefore(F[0],H);for(var b=[l.ngDisabled,l.ngReadonly,l.ngRequired,l.ngShow,l.ngHide],c=0;c<b.length;c++)b[c]&&f.$watch(b[c],x)}function v(){y(),E()?A(F):k.hasClass(M)&&H!==b.activeElement?B():C()}function w(){i>=1.3?j.addClass(k,"").then(v):j.addClass(k,"",v)}function x(){j?w():v()}function y(){F.val(L),F.attr("class",k.attr("class")||"").attr("style",k.attr("style")||"").prop("disabled",k.prop("disabled")).prop("readOnly",k.prop("readOnly")).prop("required",k.prop("required")),t(F,"on"===k.attr("unselectable"))}function z(a){i>=1.2?a.removeClass(N):a.css("display","")}function A(a){i>=1.2?a.addClass(N):a.css("display","none")}function B(){A(k),z(F)}function C(){A(F),z(k)}function D(){C(),H.focus()}function E(){var a="undefined"!=typeof l.ngShow,b="undefined"!=typeof l.ngHide;return a||b?a&&!f.$eval(l.ngShow)||b&&f.$eval(l.ngHide):!1}var F,G=q(),H=k[0],I=H.nodeName.toLowerCase(),J="input"===I||"textarea"===I,K="password"===l.type,L=l.placeholder,M=g.emptyClassName,N="ng-hide";J&&(l.$observe("placeholder",function(a){s(a)}),K&&u(),p(G),k.bind("focus",function(){k.hasClass(M)&&(k.val(""),k.removeClass(M),H.select())}),k.bind("blur",n),m||k.bind("change",function(){s(e(k.attr("placeholder"))(f))}),m&&(m.$render=function(){p(m.$viewValue),H!==b.activeElement||k.val()||H.select()}),h||(d.bind("selectstart",function(b){var c=a.element(b.target);c.hasClass(M)&&c.prop("disabled")&&b.preventDefault()}),h=!0))}}}])}(window.angular,window.document); | ||
!function(a,b,c){"use strict";a.module("ng.shims.placeholder",[]).service("placeholderSniffer",["$document",function(a){this.emptyClassName="empty",this.hasPlaceholder=function(){var b=a[0].createElement("input");return void 0!==b.placeholder}}]).directive("placeholder",["$timeout","$document","$interpolate","$injector","placeholderSniffer",function(c,d,e,f,g){if(g.hasPlaceholder())return{};var h=!1,i=parseFloat(a.version.full);try{var j=f.get("$animate")}catch(k){}return{restrict:"A",require:"?ngModel",priority:i>=1.2?110:-10,link:function(f,k,l,m){function n(a){var b=k.val();k.hasClass(M)&&b&&b===L||o(function(){p(b)})}function o(a){b.documentMode<=11?c(a,0):a()}function p(a){a||0===a||H===b.activeElement?(k.removeClass(M),k.val(a)):(k.addClass(M),k.val(K?"":L)),K&&(v(),j&&w())}function q(){return m?f.$eval(l.ngModel)||"":r()||""}function r(){var a=k.val();return a===l.placeholder&&(a=""),a}function s(a){k.hasClass(M)&&k.val()===L&&k.val(""),L=a,n()}function t(a,b){b?a.attr("unselectable","on"):a.removeAttr("unselectable")}function u(){F=a.element('<input type="text" value="'+L+'"/>'),y(),A(F),F.addClass(M).bind("focus",D),H.parentNode.insertBefore(F[0],H);for(var b=[l.ngDisabled,l.ngReadonly,l.ngRequired,l.ngShow,l.ngHide],c=0;c<b.length;c++)b[c]&&f.$watch(b[c],x)}function v(){y(),E()?A(F):k.hasClass(M)&&H!==b.activeElement?B():C()}function w(){i>=1.3?j.addClass(k,"").then(v):j.addClass(k,"",v)}function x(){j?w():v()}function y(){F.val(L),F.attr("class",k.attr("class")||"").attr("style",k.attr("style")||"").prop("disabled",k.prop("disabled")).prop("readOnly",k.prop("readOnly")).prop("required",k.prop("required")),t(F,"on"===k.attr("unselectable"))}function z(a){i>=1.2?a.removeClass(N):a.css("display","")}function A(a){i>=1.2?a.addClass(N):a.css("display","none")}function B(){A(k),z(F)}function C(){A(F),z(k)}function D(){C(),H.focus()}function E(){var a="undefined"!=typeof l.ngShow,b="undefined"!=typeof l.ngHide;return a||b?a&&!f.$eval(l.ngShow)||b&&f.$eval(l.ngHide):!1}var F,G=q(),H=k[0],I=H.nodeName.toLowerCase(),J="input"===I||"textarea"===I,K="password"===l.type,L=l.placeholder||"",M=g.emptyClassName,N="ng-hide";J&&(l.$observe("placeholder",function(a){s(a)}),K&&u(),p(G),k.bind("focus",function(){k.hasClass(M)&&(k.val(""),k.removeClass(M),H.select())}),k.bind("blur",n),m||k.bind("change",function(){s(e(k.attr("placeholder")||"")(f))}),m&&(m.$render=function(){p(m.$viewValue),H!==b.activeElement||k.val()||H.select()}),h||(d.bind("selectstart",function(b){var c=a.element(b.target);c.hasClass(M)&&c.prop("disabled")&&b.preventDefault()}),h=!0))}}}])}(window.angular,window.document); |
@@ -25,3 +25,3 @@ 'use strict'; | ||
}, | ||
ngmin: { | ||
ngAnnotate: { | ||
dist: { | ||
@@ -38,3 +38,3 @@ src: ['lib/*.js'], | ||
dist: { | ||
src: '<%= ngmin.dist.dest %>', | ||
src: '<%= ngAnnotate.dist.dest %>', | ||
dest: 'dist/<%= pkg.name %>.js' | ||
@@ -78,3 +78,3 @@ } | ||
build: { | ||
files: '<%= ngmin.dist.src %>', | ||
files: '<%= ngAnnotate.dist.src %>', | ||
tasks: ['build'] | ||
@@ -87,3 +87,3 @@ }, | ||
files: [ | ||
'<%= ngmin.dist.src %>', | ||
'<%= ngAnnotate.dist.src %>', | ||
'<%= demo %>' | ||
@@ -115,3 +115,3 @@ ] | ||
grunt.loadNpmTasks('grunt-contrib-watch'); | ||
grunt.loadNpmTasks('grunt-ngmin'); | ||
grunt.loadNpmTasks('grunt-ng-annotate'); | ||
grunt.loadNpmTasks('grunt-open'); | ||
@@ -127,3 +127,3 @@ | ||
// Build task. | ||
grunt.registerTask('build', ['ngmin', 'concat', 'uglify']); | ||
grunt.registerTask('build', ['ngAnnotate', 'concat', 'uglify']); | ||
@@ -130,0 +130,0 @@ // Dev task. |
@@ -48,3 +48,3 @@ /* | ||
is_pwd = attrs.type === 'password', | ||
text = attrs.placeholder, | ||
text = attrs.placeholder || '', | ||
emptyClassName = placeholderSniffer.emptyClassName, | ||
@@ -80,3 +80,3 @@ hiddenClassName = 'ng-hide', | ||
elem.bind('change', function () { | ||
changePlaceholder($interpolate(elem.attr('placeholder'))(scope)); | ||
changePlaceholder($interpolate(elem.attr('placeholder') || '')(scope)); | ||
}); | ||
@@ -83,0 +83,0 @@ } |
{ | ||
"name": "angular-shims-placeholder", | ||
"description": "Angular directive to emulate the `placeholder` attribute on text and password input fields for old browsers, such as IE9, IE8, and below", | ||
"version": "0.4.2", | ||
"version": "0.4.3", | ||
"homepage": "https://github.com/cvn/angular-shims-placeholder", | ||
@@ -45,3 +45,3 @@ "author": { | ||
"grunt-contrib-watch": "latest", | ||
"grunt-ngmin": "0.0.2", | ||
"grunt-ng-annotate": "latest", | ||
"grunt-open": "latest", | ||
@@ -48,0 +48,0 @@ "karma": "0.8.5" |
@@ -56,4 +56,4 @@ angular-shims-placeholder | ||
* Angular 1.0.8 - 1.4 | ||
* IE9, IE8*, IE7* (see known issues) | ||
* ngModel, ngDisabled, ngReadonly, ngRequired, ngShow, ngHide | ||
* IE9, IE8, IE7 * (see known issues) | ||
* ngModel, ngDisabled, ngReadonly, ngRequired, ngShow, ngHide, ngAttrPlaceholder | ||
* ngAnimate (Angular 1.3+ only) | ||
@@ -60,0 +60,0 @@ |
@@ -367,2 +367,31 @@ 'use strict'; | ||
describe('on an input with ngAttrPlaceholder', function() { | ||
var elem; | ||
beforeEach(function () { | ||
elem = angular.element('<input type="text" ng-attr-placeholder="Some text" ng-model="form.someText"/>'); | ||
$compile(elem)(scope); | ||
}); | ||
it('should display the placeholder as input value', function() { | ||
expect(elem.val()).toBe('Some text'); | ||
expect(elem.hasClass('empty')).toBe(true); | ||
expect(scope.form.someText).toBeUndefined(); | ||
}); | ||
}); | ||
describe('on a password input with ngAttrPlaceholder whose value is undefined', function() { | ||
var elem, clone; | ||
beforeEach(function () { | ||
elem = angular.element('<input type="password" ng-attr-placeholder="{{undefined}}" ng-model="form.somePassword"/>'); | ||
$compile(elem)(scope); | ||
clone = angular.element(elem[0].previousElementSibling); | ||
}); | ||
it('should display an empty placeholder', function() { | ||
expect(clone.val()).toBe(''); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
60959
1081