aboutsummaryrefslogtreecommitdiffstats
path: root/uikit/static/js/components/parallax.js
diff options
context:
space:
mode:
authorValentin Heinz <inktrap@users.noreply.github.com>2017-04-08 14:03:25 +0200
committerAlexis Metaireau <alexis@notmyidea.org>2017-04-08 14:03:25 +0200
commit5c231ceade17e7f5b1bba90e845dd2d17e54da1c (patch)
treef4f07dbbac2c51c8a0af1e1a24f11e030a2e4155 /uikit/static/js/components/parallax.js
parent00986ab80df4b6be2d1306671907e2b2378e487f (diff)
downloadpelican-themes-5c231ceade17e7f5b1bba90e845dd2d17e54da1c.tar.gz
uikit demo theme ported to pelican (#385)
Diffstat (limited to 'uikit/static/js/components/parallax.js')
-rw-r--r--uikit/static/js/components/parallax.js417
1 files changed, 417 insertions, 0 deletions
diff --git a/uikit/static/js/components/parallax.js b/uikit/static/js/components/parallax.js
new file mode 100644
index 0000000..3175027
--- /dev/null
+++ b/uikit/static/js/components/parallax.js
@@ -0,0 +1,417 @@
+/*! UIkit 2.21.0 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */
+(function(addon) {
+
+ var component;
+
+ if (window.UIkit) {
+ component = addon(UIkit);
+ }
+
+ if (typeof define == "function" && define.amd) {
+ define("uikit-parallax", ["uikit"], function(){
+ return component || addon(UIkit);
+ });
+ }
+
+})(function(UI){
+
+ "use strict";
+
+ var parallaxes = [],
+ supports3d = false,
+ scrolltop = 0,
+ wh = window.innerHeight,
+ checkParallaxes = function() {
+
+ scrolltop = UI.$win.scrollTop();
+
+ window.requestAnimationFrame.apply(window, [function(){
+ for (var i=0; i < parallaxes.length; i++) {
+ parallaxes[i].process();
+ }
+ }]);
+ };
+
+
+ UI.component('parallax', {
+
+ defaults: {
+ velocity : 0.5,
+ target : false,
+ viewport : false,
+ media : false
+ },
+
+ boot: function() {
+
+ supports3d = (function(){
+
+ var el = document.createElement('div'),
+ has3d,
+ transforms = {
+ 'WebkitTransform':'-webkit-transform',
+ 'MSTransform':'-ms-transform',
+ 'MozTransform':'-moz-transform',
+ 'Transform':'transform'
+ };
+
+ // Add it to the body to get the computed style.
+ document.body.insertBefore(el, null);
+
+ for (var t in transforms) {
+ if (el.style[t] !== undefined) {
+ el.style[t] = "translate3d(1px,1px,1px)";
+ has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
+ }
+ }
+
+ document.body.removeChild(el);
+
+ return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
+ })();
+
+ // listen to scroll and resize
+ UI.$doc.on("scrolling.uk.document", checkParallaxes);
+ UI.$win.on("load resize orientationchange", UI.Utils.debounce(function(){
+ wh = window.innerHeight;
+ checkParallaxes();
+ }, 50));
+
+ // init code
+ UI.ready(function(context) {
+
+ UI.$('[data-uk-parallax]', context).each(function() {
+
+ var parallax = UI.$(this);
+
+ if (!parallax.data("parallax")) {
+ var obj = UI.parallax(parallax, UI.Utils.options(parallax.attr("data-uk-parallax")));
+ }
+ });
+ });
+ },
+
+ init: function() {
+
+ this.base = this.options.target ? UI.$(this.options.target) : this.element;
+ this.props = {};
+ this.velocity = (this.options.velocity || 1);
+
+ var reserved = ['target','velocity','viewport','plugins','media'];
+
+ Object.keys(this.options).forEach(function(prop){
+
+ if (reserved.indexOf(prop) !== -1) {
+ return;
+ }
+
+ var start, end, dir, diff, startend = String(this.options[prop]).split(',');
+
+ if (prop.match(/color/i)) {
+ start = startend[1] ? startend[0] : this._getStartValue(prop),
+ end = startend[1] ? startend[1] : startend[0];
+
+ if (!start) {
+ start = 'rgba(255,255,255,0)';
+ }
+
+ } else {
+ start = parseFloat(startend[1] ? startend[0] : this._getStartValue(prop)),
+ end = parseFloat(startend[1] ? startend[1] : startend[0]);
+ diff = (start < end ? (end-start):(start-end));
+ dir = (start < end ? 1:-1);
+ }
+
+ this.props[prop] = { 'start': start, 'end': end, 'dir': dir, 'diff': diff };
+
+ }.bind(this));
+
+ parallaxes.push(this);
+ },
+
+ process: function() {
+
+ if (this.options.media) {
+
+ switch(typeof(this.options.media)) {
+ case 'number':
+ if (window.innerWidth < this.options.media) {
+ return false;
+ }
+ break;
+ case 'string':
+ if (window.matchMedia && !window.matchMedia(this.options.media).matches) {
+ return false;
+ }
+ break;
+ }
+ }
+
+ var percent = this.percentageInViewport();
+
+ if (this.options.viewport !== false) {
+ percent = (this.options.viewport === 0) ? 1 : percent / this.options.viewport;
+ }
+
+ this.update(percent);
+ },
+
+ percentageInViewport: function() {
+
+ var top = this.base.offset().top,
+ height = this.base.outerHeight(),
+ distance, percentage, percent;
+
+ if (top > (scrolltop + wh)) {
+ percent = 0;
+ } else if ((top + height) < scrolltop) {
+ percent = 1;
+ } else {
+
+ if ((top + height) < wh) {
+
+ percent = (scrolltop < wh ? scrolltop : scrolltop - wh) / (top+height);
+
+ } else {
+
+ distance = (scrolltop + wh) - top;
+ percentage = Math.round(distance / ((wh + height) / 100));
+ percent = percentage/100;
+ }
+ }
+
+ return percent;
+ },
+
+ update: function(percent) {
+
+ var css = {'transform':''},
+ compercent = percent * (1 - (this.velocity - (this.velocity * percent))),
+ opts, val;
+
+ if (compercent < 0) compercent = 0;
+ if (compercent > 1) compercent = 1;
+
+ if (this._percent !== undefined && this._percent == compercent) {
+ return;
+ }
+
+ Object.keys(this.props).forEach(function(prop) {
+
+ opts = this.props[prop];
+
+ if (percent === 0) {
+ val = opts.start;
+ } else if(percent === 1) {
+ val = opts.end;
+ } else if(opts.diff !== undefined) {
+ val = opts.start + (opts.diff * compercent * opts.dir);
+ }
+
+ if ((prop == 'bg' || prop == 'bgp') && !this._bgcover) {
+ this._bgcover = initBgImageParallax(this, prop, opts);
+ }
+
+ switch(prop) {
+
+ // transforms
+ case "x":
+ css.transform += supports3d ? ' translate3d('+val+'px, 0, 0)':' translateX('+val+'px)';
+ break;
+ case "xp":
+ css.transform += supports3d ? ' translate3d('+val+'%, 0, 0)':' translateX('+val+'%)';
+ break;
+ case "y":
+ css.transform += supports3d ? ' translate3d(0, '+val+'px, 0)':' translateY('+val+'px)';
+ break;
+ case "yp":
+ css.transform += supports3d ? ' translate3d(0, '+val+'%, 0)':' translateY('+val+'%)';
+ break;
+ case "rotate":
+ css.transform += ' rotate('+val+'deg)';
+ break;
+ case "scale":
+ css.transform += ' scale('+val+')';
+ break;
+
+ // bg image
+ case "bg":
+ css['background-position'] = '50% '+val+'px';
+ break;
+ case "bgp":
+ css['background-position'] = '50% '+val+'%';
+ break;
+
+ // color
+ case "color":
+ case "background-color":
+ case "border-color":
+ css[prop] = calcColor(opts.start, opts.end, compercent);
+ break;
+
+ default:
+ css[prop] = val;
+ break;
+ }
+
+ }.bind(this));
+
+ this.element.css(css);
+
+ this._percent = compercent;
+ },
+
+ _getStartValue: function(prop) {
+
+ var value = 0;
+
+ switch(prop) {
+ case 'scale':
+ value = 1;
+ break;
+ default:
+ value = this.element.css(prop);
+ }
+
+ return (value || 0);
+ }
+
+ });
+
+
+ // helper
+
+ function initBgImageParallax(obj, prop, opts) {
+
+ var img = new Image(), url, loaded, element, size, check, ratio, width, height;
+
+ element = obj.element.css({'background-size': 'cover', 'background-repeat': 'no-repeat'});
+ url = element.css('background-image').replace(/^url\(/g, '').replace(/\)$/g, '').replace(/("|')/g, '');
+ check = function() {
+
+ var w = element.width(), h = element.height(), extra = (prop=='bg') ? opts.diff : (opts.diff/100) * h;
+
+ h += extra;
+ w += Math.ceil(extra * ratio);
+
+ // if element height < parent height (gap underneath)
+ if ((w / ratio) < h) {
+ width = Math.ceil(h * ratio);
+ height = h;
+
+ // element width < parent width (gap to right)
+ } else {
+ width = w;
+ height = Math.ceil(w / ratio);
+ }
+
+ obj.element.css({'background-size': (width+'px '+height+'px')});
+ };
+
+ img.onerror = function(){
+ // image url doesn't exist
+ };
+
+ img.onload = function(){
+ size = {w:img.width, height:img.height};
+ ratio = img.width / img.height;
+
+ UI.$win.on("load resize orientationchange", UI.Utils.debounce(function(){
+ check();
+ }, 50));
+
+ check();
+ };
+
+ img.src = url;
+
+ return true;
+ }
+
+
+ // Some named colors to work with, added by Bradley Ayers
+ // From Interface by Stefan Petre
+ // http://interface.eyecon.ro/
+ var colors = {
+ 'black': [0,0,0,1],
+ 'blue': [0,0,255,1],
+ 'brown': [165,42,42,1],
+ 'cyan': [0,255,255,1],
+ 'fuchsia': [255,0,255,1],
+ 'gold': [255,215,0,1],
+ 'green': [0,128,0,1],
+ 'indigo': [75,0,130,1],
+ 'khaki': [240,230,140,1],
+ 'lime': [0,255,0,1],
+ 'magenta': [255,0,255,1],
+ 'maroon': [128,0,0,1],
+ 'navy': [0,0,128,1],
+ 'olive': [128,128,0,1],
+ 'orange': [255,165,0,1],
+ 'pink': [255,192,203,1],
+ 'purple': [128,0,128,1],
+ 'violet': [128,0,128,1],
+ 'red': [255,0,0,1],
+ 'silver': [192,192,192,1],
+ 'white': [255,255,255,1],
+ 'yellow': [255,255,0,1],
+ 'transparent': [255,255,255,0]
+ };
+
+ function calcColor(start, end, pos) {
+
+ start = parseColor(start);
+ end = parseColor(end);
+ pos = pos || 0;
+
+ return calculateColor(start, end, pos);
+ }
+
+ /**!
+ * @preserve Color animation 1.6.0
+ * http://www.bitstorm.org/jquery/color-animation/
+ * Copyright 2011, 2013 Edwin Martin <edwin@bitstorm.org>
+ * Released under the MIT and GPL licenses.
+ */
+
+ // Calculate an in-between color. Returns "#aabbcc"-like string.
+ function calculateColor(begin, end, pos) {
+ var color = 'rgba('
+ + parseInt((begin[0] + pos * (end[0] - begin[0])), 10) + ','
+ + parseInt((begin[1] + pos * (end[1] - begin[1])), 10) + ','
+ + parseInt((begin[2] + pos * (end[2] - begin[2])), 10) + ','
+ + (begin && end ? parseFloat(begin[3] + pos * (end[3] - begin[3])) : 1);
+
+ color += ')';
+ return color;
+ }
+
+ // Parse an CSS-syntax color. Outputs an array [r, g, b]
+ function parseColor(color) {
+
+ var match, quadruplet;
+
+ // Match #aabbcc
+ if (match = /#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/.exec(color)) {
+ quadruplet = [parseInt(match[1], 16), parseInt(match[2], 16), parseInt(match[3], 16), 1];
+
+ // Match #abc
+ } else if (match = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/.exec(color)) {
+ quadruplet = [parseInt(match[1], 16) * 17, parseInt(match[2], 16) * 17, parseInt(match[3], 16) * 17, 1];
+
+ // Match rgb(n, n, n)
+ } else if (match = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) {
+ quadruplet = [parseInt(match[1]), parseInt(match[2]), parseInt(match[3]), 1];
+
+ } else if (match = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9\.]*)\s*\)/.exec(color)) {
+ quadruplet = [parseInt(match[1], 10), parseInt(match[2], 10), parseInt(match[3], 10),parseFloat(match[4])];
+
+ // No browser returns rgb(n%, n%, n%), so little reason to support this format.
+ } else {
+ quadruplet = colors[color] || [255,255,255,0];
+ }
+ return quadruplet;
+ }
+
+ return UI.parallax;
+});