diff --git a/Copyright b/Copyright
index 925fd2a..4bd51d6 100644
--- a/Copyright
+++ b/Copyright
@@ -1,5 +1,5 @@
/*!
- * Midnight.js <%= version %>
+ * Midnight.js <%= pkg.version %>
* jQuery plugin to switch between multiple fixed header designs on the fly, so it looks in line with the content below it.
* http://aerolab.github.io/midnight.js/
*
@@ -8,4 +8,3 @@
* Released under the MIT license
* http://aerolab.github.io/midnight.js/LICENSE.txt
*/
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 9d034ae..3e6ae64 100644
--- a/README.md
+++ b/README.md
@@ -122,7 +122,9 @@ $('nav').midnight({
// The class that wraps the contents of each header. Also used as a clipping mask.
innerClass: 'midnightInner',
// The class used by the default header (useful when adding multiple headers with different markup).
- defaultClass: 'default'
+ defaultClass: 'default',
+ // Define `Y` or `X` axis to use the effect vertically(Y) or horizontally(X)
+ axis: 'Y'
});
```
diff --git a/gulpfile.js b/gulpfile.js
index ee640ce..b85ff35 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -3,20 +3,18 @@ var gulp = require('gulp')
, uglify = require("gulp-uglify")
, concat = require("gulp-concat")
, header = require("gulp-header");
-
-var getVersion = function () {
- info = require("./package.json");
- return info.version;
-};
-var getCopyright = function () {
- return fs.readFileSync('Copyright');
-};
+var pkg = require('./package.json');
-gulp.task('build', function () {
- gulp.src('./midnight.jquery.js')
- .pipe(uglify({preserveComments:'some'}))
+function buildFunction () {
+ return gulp.src('./midnight.jquery.js', {sourcemaps: true})
+ .pipe(uglify({output: {comments:'some'}}))
+ .pipe(header(fs.readFileSync('./Copyright', 'utf8'), { pkg : pkg } ))
.pipe(concat('midnight.jquery.min.js'))
.pipe(gulp.dest('./'));
-});
+}
-gulp.task('default', ['build']);
+var build = gulp.series(buildFunction);
+
+exports.build = build;
+
+exports.default = build;
diff --git a/midnight.jquery.js b/midnight.jquery.js
index d88e605..fe79002 100644
--- a/midnight.jquery.js
+++ b/midnight.jquery.js
@@ -1,5 +1,5 @@
/*!
- * Midnight.js 1.1.1
+ * Midnight.js 1.2.0
* jQuery plugin to switch between multiple fixed header designs on the fly, so it looks in line with the content below it.
* http://aerolab.github.io/midnight.js/
*
@@ -9,498 +9,537 @@
* http://aerolab.github.io/midnight.js/LICENSE.txt
*/
// jQuery Widget
-(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){var t=0,i=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var s,n,a=i.call(arguments,1),o=0,r=a.length;r>o;o++)for(s in a[o])n=a[o][s],a[o].hasOwnProperty(s)&&void 0!==n&&(t[s]=e.isPlainObject(n)?e.isPlainObject(t[s])?e.widget.extend({},t[s],n):e.widget.extend({},n):n);return t},e.widget.bridge=function(t,s){var n=s.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=i.call(arguments,1),h=this;return a=!o&&r.length?e.widget.extend.apply(null,[a].concat(r)):a,o?this.each(function(){var i,s=e.data(this,n);return"instance"===a?(h=s,!1):s?e.isFunction(s[a])&&"_"!==a.charAt(0)?(i=s[a].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var t=e.data(this,n);t?(t.option(a||{}),t._init&&t._init()):e.data(this,n,new s(a,this))}),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(i,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=t++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget});
-
-((function ( $ ) {
-
- "use strict";
-
- $.widget('aerolab.midnight', {
-
- options: {
- // The class that wraps each header. Used as a clipping mask.
- headerClass: 'midnightHeader',
- // The class that wraps the contents of each header. Also used as a clipping mask.
- innerClass: 'midnightInner',
- // The class used by the default header (useful when adding multiple headers with different markup).
- defaultClass: 'default',
- // Unused: Add a prefix to the header classes (so if you set the "thingy-" prefix, a section with data-midnight="butterfly" will use the "thingy-butterfly" header)
- classPrefix: '',
- // If you want to use plugin more than once or if you want a different data attribute name (so if you set the "header" in a section use data-header)
- sectionSelector: 'midnight'
- },
-
- // Cache all the switchable headers (different colors)
- _headers: {},
- _headerInfo: {top:0, height:0},
-
- // Cache all the sections which cause the header to change colors
- _$sections: [],
- _sections: [],
-
- // Scroll Cache
- _scrollTop: 0,
- _documentHeight: 0,
-
- // Tools
- _transformMode: false,
-
-
- refresh: function() {
-
- this._headerInfo = {
- // Todo: Add support for top (though it's mostly unnecessary)
- top: 0,
- height: this.element.outerHeight()
- };
-
- // Sections that affect the color of the header (and cache)
- this._$sections = $('[data-'+ this.options.sectionSelector +']:not(:hidden)');
- this._sections = [];
-
- this._setupHeaders();
-
- this.recalculate();
-
- },
-
- _create: function() {
-
- var context = this;
- this._scrollTop = window.pageYOffset || document.documentElement.scrollTop;
- this._documentHeight = $(document).height();
- this._headers = {};
-
- this._transformMode = this._getSupportedTransform();
-
- // Calculate all sections and create the necessary headers
- this.refresh();
-
-
- // NANANANANANANANA GRASAAAAA
- // (This is the ghetto way of keeping the section values updated after any kind of reflow. The overhead is minimal)
- setInterval(function(){
- context._recalculateSections();
- }, 1000);
-
-
- // We need to recalculate all this._sections and headers
- context.recalculate();
-
-
- // and at every resize
- $(window).resize(function(){
- context.recalculate();
- });
-
-
- // Start the RequestAnimationFrame loop. This should be done just once.
- this._updateHeadersLoop();
-
- },
-
-
- recalculate: function() {
- this._recalculateSections();
- this._updateHeaderHeight();
-
- this._recalculateHeaders();
- this._updateHeaders();
- },
-
-
- /**
- * This is to offer the optimal transform format when updating the header
- */
- _getSupportedTransform: function() {
- var prefixes = ['transform','WebkitTransform','MozTransform','OTransform','msTransform'];
- for(var ix = 0; ix < prefixes.length; ix++) {
- if(document.createElement('div').style[prefixes[ix]] !== undefined) {
- return prefixes[ix];
- }
- }
- return false;
- },
-
-
- /**
- * Get the size of the header.
- */
- _getContainerHeight: function(){
- var $customHeaders = this.element.find('> .'+this.options['headerClass']);
- var maxHeight = 0;
- var height = 0;
- var context = this;
-
- if( $customHeaders.length ) {
- $customHeaders.each(function() {
-
- var $header = $(this);
- var $inner = $header.find('> .'+context.options['innerClass']);
-
- // Disable the fixed height and trigger a reflow to get the proper height
- // Get the inner height or just the height of the container
- if( $inner.length ) {
- // Overflow: Auto fixes an issue with Chrome 41, where outerHeight() no longer takes into account
- // the margins of internal elements, creating a smaller container than necessary
- $inner.css('bottom', 'auto').css('overflow', 'auto');
- height = $inner.outerHeight();
- $inner.css('bottom', '0');
- } else {
- $header.css('bottom', 'auto');
- height = $header.outerHeight();
- $header.css('bottom', '0');
- }
-
- maxHeight = (height > maxHeight) ? height : maxHeight;
- });
- } else {
- maxHeight = height = this.element.outerHeight();
- }
- return maxHeight;
- },
-
-
- _setupHeaders: function(){
-
- // Get all the different header colors
- var context = this;
- this._headers[this.options['defaultClass']] = {};
-
- for( var i=0; i
.'+this.options['headerClass']);
- if( $customHeaders.length ) {
- if( ! $customHeaders.filter('.'+ this.options['defaultClass']).length ) {
- // If there's no default header, just pick the first one, duplicate it, and set the correct class
- $customHeaders.filter('.'+ this.options['headerClass'] +':first').clone(true, true).attr('class', this.options['headerClass'] +' '+ this.options['defaultClass']);
- }
- } else {
- // If there are no custom headers, just wrap the content and make that the default header
-
- this.element.wrapInner('');
- }
-
- // Make a copy of the default header for use in the generic ones.
- var $customHeaders = this.element.find('> .'+ this.options['headerClass']);
- var $defaultHeader = $customHeaders.filter('.'+ this.options['defaultClass']).clone(true, true);
-
-
-
- for( var headerClass in this._headers ) {
- if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
- if( typeof this._headers[headerClass].element === 'undefined' ) {
-
- // Create the outer clipping mask
- // If there's some custom markup, use it, or else just clone the default header
- var $existingHeader = $customHeaders.filter('.'+headerClass);
- if( $existingHeader.length ) {
- this._headers[headerClass].element = $existingHeader;
- } else {
- this._headers[headerClass].element = $defaultHeader.clone(true, true).removeClass( this.options['defaultClass'] ).addClass(headerClass).appendTo( this.element );
- }
-
- var resetStyles = {
- position: 'absolute',
- overflow: 'hidden',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0
- };
- this._headers[headerClass].element.css(resetStyles);
-
- if( this._transformMode !== false ) {
- this._headers[headerClass].element.css(this._transformMode, 'translateZ(0)');
- }
-
- // Create the inner clipping mask
- if( ! this._headers[headerClass].element.find('> .'+ this.options['innerClass']).length ) {
- this._headers[headerClass].element.wrapInner('');
- }
- this._headers[headerClass].inner = this._headers[headerClass].element.find('> .'+ this.options['innerClass'])
- this._headers[headerClass].inner.css(resetStyles);
-
- if( this._transformMode !== false ) {
- this._headers[headerClass].inner.css(this._transformMode, 'translateZ(0)');
- }
-
- // Set the default clipping variables
- this._headers[headerClass].from = '';
- this._headers[headerClass].progress = 0.0;
- }
- }
-
-
- // Headers that weren't initialized have to be hidden
- $customHeaders.each(function(){
- var $header = $(this);
- var hasAnyClass = false;
- for( var headerClass in context._headers ) {
- if( ! context._headers.hasOwnProperty(headerClass) ){ continue; }
- if( $header.hasClass(headerClass) ){ hasAnyClass = true; }
- }
-
- // Add the inner clipping mask just in case
- if( ! $header.find('> .'+ context.options['innerClass']).length ) {
- $header.wrapInner('');
- }
-
- if( hasAnyClass ) {
- $header.show();
- } else {
- $header.hide();
- }
- });
-
- },
-
-
- /**
- * Recalculate which headers should be visible at this time based on the scroll position and the (cached) position of each section.
- * This doesn't update
- */
- _recalculateHeaders: function(){
-
- // Check classes are currently active in the header (including the current percentage of each)
- this._scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
- // Some browsers (e.g on OS X) allow scrolling past the top/bottom.
- this._scrollTop = Math.max(this._scrollTop, 0);
- this._scrollTop = Math.min(this._scrollTop, this._documentHeight);
-
- // Get the header's position relative to the document (given that it's fixed)
- var headerHeight = this._headerInfo.height;
- var headerStart = this._scrollTop + this._headerInfo.top;
- var headerEnd = headerStart + headerHeight;
-
- // Add support for transforms (for plugins like Headroom or general css stuff)
- if( typeof window.getComputedStyle === 'function' ) {
- var style = window.getComputedStyle(this.element[0], null);
- var styleTop = style.top;
- var top = 0.0;
- var transformY = 0.0;
-
- if( this._transformMode !== false && typeof style.transform === 'string' ) {
- // Convert the transform matrix to an array
- var transformArray = (style.transform).match(/(-?[0-9\.]+)/g);
- if( transformArray !== null && transformArray.length >= 6 && ! isNaN(parseFloat(transformArray[5])) ) {
- transformY = parseFloat(transformArray[5]);
- }
- }
- if ( style.top.indexOf('%') >= 0 && ! isNaN(parseFloat(styleTop)) ) {
- // SAFARI ISSUE https://bugs.webkit.org/show_bug.cgi?id=29084
- top = window.innerHeight * ( parseFloat(styleTop) / 100 );
- } else if( (styleTop).indexOf('px') >= 0 && ! isNaN(parseFloat(styleTop)) ) {
- top = parseFloat(style.top);
- }
-
- headerStart += top + transformY;
- headerEnd += top + transformY;
- }
-
- // Reset the header status
- for( var headerClass in this._headers ) {
- if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
- // from == '' signals that the section is inactive
- this._headers[ headerClass ].from = '';
- this._headers[ headerClass ].progress = 0.0;
- }
-
- // Set the header status
- for( var ix = 0; ix < this._sections.length; ix++ ) {
-
- // Todo: This isn't exactly the best code.
-
- // If there's some kind of overlap between the header and a section, that class becomes active
- if( headerEnd >= this._sections[ix].start && headerStart <= this._sections[ix].end ) {
-
- this._headers[ this._sections[ix].className ].visible = true;
-
- // If the header sits neatly within the section, this is the only active class
- if( headerStart >= this._sections[ix].start && headerEnd <= this._sections[ix].end ) {
- this._headers[ this._sections[ix].className ].from = 'top';
- this._headers[ this._sections[ix].className ].progress += 1.0;
- }
- // If the header is in the middle of the end of a section, it comes from the top
- else if( headerEnd > this._sections[ix].end && headerStart < this._sections[ix].end ) {
- this._headers[ this._sections[ix].className ].from = 'top';
- this._headers[ this._sections[ix].className ].progress = 1.0 - (headerEnd - this._sections[ix].end) / headerHeight;
- }
- // If the header is in the middle of the start of a section, it comes from the bottom
- else if( headerEnd > this._sections[ix].start && headerStart < this._sections[ix].start ) {
- // If the same color continues in the next section, just add the progress to it so we don't switch
- if( this._headers[ this._sections[ix].className ].from === 'top' ) {
- this._headers[ this._sections[ix].className ].progress += (headerEnd - this._sections[ix].start) / headerHeight;
+ (function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){var t=0,i=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var s,n,a=i.call(arguments,1),o=0,r=a.length;r>o;o++)for(s in a[o])n=a[o][s],a[o].hasOwnProperty(s)&&void 0!==n&&(t[s]=e.isPlainObject(n)?e.isPlainObject(t[s])?e.widget.extend({},t[s],n):e.widget.extend({},n):n);return t},e.widget.bridge=function(t,s){var n=s.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=i.call(arguments,1),h=this;return a=!o&&r.length?e.widget.extend.apply(null,[a].concat(r)):a,o?this.each(function(){var i,s=e.data(this,n);return"instance"===a?(h=s,!1):s?e.isFunction(s[a])&&"_"!==a.charAt(0)?(i=s[a].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var t=e.data(this,n);t?(t.option(a||{}),t._init&&t._init()):e.data(this,n,new s(a,this))}),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"",options:{disabled:!1,create:null},_createWidget:function(i,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=t++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget});
+
+ ((function ( $ ) {
+
+ "use strict";
+
+ $.widget('aerolab.midnight', {
+
+ options: {
+ // The class that wraps each header. Used as a clipping mask.
+ headerClass: 'midnightHeader',
+ // The class that wraps the contents of each header. Also used as a clipping mask.
+ innerClass: 'midnightInner',
+ // The class used by the default header (useful when adding multiple headers with different markup).
+ defaultClass: 'default',
+ // Unused: Add a prefix to the header classes (so if you set the "thingy-" prefix, a section with data-midnight="butterfly" will use the "thingy-butterfly" header)
+ classPrefix: '',
+ // If you want to use plugin more than once or if you want a different data attribute name (so if you set the "header" in a section use data-header)
+ sectionSelector: 'midnight',
+ // Define `Y` or `X` axis to use the effect vertically(Y) or horizontally(X)
+ axis: 'Y'
+ },
+
+ // Cache all the switchable headers (different colors)
+ _headers: {},
+ _headerInfo: {top:0, height:0, left:0, width:0},
+
+ // Cache all the sections which cause the header to change colors
+ _$sections: [],
+ _sections: [],
+
+ // Scroll Cache
+ _scrollTop: 0,
+ _documentHeight: 0,
+ _scrollLeft: 0,
+ _documentWidth: 0,
+
+ // Tools
+ _transformMode: false,
+
+
+ refresh: function() {
+
+ this._headerInfo = {
+ // Todo: Add support for top (though it's mostly unnecessary)
+ top: 0,
+ height: this.element.outerHeight(),
+ left: 0,
+ width: this.element.outerWidth(),
+ };
+
+ // Sections that affect the color of the header (and cache)
+ this._$sections = $('[data-'+ this.options.sectionSelector +']:not(:hidden)');
+ this._sections = [];
+
+ this._setupHeaders();
+
+ this.recalculate();
+
+ },
+
+ _create: function() {
+
+ var context = this;
+ this._scrollTop = window.pageYOffset || document.documentElement.scrollTop;
+ this._scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
+ this._documentHeight = $(document).height();
+ this._documentWidth = $(document).width();
+ this._headers = {};
+
+ this._transformMode = this._getSupportedTransform();
+
+ // Calculate all sections and create the necessary headers
+ this.refresh();
+
+
+ // NANANANANANANANA GRASAAAAA
+ // (This is the ghetto way of keeping the section values updated after any kind of reflow. The overhead is minimal)
+ setInterval(function(){
+ context._recalculateSections();
+ }, 1000);
+
+
+ // We need to recalculate all this._sections and headers
+ context.recalculate();
+
+
+ // and at every resize
+ $(window).resize(function(){
+ context.recalculate();
+ });
+
+
+ // Start the RequestAnimationFrame loop. This should be done just once.
+ this._updateHeadersLoop();
+
+ },
+
+
+ recalculate: function() {
+ this._recalculateSections();
+ this._updateHeaderHeight();
+
+ this._recalculateHeaders();
+ this._updateHeaders();
+ },
+
+
+ /**
+ * This is to offer the optimal transform format when updating the header
+ */
+ _getSupportedTransform: function() {
+ var prefixes = ['transform','WebkitTransform','MozTransform','OTransform','msTransform'];
+ for(var ix = 0; ix < prefixes.length; ix++) {
+ if(document.createElement('div').style[prefixes[ix]] !== undefined) {
+ return prefixes[ix];
+ }
+ }
+ return false;
+ },
+
+
+ /**
+ * Get the size of the header.
+ */
+ _getContainerDimension: function(){
+ var $customHeaders = this.element.find('> .'+this.options['headerClass']);
+ var max = 0;
+ var origin = 0;
+ var context = this;
+
+ if( $customHeaders.length ) {
+ $customHeaders.each(function() {
+
+ var $header = $(this);
+ var $inner = $header.find('> .'+context.options['innerClass']);
+
+ // Disable the fixed height and trigger a reflow to get the proper height
+ // Get the inner height or just the height of the container
+ if( $inner.length ) {
+ // Overflow: Auto fixes an issue with Chrome 41, where outerHeight() no longer takes into account
+ // the margins of internal elements, creating a smaller container than necessary
+
+ if(context.options.axis === 'Y') {
+ $inner.css('bottom', 'auto').css('overflow', 'auto');
+ origin = $inner.outerHeight();
+ $inner.css('bottom', '0');
+ } else {
+ $inner.css('right', 'auto').css('overflow', 'auto');
+ origin = $inner.outerWidth();
+ $inner.css('right', '0');
+ }
+ } else {
+ if(context.options.axis === 'Y') {
+ $header.css('bottom', 'auto');
+ origin = $header.outerHeight();
+ $header.css('bottom', '0');
+ } else {
+ $header.css('right', 'auto');
+ origin = $header.outerWidth();
+ $header.css('right', '0');
}
- else {
- this._headers[ this._sections[ix].className ].from = 'bottom';
- this._headers[ this._sections[ix].className ].progress = (headerEnd - this._sections[ix].start) / headerHeight;
- }
- }
-
- }
-
- }
-
- },
-
-
- /**
- * Update the headers based on the position of each section
- */
- _updateHeaders: function(){
-
- // Don't do anything if there are no headers
- if( typeof this._headers[ this.options['defaultClass'] ] === 'undefined' ){ return; }
-
- // Do some preprocessing to ensure a header is always shown (even if some this._sections haven't been assigned)
- var totalProgress = 0.0;
- var lastActiveClass = '';
- for( var headerClass in this._headers ) {
- if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
- if( ! this._headers[headerClass].from === '' ){ continue; }
- totalProgress += this._headers[headerClass].progress;
- lastActiveClass = headerClass;
- }
-
- if( totalProgress < 1.0 ) {
- // Complete the header at the bottom with the default class
- if( this._headers[ this.options['defaultClass'] ].from === '' ) {
- this._headers[ this.options['defaultClass'] ].from = ( this._headers[lastActiveClass].from === 'top' ) ? 'bottom' : 'top';
- this._headers[ this.options['defaultClass'] ].progress = 1.0 - totalProgress;
- }
- else {
- this._headers[ this.options['defaultClass'] ].progress += 1.0 - totalProgress;
- }
- }
-
-
- for( var ix in this._headers ) {
- if( ! this._headers.hasOwnProperty(ix) ){ continue; }
- if( ! this._headers[ix].from === '' ){ continue; }
-
- var offset = (1.0 - this._headers[ix].progress) * 100.0;
-
- // Add an extra offset when an area is hidden to prevent clipping/rounding issues.
- if( offset >= 100.0 ) { offset = 110.0; }
- if( offset <= -100.0 ) { offset = -110.0; }
-
- if( this._headers[ix].from === 'top' ){
- if( this._transformMode !== false ) {
- this._headers[ix].element[0].style[this._transformMode] = 'translateY(-'+ offset +'%) translateZ(0)';
- this._headers[ix].inner[0].style[this._transformMode] = 'translateY(+'+ offset +'%) translateZ(0)';
- } else {
- this._headers[ix].element[0].style['top'] = '-'+ offset +'%';
- this._headers[ix].inner[0].style['top'] = '+'+ offset +'%';
- }
- }
- else {
- if( this._transformMode !== false ) {
- this._headers[ix].element[0].style[this._transformMode] = 'translateY(+'+ offset +'%) translateZ(0)';
- this._headers[ix].inner[0].style[this._transformMode] = 'translateY(-'+ offset +'%) translateZ(0)';
- } else {
- this._headers[ix].element[0].style['top'] = '+'+ offset +'%';
- this._headers[ix].inner[0].style['top'] = '-'+ offset +'%';
- }
- }
-
- }
-
- },
-
-
- /**
- * Update the size of all the sections.
- * This doesn't look for new sections. It only updates the ones that were around when the plugin was started.
- * Use .midnight('refresh') to do a full update.
- */
- _recalculateSections: function(){
-
- this._documentHeight = $(document).height();
-
- // Cache all the this._sections and their start/end positions (where the class starts and ends)
- this._sections = [];
-
- for( var ix=0; ix
max) ? origin : max;
+ });
+ } else {
+ max = origin = (this.options.axis === 'Y' ? this.element.outerHeight() : this.element.outerWidth());
+ }
+ return max;
+ },
+
+
+ _setupHeaders: function(){
+
+ // Get all the different header colors
+ var context = this;
+ this._headers[this.options['defaultClass']] = {};
+
+ for( var i=0; i .'+this.options['headerClass']);
+ if( $customHeaders.length ) {
+ if( ! $customHeaders.filter('.'+ this.options['defaultClass']).length ) {
+ // If there's no default header, just pick the first one, duplicate it, and set the correct class
+ $customHeaders.filter('.'+ this.options['headerClass'] +':first').clone(true, true).attr('class', this.options['headerClass'] +' '+ this.options['defaultClass']);
+ }
+ } else {
+ // If there are no custom headers, just wrap the content and make that the default header
+
+ this.element.wrapInner('');
+ }
+
+ // Make a copy of the default header for use in the generic ones.
+ var $customHeaders = this.element.find('> .'+ this.options['headerClass']);
+ var $defaultHeader = $customHeaders.filter('.'+ this.options['defaultClass']).clone(true, true);
+
+
+
+ for( var headerClass in this._headers ) {
+ if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
+ if( typeof this._headers[headerClass].element === 'undefined' ) {
+
+ // Create the outer clipping mask
+ // If there's some custom markup, use it, or else just clone the default header
+ var $existingHeader = $customHeaders.filter('.'+headerClass);
+ if( $existingHeader.length ) {
+ this._headers[headerClass].element = $existingHeader;
+ } else {
+ this._headers[headerClass].element = $defaultHeader.clone(true, true).removeClass( this.options['defaultClass'] ).addClass(headerClass).appendTo( this.element );
+ }
+
+ var resetStyles = {
+ position: 'absolute',
+ overflow: 'hidden',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0
+ };
+ this._headers[headerClass].element.css(resetStyles);
+
+ if( this._transformMode !== false ) {
+ this._headers[headerClass].element.css(this._transformMode, 'translateZ(0)');
+ }
+
+ // Create the inner clipping mask
+ if( ! this._headers[headerClass].element.find('> .'+ this.options['innerClass']).length ) {
+ this._headers[headerClass].element.wrapInner('');
+ }
+ this._headers[headerClass].inner = this._headers[headerClass].element.find('> .'+ this.options['innerClass'])
+ this._headers[headerClass].inner.css(resetStyles);
+
+ if( this._transformMode !== false ) {
+ this._headers[headerClass].inner.css(this._transformMode, 'translateZ(0)');
+ }
+
+ // Set the default clipping variables
+ this._headers[headerClass].from = '';
+ this._headers[headerClass].progress = 0.0;
+ }
+ }
+
+
+ // Headers that weren't initialized have to be hidden
+ $customHeaders.each(function(){
+ var $header = $(this);
+ var hasAnyClass = false;
+ for( var headerClass in context._headers ) {
+ if( ! context._headers.hasOwnProperty(headerClass) ){ continue; }
+ if( $header.hasClass(headerClass) ){ hasAnyClass = true; }
+ }
+
+ // Add the inner clipping mask just in case
+ if( ! $header.find('> .'+ context.options['innerClass']).length ) {
+ $header.wrapInner('');
+ }
+
+ if( hasAnyClass ) {
+ $header.show();
+ } else {
+ $header.hide();
+ }
+ });
+
+ },
+
+
+ /**
+ * Recalculate which headers should be visible at this time based on the scroll position and the (cached) position of each section.
+ * This doesn't update
+ */
+ _recalculateHeaders: function(){
+
+ // Check classes are currently active in the header (including the current percentage of each)
+ this._scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
+ this._scrollLeft = window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft;
+ // Some browsers (e.g on OS X) allow scrolling past the top/bottom.
+ this._scrollTop = Math.max(this._scrollTop, 0);
+ this._scrollTop = Math.min(this._scrollTop, this._documentHeight);
+
+ this._scrollLeft = Math.max(this._scrollLeft, 0);
+ this._scrollLeft = Math.min(this._scrollLeft, this._documentWidth);
+
+ // Get the header's position relative to the document (given that it's fixed)
+ var headerHeight = this._headerInfo.height;
+ var headerStart = this._scrollTop + this._headerInfo.top;
+ var headerEnd = headerStart + headerHeight;
+
+ // For horizontal scroll
+ var headerWidth = this._headerInfo.width;
+ if(this.options.axis === 'X') {
+ headerStart = this._scrollLeft + this._headerInfo.left;
+ headerEnd = headerStart + headerWidth;
+ }
+
+ // Add support for transforms (for plugins like Headroom or general css stuff)
+ if( typeof window.getComputedStyle === 'function' ) {
+ var style = window.getComputedStyle(this.element[0], null);
+
+ var styleOrigin = 0;
+ var origin = 0.0;
+ var transformAxis = 0.0;
+ if (this.options.axis === 'Y') {
+ styleOrigin = style.top;
+ } else {
+ styleOrigin = style.left;
+ }
+
+ if( this._transformMode !== false && typeof style.transform === 'string' ) {
+ // Convert the transform matrix to an array
+ var transformArray = (style.transform).match(/(-?[0-9\.]+)/g);
+ if( transformArray !== null && transformArray.length >= 6 && ! isNaN(parseFloat(transformArray[5])) ) {
+ transformAxis = parseFloat(transformArray[5]);
+ }
+ }
+ if ( style.top.indexOf('%') >= 0 && ! isNaN(parseFloat(styleOrigin)) ) {
+ // SAFARI ISSUE https://bugs.webkit.org/show_bug.cgi?id=29084
+ origin = (this.options.axis === 'Y' ? window.innerHeight : window.innerWidth) * ( parseFloat(styleOrigin) / 100 );
+ } else if( (styleOrigin).indexOf('px') >= 0 && ! isNaN(parseFloat(styleOrigin)) ) {
+ origin = parseFloat((this.options.axis === 'Y' ? style.top : style.left));
+ }
+
+ headerStart += origin + transformAxis;
+ headerEnd += origin + transformAxis;
+ }
+
+ // Reset the header status
+ for( var headerClass in this._headers ) {
+ if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
+ // from == '' signals that the section is inactive
+ this._headers[ headerClass ].from = '';
+ this._headers[ headerClass ].progress = 0.0;
+ }
+
+ // Set the header status
+ for( var ix = 0; ix < this._sections.length; ix++ ) {
+
+ // Todo: This isn't exactly the best code.
+
+ // If there's some kind of overlap between the header and a section, that class becomes active
+ if( headerEnd >= this._sections[ix].start && headerStart <= this._sections[ix].end ) {
+
+ this._headers[ this._sections[ix].className ].visible = true;
+
+ // If the header sits neatly within the section, this is the only active class
+ if( headerStart >= this._sections[ix].start && headerEnd <= this._sections[ix].end ) {
+ this._headers[ this._sections[ix].className ].from = (this.options.axis === 'Y' ? 'top' : 'left');
+ this._headers[ this._sections[ix].className ].progress += 1.0;
+ }
+ // If the header is in the middle of the end of a section, it comes from the top
+ else if( headerEnd > this._sections[ix].end && headerStart < this._sections[ix].end ) {
+ this._headers[ this._sections[ix].className ].from = (this.options.axis === 'Y' ? 'top' : 'left');
+ this._headers[ this._sections[ix].className ].progress = 1.0 - (headerEnd - this._sections[ix].end) / (this.options.axis === 'Y' ? headerHeight : headerWidth);
+ }
+ // If the header is in the middle of the start of a section, it comes from the bottom
+ else if( headerEnd > this._sections[ix].start && headerStart < this._sections[ix].start ) {
+ // If the same color continues in the next section, just add the progress to it so we don't switch
+ if( this._headers[ this._sections[ix].className ].from === (this.options.axis === 'Y' ? 'top' : 'left') ) {
+ this._headers[ this._sections[ix].className ].progress += (headerEnd - this._sections[ix].start) / (this.options.axis === 'Y' ? headerHeight : headerWidth);
+ }
+ else {
+ this._headers[ this._sections[ix].className ].from = (this.options.axis === 'Y' ? 'bottom' : 'right');
+ this._headers[ this._sections[ix].className ].progress = (headerEnd - this._sections[ix].start) / (this.options.axis === 'Y' ? headerHeight : headerWidth);
+ }
+ }
+
+ }
+
+ }
+
+ },
+
+
+ /**
+ * Update the headers based on the position of each section
+ */
+ _updateHeaders: function(){
+
+ // Don't do anything if there are no headers
+ if( typeof this._headers[ this.options['defaultClass'] ] === 'undefined' ){ return; }
+
+ // Do some preprocessing to ensure a header is always shown (even if some this._sections haven't been assigned)
+ var totalProgress = 0.0;
+ var lastActiveClass = '';
+ for( var headerClass in this._headers ) {
+ if( ! this._headers.hasOwnProperty(headerClass) ){ continue; }
+ if( ! this._headers[headerClass].from === '' ){ continue; }
+ totalProgress += this._headers[headerClass].progress;
+ lastActiveClass = headerClass;
+ }
+
+ if( totalProgress < 1.0 ) {
+ // Complete the header at the bottom with the default class
+ if( this._headers[ this.options['defaultClass'] ].from === '' ) {
+ var from = ( this._headers[lastActiveClass].from === 'top' ) ? 'bottom' : 'top';
+ if (this.options.axis === 'X') {
+ from = ( this._headers[lastActiveClass].from === 'left' ) ? 'right' : 'left';
+ }
+ this._headers[ this.options['defaultClass'] ].from = from;
+ this._headers[ this.options['defaultClass'] ].progress = 1.0 - totalProgress;
+ }
+ else {
+ this._headers[ this.options['defaultClass'] ].progress += 1.0 - totalProgress;
+ }
+ }
+
+
+ for( var ix in this._headers ) {
+ if( ! this._headers.hasOwnProperty(ix) ){ continue; }
+ if( ! this._headers[ix].from === '' ){ continue; }
+
+ var offset = (1.0 - this._headers[ix].progress) * 100.0;
+
+ // Add an extra offset when an area is hidden to prevent clipping/rounding issues.
+ if( offset >= 100.0 ) { offset = 110.0; }
+ if( offset <= -100.0 ) { offset = -110.0; }
+
+ var fromStyle = (this.options.axis === 'Y' ? 'top' : 'left');
+
+ if( this._headers[ix].from === fromStyle ){
+ if( this._transformMode !== false ) {
+ this._headers[ix].element[0].style[this._transformMode] = 'translate' + this.options.axis + '(-'+ offset +'%) translateZ(0)';
+ this._headers[ix].inner[0].style[this._transformMode] = 'translate' + this.options.axis + '(+'+ offset +'%) translateZ(0)';
+ } else {
+ this._headers[ix].element[0].style[fromStyle] = '-'+ offset +'%';
+ this._headers[ix].inner[0].style[fromStyle] = '+'+ offset +'%';
+ }
+ }
+ else {
+ if( this._transformMode !== false ) {
+ this._headers[ix].element[0].style[this._transformMode] = 'translate' + this.options.axis + '(+'+ offset +'%) translateZ(0)';
+ this._headers[ix].inner[0].style[this._transformMode] = 'translate' + this.options.axis + '(-'+ offset +'%) translateZ(0)';
+ } else {
+ this._headers[ix].element[0].style[fromStyle] = '+'+ offset +'%';
+ this._headers[ix].inner[0].style[fromStyle] = '-'+ offset +'%';
+ }
+ }
+
+ }
+
+ },
+
+
+ /**
+ * Update the size of all the sections.
+ * This doesn't look for new sections. It only updates the ones that were around when the plugin was started.
+ * Use .midnight('refresh') to do a full update.
+ */
+ _recalculateSections: function(){
+
+ this._documentHeight = $(document).height();
+ this._documentWidth = $(document).width();
+
+ // Cache all the this._sections and their start/end positions (where the class starts and ends)
+ this._sections = [];
+
+ for( var ix=0; ixr;r++)for(i in o[r])n=o[r][i],o[r].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var r="string"==typeof o,a=s.call(arguments,1),h=this;return o=!r&&a.length?t.widget.extend.apply(null,[o].concat(a)):o,r?this.each(function(){var s,i=t.data(this,n);return"instance"===o?(h=i,!1):i?t.isFunction(i[o])&&"_"!==o.charAt(0)?(s=i[o].apply(i,a),s!==i&&void 0!==s?(h=s&&s.jquery?h.pushStack(s.get()):s,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; attempted to call method '"+o+"'")}):this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))}),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"",options:{disabled:!1,create:null},_createWidget:function(s,i){i=t(i||this.defaultElement||this)[0],this.element=t(i),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),i!==this&&(t.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===i&&this.destroy()}}),this.document=t(i.style?i.ownerDocument:i.document||i),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),s),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(e,s){var i,n,o,r=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(r={},i=e.split("."),e=i.shift(),i.length){for(n=r[e]=t.widget.extend({},this.options[e]),o=0;i.length-1>o;o++)n[i[o]]=n[i[o]]||{},n=n[i[o]];if(e=i.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=s}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];r[e]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(e,s,i){var n,o=this;"boolean"!=typeof e&&(i=s,s=e,e=!1),i?(s=n=t(s),this.bindings=this.bindings.add(s)):(i=s,s=this.element,n=this.widget()),t.each(i,function(i,r){function a(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?o[r]:r).apply(o,arguments):void 0}"string"!=typeof r&&(a.guid=r.guid=r.guid||a.guid||t.guid++);var h=i.match(/^([\w:-]*)\s*(.*)$/),d=h[1]+o.eventNamespace,l=h[2];l?n.delegate(l,d,a):s.bind(d,a)})},_off:function(e,s){s=(s||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(s).undelegate(s),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function s(){return("string"==typeof t?i[t]:t).apply(i,arguments)}var i=this;return setTimeout(s,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,s,i){var n,o,r=this.options[e];if(i=i||{},s=t.Event(s),s.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),s.target=this.element[0],o=s.originalEvent)for(n in o)n in s||(s[n]=o[n]);return this.element.trigger(s,i),!(t.isFunction(r)&&r.apply(this.element[0],[s].concat(i))===!1||s.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,s){t.Widget.prototype["_"+e]=function(i,n,o){"string"==typeof n&&(n={effect:n});var r,a=n?n===!0||"number"==typeof n?s:n.effect||s:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=o,n.delay&&i.delay(n.delay),r&&t.effects&&t.effects.effect[a]?i[e](n):a!==e&&i[a]?i[a](n.duration,n.easing,o):i.queue(function(s){t(this)[e](),o&&o.call(i[0]),s()})}}),t.widget}),function(t){"use strict";t.widget("aerolab.midnight",{options:{headerClass:"midnightHeader",innerClass:"midnightInner",defaultClass:"default",classPrefix:"",sectionSelector:"midnight"},_headers:{},_headerInfo:{top:0,height:0},_$sections:[],_sections:[],_scrollTop:0,_documentHeight:0,_transformMode:!1,refresh:function(){this._headerInfo={top:0,height:this.element.outerHeight()},this._$sections=t("[data-"+this.options.sectionSelector+"]:not(:hidden)"),this._sections=[],this._setupHeaders(),this.recalculate()},_create:function(){var e=this;this._scrollTop=window.pageYOffset||document.documentElement.scrollTop,this._documentHeight=t(document).height(),this._headers={},this._transformMode=this._getSupportedTransform(),this.refresh(),setInterval(function(){e._recalculateSections()},1e3),e.recalculate(),t(window).resize(function(){e.recalculate()}),this._updateHeadersLoop()},recalculate:function(){this._recalculateSections(),this._updateHeaderHeight(),this._recalculateHeaders(),this._updateHeaders()},_getSupportedTransform:function(){for(var t=["transform","WebkitTransform","MozTransform","OTransform","msTransform"],e=0;e
."+this.options.headerClass),s=0,i=0,n=this;return e.length?e.each(function(){var e=t(this),o=e.find("> ."+n.options.innerClass);o.length?(o.css("bottom","auto").css("overflow","auto"),i=o.outerHeight(),o.css("bottom","0")):(e.css("bottom","auto"),i=e.outerHeight(),e.css("bottom","0")),s=i>s?i:s}):s=i=this.element.outerHeight(),s},_setupHeaders:function(){var e=this;this._headers[this.options.defaultClass]={};for(var s=0;s ."+this.options.headerClass);o.length?o.filter("."+this.options.defaultClass).length||o.filter("."+this.options.headerClass+":first").clone(!0,!0).attr("class",this.options.headerClass+" "+this.options.defaultClass):this.element.wrapInner('');var o=this.element.find("> ."+this.options.headerClass),r=o.filter("."+this.options.defaultClass).clone(!0,!0);for(var n in this._headers)if(this._headers.hasOwnProperty(n)&&"undefined"==typeof this._headers[n].element){var a=o.filter("."+n);a.length?this._headers[n].element=a:this._headers[n].element=r.clone(!0,!0).removeClass(this.options.defaultClass).addClass(n).appendTo(this.element);var h={position:"absolute",overflow:"hidden",top:0,left:0,right:0,bottom:0};this._headers[n].element.css(h),this._transformMode!==!1&&this._headers[n].element.css(this._transformMode,"translateZ(0)"),this._headers[n].element.find("> ."+this.options.innerClass).length||this._headers[n].element.wrapInner(''),this._headers[n].inner=this._headers[n].element.find("> ."+this.options.innerClass),this._headers[n].inner.css(h),this._transformMode!==!1&&this._headers[n].inner.css(this._transformMode,"translateZ(0)"),this._headers[n].from="",this._headers[n].progress=0}o.each(function(){var s=t(this),i=!1;for(var n in e._headers)e._headers.hasOwnProperty(n)&&s.hasClass(n)&&(i=!0);s.find("> ."+e.options.innerClass).length||s.wrapInner(''),i?s.show():s.hide()})},_recalculateHeaders:function(){this._scrollTop=window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop,this._scrollTop=Math.max(this._scrollTop,0),this._scrollTop=Math.min(this._scrollTop,this._documentHeight);var t=this._headerInfo.height,e=this._scrollTop+this._headerInfo.top,s=e+t;if("function"==typeof window.getComputedStyle){var i=window.getComputedStyle(this.element[0],null),n=0,o=0;if(this._transformMode!==!1&&"string"==typeof i.transform){var r=i.transform.match(/(-?[0-9\.]+)/g);null!==r&&r.length>=6&&!isNaN(parseFloat(r[5]))&&(o=parseFloat(r[5]))}i.top.indexOf("px")>=0&&!isNaN(parseFloat(i.top))&&(n=parseFloat(i.top)),e+=n+o,s+=n+o}for(var a in this._headers)this._headers.hasOwnProperty(a)&&(this._headers[a].from="",this._headers[a].progress=0);for(var h=0;h=this._sections[h].start&&e<=this._sections[h].end&&(this._headers[this._sections[h].className].visible=!0,e>=this._sections[h].start&&s<=this._sections[h].end?(this._headers[this._sections[h].className].from="top",this._headers[this._sections[h].className].progress+=1):s>this._sections[h].end&ðis._sections[h].start&&e=100&&(n=110),n<=-100&&(n=-110),"top"===this._headers[i].from?this._transformMode!==!1?(this._headers[i].element[0].style[this._transformMode]="translateY(-"+n+"%) translateZ(0)",this._headers[i].inner[0].style[this._transformMode]="translateY(+"+n+"%) translateZ(0)"):(this._headers[i].element[0].style.top="-"+n+"%",this._headers[i].inner[0].style.top="+"+n+"%"):this._transformMode!==!1?(this._headers[i].element[0].style[this._transformMode]="translateY(+"+n+"%) translateZ(0)",this._headers[i].inner[0].style[this._transformMode]="translateY(-"+n+"%) translateZ(0)"):(this._headers[i].element[0].style.top="+"+n+"%",this._headers[i].inner[0].style.top="-"+n+"%")}}},_recalculateSections:function(){this._documentHeight=t(document).height(),this._sections=[];for(var e=0;e",options:{disabled:!1,create:null},_createWidget:function(t,e){e=d(e||this.defaultElement||this)[0],this.element=d(e),this.uuid=s++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=d(),this.hoverable=d(),this.focusable=d(),e!==this&&(d.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=d(e.style?e.ownerDocument:e.document||e),this.window=d(this.document[0].defaultView||this.document[0].parentWindow)),this.options=d.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:d.noop,_getCreateEventData:d.noop,_create:d.noop,_init:d.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(d.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:d.noop,widget:function(){return this.element},option:function(t,e){var s,i,o,n=t;if(0===arguments.length)return d.widget.extend({},this.options);if("string"==typeof t)if(n={},t=(s=t.split(".")).shift(),s.length){for(i=n[t]=d.widget.extend({},this.options[t]),o=0;s.length-1>o;o++)i[s[o]]=i[s[o]]||{},i=i[s[o]];if(t=s.pop(),1===arguments.length)return void 0===i[t]?null:i[t];i[t]=e}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];n[t]=e}return this._setOptions(n),this},_setOptions:function(t){for(var e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!e),e&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(o,n,t){var r,a=this;"boolean"!=typeof o&&(t=n,n=o,o=!1),t?(n=r=d(n),this.bindings=this.bindings.add(n)):(t=n,n=this.element,r=this.widget()),d.each(t,function(t,e){function s(){return o||!0!==a.options.disabled&&!d(this).hasClass("ui-state-disabled")?("string"==typeof e?a[e]:e).apply(a,arguments):void 0}"string"!=typeof e&&(s.guid=e.guid=e.guid||s.guid||d.guid++);var t=t.match(/^([\w:-]*)\s*(.*)$/),i=t[1]+a.eventNamespace,t=t[2];t?r.delegate(t,i,s):n.bind(i,s)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e),this.bindings=d(this.bindings.not(t).get()),this.focusable=d(this.focusable.not(t).get()),this.hoverable=d(this.hoverable.not(t).get())},_delay:function(t,e){var s=this;return setTimeout(function(){return("string"==typeof t?s[t]:t).apply(s,arguments)},e||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){d(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){d(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){d(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){d(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,e,s){var i,o,n=this.options[t];if(s=s||{},(e=d.Event(e)).type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),e.target=this.element[0],o=e.originalEvent)for(i in o)i in e||(e[i]=o[i]);return this.element.trigger(e,s),!(d.isFunction(n)&&!1===n.apply(this.element[0],[e].concat(s))||e.isDefaultPrevented())}},d.each({show:"fadeIn",hide:"fadeOut"},function(n,r){d.Widget.prototype["_"+n]=function(e,t,s){var i=(t="string"==typeof t?{effect:t}:t)?!0!==t&&"number"!=typeof t&&t.effect||r:n,o=!d.isEmptyObject(t="number"==typeof(t=t||{})?{duration:t}:t);t.complete=s,t.delay&&e.delay(t.delay),o&&d.effects&&d.effects.effect[i]?e[n](t):i!==n&&e[i]?e[i](t.duration,t.easing,s):e.queue(function(t){d(this)[n](),s&&s.call(e[0]),t()})}}),d.widget}),function(r){"use strict";r.widget("aerolab.midnight",{options:{headerClass:"midnightHeader",innerClass:"midnightInner",defaultClass:"default",classPrefix:"",sectionSelector:"midnight",axis:"Y"},_headers:{},_headerInfo:{top:0,height:0,left:0,width:0},_$sections:[],_sections:[],_scrollTop:0,_documentHeight:0,_scrollLeft:0,_documentWidth:0,_transformMode:!1,refresh:function(){this._headerInfo={top:0,height:this.element.outerHeight(),left:0,width:this.element.outerWidth()},this._$sections=r("[data-"+this.options.sectionSelector+"]:not(:hidden)"),this._sections=[],this._setupHeaders(),this.recalculate()},_create:function(){var t=this;this._scrollTop=window.pageYOffset||document.documentElement.scrollTop,this._scrollLeft=window.pageXOffset||document.documentElement.scrollLeft,this._documentHeight=r(document).height(),this._documentWidth=r(document).width(),this._headers={},this._transformMode=this._getSupportedTransform(),this.refresh(),setInterval(function(){t._recalculateSections()},1e3),t.recalculate(),r(window).resize(function(){t.recalculate()}),this._updateHeadersLoop()},recalculate:function(){this._recalculateSections(),this._updateHeaderHeight(),this._recalculateHeaders(),this._updateHeaders()},_getSupportedTransform:function(){for(var t=["transform","WebkitTransform","MozTransform","OTransform","msTransform"],e=0;e ."+this.options.headerClass),s=0,i=0,o=this;return t.length?t.each(function(){var t=r(this),e=t.find("> ."+o.options.innerClass);e.length?"Y"===o.options.axis?(e.css("bottom","auto").css("overflow","auto"),i=e.outerHeight(),e.css("bottom","0")):(e.css("right","auto").css("overflow","auto"),i=e.outerWidth(),e.css("right","0")):"Y"===o.options.axis?(t.css("bottom","auto"),i=t.outerHeight(),t.css("bottom","0")):(t.css("right","auto"),i=t.outerWidth(),t.css("right","0")),s=s ."+this.options.headerClass);e.length?e.filter("."+this.options.defaultClass).length||e.filter("."+this.options.headerClass+":first").clone(!0,!0).attr("class",this.options.headerClass+" "+this.options.defaultClass):this.element.wrapInner('');var s,o,n=(e=this.element.find("> ."+this.options.headerClass)).filter("."+this.options.defaultClass).clone(!0,!0);for(s in this._headers)this._headers.hasOwnProperty(s)&&void 0===this._headers[s].element&&((o=e.filter("."+s)).length?this._headers[s].element=o:this._headers[s].element=n.clone(!0,!0).removeClass(this.options.defaultClass).addClass(s).appendTo(this.element),this._headers[s].element.css(o={position:"absolute",overflow:"hidden",top:0,left:0,right:0,bottom:0}),!1!==this._transformMode&&this._headers[s].element.css(this._transformMode,"translateZ(0)"),this._headers[s].element.find("> ."+this.options.innerClass).length||this._headers[s].element.wrapInner(''),this._headers[s].inner=this._headers[s].element.find("> ."+this.options.innerClass),this._headers[s].inner.css(o),!1!==this._transformMode&&this._headers[s].inner.css(this._transformMode,"translateZ(0)"),this._headers[s].from="",this._headers[s].progress=0);e.each(function(){var t,e=r(this),s=!1;for(t in i._headers)i._headers.hasOwnProperty(t)&&e.hasClass(t)&&(s=!0);e.find("> ."+i.options.innerClass).length||e.wrapInner(''),s?e.show():e.hide()})},_recalculateHeaders:function(){this._scrollTop=window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop,this._scrollLeft=window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft,this._scrollTop=Math.max(this._scrollTop,0),this._scrollTop=Math.min(this._scrollTop,this._documentHeight),this._scrollLeft=Math.max(this._scrollLeft,0),this._scrollLeft=Math.min(this._scrollLeft,this._documentWidth);var t,e,s,i,o,n,r=this._headerInfo.height,a=this._scrollTop+this._headerInfo.top,h=a+r,d=this._headerInfo.width;for(n in"X"===this.options.axis&&(h=(a=this._scrollLeft+this._headerInfo.left)+d),"function"==typeof window.getComputedStyle&&(t=window.getComputedStyle(this.element[0],null),s=e=o=0,o="Y"===this.options.axis?t.top:t.left,!1!==this._transformMode&&"string"==typeof t.transform&&null!==(i=t.transform.match(/(-?[0-9\.]+)/g))&&6<=i.length&&!isNaN(parseFloat(i[5]))&&(s=parseFloat(i[5])),0<=t.top.indexOf("%")&&!isNaN(parseFloat(o))?e=("Y"===this.options.axis?window.innerHeight:window.innerWidth)*(parseFloat(o)/100):0<=o.indexOf("px")&&!isNaN(parseFloat(o))&&(e=parseFloat("Y"===this.options.axis?t.top:t.left)),a+=e+s,h+=e+s),this._headers)this._headers.hasOwnProperty(n)&&(this._headers[n].from="",this._headers[n].progress=0);for(var l=0;l=this._sections[l].start&&a<=this._sections[l].end&&(this._headers[this._sections[l].className].visible=!0,a>=this._sections[l].start&&h<=this._sections[l].end?(this._headers[this._sections[l].className].from="Y"===this.options.axis?"top":"left",this._headers[this._sections[l].className].progress+=1):h>this._sections[l].end&&athis._sections[l].start&&a