angular.module('psFixedsticky', [])
.directive("fixedsticky", function(){
return {
restrict: 'AC',
scope: {
fixedsticky: '@',
fixedstickyactive: "@"
},
link: function(scope,element,attrs){
console.log(scope)
var parent = element.parent();
var fixedon = "top";
var defaultPx = {};
if(scope.fixedsticky !== undefined){
if(scope.fixedsticky.toLowerCase() == "top" || scope.fixedsticky.toLowerCase() == "bottom"){
fixedon = scope.fixedsticky.toLowerCase();
}
else fixedon = "top"
}
defaultPx[fixedon] = isNaN(element.css(fixedon)) ? 0 : element.css(fixedon)
if(isNaN(parent.data("stickyStack" + fixedon))) parent.data("stickyStack" + fixedon, defaultPx[fixedon]);
element.css(fixedon,parent.data("stickyStack"+fixedon));
parent.data("stickyStack"+fixedon, parent.data("stickyStack"+fixedon) + element[0].clientHeight)
if("fixedstickyactive" in attrs){
if(eval(scope.fixedstickyactive)){
element.fixedsticky();
}
}
else {
element.fixedsticky();
}
}
}
})
var app = angular.module('plunker', ['psFixedsticky']);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.activestuff = "true";
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="angular.js@1.2.x" src="http://code.angularjs.org/1.2.10/angular.js" data-semver="1.2.10"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div class="container" style="height: 600px; padding-top: 100px;">
<h1 fixedsticky="top"><strong>Hello My Name Is Joe</strong></h1>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h1 fixedsticky="top">test</h1>
</div>
<div>
<br />
<br />
<br />
<br />
<br />
<h1 class="top" fixedsticky>Hello My Name Is Sue</h1>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
</div>
<script src="app.js"></script>
<script src="fixed-sticky.js"></script>
</body>
</html>
/* Put your css in here */
.fixedsticky {
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
}
/* When position: sticky is supported but native behavior is ignored */
.fixedsticky-withoutfixedfixed .fixedsticky-off,
.fixed-supported .fixedsticky-off {
position: static;
}
.fixedsticky-withoutfixedfixed .fixedsticky-on,
.fixed-supported .fixedsticky-on {
position: fixed;
}
.fixedsticky-dummy {
display: none;
}
.fixedsticky-on + .fixedsticky-dummy {
display: block;
}
/* Demo CSS */
body {
font-family: sans-serif;
color: #444;
margin: 0 auto;
padding: 50px 2%;
max-width: 600px;
}
.top,
.bottom {
text-align: center;
border: solid black;
border-width: 1px 0;
padding: 1em;
width: 100%;
max-width: 600px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.top.fixedsticky-on,
.bottom.fixedsticky-on {
width: 96%;
}
/* Fixed-Sticky CSS */
.top {
top: 0;
}
.bottom {
bottom: 0;
}
#top-a {
top: 32px;
}
#bottom-b {
bottom: 16px;
}
/* Demo Colors */
#top-a,
#bottom-a {
background-color: #f00;
background-color: rgba(255,0,0,.6);
}
#top-b,
#bottom-b {
background-color: #0f0;
background-color: rgba(0,255,0,.6);
}
.container {
background-color: #999;
}
;(function( win, $ ) {
function featureTest( property, value, noPrefixes ) {
// Thanks Modernizr! https://github.com/phistuck/Modernizr/commit/3fb7217f5f8274e2f11fe6cfeda7cfaf9948a1f5
var prop = property + ':',
el = document.createElement( 'test' ),
mStyle = el.style;
if( !noPrefixes ) {
mStyle.cssText = prop + [ '-webkit-', '-moz-', '-ms-', '-o-', '' ].join( value + ';' + prop ) + value + ';';
} else {
mStyle.cssText = prop + value;
}
return mStyle[ property ].indexOf( value ) !== -1;
}
function getPx( unit ) {
return parseInt( unit, 10 ) || 0;
}
var S = {
classes: {
plugin: 'fixedsticky',
active: 'fixedsticky-on',
inactive: 'fixedsticky-off',
clone: 'fixedsticky-dummy',
withoutFixedFixed: 'fixedsticky-withoutfixedfixed'
},
keys: {
offset: 'fixedStickyOffset',
position: 'fixedStickyPosition'
},
tests: {
sticky: featureTest( 'position', 'sticky' ),
fixed: featureTest( 'position', 'fixed', true )
},
// Thanks jQuery!
getScrollTop: function() {
var prop = 'pageYOffset',
method = 'scrollTop';
return win ? (prop in win) ? win[ prop ] :
win.document.documentElement[ method ] :
win.document.body[ method ];
},
bypass: function() {
// Check native sticky, check fixed and if fixed-fixed is also included on the page and is supported
return ( S.tests.sticky && !S.optOut ) ||
!S.tests.fixed ||
win.FixedFixed && !$( win.document.documentElement ).hasClass( 'fixed-supported' );
},
update: function( el ) {
if( !el.offsetWidth ) { return; }
var $el = $( el ),
height = $el.outerHeight(),
initialOffset = $el.data( S.keys.offset ),
scroll = S.getScrollTop(),
isAlreadyOn = $el.is( '.' + S.classes.active ),
toggle = function( turnOn ) {
$el[ turnOn ? 'addClass' : 'removeClass' ]( S.classes.active )
[ !turnOn ? 'addClass' : 'removeClass' ]( S.classes.inactive );
},
viewportHeight = $( window ).height(),
position = $el.data( S.keys.position ),
skipSettingToFixed,
elTop,
elBottom,
$parent = $el.parent(),
parentOffset = $parent.offset().top,
parentHeight = $parent.outerHeight();
if( !initialOffset ) {
initialOffset = $el.offset().top;
$el.data( S.keys.offset, initialOffset );
$el.after( $( '<div>' ).addClass( S.classes.clone ).height( height ) );
}
if( !position ) {
// Some browsers require fixed/absolute to report accurate top/left values.
skipSettingToFixed = $el.css( 'top' ) !== 'auto' || $el.css( 'bottom' ) !== 'auto';
if( !skipSettingToFixed ) {
$el.css( 'position', 'fixed' );
}
position = {
top: $el.css( 'top' ) !== 'auto',
bottom: $el.css( 'bottom' ) !== 'auto'
};
if( !skipSettingToFixed ) {
$el.css( 'position', '' );
}
$el.data( S.keys.position, position );
}
function isFixedToTop() {
var offsetTop = scroll + elTop;
// Initial Offset Top
return initialOffset < offsetTop &&
// Container Bottom
offsetTop + height <= parentOffset + parentHeight;
}
function isFixedToBottom() {
// Initial Offset Top + Height
return initialOffset + ( height || 0 ) > scroll + viewportHeight - elBottom &&
// Container Top
scroll + viewportHeight - elBottom >= parentOffset + ( height || 0 );
}
elTop = getPx( $el.css( 'top' ) );
elBottom = getPx( $el.css( 'bottom' ) );
if( position.top && isFixedToTop() || position.bottom && isFixedToBottom() ) {
if( !isAlreadyOn ) {
toggle( true );
}
} else {
if( isAlreadyOn ) {
toggle( false );
}
}
},
destroy: function( el ) {
var $el = $( el );
if (S.bypass()) {
return;
}
$( win ).unbind( '.fixedsticky' );
return $el.each(function() {
$( this )
.removeData( [ S.keys.offset, S.keys.position ] )
.removeClass( S.classes.active )
.removeClass( S.classes.inactive )
.next( '.' + S.classes.clone ).remove();
});
},
init: function( el ) {
var $el = $( el );
if( S.bypass() ) {
return;
}
return $el.each(function() {
var _this = this;
$( win ).bind( 'scroll.fixedsticky', function() {
S.update( _this );
}).trigger( 'scroll.fixedsticky' );
$( win ).bind( 'resize.fixedsticky', function() {
if( $el.is( '.' + S.classes.active ) ) {
S.update( _this );
}
});
});
}
};
win.FixedSticky = S;
// Plugin
$.fn.fixedsticky = function( method ) {
if ( typeof S[ method ] === 'function') {
return S[ method ].call( S, this);
} else if ( typeof method === 'object' || ! method ) {
return S.init.call( S, this );
} else {
throw new Error( 'Method `' + method + '` does not exist on jQuery.fixedsticky' );
}
};
// Add fallback when fixed-fixed is not available.
if( !win.FixedFixed ) {
$( win.document.documentElement ).addClass( S.classes.withoutFixedFixed );
}
})( this, jQuery );