diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index 18b0674..15186eb 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -1,4 +1,2 @@ - - diff --git a/static/src/js/alpha/jquery.dropotron.min.js b/static/src/js/alpha/jquery.dropotron.min.js new file mode 100755 index 0000000..b992170 --- /dev/null +++ b/static/src/js/alpha/jquery.dropotron.min.js @@ -0,0 +1,2 @@ +/* jquery.dropotron.js v1.4.3 | (c) @ajlkn | github.com/ajlkn/jquery.dropotron | MIT licensed */ +!function(e){e.fn.disableSelection_dropotron=function(){return e(this).css("user-select","none").css("-khtml-user-select","none").css("-moz-user-select","none").css("-o-user-select","none").css("-webkit-user-select","none")},e.fn.dropotron=function(t){if(0==this.length)return e(this);if(this.length>1)for(var o=0;o0&&t.add(n).on("mouseleave",function(e){window.clearTimeout(c),c=window.setTimeout(function(){t.trigger("doCollapse")},o.hideDelay)}),t.disableSelection_dropotron().hide().addClass(o.menuClass).css("position","absolute").on("mouseenter",function(e){window.clearTimeout(c)}).on("doExpand",function(){if(t.is(":visible"))return!1;window.clearTimeout(c),s.each(function(){var t=e(this);e.contains(t.get(0),n.get(0))||t.trigger("doCollapse")});var i,a,d,f,u=n.offset(),p=n.position(),h=(n.parent().position(),n.outerWidth()),g=t.outerWidth(),v=t.css("z-index")==o.baseZIndex;if(v){switch(i=o.detach?u:p,f=i.top+n.outerHeight()+o.globalOffsetY,a=o.alignment,t.removeClass("left").removeClass("right").removeClass("center"),o.alignment){case"right":d=i.left-g+h,0>d&&(d=i.left,a="left");break;case"center":d=i.left-Math.floor((g-h)/2),0>d?(d=i.left,a="left"):d+g>l.width()&&(d=i.left-g+h,a="right");break;case"left":default:d=i.left,d+g>l.width()&&(d=i.left-g+h,a="right")}t.addClass(a)}else switch("relative"==n.css("position")||"absolute"==n.css("position")?(f=o.offsetY,d=-1*p.left):(f=p.top+o.offsetY,d=0),o.alignment){case"right":d+=-1*n.parent().outerWidth()+o.offsetX;break;case"center":case"left":default:d+=n.parent().outerWidth()+o.offsetX}navigator.userAgent.match(/MSIE ([0-9]+)\./)&&RegExp.$1<8&&(d+=o.IEOffsetX,f+=o.IEOffsetY),t.css("left",d+"px").css("top",f+"px").css("opacity","0.01").show();var C=!1;switch(d="relative"==n.css("position")||"absolute"==n.css("position")?-1*p.left:0,t.offset().left<0?(d+=n.parent().outerWidth()-o.offsetX,C=!0):t.offset().left+g>l.width()&&(d+=-1*n.parent().outerWidth()-o.offsetX,C=!0),C&&t.css("left",d+"px"),t.hide().css("opacity","1"),o.mode){case"zoom":r=!0,n.addClass(o.openerActiveClass),t.animate({width:"toggle",height:"toggle"},o.speed,o.easing,function(){r=!1});break;case"slide":r=!0,n.addClass(o.openerActiveClass),t.animate({height:"toggle"},o.speed,o.easing,function(){r=!1});break;case"fade":if(r=!0,v&&!o.noOpenerFade){var C;C="slow"==o.speed?80:"fast"==o.speed?40:Math.floor(o.speed/2),n.fadeTo(C,.01,function(){n.addClass(o.openerActiveClass),n.fadeTo(o.speed,1),t.fadeIn(o.speed,function(){r=!1})})}else n.addClass(o.openerActiveClass),n.fadeTo(o.speed,1),t.fadeIn(o.speed,function(){r=!1});break;case"instant":default:n.addClass(o.openerActiveClass),t.show()}return!1}).on("doCollapse",function(){return t.is(":visible")?(t.hide(),n.removeClass(o.openerActiveClass),t.find("."+o.openerActiveClass).removeClass(o.openerActiveClass),t.find("ul").hide(),!1):!1}).on("doToggle",function(e){return t.is(":visible")?t.trigger("doCollapse"):t.trigger("doExpand"),!1}),n.disableSelection_dropotron().addClass("opener").css("cursor","pointer").on("click touchend",function(e){r||(e.preventDefault(),e.stopPropagation(),t.trigger("doToggle"))}),"hover"==o.expandMode&&n.hover(function(e){r||(d=window.setTimeout(function(){t.trigger("doExpand")},o.hoverDelay))},function(e){window.clearTimeout(d)})}),s.find("a").css("display","block").on("click touchend",function(t){r||e(this).attr("href").length<1&&t.preventDefault()}),n.find("li").css("white-space","nowrap").each(function(){var t=e(this),o=t.children("a"),s=t.children("ul"),i=o.attr("href");o.on("click touchend",function(e){0==i.length||"#"==i?e.preventDefault():e.stopPropagation()}),o.length>0&&0==s.length&&t.on("click touchend",function(e){r||(n.trigger("doCollapseAll"),e.stopPropagation())})}),n.children("li").each(function(){var t,n=e(this),s=n.children("ul");if(s.length>0){o.detach&&(o.cloneOnDetach&&(t=s.clone(),t.attr("class","").hide().appendTo(s.parent())),s.detach().appendTo(i));for(var a=o.baseZIndex,l=1,r=s;r.length>0;l++)r.css("z-index",a++),o.submenuClassPrefix&&r.addClass(o.submenuClassPrefix+(a-1-o.baseZIndex)),r=r.find("> li > ul")}}),l.on("scroll",function(){n.trigger("doCollapseAll")}).on("keypress",function(e){r||27!=e.keyCode||(e.preventDefault(),n.trigger("doCollapseAll"))}),a.on("click touchend",function(){r||n.trigger("doCollapseAll")})}}(jQuery); diff --git a/static/src/js/alpha.js b/static/src/js/alpha/main.js similarity index 100% rename from static/src/js/alpha.js rename to static/src/js/alpha/main.js diff --git a/static/src/js/alpha/util.js b/static/src/js/alpha/util.js new file mode 100755 index 0000000..ea71e4c --- /dev/null +++ b/static/src/js/alpha/util.js @@ -0,0 +1,281 @@ +/** +* Generate an indented list of links from a nav. Meant for use with panel(). +* @return {jQuery} jQuery object. +*/ + +'use strict'; + +$.fn.navList = function() { + var $a = $(this).find('a'); + var b = []; + + $a.each(function() { + var $this = $(this), + indent = Math.max(0, $this.parents('li').length - 1), + href = $this.attr('href'), + target = $this.attr('target'); + + b.push( + '' + + '' + + $this.text() + + '' + ); + }); + + return b.join(''); +}; + +/** +* Panel-ify an element. +* @param {object} userConfig User config. +* @return {jQuery} jQuery object. +*/ +$.fn.panel = function(userConfig) { + var $this = $(this); + + // No elements? + if (this.length === 0) { + return $this; + } + + // Multiple elements? + if (this.length > 1) { + for (var i = 0; i < this.length; i++) { + $(this[i]).panel(userConfig); + } + return $this; + } + + // Vars. + var $this = $(this), + $body = $('body'), + $window = $(window), + id = $this.attr('id'), + config; + + config = $.extend({ + delay: 0, + hideOnClick: false, + hideOnEscape: false, + hideOnSwipe: false, + resetScroll: false, + resetForms: false, + side: null, + target: $this, + visibleClass: 'visible' + }, userConfig); + + if (typeof config.target !== 'jQuery') { + config.target = $(config.target); + } + + $this._hide = function(event) { + if (!config.target.hasClass(config.visibleClass)) { + return; + } + + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + + config.target.removeClass(config.visibleClass); + + window.setTimeout(function() { + if (config.resetScroll) { + $this.scrollTop(0); + } + if (config.resetForms) { + $this.find('form').each(function() { + this.reset(); + }); + } + + }, config.delay); + + }; + + // Vendor fixes. + $this + .css('-ms-overflow-style', '-ms-autohiding-scrollbar') + .css('-webkit-overflow-scrolling', 'touch'); + + if (config.hideOnClick) { + $this.find('a').css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)'); + + $this.on('click', 'a', function(event) { + + var $a = $(this), + href = $a.attr('href'), + target = $a.attr('target'); + + if (!href || href === '#' || href === '' || href === '#' + id) { + return; + } + + // Cancel original event. + event.preventDefault(); + event.stopPropagation(); + + // Hide panel. + $this._hide(); + + // Redirect to href. + window.setTimeout(function() { + if (target === '_blank') { + window.open(href); + } else { + window.location.href = href; + } + }, config.delay + 10); + }); + } + + $this.on('touchstart', function(event) { + $this.touchPosX = event.originalEvent.touches[0].pageX; + $this.touchPosY = event.originalEvent.touches[0].pageY; + }); + + $this.on('touchmove', function(event) { + if ($this.touchPosX === null || $this.touchPosY === null) { + return; + } + + var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX, + diffY = $this.touchPosY - event.originalEvent.touches[0].pageY, + th = $this.outerHeight(), + ts = ($this.get(0).scrollHeight - $this.scrollTop()); + + // Hide on swipe? + if (config.hideOnSwipe) { + var result = false, + boundary = 20, + delta = 50; + + switch (config.side) { + case 'left': + result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta); + break; + + case 'right': + result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta)); + break; + + case 'top': + result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta); + break; + + case 'bottom': + result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta)); + break; + + default: + break; + } + + if (result) { + $this.touchPosX = null; + $this.touchPosY = null; + $this._hide(); + + return false; + } + } + + if (($this.scrollTop() < 0 && diffY < 0) || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) { + event.preventDefault(); + event.stopPropagation(); + } + }); + + $this.on('click touchend touchstart touchmove', function(event) { + event.stopPropagation(); + }); + + // Event: Hide panel if a child anchor tag pointing to its ID is clicked. + $this.on('click', 'a[href="#' + id + '"]', function(event) { + event.preventDefault(); + event.stopPropagation(); + config.target.removeClass(config.visibleClass); + }); + + $body.on('click touchend', function(event) { + $this._hide(event); + }); + + $body.on('click', 'a[href="#' + id + '"]', function(event) { + event.preventDefault(); + event.stopPropagation(); + config.target.toggleClass(config.visibleClass); + }); + if (config.hideOnEscape) { + $window.on('keydown', function(event) { + if (event.keyCode === 27) { + $this._hide(event); + } + }); + } + return $this; +}; +/** +* Moves elements to/from the first positions of their respective parents. +* @param {jQuery} $elements Elements (or selector) to move. +* @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations. +*/ +$.prioritize = function($elements, condition) { + var key = '__prioritize'; + + // Expand $elements if it's not already a jQuery object. + if (typeof $elements !== 'jQuery') { + $elements = $($elements); + } + + $elements.each(function() { + var $e = $(this), + $p, + $parent = $e.parent(); + + // No parent? Bail. + if ($parent.length === 0) { + return; + } + + if (!$e.data(key)) { + // Condition is false? Bail. + if (!condition) { + return; + } + + // Get placeholder (which will serve as our point of reference for when this element needs to move back). + $p = $e.prev(); + + // Couldn't find anything? Means this element's already at the top, so bail. + if ($p.length === 0) { + return; + } + + // Move element to top of parent. + $e.prependTo($parent); + + // Mark element as moved. + $e.data(key, $p); + } else { + if (condition) { + return; + } + + $p = $e.data(key); + + // Move element back to its original location (using our placeholder). + $e.insertAfter($p); + + // Unmark element as moved. + $e.removeData(key); + } + }); +}; diff --git a/static/src/js/index.js b/static/src/js/index.js index 882ca72..940a35f 100644 --- a/static/src/js/index.js +++ b/static/src/js/index.js @@ -4,7 +4,9 @@ require('./jquery-global'); require('bootstrap'); // Install alpha things -require('./alpha'); +require('./alpha/jquery.dropotron.min'); +require('./alpha/util'); +require('./alpha/main'); $('.image').each(function () { // setup div-image hybrids