Skip to content

Instantly share code, notes, and snippets.

@joelcoxokc
Last active August 18, 2016 21:56
Show Gist options
  • Save joelcoxokc/d5c2aace29367b40dd2bb52e9f9a8333 to your computer and use it in GitHub Desktop.
Save joelcoxokc/d5c2aace29367b40dd2bb52e9f9a8333 to your computer and use it in GitHub Desktop.
sortable
.container {
display:flex;
flex-direction: row;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
min-width:100%;
min-height: 100%;
}
.container > aside {
display:flex;
flex-direction: column;
flex: 0 0 25%;
position: relative;
}
.container > aside > h1 {
font-size: 22px;
text-align:center;
margin: 0;
}
.container > aside > ul {
flex: 1;
list-style: none;
position: relative;
margin: 0;
padding: 0;
border-top: 1px solid rgba(0,0,0,0.2);
border-right: 1px solid rgba(0,0,0,0.2);
}
.container > aside:last-child > ul {
border-right:0;
}
.container > aside > ul > li {
position: absolute;
display: flex;
top: 0;
left: 0;
right: 0;
min-height: 32px;
max-height: 32px;
line-height: 32px;
font-size: 17px;
background-color: white;
padding: 4px;
cursor: move;
}
.container > aside > ul > li * {
pointer-events: none;
}
li span.content {
flex: 1;
display:flex;
flex-direction:row;
position: relative;
border: 1px solid rgba(0,0,0,0.1);
padding-left: 8px;
border-radius:6px;
background-color: inherit;
font-size: inherit;
line-height: inherit;
color: red;
font-size: 14px;
}
li span.order {
line-height: inherit;
color: red;
font-size: 14px;
margin-right: 8px;
}
li span.number {
line-height: inherit;
font-size: inherit;
color: grey;
}
<template>
<require from="./app.css"></require>
<require from="./filter-location"></require>
<div class="container">
<aside repeat.for="location of state.locations" class-name.bind="location.name">
<h1>${location.title}</h1>
<ul ref="location.element"></ul>
</aside>
</div>
</template>
import {state} from './state';
import {DraggableModel} from './draggable';
import './element';
export class App {
state = state;
attached() {
state.load().then(models => {
models.forEach(model => {
model.draggable = new DraggableModel(model, state.locations);
})
})
}
}
// Clamps a value to a min/max
function clamp(value, a, b) {
return value < a ? a : (value > b ? b : value);
}
// Changes an elements's position in array
function arrayMove(array, from, to, array2) {
array2 = array2 || array;
array.splice(to, 0, array2.splice(from, 1)[0]);
}
import {createTemplate} from './template';
const height = 40;
export class DraggableModel {
constructor(model, locations) {
const self = this;
const list = locations[model.location];
this.getLocations = ()=> locations;
this.model = model;
this.template = createTemplate(model);
this.template.temp = createTemplate(model, true);
this.element = this.template.element;
this.element.temp = this.template.temp.element;
this.element.getDraggable = ()=> this;
this.element.temp.getDraggable = ()=> this;
list.element.appendChild(this.element);
console.log(this.template);
this.animation = TweenLite.to(this.template.content, 0.3, {
boxShadow: "rgba(0,0,0,0.2) 0px 16px 32px 0px",
force3D: true,
scale: 1.1,
background: 'white',
paused: true,
})
this.dragger = new Draggable(this.element, {
onDragStart: function() {self.onDragStart(this)},
onRelease: function() {self.onRelease(this)},
onDrag: function() {self.onDrag(this)},
cursor: "move",
type: "x,y",
});
this.setIndex(list.indexOf(this.model));
}
setIndex(index) {
this.index = index;
this.template.setOrder(index)
if (!this.dragger.isDragging) {
if (this.parentChanged) {
this.template.temp.setOrder(index)
TweenLight.to(this.element.temp, 0.3, {y: this.index * height, autoAlpha:0});
} else {
TweenLite.to(this.element, 0.3, {y: this.index * height});
}
}
}
onDragStart(drag) {
this.startLocation = this.model.location;
this.animation.play();
drag.update();
}
onRelease(drag) {
this.animation.reverse();
if (this.parentChanged) {
this.parentChanged = false;
this.element.temp.parentNode.insertBefore(this.element, this.element.temp);
this.element.temp.parentNode.removeChild(this.element.temp);
TweenLite.set(this.element, {x:0});
TweenLite.to(this.element, {y:this.index * height});
} else {
TweenLite.to(this.element, 0.3, {x:0, y: this.index * height});
}
const locations = this.getLocations();
locations.forEach(list => {
Array.from(list.element.children).forEach((child, index) => {
const draggable = child.getDraggable();
if (draggable) draggable.setIndex(index);
})
})
}
onDrag(drag) {
const locations = this.getLocations();
const current = locations[this.model.location];
locations.forEach(list => {
const parent = list.element;
if (drag.hitTest(parent, '51%')) {
const nextIndex = clamp(Math.round(drag.y / height), 0, parent.children.length);
const childAtIndex = parent.children[nextIndex];
// if (list === current && this.index === nextIndex) return;
if (parent !== current.element) {
this.parentChanged = true;
if (list.name === this.startLocation) {
this.parentChanged = false;
if (this.element.temp.parentNode) {
this.element.temp.parentNode.removeChild(this.element.temp);
}
}
if (this.parentChanged) {
this.element.parentNode.appendChild(this.element);
Array.from(current.element.children)
.forEach((node, index) => {
const draggable = node.getDraggable();
if (draggable) {
draggable.setIndex(index);
}
})
}
}
if (this.parentChanged) {
parent.insertBefore(this.element.temp, childAtIndex);
} else {
parent.insertBefore(this.element, childAtIndex);
}
this.model.location = list.name;
}
Array.from(parent.children).forEach((node, index) => {
const draggable = node.getDraggable();
if (draggable) {
draggable.setIndex(index);
}
})
})
}
}
// Clamps a value to a min/max
function clamp(value, a, b) {
return value < a ? a : (value > b ? b : value);
}
Element.prototype.find = Element.prototype.querySelector;
export class FilterLocationValueConverter {
toView(list, location) {
return list.filter(model => model.location === location);
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.16.1/TweenMax.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/utils/Draggable.min.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script>
<script>
require(['aurelia-bootstrapper']);
</script>
</body>
</html>
var orderNumber = 100000;
export class Order {
location = null;
number = null;
index = null;
id = null;
element = null;
constructor(options) {
Object.assign(this, options);
this.number = createNumber();
this.id = createOrderId(this.number);
}
clone() {
const location = this.location;
const index = this.index;
let order = new Order({location, index});
order.id = this.id;
order.number = this.number;
return order;
}
}
function createNumber() {
return orderNumber++;
}
function createOrderId(number) {
return `order-${number}`;
}
import {Order} from './order';
var locations = ['north', 'east', 'south', 'west'];
var modelCount = 20;
export const state = {
models: [],
locations: [],
}
locations.forEach(name => {
const location = state.locations[name] = [];
state.locations.push(location);
location.name = name;
location.title = capitalize(name);
})
state.load = function() {
return new Promise(resolve => {
if (!this.models.length) {
for(var i = 0; i < modelCount; i++) {
createOrder();
}
}
resolve(this.models);
})
}
function createOrder() {
const location = randomLocation();
const listSet = state.locations[location]
const index = listSet.length;
const model = new Order({location, index});
state.models.push(model);
listSet.push(model);
}
function randomLocation() {
return locations[Math.floor(Math.random() * locations.length)];
}
function capitalize(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
export function createTemplate(model, hidden) {
const element = document.createElement('LI');
element.id = model.id;
if (hidden) {
element.style.opacity = 0;
}
const content = document.createElement('SPAN');
content.className = 'content';
element.appendChild(content);
const order = document.createElement('SPAN');
order.className = 'order';
order.textContent = model.index;
content.appendChild(order);
const number = document.createElement('SPAN');
number.className = 'number';
number.textContent = model.number;
content.appendChild(number);
const template = {element, content, order, number};
template.setOrder = function(value) {
order.textContent = value;
}
template.setNumber = function(value) {
number.textContent = value;
}
template.update = function() {
template.setOrder(model.index);
template.setNumber(model.number);
}
return template;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment