UNPKG

uikit

Version:

UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.

536 lines (395 loc) • 17.8 kB
/*! UIkit 3.2.1 | http://www.getuikit.com | (c) 2014 - 2019 YOOtheme | MIT License */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('uikit-util')) : typeof define === 'function' && define.amd ? define('uikitsortable', ['uikit-util'], factory) : (global = global || self, global.UIkitSortable = factory(global.UIkit.util)); }(this, function (uikitUtil) { 'use strict'; var targetClass = 'uk-animation-target'; var Animate = { props: { animation: Number }, data: { animation: 150 }, computed: { target: function() { return this.$el; } }, methods: { animate: function(action) { var this$1 = this; addStyle(); var children = uikitUtil.toNodes(this.target.children); var propsFrom = children.map(function (el) { return getProps(el, true); }); var oldHeight = uikitUtil.height(this.target); var oldScrollY = window.pageYOffset; action(); uikitUtil.Transition.cancel(this.target); children.forEach(uikitUtil.Transition.cancel); reset(this.target); this.$update(this.target); uikitUtil.fastdom.flush(); var newHeight = uikitUtil.height(this.target); children = children.concat(uikitUtil.toNodes(this.target.children).filter(function (el) { return !uikitUtil.includes(children, el); })); var propsTo = children.map(function (el, i) { return el.parentNode && i in propsFrom ? propsFrom[i] ? uikitUtil.isVisible(el) ? getPositionWithMargin(el) : {opacity: 0} : {opacity: uikitUtil.isVisible(el) ? 1 : 0} : false; } ); propsFrom = propsTo.map(function (props, i) { var from = children[i].parentNode === this$1.target ? propsFrom[i] || getProps(children[i]) : false; if (from) { if (!props) { delete from.opacity; } else if (!('opacity' in props)) { var opacity = from.opacity; if (opacity % 1) { props.opacity = 1; } else { delete from.opacity; } } } return from; }); uikitUtil.addClass(this.target, targetClass); children.forEach(function (el, i) { return propsFrom[i] && uikitUtil.css(el, propsFrom[i]); }); uikitUtil.css(this.target, 'height', oldHeight); uikitUtil.scrollTop(window, oldScrollY); return uikitUtil.Promise.all(children.map(function (el, i) { return propsFrom[i] && propsTo[i] ? uikitUtil.Transition.start(el, propsTo[i], this$1.animation, 'ease') : uikitUtil.Promise.resolve(); } ).concat(uikitUtil.Transition.start(this.target, {height: newHeight}, this.animation, 'ease'))).then(function () { children.forEach(function (el, i) { return uikitUtil.css(el, {display: propsTo[i].opacity === 0 ? 'none' : '', zIndex: ''}); }); reset(this$1.target); this$1.$update(this$1.target); uikitUtil.fastdom.flush(); // needed for IE11 }, uikitUtil.noop); } } }; function getProps(el, opacity) { var zIndex = uikitUtil.css(el, 'zIndex'); return uikitUtil.isVisible(el) ? uikitUtil.assign({ display: '', opacity: opacity ? uikitUtil.css(el, 'opacity') : '0', pointerEvents: 'none', position: 'absolute', zIndex: zIndex === 'auto' ? uikitUtil.index(el) : zIndex }, getPositionWithMargin(el)) : false; } function reset(el) { uikitUtil.css(el.children, { height: '', left: '', opacity: '', pointerEvents: '', position: '', top: '', width: '' }); uikitUtil.removeClass(el, targetClass); uikitUtil.css(el, 'height', ''); } function getPositionWithMargin(el) { var ref = el.getBoundingClientRect(); var height = ref.height; var width = ref.width; var ref$1 = uikitUtil.position(el); var top = ref$1.top; var left = ref$1.left; top += uikitUtil.toFloat(uikitUtil.css(el, 'marginTop')); return {top: top, left: left, height: height, width: width}; } var style; function addStyle() { if (style) { return; } style = uikitUtil.append(document.head, '<style>').sheet; style.insertRule( ("." + targetClass + " > * {\n margin-top: 0 !important;\n transform: none !important;\n }"), 0 ); } var Class = { connected: function() { !uikitUtil.hasClass(this.$el, this.$name) && uikitUtil.addClass(this.$el, this.$name); } }; var Component = { mixins: [Class, Animate], props: { group: String, threshold: Number, clsItem: String, clsPlaceholder: String, clsDrag: String, clsDragState: String, clsBase: String, clsNoDrag: String, clsEmpty: String, clsCustom: String, handle: String }, data: { group: false, threshold: 5, clsItem: 'uk-sortable-item', clsPlaceholder: 'uk-sortable-placeholder', clsDrag: 'uk-sortable-drag', clsDragState: 'uk-drag', clsBase: 'uk-sortable', clsNoDrag: 'uk-sortable-nodrag', clsEmpty: 'uk-sortable-empty', clsCustom: '', handle: false }, created: function() { var this$1 = this; ['init', 'start', 'move', 'end'].forEach(function (key) { var fn = this$1[key]; this$1[key] = function (e) { this$1.scrollY = window.pageYOffset; var ref = uikitUtil.getEventPos(e, 'page'); var x = ref.x; var y = ref.y; this$1.pos = {x: x, y: y}; fn(e); }; }); }, events: { name: uikitUtil.pointerDown, passive: false, handler: 'init' }, update: { write: function() { if (this.clsEmpty) { uikitUtil.toggleClass(this.$el, this.clsEmpty, uikitUtil.isEmpty(this.$el.children)); } uikitUtil.css(this.handle ? uikitUtil.$$(this.handle, this.$el) : this.$el.children, {touchAction: 'none', userSelect: 'none'}); if (this.drag) { // clamp to viewport var ref = uikitUtil.offset(window); var right = ref.right; var bottom = ref.bottom; uikitUtil.offset(this.drag, { top: uikitUtil.clamp(this.pos.y + this.origin.top, 0, bottom - this.drag.offsetHeight), left: uikitUtil.clamp(this.pos.x + this.origin.left, 0, right - this.drag.offsetWidth) }); trackScroll(this.pos); } } }, methods: { init: function(e) { var target = e.target; var button = e.button; var defaultPrevented = e.defaultPrevented; var ref = uikitUtil.toNodes(this.$el.children).filter(function (el) { return uikitUtil.within(target, el); }); var placeholder = ref[0]; if (!placeholder || defaultPrevented || button > 0 || uikitUtil.isInput(target) || uikitUtil.within(target, ("." + (this.clsNoDrag))) || this.handle && !uikitUtil.within(target, this.handle) ) { return; } e.preventDefault(); this.touched = [this]; this.placeholder = placeholder; this.origin = uikitUtil.assign({target: target, index: uikitUtil.index(placeholder)}, this.pos); uikitUtil.on(document, uikitUtil.pointerMove, this.move); uikitUtil.on(document, uikitUtil.pointerUp, this.end); uikitUtil.on(window, 'scroll', this.scroll); if (!this.threshold) { this.start(e); } }, start: function(e) { this.drag = uikitUtil.append(this.$container, this.placeholder.outerHTML.replace(/^<li/i, '<div').replace(/li>$/i, 'div>')); uikitUtil.css(this.drag, uikitUtil.assign({ boxSizing: 'border-box', width: this.placeholder.offsetWidth, height: this.placeholder.offsetHeight, overflow: 'hidden' }, uikitUtil.css(this.placeholder, ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom']))); uikitUtil.attr(this.drag, 'uk-no-boot', ''); uikitUtil.addClass(this.drag, this.clsDrag, this.clsCustom); uikitUtil.height(this.drag.firstElementChild, uikitUtil.height(this.placeholder.firstElementChild)); var ref = uikitUtil.offset(this.placeholder); var left = ref.left; var top = ref.top; uikitUtil.assign(this.origin, {left: left - this.pos.x, top: top - this.pos.y}); uikitUtil.addClass(this.placeholder, this.clsPlaceholder); uikitUtil.addClass(this.$el.children, this.clsItem); uikitUtil.addClass(document.documentElement, this.clsDragState); uikitUtil.trigger(this.$el, 'start', [this, this.placeholder]); this.move(e); }, move: function(e) { if (!this.drag) { if (Math.abs(this.pos.x - this.origin.x) > this.threshold || Math.abs(this.pos.y - this.origin.y) > this.threshold) { this.start(e); } return; } this.$emit(); var target = e.type === 'mousemove' ? e.target : document.elementFromPoint(this.pos.x - window.pageXOffset, this.pos.y - window.pageYOffset); var sortable = this.getSortable(target); var previous = this.getSortable(this.placeholder); var move = sortable !== previous; if (!sortable || uikitUtil.within(target, this.placeholder) || move && (!sortable.group || sortable.group !== previous.group)) { return; } target = sortable.$el === target.parentNode && target || uikitUtil.toNodes(sortable.$el.children).filter(function (element) { return uikitUtil.within(target, element); })[0]; if (move) { previous.remove(this.placeholder); } else if (!target) { return; } sortable.insert(this.placeholder, target); if (!uikitUtil.includes(this.touched, sortable)) { this.touched.push(sortable); } }, end: function(e) { uikitUtil.off(document, uikitUtil.pointerMove, this.move); uikitUtil.off(document, uikitUtil.pointerUp, this.end); uikitUtil.off(window, 'scroll', this.scroll); if (!this.drag) { if (e.type === 'touchend') { e.target.click(); } return; } untrackScroll(); var sortable = this.getSortable(this.placeholder); if (this === sortable) { if (this.origin.index !== uikitUtil.index(this.placeholder)) { uikitUtil.trigger(this.$el, 'moved', [this, this.placeholder]); } } else { uikitUtil.trigger(sortable.$el, 'added', [sortable, this.placeholder]); uikitUtil.trigger(this.$el, 'removed', [this, this.placeholder]); } uikitUtil.trigger(this.$el, 'stop', [this, this.placeholder]); uikitUtil.remove(this.drag); this.drag = null; var classes = this.touched.map(function (sortable) { return ((sortable.clsPlaceholder) + " " + (sortable.clsItem)); }).join(' '); this.touched.forEach(function (sortable) { return uikitUtil.removeClass(sortable.$el.children, classes); }); uikitUtil.removeClass(document.documentElement, this.clsDragState); }, scroll: function() { var scroll = window.pageYOffset; if (scroll !== this.scrollY) { this.pos.y += scroll - this.scrollY; this.scrollY = scroll; this.$emit(); } }, insert: function(element, target) { var this$1 = this; uikitUtil.addClass(this.$el.children, this.clsItem); var insert = function () { if (target) { if (!uikitUtil.within(element, this$1.$el) || isPredecessor(element, target)) { uikitUtil.before(target, element); } else { uikitUtil.after(target, element); } } else { uikitUtil.append(this$1.$el, element); } }; if (this.animation) { this.animate(insert); } else { insert(); } }, remove: function(element) { if (!uikitUtil.within(element, this.$el)) { return; } uikitUtil.css(this.handle ? uikitUtil.$$(this.handle, element) : element, {touchAction: '', userSelect: ''}); if (this.animation) { this.animate(function () { return uikitUtil.remove(element); }); } else { uikitUtil.remove(element); } }, getSortable: function(element) { return element && (this.$getComponent(element, 'sortable') || this.getSortable(element.parentNode)); } } }; function isPredecessor(element, target) { return element.parentNode === target.parentNode && uikitUtil.index(element) > uikitUtil.index(target); } var trackTimer; function trackScroll(ref) { var x = ref.x; var y = ref.y; clearTimeout(trackTimer); scrollParents(document.elementFromPoint(x - window.pageXOffset, y - window.pageYOffset)).some(function (scrollEl) { var scroll = scrollEl.scrollTop; var scrollHeight = scrollEl.scrollHeight; if (getScrollingElement() === scrollEl) { scrollEl = window; scrollHeight -= window.innerHeight; } var ref = uikitUtil.offset(scrollEl); var top = ref.top; var bottom = ref.bottom; if (top < y && top + 30 > y) { scroll -= 5; } else if (bottom > y && bottom - 20 < y) { scroll += 5; } if (scroll > 0 && scroll < scrollHeight) { return trackTimer = setTimeout(function () { uikitUtil.scrollTop(scrollEl, scroll); trackScroll({x: x, y: y}); }, 10); } }); } function untrackScroll() { clearTimeout(trackTimer); } var overflowRe = /auto|scroll/; function scrollParents(element) { var scrollEl = getScrollingElement(); return parents(element, function (parent) { return parent === scrollEl || overflowRe.test(uikitUtil.css(parent, 'overflow')); }); } function parents(element, fn) { var parents = []; do { if (fn(element)) { parents.unshift(element); } } while (element && (element = element.parentElement)); return parents; } function getScrollingElement() { return document.scrollingElement || document.documentElement; } /* global UIkit, 'sortable' */ if (typeof window !== 'undefined' && window.UIkit) { window.UIkit.component('sortable', Component); } return Component; }));