From 625ca795e74794d6bec16c2f9141dd33dc32f2d5 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Christensen Date: Tue, 26 Mar 2013 11:46:43 -0700 Subject: [PATCH 1/9] Minify javascript --- jquery.pin.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jquery.pin.min.js b/jquery.pin.min.js index efc9dd1..327a09c 100644 --- a/jquery.pin.min.js +++ b/jquery.pin.min.js @@ -1 +1 @@ -(function(e){"use strict";e.fn.pin=function(t){var n=0,r=[],i=!1;t=t||{};var s=function(){for(var n=0,s=r.length;n"),o.data("pin",{from:t.containerSelector?f.top:a.top,to:f.top+u.height()-o.outerHeight(),end:f.top+u.height(),parentTop:l.top}),o.css({width:o.outerWidth()}),o.parent().css("height",o.outerHeight())}},o=function(){if(i)return;n=window.scrollY;for(var t=0,s=r.length;tu.end){o.css("position","");continue}an?o.css("position")!="fixed"&&o.css({left:o.offset().left,top:0}).css("position","fixed"):n>=f?o.css({left:"auto",top:f-u.parentTop}).css("position","absolute"):o.css({position:"",top:"",left:""})}},u=function(){s(),o()};return this.each(function(){var t=e(this),n=e(this).data("pin")||{};if(n&&n.update)return;r.push(t),e("img",this).one("load",s),n.update=u,e(this).data("pin",n)}),e(window).scroll(o),e(window).resize(function(){s()}),s(),e(window).load(u),this}})(jQuery); \ No newline at end of file +(function(e){"use strict";e.fn.pin=function(t){var n=0,r=[],i=!1,s=e(window);t=t||{};var o=function(){for(var n=0,o=r.length;n"),u.data("pin",{from:t.containerSelector?l.top:f.top,to:l.top+a.height()-u.outerHeight(),end:l.top+a.height(),parentTop:c.top}),u.css({width:u.outerWidth()}),u.parent().css("height",u.outerHeight())}},u=function(){if(i)return;n=s.scrollTop();for(var t=0,o=r.length;ta.end){u.css("position","");continue}fn?u.css("position")!="fixed"&&u.css({left:u.offset().left,top:0}).css("position","fixed"):n>=l?u.css({left:"auto",top:l-a.parentTop}).css("position","absolute"):u.css({position:"",top:"",left:""})}},a=function(){o(),u()};return this.each(function(){var t=e(this),n=e(this).data("pin")||{};if(n&&n.update)return;r.push(t),e("img",this).one("load",o),n.update=a,e(this).data("pin",n)}),s.scroll(u),s.resize(function(){o()}),o(),s.load(a),this}})(jQuery); \ No newline at end of file From e7b0ca6c7b9d7bb2722ceaca8576d42ca46bcf3d Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Christensen Date: Sat, 30 Mar 2013 23:58:47 -0700 Subject: [PATCH 2/9] Added jQuery registry manifest --- pin.jquery.json | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 pin.jquery.json diff --git a/pin.jquery.json b/pin.jquery.json new file mode 100644 index 0000000..237a504 --- /dev/null +++ b/pin.jquery.json @@ -0,0 +1,35 @@ +{ + "name": "pin", + "title": "jQuery Pin", + "description": "jQuery plugin for pinning an element within a container.", + "keywords": [ + "scroll", + "stick", + "sticky" + ], + "version": "1.0.1", + "author": { + "name": "Webpop", + "url": "http://www.webpop.com" + }, + "maintainers": [ + { + "name": "Mathias Biilmann Christensen", + "url": "http://mathias-biilmann.net" + "email": "info@mathias-biilmann.net" + } + ], + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/jquery/jquery-color/blob/2.1.2/MIT-LICENSE.txt" + } + ], + "bugs": "https://github.com/webpop/jquery.pin/issues", + "homepage": "webpop.github.com/jquery.pin", + "docs": "webpop.github.com/jquery.pin", + "download": "https://raw.github.com/webpop/jquery.pin/gh-pages/jquery.pin.js", + "dependencies": { + "jquery": ">=1.5" + } +} \ No newline at end of file From f512012fb2648e681e337921fc2c5b354819bbde Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Christensen Date: Sun, 31 Mar 2013 00:02:29 -0700 Subject: [PATCH 3/9] Fix manifest typo --- pin.jquery.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pin.jquery.json b/pin.jquery.json index 237a504..2590426 100644 --- a/pin.jquery.json +++ b/pin.jquery.json @@ -15,7 +15,7 @@ "maintainers": [ { "name": "Mathias Biilmann Christensen", - "url": "http://mathias-biilmann.net" + "url": "http://mathias-biilmann.net", "email": "info@mathias-biilmann.net" } ], From b23ff792cc5ccb6c6934455b0461df982bfce639 Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 13 Nov 2013 19:10:06 +0100 Subject: [PATCH 4/9] Adds classes pin-absolute pin-fixed, and scrolling when the content is too long Use case is the following: when the pinned content is too high for the window, add overflow:auto so that the user can scroll within that content as well. --- jquery.pin.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jquery.pin.js b/jquery.pin.js index 180452b..ecaee73 100644 --- a/jquery.pin.js +++ b/jquery.pin.js @@ -51,7 +51,7 @@ to = data.to; if (from + $this.outerHeight() > data.end) { - $this.css('position', ''); + $this.css({position: "", top: "", left: "", overflow: "", height: ""}).removeClass('pin-fixed'); continue; } @@ -59,14 +59,14 @@ !($this.css("position") == "fixed") && $this.css({ left: $this.offset().left, top: 0 - }).css("position", "fixed"); + }).css({"position": "fixed", overflow: "auto", height: "100%"}).addClass('pin-fixed').removeClass('pin-absolute'); } else if (scrollY >= to) { $this.css({ left: "auto", top: to - data.parentTop - }).css("position", "absolute"); + }).css({position: "absolute", height: "", overflo: ""}).addClass('pin-absolute').removeClass('pin-fixed'); } else { - $this.css({position: "", top: "", left: ""}); + $this.css({position: "", top: "", left: "", overflow: "", height: ""}); } } }; @@ -92,4 +92,4 @@ return this; }; -})(jQuery); \ No newline at end of file +})(jQuery); From c9bd40f549043862ed449eaae00d32b513f7be3e Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 11 Dec 2013 00:20:16 +0100 Subject: [PATCH 5/9] Adds support for a fixed header. Adds an optional fixedHeaderSelector to the option, allowing to trigger the pin as soon as that header is hit. --- jquery.pin.js | 76 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/jquery.pin.js b/jquery.pin.js index ecaee73..30d8fe6 100644 --- a/jquery.pin.js +++ b/jquery.pin.js @@ -1,7 +1,7 @@ (function ($) { "use strict"; $.fn.pin = function (options) { - var scrollY = 0, elements = [], disabled = false, $window = $(window); + var scrollY = 0, elements = [], disabledPlugin = false, $window = $(window), $fixedHeaderOffset = 0; options = options || {}; @@ -15,67 +15,81 @@ disabled = true; continue; } else { - disabled = false; + disabledPlugin = false; } var $container = options.containerSelector ? $this.closest(options.containerSelector) : $(document.body); + $fixedHeaderOffset = options.fixedHeaderSelector ? $(options.fixedHeaderSelector).outerHeight(true) : 0; var offset = $this.offset(); var containerOffset = $container.offset(); + containerOffset.top -= $fixedHeaderOffset; var parentOffset = $this.offsetParent().offset(); + if (!$this.parent().is(".pin-wrapper")) { $this.wrap("
"); } $this.data("pin", { + enabled: $container.height() >= $this.height()+$fixedHeaderOffset, from: options.containerSelector ? containerOffset.top : offset.top, - to: containerOffset.top + $container.height() - $this.outerHeight(), - end: containerOffset.top + $container.height(), - parentTop: parentOffset.top + to: containerOffset.top + $container.height() - $this.outerHeight() - $fixedHeaderOffset, + end: containerOffset.top + $container.height() - $fixedHeaderOffset, + parentTop: parentOffset.top, + paddingTop: $fixedHeaderOffset, }); - $this.css({width: $this.outerWidth()}); $this.parent().css("height", $this.outerHeight()); } }; var onScroll = function () { - if (disabled) { return; } + if (disabledPlugin) { return; } scrollY = $window.scrollTop(); - + for (var i=0, len=elements.length; i data.end) { - $this.css({position: "", top: "", left: "", overflow: "", height: ""}).removeClass('pin-fixed'); - continue; + data = $this.data("pin"), + enabled = data.enabled, + from = data.from, + to = data.to, + end = data.end, + paddingTop = data.paddingTop; + + if(enabled) + { + if (from + $this.outerHeight() + $fixedHeaderOffset > end) { + $this.css({position: "", top: "", left: "", overflowY: "", height: ""}).removeClass('pin-fixed pin-absolute pin-top'); + continue; + } + + if (from < scrollY && to > scrollY) { + !($this.css("position") == "fixed") && $this.css({ + left: $this.offset().left, + top: 0 + }).css({"position": "fixed", overflowY: "auto", height: "100%", paddingTop: paddingTop}).addClass('pin-fixed').removeClass('pin-absolute pin-top'); + } else if (scrollY >= to) { + $this.css({ + left: "auto", + top: to - data.parentTop + }).css({position: "absolute", height: "", overflowY: "", paddingTop: paddingTop}).addClass('pin-absolute').removeClass('pin-fixed pin-top'); + } else { + $this.css({position: "", top: "", left: "", overflowY: "", height: "", paddingTop: 0}).removeClass('pin-fixed pin-absolute').addClass('pin-top'); + } } - - if (from < scrollY && to > scrollY) { - !($this.css("position") == "fixed") && $this.css({ - left: $this.offset().left, - top: 0 - }).css({"position": "fixed", overflow: "auto", height: "100%"}).addClass('pin-fixed').removeClass('pin-absolute'); - } else if (scrollY >= to) { - $this.css({ - left: "auto", - top: to - data.parentTop - }).css({position: "absolute", height: "", overflo: ""}).addClass('pin-absolute').removeClass('pin-fixed'); - } else { - $this.css({position: "", top: "", left: "", overflow: "", height: ""}); + else + { + $this.css('paddingTop', 0); } - } + } }; var update = function () { recalculateLimits(); onScroll(); }; this.each(function () { var $this = $(this), - data = $(this).data('pin') || {}; + data = $(this).data('pin') || {}; if (data && data.update) { return; } elements.push($this); @@ -91,5 +105,5 @@ $window.load(update); return this; - }; + }; })(jQuery); From 80d1da92f9e788bf1edc28d5ad7f680894753971 Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 11 Dec 2013 00:27:25 +0100 Subject: [PATCH 6/9] adds support for fixed header --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 65afee3..62f2997 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,12 @@ Include jquery and jquery pin at the bottom of your html. Then pin any element y $(".pinned").pin() -To make a pinned element stay within an outer container, use the containerSelector option: +To make a pinned element stay within an outer container, use the containerSelector option. If you use a fixed header on your page and want the pin to be triggered as soon as your element hits it, use the fixedHeaderSelector option: - $(".pinned").pin({containerSelector: ".container"}) + $(".pinned").pin({ + containerSelector: ".container", + fixedHeaderSelector: "header" + }) That's it - go pin all the things! @@ -29,4 +32,4 @@ Redistribution and use in source and binary forms, with or without modification, Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From d5b353307040db676ea3379eb73042236972f619 Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 11 Dec 2013 00:41:36 +0100 Subject: [PATCH 7/9] fixes end trigger --- README.md | 116 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 62f2997..93f9d67 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,109 @@ -## jQuery.pin +(function ($) { + "use strict"; + $.fn.pin = function (options) { + var scrollY = 0, elements = [], disabledPlugin = false, $window = $(window), $fixedHeaderOffset = 0; -Ever wanted to **pin** something to the side of a text? Ever needed a subtle sticky element to quietly hang around as you scroll down? + options = options || {}; -**Jquery.Pin** is here to help! Pin any element to the top of a container. Easily **disable** it for smaller screen-sizes where there's no room for that kind of shenanigans. + var recalculateLimits = function () { + for (var i=0, len=elements.length; i"); + } - $(".pinned").pin({ - containerSelector: ".container", - fixedHeaderSelector: "header" - }) + $this.data("pin", { + enabled: $container.height() >= $this.height()+$fixedHeaderOffset, + from: options.containerSelector ? containerOffset.top : offset.top, + to: containerOffset.top + $container.height() - $this.outerHeight() - $fixedHeaderOffset, + end: containerOffset.top + $container.height() + $fixedHeaderOffset, + parentTop: parentOffset.top, + paddingTop: $fixedHeaderOffset, + }); + $this.css({width: $this.outerWidth()}); + $this.parent().css("height", $this.outerHeight()); + } + }; -That's it - go pin all the things! + var onScroll = function () { + if (disabledPlugin) { return; } -## Examples + scrollY = $window.scrollTop(); -Plenty of examples [Here](http://webpop.github.com/jquery.pin/). + for (var i=0, len=elements.length; i end) { + $this.css({position: "", top: "", left: "", overflowY: "", height: ""}).removeClass('pin-fixed pin-absolute pin-top'); + continue; + } -Copyright (c) 2013, Mathias Biilmann -All rights reserved. + if (from < scrollY && to > scrollY) { + !($this.css("position") == "fixed") && $this.css({ + left: $this.offset().left, + top: 0 + }).css({"position": "fixed", overflowY: "auto", height: "100%", paddingTop: paddingTop}).addClass('pin-fixed').removeClass('pin-absolute pin-top'); + } else if (scrollY >= to) { + $this.css({ + left: "auto", + top: to - data.parentTop + }).css({position: "absolute", height: "", overflowY: "", paddingTop: paddingTop}).addClass('pin-absolute').removeClass('pin-fixed pin-top'); + } else { + $this.css({position: "", top: "", left: "", overflowY: "", height: "", paddingTop: 0}).removeClass('pin-fixed pin-absolute').addClass('pin-top'); + } + } + else + { + $this.css('paddingTop', 0); + } + } + }; -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + var update = function () { recalculateLimits(); onScroll(); }; -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + this.each(function () { + var $this = $(this), + data = $(this).data('pin') || {}; + + if (data && data.update) { return; } + elements.push($this); + $("img", this).one("load", recalculateLimits); + data.update = update; + $(this).data('pin', data); + }); + + $window.scroll(onScroll); + $window.resize(function () { recalculateLimits(); }); + recalculateLimits(); + + $window.load(update); + + return this; + }; +})(jQuery); From 2100b294b8a9a5ace2112a1d18a1cf0c832dfc0a Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 11 Dec 2013 00:43:29 +0100 Subject: [PATCH 8/9] fixes end trigger --- jquery.pin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jquery.pin.js b/jquery.pin.js index 30d8fe6..93f9d67 100644 --- a/jquery.pin.js +++ b/jquery.pin.js @@ -34,7 +34,7 @@ enabled: $container.height() >= $this.height()+$fixedHeaderOffset, from: options.containerSelector ? containerOffset.top : offset.top, to: containerOffset.top + $container.height() - $this.outerHeight() - $fixedHeaderOffset, - end: containerOffset.top + $container.height() - $fixedHeaderOffset, + end: containerOffset.top + $container.height() + $fixedHeaderOffset, parentTop: parentOffset.top, paddingTop: $fixedHeaderOffset, }); From 9ad4cdf7ffdf7c190cad98e02004fe27a0bdc6e3 Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 11 Dec 2013 00:44:32 +0100 Subject: [PATCH 9/9] Corrects README again sorry, i was working directly via github.com, don't know how to cancel a commit here.. :/ --- README.md | 116 ++++++++++-------------------------------------------- 1 file changed, 21 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 93f9d67..62f2997 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,35 @@ -(function ($) { - "use strict"; - $.fn.pin = function (options) { - var scrollY = 0, elements = [], disabledPlugin = false, $window = $(window), $fixedHeaderOffset = 0; +## jQuery.pin - options = options || {}; +Ever wanted to **pin** something to the side of a text? Ever needed a subtle sticky element to quietly hang around as you scroll down? - var recalculateLimits = function () { - for (var i=0, len=elements.length; i"); - } +To make a pinned element stay within an outer container, use the containerSelector option. If you use a fixed header on your page and want the pin to be triggered as soon as your element hits it, use the fixedHeaderSelector option: - $this.data("pin", { - enabled: $container.height() >= $this.height()+$fixedHeaderOffset, - from: options.containerSelector ? containerOffset.top : offset.top, - to: containerOffset.top + $container.height() - $this.outerHeight() - $fixedHeaderOffset, - end: containerOffset.top + $container.height() + $fixedHeaderOffset, - parentTop: parentOffset.top, - paddingTop: $fixedHeaderOffset, - }); - $this.css({width: $this.outerWidth()}); - $this.parent().css("height", $this.outerHeight()); - } - }; + $(".pinned").pin({ + containerSelector: ".container", + fixedHeaderSelector: "header" + }) - var onScroll = function () { - if (disabledPlugin) { return; } +That's it - go pin all the things! - scrollY = $window.scrollTop(); +## Examples - for (var i=0, len=elements.length; i end) { - $this.css({position: "", top: "", left: "", overflowY: "", height: ""}).removeClass('pin-fixed pin-absolute pin-top'); - continue; - } +## License - if (from < scrollY && to > scrollY) { - !($this.css("position") == "fixed") && $this.css({ - left: $this.offset().left, - top: 0 - }).css({"position": "fixed", overflowY: "auto", height: "100%", paddingTop: paddingTop}).addClass('pin-fixed').removeClass('pin-absolute pin-top'); - } else if (scrollY >= to) { - $this.css({ - left: "auto", - top: to - data.parentTop - }).css({position: "absolute", height: "", overflowY: "", paddingTop: paddingTop}).addClass('pin-absolute').removeClass('pin-fixed pin-top'); - } else { - $this.css({position: "", top: "", left: "", overflowY: "", height: "", paddingTop: 0}).removeClass('pin-fixed pin-absolute').addClass('pin-top'); - } - } - else - { - $this.css('paddingTop', 0); - } - } - }; +Copyright (c) 2013, Mathias Biilmann +All rights reserved. - var update = function () { recalculateLimits(); onScroll(); }; +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - this.each(function () { - var $this = $(this), - data = $(this).data('pin') || {}; - - if (data && data.update) { return; } - elements.push($this); - $("img", this).one("load", recalculateLimits); - data.update = update; - $(this).data('pin', data); - }); - - $window.scroll(onScroll); - $window.resize(function () { recalculateLimits(); }); - recalculateLimits(); - - $window.load(update); - - return this; - }; -})(jQuery); +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.