switch drag & drop lib
43
dashboard-ui/bower_components/Sortable/.bower.json
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"name": "Sortable",
|
||||||
|
"main": [
|
||||||
|
"Sortable.js",
|
||||||
|
"ng-sortable.js",
|
||||||
|
"knockout-sortable.js",
|
||||||
|
"react-sortable-mixin.js"
|
||||||
|
],
|
||||||
|
"homepage": "http://rubaxa.github.io/Sortable/",
|
||||||
|
"authors": [
|
||||||
|
"RubaXa <ibnRubaXa@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.",
|
||||||
|
"keywords": [
|
||||||
|
"sortable",
|
||||||
|
"reorder",
|
||||||
|
"list",
|
||||||
|
"html5",
|
||||||
|
"drag",
|
||||||
|
"and",
|
||||||
|
"drop",
|
||||||
|
"dnd",
|
||||||
|
"web-components"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
"version": "1.4.2",
|
||||||
|
"_release": "1.4.2",
|
||||||
|
"_resolution": {
|
||||||
|
"type": "version",
|
||||||
|
"tag": "1.4.2",
|
||||||
|
"commit": "d86937c8bca017f948aad04eb02dcaddfbb60ffa"
|
||||||
|
},
|
||||||
|
"_source": "git://github.com/RubaXa/Sortable.git",
|
||||||
|
"_target": "~1.4.2",
|
||||||
|
"_originalSource": "Sortable",
|
||||||
|
"_direct": true
|
||||||
|
}
|
|
@ -2,8 +2,7 @@
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
5
dashboard-ui/bower_components/Sortable/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
node_modules
|
||||||
|
mock.png
|
||||||
|
.*.sw*
|
||||||
|
.build*
|
||||||
|
jquery.fn.*
|
24
dashboard-ui/bower_components/Sortable/.jshintrc
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"strict": true,
|
||||||
|
"newcap": false,
|
||||||
|
"node": true,
|
||||||
|
"expr": true,
|
||||||
|
"supernew": true,
|
||||||
|
"laxbreak": true,
|
||||||
|
"white": true,
|
||||||
|
"globals": {
|
||||||
|
"define": true,
|
||||||
|
"test": true,
|
||||||
|
"expect": true,
|
||||||
|
"module": true,
|
||||||
|
"asyncTest": true,
|
||||||
|
"start": true,
|
||||||
|
"ok": true,
|
||||||
|
"equal": true,
|
||||||
|
"notEqual": true,
|
||||||
|
"deepEqual": true,
|
||||||
|
"window": true,
|
||||||
|
"document": true,
|
||||||
|
"performance": true
|
||||||
|
}
|
||||||
|
}
|
23
dashboard-ui/bower_components/Sortable/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
### Issue
|
||||||
|
|
||||||
|
1. Try [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch, perhaps the problem has been solved;
|
||||||
|
2. [Use the search](https://github.com/RubaXa/Sortable/search?q=problem), maybe already have an answer;
|
||||||
|
3. If not found, create example on [jsbin.com (draft)](http://jsbin.com/zunibaxada/1/edit?html,js,output) and describe the problem.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Pull Request
|
||||||
|
|
||||||
|
1. Before PR run `grunt`;
|
||||||
|
2. Only into [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Pieced together from [gruntjs](http://gruntjs.com/getting-started)
|
||||||
|
|
||||||
|
1. Fork repo on [github](https://github.com)
|
||||||
|
2. Clone locally
|
||||||
|
3. from local repro ```npm install```
|
||||||
|
4. Install grunt-cli globally ```sudo -H npm install -g grunt-cli```
|
103
dashboard-ui/bower_components/Sortable/Gruntfile.js
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
grunt.initConfig({
|
||||||
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
|
||||||
|
version: {
|
||||||
|
js: {
|
||||||
|
src: ['<%= pkg.exportName %>.js', '*.json']
|
||||||
|
},
|
||||||
|
cdn: {
|
||||||
|
options: {
|
||||||
|
prefix: '(cdnjs\\.cloudflare\\.com\\/ajax\\/libs\\/Sortable|cdn\\.jsdelivr\\.net\\/sortable)\\/',
|
||||||
|
replace: '[0-9\\.]+'
|
||||||
|
},
|
||||||
|
src: ['README.md']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jshint: {
|
||||||
|
all: ['*.js', '!*.min.js'],
|
||||||
|
|
||||||
|
options: {
|
||||||
|
jshintrc: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uglify: {
|
||||||
|
options: {
|
||||||
|
banner: '/*! <%= pkg.exportName %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %> */\n'
|
||||||
|
},
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
'<%= pkg.exportName %>.min.js': ['<%= pkg.exportName %>.js']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jquery: {
|
||||||
|
files: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
exec: {
|
||||||
|
'meteor-test': {
|
||||||
|
command: 'meteor/runtests.sh'
|
||||||
|
},
|
||||||
|
'meteor-publish': {
|
||||||
|
command: 'meteor/publish.sh'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
jquery: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
grunt.registerTask('jquery', function (exportName, uglify) {
|
||||||
|
if (exportName == 'min') {
|
||||||
|
exportName = null;
|
||||||
|
uglify = 'min';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exportName) {
|
||||||
|
exportName = 'sortable';
|
||||||
|
}
|
||||||
|
|
||||||
|
var fs = require('fs'),
|
||||||
|
filename = 'jquery.fn.' + exportName + '.js';
|
||||||
|
|
||||||
|
grunt.log.oklns(filename);
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
filename,
|
||||||
|
(fs.readFileSync('jquery.binding.js') + '')
|
||||||
|
.replace('$.fn.sortable', '$.fn.' + exportName)
|
||||||
|
.replace('/* CODE */',
|
||||||
|
(fs.readFileSync('Sortable.js') + '')
|
||||||
|
.replace(/^[\s\S]*?function[\s\S]*?(var[\s\S]+)\/\/\s+Export[\s\S]+/, '$1')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (uglify) {
|
||||||
|
var opts = {};
|
||||||
|
|
||||||
|
opts['jquery.fn.' + exportName + '.min.js'] = filename;
|
||||||
|
grunt.config.set('uglify.jquery.files', opts);
|
||||||
|
|
||||||
|
grunt.task.run('uglify:jquery');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
grunt.loadNpmTasks('grunt-version');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
grunt.loadNpmTasks('grunt-exec');
|
||||||
|
|
||||||
|
// Meteor tasks
|
||||||
|
grunt.registerTask('meteor-test', 'exec:meteor-test');
|
||||||
|
grunt.registerTask('meteor-publish', 'exec:meteor-publish');
|
||||||
|
grunt.registerTask('meteor', ['meteor-test', 'meteor-publish']);
|
||||||
|
|
||||||
|
grunt.registerTask('tests', ['jshint']);
|
||||||
|
grunt.registerTask('default', ['tests', 'version', 'uglify:dist']);
|
||||||
|
};
|
139
dashboard-ui/bower_components/Sortable/Sortable.html
vendored
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<link rel="import" href="../polymer/polymer.html">
|
||||||
|
<script src="./Sortable.js"></script>
|
||||||
|
|
||||||
|
<dom-module id="sortable-js">
|
||||||
|
<template>
|
||||||
|
<content></content>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: "sortable-js",
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
group : { type: String, value: () => Math.random(), observer: "groupChanged" },
|
||||||
|
sort : { type: Boolean, value: true, observer: "sortChanged" },
|
||||||
|
disabled : { type: Boolean, value: false, observer: "disabledChanged" },
|
||||||
|
store : { type: Object, value: null, observer: "storeChanged" },
|
||||||
|
handle : { type: String, value: null, observer: "handleChanged" },
|
||||||
|
scrollSensitivity : { type: Number, value: 30, observer: "scrollSensitivityChanged" },
|
||||||
|
scrollSpeed : { type: Number, value: 10, observer: "scrollSpeedChanged" },
|
||||||
|
ghostClass : { type: String, value: "sortable-ghost", observer: "ghostClassChanged" },
|
||||||
|
chosenClass : { type: String, value: "sortable-chosen", observer: "chosenClassChanged" },
|
||||||
|
ignore : { type: String, value: "a, img", observer: "ignoreChanged" },
|
||||||
|
filter : { type: Object, value: null, observer: "filterChanged" },
|
||||||
|
animation : { type: Number, value: 0, observer: "animationChanged" },
|
||||||
|
dropBubble : { type: Boolean, value: false, observer: "dropBubbleChanged" },
|
||||||
|
dragoverBubble : { type: Boolean, value: false, observer: "dragoverBubbleChanged" },
|
||||||
|
dataIdAttr : { type: String, value: "data-id", observer: "dataIdAttrChanged" },
|
||||||
|
delay : { type: Number, value: 0, observer: "delayChanged" },
|
||||||
|
forceFallback : { type: Boolean, value: false, observer: "forceFallbackChanged" },
|
||||||
|
fallbackClass : { type: String, value: "sortable-fallback", observer: "fallbackClassChanged" },
|
||||||
|
fallbackOnBody : { type: Boolean, value: false, observer: "fallbackOnBodyChanged" },
|
||||||
|
draggable : {},
|
||||||
|
scroll : {}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
// override default DOM property behavior
|
||||||
|
Object.defineProperties(this, {
|
||||||
|
draggable: { get() { return this._draggable || this.getAttribute("draggable") || ">*"}, set(value) { this._draggable = value; this.draggableChanged(value)} },
|
||||||
|
scroll: { get() { return this._scroll || JSON.parse(this.getAttribute("scroll") || "true") }, set(value) { this._scroll = value; this.scrollChanged(value)} }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
attached: function() {
|
||||||
|
// Given
|
||||||
|
// <sortable-js>
|
||||||
|
// <template is="dom-repeat" items={{data}}>
|
||||||
|
// <div>
|
||||||
|
// <template is="dom-if" if="true">
|
||||||
|
// <span>hello</span></template></div>
|
||||||
|
// After render, it becomes
|
||||||
|
// <sortable-js>
|
||||||
|
// <div>
|
||||||
|
// <span>hello</span>
|
||||||
|
// <template is="dom-if">
|
||||||
|
// <tempalte is="dom-repeat">
|
||||||
|
var templates = this.querySelectorAll("template[is='dom-repeat']")
|
||||||
|
var template = templates[templates.length-1]
|
||||||
|
|
||||||
|
var options = {}
|
||||||
|
Object.keys(this.properties).forEach(key => {
|
||||||
|
options[key] = this[key]
|
||||||
|
})
|
||||||
|
|
||||||
|
this.sortable = Sortable.create(this, Object.assign(options, {
|
||||||
|
onUpdate: e => {
|
||||||
|
if (template) {
|
||||||
|
template.splice("items", e.newIndex, 0, template.splice("items", e.oldIndex, 1)[0])
|
||||||
|
}
|
||||||
|
this.fire("update", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: e => {
|
||||||
|
if (template) {
|
||||||
|
var froms = e.from.querySelectorAll("template[is='dom-repeat']")
|
||||||
|
var from = froms[froms.length-1]
|
||||||
|
var item = from.items[e.oldIndex]
|
||||||
|
template.splice("items", e.newIndex, 0, item)
|
||||||
|
}
|
||||||
|
this.fire("add", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onRemove: e => {
|
||||||
|
if (template) {
|
||||||
|
template.splice("items", e.oldIndex, 1)[0]
|
||||||
|
}
|
||||||
|
this.fire("remove", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onStart: e => {
|
||||||
|
this.fire("start", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onEnd: e => {
|
||||||
|
this.fire("end", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onSort: e => {
|
||||||
|
this.fire("sort", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onFilter: e => {
|
||||||
|
this.fire("filter", e)
|
||||||
|
},
|
||||||
|
|
||||||
|
onMove: e => {
|
||||||
|
this.fire("move", e)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
detached: function() {
|
||||||
|
this.sortable.destroy()
|
||||||
|
},
|
||||||
|
|
||||||
|
groupChanged : function(value) { this.sortable && this.sortable.option("group", value) },
|
||||||
|
sortChanged : function(value) { this.sortable && this.sortable.option("sort", value) },
|
||||||
|
disabledChanged : function(value) { this.sortable && this.sortable.option("disabled", value) },
|
||||||
|
storeChanged : function(value) { this.sortable && this.sortable.option("store", value) },
|
||||||
|
handleChanged : function(value) { this.sortable && this.sortable.option("handle", value) },
|
||||||
|
scrollChanged : function(value) { this.sortable && this.sortable.option("scroll", value) },
|
||||||
|
scrollSensitivityChanged : function(value) { this.sortable && this.sortable.option("scrollSensitivity", value) },
|
||||||
|
scrollSpeedChanged : function(value) { this.sortable && this.sortable.option("scrollSpeed", value) },
|
||||||
|
draggableChanged : function(value) { this.sortable && this.sortable.option("draggable", value) },
|
||||||
|
ghostClassChanged : function(value) { this.sortable && this.sortable.option("ghostClass", value) },
|
||||||
|
chosenClassChanged : function(value) { this.sortable && this.sortable.option("chosenClass", value) },
|
||||||
|
ignoreChanged : function(value) { this.sortable && this.sortable.option("ignore", value) },
|
||||||
|
filterChanged : function(value) { this.sortable && this.sortable.option("filter", value) },
|
||||||
|
animationChanged : function(value) { this.sortable && this.sortable.option("animation", value) },
|
||||||
|
dropBubbleChanged : function(value) { this.sortable && this.sortable.option("dropBubble", value) },
|
||||||
|
dragoverBubbleChanged : function(value) { this.sortable && this.sortable.option("dragoverBubble", value) },
|
||||||
|
dataIdAttrChanged : function(value) { this.sortable && this.sortable.option("dataIdAttr", value) },
|
||||||
|
delayChanged : function(value) { this.sortable && this.sortable.option("delay", value) },
|
||||||
|
forceFallbackChanged : function(value) { this.sortable && this.sortable.option("forceFallback", value) },
|
||||||
|
fallbackClassChanged : function(value) { this.sortable && this.sortable.option("fallbackClass", value) },
|
||||||
|
fallbackOnBodyChanged : function(value) { this.sortable && this.sortable.option("fallbackOnBody", value) }
|
||||||
|
})
|
||||||
|
</script>
|
1249
dashboard-ui/bower_components/Sortable/Sortable.js
vendored
Normal file
2
dashboard-ui/bower_components/Sortable/Sortable.min.js
vendored
Normal file
32
dashboard-ui/bower_components/Sortable/bower.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "Sortable",
|
||||||
|
"main": [
|
||||||
|
"Sortable.js",
|
||||||
|
"ng-sortable.js",
|
||||||
|
"knockout-sortable.js",
|
||||||
|
"react-sortable-mixin.js"
|
||||||
|
],
|
||||||
|
"homepage": "http://rubaxa.github.io/Sortable/",
|
||||||
|
"authors": [
|
||||||
|
"RubaXa <ibnRubaXa@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.",
|
||||||
|
"keywords": [
|
||||||
|
"sortable",
|
||||||
|
"reorder",
|
||||||
|
"list",
|
||||||
|
"html5",
|
||||||
|
"drag",
|
||||||
|
"and",
|
||||||
|
"drop",
|
||||||
|
"dnd",
|
||||||
|
"web-components"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
]
|
||||||
|
}
|
32
dashboard-ui/bower_components/Sortable/component.json
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "Sortable",
|
||||||
|
"main": "Sortable.js",
|
||||||
|
"version": "1.4.2",
|
||||||
|
"homepage": "http://rubaxa.github.io/Sortable/",
|
||||||
|
"repo": "RubaXa/Sortable",
|
||||||
|
"authors": [
|
||||||
|
"RubaXa <ibnRubaXa@gmail.com>"
|
||||||
|
],
|
||||||
|
"description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.",
|
||||||
|
"keywords": [
|
||||||
|
"sortable",
|
||||||
|
"reorder",
|
||||||
|
"list",
|
||||||
|
"html5",
|
||||||
|
"drag",
|
||||||
|
"and",
|
||||||
|
"drop",
|
||||||
|
"dnd"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"tests"
|
||||||
|
],
|
||||||
|
|
||||||
|
"scripts": [
|
||||||
|
"Sortable.js"
|
||||||
|
]
|
||||||
|
}
|
344
dashboard-ui/bower_components/Sortable/index.html
vendored
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||||
|
<meta property="og:image" content="/st/og-image.png"/>
|
||||||
|
|
||||||
|
<title>Sortable. No jQuery.</title>
|
||||||
|
|
||||||
|
<meta name="keywords" content="sortable, reorder, list, javascript, html5, drag and drop, dnd, animation, groups, angular, ng-sortable, react, mixin, effects, rubaxa"/>
|
||||||
|
<meta name="description" content="Sortable - is a minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports Meteor, AngularJS, React and any CSS library, e.g. Bootstrap."/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=0.5"/>
|
||||||
|
|
||||||
|
<link href="//rubaxa.github.io/Ply/ply.css" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="//fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
|
<link href="st/app.css" rel="stylesheet" type="text/css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a href="https://github.com/RubaXa/Sortable"><img style="position: fixed; top: 0; right: 0; border: 0; z-index: 10000;" src="//s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div style="padding: 80px 150px 0; height: 160px;">
|
||||||
|
<a class="logo" href="https://github.com/RubaXa/Sortable"><img src="st/logo.png"/></a>
|
||||||
|
<h1 data-force="40" data-force-y="2.5">The JavaScript library for modern browsers and touch devices. No jQuery.</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Connected lists -->
|
||||||
|
<div class="container" style="height: 520px">
|
||||||
|
<div data-force="30" class="layer block" style="left: 14.5%; top: 0; width: 37%">
|
||||||
|
<div class="layer title">List A</div>
|
||||||
|
<ul id="foo" class="block__list block__list_words">
|
||||||
|
<li>бегемот</li>
|
||||||
|
<li>корм</li>
|
||||||
|
<li>антон</li>
|
||||||
|
<li>сало</li>
|
||||||
|
<li>железосталь</li>
|
||||||
|
<li>валик</li>
|
||||||
|
<li>кровать</li>
|
||||||
|
<li>краб</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div data-force="18" class="layer block" style="left: 58%; top: 143px; width: 40%;">
|
||||||
|
<div class="layer title">List B</div>
|
||||||
|
<ul id="bar" class="block__list block__list_tags">
|
||||||
|
<li>казнить</li>
|
||||||
|
<li>,</li>
|
||||||
|
<li>нельзя</li>
|
||||||
|
<li>помиловать</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Multi connected lists -->
|
||||||
|
<a name="m"></a>
|
||||||
|
<div class="container">
|
||||||
|
<div id="multi" style="margin-left: 30px">
|
||||||
|
<div><div data-force="5" class="layer title title_xl">Multi</div></div>
|
||||||
|
|
||||||
|
<div class="layer tile" data-force="30">
|
||||||
|
<div class="tile__name">Group A</div>
|
||||||
|
<div class="tile__list">
|
||||||
|
<img src="st/face-01.jpg"/><!--
|
||||||
|
--><img src="st/face-02.jpg"/><!--
|
||||||
|
--><img src="st/face-03.jpg"/><!--
|
||||||
|
--><img src="st/face-04.jpg"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layer tile" data-force="25">
|
||||||
|
<div class="tile__name">Group B</div>
|
||||||
|
<div class="tile__list">
|
||||||
|
<img src="st/face-05.jpg"/><!--
|
||||||
|
--><img src="st/face-06.jpg"/><!--
|
||||||
|
--><img src="st/face-07.jpg"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layer tile" data-force="20">
|
||||||
|
<div class="tile__name">Group C</div>
|
||||||
|
<div class="tile__list">
|
||||||
|
<img src="st/face-08.jpg"/><!--
|
||||||
|
--><img src="st/face-09.jpg"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Editable list -->
|
||||||
|
<a name="e"></a>
|
||||||
|
<div class="container" style="margin-top: 100px">
|
||||||
|
<div id="filter" style="margin-left: 30px">
|
||||||
|
<div><div data-force="5" class="layer title title_xl">Editable list</div></div>
|
||||||
|
|
||||||
|
<div style="margin-top: -8px; margin-left: 10px" class="block__list block__list_words">
|
||||||
|
<ul id="editable">
|
||||||
|
<li>Оля<i class="js-remove">✖</i></li>
|
||||||
|
<li>Владимир<i class="js-remove">✖</i></li>
|
||||||
|
<li>Алина<i class="js-remove">✖</i></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<button id="addUser">Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Advanced connected lists -->
|
||||||
|
<a name="ag"></a>
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div id="advanced" style="margin-left: 30px;">
|
||||||
|
<div><div data-force="5" class="layer title title_xl">Advanced groups</div></div>
|
||||||
|
|
||||||
|
<div style="width: 25%; float: left; margin-top: 15px; margin-left: 10px" class="block__list block__list_words">
|
||||||
|
<div class="block__list-title">pull & put</div>
|
||||||
|
<ul id="advanced-1">
|
||||||
|
<li>Meat</li>
|
||||||
|
<li>Potato</li>
|
||||||
|
<li>Tea</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width: 25%; float: left; margin-top: 15px; margin-left: 10px" class="block__list block__list_words">
|
||||||
|
<div class="block__list-title">only pull (clone) no reordering</div>
|
||||||
|
<ul id="advanced-2">
|
||||||
|
<li>Sex</li>
|
||||||
|
<li>Drugs</li>
|
||||||
|
<li>Rock'n'roll</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="width: 25%; float: left; margin-top: 15px; margin-left: 10px" class="block__list block__list_words">
|
||||||
|
<div class="block__list-title">only put</div>
|
||||||
|
<ul id="advanced-3">
|
||||||
|
<li>Money</li>
|
||||||
|
<li>Force</li>
|
||||||
|
<li>Agility</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 'handle' option -->
|
||||||
|
<a name="h"></a>
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div id="handle" style="margin-left: 30px;">
|
||||||
|
<div><div data-force="5" class="layer title title_xl">Drag handle and selectable text</div></div>
|
||||||
|
|
||||||
|
<div style="width: 30%; margin-left: 10px" class="block__list_words">
|
||||||
|
<ul id="handle-1">
|
||||||
|
<li><span class="drag-handle">☰</span>Select text freely</li>
|
||||||
|
<li><span class="drag-handle">☰</span>Drag my handle</li>
|
||||||
|
<li><span class="drag-handle">☰</span>Best of both worlds</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Angular -->
|
||||||
|
<a name="ng"></a>
|
||||||
|
<div id="todos" ng-app="todoApp" class="container" style="margin-top: 100px">
|
||||||
|
<div style="margin-left: 30px">
|
||||||
|
<div><div data-force="5" class="layer title title_xl">AngularJS / ng-sortable</div></div>
|
||||||
|
|
||||||
|
<div style="width: 30%; margin-top: -8px; margin-left: 10px; float: left;" class="block__list block__list_words">
|
||||||
|
<div ng-controller="TodoController">
|
||||||
|
<span style="padding-left: 20px">{{remaining()}} of {{todos.length}} remaining</span>
|
||||||
|
[ <a href="" ng-click="archive()">archive</a> ]
|
||||||
|
<ul ng-sortable="{ group: 'todo', animation: 150 }" class="unstyled">
|
||||||
|
<li ng-repeat="todo in todos">
|
||||||
|
<input type="checkbox" ng-model="todo.done">
|
||||||
|
<span class="done-{{todo.done}}">{{todo.text}}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<form ng-submit="addTodo()" style="padding-left: 20px">
|
||||||
|
<input type="text" ng-model="todoText" size="30"
|
||||||
|
placeholder="add new todo here">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="width: 30%; margin-top: -8px; margin-left: 10px; float: left;" class="block__list block__list_words">
|
||||||
|
<div ng-controller="TodoControllerNext">
|
||||||
|
<span style="padding-left: 20px">{{remaining()}} of {{todos.length}} remaining</span>
|
||||||
|
<ul ng-sortable="sortableConfig" class="unstyled">
|
||||||
|
<li ng-repeat="todo in todos">
|
||||||
|
<input type="checkbox" ng-model="todo.done">
|
||||||
|
<span class="done-{{todo.done}}">{{todo.text}}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Code example -->
|
||||||
|
<a name="c"></a>
|
||||||
|
<div class="container" style="margin-top: 100px">
|
||||||
|
<div style="margin-left: 30px">
|
||||||
|
<div><div class="layer title title_xl">Code example</div></div>
|
||||||
|
<pre data-force="100" class="layer javascript" style="margin-top: -8px; margin-left: 10px; width: 90%"><code>// Simple list
|
||||||
|
var list = document.getElementById("my-ui-list");
|
||||||
|
Sortable.create(list); // That's all.
|
||||||
|
|
||||||
|
|
||||||
|
// Grouping
|
||||||
|
var foo = document.getElementById("foo");
|
||||||
|
Sortable.create(foo, { group: "omega" });
|
||||||
|
|
||||||
|
var bar = document.getElementById("bar");
|
||||||
|
Sortable.create(bar, { group: "omega" });
|
||||||
|
|
||||||
|
|
||||||
|
// Or
|
||||||
|
var container = document.getElementById("multi");
|
||||||
|
var sort = Sortable.create(container, {
|
||||||
|
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
|
||||||
|
handle: ".tile__title", // Restricts sort start click/touch to the specified element
|
||||||
|
draggable: ".tile", // Specifies which items inside the element should be sortable
|
||||||
|
onUpdate: function (evt/**Event*/){
|
||||||
|
var item = evt.item; // the current dragged HTMLElement
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ..
|
||||||
|
sort.destroy();
|
||||||
|
|
||||||
|
|
||||||
|
// Editable list
|
||||||
|
var editableList = Sortable.create(editable, {
|
||||||
|
filter: '.js-remove',
|
||||||
|
onFilter: function (evt) {
|
||||||
|
var el = editableList.closest(evt.item); // get dragged item
|
||||||
|
el && el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" style="margin: 100px 0;">
|
||||||
|
<div style="margin-left: 30px">
|
||||||
|
<div><div class="layer title title_xl">See also</div></div>
|
||||||
|
<div id="rubaxa-repos" data-force="100" class="layer" style="margin-top: -8px; margin-left: 10px; width: 90%; background-color: #fff;">Loading…</div>
|
||||||
|
<script src="//rubaxa.github.io/repos.js"></script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="Sortable.js"></script>
|
||||||
|
<script src="//rubaxa.github.io/Ply/Ply.min.js"></script>
|
||||||
|
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
|
||||||
|
<script src="ng-sortable.js"></script>
|
||||||
|
|
||||||
|
<script src="st/app.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- highlight.js -->
|
||||||
|
<style>
|
||||||
|
/* Tomorrow Theme */
|
||||||
|
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
||||||
|
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
|
||||||
|
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
|
||||||
|
.tomorrow-comment, pre .comment, pre .title {
|
||||||
|
color: #8e908c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo {
|
||||||
|
color: #c82829;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant {
|
||||||
|
color: #f5871f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute {
|
||||||
|
color: #eab700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata {
|
||||||
|
color: #718c00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-aqua, pre .css .hexcolor {
|
||||||
|
color: #3e999f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title {
|
||||||
|
color: #4271ae;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tomorrow-purple, pre .keyword, pre .javascript .function {
|
||||||
|
color: #8959a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
border: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre code {
|
||||||
|
display: block;
|
||||||
|
color: #4d4d4c;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: Menlo, Monaco, Consolas, monospace;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="//yandex.st/highlightjs/7.5/highlight.min.js"></script>
|
||||||
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||||
|
|
||||||
|
ga('create', 'UA-16483888-3', 'rubaxa.github.io');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
61
dashboard-ui/bower_components/Sortable/jquery.binding.js
vendored
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* jQuery plugin for Sortable
|
||||||
|
* @author RubaXa <trash@rubaxa.org>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
(function (factory) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (typeof define === "function" && define.amd) {
|
||||||
|
define(["jquery"], factory);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* jshint sub:true */
|
||||||
|
factory(jQuery);
|
||||||
|
}
|
||||||
|
})(function ($) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
/* CODE */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery plugin for Sortable
|
||||||
|
* @param {Object|String} options
|
||||||
|
* @param {..*} [args]
|
||||||
|
* @returns {jQuery|*}
|
||||||
|
*/
|
||||||
|
$.fn.sortable = function (options) {
|
||||||
|
var retVal,
|
||||||
|
args = arguments;
|
||||||
|
|
||||||
|
this.each(function () {
|
||||||
|
var $el = $(this),
|
||||||
|
sortable = $el.data('sortable');
|
||||||
|
|
||||||
|
if (!sortable && (options instanceof Object || !options)) {
|
||||||
|
sortable = new Sortable(this, options);
|
||||||
|
$el.data('sortable', sortable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sortable) {
|
||||||
|
if (options === 'widget') {
|
||||||
|
return sortable;
|
||||||
|
}
|
||||||
|
else if (options === 'destroy') {
|
||||||
|
sortable.destroy();
|
||||||
|
$el.removeData('sortable');
|
||||||
|
}
|
||||||
|
else if (typeof sortable[options] === 'function') {
|
||||||
|
retVal = sortable[options].apply(sortable, [].slice.call(args, 1));
|
||||||
|
}
|
||||||
|
else if (options in sortable.options) {
|
||||||
|
retVal = sortable.option.apply(sortable, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (retVal === void 0) ? this : retVal;
|
||||||
|
};
|
||||||
|
});
|
182
dashboard-ui/bower_components/Sortable/knockout-sortable.js
vendored
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
(function (factory) {
|
||||||
|
"use strict";
|
||||||
|
if (typeof define === "function" && define.amd) {
|
||||||
|
// AMD anonymous module
|
||||||
|
define(["knockout"], factory);
|
||||||
|
} else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
|
||||||
|
// CommonJS module
|
||||||
|
var ko = require("knockout");
|
||||||
|
factory(ko);
|
||||||
|
} else {
|
||||||
|
// No module loader (plain <script> tag) - put directly in global namespace
|
||||||
|
factory(window.ko);
|
||||||
|
}
|
||||||
|
})(function (ko) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var init = function (element, valueAccessor, allBindings, viewModel, bindingContext, sortableOptions) {
|
||||||
|
|
||||||
|
var options = buildOptions(valueAccessor, sortableOptions);
|
||||||
|
|
||||||
|
//It's seems that we cannot update the eventhandlers after we've created the sortable, so define them in init instead of update
|
||||||
|
['onStart', 'onEnd', 'onRemove', 'onAdd', 'onUpdate', 'onSort', 'onFilter'].forEach(function (e) {
|
||||||
|
if (options[e] || eventHandlers[e])
|
||||||
|
options[e] = function (eventType, parentVM, parentBindings, handler, e) {
|
||||||
|
var itemVM = ko.dataFor(e.item),
|
||||||
|
//All of the bindings on the parent element
|
||||||
|
bindings = ko.utils.peekObservable(parentBindings()),
|
||||||
|
//The binding options for the draggable/sortable binding of the parent element
|
||||||
|
bindingHandlerBinding = bindings.sortable || bindings.draggable,
|
||||||
|
//The collection that we should modify
|
||||||
|
collection = bindingHandlerBinding.collection || bindingHandlerBinding.foreach;
|
||||||
|
if (handler)
|
||||||
|
handler(e, itemVM, parentVM, collection, bindings);
|
||||||
|
if (eventHandlers[eventType])
|
||||||
|
eventHandlers[eventType](e, itemVM, parentVM, collection, bindings);
|
||||||
|
}.bind(undefined, e, viewModel, allBindings, options[e]);
|
||||||
|
});
|
||||||
|
|
||||||
|
var sortableElement = Sortable.create(element, options);
|
||||||
|
|
||||||
|
//Destroy the sortable if knockout disposes the element it's connected to
|
||||||
|
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
|
||||||
|
sortableElement.destroy();
|
||||||
|
});
|
||||||
|
return ko.bindingHandlers.template.init(element, valueAccessor);
|
||||||
|
},
|
||||||
|
update = function (element, valueAccessor, allBindings, viewModel, bindingContext, sortableOptions) {
|
||||||
|
|
||||||
|
//There seems to be some problems with updating the options of a sortable
|
||||||
|
//Tested to change eventhandlers and the group options without any luck
|
||||||
|
|
||||||
|
return ko.bindingHandlers.template.update(element, valueAccessor, allBindings, viewModel, bindingContext);
|
||||||
|
},
|
||||||
|
eventHandlers = (function (handlers) {
|
||||||
|
|
||||||
|
var moveOperations = [],
|
||||||
|
tryMoveOperation = function (e, itemVM, parentVM, collection, parentBindings) {
|
||||||
|
//A move operation is the combination of a add and remove event, this is to make sure that we have both the target and origin collections
|
||||||
|
var currentOperation = { event: e, itemVM: itemVM, parentVM: parentVM, collection: collection, parentBindings: parentBindings },
|
||||||
|
existingOperation = moveOperations.filter(function (op) {
|
||||||
|
return op.itemVM === currentOperation.itemVM;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (!existingOperation) {
|
||||||
|
moveOperations.push(currentOperation);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//We're finishing the operation and already have a handle on the operation item meaning that it's safe to remove it
|
||||||
|
moveOperations.splice(moveOperations.indexOf(existingOperation), 1);
|
||||||
|
|
||||||
|
var removeOperation = currentOperation.event.type === 'remove' ? currentOperation : existingOperation,
|
||||||
|
addOperation = currentOperation.event.type === 'add' ? currentOperation : existingOperation;
|
||||||
|
|
||||||
|
moveItem(itemVM, removeOperation.collection, addOperation.collection, addOperation.event.clone, addOperation.event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//Moves an item from the to (collection to from (collection), these can be references to the same collection which means it's a sort,
|
||||||
|
//clone indicates if we should move or copy the item into the new collection
|
||||||
|
moveItem = function (itemVM, from, to, clone, e) {
|
||||||
|
//Unwrapping this allows us to manipulate the actual array
|
||||||
|
var fromArray = from(),
|
||||||
|
//It's not certain that the items actual index is the same as the index reported by sortable due to filtering etc.
|
||||||
|
originalIndex = fromArray.indexOf(itemVM),
|
||||||
|
newIndex = e.newIndex;
|
||||||
|
|
||||||
|
if (e.item.previousElementSibling)
|
||||||
|
{
|
||||||
|
newIndex = fromArray.indexOf(ko.dataFor(e.item.previousElementSibling));
|
||||||
|
if (originalIndex > newIndex)
|
||||||
|
newIndex = newIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove sortables "unbound" element
|
||||||
|
e.item.parentNode.removeChild(e.item);
|
||||||
|
|
||||||
|
//This splice is necessary for both clone and move/sort
|
||||||
|
//In sort/move since it shouldn't be at this index/in this array anymore
|
||||||
|
//In clone since we have to work around knockouts valuHasMutated when manipulating arrays and avoid a "unbound" item added by sortable
|
||||||
|
fromArray.splice(originalIndex, 1);
|
||||||
|
//Update the array, this will also remove sortables "unbound" clone
|
||||||
|
from.valueHasMutated();
|
||||||
|
if (clone && from !== to) {
|
||||||
|
//Readd the item
|
||||||
|
fromArray.splice(originalIndex, 0, itemVM);
|
||||||
|
//Force knockout to update
|
||||||
|
from.valueHasMutated();
|
||||||
|
}
|
||||||
|
//Insert the item on its new position
|
||||||
|
to().splice(newIndex, 0, itemVM);
|
||||||
|
//Make sure to tell knockout that we've modified the actual array.
|
||||||
|
to.valueHasMutated();
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers.onRemove = tryMoveOperation;
|
||||||
|
handlers.onAdd = tryMoveOperation;
|
||||||
|
handlers.onUpdate = function (e, itemVM, parentVM, collection, parentBindings) {
|
||||||
|
//This will be performed as a sort since the to/from collections reference the same collection and clone is set to false
|
||||||
|
moveItem(itemVM, collection, collection, false, e);
|
||||||
|
};
|
||||||
|
|
||||||
|
return handlers;
|
||||||
|
})({}),
|
||||||
|
//bindingOptions are the options set in the "data-bind" attribute in the ui.
|
||||||
|
//options are custom options, for instance draggable/sortable specific options
|
||||||
|
buildOptions = function (bindingOptions, options) {
|
||||||
|
//deep clone/copy of properties from the "from" argument onto the "into" argument and returns the modified "into"
|
||||||
|
var merge = function (into, from) {
|
||||||
|
for (var prop in from) {
|
||||||
|
if (Object.prototype.toString.call(from[prop]) === '[object Object]') {
|
||||||
|
if (Object.prototype.toString.call(into[prop]) !== '[object Object]') {
|
||||||
|
into[prop] = {};
|
||||||
|
}
|
||||||
|
into[prop] = merge(into[prop], from[prop]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
into[prop] = from[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
return into;
|
||||||
|
},
|
||||||
|
//unwrap the supplied options
|
||||||
|
unwrappedOptions = ko.utils.peekObservable(bindingOptions()).options || {};
|
||||||
|
|
||||||
|
//Make sure that we don't modify the provided settings object
|
||||||
|
options = merge({}, options);
|
||||||
|
|
||||||
|
//group is handled differently since we should both allow to change a draggable to a sortable (and vice versa),
|
||||||
|
//but still be able to set a name on a draggable without it becoming a drop target.
|
||||||
|
if (unwrappedOptions.group && Object.prototype.toString.call(unwrappedOptions.group) !== '[object Object]') {
|
||||||
|
//group property is a name string declaration, convert to object.
|
||||||
|
unwrappedOptions.group = { name: unwrappedOptions.group };
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge(options, unwrappedOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
ko.bindingHandlers.draggable = {
|
||||||
|
sortableOptions: {
|
||||||
|
group: { pull: 'clone', put: false },
|
||||||
|
sort: false
|
||||||
|
},
|
||||||
|
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||||
|
return init(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.draggable.sortableOptions);
|
||||||
|
},
|
||||||
|
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||||
|
return update(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.draggable.sortableOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ko.bindingHandlers.sortable = {
|
||||||
|
sortableOptions: {
|
||||||
|
group: { pull: true, put: true }
|
||||||
|
},
|
||||||
|
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||||
|
return init(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.sortable.sortableOptions);
|
||||||
|
},
|
||||||
|
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||||
|
return update(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.sortable.sortableOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
34
dashboard-ui/bower_components/Sortable/meteor/.versions
vendored
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
base64@1.0.3
|
||||||
|
binary-heap@1.0.3
|
||||||
|
blaze@2.1.2
|
||||||
|
blaze-tools@1.0.3
|
||||||
|
callback-hook@1.0.3
|
||||||
|
check@1.0.5
|
||||||
|
dburles:mongo-collection-instances@0.3.4
|
||||||
|
ddp@1.1.0
|
||||||
|
deps@1.0.7
|
||||||
|
ejson@1.0.6
|
||||||
|
geojson-utils@1.0.3
|
||||||
|
html-tools@1.0.4
|
||||||
|
htmljs@1.0.4
|
||||||
|
id-map@1.0.3
|
||||||
|
jquery@1.11.3_2
|
||||||
|
json@1.0.3
|
||||||
|
lai:collection-extensions@0.1.4
|
||||||
|
local-test:rubaxa:sortable@1.2.1
|
||||||
|
logging@1.0.7
|
||||||
|
meteor@1.1.6
|
||||||
|
minifiers@1.1.5
|
||||||
|
minimongo@1.0.8
|
||||||
|
mongo@1.1.0
|
||||||
|
observe-sequence@1.0.6
|
||||||
|
ordered-dict@1.0.3
|
||||||
|
random@1.0.3
|
||||||
|
reactive-var@1.0.5
|
||||||
|
retry@1.0.3
|
||||||
|
rubaxa:sortable@1.2.1
|
||||||
|
spacebars-compiler@1.0.6
|
||||||
|
templating@1.1.1
|
||||||
|
tinytest@1.0.5
|
||||||
|
tracker@1.0.7
|
||||||
|
underscore@1.0.3
|
8
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/.finished-upgraders
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# This file contains information which helps Meteor properly upgrade your
|
||||||
|
# app when you run 'meteor update'. You should check it into version control
|
||||||
|
# with your project.
|
||||||
|
|
||||||
|
notices-for-0.9.0
|
||||||
|
notices-for-0.9.1
|
||||||
|
0.9.4-platform-file
|
||||||
|
notices-for-facebook-graph-api-2
|
1
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
local
|
7
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/.id
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file contains a token that is unique to your project.
|
||||||
|
# Check it into your repository along with the rest of this directory.
|
||||||
|
# It can be used for purposes such as:
|
||||||
|
# - ensuring you don't accidentally deploy one app on top of another
|
||||||
|
# - providing package authors with aggregated statistics
|
||||||
|
|
||||||
|
ir0jg2douy3yo5mehw
|
10
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/packages
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Meteor packages used by this project, one per line.
|
||||||
|
#
|
||||||
|
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||||
|
# but you can also edit it by hand.
|
||||||
|
|
||||||
|
meteor-platform
|
||||||
|
autopublish
|
||||||
|
insecure
|
||||||
|
rubaxa:sortable
|
||||||
|
fezvrasta:bootstrap-material-design
|
2
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/platforms
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
browser
|
||||||
|
server
|
1
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/release
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
METEOR@1.1.0.3
|
53
dashboard-ui/bower_components/Sortable/meteor/example/.meteor/versions
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
autopublish@1.0.3
|
||||||
|
autoupdate@1.2.1
|
||||||
|
base64@1.0.3
|
||||||
|
binary-heap@1.0.3
|
||||||
|
blaze@2.1.2
|
||||||
|
blaze-tools@1.0.3
|
||||||
|
boilerplate-generator@1.0.3
|
||||||
|
callback-hook@1.0.3
|
||||||
|
check@1.0.5
|
||||||
|
dburles:mongo-collection-instances@0.3.4
|
||||||
|
ddp@1.1.0
|
||||||
|
deps@1.0.7
|
||||||
|
ejson@1.0.6
|
||||||
|
fastclick@1.0.3
|
||||||
|
fezvrasta:bootstrap-material-design@0.3.0
|
||||||
|
geojson-utils@1.0.3
|
||||||
|
html-tools@1.0.4
|
||||||
|
htmljs@1.0.4
|
||||||
|
http@1.1.0
|
||||||
|
id-map@1.0.3
|
||||||
|
insecure@1.0.3
|
||||||
|
jquery@1.11.3_2
|
||||||
|
json@1.0.3
|
||||||
|
lai:collection-extensions@0.1.4
|
||||||
|
launch-screen@1.0.2
|
||||||
|
livedata@1.0.13
|
||||||
|
logging@1.0.7
|
||||||
|
meteor@1.1.6
|
||||||
|
meteor-platform@1.2.2
|
||||||
|
minifiers@1.1.5
|
||||||
|
minimongo@1.0.8
|
||||||
|
mobile-status-bar@1.0.3
|
||||||
|
mongo@1.1.0
|
||||||
|
observe-sequence@1.0.6
|
||||||
|
ordered-dict@1.0.3
|
||||||
|
random@1.0.3
|
||||||
|
reactive-dict@1.1.0
|
||||||
|
reactive-var@1.0.5
|
||||||
|
reload@1.1.3
|
||||||
|
retry@1.0.3
|
||||||
|
routepolicy@1.0.5
|
||||||
|
rubaxa:sortable@1.2.1
|
||||||
|
session@1.1.0
|
||||||
|
spacebars@1.0.6
|
||||||
|
spacebars-compiler@1.0.6
|
||||||
|
templating@1.1.1
|
||||||
|
tracker@1.0.7
|
||||||
|
twbs:bootstrap@3.3.5
|
||||||
|
ui@1.0.6
|
||||||
|
underscore@1.0.3
|
||||||
|
url@1.0.4
|
||||||
|
webapp@1.2.0
|
||||||
|
webapp-hashing@1.0.3
|
57
dashboard-ui/bower_components/Sortable/meteor/example/client/define-object-type.css
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
.glyphicon {
|
||||||
|
vertical-align: baseline;
|
||||||
|
font-size: 80%;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^="mdi-"], [class*=" mdi-"] {
|
||||||
|
vertical-align: baseline;
|
||||||
|
font-size: 90%;
|
||||||
|
margin-right: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-pair {
|
||||||
|
display: flex; /* use the flexbox model */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.sortable {
|
||||||
|
/* font-size: 2em;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable.source {
|
||||||
|
/*background: #9FA8DA;*/
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-right: 1em;
|
||||||
|
cursor: move;
|
||||||
|
cursor: -webkit-grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable.target {
|
||||||
|
/*background: #3F51B5;*/
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target .well {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-handle {
|
||||||
|
cursor: move;
|
||||||
|
cursor: -webkit-grabbing;
|
||||||
|
}
|
||||||
|
.sortable-handle.pull-right {
|
||||||
|
margin-top: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-ghost {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show the remove button on hover */
|
||||||
|
.removable .close {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.removable:hover .close {
|
||||||
|
display: block;
|
||||||
|
}
|
94
dashboard-ui/bower_components/Sortable/meteor/example/client/define-object-type.html
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<head>
|
||||||
|
<title>Reactive RubaXa:Sortable for Meteor</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{{> navbar}}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>RubaXa:Sortable - reactive reorderable lists for Meteor</h1>
|
||||||
|
<h2>Drag attribute types from the left to define an object type on the right</h2>
|
||||||
|
<h3>Drag the <i class="sortable-handle mdi-action-view-headline"></i> handle to reorder elements</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{> typeDefinition}}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<template name="typeDefinition">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="list-pair col-sm-12">
|
||||||
|
|
||||||
|
<div class="sortable source list-group" id="types">
|
||||||
|
{{#sortable items=types options=typesOptions}}
|
||||||
|
<div class="list-group-item well well-sm">
|
||||||
|
{{{icon}}} {{name}}
|
||||||
|
</div>
|
||||||
|
{{/sortable}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sortable target" id="object">
|
||||||
|
{{#sortable items=attributes animation="100" handle=".sortable-handle" ghostClass="sortable-ghost" options=attributesOptions}}
|
||||||
|
{{> sortableItemTarget}}
|
||||||
|
{{/sortable}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="sortableItemTarget">
|
||||||
|
<div data-id="{{order}}" class="sortable-item removable well well-sm">
|
||||||
|
{{{icon}}}
|
||||||
|
<i class="sortable-handle mdi-action-view-headline pull-right"></i>
|
||||||
|
<span class="name">{{name}}</span>
|
||||||
|
<span class="badge">{{order}}</span>
|
||||||
|
<button type="button" class="close" data-dismiss="alert">
|
||||||
|
<span aria-hidden="true">×</span><span class="sr-only">Close</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template name="navbar">
|
||||||
|
<div class="navbar navbar-inverse">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-inverse-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="https://atmospherejs.com/rubaxa/sortable">RubaXa:Sortable</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse navbar-inverse-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li class="active"><a href="http://rubaxa-sortable.meteor.com">Meteor Demo</a></li>
|
||||||
|
<li><a href="https://rubaxa.github.io/Sortable/" target="_blank">Sortable standalone demo</a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Source <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li class="dropdown-header">GitHub</li>
|
||||||
|
<li><a href="https://github.com/RubaXa/Sortable/tree/dev/meteor/example" target="_blank">This demo</a></li>
|
||||||
|
<li><a href="https://github.com/RubaXa/Sortable/tree/dev/meteor" target="_blank">Meteor integration</a></li>
|
||||||
|
<li><a href="https://github.com/RubaXa/Sortable" target="_blank">rubaxa/sortable</a></li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li><a href="https://atmospherejs.com/rubaxa/sortable">Star this package on Atmosphere!</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<li class="dropdown">
|
||||||
|
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Resources <b class="caret"></b></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="http://www.meteorpedia.com/read/Packaging_existing_Libraries">Packaging 3rd party libraries for Meteor</a></li>
|
||||||
|
<li><a href="https://twitter.com/dandv">Author: @dandv</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
101
dashboard-ui/bower_components/Sortable/meteor/example/client/define-object-type.js
vendored
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// Define an object type by dragging together attributes
|
||||||
|
|
||||||
|
Template.typeDefinition.helpers({
|
||||||
|
types: function () {
|
||||||
|
return Types.find({}, { sort: { order: 1 } });
|
||||||
|
},
|
||||||
|
typesOptions: {
|
||||||
|
sortField: 'order', // defaults to 'order' anyway
|
||||||
|
group: {
|
||||||
|
name: 'typeDefinition',
|
||||||
|
pull: 'clone',
|
||||||
|
put: false
|
||||||
|
},
|
||||||
|
sort: false // don't allow reordering the types, just the attributes below
|
||||||
|
},
|
||||||
|
|
||||||
|
attributes: function () {
|
||||||
|
return Attributes.find({}, {
|
||||||
|
sort: { order: 1 },
|
||||||
|
transform: function (doc) {
|
||||||
|
doc.icon = Types.findOne({name: doc.type}).icon;
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
attributesOptions: {
|
||||||
|
group: {
|
||||||
|
name: 'typeDefinition',
|
||||||
|
put: true
|
||||||
|
},
|
||||||
|
onAdd: function (event) {
|
||||||
|
delete event.data._id; // Generate a new id when inserting in the Attributes collection. Otherwise, if we add the same type twice, we'll get an error that the ids are not unique.
|
||||||
|
delete event.data.icon;
|
||||||
|
event.data.type = event.data.name;
|
||||||
|
event.data.name = 'Rename me (double click)'
|
||||||
|
},
|
||||||
|
// event handler for reordering attributes
|
||||||
|
onSort: function (event) {
|
||||||
|
console.log('Item %s went from #%d to #%d',
|
||||||
|
event.data.name, event.oldIndex, event.newIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.sortableItemTarget.events({
|
||||||
|
'dblclick .name': function (event, template) {
|
||||||
|
// Make the name editable. We should use an existing component, but it's
|
||||||
|
// in a sorry state - https://github.com/arillo/meteor-x-editable/issues/1
|
||||||
|
var name = template.$('.name');
|
||||||
|
var input = template.$('input');
|
||||||
|
if (input.length) { // jQuery never returns null - http://stackoverflow.com/questions/920236/how-can-i-detect-if-a-selector-returns-null
|
||||||
|
input.show();
|
||||||
|
} else {
|
||||||
|
input = $('<input class="form-control" type="text" placeholder="' + this.name + '" style="display: inline">');
|
||||||
|
name.after(input);
|
||||||
|
}
|
||||||
|
name.hide();
|
||||||
|
input.focus();
|
||||||
|
},
|
||||||
|
'blur input[type=text]': function (event, template) {
|
||||||
|
// commit the change to the name, if any
|
||||||
|
var input = template.$('input');
|
||||||
|
input.hide();
|
||||||
|
template.$('.name').show();
|
||||||
|
// TODO - what is the collection here? We'll hard-code for now.
|
||||||
|
// https://github.com/meteor/meteor/issues/3303
|
||||||
|
if (this.name !== input.val() && this.name !== '')
|
||||||
|
Attributes.update(this._id, {$set: {name: input.val()}});
|
||||||
|
},
|
||||||
|
'keydown input[type=text]': function (event, template) {
|
||||||
|
if (event.which === 27) {
|
||||||
|
// ESC - discard edits and keep existing value
|
||||||
|
template.$('input').val(this.name);
|
||||||
|
event.preventDefault();
|
||||||
|
event.target.blur();
|
||||||
|
} else if (event.which === 13) {
|
||||||
|
// ENTER
|
||||||
|
event.preventDefault();
|
||||||
|
event.target.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// you can add events to all Sortable template instances
|
||||||
|
Template.sortable.events({
|
||||||
|
'click .close': function (event, template) {
|
||||||
|
// `this` is the data context set by the enclosing block helper (#each, here)
|
||||||
|
template.collection.remove(this._id);
|
||||||
|
// custom code, working on a specific collection
|
||||||
|
if (Attributes.find().count() === 0) {
|
||||||
|
Meteor.setTimeout(function () {
|
||||||
|
Attributes.insert({
|
||||||
|
name: 'Not nice to delete the entire list! Add some attributes instead.',
|
||||||
|
type: 'String',
|
||||||
|
order: 0
|
||||||
|
})
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
2
dashboard-ui/bower_components/Sortable/meteor/example/model.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Types = new Mongo.Collection('types');
|
||||||
|
Attributes = new Mongo.Collection('attributes');
|
7
dashboard-ui/bower_components/Sortable/meteor/example/run.bat
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
@echo off
|
||||||
|
REM Sanity check: make sure we're in the directory of the script
|
||||||
|
set DIR=%~dp0
|
||||||
|
cd %DIR%
|
||||||
|
|
||||||
|
set PACKAGE_DIRS=..\..\
|
||||||
|
meteor run %*
|
5
dashboard-ui/bower_components/Sortable/meteor/example/run.sh
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# sanity check: make sure we're in the root directory of the example
|
||||||
|
cd "$( dirname "$0" )"
|
||||||
|
|
||||||
|
# let Meteor find the local package
|
||||||
|
PACKAGE_DIRS=../../ meteor run "$@"
|
75
dashboard-ui/bower_components/Sortable/meteor/example/server/fixtures.js
vendored
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
Meteor.startup(function () {
|
||||||
|
if (Types.find().count() === 0) {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'String',
|
||||||
|
icon: '<span class="glyphicon glyphicon-tag" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Text, multi-line',
|
||||||
|
icon: '<i class="mdi-communication-message" aria-hidden="true"></i>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Category',
|
||||||
|
icon: '<span class="glyphicon glyphicon-list" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Number',
|
||||||
|
icon: '<i class="mdi-image-looks-one" aria-hidden="true"></i>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Date',
|
||||||
|
icon: '<span class="glyphicon glyphicon-calendar" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hyperlink',
|
||||||
|
icon: '<span class="glyphicon glyphicon-link" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Image',
|
||||||
|
icon: '<span class="glyphicon glyphicon-picture" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Progress',
|
||||||
|
icon: '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
icon: '<span class="glyphicon glyphicon-time" aria-hidden="true"></span>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Map address',
|
||||||
|
icon: '<i class="mdi-maps-place" aria-hidden="true"></i>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Relationship',
|
||||||
|
icon: '<span class="glyphicon glyphicon-flash" aria-hidden="true"></span>'
|
||||||
|
}
|
||||||
|
].forEach(function (type, i) {
|
||||||
|
Types.insert({
|
||||||
|
name: type.name,
|
||||||
|
icon: type.icon,
|
||||||
|
order: i
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log('Initialized attribute types.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Attributes.find().count() === 0) {
|
||||||
|
[
|
||||||
|
{ name: 'Name', type: 'String' },
|
||||||
|
{ name: 'Created at', type: 'Date' },
|
||||||
|
{ name: 'Link', type: 'Hyperlink' },
|
||||||
|
{ name: 'Owner', type: 'Relationship' }
|
||||||
|
].forEach(function (attribute, i) {
|
||||||
|
Attributes.insert({
|
||||||
|
name: attribute.name,
|
||||||
|
type: attribute.type,
|
||||||
|
order: i
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log('Created sample object type.');
|
||||||
|
}
|
||||||
|
});
|
3
dashboard-ui/bower_components/Sortable/meteor/example/server/sortable-collections.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Sortable.collections = ['attributes'];
|
16
dashboard-ui/bower_components/Sortable/meteor/methods-client.js
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
/**
|
||||||
|
* Update the sortField of documents with given ids in a collection, incrementing it by incDec
|
||||||
|
* @param {String} collectionName - name of the collection to update
|
||||||
|
* @param {String[]} ids - array of document ids
|
||||||
|
* @param {String} orderField - the name of the order field, usually "order"
|
||||||
|
* @param {Number} incDec - pass 1 or -1
|
||||||
|
*/
|
||||||
|
'rubaxa:sortable/collection-update': function (collectionName, ids, sortField, incDec) {
|
||||||
|
var selector = {_id: {$in: ids}}, modifier = {$inc: {}};
|
||||||
|
modifier.$inc[sortField] = incDec;
|
||||||
|
Mongo.Collection.get(collectionName).update(selector, modifier, {multi: true});
|
||||||
|
}
|
||||||
|
});
|
31
dashboard-ui/bower_components/Sortable/meteor/methods-server.js
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Sortable = {};
|
||||||
|
Sortable.collections = []; // array of collection names that the client is allowed to reorder
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
/**
|
||||||
|
* Update the sortField of documents with given ids in a collection, incrementing it by incDec
|
||||||
|
* @param {String} collectionName - name of the collection to update
|
||||||
|
* @param {String[]} ids - array of document ids
|
||||||
|
* @param {String} orderField - the name of the order field, usually "order"
|
||||||
|
* @param {Number} incDec - pass 1 or -1
|
||||||
|
*/
|
||||||
|
'rubaxa:sortable/collection-update': function (collectionName, ids, sortField, incDec) {
|
||||||
|
check(collectionName, String);
|
||||||
|
// don't allow the client to modify just any collection
|
||||||
|
if (!Sortable || !Array.isArray(Sortable.collections)) {
|
||||||
|
throw new Meteor.Error(500, 'Please define Sortable.collections');
|
||||||
|
}
|
||||||
|
if (Sortable.collections.indexOf(collectionName) === -1) {
|
||||||
|
throw new Meteor.Error(403, 'Collection <' + collectionName + '> is not Sortable. Please add it to Sortable.collections in server code.');
|
||||||
|
}
|
||||||
|
|
||||||
|
check(ids, [String]);
|
||||||
|
check(sortField, String);
|
||||||
|
check(incDec, Number);
|
||||||
|
var selector = {_id: {$in: ids}}, modifier = {$inc: {}};
|
||||||
|
modifier.$inc[sortField] = incDec;
|
||||||
|
Mongo.Collection.get(collectionName).update(selector, modifier, {multi: true});
|
||||||
|
}
|
||||||
|
});
|
85
dashboard-ui/bower_components/Sortable/meteor/package.js
vendored
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// Package metadata file for Meteor.js
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var packageName = 'rubaxa:sortable'; // https://atmospherejs.com/rubaxa/sortable
|
||||||
|
var gitHubPath = 'RubaXa/Sortable'; // https://github.com/RubaXa/Sortable
|
||||||
|
var npmPackageName = 'sortablejs'; // https://www.npmjs.com/package/sortablejs - optional but recommended; used as fallback if GitHub fails
|
||||||
|
|
||||||
|
/* All of the below is just to get the version number of the 3rd party library.
|
||||||
|
* First we'll try to read it from package.json. This works when publishing or testing the package
|
||||||
|
* but not when running an example app that uses a local copy of the package because the current
|
||||||
|
* directory will be that of the app, and it won't have package.json. Finding the path of a file is hard:
|
||||||
|
* http://stackoverflow.com/questions/27435797/how-do-i-obtain-the-path-of-a-file-in-a-meteor-package
|
||||||
|
* Therefore, we'll fall back to GitHub (which is more frequently updated), and then to NPMJS.
|
||||||
|
* We also don't have the HTTP package at this stage, and if we use Package.* in the request() callback,
|
||||||
|
* it will error that it must be run in a Fiber. So we'll use Node futures.
|
||||||
|
*/
|
||||||
|
var request = Npm.require('request');
|
||||||
|
var Future = Npm.require('fibers/future');
|
||||||
|
|
||||||
|
var fut = new Future;
|
||||||
|
var version;
|
||||||
|
|
||||||
|
if (!version) try {
|
||||||
|
var packageJson = JSON.parse(Npm.require('fs').readFileSync('../package.json'));
|
||||||
|
version = packageJson.version;
|
||||||
|
} catch (e) {
|
||||||
|
// if the file was not found, fall back to GitHub
|
||||||
|
console.warn('Could not find ../package.json to read version number from; trying GitHub...');
|
||||||
|
var url = 'https://api.github.com/repos/' + gitHubPath + '/tags';
|
||||||
|
request.get({
|
||||||
|
url: url,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'request' // GitHub requires it
|
||||||
|
}
|
||||||
|
}, function (error, response, body) {
|
||||||
|
if (!error && response.statusCode === 200) {
|
||||||
|
var versions = JSON.parse(body).map(function (version) {
|
||||||
|
return version['name'].replace(/^\D+/, '') // trim leading non-digits from e.g. "v4.3.0"
|
||||||
|
}).sort();
|
||||||
|
fut.return(versions[versions.length -1]);
|
||||||
|
} else {
|
||||||
|
// GitHub API rate limit reached? Fall back to npmjs.
|
||||||
|
console.warn('GitHub request to', url, 'failed:\n ', response && response.statusCode, response && response.body, error || '', '\nTrying NPMJS...');
|
||||||
|
url = 'http://registry.npmjs.org/' + npmPackageName + '/latest';
|
||||||
|
request.get(url, function (error, response, body) {
|
||||||
|
if (!error && response.statusCode === 200)
|
||||||
|
fut.return(JSON.parse(body).version);
|
||||||
|
else
|
||||||
|
fut.throw('Could not get version information from ' + url + ' either (incorrect package name?):\n' + (response && response.statusCode || '') + (response && response.body || '') + (error || ''));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
version = fut.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we finally have an accurate version number...
|
||||||
|
Package.describe({
|
||||||
|
name: packageName,
|
||||||
|
summary: 'Sortable: reactive minimalist reorderable drag-and-drop lists on modern browsers and touch devices',
|
||||||
|
version: version,
|
||||||
|
git: 'https://github.com/RubaXa/Sortable.git',
|
||||||
|
documentation: 'README.md'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onUse(function (api) {
|
||||||
|
api.versionsFrom(['METEOR@0.9.0', 'METEOR@1.0']);
|
||||||
|
api.use('templating', 'client');
|
||||||
|
api.use('dburles:mongo-collection-instances@0.3.4'); // to watch collections getting created
|
||||||
|
api.export('Sortable'); // exported on the server too, as a global to hold the array of sortable collections (for security)
|
||||||
|
api.addFiles([
|
||||||
|
'../Sortable.js',
|
||||||
|
'template.html', // the HTML comes first, so reactivize.js can refer to the template in it
|
||||||
|
'reactivize.js'
|
||||||
|
], 'client');
|
||||||
|
api.addFiles('methods-client.js', 'client');
|
||||||
|
api.addFiles('methods-server.js', 'server');
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onTest(function (api) {
|
||||||
|
api.use(packageName, 'client');
|
||||||
|
api.use('tinytest', 'client');
|
||||||
|
|
||||||
|
api.addFiles('test.js', 'client');
|
||||||
|
});
|
26
dashboard-ui/bower_components/Sortable/meteor/publish.sh
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Publish package to Meteor's repository, Atmospherejs.com
|
||||||
|
|
||||||
|
# Make sure Meteor is installed, per https://www.meteor.com/install.
|
||||||
|
# The curl'ed script is totally safe; takes 2 minutes to read its source and check.
|
||||||
|
type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }
|
||||||
|
|
||||||
|
# sanity check: make sure we're in the directory of the script
|
||||||
|
cd "$( dirname "$0" )"
|
||||||
|
|
||||||
|
# publish package, creating it if it's the first time we're publishing
|
||||||
|
PACKAGE_NAME=$(grep -i name package.js | head -1 | cut -d "'" -f 2)
|
||||||
|
|
||||||
|
echo "Publishing $PACKAGE_NAME..."
|
||||||
|
|
||||||
|
# Attempt to re-publish the package - the most common operation once the initial release has
|
||||||
|
# been made. If the package name was changed (rare), you'll have to pass the --create flag.
|
||||||
|
meteor publish "$@"; EXIT_CODE=$?
|
||||||
|
if (( $EXIT_CODE == 0 )); then
|
||||||
|
echo "Thanks for releasing a new version. You can see it at"
|
||||||
|
echo "https://atmospherejs.com/${PACKAGE_NAME/://}"
|
||||||
|
else
|
||||||
|
echo "We have an error. Please post it at https://github.com/RubaXa/Sortable/issues"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $EXIT_CODE
|
201
dashboard-ui/bower_components/Sortable/meteor/reactivize.js
vendored
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
Make a Sortable reactive by binding it to a Mongo.Collection.
|
||||||
|
Calls `rubaxa:sortable/collection-update` on the server to update the sortField of affected records.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* supply consecutive values if the `order` field doesn't have any
|
||||||
|
* .get(DOMElement) - return the Sortable object of a DOMElement
|
||||||
|
* create a new _id automatically onAdd if the event.from list had pull: 'clone'
|
||||||
|
* support arrays
|
||||||
|
* sparse arrays
|
||||||
|
* tests
|
||||||
|
* drop onto existing empty lists
|
||||||
|
* insert back into lists emptied by dropping
|
||||||
|
* performance on dragging into long list at the beginning
|
||||||
|
* handle failures on Collection operations, e.g. add callback to .insert
|
||||||
|
* when adding elements, update ranks just for the half closer to the start/end of the list
|
||||||
|
* revisit http://programmers.stackexchange.com/questions/266451/maintain-ordered-collection-by-updating-as-few-order-fields-as-possible
|
||||||
|
* reproduce the insidious bug where the list isn't always sorted (fiddle with dragging #1 over #2, then back, then #N before #1)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Template.sortable.created = function () {
|
||||||
|
var templateInstance = this;
|
||||||
|
// `this` is a template instance that can store properties of our choice - http://docs.meteor.com/#/full/template_inst
|
||||||
|
if (templateInstance.setupDone) return; // paranoid: only run setup once
|
||||||
|
// this.data is the data context - http://docs.meteor.com/#/full/template_data
|
||||||
|
// normalize all options into templateInstance.options, and remove them from .data
|
||||||
|
templateInstance.options = templateInstance.data.options || {};
|
||||||
|
Object.keys(templateInstance.data).forEach(function (key) {
|
||||||
|
if (key === 'options' || key === 'items') return;
|
||||||
|
templateInstance.options[key] = templateInstance.data[key];
|
||||||
|
delete templateInstance.data[key];
|
||||||
|
});
|
||||||
|
templateInstance.options.sortField = templateInstance.options.sortField || 'order';
|
||||||
|
// We can get the collection via the .collection property of the cursor, but changes made that way
|
||||||
|
// will NOT be sent to the server - https://github.com/meteor/meteor/issues/3271#issuecomment-66656257
|
||||||
|
// Thus we need to use dburles:mongo-collection-instances to get a *real* collection
|
||||||
|
if (templateInstance.data.items && templateInstance.data.items.collection) {
|
||||||
|
// cursor passed via items=; its .collection works client-only and has a .name property
|
||||||
|
templateInstance.collectionName = templateInstance.data.items.collection.name;
|
||||||
|
templateInstance.collection = Mongo.Collection.get(templateInstance.collectionName);
|
||||||
|
} else if (templateInstance.data.items) {
|
||||||
|
// collection passed via items=; does NOT have a .name property, but _name
|
||||||
|
templateInstance.collection = templateInstance.data.items;
|
||||||
|
templateInstance.collectionName = templateInstance.collection._name;
|
||||||
|
} else if (templateInstance.data.collection) {
|
||||||
|
// cursor passed directly
|
||||||
|
templateInstance.collectionName = templateInstance.data.collection.name;
|
||||||
|
templateInstance.collection = Mongo.Collection.get(templateInstance.collectionName);
|
||||||
|
} else {
|
||||||
|
templateInstance.collection = templateInstance.data; // collection passed directly
|
||||||
|
templateInstance.collectionName = templateInstance.collection._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO if (Array.isArray(templateInstance.collection))
|
||||||
|
|
||||||
|
// What if user filters some of the items in the cursor, instead of ordering the entire collection?
|
||||||
|
// Use case: reorder by preference movies of a given genre, a filter within all movies.
|
||||||
|
// A: Modify all intervening items **that are on the client**, to preserve the overall order
|
||||||
|
// TODO: update *all* orders via a server method that takes not ids, but start & end elements - mild security risk
|
||||||
|
delete templateInstance.data.options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an element was moved, adjust its orders and possibly the order of
|
||||||
|
* other elements, so as to maintain a consistent and correct order.
|
||||||
|
*
|
||||||
|
* There are three approaches to this:
|
||||||
|
* 1) Using arbitrary precision arithmetic and setting only the order of the moved
|
||||||
|
* element to the average of the orders of the elements around it -
|
||||||
|
* http://programmers.stackexchange.com/questions/266451/maintain-ordered-collection-by-updating-as-few-order-fields-as-possible
|
||||||
|
* The downside is that the order field in the DB will increase by one byte every
|
||||||
|
* time an element is reordered.
|
||||||
|
* 2) Adjust the orders of the intervening items. This keeps the orders sane (integers)
|
||||||
|
* but is slower because we have to modify multiple documents.
|
||||||
|
* TODO: we may be able to update fewer records by only altering the
|
||||||
|
* order of the records between the newIndex/oldIndex and the start/end of the list.
|
||||||
|
* 3) Use regular precision arithmetic, but when the difference between the orders of the
|
||||||
|
* moved item and the one before/after it falls below a certain threshold, adjust
|
||||||
|
* the order of that other item, and cascade doing so up or down the list.
|
||||||
|
* This will keep the `order` field constant in size, and will only occasionally
|
||||||
|
* require updating the `order` of other records.
|
||||||
|
*
|
||||||
|
* For now, we use approach #2.
|
||||||
|
*
|
||||||
|
* @param {String} itemId - the _id of the item that was moved
|
||||||
|
* @param {Number} orderPrevItem - the order of the item before it, or null
|
||||||
|
* @param {Number} orderNextItem - the order of the item after it, or null
|
||||||
|
*/
|
||||||
|
templateInstance.adjustOrders = function adjustOrders(itemId, orderPrevItem, orderNextItem) {
|
||||||
|
var orderField = templateInstance.options.sortField;
|
||||||
|
var selector = templateInstance.options.selector || {}, modifier = {$set: {}};
|
||||||
|
var ids = [];
|
||||||
|
var startOrder = templateInstance.collection.findOne(itemId)[orderField];
|
||||||
|
if (orderPrevItem !== null) {
|
||||||
|
// Element has a previous sibling, therefore it was moved down in the list.
|
||||||
|
// Decrease the order of intervening elements.
|
||||||
|
selector[orderField] = {$lte: orderPrevItem, $gt: startOrder};
|
||||||
|
ids = _.pluck(templateInstance.collection.find(selector, {fields: {_id: 1}}).fetch(), '_id');
|
||||||
|
Meteor.call('rubaxa:sortable/collection-update', templateInstance.collectionName, ids, orderField, -1);
|
||||||
|
|
||||||
|
// Set the order of the dropped element to the order of its predecessor, whose order was decreased
|
||||||
|
modifier.$set[orderField] = orderPrevItem;
|
||||||
|
} else {
|
||||||
|
// element moved up the list, increase order of intervening elements
|
||||||
|
selector[orderField] = {$gte: orderNextItem, $lt: startOrder};
|
||||||
|
ids = _.pluck(templateInstance.collection.find(selector, {fields: {_id: 1}}).fetch(), '_id');
|
||||||
|
Meteor.call('rubaxa:sortable/collection-update', templateInstance.collectionName, ids, orderField, 1);
|
||||||
|
|
||||||
|
// Set the order of the dropped element to the order of its successor, whose order was increased
|
||||||
|
modifier.$set[orderField] = orderNextItem;
|
||||||
|
}
|
||||||
|
templateInstance.collection.update(itemId, modifier);
|
||||||
|
};
|
||||||
|
|
||||||
|
templateInstance.setupDone = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Template.sortable.rendered = function () {
|
||||||
|
var templateInstance = this;
|
||||||
|
var orderField = templateInstance.options.sortField;
|
||||||
|
|
||||||
|
// sorting was changed within the list
|
||||||
|
var optionsOnUpdate = templateInstance.options.onUpdate;
|
||||||
|
templateInstance.options.onUpdate = function sortableUpdate(/**Event*/event) {
|
||||||
|
var itemEl = event.item; // dragged HTMLElement
|
||||||
|
event.data = Blaze.getData(itemEl);
|
||||||
|
if (event.newIndex < event.oldIndex) {
|
||||||
|
// Element moved up in the list. The dropped element has a next sibling for sure.
|
||||||
|
var orderNextItem = Blaze.getData(itemEl.nextElementSibling)[orderField];
|
||||||
|
templateInstance.adjustOrders(event.data._id, null, orderNextItem);
|
||||||
|
} else if (event.newIndex > event.oldIndex) {
|
||||||
|
// Element moved down in the list. The dropped element has a previous sibling for sure.
|
||||||
|
var orderPrevItem = Blaze.getData(itemEl.previousElementSibling)[orderField];
|
||||||
|
templateInstance.adjustOrders(event.data._id, orderPrevItem, null);
|
||||||
|
} else {
|
||||||
|
// do nothing - drag and drop in the same location
|
||||||
|
}
|
||||||
|
if (optionsOnUpdate) optionsOnUpdate(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
// element was added from another list
|
||||||
|
var optionsOnAdd = templateInstance.options.onAdd;
|
||||||
|
templateInstance.options.onAdd = function sortableAdd(/**Event*/event) {
|
||||||
|
var itemEl = event.item; // dragged HTMLElement
|
||||||
|
event.data = Blaze.getData(itemEl);
|
||||||
|
// let the user decorate the object with additional properties before insertion
|
||||||
|
if (optionsOnAdd) optionsOnAdd(event);
|
||||||
|
|
||||||
|
// Insert the new element at the end of the list and move it where it was dropped.
|
||||||
|
// We could insert it at the beginning, but that would lead to negative orders.
|
||||||
|
var sortSpecifier = {}; sortSpecifier[orderField] = -1;
|
||||||
|
event.data.order = templateInstance.collection.findOne({}, { sort: sortSpecifier, limit: 1 }).order + 1;
|
||||||
|
// TODO: this can obviously be optimized by setting the order directly as the arithmetic average, with the caveats described above
|
||||||
|
var newElementId = templateInstance.collection.insert(event.data);
|
||||||
|
event.data._id = newElementId;
|
||||||
|
if (itemEl.nextElementSibling) {
|
||||||
|
var orderNextItem = Blaze.getData(itemEl.nextElementSibling)[orderField];
|
||||||
|
templateInstance.adjustOrders(newElementId, null, orderNextItem);
|
||||||
|
} else {
|
||||||
|
// do nothing - inserted after the last element
|
||||||
|
}
|
||||||
|
// remove the dropped HTMLElement from the list because we have inserted it in the collection, which will update the template
|
||||||
|
itemEl.parentElement.removeChild(itemEl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// element was removed by dragging into another list
|
||||||
|
var optionsOnRemove = templateInstance.options.onRemove;
|
||||||
|
templateInstance.options.onRemove = function sortableRemove(/**Event*/event) {
|
||||||
|
var itemEl = event.item; // dragged HTMLElement
|
||||||
|
event.data = Blaze.getData(itemEl);
|
||||||
|
// don't remove from the collection if group.pull is clone or false
|
||||||
|
if (typeof templateInstance.options.group === 'undefined'
|
||||||
|
|| typeof templateInstance.options.group.pull === 'undefined'
|
||||||
|
|| templateInstance.options.group.pull === true
|
||||||
|
) templateInstance.collection.remove(event.data._id);
|
||||||
|
if (optionsOnRemove) optionsOnRemove(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
// just compute the `data` context
|
||||||
|
['onStart', 'onEnd', 'onSort', 'onFilter'].forEach(function (eventHandler) {
|
||||||
|
if (templateInstance.options[eventHandler]) {
|
||||||
|
var userEventHandler = templateInstance.options[eventHandler];
|
||||||
|
templateInstance.options[eventHandler] = function (/**Event*/event) {
|
||||||
|
var itemEl = event.item; // dragged HTMLElement
|
||||||
|
event.data = Blaze.getData(itemEl);
|
||||||
|
userEventHandler(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
templateInstance.sortable = Sortable.create(templateInstance.firstNode.parentElement, templateInstance.options);
|
||||||
|
// TODO make the object accessible, e.g. via Sortable.getSortableById() or some such
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Template.sortable.destroyed = function () {
|
||||||
|
if(this.sortable) this.sortable.destroy();
|
||||||
|
};
|
8
dashboard-ui/bower_components/Sortable/meteor/runtests.bat
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
@echo off
|
||||||
|
REM Test Meteor package before publishing to Atmospherejs.com
|
||||||
|
|
||||||
|
REM Sanity check: make sure we're in the directory of the script
|
||||||
|
set DIR=%~dp0
|
||||||
|
cd %DIR%
|
||||||
|
|
||||||
|
meteor test-packages ./ %*
|
35
dashboard-ui/bower_components/Sortable/meteor/runtests.sh
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Test Meteor package before publishing to Atmospherejs.com
|
||||||
|
|
||||||
|
# Make sure Meteor is installed, per https://www.meteor.com/install.
|
||||||
|
# The curl'ed script is totally safe; takes 2 minutes to read its source and check.
|
||||||
|
type meteor >/dev/null 2>&1 || { curl https://install.meteor.com/ | sh; }
|
||||||
|
|
||||||
|
# sanity check: make sure we're in the directory of the script
|
||||||
|
cd "$( dirname "$0" )"
|
||||||
|
|
||||||
|
|
||||||
|
# delete the temporary files even if Ctrl+C is pressed
|
||||||
|
int_trap() {
|
||||||
|
printf "\nTests interrupted. Cleaning up...\n\n"
|
||||||
|
}
|
||||||
|
trap int_trap INT
|
||||||
|
|
||||||
|
|
||||||
|
EXIT_CODE=0
|
||||||
|
|
||||||
|
PACKAGE_NAME=$(grep -i name package.js | head -1 | cut -d "'" -f 2)
|
||||||
|
|
||||||
|
echo "### Testing $PACKAGE_NAME..."
|
||||||
|
|
||||||
|
# provide an invalid MONGO_URL so Meteor doesn't bog us down with an empty Mongo database
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
# interpret any parameter to mean we want an interactive test
|
||||||
|
MONGO_URL=mongodb:// meteor test-packages ./
|
||||||
|
else
|
||||||
|
# automated/CI test with phantomjs
|
||||||
|
./node_modules/.bin/spacejam --mongo-url mongodb:// test-packages ./
|
||||||
|
EXIT_CODE=$(( $EXIT_CODE + $? ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $EXIT_CODE
|
5
dashboard-ui/bower_components/Sortable/meteor/template.html
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<template name="sortable">
|
||||||
|
{{#each items}}
|
||||||
|
{{> Template.contentBlock this}}
|
||||||
|
{{/each}}
|
||||||
|
</template>
|
9
dashboard-ui/bower_components/Sortable/meteor/test.js
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Tinytest.add('Sortable.is', function (test) {
|
||||||
|
var items = document.createElement('ul');
|
||||||
|
items.innerHTML = '<li data-id="one">item 1</li><li data-id="two">item 2</li><li data-id="three">item 3</li>';
|
||||||
|
var sortable = new Sortable(items);
|
||||||
|
test.instanceOf(sortable, Sortable, 'Instantiation OK');
|
||||||
|
test.length(sortable.toArray(), 3, 'Three elements');
|
||||||
|
});
|
191
dashboard-ui/bower_components/Sortable/ng-sortable.js
vendored
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/**
|
||||||
|
* @author RubaXa <trash@rubaxa.org>
|
||||||
|
* @licence MIT
|
||||||
|
*/
|
||||||
|
(function (factory) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['angular', './Sortable'], factory);
|
||||||
|
}
|
||||||
|
else if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
|
||||||
|
require('angular');
|
||||||
|
factory(angular, require('./Sortable'));
|
||||||
|
module.exports = 'ng-sortable';
|
||||||
|
}
|
||||||
|
else if (window.angular && window.Sortable) {
|
||||||
|
factory(angular, Sortable);
|
||||||
|
}
|
||||||
|
})(function (angular, Sortable) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ngSortEvent
|
||||||
|
* @property {*} model List item
|
||||||
|
* @property {Object|Array} models List of items
|
||||||
|
* @property {number} oldIndex before sort
|
||||||
|
* @property {number} newIndex after sort
|
||||||
|
*/
|
||||||
|
|
||||||
|
var expando = 'Sortable:ng-sortable';
|
||||||
|
|
||||||
|
angular.module('ng-sortable', [])
|
||||||
|
.constant('ngSortableVersion', '0.4.0')
|
||||||
|
.constant('ngSortableConfig', {})
|
||||||
|
.directive('ngSortable', ['$parse', 'ngSortableConfig', function ($parse, ngSortableConfig) {
|
||||||
|
var removed,
|
||||||
|
nextSibling,
|
||||||
|
getSourceFactory = function getSourceFactory(el, scope) {
|
||||||
|
var ngRepeat = [].filter.call(el.childNodes, function (node) {
|
||||||
|
return (
|
||||||
|
(node.nodeType === 8) &&
|
||||||
|
(node.nodeValue.indexOf('ngRepeat:') !== -1)
|
||||||
|
);
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (!ngRepeat) {
|
||||||
|
// Without ng-repeat
|
||||||
|
return function () {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// tests: http://jsbin.com/kosubutilo/1/edit?js,output
|
||||||
|
ngRepeat = ngRepeat.nodeValue.match(/ngRepeat:\s*(?:\(.*?,\s*)?([^\s)]+)[\s)]+in\s+([^\s|]+)/);
|
||||||
|
|
||||||
|
var itemsExpr = $parse(ngRepeat[2]);
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
return itemsExpr(scope.$parent) || [];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Export
|
||||||
|
return {
|
||||||
|
restrict: 'AC',
|
||||||
|
scope: { ngSortable: "=?" },
|
||||||
|
link: function (scope, $el) {
|
||||||
|
var el = $el[0],
|
||||||
|
options = angular.extend(scope.ngSortable || {}, ngSortableConfig),
|
||||||
|
watchers = [],
|
||||||
|
getSource = getSourceFactory(el, scope),
|
||||||
|
sortable
|
||||||
|
;
|
||||||
|
|
||||||
|
el[expando] = getSource;
|
||||||
|
|
||||||
|
function _emitEvent(/**Event*/evt, /*Mixed*/item) {
|
||||||
|
var name = 'on' + evt.type.charAt(0).toUpperCase() + evt.type.substr(1);
|
||||||
|
var source = getSource();
|
||||||
|
|
||||||
|
/* jshint expr:true */
|
||||||
|
options[name] && options[name]({
|
||||||
|
model: item || source[evt.newIndex],
|
||||||
|
models: source,
|
||||||
|
oldIndex: evt.oldIndex,
|
||||||
|
newIndex: evt.newIndex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _sync(/**Event*/evt) {
|
||||||
|
var items = getSource();
|
||||||
|
|
||||||
|
if (!items) {
|
||||||
|
// Without ng-repeat
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldIndex = evt.oldIndex,
|
||||||
|
newIndex = evt.newIndex;
|
||||||
|
|
||||||
|
if (el !== evt.from) {
|
||||||
|
var prevItems = evt.from[expando]();
|
||||||
|
|
||||||
|
removed = prevItems[oldIndex];
|
||||||
|
|
||||||
|
if (evt.clone) {
|
||||||
|
removed = angular.copy(removed);
|
||||||
|
prevItems.splice(Sortable.utils.index(evt.clone), 0, prevItems.splice(oldIndex, 1)[0]);
|
||||||
|
evt.from.removeChild(evt.clone);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prevItems.splice(oldIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
items.splice(newIndex, 0, removed);
|
||||||
|
|
||||||
|
evt.from.insertBefore(evt.item, nextSibling); // revert element
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
items.splice(newIndex, 0, items.splice(oldIndex, 1)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.$apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sortable = Sortable.create(el, Object.keys(options).reduce(function (opts, name) {
|
||||||
|
opts[name] = opts[name] || options[name];
|
||||||
|
return opts;
|
||||||
|
}, {
|
||||||
|
onStart: function (/**Event*/evt) {
|
||||||
|
nextSibling = evt.item.nextSibling;
|
||||||
|
_emitEvent(evt);
|
||||||
|
scope.$apply();
|
||||||
|
},
|
||||||
|
onEnd: function (/**Event*/evt) {
|
||||||
|
_emitEvent(evt, removed);
|
||||||
|
scope.$apply();
|
||||||
|
},
|
||||||
|
onAdd: function (/**Event*/evt) {
|
||||||
|
_sync(evt);
|
||||||
|
_emitEvent(evt, removed);
|
||||||
|
scope.$apply();
|
||||||
|
},
|
||||||
|
onUpdate: function (/**Event*/evt) {
|
||||||
|
_sync(evt);
|
||||||
|
_emitEvent(evt);
|
||||||
|
},
|
||||||
|
onRemove: function (/**Event*/evt) {
|
||||||
|
_emitEvent(evt, removed);
|
||||||
|
},
|
||||||
|
onSort: function (/**Event*/evt) {
|
||||||
|
_emitEvent(evt);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
$el.on('$destroy', function () {
|
||||||
|
angular.forEach(watchers, function (/** Function */unwatch) {
|
||||||
|
unwatch();
|
||||||
|
});
|
||||||
|
|
||||||
|
sortable.destroy();
|
||||||
|
|
||||||
|
el[expando] = null;
|
||||||
|
el = null;
|
||||||
|
watchers = null;
|
||||||
|
sortable = null;
|
||||||
|
nextSibling = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
angular.forEach([
|
||||||
|
'sort', 'disabled', 'draggable', 'handle', 'animation', 'group', 'ghostClass', 'filter',
|
||||||
|
'onStart', 'onEnd', 'onAdd', 'onUpdate', 'onRemove', 'onSort'
|
||||||
|
], function (name) {
|
||||||
|
watchers.push(scope.$watch('ngSortable.' + name, function (value) {
|
||||||
|
if (value !== void 0) {
|
||||||
|
options[name] = value;
|
||||||
|
|
||||||
|
if (!/^on[A-Z]/.test(name)) {
|
||||||
|
sortable.option(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}]);
|
||||||
|
});
|
41
dashboard-ui/bower_components/Sortable/package.json
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "sortablejs",
|
||||||
|
"exportName": "Sortable",
|
||||||
|
"version": "1.4.2",
|
||||||
|
"devDependencies": {
|
||||||
|
"grunt": "*",
|
||||||
|
"grunt-version": "*",
|
||||||
|
"grunt-exec": "*",
|
||||||
|
"grunt-contrib-jshint": "0.9.2",
|
||||||
|
"grunt-contrib-uglify": "*",
|
||||||
|
"spacejam": "*"
|
||||||
|
},
|
||||||
|
"description": "Minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports AngularJS and any CSS library, e.g. Bootstrap.",
|
||||||
|
"main": "Sortable.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "grunt"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/rubaxa/Sortable.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"sortable",
|
||||||
|
"reorder",
|
||||||
|
"drag",
|
||||||
|
"meteor",
|
||||||
|
"angular",
|
||||||
|
"ng-sortable",
|
||||||
|
"react",
|
||||||
|
"mixin"
|
||||||
|
],
|
||||||
|
"author": "Konstantin Lebedev <ibnRubaXa@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"spm": {
|
||||||
|
"main": "Sortable.js",
|
||||||
|
"ignore": [
|
||||||
|
"meteor",
|
||||||
|
"st"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
165
dashboard-ui/bower_components/Sortable/react-sortable-mixin.js
vendored
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/**
|
||||||
|
* @author RubaXa <trash@rubaxa.org>
|
||||||
|
* @licence MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function (factory) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
|
||||||
|
module.exports = factory(require('./Sortable'));
|
||||||
|
}
|
||||||
|
else if (typeof define === 'function' && define.amd) {
|
||||||
|
define(['./Sortable'], factory);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* jshint sub:true */
|
||||||
|
window['SortableMixin'] = factory(Sortable);
|
||||||
|
}
|
||||||
|
})(function (/** Sortable */Sortable) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _nextSibling;
|
||||||
|
|
||||||
|
var _activeComponent;
|
||||||
|
|
||||||
|
var _defaultOptions = {
|
||||||
|
ref: 'list',
|
||||||
|
model: 'items',
|
||||||
|
|
||||||
|
animation: 100,
|
||||||
|
onStart: 'handleStart',
|
||||||
|
onEnd: 'handleEnd',
|
||||||
|
onAdd: 'handleAdd',
|
||||||
|
onUpdate: 'handleUpdate',
|
||||||
|
onRemove: 'handleRemove',
|
||||||
|
onSort: 'handleSort',
|
||||||
|
onFilter: 'handleFilter',
|
||||||
|
onMove: 'handleMove'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function _getModelName(component) {
|
||||||
|
return component.sortableOptions && component.sortableOptions.model || _defaultOptions.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _getModelItems(component) {
|
||||||
|
var name = _getModelName(component),
|
||||||
|
items = component.state && component.state[name] || component.props[name];
|
||||||
|
|
||||||
|
return items.slice();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _extend(dst, src) {
|
||||||
|
for (var key in src) {
|
||||||
|
if (src.hasOwnProperty(key)) {
|
||||||
|
dst[key] = src[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple and easy mixin-wrapper for rubaxa/Sortable library, in order to
|
||||||
|
* make reorderable drag-and-drop lists on modern browsers and touch devices.
|
||||||
|
*
|
||||||
|
* @mixin
|
||||||
|
*/
|
||||||
|
var SortableMixin = {
|
||||||
|
sortableMixinVersion: '0.1.1',
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Sortable}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_sortableInstance: null,
|
||||||
|
|
||||||
|
|
||||||
|
componentDidMount: function () {
|
||||||
|
var DOMNode, options = _extend(_extend({}, _defaultOptions), this.sortableOptions || {}),
|
||||||
|
copyOptions = _extend({}, options),
|
||||||
|
|
||||||
|
emitEvent = function (/** string */type, /** Event */evt) {
|
||||||
|
var method = this[options[type]];
|
||||||
|
method && method.call(this, evt, this._sortableInstance);
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
|
||||||
|
// Bind callbacks so that "this" refers to the component
|
||||||
|
'onStart onEnd onAdd onSort onUpdate onRemove onFilter onMove'.split(' ').forEach(function (/** string */name) {
|
||||||
|
copyOptions[name] = function (evt) {
|
||||||
|
if (name === 'onStart') {
|
||||||
|
_nextSibling = evt.item.nextElementSibling;
|
||||||
|
_activeComponent = this;
|
||||||
|
}
|
||||||
|
else if (name === 'onAdd' || name === 'onUpdate') {
|
||||||
|
evt.from.insertBefore(evt.item, _nextSibling);
|
||||||
|
|
||||||
|
var newState = {},
|
||||||
|
remoteState = {},
|
||||||
|
oldIndex = evt.oldIndex,
|
||||||
|
newIndex = evt.newIndex,
|
||||||
|
items = _getModelItems(this),
|
||||||
|
remoteItems,
|
||||||
|
item;
|
||||||
|
|
||||||
|
if (name === 'onAdd') {
|
||||||
|
remoteItems = _getModelItems(_activeComponent);
|
||||||
|
item = remoteItems.splice(oldIndex, 1)[0];
|
||||||
|
items.splice(newIndex, 0, item);
|
||||||
|
|
||||||
|
remoteState[_getModelName(_activeComponent)] = remoteItems;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
items.splice(newIndex, 0, items.splice(oldIndex, 1)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
newState[_getModelName(this)] = items;
|
||||||
|
|
||||||
|
if (copyOptions.stateHandler) {
|
||||||
|
this[copyOptions.stateHandler](newState);
|
||||||
|
} else {
|
||||||
|
this.setState(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
(this !== _activeComponent) && _activeComponent.setState(remoteState);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
emitEvent(name, evt);
|
||||||
|
}, 0);
|
||||||
|
}.bind(this);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
DOMNode = this.getDOMNode() ? (this.refs[options.ref] || this).getDOMNode() : this.refs[options.ref] || this;
|
||||||
|
|
||||||
|
/** @namespace this.refs — http://facebook.github.io/react/docs/more-about-refs.html */
|
||||||
|
this._sortableInstance = Sortable.create(DOMNode, copyOptions);
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillReceiveProps: function (nextProps) {
|
||||||
|
var newState = {},
|
||||||
|
modelName = _getModelName(this),
|
||||||
|
items = nextProps[modelName];
|
||||||
|
|
||||||
|
if (items) {
|
||||||
|
newState[modelName] = items;
|
||||||
|
this.setState(newState);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUnmount: function () {
|
||||||
|
this._sortableInstance.destroy();
|
||||||
|
this._sortableInstance = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Export
|
||||||
|
return SortableMixin;
|
||||||
|
});
|
239
dashboard-ui/bower_components/Sortable/st/app.css
vendored
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
html {
|
||||||
|
background-image: -webkit-linear-gradient(bottom, #F4E2C9 20%, #F4D7C9 100%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, #F4E2C9 20%, #F4D7C9 100%);
|
||||||
|
background-image: linear-gradient(to bottom, #F4E2C9 20%, #F4D7C9 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
color: #464637;
|
||||||
|
min-height: 100%;
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #FF3F00;
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
min-width: 1100px;
|
||||||
|
max-width: 1300px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 750px) and (max-width: 970px){
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 750px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sortable-ghost {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
top: 55px;
|
||||||
|
left: 30px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: #fff;
|
||||||
|
padding: 3px 10px;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
background-color: #FF7373;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.title_xl {
|
||||||
|
padding: 3px 15px;
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tile {
|
||||||
|
width: 22%;
|
||||||
|
min-width: 245px;
|
||||||
|
color: #FF7270;
|
||||||
|
padding: 10px 30px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 30px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.tile__name {
|
||||||
|
cursor: move;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #FF7373;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile__list {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.tile__list:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
min-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tile__list img {
|
||||||
|
cursor: move;
|
||||||
|
margin: 10px;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.block {
|
||||||
|
opacity: 1;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.block__list {
|
||||||
|
padding: 20px 0;
|
||||||
|
max-width: 360px;
|
||||||
|
margin-top: -8px;
|
||||||
|
margin-left: 5px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.block__list-title {
|
||||||
|
margin: -20px 0 0;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
background: #5F9EDF;
|
||||||
|
}
|
||||||
|
.block__list li { cursor: move; }
|
||||||
|
|
||||||
|
.block__list_words li {
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
.block__list_words .sortable-ghost {
|
||||||
|
opacity: 0.4;
|
||||||
|
background-color: #F4E2C9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block__list_words li:first-letter {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block__list_tags {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block__list_tags:after {
|
||||||
|
clear: both;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.block__list_tags li {
|
||||||
|
color: #fff;
|
||||||
|
float: left;
|
||||||
|
margin: 8px 20px 10px 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
min-width: 10px;
|
||||||
|
background-color: #5F9EDF;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.block__list_tags li:first-child:first-letter {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#editable {}
|
||||||
|
#editable li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editable i {
|
||||||
|
-webkit-transition: opacity .2s;
|
||||||
|
transition: opacity .2s;
|
||||||
|
opacity: 0;
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #c00;
|
||||||
|
top: 10px;
|
||||||
|
right: 40px;
|
||||||
|
position: absolute;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editable li:hover i {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#filter {}
|
||||||
|
#filter button {
|
||||||
|
color: #fff;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
opacity: .5;
|
||||||
|
margin: 10px 0 0;
|
||||||
|
transition: opacity .1s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #5F9EDF;
|
||||||
|
padding: 10px 0;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
#filter button:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filter .block__list {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-handle {
|
||||||
|
margin-right: 10px;
|
||||||
|
font: bold 20px Sans-Serif;
|
||||||
|
color: #5F9EDF;
|
||||||
|
display: inline-block;
|
||||||
|
cursor: move;
|
||||||
|
cursor: -webkit-grabbing; /* overrides 'move' */
|
||||||
|
}
|
||||||
|
|
||||||
|
#todos input {
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#nested ul li {
|
||||||
|
background-color: rgba(0,0,0,.05);
|
||||||
|
}
|
226
dashboard-ui/bower_components/Sortable/st/app.js
vendored
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var byId = function (id) { return document.getElementById(id); },
|
||||||
|
|
||||||
|
loadScripts = function (desc, callback) {
|
||||||
|
var deps = [], key, idx = 0;
|
||||||
|
|
||||||
|
for (key in desc) {
|
||||||
|
deps.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
(function _next() {
|
||||||
|
var pid,
|
||||||
|
name = deps[idx],
|
||||||
|
script = document.createElement('script');
|
||||||
|
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = desc[deps[idx]];
|
||||||
|
|
||||||
|
pid = setInterval(function () {
|
||||||
|
if (window[name]) {
|
||||||
|
clearTimeout(pid);
|
||||||
|
|
||||||
|
deps[idx++] = window[name];
|
||||||
|
|
||||||
|
if (deps[idx]) {
|
||||||
|
_next();
|
||||||
|
} else {
|
||||||
|
callback.apply(null, deps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 30);
|
||||||
|
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(script);
|
||||||
|
})()
|
||||||
|
},
|
||||||
|
|
||||||
|
console = window.console;
|
||||||
|
|
||||||
|
|
||||||
|
if (!console.log) {
|
||||||
|
console.log = function () {
|
||||||
|
alert([].join.apply(arguments, ' '));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Sortable.create(byId('foo'), {
|
||||||
|
group: "words",
|
||||||
|
animation: 150,
|
||||||
|
store: {
|
||||||
|
get: function (sortable) {
|
||||||
|
var order = localStorage.getItem(sortable.options.group);
|
||||||
|
return order ? order.split('|') : [];
|
||||||
|
},
|
||||||
|
set: function (sortable) {
|
||||||
|
var order = sortable.toArray();
|
||||||
|
localStorage.setItem(sortable.options.group, order.join('|'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onAdd: function (evt){ console.log('onAdd.foo:', [evt.item, evt.from]); },
|
||||||
|
onUpdate: function (evt){ console.log('onUpdate.foo:', [evt.item, evt.from]); },
|
||||||
|
onRemove: function (evt){ console.log('onRemove.foo:', [evt.item, evt.from]); },
|
||||||
|
onStart:function(evt){ console.log('onStart.foo:', [evt.item, evt.from]);},
|
||||||
|
onSort:function(evt){ console.log('onStart.foo:', [evt.item, evt.from]);},
|
||||||
|
onEnd: function(evt){ console.log('onEnd.foo:', [evt.item, evt.from]);}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Sortable.create(byId('bar'), {
|
||||||
|
group: "words",
|
||||||
|
animation: 150,
|
||||||
|
onAdd: function (evt){ console.log('onAdd.bar:', evt.item); },
|
||||||
|
onUpdate: function (evt){ console.log('onUpdate.bar:', evt.item); },
|
||||||
|
onRemove: function (evt){ console.log('onRemove.bar:', evt.item); },
|
||||||
|
onStart:function(evt){ console.log('onStart.foo:', evt.item);},
|
||||||
|
onEnd: function(evt){ console.log('onEnd.foo:', evt.item);}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Multi groups
|
||||||
|
Sortable.create(byId('multi'), {
|
||||||
|
animation: 150,
|
||||||
|
draggable: '.tile',
|
||||||
|
handle: '.tile__name'
|
||||||
|
});
|
||||||
|
|
||||||
|
[].forEach.call(byId('multi').getElementsByClassName('tile__list'), function (el){
|
||||||
|
Sortable.create(el, {
|
||||||
|
group: 'photo',
|
||||||
|
animation: 150
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Editable list
|
||||||
|
var editableList = Sortable.create(byId('editable'), {
|
||||||
|
animation: 150,
|
||||||
|
filter: '.js-remove',
|
||||||
|
onFilter: function (evt) {
|
||||||
|
evt.item.parentNode.removeChild(evt.item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
byId('addUser').onclick = function () {
|
||||||
|
Ply.dialog('prompt', {
|
||||||
|
title: 'Add',
|
||||||
|
form: { name: 'name' }
|
||||||
|
}).done(function (ui) {
|
||||||
|
var el = document.createElement('li');
|
||||||
|
el.innerHTML = ui.data.name + '<i class="js-remove">✖</i>';
|
||||||
|
editableList.el.appendChild(el);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Advanced groups
|
||||||
|
[{
|
||||||
|
name: 'advanced',
|
||||||
|
pull: true,
|
||||||
|
put: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'advanced',
|
||||||
|
pull: 'clone',
|
||||||
|
put: false
|
||||||
|
}, {
|
||||||
|
name: 'advanced',
|
||||||
|
pull: false,
|
||||||
|
put: true
|
||||||
|
}].forEach(function (groupOpts, i) {
|
||||||
|
Sortable.create(byId('advanced-' + (i + 1)), {
|
||||||
|
sort: (i != 1),
|
||||||
|
group: groupOpts,
|
||||||
|
animation: 150
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 'handle' option
|
||||||
|
Sortable.create(byId('handle-1'), {
|
||||||
|
handle: '.drag-handle',
|
||||||
|
animation: 150
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Angular example
|
||||||
|
angular.module('todoApp', ['ng-sortable'])
|
||||||
|
.constant('ngSortableConfig', {onEnd: function() {
|
||||||
|
console.log('default onEnd()');
|
||||||
|
}})
|
||||||
|
.controller('TodoController', ['$scope', function ($scope) {
|
||||||
|
$scope.todos = [
|
||||||
|
{text: 'learn angular', done: true},
|
||||||
|
{text: 'build an angular app', done: false}
|
||||||
|
];
|
||||||
|
|
||||||
|
$scope.addTodo = function () {
|
||||||
|
$scope.todos.push({text: $scope.todoText, done: false});
|
||||||
|
$scope.todoText = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.remaining = function () {
|
||||||
|
var count = 0;
|
||||||
|
angular.forEach($scope.todos, function (todo) {
|
||||||
|
count += todo.done ? 0 : 1;
|
||||||
|
});
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.archive = function () {
|
||||||
|
var oldTodos = $scope.todos;
|
||||||
|
$scope.todos = [];
|
||||||
|
angular.forEach(oldTodos, function (todo) {
|
||||||
|
if (!todo.done) $scope.todos.push(todo);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}])
|
||||||
|
.controller('TodoControllerNext', ['$scope', function ($scope) {
|
||||||
|
$scope.todos = [
|
||||||
|
{text: 'learn Sortable', done: true},
|
||||||
|
{text: 'use ng-sortable', done: false},
|
||||||
|
{text: 'Enjoy', done: false}
|
||||||
|
];
|
||||||
|
|
||||||
|
$scope.remaining = function () {
|
||||||
|
var count = 0;
|
||||||
|
angular.forEach($scope.todos, function (todo) {
|
||||||
|
count += todo.done ? 0 : 1;
|
||||||
|
});
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.sortableConfig = { group: 'todo', animation: 150 };
|
||||||
|
'Start End Add Update Remove Sort'.split(' ').forEach(function (name) {
|
||||||
|
$scope.sortableConfig['on' + name] = console.log.bind(console, name);
|
||||||
|
});
|
||||||
|
}]);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Background
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
function setNoiseBackground(el, width, height, opacity) {
|
||||||
|
var canvas = document.createElement("canvas");
|
||||||
|
var context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
|
||||||
|
for (var i = 0; i < width; i++) {
|
||||||
|
for (var j = 0; j < height; j++) {
|
||||||
|
var val = Math.floor(Math.random() * 255);
|
||||||
|
context.fillStyle = "rgba(" + val + "," + val + "," + val + "," + opacity + ")";
|
||||||
|
context.fillRect(i, j, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
el.style.background = "url(" + canvas.toDataURL("image/png") + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
setNoiseBackground(document.getElementsByTagName('body')[0], 50, 50, 0.02);
|
||||||
|
}, false);
|
BIN
dashboard-ui/bower_components/Sortable/st/face-01.jpg
vendored
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-02.jpg
vendored
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-03.jpg
vendored
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-04.jpg
vendored
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-05.jpg
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-06.jpg
vendored
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-07.jpg
vendored
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-08.jpg
vendored
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/face-09.jpg
vendored
Normal file
After Width: | Height: | Size: 4.6 KiB |
32
dashboard-ui/bower_components/Sortable/st/iframe/frame.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- List with handle -->
|
||||||
|
<div id="listWithHandle" class="list-group">
|
||||||
|
<div class="list-group-item">
|
||||||
|
<span class="badge">14</span>
|
||||||
|
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
|
||||||
|
Drag me by the handle
|
||||||
|
</div>
|
||||||
|
<div class="list-group-item">
|
||||||
|
<span class="badge">2</span>
|
||||||
|
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
|
||||||
|
You can also select text
|
||||||
|
</div>
|
||||||
|
<div class="list-group-item">
|
||||||
|
<span class="badge">1</span>
|
||||||
|
<span class="glyphicon glyphicon-move" aria-hidden="true"></span>
|
||||||
|
Best of both worlds!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
49
dashboard-ui/bower_components/Sortable/st/iframe/index.html
vendored
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>IFrame playground</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Latest compiled and minified CSS -->
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Latest Sortable -->
|
||||||
|
<script src="../../Sortable.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Simple List -->
|
||||||
|
<div id="simpleList" class="list-group">
|
||||||
|
<div class="list-group-item">This is <a href="http://rubaxa.github.io/Sortable/">Sortable</a></div>
|
||||||
|
<div class="list-group-item">It works with Bootstrap...</div>
|
||||||
|
<div class="list-group-item">...out of the box.</div>
|
||||||
|
<div class="list-group-item">It has support for touch devices.</div>
|
||||||
|
<div class="list-group-item">Just drag some elements around.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
Sortable.create(simpleList, {group: 'shared'});
|
||||||
|
|
||||||
|
|
||||||
|
var iframe = document.createElement('iframe');
|
||||||
|
|
||||||
|
iframe.src = 'frame.html';
|
||||||
|
iframe.width = '100%';
|
||||||
|
iframe.onload = function () {
|
||||||
|
var doc = iframe.contentDocument,
|
||||||
|
list = doc.getElementById('listWithHandle');
|
||||||
|
|
||||||
|
Sortable.create(list, {group: 'shared'});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
dashboard-ui/bower_components/Sortable/st/logo.png
vendored
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
dashboard-ui/bower_components/Sortable/st/og-image.png
vendored
Normal file
After Width: | Height: | Size: 12 KiB |
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "dragula.js",
|
|
||||||
"version": "3.5.1",
|
|
||||||
"description": "Drag and drop so simple it hurts",
|
|
||||||
"main": [
|
|
||||||
"dist/dragula.js",
|
|
||||||
"dist/dragula.css"
|
|
||||||
],
|
|
||||||
"ignore": [],
|
|
||||||
"homepage": "https://github.com/bevacqua/dragula",
|
|
||||||
"authors": [
|
|
||||||
"Nicolas Bevacqua <nicolasbevacqua@gmail.com>"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"_release": "3.5.1",
|
|
||||||
"_resolution": {
|
|
||||||
"type": "version",
|
|
||||||
"tag": "v3.5.1",
|
|
||||||
"commit": "bbd33f7f871d2f672bebf70bfc054134a48cf0e9"
|
|
||||||
},
|
|
||||||
"_source": "git://github.com/bevacqua/dragula.git",
|
|
||||||
"_target": "~3.5.1",
|
|
||||||
"_originalSource": "dragula",
|
|
||||||
"_direct": true
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
node_modules
|
|
||||||
npm-debug.log
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
|
@ -1,4 +0,0 @@
|
||||||
node_modules
|
|
||||||
bower_components
|
|
||||||
dist
|
|
||||||
example
|
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"curly": true,
|
|
||||||
"eqeqeq": true,
|
|
||||||
"newcap": true,
|
|
||||||
"noarg": true,
|
|
||||||
"noempty": true,
|
|
||||||
"nonew": true,
|
|
||||||
"sub": true,
|
|
||||||
"undef": true,
|
|
||||||
"unused": true,
|
|
||||||
"trailing": true,
|
|
||||||
"boss": true,
|
|
||||||
"eqnull": true,
|
|
||||||
"strict": true,
|
|
||||||
"immed": true,
|
|
||||||
"expr": true,
|
|
||||||
"latedef": "nofunc",
|
|
||||||
"quotmark": "single",
|
|
||||||
"validthis": true,
|
|
||||||
"indent": 2,
|
|
||||||
"node": true,
|
|
||||||
"browser": true
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 'iojs'
|
|
||||||
- '4'
|
|
||||||
before_script:
|
|
||||||
- export DISPLAY=:99.0; sh -e /etc/init.d/xvfb start
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"name": "dragula.js",
|
|
||||||
"version": "3.5.1",
|
|
||||||
"description": "Drag and drop so simple it hurts",
|
|
||||||
"main": [
|
|
||||||
"dist/dragula.js",
|
|
||||||
"dist/dragula.css"
|
|
||||||
],
|
|
||||||
"ignore": [],
|
|
||||||
"homepage": "https://github.com/bevacqua/dragula",
|
|
||||||
"authors": [
|
|
||||||
"Nicolas Bevacqua <nicolasbevacqua@gmail.com>"
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
|
|
@ -1,228 +0,0 @@
|
||||||
# 3.5.1 Which Hunt
|
|
||||||
|
|
||||||
- Fixed a bug when determining the mouse button being pressed
|
|
||||||
- Fixed a bug when determining the element behind the mouse cursor when `ignoreInputTextSelection` was enabled
|
|
||||||
|
|
||||||
# 3.5.0 Input Fanatic
|
|
||||||
|
|
||||||
- Added a feature where users are able to select text ranges with their mouse in inputs within a dragula container
|
|
||||||
|
|
||||||
# 3.4.1 Input Accomodation
|
|
||||||
|
|
||||||
- Fixed a bug where text in inputs inside containers assigned to `dragula` couldn't be selected
|
|
||||||
|
|
||||||
# 3.4.0 Event Sourcing
|
|
||||||
|
|
||||||
- Events for `cancel`, `remove`, and `shadow` now all provide a `source` parameter in the third position
|
|
||||||
|
|
||||||
# 3.3.2 Captain Obvious
|
|
||||||
|
|
||||||
- Fixed a bug where `out` would be emitted with an `undefined` container
|
|
||||||
|
|
||||||
# 3.3.1 Significant Other
|
|
||||||
|
|
||||||
- Fixed a fringe bug [(#207)](https://github.com/bevacqua/dragula/pull/207) where the click handler wouldn't work
|
|
||||||
- Fixed a bug where `drop` events would sometimes not receive the current sibling
|
|
||||||
|
|
||||||
# 3.3.0 Brotherhood
|
|
||||||
|
|
||||||
- The `options.moves` callback now receives a fourth parameter, the `sibling` found after `el`
|
|
||||||
- The `drop` event now receives a fourth parameter, the `sibling` found after `el`
|
|
||||||
|
|
||||||
# 3.2.0 Sortable Sauce
|
|
||||||
|
|
||||||
- You can now use `options.copySortSource` to enable sorting in `copy`-source containers
|
|
||||||
|
|
||||||
# 3.1.0 Copy Paste
|
|
||||||
|
|
||||||
- You can now set `options.copy` to a method. It'll be invoked once per drag to ask whether the element being dragged should be treated as a copy or not
|
|
||||||
- Fixed a bug where starting a drag programatically while an element was being dragged resulted in an exception
|
|
||||||
|
|
||||||
# 3.0.7 Crossroads
|
|
||||||
|
|
||||||
- Fixed a bug in Webpack builds by updating `crossvent` to `1.5.3`
|
|
||||||
|
|
||||||
# 3.0.5 Mouse Rat Rock Band
|
|
||||||
|
|
||||||
- Fixed a bug where `mousedown` would be prevented and focusing draggable inputs wouldn't be possible
|
|
||||||
|
|
||||||
# 3.0.4 IE is the old IE
|
|
||||||
|
|
||||||
- Fixed a bug in IE8 by updating `crossvent` to `1.5.2`
|
|
||||||
|
|
||||||
# 3.0.3 Forest Fire
|
|
||||||
|
|
||||||
- Fixed a bug in Firefox where dragging links and images would result in issues
|
|
||||||
|
|
||||||
# 3.0.2 Clickhood Rainforest
|
|
||||||
|
|
||||||
- Fixed a _historical_ bug, where click on anchors would be ignored within `dragula` containers in mobile
|
|
||||||
- Fixed a bug where events wouldn't be gracefully removed if `drake` were destroyed during a drag event
|
|
||||||
- Now emits `dragend` after `out` to preserve consistency _(because `drag` is emitted before `over`)_
|
|
||||||
- Fixed another old bug where attempting to remove elements using `removeOnSpill` on mobile would fail
|
|
||||||
|
|
||||||
# 3.0.1 Carjacking
|
|
||||||
|
|
||||||
- Fixed a bug in mobile, caused by `3.0.0`, where scrolling would be impossible
|
|
||||||
- Fixed a bug where dragging would cause text selection in IE8
|
|
||||||
|
|
||||||
# 3.0.0 Guilty Conscience
|
|
||||||
|
|
||||||
- Removed `addContainer` method, which was previously deprecated
|
|
||||||
- Removed `removeContainer` method, which was previously deprecated
|
|
||||||
- Removed `delay` option in favor of using `mousemove`
|
|
||||||
- Drag events now start on the first occurrence of a `mousemove` event
|
|
||||||
- If `mousemove` never fires, then the `drag` machinery won't start, either
|
|
||||||
- Changed default value for `invalid`, now always returns `false` by default
|
|
||||||
- Added `mirrorContainer` option to determine where the mirror gets appended to _(defaults to `document.body`)_
|
|
||||||
|
|
||||||
# 2.1.2 Shady Sibling
|
|
||||||
|
|
||||||
- Fixed a bug where `shadow` would trigger multiple times while dragging an element over the same spot
|
|
||||||
|
|
||||||
# 2.1.1 Classy Drake
|
|
||||||
|
|
||||||
- Fixed a bug where adding and removing classes might've caused issues on elements that had foreign CSS classes
|
|
||||||
- Added an argument to `cloned` event that specifies the kind of clone. Possible values include `mirror` and `copy` at the moment
|
|
||||||
|
|
||||||
# 2.1.0 Over and Out
|
|
||||||
|
|
||||||
- Added `over` event that fires whenever an element is dragged over a container _(or whenever a drag event starts)_
|
|
||||||
- Added `out` event that fires whenever an element is dragged out of a container _(or whenever a drag event ends)_
|
|
||||||
|
|
||||||
# 2.0.7 Mayhem
|
|
||||||
|
|
||||||
- Fixed a bug caused in `2.0.6` where anything would be regarded as a `drake` container
|
|
||||||
|
|
||||||
# 2.0.6 Coruscant
|
|
||||||
|
|
||||||
- Fixed a bug where `isContainer` would be called with a `el=null` in some situations
|
|
||||||
|
|
||||||
# 2.0.5 Cross Ventilation
|
|
||||||
|
|
||||||
- Bumped `crossvent@1.5.0`
|
|
||||||
|
|
||||||
# 2.0.4 Transit Overload
|
|
||||||
|
|
||||||
- Set `gu-transit` after a drag event has fully started
|
|
||||||
|
|
||||||
# 2.0.3 Mice Trap
|
|
||||||
|
|
||||||
- Fixed a bug where using `.cancel` would throw an exception
|
|
||||||
|
|
||||||
# 2.0.2 Aural Emission
|
|
||||||
|
|
||||||
- Replaced `contra.emitter` with `contra@1.9.1/emitter`
|
|
||||||
|
|
||||||
# 2.0.1 Copycat
|
|
||||||
|
|
||||||
- Fixed a bug where dragging a copy back to origin after hovering over another container would still result in a copy being made if you never spilled the item
|
|
||||||
|
|
||||||
# 2.0.0 Containerization
|
|
||||||
|
|
||||||
- Deprecated `addContainer` method
|
|
||||||
- Deprecated `removeContainer` method
|
|
||||||
- Exposed `dragula.containers` collection
|
|
||||||
- Introduced dynamic `isContainer` method
|
|
||||||
- Can now omit `containers` argument to `dragula(containers, options)`
|
|
||||||
- Can now pass `containers` as an option
|
|
||||||
|
|
||||||
# 1.7.0 Clickety Click
|
|
||||||
|
|
||||||
- Differentiate between drag and click using `delay` option
|
|
||||||
- Ability to specify which event targets are `invalid` drag triggers
|
|
||||||
|
|
||||||
# 1.6.1 Shadow Drake
|
|
||||||
|
|
||||||
- Improved shadow positioning when `revertOnSpill` is `true`
|
|
||||||
|
|
||||||
# 1.6.0 Lonely Clown Clone
|
|
||||||
|
|
||||||
- Added `'cloned'` event when a DOM element is cloned
|
|
||||||
|
|
||||||
# 1.5.1 Touchypants
|
|
||||||
|
|
||||||
- Fixed an issue where dragula didn't understand where an element was being dropped
|
|
||||||
|
|
||||||
# 1.5.0 Drag Racing
|
|
||||||
|
|
||||||
- Introduced drag handles so that elements could only be dragged from a handle element
|
|
||||||
|
|
||||||
# 1.4.2 Container Camp
|
|
||||||
|
|
||||||
- Fixed a bug where `addContainer` and `removeContainer` wouldn't update the list of available containers
|
|
||||||
- Fixed a bug where `document.body` would be accessed before it was available if the scripts were loaded in the `<head>`
|
|
||||||
|
|
||||||
# 1.4.1 Blood Prince
|
|
||||||
|
|
||||||
- Fixed an issue where manually started drag events wouldn't know if position changed when an item was dropped in the source container
|
|
||||||
- Added minor styling to `gu-mirror`, to visually identify that a drag is in progress
|
|
||||||
|
|
||||||
# 1.4.0 Top Fuel
|
|
||||||
|
|
||||||
- Added a `dragend` event that's always fired
|
|
||||||
- Added a `dragging` property to API
|
|
||||||
- Introduced manual `start` API method
|
|
||||||
- Introduced `addContainer` and `removeContainer` dynamic API
|
|
||||||
|
|
||||||
# 1.3.0 Terror
|
|
||||||
|
|
||||||
Introduced an `.end` instance API method that gracefully ends the drag event using the last known valid drop target.
|
|
||||||
|
|
||||||
# 1.2.4 Brother in Arms
|
|
||||||
|
|
||||||
- The `accepts` option now takes a fourth argument, `sibling`, giving us a hint of the precise position the item would be dropped in
|
|
||||||
|
|
||||||
# 1.2.3 Breeding Pool
|
|
||||||
|
|
||||||
- Fixed a bug in cross browser behavior that caused the hover effect to ignore scrolling
|
|
||||||
- Fixed a bug where touch events weren't working in obscure versions of IE
|
|
||||||
|
|
||||||
# 1.2.2 Originality Accepted
|
|
||||||
|
|
||||||
- Improved `accepts` mechanism so that it always accepts the original starting point
|
|
||||||
|
|
||||||
# 1.2.1 Firehose
|
|
||||||
|
|
||||||
- Fixed a bug introduced in `1.2.0`
|
|
||||||
- Fixed a bug where cancelling with `revert` enabled wouldn't respect sort order
|
|
||||||
|
|
||||||
# 1.2.0 Firefly
|
|
||||||
|
|
||||||
- Introduced `moves` option, used to determine if an item is draggable
|
|
||||||
- Added a `source` parameter for the `drop` event
|
|
||||||
- Cancelling a drag event when `revertOnSpill` is `true` will now move the element to its original position in the source element instead of appending it
|
|
||||||
- Fixed a bug where _"cancellations"_ that ended up leaving the dragged element in the source container but changed sort order would trigger a `cancel` event instead of `drop`
|
|
||||||
- Fixed a bug where _"drops"_ that ended up leaving the element in the exact same place it was dragged from would end up triggering a `drop` event instead of `cancel`
|
|
||||||
- Added touch event support
|
|
||||||
|
|
||||||
# 1.1.4 Fog Creek
|
|
||||||
|
|
||||||
- Added `'shadow'` event to enable easy updates to shadow element as it's moved
|
|
||||||
|
|
||||||
# 1.1.3 Drag Queen
|
|
||||||
|
|
||||||
- Fixed a bug where `dragula` wouldn't make a copy if the element was dropped outside of a target container
|
|
||||||
- If a dragged element gets removed for an instance that has `copy` set to `true`, a `cancel` event is raised instead
|
|
||||||
|
|
||||||
# 1.1.2 Eavesdropping
|
|
||||||
|
|
||||||
- Fixed a bug where _"cancellations"_ that ended up leaving the dragged element somewhere other than the source container wouldn't trigger a `drop` event
|
|
||||||
|
|
||||||
# 1.1.1 Slipping Jimmy
|
|
||||||
|
|
||||||
- Fixed a bug where the movable shadow wouldn't update properly if the element was hovered over the last position of a container
|
|
||||||
|
|
||||||
# 1.1.0 Age of Shadows
|
|
||||||
|
|
||||||
- Added a movable shadow that gives visual feedback as to where a dragged item would be dropped
|
|
||||||
- Added an option to remove dragged elements when they are dropped outside of sanctioned containers
|
|
||||||
- Added an option to revert dragged elements back to their source container when they are dropped outside of sanctioned containers
|
|
||||||
|
|
||||||
# 1.0.1 Consuelo
|
|
||||||
|
|
||||||
- Removed `console.log` statement
|
|
||||||
|
|
||||||
# 1.0.0 IPO
|
|
||||||
|
|
||||||
- Initial Public Release
|
|
|
@ -1,33 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var cache = {};
|
|
||||||
var start = '(?:^|\\s)';
|
|
||||||
var end = '(?:\\s|$)';
|
|
||||||
|
|
||||||
function lookupClass (className) {
|
|
||||||
var cached = cache[className];
|
|
||||||
if (cached) {
|
|
||||||
cached.lastIndex = 0;
|
|
||||||
} else {
|
|
||||||
cache[className] = cached = new RegExp(start + className + end, 'g');
|
|
||||||
}
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addClass (el, className) {
|
|
||||||
var current = el.className;
|
|
||||||
if (!current.length) {
|
|
||||||
el.className = className;
|
|
||||||
} else if (!lookupClass(className).test(current)) {
|
|
||||||
el.className += ' ' + className;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rmClass (el, className) {
|
|
||||||
el.className = el.className.replace(lookupClass(className), ' ').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
add: addClass,
|
|
||||||
rm: rmClass
|
|
||||||
};
|
|
|
@ -1,60 +0,0 @@
|
||||||
# Contributing
|
|
||||||
|
|
||||||
Hey there! Glad you want to chime in. Here's what you need to know.
|
|
||||||
|
|
||||||
### Support Requests
|
|
||||||
|
|
||||||
There's now a dedicated support channel in Slack. Visit the `dragula` [demo page][2] to get an invite. Support requests won't be handled through the repository anymore.
|
|
||||||
|
|
||||||
If you have a question, make sure it wasn't [already answered][1]. If it wasn't, please refer to the Slack chat. To get an invite, use the badge in the [demo page][2].
|
|
||||||
|
|
||||||
> Our goal is to provide answers to the most frequently asked questions somewhere in the documentation.
|
|
||||||
|
|
||||||
### Bugs
|
|
||||||
|
|
||||||
Bug reports are tricky. Please provide as much context as possible, and if you want to start working on a fix, we'll be forever grateful! Please try and test around for a bit to make sure you're dealing with a bug and not an issue in your implementation.
|
|
||||||
|
|
||||||
If possible, provide a demo where the bug is isolated and turned into its smallest possible representation. That would help a lot!
|
|
||||||
|
|
||||||
Thanks for reporting bugs, we'd be lost without you.
|
|
||||||
|
|
||||||
### Feature Requests
|
|
||||||
|
|
||||||
We're still considering feature requests. Note that we might not implement the feature you want, or exactly how you want it. The goal here is to keep making `dragula` awesome while not making it too bloated.
|
|
||||||
|
|
||||||
We also dislike overly specific features and favor more abstract ones you the consumer can build other features upon.
|
|
||||||
|
|
||||||
# Development
|
|
||||||
|
|
||||||
Development flows are based on `npm run` scripts.
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
To compile a standalone browserify module, use the following command. A minified version will also be produced. The compiled bundles are placed inside `dist`. Since **these are autogenerated**, please don't include them in your pull requests.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also run the build continuously, _to faciliate development_, with this command.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test
|
|
||||||
|
|
||||||
Run the command below to execute all tests in a DevTools window through Electron. Note that the DevTools will get reloaded whenever your test files change, making tests a breeze!
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm run test-watch
|
|
||||||
```
|
|
||||||
|
|
||||||
To run tests a single time, simply run the following command. This is used in CI testing.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
[1]: https://github.com/bevacqua/dragula/issues?q=label%3Asupport
|
|
||||||
[2]: http://bevacqua.github.io/dragula/
|
|
|
@ -1,22 +0,0 @@
|
||||||
.gu-mirror {
|
|
||||||
position: fixed !important;
|
|
||||||
margin: 0 !important;
|
|
||||||
z-index: 9999 !important;
|
|
||||||
opacity: 0.8;
|
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
|
|
||||||
filter: alpha(opacity=80);
|
|
||||||
}
|
|
||||||
.gu-hide {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
.gu-unselectable {
|
|
||||||
-webkit-user-select: none !important;
|
|
||||||
-moz-user-select: none !important;
|
|
||||||
-ms-user-select: none !important;
|
|
||||||
user-select: none !important;
|
|
||||||
}
|
|
||||||
.gu-transit {
|
|
||||||
opacity: 0.2;
|
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
|
||||||
filter: alpha(opacity=20);
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
.gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";filter:alpha(opacity=20)}
|
|
585
dashboard-ui/bower_components/dragula.js/dragula.js
vendored
|
@ -1,585 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var emitter = require('contra/emitter');
|
|
||||||
var crossvent = require('crossvent');
|
|
||||||
var classes = require('./classes');
|
|
||||||
|
|
||||||
function dragula (initialContainers, options) {
|
|
||||||
var len = arguments.length;
|
|
||||||
if (len === 1 && Array.isArray(initialContainers) === false) {
|
|
||||||
options = initialContainers;
|
|
||||||
initialContainers = [];
|
|
||||||
}
|
|
||||||
var body = document.body;
|
|
||||||
var documentElement = document.documentElement;
|
|
||||||
var _mirror; // mirror image
|
|
||||||
var _source; // source container
|
|
||||||
var _item; // item being dragged
|
|
||||||
var _offsetX; // reference x
|
|
||||||
var _offsetY; // reference y
|
|
||||||
var _moveX; // reference move x
|
|
||||||
var _moveY; // reference move y
|
|
||||||
var _initialSibling; // reference sibling when grabbed
|
|
||||||
var _currentSibling; // reference sibling now
|
|
||||||
var _copy; // item used for copying
|
|
||||||
var _renderTimer; // timer for setTimeout renderMirrorImage
|
|
||||||
var _lastDropTarget = null; // last container item was over
|
|
||||||
var _grabbed; // holds mousedown context until first mousemove
|
|
||||||
|
|
||||||
var o = options || {};
|
|
||||||
if (o.moves === void 0) { o.moves = always; }
|
|
||||||
if (o.accepts === void 0) { o.accepts = always; }
|
|
||||||
if (o.invalid === void 0) { o.invalid = invalidTarget; }
|
|
||||||
if (o.containers === void 0) { o.containers = initialContainers || []; }
|
|
||||||
if (o.isContainer === void 0) { o.isContainer = never; }
|
|
||||||
if (o.copy === void 0) { o.copy = false; }
|
|
||||||
if (o.copySortSource === void 0) { o.copySortSource = false; }
|
|
||||||
if (o.revertOnSpill === void 0) { o.revertOnSpill = false; }
|
|
||||||
if (o.removeOnSpill === void 0) { o.removeOnSpill = false; }
|
|
||||||
if (o.direction === void 0) { o.direction = 'vertical'; }
|
|
||||||
if (o.ignoreInputTextSelection === void 0) { o.ignoreInputTextSelection = true; }
|
|
||||||
if (o.mirrorContainer === void 0) { o.mirrorContainer = body; }
|
|
||||||
|
|
||||||
var drake = emitter({
|
|
||||||
containers: o.containers,
|
|
||||||
start: manualStart,
|
|
||||||
end: end,
|
|
||||||
cancel: cancel,
|
|
||||||
remove: remove,
|
|
||||||
destroy: destroy,
|
|
||||||
dragging: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (o.removeOnSpill === true) {
|
|
||||||
drake.on('over', spillOver).on('out', spillOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
events();
|
|
||||||
|
|
||||||
return drake;
|
|
||||||
|
|
||||||
function isContainer (el) {
|
|
||||||
return drake.containers.indexOf(el) !== -1 || o.isContainer(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
function events (remove) {
|
|
||||||
var op = remove ? 'remove' : 'add';
|
|
||||||
touchy(documentElement, op, 'mousedown', grab);
|
|
||||||
touchy(documentElement, op, 'mouseup', release);
|
|
||||||
}
|
|
||||||
|
|
||||||
function eventualMovements (remove) {
|
|
||||||
var op = remove ? 'remove' : 'add';
|
|
||||||
touchy(documentElement, op, 'mousemove', startBecauseMouseMoved);
|
|
||||||
}
|
|
||||||
|
|
||||||
function movements (remove) {
|
|
||||||
var op = remove ? 'remove' : 'add';
|
|
||||||
touchy(documentElement, op, 'selectstart', preventGrabbed); // IE8
|
|
||||||
touchy(documentElement, op, 'click', preventGrabbed);
|
|
||||||
}
|
|
||||||
|
|
||||||
function destroy () {
|
|
||||||
events(true);
|
|
||||||
release({});
|
|
||||||
}
|
|
||||||
|
|
||||||
function preventGrabbed (e) {
|
|
||||||
if (_grabbed) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function grab (e) {
|
|
||||||
_moveX = e.clientX;
|
|
||||||
_moveY = e.clientY;
|
|
||||||
|
|
||||||
var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey;
|
|
||||||
if (ignore) {
|
|
||||||
return; // we only care about honest-to-god left clicks and touch events
|
|
||||||
}
|
|
||||||
var item = e.target;
|
|
||||||
var context = canStart(item);
|
|
||||||
if (!context) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_grabbed = context;
|
|
||||||
eventualMovements();
|
|
||||||
if (e.type === 'mousedown') {
|
|
||||||
if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208
|
|
||||||
item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176
|
|
||||||
} else {
|
|
||||||
e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startBecauseMouseMoved (e) {
|
|
||||||
if (!_grabbed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (whichMouseButton(e) === 0) {
|
|
||||||
release({});
|
|
||||||
return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope
|
|
||||||
}
|
|
||||||
if (e.clientX === _moveX && e.clientY === _moveY) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (o.ignoreInputTextSelection) {
|
|
||||||
var clientX = getCoord('clientX', e);
|
|
||||||
var clientY = getCoord('clientY', e);
|
|
||||||
var elementBehindCursor = document.elementFromPoint(clientX, clientY);
|
|
||||||
if (isInput(elementBehindCursor)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var grabbed = _grabbed; // call to end() unsets _grabbed
|
|
||||||
eventualMovements(true);
|
|
||||||
movements();
|
|
||||||
end();
|
|
||||||
start(grabbed);
|
|
||||||
|
|
||||||
var offset = getOffset(_item);
|
|
||||||
_offsetX = getCoord('pageX', e) - offset.left;
|
|
||||||
_offsetY = getCoord('pageY', e) - offset.top;
|
|
||||||
|
|
||||||
classes.add(_copy || _item, 'gu-transit');
|
|
||||||
renderMirrorImage();
|
|
||||||
drag(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function canStart (item) {
|
|
||||||
if (drake.dragging && _mirror) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isContainer(item)) {
|
|
||||||
return; // don't drag container itself
|
|
||||||
}
|
|
||||||
var handle = item;
|
|
||||||
while (item.parentElement && isContainer(item.parentElement) === false) {
|
|
||||||
if (o.invalid(item, handle)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
item = item.parentElement; // drag target should be a top element
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var source = item.parentElement;
|
|
||||||
if (!source) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (o.invalid(item, handle)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var movable = o.moves(item, source, handle, nextEl(item));
|
|
||||||
if (!movable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
item: item,
|
|
||||||
source: source
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function manualStart (item) {
|
|
||||||
var context = canStart(item);
|
|
||||||
if (context) {
|
|
||||||
start(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function start (context) {
|
|
||||||
if (isCopy(context.item, context.source)) {
|
|
||||||
_copy = context.item.cloneNode(true);
|
|
||||||
drake.emit('cloned', _copy, context.item, 'copy');
|
|
||||||
}
|
|
||||||
|
|
||||||
_source = context.source;
|
|
||||||
_item = context.item;
|
|
||||||
_initialSibling = _currentSibling = nextEl(context.item);
|
|
||||||
|
|
||||||
drake.dragging = true;
|
|
||||||
drake.emit('drag', _item, _source);
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalidTarget () {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function end () {
|
|
||||||
if (!drake.dragging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var item = _copy || _item;
|
|
||||||
drop(item, item.parentElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ungrab () {
|
|
||||||
_grabbed = false;
|
|
||||||
eventualMovements(true);
|
|
||||||
movements(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function release (e) {
|
|
||||||
ungrab();
|
|
||||||
|
|
||||||
if (!drake.dragging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var item = _copy || _item;
|
|
||||||
var clientX = getCoord('clientX', e);
|
|
||||||
var clientY = getCoord('clientY', e);
|
|
||||||
var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
|
|
||||||
var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
|
|
||||||
if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) {
|
|
||||||
drop(item, dropTarget);
|
|
||||||
} else if (o.removeOnSpill) {
|
|
||||||
remove();
|
|
||||||
} else {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drop (item, target) {
|
|
||||||
var parent = item.parentElement;
|
|
||||||
if (_copy && o.copySortSource && target === _source) {
|
|
||||||
parent.removeChild(_item);
|
|
||||||
}
|
|
||||||
if (isInitialPlacement(target)) {
|
|
||||||
drake.emit('cancel', item, _source, _source);
|
|
||||||
} else {
|
|
||||||
drake.emit('drop', item, target, _source, _currentSibling);
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove () {
|
|
||||||
if (!drake.dragging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var item = _copy || _item;
|
|
||||||
var parent = item.parentElement;
|
|
||||||
if (parent) {
|
|
||||||
parent.removeChild(item);
|
|
||||||
}
|
|
||||||
drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source);
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel (revert) {
|
|
||||||
if (!drake.dragging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var reverts = arguments.length > 0 ? revert : o.revertOnSpill;
|
|
||||||
var item = _copy || _item;
|
|
||||||
var parent = item.parentElement;
|
|
||||||
if (parent === _source && _copy) {
|
|
||||||
parent.removeChild(_copy);
|
|
||||||
}
|
|
||||||
var initial = isInitialPlacement(parent);
|
|
||||||
if (initial === false && !_copy && reverts) {
|
|
||||||
_source.insertBefore(item, _initialSibling);
|
|
||||||
}
|
|
||||||
if (initial || reverts) {
|
|
||||||
drake.emit('cancel', item, _source, _source);
|
|
||||||
} else {
|
|
||||||
drake.emit('drop', item, parent, _source, _currentSibling);
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
function cleanup () {
|
|
||||||
var item = _copy || _item;
|
|
||||||
ungrab();
|
|
||||||
removeMirrorImage();
|
|
||||||
if (item) {
|
|
||||||
classes.rm(item, 'gu-transit');
|
|
||||||
}
|
|
||||||
if (_renderTimer) {
|
|
||||||
clearTimeout(_renderTimer);
|
|
||||||
}
|
|
||||||
drake.dragging = false;
|
|
||||||
if (_lastDropTarget) {
|
|
||||||
drake.emit('out', item, _lastDropTarget, _source);
|
|
||||||
}
|
|
||||||
drake.emit('dragend', item);
|
|
||||||
_source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isInitialPlacement (target, s) {
|
|
||||||
var sibling;
|
|
||||||
if (s !== void 0) {
|
|
||||||
sibling = s;
|
|
||||||
} else if (_mirror) {
|
|
||||||
sibling = _currentSibling;
|
|
||||||
} else {
|
|
||||||
sibling = nextEl(_copy || _item);
|
|
||||||
}
|
|
||||||
return target === _source && sibling === _initialSibling;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findDropTarget (elementBehindCursor, clientX, clientY) {
|
|
||||||
var target = elementBehindCursor;
|
|
||||||
while (target && !accepted()) {
|
|
||||||
target = target.parentElement;
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
|
|
||||||
function accepted () {
|
|
||||||
var droppable = isContainer(target);
|
|
||||||
if (droppable === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var immediate = getImmediateChild(target, elementBehindCursor);
|
|
||||||
var reference = getReference(target, immediate, clientX, clientY);
|
|
||||||
var initial = isInitialPlacement(target, reference);
|
|
||||||
if (initial) {
|
|
||||||
return true; // should always be able to drop it right back where it was
|
|
||||||
}
|
|
||||||
return o.accepts(_item, target, _source, reference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function drag (e) {
|
|
||||||
if (!_mirror) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var clientX = getCoord('clientX', e);
|
|
||||||
var clientY = getCoord('clientY', e);
|
|
||||||
var x = clientX - _offsetX;
|
|
||||||
var y = clientY - _offsetY;
|
|
||||||
|
|
||||||
_mirror.style.left = x + 'px';
|
|
||||||
_mirror.style.top = y + 'px';
|
|
||||||
|
|
||||||
var item = _copy || _item;
|
|
||||||
var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);
|
|
||||||
var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);
|
|
||||||
var changed = dropTarget !== null && dropTarget !== _lastDropTarget;
|
|
||||||
if (changed || dropTarget === null) {
|
|
||||||
out();
|
|
||||||
_lastDropTarget = dropTarget;
|
|
||||||
over();
|
|
||||||
}
|
|
||||||
if (dropTarget === _source && _copy && !o.copySortSource) {
|
|
||||||
if (item.parentElement) {
|
|
||||||
item.parentElement.removeChild(item);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var reference;
|
|
||||||
var immediate = getImmediateChild(dropTarget, elementBehindCursor);
|
|
||||||
if (immediate !== null) {
|
|
||||||
reference = getReference(dropTarget, immediate, clientX, clientY);
|
|
||||||
} else if (o.revertOnSpill === true && !_copy) {
|
|
||||||
reference = _initialSibling;
|
|
||||||
dropTarget = _source;
|
|
||||||
} else {
|
|
||||||
if (_copy && item.parentElement) {
|
|
||||||
item.parentElement.removeChild(item);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
reference === null ||
|
|
||||||
reference !== item &&
|
|
||||||
reference !== nextEl(item) &&
|
|
||||||
reference !== _currentSibling
|
|
||||||
) {
|
|
||||||
_currentSibling = reference;
|
|
||||||
dropTarget.insertBefore(item, reference);
|
|
||||||
drake.emit('shadow', item, dropTarget, _source);
|
|
||||||
}
|
|
||||||
function moved (type) { drake.emit(type, item, _lastDropTarget, _source); }
|
|
||||||
function over () { if (changed) { moved('over'); } }
|
|
||||||
function out () { if (_lastDropTarget) { moved('out'); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
function spillOver (el) {
|
|
||||||
classes.rm(el, 'gu-hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
function spillOut (el) {
|
|
||||||
if (drake.dragging) { classes.add(el, 'gu-hide'); }
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderMirrorImage () {
|
|
||||||
if (_mirror) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var rect = _item.getBoundingClientRect();
|
|
||||||
_mirror = _item.cloneNode(true);
|
|
||||||
_mirror.style.width = getRectWidth(rect) + 'px';
|
|
||||||
_mirror.style.height = getRectHeight(rect) + 'px';
|
|
||||||
classes.rm(_mirror, 'gu-transit');
|
|
||||||
classes.add(_mirror, 'gu-mirror');
|
|
||||||
o.mirrorContainer.appendChild(_mirror);
|
|
||||||
touchy(documentElement, 'add', 'mousemove', drag);
|
|
||||||
classes.add(o.mirrorContainer, 'gu-unselectable');
|
|
||||||
drake.emit('cloned', _mirror, _item, 'mirror');
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeMirrorImage () {
|
|
||||||
if (_mirror) {
|
|
||||||
classes.rm(o.mirrorContainer, 'gu-unselectable');
|
|
||||||
touchy(documentElement, 'remove', 'mousemove', drag);
|
|
||||||
_mirror.parentElement.removeChild(_mirror);
|
|
||||||
_mirror = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getImmediateChild (dropTarget, target) {
|
|
||||||
var immediate = target;
|
|
||||||
while (immediate !== dropTarget && immediate.parentElement !== dropTarget) {
|
|
||||||
immediate = immediate.parentElement;
|
|
||||||
}
|
|
||||||
if (immediate === documentElement) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return immediate;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getReference (dropTarget, target, x, y) {
|
|
||||||
var horizontal = o.direction === 'horizontal';
|
|
||||||
var reference = target !== dropTarget ? inside() : outside();
|
|
||||||
return reference;
|
|
||||||
|
|
||||||
function outside () { // slower, but able to figure out any position
|
|
||||||
var len = dropTarget.children.length;
|
|
||||||
var i;
|
|
||||||
var el;
|
|
||||||
var rect;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
el = dropTarget.children[i];
|
|
||||||
rect = el.getBoundingClientRect();
|
|
||||||
if (horizontal && rect.left > x) { return el; }
|
|
||||||
if (!horizontal && rect.top > y) { return el; }
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function inside () { // faster, but only available if dropped inside a child element
|
|
||||||
var rect = target.getBoundingClientRect();
|
|
||||||
if (horizontal) {
|
|
||||||
return resolve(x > rect.left + getRectWidth(rect) / 2);
|
|
||||||
}
|
|
||||||
return resolve(y > rect.top + getRectHeight(rect) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolve (after) {
|
|
||||||
return after ? nextEl(target) : target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isCopy (item, container) {
|
|
||||||
return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function touchy (el, op, type, fn) {
|
|
||||||
var touch = {
|
|
||||||
mouseup: 'touchend',
|
|
||||||
mousedown: 'touchstart',
|
|
||||||
mousemove: 'touchmove'
|
|
||||||
};
|
|
||||||
var microsoft = {
|
|
||||||
mouseup: 'MSPointerUp',
|
|
||||||
mousedown: 'MSPointerDown',
|
|
||||||
mousemove: 'MSPointerMove'
|
|
||||||
};
|
|
||||||
if (global.navigator.msPointerEnabled) {
|
|
||||||
crossvent[op](el, microsoft[type], fn);
|
|
||||||
}
|
|
||||||
crossvent[op](el, touch[type], fn);
|
|
||||||
crossvent[op](el, type, fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function whichMouseButton (e) {
|
|
||||||
if (e.buttons !== void 0) { return e.buttons; }
|
|
||||||
if (e.which !== void 0) { return e.which; }
|
|
||||||
var button = e.button;
|
|
||||||
if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575
|
|
||||||
return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOffset (el) {
|
|
||||||
var rect = el.getBoundingClientRect();
|
|
||||||
return {
|
|
||||||
left: rect.left + getScroll('scrollLeft', 'pageXOffset'),
|
|
||||||
top: rect.top + getScroll('scrollTop', 'pageYOffset')
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getScroll (scrollProp, offsetProp) {
|
|
||||||
if (typeof global[offsetProp] !== 'undefined') {
|
|
||||||
return global[offsetProp];
|
|
||||||
}
|
|
||||||
var documentElement = document.documentElement;
|
|
||||||
if (documentElement.clientHeight) {
|
|
||||||
return documentElement[scrollProp];
|
|
||||||
}
|
|
||||||
var body = document.body;
|
|
||||||
return body[scrollProp];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getElementBehindPoint (point, x, y) {
|
|
||||||
var p = point || {};
|
|
||||||
var state = p.className;
|
|
||||||
var el;
|
|
||||||
p.className += ' gu-hide';
|
|
||||||
el = document.elementFromPoint(x, y);
|
|
||||||
p.className = state;
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
function never () { return false; }
|
|
||||||
function always () { return true; }
|
|
||||||
function getRectWidth (rect) { return rect.width || (rect.right - rect.left); }
|
|
||||||
function getRectHeight (rect) { return rect.height || (rect.bottom - rect.top); }
|
|
||||||
function isInput (el) { return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA'; }
|
|
||||||
|
|
||||||
function nextEl (el) {
|
|
||||||
return el.nextElementSibling || manually();
|
|
||||||
function manually () {
|
|
||||||
var sibling = el;
|
|
||||||
do {
|
|
||||||
sibling = sibling.nextSibling;
|
|
||||||
} while (sibling && sibling.nodeType !== 1);
|
|
||||||
return sibling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEventHost (e) {
|
|
||||||
// on touchend event, we have to use `e.changedTouches`
|
|
||||||
// see http://stackoverflow.com/questions/7192563/touchend-event-properties
|
|
||||||
// see https://github.com/bevacqua/dragula/issues/34
|
|
||||||
if (e.targetTouches && e.targetTouches.length) {
|
|
||||||
return e.targetTouches[0];
|
|
||||||
}
|
|
||||||
if (e.changedTouches && e.changedTouches.length) {
|
|
||||||
return e.changedTouches[0];
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCoord (coord, e) {
|
|
||||||
var host = getEventHost(e);
|
|
||||||
var missMap = {
|
|
||||||
pageX: 'clientX', // IE8
|
|
||||||
pageY: 'clientY' // IE8
|
|
||||||
};
|
|
||||||
if (coord in missMap && !(coord in host) && missMap[coord] in host) {
|
|
||||||
coord = missMap[coord];
|
|
||||||
}
|
|
||||||
return host[coord];
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = dragula;
|
|
|
@ -1,14 +0,0 @@
|
||||||
.gu-mirror
|
|
||||||
position fixed !important
|
|
||||||
margin 0 !important
|
|
||||||
z-index 9999 !important
|
|
||||||
opacity 0.8
|
|
||||||
|
|
||||||
.gu-hide
|
|
||||||
display none !important
|
|
||||||
|
|
||||||
.gu-unselectable
|
|
||||||
user-select none !important
|
|
||||||
|
|
||||||
.gu-transit
|
|
||||||
opacity 0.2
|
|
|
@ -1,194 +0,0 @@
|
||||||
body {
|
|
||||||
background-color: #942A57;
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 760px;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
*, *:before, *:after {
|
|
||||||
-webkit-box-sizing: inherit;
|
|
||||||
-moz-box-sizing: inherit;
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
body, input, button {
|
|
||||||
font-family: Georgia, Helvetica;
|
|
||||||
font-size: 17px;
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
background-color: #AC5C7E;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
border-bottom: 5px solid #A13462;
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 div {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tagline {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
.tagline-text {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.__slackin {
|
|
||||||
float: right;
|
|
||||||
margin-left: 10px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.promo {
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-style: italic;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: #ff4020;
|
|
||||||
border-bottom: 5px solid #c00;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
a,
|
|
||||||
a:hover {
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre code {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
display: block;
|
|
||||||
text-align: right;
|
|
||||||
margin-top: -10px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parent {
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
margin: 50px 0;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
background-color: #ecf0f1;
|
|
||||||
padding: 10px;
|
|
||||||
color: #942A57;
|
|
||||||
border: 0;
|
|
||||||
margin: 5px 0;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: #ecf0f1;
|
|
||||||
color: #942A57;
|
|
||||||
border: 0;
|
|
||||||
padding: 18px 12px;
|
|
||||||
margin-left: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
background-color: #e74c3c;
|
|
||||||
color: #ecf0f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gh-fork {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dragula-specific example page styles */
|
|
||||||
.wrapper {
|
|
||||||
display: table;
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
display: table-cell;
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
.container:nth-child(odd) {
|
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* note that styling gu-mirror directly is a bad practice because it's too generic.
|
|
||||||
* you're better off giving the draggable elements a unique class and styling that directly!
|
|
||||||
*/
|
|
||||||
.container > div,
|
|
||||||
.gu-mirror {
|
|
||||||
margin: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: rgba(0, 0, 0, 0.2);
|
|
||||||
transition: opacity 0.4s ease-in-out;
|
|
||||||
}
|
|
||||||
.container > div {
|
|
||||||
cursor: move;
|
|
||||||
cursor: grab;
|
|
||||||
cursor: -moz-grab;
|
|
||||||
cursor: -webkit-grab;
|
|
||||||
}
|
|
||||||
.gu-mirror {
|
|
||||||
cursor: grabbing;
|
|
||||||
cursor: -moz-grabbing;
|
|
||||||
cursor: -webkit-grabbing;
|
|
||||||
}
|
|
||||||
.container .ex-moved {
|
|
||||||
background-color: #e74c3c;
|
|
||||||
}
|
|
||||||
.container.ex-over {
|
|
||||||
background-color: rgba(255, 255, 255, 0.3);
|
|
||||||
}
|
|
||||||
#left-lovehandles > div,
|
|
||||||
#right-lovehandles > div {
|
|
||||||
cursor: initial;
|
|
||||||
}
|
|
||||||
.handle {
|
|
||||||
padding: 0 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
|
||||||
cursor: move;
|
|
||||||
}
|
|
||||||
.image-thing {
|
|
||||||
margin: 20px 0;
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var crossvent = require('crossvent');
|
|
||||||
var sortable = $('sortable');
|
|
||||||
|
|
||||||
dragula([$('left-defaults'), $('right-defaults')]);
|
|
||||||
dragula([$('left-copy'), $('right-copy')], { copy: true });
|
|
||||||
dragula([$('left-events'), $('right-events')])
|
|
||||||
.on('drag', function (el) {
|
|
||||||
el.className = el.className.replace('ex-moved', '');
|
|
||||||
})
|
|
||||||
.on('drop', function (el) {
|
|
||||||
el.className += ' ex-moved';
|
|
||||||
})
|
|
||||||
.on('over', function (el, container) {
|
|
||||||
container.className += ' ex-over';
|
|
||||||
})
|
|
||||||
.on('out', function (el, container) {
|
|
||||||
container.className = container.className.replace('ex-over', '');
|
|
||||||
});
|
|
||||||
dragula([$('left-rollbacks'), $('right-rollbacks')], { revertOnSpill: true });
|
|
||||||
dragula([$('left-lovehandles'), $('right-lovehandles')], {
|
|
||||||
moves: function (el, container, handle) {
|
|
||||||
return handle.className === 'handle';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dragula([$('left-rm-spill'), $('right-rm-spill')], { removeOnSpill: true });
|
|
||||||
dragula([$('left-copy-1tomany'), $('right-copy-1tomany')], {
|
|
||||||
copy: function (el, source) {
|
|
||||||
return source === $('left-copy-1tomany');
|
|
||||||
},
|
|
||||||
accepts: function (el, target) {
|
|
||||||
return target !== $('left-copy-1tomany');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dragula([sortable]);
|
|
||||||
|
|
||||||
crossvent.add(sortable, 'click', clickHandler);
|
|
||||||
|
|
||||||
function clickHandler (e) {
|
|
||||||
var target = e.target;
|
|
||||||
if (target === sortable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
target.innerHTML += ' [click!]';
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
target.innerHTML = target.innerHTML.replace(/ \[click!\]/g, '');
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
function $ (id) {
|
|
||||||
return document.getElementById(id);
|
|
||||||
}
|
|
BIN
dashboard-ui/bower_components/dragula.js/favicon.ico
vendored
Before Width: | Height: | Size: 32 KiB |
205
dashboard-ui/bower_components/dragula.js/index.html
vendored
|
@ -1,205 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<meta charset='utf-8'>
|
|
||||||
<link rel="shortcut icon" href="favicon.ico">
|
|
||||||
<link href='dist/dragula.css' rel='stylesheet' type='text/css' />
|
|
||||||
<link href='example/example.css' rel='stylesheet' type='text/css' />
|
|
||||||
<title>dragula</title>
|
|
||||||
<h1><a href='https://github.com/bevacqua/dragula'><img src='resources/logo.svg' onerror='this.src="resources/logo.png"' alt='dragula'/></a></h1>
|
|
||||||
<h3 class='tagline'><span class='tagline-text'>Drag and drop so simple it hurts</span><script async defer src='https://dragula-slackin.herokuapp.com/slackin.js'></script></h3>
|
|
||||||
<a href='https://github.com/bevacqua/dragula'>
|
|
||||||
<img class='gh-fork' src='https://camo.githubusercontent.com/52760788cde945287fbb584134c4cbc2bc36f904/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f77686974655f6666666666662e706e67' alt='Fork me on GitHub' data-canonical-src='https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png' />
|
|
||||||
</a>
|
|
||||||
<div class='examples'>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>Move stuff between these two containers. Note how the stuff gets inserted near the mouse pointer? Great stuff.</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-defaults' class='container'>
|
|
||||||
<div>You can move these elements between these two containers</div>
|
|
||||||
<div>Moving them anywhere else isn't quite possible</div>
|
|
||||||
<div>Anything can be moved around. That includes images, <a href='https://github.com/bevacqua/dragula'>links</a>, or any other nested elements.
|
|
||||||
<div class='image-thing'><img src='resources/icon.svg' onerror='this.src="resources/icon.png"' alt='dragula'/></div><sub>(You can still click on links, as usual!)</sub>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-defaults' class='container'>
|
|
||||||
<div>There's also the possibility of moving elements around in the same container, changing their position</div>
|
|
||||||
<div>This is the default use case. You only need to specify the containers you want to use</div>
|
|
||||||
<div>More interactive use cases lie ahead</div>
|
|
||||||
<div>Moving <code><input/></code> elements works just fine. You can still focus them, too. <input placeholder='See?' /></div>
|
|
||||||
<div>Make sure to check out the <a href='https://github.com/bevacqua/dragula#readme'>documentation on GitHub!</a></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)]);
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>There are plenty of events along the lifetime of a drag event. Check out <a href='https://github.com/bevacqua/dragula#drakeon-events'>all of them</a> in the docs!</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-events' class='container'>
|
|
||||||
<div>As soon as you start dragging an element, a <code>drag</code> event is fired</div>
|
|
||||||
<div>Whenever an element is cloned because <code>copy: true</code>, a <code>cloned</code> event fires</div>
|
|
||||||
<div>The <code>shadow</code> event fires whenever the placeholder showing where an element would be dropped is moved to a different container or position</div>
|
|
||||||
<div>A <code>drop</code> event is fired whenever an element is dropped anywhere other than its origin <em>(where it was initially dragged from)</em></div>
|
|
||||||
</div>
|
|
||||||
<div id='right-events' class='container'>
|
|
||||||
<div>If the element gets removed from the DOM as a result of dropping outside of any containers, a <code>remove</code> event gets fired</div>
|
|
||||||
<div>A <code>cancel</code> event is fired when an element would be dropped onto an invalid target, but retains its original placement instead</div>
|
|
||||||
<div>The <code>over</code> event fires when you drag something over a container, and <code>out</code> fires when you drag it away from the container</div>
|
|
||||||
<div>Lastly, a <code>dragend</code> event is fired whenever a drag operation ends, regardless of whether it ends in a cancellation, removal, or drop</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)])
|
|
||||||
.on('drag', function (el) {
|
|
||||||
el.className = el.className.replace('ex-moved', '');
|
|
||||||
}).on('drop', function (el) {
|
|
||||||
el.className += ' ex-moved';
|
|
||||||
}).on('over', function (el, container) {
|
|
||||||
container.className += ' ex-over';
|
|
||||||
}).on('out', function (el, container) {
|
|
||||||
container.className = container.className.replace('ex-over', '');
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>Need to be able to quickly delete stuff when it spills out of the chosen containers? Note how you can easily sort the items in any containers by just dragging and dropping.</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-rm-spill' class='container'>
|
|
||||||
<div>Anxious Cab Driver</div>
|
|
||||||
<div>Thriving Venture</div>
|
|
||||||
<div>Such <a href='http://ponyfoo.com'>a good blog</a></div>
|
|
||||||
<div>Calm Clam</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-rm-spill' class='container'>
|
|
||||||
<div>Banana Boat</div>
|
|
||||||
<div>Orange Juice</div>
|
|
||||||
<div>Cuban Cigar</div>
|
|
||||||
<div>Terrible Comedian</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(single)], {
|
|
||||||
removeOnSpill: true
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>By default, dropping an element outside of any known containers will keep the element in the last place it went over. You can make elements go back to origin if they're dropped outside of known containers, too.</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-rollbacks' class='container'>
|
|
||||||
<div>Moving items between containers works as usual</div>
|
|
||||||
<div>If you try to drop an item outside of any containers, though, it'll retain its original position</div>
|
|
||||||
<div>When that happens, a <code>cancel</code> event will be raised</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-rollbacks' class='container'>
|
|
||||||
<div>Note that the dragged element will go back to the place you originally dragged it from, even if you move it over other containers</div>
|
|
||||||
<div>This is useful if you want to ensure drop events only happen when the user intends for them to happen explicitly, avoiding surprises</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)], {
|
|
||||||
revertOnSpill: true
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>Copying stuff is common too, so we made it easy for you.</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-copy' class='container'>
|
|
||||||
<div>When elements are copyable, they can't be sorted in their origin container</div>
|
|
||||||
<div>Copying prevents original elements from being dragged. A copy gets created and <em>that</em> gets dragged instead</div>
|
|
||||||
<div>Whenever that happens, a <code>cloned</code> event is raised</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-copy' class='container'>
|
|
||||||
<div>Note that the clones get destroyed if they're not dropped into another container</div>
|
|
||||||
<div>You'll be dragging a copy, so when they're dropped into another container you'll see the duplication.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)], {
|
|
||||||
copy: true
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>Copying stuff from only one of the containers and sorting on the other one? No problem!</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-copy-1tomany' class='container'>
|
|
||||||
<div>When elements are copyable, they can't be sorted in their origin container</div>
|
|
||||||
<div>Copying prevents original elements from being dragged. A copy gets created and <em>that</em> gets dragged instead</div>
|
|
||||||
<div>Whenever that happens, a <code>cloned</code> event is raised</div>
|
|
||||||
<div>Note that the clones get destroyed if they're not dropped into another container</div>
|
|
||||||
<div>You'll be dragging a copy, so when they're dropped into another container you'll see the duplication.</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-copy-1tomany' class='container'>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)], {
|
|
||||||
copy: function (el, source) {
|
|
||||||
return source === left
|
|
||||||
},
|
|
||||||
accepts: function (el, target) {
|
|
||||||
return target !== left
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label for='hy'>Drag handles float your cruise?</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='left-lovehandles' class='container'>
|
|
||||||
<div><span class='handle'>+</span>Move me, but you can use the plus sign to drag me around.</div>
|
|
||||||
<div><span class='handle'>+</span>Note that <code>handle</code> element in the <code>moves</code> handler is just the original event target.</div>
|
|
||||||
</div>
|
|
||||||
<div id='right-lovehandles' class='container'>
|
|
||||||
<div><span class='handle'>+</span>This might also be useful if you want multiple children of an element to be able to trigger a drag event.</div>
|
|
||||||
<div><span class='handle'>+</span>You can also use the <code>moves</code> option to determine whether an element can be dragged at all from a container, <em>drag handle or not</em>.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(left), document.getElementById(right)], {
|
|
||||||
moves: function (el, container, handle) {
|
|
||||||
return handle.className === 'handle';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
<div>There are a few similar mechanisms to determine whether an element can be dragged from a certain container <a href='https://github.com/bevacqua/dragula#optionsmoves'>(<code>moves</code>)</a>, whether an element can be dropped into a certain container at a certain position <a href='https://github.com/bevacqua/dragula#optionsaccepts'>(<code>accepts</code>)</a>, and whether an element is able to originate a drag event <a href='https://github.com/bevacqua/dragula#optionsinvalid'>(<code>invalid</code>)</a>.</div>
|
|
||||||
</div>
|
|
||||||
<div class='parent'>
|
|
||||||
<label><strong>Click or Drag!</strong> Fires a click when the mouse button is released before a <code>mousemove</code> event, otherwise a drag event is fired. No extra configuration is necessary.</label>
|
|
||||||
<div class='wrapper'>
|
|
||||||
<div id='sortable' class='container'>
|
|
||||||
<div>Clicking on these elements triggers a regular <code>click</code> event you can listen to.</div>
|
|
||||||
<div>Try dragging or clicking on this element.</div>
|
|
||||||
<div>Note how you can click normally?</div>
|
|
||||||
<div>Drags don't trigger click events.</div>
|
|
||||||
<div>Clicks don't end up in a drag, either.</div>
|
|
||||||
<div>This is useful if you have elements that can be both clicked or dragged.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
dragula([document.getElementById(container)]);
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h3 class='promo'>Who couldn't love a pun that good? — <a href='http://thenextweb.com/dd/2015/07/20/less-of-a-drag-maaaaaaaan'>The Next Web</a></h3>
|
|
||||||
<h3>Get it on GitHub! <a href='https://github.com/bevacqua/dragula'>bevacqua/dragula</a></h3>
|
|
||||||
<script src='dist/dragula.js'></script>
|
|
||||||
<script src='example/example.min.js'></script>
|
|
20
dashboard-ui/bower_components/dragula.js/license
vendored
|
@ -1,20 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright © 2015 Nicolas Bevacqua
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
@ -1,72 +0,0 @@
|
||||||
{
|
|
||||||
"name": "dragula",
|
|
||||||
"version": "3.5.1",
|
|
||||||
"description": "Drag and drop so simple it hurts",
|
|
||||||
"main": "dragula.js",
|
|
||||||
"scripts": {
|
|
||||||
"build": "npm run scripts && npm run styles",
|
|
||||||
"deploy": "npm run build && npm run deployment && npm run sync",
|
|
||||||
"deploy-plugins": "npm run deploy-react ; npm run deploy-angular ; cd ../dragula",
|
|
||||||
"deploy-react": "cd ../react-dragula ; npm i -S dragula@* ; git commit package.json -m 'bumped dragula version'; npm run deploy",
|
|
||||||
"deploy-angular": "cd ../angular-dragula ; npm i -S dragula@* ; git commit package.json -m 'bumped dragula version'; npm run deploy",
|
|
||||||
"deployment": "git add dist && npm version ${BUMP:-\"patch\"} --no-git-tag-version && git add package.json && git commit -am \"Autogenerated pre-deployment commit\" && bower version ${BUMP:-\"patch\"} && git reset HEAD~2 && git add . && git commit -am \"Release $(cat package.json | jq -r .version)\" && git push --tags && npm publish && git push",
|
|
||||||
"scripts": "jshint . && browserify -s dragula -do dist/dragula.js dragula.js && uglifyjs -m -c -o dist/dragula.min.js dist/dragula.js",
|
|
||||||
"start": "watchify -dvo example/example.min.js example/example.js & watchify -dvs dragula -o dist/dragula.js dragula.js & stylus -w dragula.styl --import node_modules/nib -o dist",
|
|
||||||
"styles": "stylus dragula.styl --import node_modules/nib -o dist && cleancss dist/dragula.css -o dist/dragula.min.css",
|
|
||||||
"sync": "git checkout gh-pages ; git merge master ; git push ; git checkout master",
|
|
||||||
"lint": "jshint . --reporter node_modules/jshint-stylish/index.js",
|
|
||||||
"codestyle": "xo",
|
|
||||||
"test": "npm run lint && npm run codestyle && browserify test/*.js | testron",
|
|
||||||
"test-watch": "hihat test/*.js -p tap-dev-tool"
|
|
||||||
},
|
|
||||||
"xo": {
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"space": true,
|
|
||||||
"ignores": [
|
|
||||||
"dist/**"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"consistent-return": 0,
|
|
||||||
"no-void": 0,
|
|
||||||
"no-inline-comments": 0,
|
|
||||||
"object-curly-spacing": 0,
|
|
||||||
"space-before-function-paren": 0,
|
|
||||||
"no-undef": 0,
|
|
||||||
"brace-style": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/bevacqua/dragula.git"
|
|
||||||
},
|
|
||||||
"author": "Nicolas Bevacqua <nicolasbevacqua@gmail.com> (http://bevacqua.io/)",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/bevacqua/dragula/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/bevacqua/dragula",
|
|
||||||
"dependencies": {
|
|
||||||
"contra": "1.9.1",
|
|
||||||
"crossvent": "1.5.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"bower": "1.5.2",
|
|
||||||
"browserify": "11.0.0",
|
|
||||||
"clean-css": "3.3.6",
|
|
||||||
"electron-prebuilt": "0.30.1",
|
|
||||||
"hihat": "1.2.1",
|
|
||||||
"jshint": "2.8.0",
|
|
||||||
"jshint-stylish": "2.0.1",
|
|
||||||
"nib": "1.1.0",
|
|
||||||
"stylus": "0.52.0",
|
|
||||||
"tap-dev-tool": "1.3.0",
|
|
||||||
"tape": "4.0.1",
|
|
||||||
"testron": "1.2.0",
|
|
||||||
"uglify-js": "2.4.24",
|
|
||||||
"watchify": "3.3.0",
|
|
||||||
"xo": "0.7.1"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,314 +0,0 @@
|
||||||
[![logo.png][3]][2]
|
|
||||||
|
|
||||||
[![Travis CI][5]][4] [![Slack Status][17]][18] [![Flattr][6]][7] [![Patreon][19]][20]
|
|
||||||
|
|
||||||
> Drag and drop so simple it hurts
|
|
||||||
|
|
||||||
Browser support includes every sane browser and **IE7+**. <sub>_(Granted you polyfill the functional `Array` methods in ES5)_</sub>
|
|
||||||
|
|
||||||
Framework support includes vanilla JavaScript, Angular, and React.
|
|
||||||
|
|
||||||
- Official [Angular bridge][8] for `dragula` [_(demo)_][10]
|
|
||||||
- Official [React bridge][9] for `dragula` [_(demo)_][11]
|
|
||||||
|
|
||||||
# Demo
|
|
||||||
|
|
||||||
[![demo.png][1]][2]
|
|
||||||
|
|
||||||
Try out the [demo][2]!
|
|
||||||
|
|
||||||
# Inspiration
|
|
||||||
|
|
||||||
Have you ever wanted a drag and drop library that just works? That doesn't just depend on bloated frameworks, that has great support? That actually understands where to place the elements when they are dropped? That doesn't need you to do a zillion things to get it to work? Well, so did I!
|
|
||||||
|
|
||||||
# Features
|
|
||||||
|
|
||||||
- Super easy to set up
|
|
||||||
- No bloated dependencies
|
|
||||||
- **Figures out sort order** on its own
|
|
||||||
- A shadow where the item would be dropped offers **visual feedback**
|
|
||||||
- Touch events!
|
|
||||||
- Seamlessly handles clicks *without any configuration*
|
|
||||||
|
|
||||||
# Install
|
|
||||||
|
|
||||||
You can get it on npm.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm install dragula --save
|
|
||||||
```
|
|
||||||
|
|
||||||
Or bower, too.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bower install dragula --save
|
|
||||||
```
|
|
||||||
|
|
||||||
If you're not using either package manager, you can use `dragula` by downloading the [files in the `dist` folder][15]. We **strongly suggest** using `npm`, though.
|
|
||||||
|
|
||||||
##### Including the CSS!
|
|
||||||
|
|
||||||
There's [a few CSS styles][16] you need to incorporate in order for `dragula` to work as expected.
|
|
||||||
|
|
||||||
You can add them by including [`dist/dragula.css`][12] or [`dist/dragula.min.css`][13] in your document. If you're using Stylus, you can include the styles using the directive below.
|
|
||||||
|
|
||||||
```styl
|
|
||||||
@import 'node_modules/dragula/dragula'
|
|
||||||
```
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
Dragula provides the easiest possible API to make drag and drop a breeze in your applications.
|
|
||||||
|
|
||||||
## `dragula(containers?, options?)`
|
|
||||||
|
|
||||||
By default, `dragula` will allow the user to drag an element in any of the `containers` and drop it in any other container in the list. If the element is dropped anywhere that's not one of the `containers`, the event will be gracefully cancelled according to the `revertOnSpill` and `removeOnSpill` options.
|
|
||||||
|
|
||||||
Note that dragging is only triggered on left clicks, and only if no meta keys are pressed.
|
|
||||||
|
|
||||||
The example below allows the user to drag elements from `left` into `right`, and from `right` into `left`.
|
|
||||||
|
|
||||||
```js
|
|
||||||
dragula([document.querySelector('#left'), document.querySelector('#right')]);
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also provide an `options` object. Here's an **overview of the default values**.
|
|
||||||
|
|
||||||
```js
|
|
||||||
dragula(containers, {
|
|
||||||
isContainer: function (el) {
|
|
||||||
return false; // only elements in drake.containers will be taken into account
|
|
||||||
},
|
|
||||||
moves: function (el, source, handle, sibling) {
|
|
||||||
return true; // elements are always draggable by default
|
|
||||||
},
|
|
||||||
accepts: function (el, target, source, sibling) {
|
|
||||||
return true; // elements can be dropped in any of the `containers` by default
|
|
||||||
},
|
|
||||||
invalid: function (el, target) {
|
|
||||||
return false; // don't prevent any drags from initiating by default
|
|
||||||
},
|
|
||||||
direction: 'vertical', // Y axis is considered when determining where an element would be dropped
|
|
||||||
copy: false, // elements are moved by default, not copied
|
|
||||||
copySortSource: false, // elements are moved by default, not copied
|
|
||||||
revertOnSpill: false, // spilling will put the element back where it was dragged from, if this is true
|
|
||||||
removeOnSpill: false, // spilling will `.remove` the element, if this is true
|
|
||||||
mirrorContainer: document.body, // set the element that gets mirror elements appended
|
|
||||||
ignoreInputTextSelection: true // allows users to select input text, see details below
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
You can omit the `containers` argument and add containers dynamically later on.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var drake = dragula({
|
|
||||||
copy: true
|
|
||||||
});
|
|
||||||
drake.containers.push(container);
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also set the `containers` from the `options` object.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var drake = dragula({ containers: containers });
|
|
||||||
```
|
|
||||||
|
|
||||||
And you could also not set any arguments, which defaults to a drake without containers and with the default options.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var drake = dragula();
|
|
||||||
```
|
|
||||||
|
|
||||||
The options are detailed below.
|
|
||||||
|
|
||||||
#### `options.containers`
|
|
||||||
|
|
||||||
Setting this option is effectively the same as passing the containers in the first argument to `dragula(containers, options)`.
|
|
||||||
|
|
||||||
#### `options.isContainer`
|
|
||||||
|
|
||||||
Besides the containers that you pass to `dragula`, or the containers you dynamically `push` or `unshift` from [drake.containers](#drakecontainers), you can also use this method to specify any sort of logic that defines what is a container for this particular `drake` instance.
|
|
||||||
|
|
||||||
The example below dynamically treats all DOM elements with a CSS class of `dragula-container` as dragula containers for this `drake`.
|
|
||||||
|
|
||||||
```js
|
|
||||||
var drake = dragula({
|
|
||||||
isContainer: function (el) {
|
|
||||||
return el.classList.contains('dragula-container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `options.moves`
|
|
||||||
|
|
||||||
You can define a `moves` method which will be invoked with `(el, source, handle, sibling)` whenever an element is clicked. If this method returns `false`, a drag event won't begin, and the event won't be prevented either. The `handle` element will be the original click target, which comes in handy to test if that element is an expected _"drag handle"_.
|
|
||||||
|
|
||||||
#### `options.accepts`
|
|
||||||
|
|
||||||
You can set `accepts` to a method with the following signature: `(el, target, source, sibling)`. It'll be called to make sure that an element `el`, that came from container `source`, can be dropped on container `target` before a `sibling` element. The `sibling` can be `null`, which would mean that the element would be placed as the last element in the container. Note that if `options.copy` is set to `true`, `el` will be set to the copy, instead of the originally dragged element.
|
|
||||||
|
|
||||||
Also note that **the position where a drag starts is always going to be a valid place where to drop the element**, even if `accepts` returned `false` for all cases.
|
|
||||||
|
|
||||||
#### `options.copy`
|
|
||||||
|
|
||||||
If `copy` is set to `true` _(or a method that returns `true`)_, items will be copied rather than moved. This implies the following differences:
|
|
||||||
|
|
||||||
Event | Move | Copy
|
|
||||||
----------|------------------------------------------|---------------------------------------------
|
|
||||||
`drag` | Element will be concealed from `source` | Nothing happens
|
|
||||||
`drop` | Element will be moved into `target` | Element will be cloned into `target`
|
|
||||||
`remove` | Element will be removed from DOM | Nothing happens
|
|
||||||
`cancel` | Element will stay in `source` | Nothing happens
|
|
||||||
|
|
||||||
If a method is passed, it'll be called whenever an element starts being dragged in order to decide whether it should follow `copy` behavior or not. Consider the following example.
|
|
||||||
|
|
||||||
```js
|
|
||||||
copy: function (el, source) {
|
|
||||||
return el.className === 'you-may-copy-us';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
#### `options.copySortSource`
|
|
||||||
|
|
||||||
If `copy` is set to `true` _(or a method that returns `true`)_ and `copySortSource` is `true` as well, users will be able to sort elements in `copy`-source containers.
|
|
||||||
|
|
||||||
```js
|
|
||||||
copy: true,
|
|
||||||
copySortSource: true
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `options.revertOnSpill`
|
|
||||||
|
|
||||||
By default, spilling an element outside of any containers will move the element back to the _drop position previewed by the feedback shadow_. Setting `revertOnSpill` to `true` will ensure elements dropped outside of any approved containers are moved back to the source element where the drag event began, rather than stay at the _drop position previewed by the feedback shadow_.
|
|
||||||
|
|
||||||
#### `options.removeOnSpill`
|
|
||||||
|
|
||||||
By default, spilling an element outside of any containers will move the element back to the _drop position previewed by the feedback shadow_. Setting `removeOnSpill` to `true` will ensure elements dropped outside of any approved containers are removed from the DOM. Note that `remove` events won't fire if `copy` is set to `true`.
|
|
||||||
|
|
||||||
#### `options.direction`
|
|
||||||
|
|
||||||
When an element is dropped onto a container, it'll be placed near the point where the mouse was released. If the `direction` is `'vertical'`, the default value, the Y axis will be considered. Otherwise, if the `direction` is `'horizontal'`, the X axis will be considered.
|
|
||||||
|
|
||||||
#### `options.invalid`
|
|
||||||
|
|
||||||
You can provide an `invalid` method with a `(el, target)` signature. This method should return `true` for elements that shouldn't trigger a drag. Here's the default implementation, which doesn't prevent any drags.
|
|
||||||
|
|
||||||
```js
|
|
||||||
function invalidTarget (el, target) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that `invalid` will be invoked on the DOM element that was clicked and every parent up to immediate children of a `drake` container.
|
|
||||||
|
|
||||||
As an example, you could set `invalid` to return `false` whenever the clicked element _(or any of its parents)_ is an anchor tag.
|
|
||||||
|
|
||||||
```js
|
|
||||||
invalid: function (el) {
|
|
||||||
return el.tagName === 'A';
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `options.mirrorContainer`
|
|
||||||
|
|
||||||
The DOM element where the mirror element displayed while dragging will be appended to. Defaults to `document.body`.
|
|
||||||
|
|
||||||
#### `options.ignoreInputTextSelection`
|
|
||||||
|
|
||||||
When this option is enabled, if the user clicks on an input element the drag won't start until their mouse pointer exits the input. This translates into the user being able to select text in inputs contained inside draggable elements, and still drag the element by moving their mouse outside of the input -- so you get the best of both worlds.
|
|
||||||
|
|
||||||
This option is enabled by default. Turn it off by setting it to `false`. If its disabled your users won't be able to select text in inputs within `dragula` containers with their mouse.
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
The `dragula` method returns a tiny object with a concise API. We'll refer to the API returned by `dragula` as `drake`.
|
|
||||||
|
|
||||||
#### `drake.containers`
|
|
||||||
|
|
||||||
This property contains the collection of containers that was passed to `dragula` when building this `drake` instance. You can `push` more containers and `splice` old containers at will.
|
|
||||||
|
|
||||||
#### `drake.dragging`
|
|
||||||
|
|
||||||
This property will be `true` whenever an element is being dragged.
|
|
||||||
|
|
||||||
#### `drake.start(item)`
|
|
||||||
|
|
||||||
Enter drag mode **without a shadow**. This method is most useful when providing complementary keyboard shortcuts to an existing drag and drop solution. Even though a shadow won't be created at first, the user will get one as soon as they click on `item` and start dragging it around. Note that if they click and drag something else, `.end` will be called before picking up the new item.
|
|
||||||
|
|
||||||
#### `drake.end()`
|
|
||||||
|
|
||||||
Gracefully end the drag event as if using **the last position marked by the preview shadow** as the drop target. The proper `cancel` or `drop` event will be fired, depending on whether the item was dropped back where it was originally lifted from _(which is essentially a no-op that's treated as a `cancel` event)_.
|
|
||||||
|
|
||||||
#### `drake.cancel(revert)`
|
|
||||||
|
|
||||||
If an element managed by `drake` is currently being dragged, this method will gracefully cancel the drag action. You can also pass in `revert` at the method invocation level, effectively producing the same result as if `revertOnSpill` was `true`.
|
|
||||||
|
|
||||||
Note that **a _"cancellation"_ will result in a `cancel` event** only in the following scenarios.
|
|
||||||
|
|
||||||
- `revertOnSpill` is `true`
|
|
||||||
- Drop target _(as previewed by the feedback shadow)_ is the source container **and** the item is dropped in the same position where it was originally dragged from
|
|
||||||
|
|
||||||
#### `drake.remove()`
|
|
||||||
|
|
||||||
If an element managed by `drake` is currently being dragged, this method will gracefully remove it from the DOM.
|
|
||||||
|
|
||||||
#### `drake.on` _(Events)_
|
|
||||||
|
|
||||||
The `drake` is an event emitter. The following events can be tracked using `drake.on(type, listener)`:
|
|
||||||
|
|
||||||
Event Name | Listener Arguments | Event Description
|
|
||||||
-----------|----------------------------------|-------------------------------------------------------------------------------------
|
|
||||||
`drag` | `el, source` | `el` was lifted from `source`
|
|
||||||
`dragend` | `el` | Dragging event for `el` ended with either `cancel`, `remove`, or `drop`
|
|
||||||
`drop` | `el, target, source, sibling` | `el` was dropped into `target` before a `sibling` element, and originally came from `source`
|
|
||||||
`cancel` | `el, container, source` | `el` was being dragged but it got nowhere and went back into `container`, its last stable parent; `el` originally came from `source`
|
|
||||||
`remove` | `el, container, source` | `el` was being dragged but it got nowhere and it was removed from the DOM. Its last stable parent was `container`, and originally came from `source`
|
|
||||||
`shadow` | `el, container, source` | `el`, _the visual aid shadow_, was moved into `container`. May trigger many times as the position of `el` changes, even within the same `container`; `el` originally came from `source`
|
|
||||||
`over` | `el, container, source` | `el` is over `container`, and originally came from `source`
|
|
||||||
`out` | `el, container, source` | `el` was dragged out of `container` or dropped, and originally came from `source`
|
|
||||||
`cloned` | `clone, original, type` | DOM element `original` was cloned as `clone`, of `type` _(`'mirror'` or `'copy'`)_. Fired for mirror images and when `copy: true`
|
|
||||||
|
|
||||||
#### `drake.destroy()`
|
|
||||||
|
|
||||||
Removes all drag and drop events used by `dragula` to manage drag and drop between the `containers`. If `.destroy` is called while an element is being dragged, the drag will be effectively cancelled.
|
|
||||||
|
|
||||||
## CSS
|
|
||||||
|
|
||||||
Dragula uses only four CSS classes. Their purpose is quickly explained below, but you can check [`dist/dragula.css`][12] to see the corresponding CSS rules.
|
|
||||||
|
|
||||||
- `gu-unselectable` is added to the `mirrorContainer` element when dragging. You can use it to style the `mirrorContainer` while something is being dragged.
|
|
||||||
- `gu-transit` is added to the source element when its mirror image is dragged. It just adds opacity to it.
|
|
||||||
- `gu-mirror` is added to the mirror image. It handles fixed positioning and `z-index` _(and removes any prior margins on the element)_. Note that the mirror image is appended to the `mirrorContainer`, not to its initial container. Keep that in mind when styling your elements with nested rules, like `.list .item { padding: 10px; }`.
|
|
||||||
- `gu-hide` is a helper class to apply `display: none` to an element.
|
|
||||||
|
|
||||||
# Contributing
|
|
||||||
|
|
||||||
See [contributing.markdown][14] for details.
|
|
||||||
|
|
||||||
# Support
|
|
||||||
|
|
||||||
There's now a dedicated support channel in Slack. Visit the `dragula` [demo page][2] to get an invite. Support requests won't be handled through the repository anymore.
|
|
||||||
|
|
||||||
# License
|
|
||||||
|
|
||||||
MIT
|
|
||||||
|
|
||||||
[1]: https://github.com/bevacqua/dragula/blob/master/resources/demo.png
|
|
||||||
[2]: http://bevacqua.github.io/dragula/
|
|
||||||
[3]: https://github.com/bevacqua/dragula/blob/master/resources/logo.png
|
|
||||||
[4]: https://travis-ci.org/bevacqua/dragula
|
|
||||||
[5]: https://travis-ci.org/bevacqua/dragula.svg
|
|
||||||
[6]: http://api.flattr.com/button/flattr-badge-large.png
|
|
||||||
[7]: http://flattr.com/thing/4127996/bevacquadragula-on-GitHub
|
|
||||||
[8]: https://github.com/bevacqua/angular-dragula
|
|
||||||
[9]: https://github.com/bevacqua/react-dragula
|
|
||||||
[10]: http://bevacqua.github.io/angular-dragula/
|
|
||||||
[11]: http://bevacqua.github.io/react-dragula/
|
|
||||||
[12]: https://github.com/bevacqua/dragula/blob/master/dist/dragula.css
|
|
||||||
[13]: https://github.com/bevacqua/dragula/blob/master/dist/dragula.min.css
|
|
||||||
[14]: https://github.com/bevacqua/dragula/blob/master/contributing.markdown
|
|
||||||
[15]: https://github.com/bevacqua/dragula/blob/master/dist
|
|
||||||
[16]: #css
|
|
||||||
[17]: https://dragula-slackin.herokuapp.com/badge.svg
|
|
||||||
[18]: https://bevacqua.github.io/dragula/
|
|
||||||
[19]: https://rawgit.com/bevacqua/dragula/master/resources/patreon.svg
|
|
||||||
[20]: https://patreon.com/bevacqua
|
|
Before Width: | Height: | Size: 499 KiB |
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg version="1" xmlns="http://www.w3.org/2000/svg" width="200" height="220" viewBox="0 0 200 220"><path fill="#961914" stroke="#52100F" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M45.09 158.663c-2.652 40.673-7.848 34.5-7.797 43.87.05 9.37 8.36 9.02 8.36 9.02s8.315.26 8.265-9.11c-.064-11.833-5.916-5.496-8.827-43.78z"/><path fill="#221C3B" d="M161.298 129.555c-.584-.182-32.122-10.11-68.73-26.774l28.113-10.01c.815-.29 1.35-1.07 1.33-1.934-.02-.864-.596-1.617-1.423-1.865-.852-.255-85.436-26.222-107.022-77.88-.366-.877-1.3-1.374-2.23-1.19-.934.183-1.608.997-1.615 1.948-.15 21.842 9.604 43.05 28.337 61.876C25.045 65.42 13.063 56.408 3.41 46.828c-.66-.655-1.68-.77-2.466-.278-.787.49-1.134 1.456-.84 2.335 15.855 47.184 75.654 67.73 78.192 68.582.083.028.168.05.254.067l81.773 15.895c.128.024.256.036.383.036.9 0 1.71-.61 1.938-1.512.258-1.03-.332-2.083-1.346-2.4z"/><path fill="#952A58" d="M20.208 33.882C41.114 63.294 88.69 88.366 88.69 88.366l-5.67 11.54S28.464 66.843 20.207 33.883z"/><path fill="#221C3B" d="M176.817 96.7C169.673 82.777 156 73.51 136.173 69.153 81.2 57.076 66.583 46.878 38.43.955c-.473-.77-1.4-1.128-2.268-.874-.866.254-1.456 1.057-1.438 1.96.192 9.995 4.417 22.933 9.31 37.913 11.585 35.473 26.002 79.622-.626 117.455-.03.04-.057.083-.083.127-.157.258-.25.543-.28.832v.008c-.008.095-.01.19-.007.283v.008c.018.38.145.757.378 1.08.71.985 1.82 2.365 3.222 4.11 6.98 8.69 23.325 29.04 20.575 41.56-.212.967.316 1.944 1.242 2.297.233.09.474.13.71.13.707 0 1.383-.374 1.746-1.02 8.72-15.55 27.214-18.688 46.793-22.01 25.645-4.35 54.71-9.282 62.648-45.41 3.605-16.406 2.383-31.173-3.533-42.703zM80.36 118.05c9.852 2.812 31.804 9.922 32.124 24.504-15.71 4.128-28.223 7.467-41.418 19.84-3.02-1.093-11.167-3.906-18.468-5.194 14.872-8.625 23.905-24.973 27.76-39.15z"/><path fill="#952A58" d="M47.667 26.33c21.25 33.75 42.806 41.29 80.186 49.5 36.266 7.97 48.95 32.165 42.857 59.904-11.654 53.044-78.047 28.823-100.376 56.015-9.748-24.576-25.298-33.18-25.298-33.18s18.36 6.14 24.6 13.206c2.698 3.055 3.915 6.678 3.948 7.22 1.417 1-.43-5.054.34-5.968 21.34-25.367 55.016-14.355 60.676-40.12 7.2-32.77-34.33-29.798-59.6-42.625-5.08 31.65-10.715 48.995-29.964 68.287 21.16-21.657 22.518-60.586 14.408-99.74 21.733 28.916 53.058 34.035 69.974 37.75-37.017-11.142-66.5-29.685-81.75-70.25z"/></svg>
|
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 8.4 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="-2,0,65,65" color="#ff5900"><path d="M8 31.3C8 20.1 17.1 9.6 29.1 8.1c8.6-1 15.1 2.3 19.6 6.6 4.2 4 6.7 9.1 7.3 15.1 0.5 6-0.8 11.2-4.3 16.1-3.5 4.8-10.4 10.1-19 10.1l-11.7 0 0-23.1c0.1-5.1 1.8-9.5 8-11.6 5.4-1.6 11.7 1.4 13.6 7.1 2 6.1-0.9 10.2-4.3 12.7-3.4 2.5-8.7 2.5-12.2 0.1l0 7.9c2.3 1.1 5.2 1.4 7.3 1.3 7.6-1.1 13.5-5.4 16-11.9 2.6-6.9 0.8-14.9-4.6-19.9-6.5-5.3-13.6-6.6-21.2-2.9-5.3 2.7-9 8.2-9.9 14.2l0 26.1-5.6 0z" fill="#ff5900"/></svg>
|
|
Before Width: | Height: | Size: 520 B |
|
@ -1,108 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('cancel does not throw when not dragging', function (t) {
|
|
||||||
t.test('a single time', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.cancel();
|
|
||||||
}, 'dragula ignores a single call to drake.cancel');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.test('multiple times', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.cancel();
|
|
||||||
drake.cancel();
|
|
||||||
drake.cancel();
|
|
||||||
drake.cancel();
|
|
||||||
}, 'dragula ignores multiple calls to drake.cancel');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and cancel gets called, nothing happens', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.cancel();
|
|
||||||
t.equal(div.children.length, 1, 'nothing happens');
|
|
||||||
t.equal(drake.dragging, false, 'drake has stopped dragging');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and cancel gets called, cancel event is emitted', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.cancel();
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function cancel (target, container) {
|
|
||||||
t.equal(target, item, 'cancel was invoked with item');
|
|
||||||
t.equal(container, div, 'cancel was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and cancel gets called, default does not revert', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item);
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.cancel();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function drop (target, parent, source) {
|
|
||||||
t.equal(target, item, 'drop was invoked with item');
|
|
||||||
t.equal(parent, div2, 'drop was invoked with final container');
|
|
||||||
t.equal(source, div, 'drop was invoked with source container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and cancel gets called, revert is executed', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item);
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.cancel(true);
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function cancel (target, container) {
|
|
||||||
t.equal(target, item, 'cancel was invoked with item');
|
|
||||||
t.equal(container, div, 'cancel was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,65 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var classes = require('../classes');
|
|
||||||
|
|
||||||
test('classes exports the expected api', function (t) {
|
|
||||||
t.equal(typeof classes.add, 'function', 'classes.add is a method');
|
|
||||||
t.equal(typeof classes.rm, 'function', 'classes.rm is a method');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can add a class', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
classes.add(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'gu-foo', 'setting a class works');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can add a class to an element that already has classes', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'bar';
|
|
||||||
classes.add(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'bar gu-foo', 'appending a class works');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes.add is a no-op if class already is in element', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'gu-foo';
|
|
||||||
classes.add(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'gu-foo', 'no-op as expected');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can remove a class', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'gu-foo';
|
|
||||||
classes.rm(el, 'gu-foo');
|
|
||||||
t.equal(el.className, '', 'removing a class works');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can remove a class from a list on the right', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'bar gu-foo';
|
|
||||||
classes.rm(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'bar', 'removing a class from the list works to the right');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can remove a class from a list on the left', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'gu-foo bar';
|
|
||||||
classes.rm(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'bar', 'removing a class from the list works to the left');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('classes can remove a class from a list on the middle', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
el.className = 'foo gu-foo bar';
|
|
||||||
classes.rm(el, 'gu-foo');
|
|
||||||
t.equal(el.className, 'foo bar', 'removing a class from the list works to the middle');
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('drake defaults to no containers', function (t) {
|
|
||||||
var drake = dragula();
|
|
||||||
t.ok(Array.isArray(drake.containers), 'drake.containers is an array');
|
|
||||||
t.equal(drake.containers.length, 0, 'drake.containers is empty');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('drake reads containers from array argument', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
var containers = [el];
|
|
||||||
var drake = dragula(containers);
|
|
||||||
t.equal(drake.containers, containers, 'drake.containers matches input');
|
|
||||||
t.equal(drake.containers.length, 1, 'drake.containers has one item');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('drake reads containers from array in options', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
var containers = [el];
|
|
||||||
var drake = dragula({ containers: containers });
|
|
||||||
t.equal(drake.containers, containers, 'drake.containers matches input');
|
|
||||||
t.equal(drake.containers.length, 1, 'drake.containers has one item');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('containers in options take precedent', function (t) {
|
|
||||||
var el = document.createElement('div');
|
|
||||||
var containers = [el];
|
|
||||||
var drake = dragula([], { containers: containers });
|
|
||||||
t.equal(drake.containers, containers, 'drake.containers matches input');
|
|
||||||
t.equal(drake.containers.length, 1, 'drake.containers has one item');
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('drake has sensible default options', function (t) {
|
|
||||||
var options = {};
|
|
||||||
dragula(options);
|
|
||||||
t.equal(typeof options.moves, 'function', 'options.moves defaults to a method');
|
|
||||||
t.equal(typeof options.accepts, 'function', 'options.accepts defaults to a method');
|
|
||||||
t.equal(typeof options.invalid, 'function', 'options.invalid defaults to a method');
|
|
||||||
t.equal(typeof options.isContainer, 'function', 'options.isContainer defaults to a method');
|
|
||||||
t.equal(options.copy, false, 'options.copy defaults to false');
|
|
||||||
t.equal(options.revertOnSpill, false, 'options.revertOnSpill defaults to false');
|
|
||||||
t.equal(options.removeOnSpill, false, 'options.removeOnSpill defaults to false');
|
|
||||||
t.equal(options.direction, 'vertical', 'options.direction defaults to \'vertical\'');
|
|
||||||
t.equal(options.mirrorContainer, document.body, 'options.mirrorContainer defaults to an document.body');
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,103 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('destroy does not throw when not dragging, destroyed, or whatever', function (t) {
|
|
||||||
t.test('a single time', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.destroy();
|
|
||||||
}, 'dragula bites into a single call to drake.destroy');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.test('multiple times', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.destroy();
|
|
||||||
drake.destroy();
|
|
||||||
drake.destroy();
|
|
||||||
drake.destroy();
|
|
||||||
}, 'dragula bites into multiple calls to drake.destroy');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and destroy gets called, nothing happens', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.destroy();
|
|
||||||
t.equal(div.children.length, 1, 'nothing happens');
|
|
||||||
t.equal(drake.dragging, false, 'drake has stopped dragging');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and destroy gets called, dragend event is emitted gracefully', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.destroy();
|
|
||||||
t.plan(1);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and destroy gets called, default does not revert', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item);
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.destroy();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function drop (target, parent, source) {
|
|
||||||
t.equal(target, item, 'drop was invoked with item');
|
|
||||||
t.equal(parent, div2, 'drop was invoked with final container');
|
|
||||||
t.equal(source, div, 'drop was invoked with source container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and destroy gets called, revert is executed', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2], { revertOnSpill: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item);
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.destroy();
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function cancel (target, container) {
|
|
||||||
t.equal(target, item, 'cancel was invoked with item');
|
|
||||||
t.equal(container, div, 'cancel was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,256 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var events = require('./lib/events');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('drag event gets emitted when clicking an item', function (t) {
|
|
||||||
testCase('works for left clicks', { which: 0 });
|
|
||||||
testCase('works for wheel clicks', { which: 1 });
|
|
||||||
testCase('works when clicking buttons by default', { which: 0 }, { tag: 'button', passes: true });
|
|
||||||
testCase('works when clicking anchors by default', { which: 0 }, { tag: 'a', passes: true });
|
|
||||||
testCase('fails for right clicks', { which: 2 }, { passes: false });
|
|
||||||
testCase('fails for meta-clicks', { which: 0, metaKey: true }, { passes: false });
|
|
||||||
testCase('fails for ctrl-clicks', { which: 0, ctrlKey: true }, { passes: false });
|
|
||||||
testCase('fails when clicking containers', { which: 0 }, { containerClick: true, passes: false });
|
|
||||||
testCase('fails whenever invalid returns true', { which: 0 }, { passes: false, dragulaOpts: { invalid: always } });
|
|
||||||
testCase('fails whenever moves returns false', { which: 0 }, { passes: false, dragulaOpts: { moves: never } });
|
|
||||||
t.end();
|
|
||||||
function testCase (desc, eventOptions, options) {
|
|
||||||
t.test(desc, function subtest (st) {
|
|
||||||
var o = options || {};
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement(o.tag || 'div');
|
|
||||||
var passes = o.passes !== false;
|
|
||||||
var drake = dragula([div], o.dragulaOpts);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
events.raise(o.containerClick ? div : item, 'mousedown', eventOptions);
|
|
||||||
events.raise(o.containerClick ? div : item, 'mousemove');
|
|
||||||
st.plan(passes ? 4 : 1);
|
|
||||||
st.equal(drake.dragging, passes, desc + ': final state is drake is ' + (passes ? '' : 'not ') + 'dragging');
|
|
||||||
st.end();
|
|
||||||
function drag (target, container) {
|
|
||||||
st[passes ? 'pass' : 'fail'](desc + ': drag event was emitted synchronously');
|
|
||||||
st.equal(target, item, desc + ': first argument is selected item');
|
|
||||||
st.equal(container, div, desc + ': second argument is container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when already dragging, mousedown/mousemove ends (cancels) previous drag', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item1 = document.createElement('div');
|
|
||||||
var item2 = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item1);
|
|
||||||
div.appendChild(item2);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item1);
|
|
||||||
drake.on('dragend', end);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
events.raise(item2, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item2, 'mousemove', { which: 0 });
|
|
||||||
t.plan(7);
|
|
||||||
t.equal(drake.dragging, true, 'final state is drake is dragging');
|
|
||||||
t.end();
|
|
||||||
function end (item) {
|
|
||||||
t.equal(item, item1, 'dragend invoked with correct item');
|
|
||||||
}
|
|
||||||
function cancel (item, source) {
|
|
||||||
t.equal(item, item1, 'cancel invoked with correct item');
|
|
||||||
t.equal(source, div, 'cancel invoked with correct source');
|
|
||||||
}
|
|
||||||
function drag (item, container) {
|
|
||||||
t.pass('drag event was emitted synchronously');
|
|
||||||
t.equal(item, item2, 'first argument is selected item');
|
|
||||||
t.equal(container, div, 'second argument is container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when already dragged, ends (drops) previous drag', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item1 = document.createElement('div');
|
|
||||||
var item2 = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item1);
|
|
||||||
div.appendChild(item2);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item1);
|
|
||||||
div2.appendChild(item1);
|
|
||||||
drake.on('dragend', end);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
events.raise(item2, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item2, 'mousemove', { which: 0 });
|
|
||||||
t.plan(8);
|
|
||||||
t.equal(drake.dragging, true, 'final state is drake is dragging');
|
|
||||||
t.end();
|
|
||||||
function end (item) {
|
|
||||||
t.equal(item, item1, 'dragend invoked with correct item');
|
|
||||||
}
|
|
||||||
function drop (item, target, source) {
|
|
||||||
t.equal(item, item1, 'drop invoked with correct item');
|
|
||||||
t.equal(source, div, 'drop invoked with correct source');
|
|
||||||
t.equal(target, div2, 'drop invoked with correct target');
|
|
||||||
}
|
|
||||||
function drag (item, container) {
|
|
||||||
t.pass('drag event was emitted synchronously');
|
|
||||||
t.equal(item, item2, 'first argument is selected item');
|
|
||||||
t.equal(container, div, 'second argument is container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when copying, emits cloned with the copy', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item1 = document.createElement('div');
|
|
||||||
var item2 = document.createElement('span');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
item2.innerHTML = '<em>the force is <strong>with this one</strong></em>';
|
|
||||||
div.appendChild(item1);
|
|
||||||
div.appendChild(item2);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item1);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
events.raise(item2, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item2, 'mousemove', { which: 0 });
|
|
||||||
t.plan(12);
|
|
||||||
t.equal(drake.dragging, true, 'final state is drake is dragging');
|
|
||||||
t.end();
|
|
||||||
function cloned (copy, item) {
|
|
||||||
t.notEqual(copy, item2, 'first argument is not exactly the target');
|
|
||||||
t.equal(copy.tagName, item2.tagName, 'first argument has same tag as target');
|
|
||||||
t.equal(copy.innerHTML, item2.innerHTML, 'first argument has same inner html as target');
|
|
||||||
t.equal(item, item2, 'second argument is clicked item');
|
|
||||||
}
|
|
||||||
function drag (item, container) {
|
|
||||||
t.pass('drag event was emitted synchronously');
|
|
||||||
t.equal(item, item2, 'first argument is selected item');
|
|
||||||
t.equal(container, div, 'second argument is container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging, element gets gu-transit class', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.equal(item.className, 'gu-transit', 'item has gu-transit class');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging, body gets gu-unselectable class', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging, element gets a mirror image for show', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
item.innerHTML = '<em>the force is <strong>with this one</strong></em>';
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function cloned (mirror, target) {
|
|
||||||
t.equal(item.className, 'gu-transit', 'item does not have gu-mirror class');
|
|
||||||
t.equal(mirror.className, 'gu-mirror', 'mirror only has gu-mirror class');
|
|
||||||
t.equal(mirror.innerHTML, item.innerHTML, 'mirror is passed to \'cloned\' event');
|
|
||||||
t.equal(target, item, 'cloned lets you know that the mirror is a clone of `item`');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging, mirror element gets appended to configured mirrorContainer', function (t) {
|
|
||||||
var mirrorContainer = document.createElement('div');
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], {
|
|
||||||
'mirrorContainer': mirrorContainer
|
|
||||||
});
|
|
||||||
item.innerHTML = '<em>the force is <strong>with this one</strong></em>';
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.plan(1);
|
|
||||||
t.end();
|
|
||||||
function cloned (mirror) {
|
|
||||||
t.equal(mirror.parentNode, mirrorContainer, 'mirrors parent is the configured mirrorContainer');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging stops, element gets gu-transit class removed', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.equal(item.className, 'gu-transit', 'item has gu-transit class');
|
|
||||||
drake.end();
|
|
||||||
t.equal(item.className, '', 'item has gu-transit class removed');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging stops, body becomes selectable again', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.equal(document.body.className, 'gu-unselectable', 'body has gu-unselectable class');
|
|
||||||
drake.end();
|
|
||||||
t.equal(document.body.className, '', 'body got gu-unselectable class removed');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when drag begins, check for copy option', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
item.className = 'copyable';
|
|
||||||
div.className = 'contains';
|
|
||||||
var drake = dragula([div], {
|
|
||||||
copy: checkCondition
|
|
||||||
});
|
|
||||||
item.innerHTML = '<em>the force is <strong>with this one</strong></em>';
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 }); // ensure the copy method condition is only asserted once
|
|
||||||
t.plan(2);
|
|
||||||
t.end();
|
|
||||||
function checkCondition (el, source) {
|
|
||||||
t.equal(el.className, 'copyable', 'dragged element classname is copyable');
|
|
||||||
t.equal(source.className, 'contains', 'source container classname is contains');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
drake.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
function always () { return true; }
|
|
||||||
function never () { return false; }
|
|
|
@ -1,27 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('drake can be instantiated without throwing', function (t) {
|
|
||||||
t.doesNotThrow(drakeFactory, 'calling dragula() without arguments does not throw');
|
|
||||||
t.end();
|
|
||||||
function drakeFactory () {
|
|
||||||
return dragula();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('drake has expected api properties', function (t) {
|
|
||||||
var drake = dragula();
|
|
||||||
t.ok(drake, 'drake is not null');
|
|
||||||
t.equal(typeof drake, 'object', 'drake is an object');
|
|
||||||
t.ok(Array.isArray(drake.containers), 'drake.containers is an array');
|
|
||||||
t.equal(typeof drake.start, 'function', 'drake.start is a method');
|
|
||||||
t.equal(typeof drake.end, 'function', 'drake.end is a method');
|
|
||||||
t.equal(typeof drake.cancel, 'function', 'drake.cancel is a method');
|
|
||||||
t.equal(typeof drake.remove, 'function', 'drake.remove is a method');
|
|
||||||
t.equal(typeof drake.destroy, 'function', 'drake.destroy is a method');
|
|
||||||
t.equal(typeof drake.dragging, 'boolean', 'drake.dragging is a boolean');
|
|
||||||
t.equal(drake.dragging, false, 'drake.dragging is initialized as false');
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,77 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('end does not throw when not dragging', function (t) {
|
|
||||||
t.test('a single time', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.end();
|
|
||||||
}, 'dragula ignores a single call to drake.end');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.test('multiple times', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.end();
|
|
||||||
drake.end();
|
|
||||||
drake.end();
|
|
||||||
drake.end();
|
|
||||||
}, 'dragula ignores multiple calls to drake.end');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when already dragging, .end() ends (cancels) previous drag', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item1 = document.createElement('div');
|
|
||||||
var item2 = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item1);
|
|
||||||
div.appendChild(item2);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item1);
|
|
||||||
drake.on('dragend', end);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.end();
|
|
||||||
t.plan(4);
|
|
||||||
t.equal(drake.dragging, false, 'final state is: drake is not dragging');
|
|
||||||
t.end();
|
|
||||||
function end (item) {
|
|
||||||
t.equal(item, item1, 'dragend invoked with correct item');
|
|
||||||
}
|
|
||||||
function cancel (item, source) {
|
|
||||||
t.equal(item, item1, 'cancel invoked with correct item');
|
|
||||||
t.equal(source, div, 'cancel invoked with correct source');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when already dragged, ends (drops) previous drag', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item1 = document.createElement('div');
|
|
||||||
var item2 = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item1);
|
|
||||||
div.appendChild(item2);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.start(item1);
|
|
||||||
div2.appendChild(item1);
|
|
||||||
drake.on('dragend', end);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
drake.end();
|
|
||||||
t.plan(5);
|
|
||||||
t.equal(drake.dragging, false, 'final state is: drake is not dragging');
|
|
||||||
t.end();
|
|
||||||
function end (item) {
|
|
||||||
t.equal(item, item1, 'dragend invoked with correct item');
|
|
||||||
}
|
|
||||||
function drop (item, target, source) {
|
|
||||||
t.equal(item, item1, 'drop invoked with correct item');
|
|
||||||
t.equal(source, div, 'drop invoked with correct source');
|
|
||||||
t.equal(target, div2, 'drop invoked with correct target');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,292 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var events = require('./lib/events');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('.start() emits "cloned" for copies', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
drake.start(item);
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function cloned (copy, original, type) {
|
|
||||||
if (type === 'copy') {
|
|
||||||
t.notEqual(copy, item, 'copy is not a reference to item');
|
|
||||||
t.deepEqual(copy, item, 'copy of original is provided');
|
|
||||||
t.equal(original, item, 'original item is provided');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.start() emits "drag" for items', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
drake.start(item);
|
|
||||||
t.plan(2);
|
|
||||||
t.end();
|
|
||||||
function drag (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.end() emits "cancel" when not moved', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.end();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function cancel (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.end() emits "drop" when moved', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div, div2]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.end();
|
|
||||||
t.plan(5);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function drop (original, target, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(target, div2, 'target matches expected div');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.remove() emits "remove" for items', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('remove', remove);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.remove();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function remove (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.remove() emits "cancel" for copies', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.remove();
|
|
||||||
t.plan(6);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got invoked');
|
|
||||||
}
|
|
||||||
function out (copy) {
|
|
||||||
t.notEqual(copy, item, 'copy is not a reference to item');
|
|
||||||
t.deepEqual(copy, item, 'item is a copy of item');
|
|
||||||
}
|
|
||||||
function cancel (copy, container) {
|
|
||||||
t.notEqual(copy, item, 'copy is not a reference to item');
|
|
||||||
t.deepEqual(copy, item, 'item is a copy of item');
|
|
||||||
t.equal(container, null, 'container matches expectation');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.cancel() emits "cancel" when not moved', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.cancel();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function cancel (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.cancel() emits "drop" when not reverted', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('drop', drop);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.cancel();
|
|
||||||
t.plan(5);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function drop (original, parent, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(parent, div2, 'parent matches expected div');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('.cancel() emits "cancel" when reverts', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var div2 = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { revertOnSpill: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
document.body.appendChild(div2);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.on('out', out);
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
div2.appendChild(item);
|
|
||||||
drake.cancel();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function out (original) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
}
|
|
||||||
function cancel (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('mousedown emits "cloned" for mirrors', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function cloned (copy, original, type) {
|
|
||||||
if (type === 'mirror') {
|
|
||||||
t.notEqual(copy, item, 'mirror is not a reference to item');
|
|
||||||
t.deepEqual(copy, item, 'mirror of original is provided');
|
|
||||||
t.equal(original, item, 'original item is provided');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('mousedown emits "cloned" for copies', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('cloned', cloned);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function cloned (copy, original, type) {
|
|
||||||
if (type === 'copy') {
|
|
||||||
t.notEqual(copy, item, 'copy is not a reference to item');
|
|
||||||
t.deepEqual(copy, item, 'copy of original is provided');
|
|
||||||
t.equal(original, item, 'original item is provided');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('mousedown emits "drag" for items', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.on('drag', drag);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
t.plan(2);
|
|
||||||
t.end();
|
|
||||||
function drag (original, container) {
|
|
||||||
t.equal(original, item, 'item is a reference to moving target');
|
|
||||||
t.equal(container, div, 'container matches expected div');
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function raise (el, type, options) {
|
|
||||||
var o = options || {};
|
|
||||||
var e = document.createEvent('Event');
|
|
||||||
e.initEvent(type, true, true);
|
|
||||||
Object.keys(o).forEach(apply);
|
|
||||||
el.dispatchEvent(e);
|
|
||||||
function apply (key) {
|
|
||||||
e[key] = o[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
raise: raise
|
|
||||||
};
|
|
|
@ -1,9 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('public api matches expectation', function (t) {
|
|
||||||
t.equal(typeof dragula, 'function', 'dragula is a function');
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,106 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var test = require('tape');
|
|
||||||
var events = require('./lib/events');
|
|
||||||
var dragula = require('..');
|
|
||||||
|
|
||||||
test('remove does not throw when not dragging', function (t) {
|
|
||||||
t.test('a single time', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.remove();
|
|
||||||
}, 'dragula ignores a single call to drake.remove');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.test('multiple times', function once (st) {
|
|
||||||
var drake = dragula();
|
|
||||||
st.doesNotThrow(function () {
|
|
||||||
drake.remove();
|
|
||||||
drake.remove();
|
|
||||||
drake.remove();
|
|
||||||
drake.remove();
|
|
||||||
}, 'dragula ignores multiple calls to drake.remove');
|
|
||||||
st.end();
|
|
||||||
});
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and remove gets called, element is removed', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.remove();
|
|
||||||
t.equal(div.children.length, 0, 'item got removed from container');
|
|
||||||
t.equal(drake.dragging, false, 'drake has stopped dragging');
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging and remove gets called, remove event is emitted', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div]);
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
drake.start(item);
|
|
||||||
drake.on('remove', remove);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.remove();
|
|
||||||
t.plan(3);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function remove (target, container) {
|
|
||||||
t.equal(target, item, 'remove was invoked with item');
|
|
||||||
t.equal(container, div, 'remove was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and remove gets called, cancel event is emitted', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.remove();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function cancel (target, container) {
|
|
||||||
t.equal(target.className, 'gu-transit', 'cancel was invoked with item');
|
|
||||||
t.notEqual(target, item, 'item is a copy and not the original');
|
|
||||||
t.equal(container, null, 'cancel was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('when dragging a copy and remove gets called, cancel event is emitted', function (t) {
|
|
||||||
var div = document.createElement('div');
|
|
||||||
var item = document.createElement('div');
|
|
||||||
var drake = dragula([div], { copy: true });
|
|
||||||
div.appendChild(item);
|
|
||||||
document.body.appendChild(div);
|
|
||||||
events.raise(item, 'mousedown', { which: 0 });
|
|
||||||
events.raise(item, 'mousemove', { which: 0 });
|
|
||||||
drake.on('cancel', cancel);
|
|
||||||
drake.on('dragend', dragend);
|
|
||||||
drake.remove();
|
|
||||||
t.plan(4);
|
|
||||||
t.end();
|
|
||||||
function dragend () {
|
|
||||||
t.pass('dragend got called');
|
|
||||||
}
|
|
||||||
function cancel (target, container) {
|
|
||||||
t.equal(target.className, 'gu-transit', 'cancel was invoked with item');
|
|
||||||
t.notEqual(target, item, 'item is a copy and not the original');
|
|
||||||
t.equal(container, null, 'cancel was invoked with container');
|
|
||||||
}
|
|
||||||
});
|
|
13
dashboard-ui/cordova/iap.js
vendored
|
@ -69,25 +69,24 @@
|
||||||
var receipt = product.transaction.appStoreReceipt;
|
var receipt = product.transaction.appStoreReceipt;
|
||||||
var price = product.price;
|
var price = product.price;
|
||||||
|
|
||||||
HttpClient.send({
|
ApiClient.ajax({
|
||||||
|
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: "https://mb3admin.com/test/admin/service/appstore/register",
|
url: ApiClient.getUrl("Appstore/Register"),
|
||||||
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
data: {
|
data: {
|
||||||
|
Parameters: JSON.stringify({
|
||||||
store: "Apple",
|
store: "Apple",
|
||||||
application: "com.emby.mobile",
|
application: "com.emby.mobile",
|
||||||
product: productId,
|
product: productId,
|
||||||
type: "Subscription",
|
type: "Subscription",
|
||||||
feature: "MBSClubMonthly",
|
feature: "MBSClubMonthly",
|
||||||
email: enteredEmail,
|
email: enteredEmail,
|
||||||
token: receipt,
|
storeToken: receipt,
|
||||||
amt: price,
|
amt: price,
|
||||||
storeId: transactionId
|
storeId: transactionId
|
||||||
},
|
})
|
||||||
headers: {
|
|
||||||
"X-Emby-Token": "08606E86D043"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
|
|
||||||
callback(true, product);
|
callback(true, product);
|
||||||
|
|