Skip to content

Instantly share code, notes, and snippets.

@simplesthing
Last active August 29, 2015 14:18
Show Gist options
  • Save simplesthing/b33a953e9c8864cda3d4 to your computer and use it in GitHub Desktop.
Save simplesthing/b33a953e9c8864cda3d4 to your computer and use it in GitHub Desktop.
timeline code to be optimized
'use strict';
app
.directive('journeyStep', function ($window, $state, $rootScope, $document, _){
return {
restrict: 'AE',
scope: {
challenge: '=',
index: '@',
total: '@',
ready: '@'
},
templateUrl: 'modules/shared/directives/journey-step.html',
link: function (scope, elem){
// set background - could do this in ng-sttr-style but liked having it here to dev the animation
elem.css({
'background-image': 'linear-gradient(hsla(0, 0%, 100%, .8), hsla(0, 0%, 100%, .8)), url(images/challenges/'+scope.challenge.attributes.image+')',
'background-position': 'top center, center center',
'background-repeat': 'no-repeat',
'background-size': 'cover',
'background-origin': 'border-box'
});
// dirty hack since scope is nested in an ng-repeat 2 way binding is not working
scope.$on('journey-coach-mark', function (e, d){
scope.ready = d;
});
elem.click(function journeyClickHandler(){
if ((scope.challenge && scope.challenge.state && scope.challenge.state !== 'locked' && scope.ready === 'false') || $rootScope.override) {
// hide footer
// angular.element('.journey-footer').hide();
document.querySelector('.journey-footer').classList.add('hide');
// remove table displays
angular.element('#journey-wrapper, .journey').css('display', 'block');
// remove overlay
angular.element('.content').removeClass('overlay');
// calculate a width - they are all logging as the size of the background image so have to switch to an avergae width on click
var avgWidth = angular.element('#journey-wrapper').innerWidth()/scope.total;
// set css for each repeated section
angular.element('.challenge').each(function (){
var self = angular.element(this);
// determine direction of slide and apply styles
if(self.data('position') > scope.index) {
self.addClass('right');
self.css({
'display': 'block',
'width': avgWidth + 'px',
'float': 'left'
});
}
if(self.data('position') < scope.index) {
self.addClass('left');
self.css({
'display': 'block',
'width': avgWidth + 'px',
'float': 'left'
});
}
// element clicked
if(self.data('position') === parseInt(scope.index)) {
self.css({
'display': 'block',
'width': avgWidth + 'px',
'float': 'left',
'background-image': 'linear-gradient(rgba(0, 0, 0, 0.0),rgba(0, 0, 0, .25)), url(images/challenges/hero-background.png), url(images/challenges/'+scope.challenge.attributes.image+')',
'background-position': 'center center',
'background-repeat': 'no-repeat',
'background-size': 'cover',
'background-origin': 'border-box'
});
// hide inner content
self.find('.content').hide();
}
});
// wrap in a directional floated parent
angular.element('.right').wrapAll('<div style="float: right; height:100%;"></div>');
angular.element('.left').wrapAll('<div style="float: left; height: 100%; "></div>');
// animate wrapper width
angular.element('#journey-wrapper').animate({
'left': '-' + avgWidth * parseInt(scope.index) + 'px',
'width': ($window.innerWidth) * 2 +'px',
'height': '100%'
}, 1000, 'linear');
// animate element width
elem.animate({
'width': $window.innerWidth + 'px'
}, 1000, 'linear', function (){
// then go to exercise
$state.go('auth.accepted.challenge.view', {
challengeId: scope.challenge.identifier,
view: 'overview',
anchor: 'journey'
});
});
}
});
// needed a flag that is visible to all repeated steps
scope.$parent.$parent.isScrolling = false;
// TODO: need to remove this event when scrolling or transitioning
elem.on('mouseenter', _.debounce(function (){
if(!scope.$parent.$parent.isScrolling) {
doScroll();
}
},100));
function doScroll (){
var offset = elem.offset(),
pageX = $window.pageXOffset,
parent = angular.element('.journey'),
// isFirst = elem.prev('article').length === 0,
// isLast = elem.next('article').length === 0,
leftHidden = pageX > offset.left,
rightHidden = elem.innerWidth()> (($window.innerWidth + pageX) - offset.left),
inViewport = !leftHidden && !rightHidden;
if(!inViewport) {
var destination = function (){
if(leftHidden) {
return offset.left - elem.innerWidth() * 0.1;
} else if(rightHidden){
var totalSteps = angular.element('.challenge').length,
thisStep = (elem.data('position')+ 1),
leftOffset = totalSteps - thisStep;
return (parent.innerWidth() - $window.innerWidth) - (elem.innerWidth() * leftOffset) + (elem.innerWidth() * 0.2);
} else {
return null;
}
};
if(destination()) {
scope.$parent.$parent.isScrolling = true;
// use scrollTo since scrollLeft method is sometimes there/not depending upon minification
$document.scrollTo(destination(), $document.scrollTop(), 500).then(function (){
scope.$parent.$parent.isScrolling = false;
});
}
}
}
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment