Skip to content

Instantly share code, notes, and snippets.

@adamreisnz
Last active October 18, 2023 04:11
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save adamreisnz/2664df320da873c69e0f to your computer and use it in GitHub Desktop.
Save adamreisnz/2664df320da873c69e0f to your computer and use it in GitHub Desktop.
A collection of random useful Angular directives
Angular directives
/**
* Module definition and dependencies
*/
angular.module('Layout.BackgroundImage.Directive', [])
/**
* Directive definition
*/
.directive('backgroundImage', function($document, $animate) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
attrs.$observe('backgroundImage', function(src) {
//Add loading class and reset background image
element.addClass('loading').css({
'background-image': null
});
//Create image element
var img = $document[0].createElement('img');
//Append onload event
img.onload = function() {
//Remove loading class using the animate service (to trigger CSS animations)
$animate.removeClass(element, 'loading');
element.css({
'background-image': 'url(' + this.src + ')'
});
};
//Set source on image now
img.src = src;
});
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Events.DetectScrolling.Directive', [])
/**
* Directive
*/
.directive('detectScrolling', function($rootScope) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
//Attach event to element
element.on('scroll', function() {
var scrollOffset = 0;
if (angular.isDefined(element[0].scrollTop)) {
scrollOffset = element[0].scrollTop;
}
else if (element[0].context && angular.isDefined(element[0].context.scrollTop)) {
scrollOffset = element[0].context.scrollTop;
}
//Broadcast event
scope.$apply(function() {
scope.isScrolling = (scrollOffset > 0);
$rootScope.$broadcast('detectedScrolling', scrollOffset, element);
});
});
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Events.DetectWindowScrolling.Directive', [])
/**
* Directive
*/
.directive('detectWindowScrolling', function($window, $rootScope) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
angular.element($window).on('scroll resize', function() {
scope.$apply(function() {
scope.isScrolling = ($window.pageYOffset > 0);
$rootScope.$broadcast('detectedScrolling', $window.pageYOffset, $window);
});
});
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Layout.DisableAnimate.Directive', [])
/**
* Animate disabler
*/
.directive('disableAnimate', function($animate) {
return function(scope, element) {
$animate.enabled(false, element);
};
});
/**
* Module definition and dependencies
*/
angular.module('Validation.EqualOrMore.Directive', [])
/**
* Directive
*/
.directive('equalOrMore', function($parse) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
//Match getter
var matchGetter = $parse(attrs.equalOrMore);
var allowEmpty = (attrs.allowEmpty === 'true');
//Match value helper
function getMatchValue() {
var match = matchGetter(scope);
if (angular.isObject(match) && match.hasOwnProperty('$viewValue')) {
match = match.$viewValue;
}
return match;
}
//Re-validate on change of the match value
scope.$watch(getMatchValue, function() {
ngModel.$validate();
});
//Add validator
ngModel.$validators.equalOrMore = function(modelValue, viewValue) {
//Get match value and our value
var value = modelValue || viewValue;
var match = getMatchValue();
//Must have match
if (match === null || !angular.isDefined(match)) {
return true;
}
//Allow empty?
if (allowEmpty && (value === null || !angular.isDefined(value) || value === '')) {
return true;
}
//Check match
return value >= match;
};
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Ui.FullScreen.Directive', [])
/**
* Service definition
*/
.factory('FullScreen', function($document, $rootScope) {
//Get document element
var document = $document[0];
//Create service instance
var FullScreen = {
/**
* Enable full screen on the complete document
*/
all: function() {
FullScreen.enable(document.documentElement);
},
/**
* Enable full screen on a specific element
*/
enable: function(element) {
if (element.requestFullScreen) {
element.requestFullScreen();
}
else if(element.mozRequestFullScreen) {
element.mozRequestFullScreen();
}
else if(element.webkitRequestFullScreen) {
element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
},
/**
* Disable full screen
*/
disable: function() {
if (document.cancelFullScreen) {
document.cancelFullScreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
},
/**
* Check to see if full screen is enabled
*/
isEnabled: function() {
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
return fullscreenElement;
},
/**
* Check to see if full screen mode is supported
*/
isSupported: function() {
return document.documentElement.requestFullScreen ||
document.documentElement.mozRequestFullScreen ||
document.documentElement.webkitRequestFullScreen ||
document.documentElement.msRequestFullscreen;
}
};
//Return the instance
return FullScreen;
})
/**
* Directive
*/
.directive('fullscreen', function($rootScope, FullScreen) {
return {
link: function (scope, element, attrs) {
//Watch for changes on scope if model is provided
if (attrs.fullscreen) {
scope.$watch(attrs.fullscreen, function(value) {
var isEnabled = FullScreen.isEnabled();
if (value && !isEnabled) {
FullScreen.enable(element[0]);
element.addClass('full-screen');
}
else if (!value && isEnabled) {
FullScreen.cancel();
element.removeClass('full-screen');
}
});
element.on('fullscreenchange webkitfullscreenchange mozfullscreenchange', function() {
if (!FullScreen.isEnabled()){
scope.$evalAsync(function() {
scope[attrs.fullscreen] = false;
element.removeClass('full-screen');
});
}
});
}
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Validation.IsolatedForm.Directive', [])
/**
* Directive
*/
.directive('isolatedForm', function($animate) {
return {
restrict: 'A',
require: '?form',
link: function(scope, element, attrs, ngModel) {
//Must have model controller
if (!ngModel) {
return;
}
//Copy the controller
var ngModelCopy = {};
angular.copy(ngModel, ngModelCopy);
//Get the parent element of the form
var parent = element.parent().controller('form');
//Remove parent link to the controller
parent.$removeControl(ngModel);
//Replace form controller with an isolated version
var ngModelIsolated = {
$setValidity: function(validationToken, isValid, control) {
ngModelCopy.$setValidity(validationToken, isValid, control);
parent.$setValidity(validationToken, true, ngModel);
},
$setDirty: function() {
$animate.removeClass(element, 'ng-pristine');
$animate.addClass(element, 'ng-dirty');
ngModel.$dirty = true;
ngModel.$pristine = false;
},
$setSubmitted: function() {
$animate.addClass(element, 'ng-submitted');
ngModel.$submitted = true;
}
};
//Extend the controller now
angular.extend(ngModel, ngModelIsolated);
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Layout.IsOverflowing.Directive', [])
/**
* Directive
*/
.directive('isOverflowing', function() {
/**
* Helper to determine if overflowing
*/
function isOverflowing(element) {
//Remember current overflow, and set to hidden
var curOverflow = element[0].style.overflow;
element[0].style.overflow = 'hidden';
//Determine if overflowing and set back to original value
var overflowing = element[0].clientWidth < element[0].scrollWidth ||
element[0].clientHeight < element[0].scrollHeight;
element[0].style.overflow = curOverflow;
//Return
return overflowing;
}
/**
* Directive
*/
return {
link: function(scope, element, attrs) {
//Determine overflow class
var overflowClass = attrs.checkOverflow || 'overflowing';
//Watch content
scope.$watch(function() {
return element[0].text;
}, function() {
if (isOverflowing(element)) {
element.addClass(overflowClass);
}
else {
element.removeClass(overflowClass);
}
});
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Validation.Match.Directive', [])
/**
* Directive
*/
.directive('match', function($parse) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
//Match getter
var matchGetter = $parse(attrs.match);
var allowEmpty = (attrs.allowEmpty === 'true');
//Match value helper
function getMatchValue() {
var match = matchGetter(scope);
if (angular.isObject(match) && match.hasOwnProperty('$viewValue')) {
match = match.$viewValue;
}
return match;
}
//Re-validate on change of the match value
scope.$watch(getMatchValue, function() {
ngModel.$validate();
});
//Add validator
ngModel.$validators.match = function(modelValue, viewValue) {
//Get match value and our value
var value = modelValue || viewValue;
var match = getMatchValue();
//Must have match
if (match === null || !angular.isDefined(match)) {
return true;
}
//Allow empty?
if (allowEmpty && (value === null || !angular.isDefined(value) || value === '')) {
return true;
}
//Check match
return value === match;
};
}
};
});
/**
* Module definition and dependencies
*/
angular.module('Validation.MaxFileSize.Directive', [])
/**
* Directive
*/
.directive('maxFileSize', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
//Get max file size
var maxSize = parseInt(attrs.maxFileSize, 10);
//Add validator
ngModel.$validators.fileSize = function(modelValue, viewValue) {
//No max size limit?
if (maxSize === 0) {
return true;
}
//Get files list
var model = modelValue || viewValue;
if (!model.files) {
return true;
}
//Loop and check each file
for (var i = 0; i < model.files.length; i++) {
if (model.files[i].size && model.files[i].size > maxSize) {
return false;
}
if (model.files[i].fileSize && model.files[i].fileSize > maxSize) {
return false;
}
}
//By default, pass through
return true;
};
}
};
});
@arangates
Copy link

awesome...Excited for Angular 5 version for these !!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment