/*!
* ng-backstretch
* https://github.com/rprovost/ng-backstretch
*
* Copyright (c) 2014-2015 Ryan Provost
* Licensed under the MIT license.
*/
angular.module('ng-backstretch', []).
directive('backstretch', ['$window', '$timeout', function($window, $timeout) {
return {
restrict: 'A',
scope: {
images: '&backstretchImages',
duration: '&backstretchDuration',
fade: '&backstretchFade'
},
link: function(scope, element, attributes) {
/* In its simplest form, we allow Backstretch to be called on an image path.
* e.g.
* So, we need to turn this back into an array.
*/
scope.images = Array.isArray(scope.images()) ? scope.images() : [scope.images()];
scope.duration = scope.duration() || 5000;
scope.fade = scope.fade() || 1;
// We need at least one image or method name
if (scope.images.length === 0) {
return false;
}
/* STYLES
*
* Baked-in styles that we'll apply to our elements.
* In an effort to keep the plugin simple, these are not exposed as options.
* That said, anyone can override these in their own stylesheet.
* ========================= */
var styles = {
wrapper: {
left: 0,
top: 0,
overflow: 'hidden',
margin: 0,
padding: 0,
height: '100%',
width: '100%',
zIndex: -999998,
position: 'absolute',
},
image: {
position: 'absolute',
opacity: 0,
margin: 0,
padding: 0,
border: 'none',
width: 'auto',
height: 'auto',
maxHeight: 'none',
maxWidth: 'none',
zIndex: -999999,
transition: 'all '+scope.fade+'s'
}
};
// create the scope.wrapper element
scope.wrapper = angular.element('
');
scope.wrapper.css(styles.wrapper);
scope.images.forEach(function(element, index, array){
scope.image = angular.element('
![]()
');
scope.image[0].src = element;
scope.image.css(styles.image);
// append these images to the wrapper
scope.wrapper.append(scope.image);
});
// append the wrapper
element.append(scope.wrapper);
// Set the first image
scope.index = 0;
scope.load = function(e) {
// figure out what the width:height ratio is
scope.ratio = this.width / this.height;
// perform an initial sizing
scope.resize();
// display the first image
scope.show(scope.index++);
};
scope.resize = function(e) {
// set some default css
var background_css = {left: 0, top: 0, width: 'auto', height: 'auto'};
// set some initial calculations
var root_width = element[0].offsetWidth,
background_width = root_width,
root_height = element[0].offsetHeight,
background_height = background_width / scope.ratio,
background_offset;
// make adjustments based on image ratio
if (background_height >= root_height) {
background_offset = (background_height - root_height) / 2;
background_css.top = '-' + background_offset + 'px';
} else {
background_height = root_height;
background_width = background_height * scope.ratio;
background_offset = (background_width - root_width) / 2;
background_css.left = '-' + background_offset + 'px';
}
// set the css for the width and height
background_css.width = background_width + 'px';
background_css.height = background_height + 'px';
// apply the appropriate styles to the wrapper and image
scope.wrapper.css({ width: root_width, height: root_height });
for(var i = 0; i < scope.wrapper.children().length; i++) {
var img = angular.element(scope.wrapper.children()[i]);
img.css(background_css);
}
};
scope.show = function(index) {
var element = scope.wrapper.children()[index];
scope.image = angular.element(element);
// only one image
if (scope.images.length === 1) {
scope.image.css({opacity:1});
return;
}
// bring things back around once we've hit the end
if (index >= scope.images.length-1) {
scope.index = 0;
}
// show the image since it's finished loading
scope.image.css({opacity:1});
// hide it once the duration has been reached
$timeout(function(){
scope.image.css({opacity:0});
}, scope.duration);
$timeout(function(){
scope.show(scope.index++);
}, scope.duration);
};
// don't do anything until the image has finished loading
scope.image.bind('load', scope.load);
// make sure to update the image sizes when the page scales/changes
angular.element($window).bind('resize', scope.resize);
}
};
}]);