diff options
Diffstat (limited to 'uikit/static/js/components/grid.js')
-rw-r--r-- | uikit/static/js/components/grid.js | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/uikit/static/js/components/grid.js b/uikit/static/js/components/grid.js new file mode 100644 index 0000000..3a7ae7a --- /dev/null +++ b/uikit/static/js/components/grid.js @@ -0,0 +1,524 @@ +/*! 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-grid", ["uikit"], function(){ + return component || addon(UIkit); + }); + } + +})(function(UI){ + + "use strict"; + + UI.component('grid', { + + defaults: { + colwidth : 'auto', + animation : true, + duration : 300, + gutter : 0, + controls : false, + filter : false + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$('[data-uk-grid]', context).each(function(){ + + var ele = UI.$(this); + + if(!ele.data("grid")) { + var plugin = UI.grid(ele, UI.Utils.options(ele.attr('data-uk-grid'))); + } + }); + }); + }, + + init: function() { + + var $this = this, gutter = String(this.options.gutter).trim().split(' '); + + this.gutterv = parseInt(gutter[0], 10); + this.gutterh = parseInt((gutter[1] || gutter[0]), 10); + + // make sure parent element has the right position property + this.element.css({'position': 'relative'}); + + this.controls = null; + + if (this.options.controls) { + + this.controls = UI.$(this.options.controls); + + // filter + this.controls.on('click', '[data-uk-filter]', function(e){ + e.preventDefault(); + $this.filter(UI.$(this).data('ukFilter')); + }); + + // sort + this.controls.on('click', '[data-uk-sort]', function(e){ + e.preventDefault(); + var cmd = UI.$(this).attr('data-uk-sort').split(':'); + $this.sort(cmd[0], cmd[1]); + }); + } + + UI.$win.on('load resize orientationchange', UI.Utils.debounce(function(){ + + if ($this.currentfilter) { + $this.filter($this.currentfilter); + } else { + this.updateLayout(); + } + + }.bind(this), 100)); + + this.on('display.uk.check', function(){ + if ($this.element.is(":visible")) $this.updateLayout(); + }); + + UI.$html.on("changed.uk.dom", function(e) { + $this.updateLayout(); + }); + + if (this.options.filter !== false) { + this.filter(this.options.filter); + } else { + this.updateLayout(); + } + }, + + _prepareElements: function() { + + var children = this.element.children(':not([data-grid-prepared])'), css; + + // exit if no already prepared elements found + if (!children.length) { + return; + } + + css = { + 'position' : 'absolute', + 'box-sizing' : 'border-box', + 'width' : this.options.colwidth == 'auto' ? '' : this.options.colwidth + }; + + if (this.options.gutter) { + + css['padding-left'] = this.gutterh; + css['padding-bottom'] = this.gutterv; + + this.element.css('margin-left', this.gutterh * -1); + } + + children.attr('data-grid-prepared', 'true').css(css); + }, + + updateLayout: function(elements) { + + this._prepareElements(); + + elements = elements || this.element.children(':visible'); + + var $this = this, + children = elements, + maxwidth = this.element.width() + (2*this.gutterh) + 2, + left = 0, + top = 0, + positions = [], + + item, width, height, pos, aX, aY, i, z, max, size; + + this.trigger('beforeupdate.uk.grid', [children]); + + children.each(function(index){ + + size = getElementSize(this); + + item = UI.$(this); + width = size.outerWidth; + height = size.outerHeight; + left = 0; + top = 0; + + for (i=0,max=positions.length;i<max;i++) { + + pos = positions[i]; + + if (left <= pos.aX) { left = pos.aX; } + if (maxwidth < (left + width)) { left = 0; } + if (top <= pos.aY) { top = pos.aY; } + } + + positions.push({ + "ele" : item, + "top" : top, + "left" : left, + "width" : width, + "height" : height, + "aY" : (top + height), + "aX" : (left + width) + }); + }); + + var posPrev, maxHeight = 0; + + // fix top + for (i=0,max=positions.length;i<max;i++) { + + pos = positions[i]; + top = 0; + + for (z=0;z<i;z++) { + + posPrev = positions[z]; + + // (posPrev.left + 1) fixex 1px bug when using % based widths + if (pos.left < posPrev.aX && (posPrev.left +1) < pos.aX) { + top = posPrev.aY; + } + } + + pos.top = top; + pos.aY = top + pos.height; + + maxHeight = Math.max(maxHeight, pos.aY); + } + + maxHeight = maxHeight - this.gutterv; + + if (this.options.animation) { + + this.element.stop().animate({'height': maxHeight}, 100); + + positions.forEach(function(pos){ + pos.ele.stop().animate({"top": pos.top, "left": pos.left, opacity: 1}, this.options.duration); + }.bind(this)); + + } else { + + this.element.css('height', maxHeight); + + positions.forEach(function(pos){ + pos.ele.css({"top": pos.top, "left": pos.left, opacity: 1}); + }.bind(this)); + } + + // make sure to trigger possible scrollpies etc. + setTimeout(function() { + UI.$doc.trigger('scrolling.uk.document'); + }, 2 * this.options.duration * (this.options.animation ? 1:0)); + + this.trigger('afterupdate.uk.grid', [children]); + }, + + filter: function(filter) { + + this.currentfilter = filter; + + filter = filter || []; + + if (typeof(filter) === 'string') { + filter = filter.split(/,/).map(function(item){ return item.trim(); }); + } + + var $this = this, children = this.element.children(), elements = {"visible": [], "hidden": []}, visible, hidden; + + children.each(function(index){ + + var ele = UI.$(this), f = ele.attr('data-uk-filter'), infilter = filter.length ? false : true; + + if (f) { + + f = f.split(/,/).map(function(item){ return item.trim(); }); + + filter.forEach(function(item){ + if (f.indexOf(item) > -1) infilter = true; + }); + } + + elements[infilter ? "visible":"hidden"].push(ele); + }); + + // convert to jQuery collections + elements.hidden = UI.$(elements.hidden).map(function () {return this[0];}); + elements.visible = UI.$(elements.visible).map(function () {return this[0];}); + + elements.hidden.attr('aria-hidden', 'true').filter(':visible').fadeOut(this.options.duration); + elements.visible.attr('aria-hidden', 'false').filter(':hidden').css('opacity', 0).show(); + + $this.updateLayout(elements.visible); + + if (this.controls && this.controls.length) { + this.controls.find('[data-uk-filter]').removeClass('uk-active').filter('[data-uk-filter="'+filter+'"]').addClass('uk-active'); + } + }, + + sort: function(by, order){ + + order = order || 1; + + // covert from string (asc|desc) to number + if (typeof(order) === 'string') { + order = order.toLowerCase() == 'desc' ? -1 : 1; + } + + var elements = this.element.children(); + + elements.sort(function(a, b){ + + a = UI.$(a); + b = UI.$(b); + + return (b.data(by) || '') < (a.data(by) || '') ? order : (order*-1); + + }).appendTo(this.element); + + this.updateLayout(elements.filter(':visible')); + + if (this.controls && this.controls.length) { + this.controls.find('[data-uk-sort]').removeClass('uk-active').filter('[data-uk-sort="'+by+':'+(order == -1 ? 'desc':'asc')+'"]').addClass('uk-active'); + } + } + }); + + + /*! + * getSize v1.2.2 + * measure size of elements + * MIT license + * https://github.com/desandro/get-size + */ + var _getSize = (function(){ + + var prefixes = 'Webkit Moz ms Ms O'.split(' '); + var docElemStyle = document.documentElement.style; + + function getStyleProperty( propName ) { + if ( !propName ) { + return; + } + + // test standard property first + if ( typeof docElemStyle[ propName ] === 'string' ) { + return propName; + } + + // capitalize + propName = propName.charAt(0).toUpperCase() + propName.slice(1); + + // test vendor specific properties + var prefixed; + for ( var i=0, len = prefixes.length; i < len; i++ ) { + prefixed = prefixes[i] + propName; + if ( typeof docElemStyle[ prefixed ] === 'string' ) { + return prefixed; + } + } + } + + // -------------------------- helpers -------------------------- // + + // get a number from a string, not a percentage + function getStyleSize( value ) { + var num = parseFloat( value ); + // not a percent like '100%', and a number + var isValid = value.indexOf('%') === -1 && !isNaN( num ); + return isValid && num; + } + + function noop() {} + + var logError = typeof console === 'undefined' ? noop : function( message ) { + console.error( message ); + }; + + // -------------------------- measurements -------------------------- // + + var measurements = [ + 'paddingLeft', + 'paddingRight', + 'paddingTop', + 'paddingBottom', + 'marginLeft', + 'marginRight', + 'marginTop', + 'marginBottom', + 'borderLeftWidth', + 'borderRightWidth', + 'borderTopWidth', + 'borderBottomWidth' + ]; + + function getZeroSize() { + var size = { + width: 0, + height: 0, + innerWidth: 0, + innerHeight: 0, + outerWidth: 0, + outerHeight: 0 + }; + for ( var i=0, len = measurements.length; i < len; i++ ) { + var measurement = measurements[i]; + size[ measurement ] = 0; + } + return size; + } + + + // -------------------------- setup -------------------------- // + + var isSetup = false; + var getStyle, boxSizingProp, isBoxSizeOuter; + + /** + * setup vars and functions + * do it on initial getSize(), rather than on script load + * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 + */ + function setup() { + // setup once + if ( isSetup ) { + return; + } + isSetup = true; + + var getComputedStyle = window.getComputedStyle; + getStyle = ( function() { + var getStyleFn = getComputedStyle ? + function( elem ) { + return getComputedStyle( elem, null ); + } : + function( elem ) { + return elem.currentStyle; + }; + + return function getStyle( elem ) { + var style = getStyleFn( elem ); + if ( !style ) { + logError( 'Style returned ' + style + + '. Are you running this code in a hidden iframe on Firefox? ' + + 'See http://bit.ly/getsizebug1' ); + } + return style; + }; + })(); + + // -------------------------- box sizing -------------------------- // + + boxSizingProp = getStyleProperty('boxSizing'); + + /** + * WebKit measures the outer-width on style.width on border-box elems + * IE & Firefox measures the inner-width + */ + if ( boxSizingProp ) { + var div = document.createElement('div'); + div.style.width = '200px'; + div.style.padding = '1px 2px 3px 4px'; + div.style.borderStyle = 'solid'; + div.style.borderWidth = '1px 2px 3px 4px'; + div.style[ boxSizingProp ] = 'border-box'; + + var body = document.body || document.documentElement; + body.appendChild( div ); + var style = getStyle( div ); + + isBoxSizeOuter = getStyleSize( style.width ) === 200; + body.removeChild( div ); + } + + } + + // -------------------------- getSize -------------------------- // + + function getSize( elem ) { + setup(); + + // use querySeletor if elem is string + if ( typeof elem === 'string' ) { + elem = document.querySelector( elem ); + } + + // do not proceed on non-objects + if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { + return; + } + + var style = getStyle( elem ); + + // if hidden, everything is 0 + if ( style.display === 'none' ) { + return getZeroSize(); + } + + var size = {}; + size.width = elem.offsetWidth; + size.height = elem.offsetHeight; + + var isBorderBox = size.isBorderBox = !!( boxSizingProp && + style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); + + // get all measurements + for ( var i=0, len = measurements.length; i < len; i++ ) { + var measurement = measurements[i]; + var value = style[ measurement ]; + + var num = parseFloat( value ); + // any 'auto', 'medium' value will be 0 + size[ measurement ] = !isNaN( num ) ? num : 0; + } + + var paddingWidth = size.paddingLeft + size.paddingRight; + var paddingHeight = size.paddingTop + size.paddingBottom; + var marginWidth = size.marginLeft + size.marginRight; + var marginHeight = size.marginTop + size.marginBottom; + var borderWidth = size.borderLeftWidth + size.borderRightWidth; + var borderHeight = size.borderTopWidth + size.borderBottomWidth; + + var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; + + // overwrite width and height if we can get it from style + var styleWidth = getStyleSize( style.width ); + if ( styleWidth !== false ) { + size.width = styleWidth + + // add padding and border unless it's already including it + ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); + } + + var styleHeight = getStyleSize( style.height ); + if ( styleHeight !== false ) { + size.height = styleHeight + + // add padding and border unless it's already including it + ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); + } + + size.innerWidth = size.width - ( paddingWidth + borderWidth ); + size.innerHeight = size.height - ( paddingHeight + borderHeight ); + + size.outerWidth = size.width + marginWidth; + size.outerHeight = size.height + marginHeight; + + return size; + } + + return getSize; + + })(); + + function getElementSize(ele) { + return _getSize(ele); + } +}); |