Merge pull request #1473 from coreos-inc/angularup

Move to Angular 1.5
This commit is contained in:
josephschorr 2016-05-17 16:34:01 -04:00
commit d596a6d5b2
19 changed files with 91 additions and 133 deletions

View file

@ -18,7 +18,7 @@ CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'MIXPANEL_KEY',
'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN', 'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN',
'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT', 'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT',
'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'DOCUMENTATION_LOCATION', 'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'DOCUMENTATION_LOCATION',
'DOCUMENTATION_METADATA', 'SETUP_COMPLETE'] 'DOCUMENTATION_METADATA', 'SETUP_COMPLETE', 'DEBUG']
def frontend_visible_config(config_dict): def frontend_visible_config(config_dict):

View file

@ -7,10 +7,11 @@ LOCAL_DIRECTORY = '/static/ldn/'
EXTERNAL_JS = [ EXTERNAL_JS = [
'code.jquery.com/jquery.js', 'code.jquery.com/jquery.js',
'netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js', 'netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js',
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js', 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js',
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.min.js', 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-route.min.js',
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-sanitize.min.js', 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-sanitize.min.js',
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-animate.min.js', 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.min.js',
'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-cookies.min.js',
'cdn.jsdelivr.net/g/momentjs', 'cdn.jsdelivr.net/g/momentjs',
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.2.0/js/bootstrap-datepicker.min.js', 'cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.2.0/js/bootstrap-datepicker.min.js',
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js', 'cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js',

View file

@ -4,7 +4,6 @@
color: white !important; color: white !important;
text-align: center; text-align: center;
position: relative; position: relative;
background: white;
overflow: hidden; overflow: hidden;
} }
@ -16,7 +15,6 @@
position: absolute; position: absolute;
top: 0px; top: 0px;
left: 0px; left: 0px;
background: white;
} }
.avatar-element .letter { .avatar-element .letter {

View file

@ -1,11 +1,13 @@
<span class="avatar-element" <span class="avatar-element"
ng-style="{'width': size, 'height': size, 'backgroundColor': data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}" ng-style="{'width': size, 'height': size, 'backgroundColor': (showGravatar || isLoading) ? 'transparent' : data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}"
ng-class="data.kind"> ng-class="data.kind">
<img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=404&size={{ size }}" <img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=blank&size=512"
ng-if="loadGravatar" ng-if="loadGravatar"
ng-show="hasGravatar" ng-visible="showGravatar"
ng-image-watch="imageCallback(result)"> ng-image-watch="imageCallback(result)"
<span class="default-avatar" ng-if="!isLoading && !hasGravatar"> ng-style="{'width': imageSize + 'px', 'height': imageSize + 'px'}"
crossorigin="anonymous">
<span class="default-avatar" ng-if="!isLoading && !showGravatar">
<span class="letter" ng-if="data.kind != 'team' || data.name != 'owners'">{{ data.name.charAt(0).toUpperCase() }}</span> <span class="letter" ng-if="data.kind != 'team' || data.name != 'owners'">{{ data.name.charAt(0).toUpperCase() }}</span>
<span class="letter" ng-if="data.kind == 'team' && data.name == 'owners'">&Omega;</span> <span class="letter" ng-if="data.kind == 'team' && data.name == 'owners'">&Omega;</span>
</span> </span>

View file

@ -105,7 +105,7 @@
<td> <td>
<div class="co-checkbox"> <div class="co-checkbox">
<input id="enable-ssl" type="checkbox" ng-model="config.PREFERRED_URL_SCHEME" <input id="enable-ssl" type="checkbox" ng-model="config.PREFERRED_URL_SCHEME"
ng-true-value="https" ng-false-value="http"> ng-true-value="'https'" ng-false-value="'http'">
<label for="enable-ssl">Enable SSL</label> <label for="enable-ssl">Enable SSL</label>
</div> </div>
<div class="help-text" style="margin-bottom: 10px"> <div class="help-text" style="margin-bottom: 10px">
@ -322,7 +322,7 @@
<tr> <tr>
<td>Authentication Key:</td> <td>Authentication Key:</td>
<td> <td>
<span class="config-service-key-field" service-name="{{ config.SECURITY_SCANNER_ISSUER_NAME }}"></span> <span class="config-service-key-field" service-name="{{ config.SECURITY_SCANNER_ISSUER_NAME || 'secscan' }}"></span>
<div class="help-text"> <div class="help-text">
The security scanning service requires an authorized service key to speak to Quay. Once setup, the key The security scanning service requires an authorized service key to speak to Quay. Once setup, the key
can be managed in the Service Keys panel under the Super User Admin Panel. can be managed in the Service Keys panel under the Super User Admin Panel.

View file

@ -1 +1 @@
<ng-transclude> <span></span>

View file

@ -6,7 +6,7 @@
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
&equiv; &equiv;
</button> </button>
<a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}" target="{{ appLinkTarget() }}"> <a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}">
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}" <span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"
ng-class="Config.ENTERPRISE_LOGO_URL ? 'enterprise-logo' : 'hosted-logo'"></span> ng-class="Config.ENTERPRISE_LOGO_URL ? 'enterprise-logo' : 'hosted-logo'"></span>
</a> </a>
@ -21,17 +21,17 @@
<div class="collapse navbar-collapse navbar-ex1-collapse"> <div class="collapse navbar-collapse navbar-ex1-collapse">
<!-- Not signed in --> <!-- Not signed in -->
<ul class="nav navbar-nav navbar-links" ng-if="user.anonymous"> <ul class="nav navbar-nav navbar-links" ng-if="user.anonymous">
<li><a ng-href="/tour/" target="{{ appLinkTarget() }}" quay-section="tour">Tour</a></li> <li><a ng-href="/tour/" quay-section="tour">Tour</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li> <li><a ng-href="/tutorial/" quay-section="tutorial">Tutorial</a></li>
<li quay-require="['BILLING']"><a ng-href="/plans/" target="{{ appLinkTarget() }}" quay-section="plans">Pricing</a></li> <li quay-require="['BILLING']"><a ng-href="/plans/" quay-section="plans">Pricing</a></li>
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li> <li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li> <li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
</ul> </ul>
<!-- Signed in --> <!-- Signed in -->
<ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous"> <ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous">
<li><a ng-href="/repository/" target="{{ appLinkTarget() }}" quay-section="repository">Repositories</a></li> <li><a ng-href="/repository/" quay-section="repository">Repositories</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li> <li><a ng-href="/tutorial/" quay-section="tutorial">Tutorial</a></li>
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li> <li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li> <li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
</ul> </ul>
@ -39,13 +39,13 @@
<!-- Phone --> <!-- Phone -->
<ul class="nav navbar-nav navbar-right visible-xs" ng-switch on="user.anonymous"> <ul class="nav navbar-nav navbar-right visible-xs" ng-switch on="user.anonymous">
<li ng-switch-when="false"> <li ng-switch-when="false">
<a href="/user/{{ user.username }}?tab=settings" class="user-view" target="{{ appLinkTarget() }}"> <a href="/user/{{ user.username }}?tab=settings" class="user-view">
<span class="avatar" size="32" data="user.avatar"></span> <span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }} {{ user.username }}
</a> </a>
</li> </li>
<li ng-switch-default> <li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}" ng-if="!externalSigninUrl">Sign in</a> <a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a> <a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
</li> </li>
</ul> </ul>
@ -128,7 +128,7 @@
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <li>
<a href="/user/{{ user.username }}?tab=settings" target="{{ appLinkTarget() }}"> <a href="/user/{{ user.username }}?tab=settings">
Account Settings Account Settings
</a> </a>
</li> </li>
@ -137,7 +137,7 @@
</ul> </ul>
</li> </li>
<li ng-switch-default> <li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}" ng-if="!externalSigninUrl">Sign in</a> <a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a> <a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
</li> </li>
</ul> </ul>
@ -149,7 +149,6 @@
<div class="search-box-wrapper"> <div class="search-box-wrapper">
<input id="search-box-input" type="search" placeholder="(Enter Search Terms)" <input id="search-box-input" type="search" placeholder="(Enter Search Terms)"
ng-model-options="{'debounce': 250}" ng-model="currentSearchQuery" ng-model-options="{'debounce': 250}" ng-model="currentSearchQuery"
debounce="250"
ng-keydown="handleSearchKeyDown($event)"> ng-keydown="handleSearchKeyDown($event)">
</div> </div>
</div> </div>

View file

@ -1,12 +1,12 @@
<div class="repo-list-table-element"> <div class="repo-list-table-element">
<div class="cor-loader" ng-if="isLoading"></div> <div class="cor-loader" ng-if="isLoading"></div>
<div ng-if="orderedRepositories.length == 0 && !isLoading"> <div ng-if="orderedRepositories.entries.length == 0 && !isLoading">
<div class="empty-primary-msg" ng-if="namespaces.length != 1">You do not have any viewable repositories.</div> <div class="empty-primary-msg" ng-if="namespaces.length != 1">You do not have any viewable repositories.</div>
<div class="empty-primary-msg" ng-if="namespaces.length == 1">This namespace doesn't have any viewable repositories.</div> <div class="empty-primary-msg" ng-if="namespaces.length == 1">This namespace doesn't have any viewable repositories.</div>
<div class="empty-secondary-msg">Either no repositories exist yet or you may not have permission to view any. If you have permission, try <a href="/new">creating a new repository</a>.</div> <div class="empty-secondary-msg">Either no repositories exist yet or you may not have permission to view any. If you have permission, try <a href="/new">creating a new repository</a>.</div>
</div> </div>
<table class="co-table" ng-if="orderedRepositories.length && !isLoading"> <table class="co-table" ng-if="orderedRepositories.entries.length && !isLoading">
<thead> <thead>
<td class="hidden-xs" <td class="hidden-xs"
ng-class="tablePredicateClass('full_name', options.predicate, options.reverse)"> ng-class="tablePredicateClass('full_name', options.predicate, options.reverse)">

View file

@ -1,7 +1,7 @@
<div class="user-setup-element"> <div class="user-setup-element">
<div class="user-setup-element-view"> <div class="user-setup-element-view">
<div class="setup-logo-container" ng-show="hideLogo != 'true'"> <div class="setup-logo-container" ng-show="hideLogo != 'true'">
<img src="{{ Config.getEnterpriseLogo(true) }}"> <img ng-src="{{ Config.getEnterpriseLogo(true) }}">
</div> </div>
<div class="user-setup-content"> <div class="user-setup-content">

View file

@ -36,7 +36,7 @@ quayPages.constant('pages', {
}); });
quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'cfp.hotkeys', 'angular-tour', 'restangular', 'angularMoment', quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'cfp.hotkeys', 'angular-tour', 'restangular', 'angularMoment',
'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml', 'debounce', 'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml',
'core-ui', 'core-config-setup', 'quayPages', 'infinite-scroll']; 'core-ui', 'core-config-setup', 'quayPages', 'infinite-scroll'];
if (window.__config && window.__config.MIXPANEL_KEY) { if (window.__config && window.__config.MIXPANEL_KEY) {
@ -72,6 +72,12 @@ quayApp.config(['$tooltipProvider', function ($tooltipProvider) {
}; };
}]); }]);
quayApp.config(['$compileProvider', function ($compileProvider) {
if (!window.__config['DEBUG']) {
$compileProvider.debugInfoEnabled(false);
}
}]);
// Configure the routes. // Configure the routes.
quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) { quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) {
$locationProvider.html5Mode(true); $locationProvider.html5Mode(true);

View file

@ -1133,12 +1133,19 @@ angular.module("core-config-setup", ['angularFileUpload'])
controller: function($scope, $element) { controller: function($scope, $element) {
var firstSet = true; var firstSet = true;
$scope.patternMap = {};
$scope.getRegexp = function(pattern) { $scope.getRegexp = function(pattern) {
if (!pattern) { if (!pattern) {
pattern = '.*'; pattern = '.*';
} }
return new RegExp(pattern);
}; if ($scope.patternMap[pattern]) {
return $scope.patternMap[pattern];
}
return $scope.patternMap[pattern] = new RegExp(pattern);
};
$scope.$watch('binding', function(binding) { $scope.$watch('binding', function(binding) {
if (firstSet && !binding && $scope.defaultValue) { if (firstSet && !binding && $scope.defaultValue) {

View file

@ -16,20 +16,38 @@ angular.module('quay').directive('avatar', function () {
$scope.AvatarService = AvatarService; $scope.AvatarService = AvatarService;
$scope.Config = Config; $scope.Config = Config;
$scope.isLoading = true; $scope.isLoading = true;
$scope.hasGravatar = false; $scope.showGravatar = false;
$scope.loadGravatar = false; $scope.loadGravatar = false;
$scope.imageCallback = function(r) { $scope.imageCallback = function(result) {
$timeout(function() { $scope.isLoading = false;
$scope.isLoading = false;
$scope.hasGravatar = r; if (!result) {
}, 1); $scope.showGravatar = false;
return;
}
// Determine whether the gravatar is blank.
var canvas = document.createElement("canvas");
canvas.width = 512;
canvas.height = 512;
var ctx = canvas.getContext("2d");
ctx.drawImage($element.find('img')[0], 0, 0);
var blank = document.createElement("canvas");
blank.width = 512;
blank.height = 512;
var isBlank = canvas.toDataURL('text/png') == blank.toDataURL('text/png');
$scope.showGravatar = !isBlank;
}; };
$scope.$watch('size', function(size) { $scope.$watch('size', function(size) {
size = size * 1 || 16; size = size * 1 || 16;
$scope.fontSize = (size - 4) + 'px'; $scope.fontSize = (size - 4) + 'px';
$scope.lineHeight = size + 'px'; $scope.lineHeight = size + 'px';
$scope.imageSize = size;
}); });
$scope.$watch('data', function(data) { $scope.$watch('data', function(data) {

View file

@ -147,18 +147,6 @@ angular.module('quay').directive('headerBar', function () {
}); });
}; };
$scope.appLinkTarget = function() {
if ($scope._appLinkTarget) {
return $scope._appLinkTarget;
}
if ($("div[ng-view]").length === 0) {
return $scope._appLinkTarget = "_self";
}
return $scope._appLinkTarget = "";
};
$scope.getEnterpriseLogo = function() { $scope.getEnterpriseLogo = function() {
return Config.getEnterpriseLogo(false); return Config.getEnterpriseLogo(false);
}; };

View file

@ -14,6 +14,8 @@ angular.module('quay').directive('popupInputButton', function () {
'submitted': '&submitted' 'submitted': '&submitted'
}, },
controller: function($scope, $element) { controller: function($scope, $element) {
$scope.patternMap = {};
$scope.popupShown = function() { $scope.popupShown = function() {
setTimeout(function() { setTimeout(function() {
var box = $('#input-box'); var box = $('#input-box');
@ -26,7 +28,12 @@ angular.module('quay').directive('popupInputButton', function () {
if (!pattern) { if (!pattern) {
pattern = '.*'; pattern = '.*';
} }
return new RegExp(pattern);
if ($scope.patternMap[pattern]) {
return $scope.patternMap[pattern];
}
return $scope.patternMap[pattern] = new RegExp(pattern);
}; };
$scope.inputSubmit = function() { $scope.inputSubmit = function() {

View file

@ -77,7 +77,12 @@ angular.module('quay').directive('signinForm', function () {
if (redirectUrl == $location.path() || redirectUrl == null) { if (redirectUrl == $location.path() || redirectUrl == null) {
return; return;
} }
window.location = (redirectUrl ? redirectUrl : '/');
if (redirectUrl) {
window.location = redirectUrl
} else {
$location.path('/');
}
}, 500); }, 500);
}, function(result) { }, function(result) {
$scope.signingIn = false; $scope.signingIn = false;

View file

@ -21,7 +21,7 @@
UserService.updateUserIn($scope, function(user) { UserService.updateUserIn($scope, function(user) {
if (!user.anonymous) { if (!user.anonymous) {
$location.path('/repository'); $location.path('/repository/');
} }
}); });

View file

@ -1,22 +1,22 @@
/** /**
* Helper service for working with cookies. * Helper service for working with cookies.
*/ */
angular.module('quay').factory('CookieService', ['$cookies', '$cookieStore', function($cookies, $cookieStore) { angular.module('quay').factory('CookieService', ['$cookies', function($cookies) {
var cookieService = {}; var cookieService = {};
cookieService.putPermanent = function(name, value) { cookieService.putPermanent = function(name, value) {
document.cookie = escape(name) + "=" + escape(value) + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/"; document.cookie = escape(name) + "=" + escape(value) + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
}; };
cookieService.putSession = function(name, value) { cookieService.putSession = function(name, value) {
$cookies[name] = value; $cookies.put(name, value);
}; };
cookieService.clear = function(name) { cookieService.clear = function(name) {
$cookies[name] = ''; $cookies.remove(name);
}; };
cookieService.get = function(name) { cookieService.get = function(name) {
return $cookies[name]; return $cookies.get(name);
}; };
return cookieService; return cookieService;

View file

@ -1,7 +0,0 @@
/*
AngularJS v1.2.0-ed8640b
(c) 2010-2012 Google, Inc. http://angularjs.org
License: MIT
*/
(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&d.$apply())})();k=!0;d.$watch(function(){var a,e,d;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)(e=c[a],f.isString(e))?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(m(e[a])?delete c[a]:c[a]=e[a])});
return c}]).factory("$cookieStore",["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular);

View file

@ -1,66 +0,0 @@
'use strict';
angular.module('debounce', [])
.service('debounce', ['$timeout', function ($timeout) {
return function (func, wait, immediate) {
var timeout, args, context, result;
function debounce() {
/* jshint validthis:true */
context = this;
args = arguments;
var later = function () {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
}
};
var callNow = immediate && !timeout;
if (timeout) {
$timeout.cancel(timeout);
}
timeout = $timeout(later, wait);
if (callNow) {
result = func.apply(context, args);
}
return result;
}
debounce.cancel = function () {
$timeout.cancel(timeout);
timeout = null;
};
return debounce;
};
}])
.directive('debounce', ['debounce', '$parse', function (debounce, $parse) {
return {
require: 'ngModel',
priority: 999,
link: function ($scope, $element, $attrs, ngModelController) {
var debounceDuration = $parse($attrs.debounce)($scope);
var immediate = !!$parse($attrs.immediate)($scope);
var debouncedValue, pass;
var prevRender = ngModelController.$render.bind(ngModelController);
var commitSoon = debounce(function (viewValue) {
pass = true;
ngModelController.$setViewValue(viewValue);
pass = false;
}, parseInt(debounceDuration, 10), immediate);
ngModelController.$render = function () {
prevRender();
commitSoon.cancel();
//we must be first parser for this to work properly,
//so we have priority 999 so that we unshift into parsers last
debouncedValue = this.$viewValue;
};
ngModelController.$parsers.unshift(function (value) {
if (pass) {
debouncedValue = value;
return value;
} else {
commitSoon(ngModelController.$viewValue);
return debouncedValue;
}
});
}
};
}]);