@@ -1,5 +1,5 @@
/*
* Clingify v1.0.1
* Clingify v1.1
*
* A jQuery 1.7+ plugin for sticky elements
* http://github.com/theroux/clingify
@@ -14,153 +14,248 @@

// defaults
var pluginName = 'clingify',
// the name of using in .data()
dataPlugin = "plugin_" + pluginName,
defaults = {
breakpoint: 0,
// Media query width breakpoint in pixels.
breakpointHeight: 0,
breakpointWidth: 0,
// Media query breakpoints in pixels.
// Below this value, Clingify behavior is disabled. (Useful for small screens.)
// Use 0 if you want Clingify to work at all screen widths.
// Use 0 if you want Clingify to work at all screen widths/heights.

extraClass: '',
// Add an additional class of your choosing to the sticky element
// and its parent wrapper & placeholder divs

throttle: 100,
throttle: 50,
// Delay Clingify functions, in milliseconds, when scrolling/resizing.
// Too fast is bad for performance, especially on older browsers/machines.

// Callback functions
detached: $.noop, // Fires before element is detached
locked: $.noop, // Fires before element is attached
resized: $.noop // Fires after window resize event, benefits from the throttle
resized: $.noop, // Fires after window resize event, benefits from the throttle

// Classes for CSS hooks
wrapperClass: 'js-clingify-wrapper',
lockedClass: 'js-clingify-locked',
overrideClass: 'js-clingify-permalock',
placeholderClass: 'js-clingify-placeholder'
},
wrapperClass = 'js-clingify-wrapper',
lockedClass = 'js-clingify-locked',
placeholderClass = 'js-clingify-placeholder',
$buildPlaceholder = $('<div>').addClass(placeholderClass),
$buildWrapper = $('<div>').addClass(wrapperClass),
$window = $(window);

// plugin constructor
function Plugin(element, options) {
this.element = element; // The element is the thing you passed to clingify()
/*
var privateMethod = function () {
console.log("private methods go here!");
};
*/

// turn our Clingify element into jQuery object
this.$element = $(element);

// Overwrites defaults with options
this.options = $.extend({}, defaults, options);

this._defaults = defaults;
this._name = pluginName;

this.vars = {
elemHeight: this.$element.height()
};
this.init();
}
// The actual plugin constructor
var Plugin = function ( element ) {
// Plugin instantiation

this.element = element;
this.options = $.extend( {}, defaults );
};

Plugin.prototype = {

init: function() {
init: function ( options ) {

// extend options ( http://api.jquery.com/jQuery.extend/ )
$.extend( this.options, options );
var cling = this,
$elem = $(this.element),
scrollTimeout,
throttle = cling.options.throttle,
extraClass = cling.options.extraClass;

// Give Clingify element two wrapper divs.
// Placeholder div is set to same height as element
// This ensures content beneath element does not re-flow.
// Wrapper div is 100% width, which eases styling/centering/positioning
cling.$element
.wrap($buildPlaceholder.height(cling.vars.elemHeight))
.wrap($buildWrapper);
throttle = this.options.throttle;

this.wrap();

if ((extraClass !== '') && (typeof extraClass === 'string')) {
cling.findWrapper().addClass(extraClass);
cling.findPlaceholder().addClass(extraClass);
if ((this.options.extraClass !== "") && (typeof this.options.extraClass === "string")) {
this.findWrapper().addClass(this.options.extraClass);
this.findPlaceholder().addClass(this.options.extraClass);
this.options.wrapperClass += "." + this.options.extraClass;
this.options.placeholderClass += "." + this.options.extraClass;
}

this.bindScroll();
this.bindResize();
},

bindResize: function() {
var cling = this,
scrollTimeout;

$window.on('scroll resize', function(event) {
$window.on('resize.Clingify', function(event) {
if (!scrollTimeout) {
scrollTimeout = setTimeout(function() {
if ((event.type === 'resize') && (typeof cling.options.resized === 'function')) {
cling.options.resized();
}
cling.checkElemStatus();
scrollTimeout = null;
}, throttle);
}, cling.options.throttle);
}
});
},

bindScroll: function() {
var cling = this,
scrollTimeout;

$window.on('scroll.Clingify', function(event) {
if (!scrollTimeout) {
scrollTimeout = setTimeout(function() {
cling.checkElemStatus();
scrollTimeout = null;
}, cling.options.throttle);
}
});
},

unbindResize: function() {
$window.off('resize.Clingify');
},
unbindScroll: function() {
$window.off('scroll.Clingify');
},

destroy: function () {
this.unwrap();

// unset Plugin data instance
this.element.removeData(dataPlugin);
return;
},

//Other functions below
checkCoords: function() {
var coords = {
windowWidth: $window.width(),
windowOffset: $window.scrollTop(),
// Y-position for Clingify placeholder
// needs to be recalculated in DOM has shifted
placeholderOffset: this.findPlaceholder().offset().top
};
windowHeight: $window.height(),
windowWidth: $window.width(),
windowOffset: $window.scrollTop(),
// Y-position for Clingify placeholder
// needs to be recalculated in DOM has shifted
placeholderOffset: this.findPlaceholder().offset().top
};
return coords;
},

detachElem: function() {
if (typeof this.options.detached === 'function') {
this.options.detached(); // fire callback
}
this.findWrapper().removeClass(lockedClass);
if (this.findWrapper().hasClass(this.options.overrideClass)) {
return;
} else {
this.findWrapper().removeClass(this.options.lockedClass);
}
return;
},

lockElem: function() {
if (typeof this.options.locked === 'function') {
this.options.locked(); // fire callback
}
this.findWrapper().addClass(lockedClass);
this.findWrapper().addClass(this.options.lockedClass);
return;
},

findPlaceholder: function() {
return this.$element.closest('.'+placeholderClass);
return this.$element.closest('.'+ this.options.placeholderClass);
},

findWrapper: function() {
return this.$element.closest('.'+wrapperClass);
return this.$element.closest('.'+ this.options.wrapperClass);
},

checkElemStatus: function() {
var cling = this,
currentCoords = cling.checkCoords(),
currentCoords = this.checkCoords(),
isScrolledPast = function() {
if (currentCoords.windowOffset >= currentCoords.placeholderOffset) {
return true;
} else {
return false;
}
},
isWideEnough = function() {
if (currentCoords.windowWidth >= cling.options.breakpoint) {
isWideTallEnough = function() {
if ((currentCoords.windowWidth >= cling.options.breakpointWidth) && currentCoords.windowHeight >= cling.options.breakpointHeight) {
return true;
} else {
return false;
}
};

if (isScrolledPast() && isWideEnough()) {
cling.lockElem();
} else if (!isScrolledPast() || !isWideEnough()) {
cling.detachElem();
if (isScrolledPast() && isWideTallEnough()) {
this.lockElem();
} else if (!isScrolledPast() || !isWideTallEnough()) {
this.detachElem();
}
return;
},

unwrap: function() {
// Removes wrapper and placeholder
this.findPlaceholder().replaceWith(this.element);
return;
},
test: function() {
console.log('Public test method is working!');
},

wrap: function() {
// Creates wrapper and placeholder divs
var $buildPlaceholder = $('<div>').addClass(this.options.placeholderClass),
$buildWrapper = $('<div>').addClass(this.options.wrapperClass);

this.$element = $(this.element);
this.elemHeight = this.$element.outerHeight();

this.$element
.wrap($buildPlaceholder.height(this.elemHeight))
.wrap($buildWrapper);
this.findPlaceholder().height(this.elemHeight);
return;
}
};

$.fn[ pluginName ] = function ( arg ) {

// wrapper that prevents multiple instantiations
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
var args, instance;

// only allow the plugin to be instantiated once
if (!( this.data( dataPlugin ) instanceof Plugin )) {

// if no instance, create one
this.data( dataPlugin, new Plugin( this ) );
}

instance = this.data( dataPlugin );

instance.element = this;

// Is the first parameter an object (arg), or was omitted,
// call Plugin.init( arg )
if (typeof arg === 'undefined' || typeof arg === 'object') {

if ( typeof instance['init'] === 'function' ) {
instance.init( arg );
}
});
};

// checks that the requested public method exists
} else if ( typeof arg === 'string' && typeof instance[arg] === 'function' ) {

// copy arguments & remove function name
args = Array.prototype.slice.call( arguments, 1 );

// call the method
return instance[arg].apply( instance, args );

} else {

$.error('Method ' + arg + ' does not exist on jQuery.' + pluginName);

}
};
})(jQuery, window, document);

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.