Functional directives TS

This commit is contained in:
Mo Bitar
2020-04-13 08:27:10 -05:00
parent 38873afa43
commit aed8d4a3da
15 changed files with 138 additions and 120 deletions

View File

@@ -1,16 +0,0 @@
/* @ngInject */
export function autofocus($timeout) {
return {
restrict: 'A',
scope: {
shouldFocus: '='
},
link: function($scope, $element) {
$timeout(function() {
if ($scope.shouldFocus) {
$element[0].focus();
}
});
}
};
}

View File

@@ -0,0 +1,19 @@
/* @ngInject */
export function autofocus($timeout: ng.ITimeoutService) {
return {
restrict: 'A',
scope: {
shouldFocus: '='
},
link: function (
$scope: ng.IScope,
$element: JQLite
) {
$timeout(() => {
if (($scope as any).shouldFocus) {
$element[0].focus();
}
});
}
};
}

View File

@@ -1,9 +1,9 @@
/* @ngInject */
export function clickOutside($document) {
export function clickOutside($document: ng.IDocumentService) {
return {
restrict: 'A',
replace: false,
link: function ($scope, $element, attrs) {
link: function ($scope: ng.IScope, $element: JQLite, attrs: any) {
// Causes memory leak as-is:
// let didApplyClickOutside = false;

View File

@@ -1,44 +0,0 @@
import angular from 'angular';
/* @ngInject */
export function delayHide($timeout) {
return {
restrict: 'A',
scope: {
show: '=',
delay: '@'
},
link: function(scope, elem, attrs) {
showElement(false);
// This is where all the magic happens!
// Whenever the scope variable updates we simply
// show if it evaluates to 'true' and hide if 'false'
scope.$watch('show', function(newVal) {
newVal ? showSpinner() : hideSpinner();
});
function showSpinner() {
if (scope.hidePromise) {
$timeout.cancel(scope.hidePromise);
scope.hidePromise = null;
}
showElement(true);
}
function hideSpinner() {
scope.hidePromise = $timeout(showElement.bind(this, false), getDelay());
}
function showElement(show) {
show ? elem.css({ display: '' }) : elem.css({ display: 'none' });
}
function getDelay() {
var delay = parseInt(scope.delay);
return angular.isNumber(delay) ? delay : 200;
}
}
};
}

View File

@@ -0,0 +1,45 @@
import angular from 'angular';
/* @ngInject */
export function delayHide($timeout: ng.ITimeoutService) {
return {
restrict: 'A',
scope: {
show: '=',
delay: '@'
},
link: function (scope: ng.IScope, elem: JQLite) {
const scopeAny = scope as any;
const showSpinner = () => {
if (scopeAny.hidePromise) {
$timeout.cancel(scopeAny.hidePromise);
scopeAny.hidePromise = null;
}
showElement(true);
}
const hideSpinner = () => {
scopeAny.hidePromise = $timeout(
showElement.bind(this as any, false),
getDelay()
);
}
const showElement = (show: boolean) => {
show ? elem.css({ display: '' }) : elem.css({ display: 'none' });
}
const getDelay = () => {
const delay = parseInt(scopeAny.delay);
return angular.isNumber(delay) ? delay : 200;
}
showElement(false);
// Whenever the scope variable updates we simply
// show if it evaluates to 'true' and hide if 'false'
scope.$watch('show', function (newVal) {
newVal ? showSpinner() : hideSpinner();
});
}
};
}

View File

@@ -1,8 +1,8 @@
/* @ngInject */
export function elemReady($parse) {
export function elemReady($parse: ng.IParseService) {
return {
restrict: 'A',
link: function($scope, elem, attrs) {
link: function($scope: ng.IScope, elem: JQLite, attrs: any) {
elem.ready(function() {
$scope.$apply(function() {
var func = $parse(attrs.elemReady);

View File

@@ -1,16 +0,0 @@
/* @ngInject */
export function fileChange() {
return {
restrict: 'A',
scope: {
handler: '&'
},
link: function(scope, element) {
element.on('change', function(event) {
scope.$apply(function() {
scope.handler({ files: event.target.files });
});
});
}
};
}

View File

@@ -0,0 +1,19 @@
/* @ngInject */
export function fileChange() {
return {
restrict: 'A',
scope: {
handler: '&'
},
link: function (scope: ng.IScope, element: JQLite) {
element.on('change', (event) => {
scope.$apply(() => {
const files = (event.target as HTMLInputElement).files;
(scope as any).handler({
files: files
});
});
});
}
};
}

View File

@@ -1,10 +1,11 @@
/* @ngInject */
export function infiniteScroll() {
return {
link: function(scope, elem, attrs) {
link: function (scope: ng.IScope, elem: JQLite, attrs: any) {
const scopeAny = scope as any;
const offset = parseInt(attrs.threshold) || 0;
const e = elem[0];
scope.onScroll = () => {
scopeAny.onScroll = () => {
if (
scope.$eval(attrs.canLoad) &&
e.scrollTop + e.offsetHeight >= e.scrollHeight - offset
@@ -12,9 +13,9 @@ export function infiniteScroll() {
scope.$apply(attrs.infiniteScroll);
}
};
elem.on('scroll', scope.onScroll);
elem.on('scroll', scopeAny.onScroll);
scope.$on('$destroy', () => {
elem.off('scroll', scope.onScroll);;
elem.off('scroll', scopeAny.onScroll);;
});
}
};

View File

@@ -1,19 +0,0 @@
/* @ngInject */
export function lowercase() {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
var lowercase = function(inputValue) {
if (inputValue === undefined) inputValue = '';
var lowercased = inputValue.toLowerCase();
if (lowercased !== inputValue) {
modelCtrl.$setViewValue(lowercased);
modelCtrl.$render();
}
return lowercased;
};
modelCtrl.$parsers.push(lowercase);
lowercase(scope[attrs.ngModel]);
}
};
}

View File

@@ -0,0 +1,24 @@
/* @ngInject */
export function lowercase() {
return {
require: 'ngModel',
link: function (
scope: ng.IScope,
_: JQLite,
attrs: any,
ctrl: ng.IController
) {
const lowercase = (inputValue: string) => {
if (inputValue === undefined) inputValue = '';
const lowercased = inputValue.toLowerCase();
if (lowercased !== inputValue) {
ctrl.$setViewValue(lowercased);
ctrl.$render();
}
return lowercased;
};
ctrl.$parsers.push(lowercase);
lowercase((scope as any)[attrs.ngModel]);
}
};
}

View File

@@ -1,14 +0,0 @@
/* @ngInject */
export function selectOnClick($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.on('focus', function() {
if (!$window.getSelection().toString()) {
/** Required for mobile Safari */
this.setSelectionRange(0, this.value.length);
}
});
}
};
}

View File

@@ -0,0 +1,15 @@
/* @ngInject */
export function selectOnClick($window: ng.IWindowService) {
return {
restrict: 'A',
link: function(scope: ng.IScope, element: JQLite) {
element.on('focus', function() {
if (!$window.getSelection()!.toString()) {
const input = element as any;
/** Required for mobile Safari */
input.setSelectionRange(0, input.value.length);
}
});
}
};
}

View File

@@ -1,9 +1,13 @@
/* @ngInject */
export function snEnter() {
return function(scope, element, attrs) {
element.bind('keydown keypress', function(event) {
return function (
scope: ng.IScope,
element: JQLite,
attrs: any
) {
element.bind('keydown keypress', function (event) {
if (event.which === 13) {
scope.$apply(function() {
scope.$apply(function () {
scope.$eval(attrs.snEnter, { event: event });
});