mirror of https://github.com/RubaXa/Sortable.git
RubaXa
11 years ago
commit
6ace554483
7 changed files with 963 additions and 0 deletions
@ -0,0 +1,31 @@
|
||||
'use strict'; |
||||
|
||||
module.exports = function (grunt){ |
||||
grunt.initConfig({ |
||||
pkg: grunt.file.readJSON('package.json'), |
||||
|
||||
version: { |
||||
src: '<%= pkg.exportName %>.js' |
||||
}, |
||||
|
||||
uglify: { |
||||
options: { |
||||
banner: '/*! <%= pkg.exportName %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %> */\n' |
||||
}, |
||||
dist: { |
||||
files: { |
||||
'<%= pkg.exportName %>.min.js': ['<%= pkg.exportName %>.js'] |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
|
||||
// These plugins provide necessary tasks.
|
||||
grunt.loadNpmTasks('grunt-version'); |
||||
grunt.loadNpmTasks('grunt-contrib-uglify'); |
||||
|
||||
|
||||
// Default task.
|
||||
grunt.registerTask('default', ['version', 'uglify']); |
||||
}; |
@ -0,0 +1,46 @@
|
||||
# Sortable |
||||
|
||||
|
||||
## Features |
||||
* Support touch devices |
||||
* Built using native HTML5 drag and drop API |
||||
* Simple API |
||||
* Lightweight, 2KB gzipped |
||||
* No jQuery |
||||
|
||||
|
||||
### Usage |
||||
```html |
||||
<ul id="items"> |
||||
<li>item 1</li> |
||||
<li>item 2</li> |
||||
<li>item 3</li> |
||||
</ul> |
||||
``` |
||||
|
||||
```js |
||||
new Sortable(items); |
||||
``` |
||||
|
||||
|
||||
### Options |
||||
```js |
||||
new Sortable(elem, { |
||||
group: "name", |
||||
handle: ".my-handle", // Restricts sort start click/touch to the specified element |
||||
draggable: ".item", // Specifies which items inside the element should be sortable |
||||
ghostClass: "sortable-ghost", |
||||
|
||||
onAdd: function (evt){ |
||||
var itemEl = ui.detail; |
||||
}, |
||||
|
||||
onUpdate: function (evt){ |
||||
var itemEl = ui.detail; // the current dragged HTMLElement |
||||
}, |
||||
|
||||
onRemove: function (evt){ |
||||
var itemEl = ui.detail; |
||||
} |
||||
}); |
||||
``` |
@ -0,0 +1,474 @@
|
||||
/**! |
||||
* Sortable |
||||
* @author RubaXa <trash@rubaxa.org> |
||||
* @license MIT |
||||
*/ |
||||
|
||||
|
||||
(function (factory){ |
||||
"use strict"; |
||||
|
||||
if( typeof define === "function" && define.amd ){ |
||||
define("Sortable", [], factory); |
||||
} |
||||
else { |
||||
window["Sortable"] = factory(); |
||||
} |
||||
})(function (){ |
||||
"use strict"; |
||||
|
||||
var |
||||
dragEl |
||||
, ghostEl |
||||
, rootEl |
||||
, nextEl |
||||
|
||||
, lastEl |
||||
, lastCSS |
||||
|
||||
, activeGroup |
||||
|
||||
, tapEvt |
||||
, touchEvt |
||||
|
||||
, expando = 'Sortable' + (new Date).getTime() |
||||
|
||||
, win = window |
||||
, document = win.document |
||||
, parseInt = win.parseInt |
||||
, Event = win.CustomEvent |
||||
|
||||
, noop = function (){} |
||||
, slice = [].slice |
||||
|
||||
, touchDragOverListeners = [] |
||||
; |
||||
|
||||
|
||||
/** |
||||
* @class Sortable |
||||
* @param {HTMLElement} el |
||||
* @param {Object} [options] |
||||
* @constructor |
||||
*/ |
||||
function Sortable(el, options){ |
||||
this.el = el; // root element
|
||||
this.options = options = (options || {}); |
||||
|
||||
|
||||
// Defaults
|
||||
options.group = options.group || Math.random(); |
||||
options.handle = options.handle || null; |
||||
options.draggable = options.draggable || el.children[0] && el.children[0].nodeName || 'li'; |
||||
options.ghostClass = options.ghostClass || 'sortable-ghost'; |
||||
|
||||
options.onAdd = _bind(this, options.onAdd || noop); |
||||
options.onUpdate = _bind(this, options.onUpdate || noop); |
||||
options.onRemove = _bind(this, options.onRemove || noop); |
||||
|
||||
|
||||
el[expando] = options.group; |
||||
|
||||
|
||||
// Bind all prevate methods
|
||||
for( var fn in this ){ |
||||
if( fn.charAt(0) === '_' ){ |
||||
this[fn] = _bind(this, this[fn]); |
||||
} |
||||
} |
||||
|
||||
|
||||
// Bind events
|
||||
_on(el, 'add', options.onAdd); |
||||
_on(el, 'update', options.onUpdate); |
||||
_on(el, 'remove', options.onRemove); |
||||
|
||||
_on(el, 'mousedown', this._onTapStart); |
||||
_on(el, 'touchstart', this._onTapStart); |
||||
|
||||
_on(el, 'dragover', this._onDragOver); |
||||
_on(el, 'dragenter', this._onDragOver); |
||||
|
||||
touchDragOverListeners.push(this._onDragOver); |
||||
} |
||||
|
||||
|
||||
Sortable.prototype = { |
||||
constructor: Sortable, |
||||
|
||||
|
||||
_applyEffects: function (){ |
||||
_toggleClass(dragEl, this.options.ghostClass, true); |
||||
}, |
||||
|
||||
|
||||
_onTapStart: function (evt/**TouchEvent*/){ |
||||
var |
||||
touch = evt.touches && evt.touches[0] |
||||
, target = (touch || evt).target |
||||
, options = this.options |
||||
; |
||||
|
||||
if( options.handle ){ |
||||
target = _closest(target, options.handle, this.el); |
||||
} |
||||
|
||||
target = _closest(target, options.draggable, this.el); |
||||
|
||||
if( target && !dragEl ){ |
||||
tapEvt = evt; |
||||
target.draggable = true; |
||||
|
||||
// Disable "draggable"
|
||||
_find(target, 'a', _disableDraggable); |
||||
_find(target, 'img', _disableDraggable); |
||||
|
||||
|
||||
if( touch ){ |
||||
// Touch device support
|
||||
tapEvt = { |
||||
target: target |
||||
, clientX: touch.clientX |
||||
, clientY: touch.clientY |
||||
}; |
||||
this._onDragStart(tapEvt, true); |
||||
evt.preventDefault(); |
||||
} |
||||
|
||||
|
||||
_on(this.el, 'dragstart', this._onDragStart); |
||||
_on(document, 'dragover', _globalDragOver); |
||||
|
||||
|
||||
try { |
||||
if( document.selection ){ |
||||
document.selection.empty(); |
||||
} else { |
||||
window.getSelection().removeAllRanges() |
||||
} |
||||
} catch (err){ } |
||||
} |
||||
}, |
||||
|
||||
|
||||
_emulateDragOver: function (){ |
||||
if( touchEvt ){ |
||||
_css(ghostEl, 'display', 'none'); |
||||
|
||||
var |
||||
target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY) |
||||
, parent = target |
||||
, group = this.options.group |
||||
, i = touchDragOverListeners.length |
||||
; |
||||
|
||||
do { |
||||
if( parent[expando] === group ){ |
||||
|
||||
while( i-- ){ |
||||
touchDragOverListeners[i]({ |
||||
clientX: touchEvt.clientX, |
||||
clientY: touchEvt.clientY, |
||||
target: target, |
||||
rootEl: parent |
||||
}); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
while( parent = parent.parentNode ); |
||||
|
||||
_css(ghostEl, 'display', ''); |
||||
} |
||||
}, |
||||
|
||||
|
||||
_onTouchMove: function (evt){ |
||||
if( tapEvt ){ |
||||
var |
||||
touch = evt.touches[0] |
||||
, dx = touch.clientX - tapEvt.clientX |
||||
, dy = touch.clientY - tapEvt.clientY |
||||
; |
||||
|
||||
touchEvt = touch; |
||||
_css(ghostEl, 'webkitTransform', 'translate3d('+dx+'px,'+dy+'px,0)'); |
||||
} |
||||
}, |
||||
|
||||
|
||||
_onDragStart: function (evt/**Event*/, isTouch){ |
||||
var |
||||
target = evt.target |
||||
, dataTransfer = evt.dataTransfer |
||||
; |
||||
|
||||
rootEl = this.el; |
||||
dragEl = target; |
||||
nextEl = target.nextSibling; |
||||
activeGroup = this.options.group; |
||||
|
||||
if( isTouch ){ |
||||
var rect = target.getBoundingClientRect(), css = _css(target); |
||||
|
||||
ghostEl = target.cloneNode(true); |
||||
|
||||
_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); |
||||
_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); |
||||
_css(ghostEl, 'width', rect.right - rect.left); |
||||
_css(ghostEl, 'height', rect.bottom - rect.top); |
||||
_css(ghostEl, 'opacity', '0.8'); |
||||
_css(ghostEl, 'position', 'fixed'); |
||||
_css(ghostEl, 'zIndex', '100000'); |
||||
|
||||
target.parentNode.insertBefore(ghostEl, target); |
||||
|
||||
// Bind touch events
|
||||
_on(document, 'touchmove', this._onTouchMove); |
||||
_on(document, 'touchend', this._onDrop); |
||||
|
||||
this._loopId = setInterval(this._emulateDragOver, 100); |
||||
} |
||||
else { |
||||
dataTransfer.effectAllowed = 'move'; |
||||
dataTransfer.setData('Text', target.textContent); |
||||
|
||||
_on(document, 'drop', this._onDrop); |
||||
} |
||||
|
||||
setTimeout(this._applyEffects); |
||||
}, |
||||
|
||||
|
||||
_onDragOver: function (evt){ |
||||
if( activeGroup === this.options.group && (evt.rootEl === void 0 || evt.rootEl === this.el) ){ |
||||
var |
||||
el = this.el |
||||
, target = _closest(evt.target, this.options.draggable, el) |
||||
; |
||||
|
||||
|
||||
if( el.children.length === 0 || target == null ){ |
||||
el.appendChild(dragEl); |
||||
} |
||||
else if( target && (target !== dragEl) ){ |
||||
if( lastEl !== target ){ |
||||
lastEl = target; |
||||
lastCSS = _css(target) |
||||
} |
||||
|
||||
|
||||
var |
||||
rect = target.getBoundingClientRect() |
||||
, width = rect.right - rect.left |
||||
, height = rect.bottom - rect.top |
||||
, floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) |
||||
, after = !floating && (evt.clientY - rect.top)/height > .5 || floating && (evt.clientX - rect.left)/width > .5 |
||||
, nextSibling = target.nextSibling |
||||
; |
||||
|
||||
|
||||
if( after && !nextSibling ){ |
||||
el.appendChild(dragEl); |
||||
} else { |
||||
target.parentNode.insertBefore(dragEl, after ? nextSibling : target); |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
|
||||
|
||||
_onDrop: function (evt/**Event*/){ |
||||
clearInterval(this._loopId); |
||||
|
||||
// Unbind events
|
||||
_off(document, 'drop', this._onDrop); |
||||
_off(document, 'dragover', _globalDragOver); |
||||
|
||||
_off(this.el, 'dragstart', this._onDragStart); |
||||
|
||||
_off(document, 'touchmove', this._onTouchMove); |
||||
_off(document, 'touchend', this._onDrop); |
||||
|
||||
|
||||
if( evt ){ |
||||
evt.preventDefault(); |
||||
|
||||
if( dragEl ){ |
||||
var opts = { bubbles: true, cancelable: true, detail: dragEl }; |
||||
|
||||
_toggleClass(dragEl, this.options.ghostClass, false); |
||||
|
||||
if( !rootEl.contains(dragEl) ){ |
||||
// Remove event
|
||||
rootEl.dispatchEvent(new Event('remove', opts)); |
||||
|
||||
// Add event
|
||||
dragEl.dispatchEvent(new Event('add', opts)); |
||||
} |
||||
else if( dragEl.nextSibling !== nextEl ){ |
||||
// Update event
|
||||
dragEl.dispatchEvent(new Event('update', opts)); |
||||
} |
||||
} |
||||
|
||||
if( ghostEl ){ |
||||
ghostEl.parentNode.removeChild(ghostEl); |
||||
} |
||||
|
||||
|
||||
// Set NULL
|
||||
rootEl = |
||||
dragEl = |
||||
ghostEl = |
||||
nextEl = |
||||
|
||||
tapEvt = |
||||
touchEvt = |
||||
|
||||
lastEl = |
||||
lastCSS = |
||||
|
||||
activeGroup = null; |
||||
} |
||||
}, |
||||
|
||||
|
||||
destroy: function (){ |
||||
var el = this.el, options = this.options; |
||||
|
||||
_off(el, 'add', options.onAdd); |
||||
_off(el, 'update', options.onUpdate); |
||||
_off(el, 'remove', options.onRemove); |
||||
|
||||
_off(el, 'mousedown', this._onTapStart); |
||||
_off(el, 'touchstart', this._onTapStart); |
||||
|
||||
_off(el, 'dragover', this._onDragOver); |
||||
_off(el, 'dragenter', this._onDragOver); |
||||
|
||||
touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1); |
||||
|
||||
this._onDrop(); |
||||
|
||||
this.el = null; |
||||
} |
||||
}; |
||||
|
||||
|
||||
function _bind(ctx, fn){ |
||||
var args = slice.call(arguments, 2); |
||||
return fn.bind ? fn.bind.apply(fn, [ctx].concat(args)) : function (){ |
||||
return fn.apply(ctx, args.concat(slice.call(arguments))); |
||||
}; |
||||
} |
||||
|
||||
|
||||
function _closest(el, selector, ctx){ |
||||
if( el && ctx ){ |
||||
ctx = ctx || document; |
||||
selector = selector.split('.'); |
||||
|
||||
var |
||||
tag = selector.shift().toUpperCase() |
||||
, re = new RegExp('\\b('+selector.join('|')+')\\b', 'g') |
||||
; |
||||
|
||||
do { |
||||
if( |
||||
(tag === '' || el.nodeName == tag) |
||||
&& (!selector.length || ((el.className+'').match(re) || []).length == selector.length) |
||||
){ |
||||
return el; |
||||
} |
||||
} |
||||
while( el !== ctx && (el = el.parentNode) ); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
|
||||
function _globalDragOver(evt){ |
||||
evt.dataTransfer.dropEffect = 'move'; |
||||
evt.preventDefault(); |
||||
} |
||||
|
||||
|
||||
function _on(el, event, fn){ |
||||
el.addEventListener(event, fn, false); |
||||
} |
||||
|
||||
|
||||
function _off(el, event, fn){ |
||||
el.removeEventListener(event, fn, false); |
||||
} |
||||
|
||||
|
||||
function _toggleClass(el, name, state){ |
||||
if( el ){ |
||||
if( el.classList ){ |
||||
el.classList[state ? 'add' : 'remove'](name); |
||||
} |
||||
else { |
||||
var className = (' '+el.className+' ').replace(' '+name+' ', '').replace(/\s+/g, ' '); |
||||
el.className = className + (state ? ' '+name : '') |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
function _css(el, prop, val){ |
||||
if( el && el.style ){ |
||||
if( val === void 0 ){ |
||||
if( document.defaultView && document.defaultView.getComputedStyle ){ |
||||
val = document.defaultView.getComputedStyle(el, ''); |
||||
} |
||||
else if( el.currentStyle ){ |
||||
val = el.currentStyle; |
||||
} |
||||
return prop === void 0 ? val : val[prop]; |
||||
} else { |
||||
el.style[prop] = val + (typeof val === 'string' ? '' : 'px'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
function _find(ctx, tagName, iterator){ |
||||
if( ctx ){ |
||||
var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length; |
||||
if( iterator ){ |
||||
for( ; i < n; i++ ){ |
||||
iterator(list[i], i); |
||||
} |
||||
} |
||||
return list; |
||||
} |
||||
return []; |
||||
} |
||||
|
||||
|
||||
function _disableDraggable(el){ |
||||
return el.draggable = false; |
||||
} |
||||
|
||||
|
||||
|
||||
// Export utils
|
||||
Sortable.utils = { |
||||
on: _on, |
||||
off: _off, |
||||
css: _css, |
||||
find: _find, |
||||
bind: _bind, |
||||
closest: _closest, |
||||
toggleClass: _toggleClass |
||||
}; |
||||
|
||||
|
||||
Sortable.version = '0.1.0'; |
||||
|
||||
// Export
|
||||
return Sortable; |
||||
}); |
File diff suppressed because one or more lines are too long
@ -0,0 +1,387 @@
|
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"/> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> |
||||
|
||||
<title>Sortable (No jQuery)</title> |
||||
|
||||
<meta name="keywords" content="sortable, reorder, list, javascript, html5, drag and drop, dnd, rubaxa"/> |
||||
<meta name="description" content="Sortable - is a minimalist JavaScript library for modern browsers and touch devices (No jQuery)."/> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/> |
||||
|
||||
|
||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"> |
||||
|
||||
<style> |
||||
@import url(http://fonts.googleapis.com/css?family=Roboto:300); |
||||
|
||||
|
||||
html, body { |
||||
color: #333; |
||||
min-height: 100%; |
||||
font-size: 18px; |
||||
font-family: "Arial", Helvetica, Garuda, sans-serif; |
||||
} |
||||
|
||||
h1, h2, h3 { |
||||
font-family: 'Roboto', sans-serif; |
||||
font-weight: 300; |
||||
} |
||||
|
||||
h1 a { |
||||
color: #333; |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
h1 + div { |
||||
opacity: 0.95; |
||||
margin-bottom: 50px; |
||||
} |
||||
|
||||
|
||||
ul { |
||||
margin: 0; |
||||
padding: 0; |
||||
list-style: none; |
||||
} |
||||
|
||||
|
||||
.sortable-ghost { |
||||
opacity: .2; |
||||
} |
||||
|
||||
|
||||
img { vertical-align: middle; } |
||||
|
||||
#contacts { |
||||
border-radius: 3px; |
||||
box-shadow: 0 0 1px rgba(0,0,0,0.4); |
||||
} |
||||
#contacts li:first-child { |
||||
border-radius: 3px 3px 0 0; |
||||
} |
||||
#contacts li:last-child { |
||||
border-radius: 0 0 3px 3px; |
||||
} |
||||
|
||||
#contacts li { |
||||
cursor: move; |
||||
padding: 10px; |
||||
background: rgba(255,255,255,.8); |
||||
border-bottom: 1px solid #ccc; |
||||
} |
||||
|
||||
#contacts img { |
||||
margin-right: 5px; |
||||
} |
||||
|
||||
|
||||
#tags { |
||||
min-height: 100px; |
||||
box-shadow: 0 1px 1px rgba(0,0,0,0.3); |
||||
border-radius: 5px; |
||||
background-color: #fff; |
||||
} |
||||
|
||||
#tags li { |
||||
cursor: move; |
||||
float: left; |
||||
margin: 10px; |
||||
padding: 6px 15px; |
||||
background: #B7D967; |
||||
border-radius: 3px; |
||||
box-shadow: 0 2px 0 #6d823d; |
||||
text-shadow: 0 1px 1px rgba(255,255,255,0.6); |
||||
} |
||||
|
||||
#tags img { |
||||
display: none; |
||||
} |
||||
|
||||
|
||||
.tile { |
||||
width: 280px; |
||||
float: left; |
||||
padding: 2px; |
||||
box-shadow: 0 0 0 3px rgba(0,0,0,0.2); |
||||
background-color: #fff; |
||||
margin-right: 30px; |
||||
margin-bottom: 30px; |
||||
} |
||||
.tile__title { |
||||
cursor: pointer; |
||||
padding: 7px 0 10px; |
||||
text-align: center; |
||||
background-color: #E0E4F2; |
||||
} |
||||
|
||||
.tile__list { |
||||
padding: 15px; |
||||
} |
||||
.tile__list img { |
||||
margin: 10px; |
||||
cursor: move; |
||||
} |
||||
|
||||
.download { |
||||
color: #333; |
||||
margin-left: 10px; |
||||
text-decoration: none; |
||||
} |
||||
.download:hover { |
||||
text-decoration: none; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
|
||||
<a href="https://github.com/RubaXa/Sortable"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a> |
||||
|
||||
<div class="container"> |
||||
<h1> |
||||
<a href="https://github.com/RubaXa/Sortable/">Sortable</a> |
||||
<a class="download" title="Download" href="https://github.com/RubaXa/Sortable/archive/master.zip">↓</a> |
||||
</h1> |
||||
<div>— is a minimalist JavaScript library for modern browsers and touch devices (No jQuery).</div> |
||||
|
||||
|
||||
<div class="row"> |
||||
<div class="col-md-6 col-sm-6"> |
||||
<h3>List A</h3> |
||||
|
||||
<ul id="contacts"> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-prn1/s32x32/41627_1611219478_5779_q.jpg"/> |
||||
<span>Catherine</span> |
||||
</li> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash3/s32x32/370175_619386670_43244658_q.jpg"/> |
||||
<span>Polina</span> |
||||
</li> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash3/s32x32/173108_654249662_698694459_q.jpg"/> |
||||
<span>Duke</span> |
||||
</li> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/s32x32/372024_100000330534964_827799899_q.jpg"/> |
||||
<span>Adnrey</span> |
||||
</li> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash1/s32x32/260934_100000460170867_1741520317_q.jpg"/> |
||||
<span>Maxim</span> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="col-md-6 col-sm-6"> |
||||
<h3>List B</h3> |
||||
|
||||
<ul id="tags"> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/s32x32/274297_100002088418977_1552918698_q.jpg"/> |
||||
<span>Ilya</span> |
||||
</li> |
||||
<li> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash1/s32x32/370664_100003149104712_1050952731_q.jpg"/> |
||||
<span>Anna</span> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<p> </p> |
||||
<p> </p> |
||||
|
||||
<div class="container" id="multi"> |
||||
<h2>Multi</h2> |
||||
|
||||
<div class="tile"> |
||||
<div class="tile__title">Group A</div> |
||||
<div class="tile__list"> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-prn1/c9.9.113.113/s100x100/59436_1391411357920_1388516_s.jpg"/><!-- |
||||
--><img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash3/c13.8.104.104/s100x100/941190_10151608397684663_1532692251_s.jpg"/><!-- |
||||
--><img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-frc3/c0.0.103.103/s100x100/382696_10150378364701671_1792621129_a.jpg"/><!-- |
||||
--><img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash3/c44.10.116.116/s100x100/552948_430685950285752_1435082176_a.jpg"/> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="tile"> |
||||
<div class="tile__title">Group B</div> |
||||
<div class="tile__list"> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash3/c8.8.105.105/s100x100/558916_4874661741992_448469446_s.jpg"/><!-- |
||||
--><img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-prn1/c29.9.117.117/s100x100/68347_385372304875713_1358705380_a.jpg"/><!-- |
||||
--><img src="https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/c9.9.113.113/s100x100/424349_465457316812937_2106915541_s.jpg"/> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="tile"> |
||||
<div class="tile__title">Group C</div> |
||||
<div class="tile__list"> |
||||
<img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-frc3/c12.12.156.156/s100x100/303317_320632284665935_15996162_a.jpg"/><!-- |
||||
--><img src="//fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/c9.9.109.109/s100x100/484507_4207733265938_1693034881_s.jpg"/> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="row"></div> |
||||
<p> </p> |
||||
</div> |
||||
|
||||
<div class="container"> |
||||
<h2>Code example</h2> |
||||
<pre class="javascript"><code>// Simple list |
||||
var list = document.getElementById("my-ui-list"); |
||||
new Sortable(list); // That's all. |
||||
|
||||
|
||||
// Grouping |
||||
var foo = document.getElementById("foo"); |
||||
new Sortable(foo, { group: "omega" }); |
||||
|
||||
var bar = document.getElementById("bar"); |
||||
new Sortable(bar, { group: "omega" }); |
||||
|
||||
|
||||
// Or |
||||
var container = document.getElementById("multi"); |
||||
var sort = new Sortable(container, { |
||||
handle: ".tile__title", // Restricts sort start click/touch to the specified element |
||||
dragabble: ".tile", // Specifies which items inside the element should be sortable |
||||
onUpdate: function (evt/**Event*/){ |
||||
var item = evt.detail; // the current dragged HTMLElement |
||||
} |
||||
}); |
||||
|
||||
// .. |
||||
sort.destroy(); |
||||
</code></pre> |
||||
|
||||
<p> </p> |
||||
<p> </p> |
||||
<p> </p> |
||||
</div> |
||||
|
||||
|
||||
<script src="Sortable.js"></script> |
||||
|
||||
<script> |
||||
(function (){ |
||||
var console = window.console; |
||||
|
||||
if( !console.log ){ |
||||
console.log = function (){ |
||||
alert([].join.apply(arguments, ' ')); |
||||
}; |
||||
} |
||||
|
||||
|
||||
new Sortable(contacts, { |
||||
group: "contacts", |
||||
onAdd: function (evt){ console.log('onAdd.contacts:', evt.detail); }, |
||||
onUpdate: function (evt){ console.log('onUpdate.contacts:', evt.detail); }, |
||||
onRemove: function (evt){ console.log('onRemove.contacts:', evt.detail); } |
||||
}); |
||||
|
||||
new Sortable(tags, { |
||||
group: "contacts", |
||||
onAdd: function (evt){ console.log('onAdd.tags:', evt.detail); }, |
||||
onUpdate: function (evt){ console.log('onUpdate.tags:', evt.detail); }, |
||||
onRemove: function (evt){ console.log('onRemove.tags:', evt.detail); } |
||||
}); |
||||
|
||||
|
||||
new Sortable(multi, { |
||||
draggable: '.tile', |
||||
handle: '.tile__title' |
||||
}); |
||||
|
||||
|
||||
[].forEach.call(multi.getElementsByClassName('tile__list'), function (el){ |
||||
new Sortable(el, { group: 'photo' }); |
||||
}); |
||||
})(); |
||||
|
||||
|
||||
function setNoiseBackground(el, color, 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") + "), "+color; |
||||
} |
||||
|
||||
// Usage |
||||
setNoiseBackground(document.getElementsByTagName('body')[0], "linear-gradient(to bottom, #E1E2D1 0%, #5AABA5 100%)", 50, 50, 0.03); |
||||
</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; |
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.4); |
||||
background-color: #fff; |
||||
} |
||||
|
||||
pre code { |
||||
display: block; |
||||
color: #4d4d4c; |
||||
font-family: Menlo, Monaco, Consolas, monospace; |
||||
line-height: 1.5; |
||||
padding: 10px; |
||||
} |
||||
</style> |
||||
|
||||
<script src="//yandex.st/highlightjs/7.5/highlight.min.js"></script> |
||||
<script>hljs.initHighlightingOnLoad();</script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,22 @@
|
||||
{ |
||||
"name": "sortable", |
||||
"exportName": "Sortable", |
||||
"version": "0.1.0", |
||||
"devDependencies": { |
||||
"grunt": "*", |
||||
"grunt-version": "*", |
||||
"grunt-contrib-uglify": "*" |
||||
}, |
||||
"description": "Sortable - is a minimalist JavaScript library for modern browsers and touch devices (No jQuery).", |
||||
"main": "Sortable.js", |
||||
"scripts": { |
||||
"test": "grunt" |
||||
}, |
||||
"repository": { |
||||
"type": "git", |
||||
"url": "git://github.com/rubaxa/Sortable.git" |
||||
}, |
||||
"keywords": ["sortable", "reorder"], |
||||
"author": "Konstantin Lebedev <ibnRubaXa@gmail.com>", |
||||
"license": "MIT" |
||||
} |
Loading…
Reference in new issue