1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00
This commit is contained in:
Luke Pulverenti 2017-01-27 18:07:14 -05:00
parent 82bcca376f
commit 8a6884abef
494 changed files with 256 additions and 120180 deletions

View file

@ -1,43 +0,0 @@
{
"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
}

View file

@ -1,12 +0,0 @@
# editorconfig.org
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View file

@ -1,5 +0,0 @@
node_modules
mock.png
.*.sw*
.build*
jquery.fn.*

View file

@ -1,24 +0,0 @@
{
"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
}
}

View file

@ -1,23 +0,0 @@
# 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```

View file

@ -1,103 +0,0 @@
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']);
};

View file

@ -1,32 +0,0 @@
{
"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"
]
}

View file

@ -1,32 +0,0 @@
{
"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"
]
}

View file

@ -1,61 +1 @@
/**
* 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;
};
});
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["jquery"],factory):factory(jQuery)}(function($){"use strict";$.fn.sortable=function(options){var retVal,args=arguments;return 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)),sortable){if("widget"===options)return sortable;"destroy"===options?(sortable.destroy(),$el.removeData("sortable")):"function"==typeof sortable[options]?retVal=sortable[options].apply(sortable,[].slice.call(args,1)):options in sortable.options&&(retVal=sortable.option.apply(sortable,args))}}),void 0===retVal?this:retVal}});

View file

@ -1,182 +1 @@
(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);
}
};
});
!function(factory){"use strict";if("function"==typeof define&&define.amd)define(["knockout"],factory);else if("function"==typeof require&&"object"==typeof exports&&"object"==typeof module){var ko=require("knockout");factory(ko)}else factory(window.ko)}(function(ko){"use strict";var init=function(element,valueAccessor,allBindings,viewModel,bindingContext,sortableOptions){var options=buildOptions(valueAccessor,sortableOptions);["onStart","onEnd","onRemove","onAdd","onUpdate","onSort","onFilter"].forEach(function(e){(options[e]||eventHandlers[e])&&(options[e]=function(eventType,parentVM,parentBindings,handler,e){var itemVM=ko.dataFor(e.item),bindings=ko.utils.peekObservable(parentBindings()),bindingHandlerBinding=bindings.sortable||bindings.draggable,collection=bindingHandlerBinding.collection||bindingHandlerBinding.foreach;handler&&handler(e,itemVM,parentVM,collection,bindings),eventHandlers[eventType]&&eventHandlers[eventType](e,itemVM,parentVM,collection,bindings)}.bind(void 0,e,viewModel,allBindings,options[e]))});var sortableElement=Sortable.create(element,options);return ko.utils.domNodeDisposal.addDisposeCallback(element,function(){sortableElement.destroy()}),ko.bindingHandlers.template.init(element,valueAccessor)},update=function(element,valueAccessor,allBindings,viewModel,bindingContext,sortableOptions){return ko.bindingHandlers.template.update(element,valueAccessor,allBindings,viewModel,bindingContext)},eventHandlers=function(handlers){var moveOperations=[],tryMoveOperation=function(e,itemVM,parentVM,collection,parentBindings){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.splice(moveOperations.indexOf(existingOperation),1);var removeOperation="remove"===currentOperation.event.type?currentOperation:existingOperation,addOperation="add"===currentOperation.event.type?currentOperation:existingOperation;moveItem(itemVM,removeOperation.collection,addOperation.collection,addOperation.event.clone,addOperation.event)}else moveOperations.push(currentOperation)},moveItem=function(itemVM,from,to,clone,e){var fromArray=from(),originalIndex=fromArray.indexOf(itemVM),newIndex=e.newIndex;e.item.previousElementSibling&&(newIndex=fromArray.indexOf(ko.dataFor(e.item.previousElementSibling)),originalIndex>newIndex&&(newIndex+=1)),e.item.parentNode.removeChild(e.item),fromArray.splice(originalIndex,1),from.valueHasMutated(),clone&&from!==to&&(fromArray.splice(originalIndex,0,itemVM),from.valueHasMutated()),to().splice(newIndex,0,itemVM),to.valueHasMutated()};return handlers.onRemove=tryMoveOperation,handlers.onAdd=tryMoveOperation,handlers.onUpdate=function(e,itemVM,parentVM,collection,parentBindings){moveItem(itemVM,collection,collection,!1,e)},handlers}({}),buildOptions=function(bindingOptions,options){var merge=function(into,from){for(var prop in from)"[object Object]"===Object.prototype.toString.call(from[prop])?("[object Object]"!==Object.prototype.toString.call(into[prop])&&(into[prop]={}),into[prop]=merge(into[prop],from[prop])):into[prop]=from[prop];return into},unwrappedOptions=ko.utils.peekObservable(bindingOptions()).options||{};return options=merge({},options),unwrappedOptions.group&&"[object Object]"!==Object.prototype.toString.call(unwrappedOptions.group)&&(unwrappedOptions.group={name:unwrappedOptions.group}),merge(options,unwrappedOptions)};ko.bindingHandlers.draggable={sortableOptions:{group:{pull:"clone",put:!1},sort:!1},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:!0,put:!0}},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)}}});

View file

@ -1,191 +1 @@
/**
* @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);
}
}
}));
});
}
};
}]);
});
!function(factory){"use strict";"function"==typeof define&&define.amd?define(["angular","./Sortable"],factory):"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?(require("angular"),factory(angular,require("./Sortable")),module.exports="ng-sortable"):window.angular&&window.Sortable&&factory(angular,Sortable)}(function(angular,Sortable){"use strict";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(el,scope){var ngRepeat=[].filter.call(el.childNodes,function(node){return 8===node.nodeType&&node.nodeValue.indexOf("ngRepeat:")!==-1})[0];if(!ngRepeat)return function(){return null};ngRepeat=ngRepeat.nodeValue.match(/ngRepeat:\s*(?:\(.*?,\s*)?([^\s)]+)[\s)]+in\s+([^\s|]+)/);var itemsExpr=$parse(ngRepeat[2]);return function(){return itemsExpr(scope.$parent)||[]}};return{restrict:"AC",scope:{ngSortable:"=?"},link:function(scope,$el){function _emitEvent(evt,item){var name="on"+evt.type.charAt(0).toUpperCase()+evt.type.substr(1),source=getSource();options[name]&&options[name]({model:item||source[evt.newIndex],models:source,oldIndex:evt.oldIndex,newIndex:evt.newIndex})}function _sync(evt){var items=getSource();if(items){var oldIndex=evt.oldIndex,newIndex=evt.newIndex;if(el!==evt.from){var prevItems=evt.from[expando]();removed=prevItems[oldIndex],evt.clone?(removed=angular.copy(removed),prevItems.splice(Sortable.utils.index(evt.clone),0,prevItems.splice(oldIndex,1)[0]),evt.from.removeChild(evt.clone)):prevItems.splice(oldIndex,1),items.splice(newIndex,0,removed),evt.from.insertBefore(evt.item,nextSibling)}else items.splice(newIndex,0,items.splice(oldIndex,1)[0]);scope.$apply()}}var sortable,el=$el[0],options=angular.extend(scope.ngSortable||{},ngSortableConfig),watchers=[],getSource=getSourceFactory(el,scope);el[expando]=getSource,sortable=Sortable.create(el,Object.keys(options).reduce(function(opts,name){return opts[name]=opts[name]||options[name],opts},{onStart:function(evt){nextSibling=evt.item.nextSibling,_emitEvent(evt),scope.$apply()},onEnd:function(evt){_emitEvent(evt,removed),scope.$apply()},onAdd:function(evt){_sync(evt),_emitEvent(evt,removed),scope.$apply()},onUpdate:function(evt){_sync(evt),_emitEvent(evt)},onRemove:function(evt){_emitEvent(evt,removed)},onSort:function(evt){_emitEvent(evt)}})),$el.on("$destroy",function(){angular.forEach(watchers,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){void 0!==value&&(options[name]=value,/^on[A-Z]/.test(name)||sortable.option(name,value))}))})}}}])});

View file

@ -1,41 +0,0 @@
{
"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"
]
}
}

View file

@ -1,165 +1 @@
/**
* @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;
});
!function(factory){"use strict";"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=factory(require("./Sortable")):"function"==typeof define&&define.amd?define(["./Sortable"],factory):window.SortableMixin=factory(Sortable)}(function(Sortable){"use strict";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)src.hasOwnProperty(key)&&(dst[key]=src[key]);return dst}var _nextSibling,_activeComponent,_defaultOptions={ref:"list",model:"items",animation:100,onStart:"handleStart",onEnd:"handleEnd",onAdd:"handleAdd",onUpdate:"handleUpdate",onRemove:"handleRemove",onSort:"handleSort",onFilter:"handleFilter",onMove:"handleMove"},SortableMixin={sortableMixinVersion:"0.1.1",_sortableInstance:null,componentDidMount:function(){var DOMNode,options=_extend(_extend({},_defaultOptions),this.sortableOptions||{}),copyOptions=_extend({},options),emitEvent=function(type,evt){var method=this[options[type]];method&&method.call(this,evt,this._sortableInstance)}.bind(this);"onStart onEnd onAdd onSort onUpdate onRemove onFilter onMove".split(" ").forEach(function(name){copyOptions[name]=function(evt){if("onStart"===name)_nextSibling=evt.item.nextElementSibling,_activeComponent=this;else if("onAdd"===name||"onUpdate"===name){evt.from.insertBefore(evt.item,_nextSibling);var remoteItems,item,newState={},remoteState={},oldIndex=evt.oldIndex,newIndex=evt.newIndex,items=_getModelItems(this);"onAdd"===name?(remoteItems=_getModelItems(_activeComponent),item=remoteItems.splice(oldIndex,1)[0],items.splice(newIndex,0,item),remoteState[_getModelName(_activeComponent)]=remoteItems):items.splice(newIndex,0,items.splice(oldIndex,1)[0]),newState[_getModelName(this)]=items,copyOptions.stateHandler?this[copyOptions.stateHandler](newState):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,this._sortableInstance=Sortable.create(DOMNode,copyOptions)},componentWillReceiveProps:function(nextProps){var newState={},modelName=_getModelName(this),items=nextProps[modelName];items&&(newState[modelName]=items,this.setState(newState))},componentWillUnmount:function(){this._sortableInstance.destroy(),this._sortableInstance=null}};return SortableMixin});