Thomas Goirand e1d199edf3 Commits changes available on PyPi
The release .2 on PyPi already includes changes acted uppon in
Horizon. This patch commits those changes to stackforge. It
also adds a .gitreview file.

Change-Id: Ibc25f66dba97c2121b5d7fe485175d7cd76b6267
2015-04-03 09:26:20 +02:00

184 lines
6.6 KiB
JavaScript

(function (ng) {
'use strict';
function isJqueryEventDataTransfer(){
return window.jQuery && (-1 == window.jQuery.event.props.indexOf('dataTransfer'));
}
if (isJqueryEventDataTransfer()) {
window.jQuery.event.props.push('dataTransfer');
}
var module = ng.module('lrDragNDrop', []);
module.service('lrDragStore', ['$document', function (document) {
var store = {};
this.hold = function hold(key, item, collectionFrom, safe) {
store[key] = {
item: item,
collection: collectionFrom,
safe: safe === true
}
};
this.get = function (namespace) {
var
modelItem = store[namespace], itemIndex;
if (modelItem) {
itemIndex = modelItem.collection.indexOf(modelItem.item);
return modelItem.safe === true ? modelItem.item : modelItem.collection.splice(itemIndex, 1)[0];
} else {
return null;
}
};
this.clean = function clean() {
store = {};
};
this.isHolding = function (namespace) {
return store[namespace] !== undefined;
};
document.bind('dragend', this.clean);
}]);
module.service('lrDragHelper', function () {
var th = this;
th.parseRepeater = function(scope, attr) {
var
repeatExpression = attr.ngRepeat,
match;
if (!repeatExpression) {
throw Error('this directive must be used with ngRepeat directive');
}
match = repeatExpression.match(/^(.*\sin).(\S*)/);
if (!match) {
throw Error("Expected ngRepeat in form of '_item_ in _collection_' but got '" +
repeatExpression + "'.");
}
return scope.$eval(match[2]);
};
th.lrDragSrcDirective = function(store, safe) {
return function compileFunc(el, iattr) {
iattr.$set('draggable', true);
return function linkFunc(scope, element, attr) {
var
collection,
key = (safe === true ? attr.lrDragSrcSafe : attr.lrDragSrc ) || 'temp';
if(attr.lrDragData) {
scope.$watch(attr.lrDragData, function (newValue) {
collection = newValue;
});
} else {
collection = th.parseRepeater(scope, attr);
}
element.bind('dragstart', function (evt) {
store.hold(key, collection[scope.$index], collection, safe);
if(angular.isDefined(evt.dataTransfer)) {
evt.dataTransfer.setData('text/html', null); //FF/jQuery fix
}
});
}
}
}
});
module.directive('lrDragSrc', ['lrDragStore', 'lrDragHelper', function (store, dragHelper) {
return{
compile: dragHelper.lrDragSrcDirective(store)
};
}]);
module.directive('lrDragSrcSafe', ['lrDragStore', 'lrDragHelper', function (store, dragHelper) {
return{
compile: dragHelper.lrDragSrcDirective(store, true)
};
}]);
module.directive('lrDropTarget', ['lrDragStore', 'lrDragHelper', '$parse', function (store, dragHelper, $parse) {
return {
link: function (scope, element, attr) {
var
collection,
key = attr.lrDropTarget || 'temp',
classCache = null;
function isAfter(x, y) {
//check if below or over the diagonal of the box element
return (element[0].offsetHeight - x * element[0].offsetHeight / element[0].offsetWidth) < y;
}
function resetStyle() {
if (classCache !== null) {
element.removeClass(classCache);
classCache = null;
}
}
if(attr.lrDragData) {
scope.$watch(attr.lrDragData, function (newValue) {
collection = newValue;
});
} else {
collection = dragHelper.parseRepeater(scope, attr);
}
element.bind('drop', function (evt) {
var
collectionCopy = ng.copy(collection),
item = store.get(key),
dropIndex, i, l;
if (item !== null) {
dropIndex = scope.$index;
dropIndex = isAfter(evt.offsetX, evt.offsetY) ? dropIndex + 1 : dropIndex;
//srcCollection=targetCollection => we may need to apply a correction
if (collectionCopy.length > collection.length) {
for (i = 0, l = Math.min(dropIndex, collection.length - 1); i <= l; i++) {
if (!ng.equals(collectionCopy[i], collection[i])) {
dropIndex = dropIndex - 1;
break;
}
}
}
scope.$apply(function () {
collection.splice(dropIndex, 0, item);
var fn = $parse(attr.lrDropSuccess) || ng.noop;
fn(scope, {e: evt, item: item, collection: collection});
});
evt.preventDefault();
resetStyle();
store.clean();
}
});
element.bind('dragleave', resetStyle);
element.bind('dragover', function (evt) {
var className;
if (store.isHolding(key)) {
className = isAfter(evt.offsetX, evt.offsetY) ? 'lr-drop-target-after' : 'lr-drop-target-before';
if (classCache !== className && classCache !== null) {
element.removeClass(classCache);
}
if (classCache !== className) {
element.addClass(className);
}
classCache = className;
}
evt.preventDefault();
});
}
};
}]);
})(angular);