Created
September 21, 2016 18:08
-
-
Save cristoferdomingues/6fb4f116ed9abad50fe7e84e7193113e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// custom directive to fade in the header bar after scrolling | |
(function() { | |
'use strict'; | |
angular | |
.module('dbaq.ionCoverHeader', []) | |
.directive('ionCoverHeader', ['$document', '$timeout', '$ionicScrollDelegate', function($document, $timeout, $ionicScrollDelegate) { | |
/** | |
* updates the background opacity of an element | |
* | |
* this method retrieves automatically the background RGB and set the alpha | |
* | |
* @param elem, the DOM element to update the background opacity | |
* @param alpha, the opacity to apply, anything between 0 and 1. | |
*/ | |
var updateBackgroundAlpha = function(elem, alpha) { | |
var currentColor = getComputedStyle(elem).getPropertyValue('background-color'); | |
var match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(currentColor); | |
elem.style.backgroundColor = 'rgba(' + [match[1], match[2], match[3], alpha].join(',') + ')'; | |
}; | |
/** | |
* shows the header bar | |
* | |
* @param header, the bar-header DOM element | |
* @param headerTitle, the title DOM element in the bar-header (could be null) | |
* @param opaqueAt, the value in pixels where the bar-header should be totaly opaque | |
* @param amt, the current scrolling value, the value in pixels from the top | |
*/ | |
var showHeader = function(header, headerTitle, opaqueAt, amt) { | |
var fadeAmt = 1 - (Math.min(opaqueAt, amt) / opaqueAt); | |
ionic.requestAnimationFrame(function() { | |
updateBackgroundAlpha(header, (1 - fadeAmt)); | |
if (headerTitle) { | |
headerTitle.style.opacity = (1 - fadeAmt); | |
} | |
}); | |
}; | |
/** | |
* applies the required style on the header bar and the content | |
* | |
* - set the background opacity to 0 | |
* - set the .title element opacity to 0 if exists | |
* - remove the background image of the header bar | |
* - set the content top property to 0 | |
* | |
* @param header, the bar-header DOM element | |
* @param headerTitle, the title DOM element in the bar-header (could be null) | |
* @param content, the scroll-content DOM element | |
*/ | |
var initStyles = function(header, headerTitle, content) { | |
//header bar background opacity to 0 | |
updateBackgroundAlpha(header, 0); | |
//header bar background image to none | |
header.style.backgroundImage = 'none'; | |
//header bar title opactity to 0 | |
if (headerTitle) { | |
headerTitle.style.opacity = 0; | |
} | |
//set the content top property to 0 | |
content.style.top = 0; | |
}; | |
var computeAmt = function(opaqueAt, scrollTop) { | |
return scrollTop > 0 ? (opaqueAt - Math.max(0, (opaqueAt - scrollTop))) : 0; | |
} | |
return { | |
restrict: 'A', | |
link: function($scope, $element, $attr) { | |
var opaqueAt = $attr.ionCoverHeader || 200; | |
//retrieves elements that we need, the header bar, the header bar title, the content | |
var headerElem = $element[0].querySelector('.bar-header'); | |
var contentElem = $element[0].querySelector('.scroll-content'); | |
var ionNavBarElem; | |
var headerTitleElem; | |
//check if elems exist | |
if (!headerElem) { | |
//if no ion-header-bar, we are looking for an ion-nav-bar | |
ionNavBarElem = $document[0].querySelector('.nav-bar-container'); | |
if (!ionNavBarElem) { | |
console.error('ionCoverHeader - no .bar-header or .nav-bar-container element found.'); | |
return; | |
} | |
} | |
if (!contentElem) { | |
console.error('ionCoverHeader - no .scroll-content element found. Scroll must be enabled on your ion-content.'); | |
return; | |
} | |
var onScroll = function(e) { | |
var scrollTop = e.detail ? e.detail.scrollTop : (e.target ? e.target.scrollTop : null); | |
showHeader(headerElem, headerTitleElem, opaqueAt, computeAmt(opaqueAt, scrollTop)); | |
}; | |
var init = function (headerElem, headerTitleElem, contentElem) { | |
// makes the header bar transparent and the content stick to the top | |
initStyles(headerElem, headerTitleElem, contentElem); | |
// binds the scroll event to the content | |
angular.element(contentElem).bind('scroll', onScroll); | |
}; | |
// init | |
if (!ionNavBarElem) { | |
// retrieves the headerTitleElem | |
headerTitleElem = headerElem.querySelector('.title'); | |
init(headerElem, headerTitleElem, contentElem); | |
} else { | |
var ionNavBarCachedElem = null; | |
var ionNavBarActiveElem = null; | |
$scope.$on('$ionicView.beforeEnter', function(){ | |
// retrieves both bars generated by <ion-nav-bar> directives | |
// the active one becomes the cached one and the cached becomes the active one | |
ionNavBarCachedElem = ionNavBarElem.querySelector('[nav-bar="active"]'); | |
ionNavBarActiveElem = ionNavBarElem.querySelector('[nav-bar="cached"]'); | |
// the header elem is the header in the active bar | |
headerElem = ionNavBarActiveElem.querySelector('.bar-header'); | |
// retrieves the headerTitleElem | |
headerTitleElem = headerElem.querySelector('.title'); | |
// hides the cached bar | |
ionNavBarCachedElem.style.opacity = 0; | |
init(headerElem, headerTitleElem, contentElem); | |
// the timeout allows to fix a race condition when using ion-nav-bar on the title opacity | |
$timeout(function() { | |
headerTitleElem.style.opacity = 0; | |
}, 100); | |
}); | |
// if the view was cached, the scroll position might be greater than 0 | |
// in that case we need to show the header accordingly | |
$scope.$on('$ionicView.enter', function(){ | |
$timeout(function() { | |
if ($ionicScrollDelegate.getScrollPosition().top > 0 ) { | |
showHeader(headerElem, headerTitleElem, opaqueAt, computeAmt(opaqueAt, $ionicScrollDelegate.getScrollPosition().top)); | |
} | |
}); | |
}); | |
// since the bars are reused for other views, we need to restore the opacity | |
$scope.$on('$ionicView.beforeLeave', function(){ | |
angular.element(contentElem).unbind('scroll', onScroll); | |
ionNavBarCachedElem.style.opacity = 1; | |
$timeout(function() { | |
updateBackgroundAlpha(headerElem, 1); | |
headerTitleElem.style.opacity = 1; | |
}); | |
}); | |
} | |
} | |
}; | |
}]); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment