Added drag/drop for Role Assign page

Updated dragdrop lib

Change-Id: I2a66b8bdf2b8cc03b648ce2fc647a6220be9464d
This commit is contained in:
Shuai Zhu 2014-09-16 17:11:42 -07:00
parent 6dc22eaf8a
commit e44bc3f6e2
5 changed files with 392 additions and 124 deletions

View File

@ -608,6 +608,7 @@ div.center-align {
} }
.widget-header-marginbottom { .widget-header-marginbottom {
border-bottom: 1px solid #bed2db !important; border-bottom: 1px solid #bed2db !important;
margin-bottom: 15px;
} }
.network-background { .network-background {
background-image: url(); background-image: url();
@ -948,7 +949,6 @@ circle[depth='4'] {
display: block !important; display: block !important;
} }
} }
.angular-ui-tree-handle { .angular-ui-tree-handle {
background: #f8faff; background: #f8faff;
border: 1px solid #dae2ea; border: 1px solid #dae2ea;
@ -956,13 +956,11 @@ circle[depth='4'] {
padding: 10px 10px; padding: 10px 10px;
cursor: default; cursor: default;
} }
.angular-ui-tree-handle:hover { .angular-ui-tree-handle:hover {
color: #438eb9; color: #438eb9;
background: #f4f6f7; background: #f4f6f7;
border-color: #dce2e8; border-color: #dce2e8;
} }
.angular-ui-tree-placeholder { .angular-ui-tree-placeholder {
background: #f0f9ff; background: #f0f9ff;
border: 2px dashed #bed2db; border: 2px dashed #bed2db;
@ -970,9 +968,54 @@ circle[depth='4'] {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }
.group-title { .group-title {
background-color: #687074 !important; background-color: #687074 !important;
color: #FFF !important; color: #FFF !important;
} }
.role-assign-drop {
min-height: 25px;
min-width: 200px;
/* background-color: rgba(221, 221, 221, 0.32); */
}
.role-assign-drag {
border: 1px solid rgba(190, 210, 219, 0.5) !important;
border-radius: 4px;
min-height: 400px;
min-width: 120px;
}
.role-table-padding {
padding: 0px 0px 15px 0px !important;
width: 87%;
}
.role-widget-box {
position: fixed !important;
margin-left: 0px !important;
}
.margin-left-neg4 {
margin-left: -4px;
}
.drag-roles {
margin-left: 12px;
margin-top: 7px;
display: block !important;
width: 95px !important;
border-radius: 4px !important;
}
.drag-role-col {
width: 13%;
}
.role-col {
float: left !important;
min-height: 1px;
padding-left: 15px;
padding-right: 15px;
position: relative;
}
.drag-enter-role {
background: none repeat scroll 0 0 #F0F9FF;
border: 2px dashed #BED2DB !important;
box-sizing: border-box;
margin: 5px 0;
min-height: 35px;
padding: 0;
}

View File

@ -390,6 +390,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
}]; }];
return [200, machines, {}]; return [200, machines, {}];
}); });
/* /*
$httpBackend.whenPOST(settings.apiUrlBase + '/switch-filters').respond(function(method, url, data) { $httpBackend.whenPOST(settings.apiUrlBase + '/switch-filters').respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
@ -650,6 +651,15 @@ compassAppDev.run(function($httpBackend, settings, $http) {
}, { }, {
"display_name": "Network", "display_name": "Network",
"name": "os-network" "name": "os-network"
}, {
"display_name": "Storage",
"name": "os-block-storage-worker"
}, {
"display_name": "Message Queue",
"name": "os-mq"
}, {
"display_name": "database",
"name": "os-db"
}] }]
}, },
"links": [{ "links": [{
@ -915,6 +925,26 @@ compassAppDev.run(function($httpBackend, settings, $http) {
console.log(method, url, data); console.log(method, url, data);
var hosts = []; var hosts = [];
var num = 20; var num = 20;
var test_roles = [{
"display_name": "Compute",
"name": "os-compute-worker"
}, {
"display_name": "Controller",
"name": "os-controller"
}, {
"display_name": "Network",
"name": "os-network"
}, {
"display_name": "Storage",
"name": "os-block-storage-worker"
}, {
"display_name": "Message Queue",
"name": "os-mq"
}, {
"display_name": "database",
"name": "os-db"
}];
for (var i = 1; i <= num; i++) { for (var i = 1; i <= num; i++) {
var host = { var host = {
"id": i, "id": i,
@ -925,14 +955,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
"switch_ip": "172.29.8.40", "switch_ip": "172.29.8.40",
"port": i, "port": i,
"vlan": i, "vlan": i,
"roles": [{ "roles": [test_roles[i%6]],
"display_name": "Network",
"name": "os-network"
}, {
"display_name": "Storage",
"name": "os-block-storage-worker"
}],
"os_name": "CentOS",
"clusters": [{ "clusters": [{
"id": 1, "id": 1,
"name": "cluster1" "name": "cluster1"

View File

@ -76,6 +76,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="role-col role-table-padding">
<div class="space-6"></div> <div class="space-6"></div>
<table ng-table="tableParams" class="table table-hover table-striped"> <table ng-table="tableParams" class="table table-hover table-striped">
<thead> <thead>
@ -94,43 +95,60 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="server in $data | filter: search" ng-init="server.roles = server.roles === undefinded? [] : server.roles" ng-class="{'hightlight': server.checked}"> <tr ng-repeat="(key, value) in $data | filter: search" ng-init="value.roles = value.roles === undefinded? [] : value.roles" ng-class="{'hightlight': value.checked}">
<td> <td>
<label> <label>
<input ng-model="server.checked" type="checkbox" class="ace"> <input ng-model="value.checked" type="checkbox" class="ace">
<span class="lbl"></span> <span class="lbl"></span>
</label> </label>
</td> </td>
<td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field"> <td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field">
<span ng-switch on="column.field"> <span ng-switch on="column.field">
<span ng-switch-when="os_installed"> <span ng-switch-when="os_installed">
<span ng-if="server['os']"> <span ng-if="value['os']">
<label> <label>
<input ng-model="server.reinstallos" type="checkbox" class="ace"> <input ng-model="value.reinstallos" type="checkbox" class="ace">
<span class="lbl"></span> <span class="lbl"></span>
</label> </label>
</span> </span>
<span ng-if="!server['os']"> <span ng-if="!value['os']">
- -
</span> </span>
</span> </span>
<span ng-switch-when="clusters"> <span ng-switch-when="clusters">
<span ng-repeat="cluster in server.clusters"> <span ng-repeat="cluster in value.clusters">
{{cluster.name}}&nbsp; {{cluster.name}}&nbsp;
</span> </span>
</span> </span>
<span ng-switch-default> <span ng-switch-default>
{{server[column.field]}} {{value[column.field]}}
</span> </span>
</span> </span>
</td> </td>
<td> <td>
<alert ng-repeat="role in server['roles']" class="role-tag" ng-style="{'background-color': role.color}" close="removeRole(server, role)"> <div class="role-assign-drop" ui-on-Drop="onDrop($event, key)" drag-hover-class="drag-enter-role" drop-channel="{{value.dropChannel}}">
<alert ng-repeat="role in value['roles']" class="role-tag border-radius-4" ng-style="{'background-color': role.color}" close="removeRole(value, role)">
{{role.display_name}} {{role.display_name}}
</alert> </alert>
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="role-col drag-role-col">
<div class="widget-box transparent role-widget-box">
<div class="widget-header widget-header-marginbottom">
<br>
<h4 class="margin-left-neg4">Drag Roles <br> to Assign</h4>
</div>
<div class="role-assign-drag">
<div ui-draggable="true" on-drop-success="dropSuccessHandler($event,role_value,role_key)" class="role-tag drag-roles ui-draggable" ng-repeat="(role_key, role_value) in roles" ng-style="{'background-color': role_value.color}" drag-channel="{{role_value.dragChannel}}">
<i class="ace-icon fa fa-arrows margin-left-neg4"></i>
<span>{{role_value.display_name}}</span>
</div>
</div>
</div>
</div>
</div>
</div> </div>

View File

@ -1117,29 +1117,43 @@ angular.module('compass.wizard', [
var cluster = wizardFactory.getClusterInfo(); var cluster = wizardFactory.getClusterInfo();
$scope.servers = wizardFactory.getServers(); $scope.servers = wizardFactory.getServers();
var colors = ['#8EA16C', '#C2CF30', '#FEC700', '#FF8900', '#D3432B', '#BB2952', '#8E1E5F', '#DE4AB6', '#9900EC', '#3A1AA8', '#3932FE', '#278BC0', '#35B9F6', '#91E0CB', '#42BC6A', '#5B4141']; var colors = ['#8EA16C', '#C2CF30', '#FEC700', '#FF8900', '#D3432B', '#BB2952', '#8E1E5F', '#DE4AB6', '#9900EC', '#3A1AA8', '#3932FE', '#278BC0', '#35B9F6', '#91E0CB', '#42BC6A', '#5B4141'];
$scope.existingRoles = [];
$scope.realRole = [];
dataService.getServerColumns().success(function(data) {
$scope.server_columns = data.showless;
});
dataService.getClusterById(cluster.id).success(function(data) { dataService.getClusterById(cluster.id).success(function(data) {
// wizardFactory.setAdapter(data); // wizardFactory.setAdapter(data);
$scope.roles = data.flavor.roles; $scope.roles = data.flavor.roles;
var i = 0; var i = 0;
angular.forEach($scope.roles, function(role) { angular.forEach($scope.roles, function(role, role_key) {
role.color = colors[i]; role.color = colors[i];
$scope.roles[role_key].dragChannel = i;
i++; i++;
})
}); });
angular.forEach($scope.roles, function(role, role_key) {
dataService.getServerColumns().success(function(data) { //realRole.splice(z,0,z);
$scope.server_columns = data.showless; $scope.realRole.push(role_key);
});
angular.forEach($scope.servers, function(value, key) {
$scope.existingRoles.push(angular.copy($scope.realRole));
$scope.servers[key].dropChannel = $scope.existingRoles[key].toString();
});
$scope.checkExistRolesDrag();
}); });
$scope.selectAllServers = function(flag) { $scope.selectAllServers = function(flag) {
if (flag) { if (flag) {
angular.forEach($scope.servers, function(sv) { angular.forEach($scope.servers, function(sv) {
sv.checked = true; sv.checked = true;
}) });
} else { } else {
angular.forEach($scope.servers, function(sv) { angular.forEach($scope.servers, function(sv) {
sv.checked = false; sv.checked = false;
}) });
} }
}; };
@ -1147,6 +1161,14 @@ angular.module('compass.wizard', [
var serverIndex = $scope.servers.indexOf(server); var serverIndex = $scope.servers.indexOf(server);
var roleIndex = $scope.servers[serverIndex].roles.indexOf(role); var roleIndex = $scope.servers[serverIndex].roles.indexOf(role);
$scope.servers[serverIndex].roles.splice(roleIndex, 1); $scope.servers[serverIndex].roles.splice(roleIndex, 1);
angular.forEach($scope.roles, function(role_value, role_key) {
if (role.display_name == $scope.roles[role_key].display_name) {
$scope.existingRoles[serverIndex].splice(role_key, 1, role_key)
}
});
$scope.servers[serverIndex].dropChannel = $scope.existingRoles[serverIndex].toString();
}; };
$scope.assignRole = function(role) { $scope.assignRole = function(role) {
@ -1192,7 +1214,7 @@ angular.module('compass.wizard', [
} }
svIndex++; svIndex++;
} }
}) });
}; };
$scope.checkRoleExist = function(existingRoles, newRole) { $scope.checkRoleExist = function(existingRoles, newRole) {
@ -1310,6 +1332,33 @@ angular.module('compass.wizard', [
wizardFactory.setCommitState(commitState); wizardFactory.setCommitState(commitState);
}); });
}; };
$scope.onDrop = function($event, key) {
$scope.dragKey = key;
};
$scope.dropSuccessHandler = function($event, role_value, key) {
var roleExist = $scope.checkRoleExist($scope.servers[$scope.dragKey].roles, role_value);
if (!roleExist) {
$scope.servers[$scope.dragKey].roles.push(role_value);
} else {
console.log("role exists");
}
$scope.checkExistRolesDrag();
};
$scope.checkExistRolesDrag = function() {
angular.forEach($scope.servers, function(value, key) {
angular.forEach($scope.servers[key].roles, function(server_role, server_role_key) {
angular.forEach($scope.roles, function(role, role_key) {
if ($scope.servers[key].roles[server_role_key].display_name == $scope.roles[role_key].display_name) {
$scope.existingRoles[key].splice(role_key, 1, "p")
}
})
})
$scope.servers[key].dropChannel = $scope.existingRoles[key].toString();
})
};
}) })
.controller('networkMappingCtrl', function($scope, wizardFactory, dataService) { .controller('networkMappingCtrl', function($scope, wizardFactory, dataService) {
@ -1326,7 +1375,6 @@ angular.module('compass.wizard', [
$scope.interfaces[key].dropChannel = "E"; $scope.interfaces[key].dropChannel = "E";
}) })
$scope.networking = {}; $scope.networking = {};
angular.forEach($scope.original_networking, function(value, key) { angular.forEach($scope.original_networking, function(value, key) {
$scope.networking[key] = {}; $scope.networking[key] = {};
@ -1339,7 +1387,6 @@ angular.module('compass.wizard', [
$scope.dropSuccessHandler = function($event, key, dict) { $scope.dropSuccessHandler = function($event, key, dict) {
dict[key].mapping_interface = $scope.pendingInterface; dict[key].mapping_interface = $scope.pendingInterface;
console.log($scope.pendingInterface);
}; };
angular.forEach($scope.interfaces, function(value, key) { angular.forEach($scope.interfaces, function(value, key) {

View File

@ -5,26 +5,45 @@
* Time: 11:27 * Time: 11:27
* To change this template use File | Settings | File Templates. * To change this template use File | Settings | File Templates.
*/ */
(function(){
function isDnDsSupported(){
return 'draggable' in document.createElement("span");
}
if(!isDnDsSupported()){
return;
}
if (window.jQuery && (-1 == window.jQuery.event.props.indexOf("dataTransfer"))) { if (window.jQuery && (-1 == window.jQuery.event.props.indexOf("dataTransfer"))) {
window.jQuery.event.props.push("dataTransfer"); window.jQuery.event.props.push("dataTransfer");
} }
var currentData;
angular.module("ngDragDrop",[]) angular.module("ngDragDrop",[])
.directive("uiDraggable", [ .directive("uiDraggable", [
'$parse', '$parse',
'$rootScope', '$rootScope',
function ($parse, $rootScope) { '$dragImage',
function ($parse, $rootScope, $dragImage) {
return function (scope, element, attrs) { return function (scope, element, attrs) {
var dragData = "", var dragData = "",
isDragHandleUsed = false, isDragHandleUsed = false,
dragHandleClass, dragHandleClass,
dragHandles,
dragTarget; dragTarget;
element.attr("draggable", false); element.attr("draggable", false);
attrs.$observe("uiDraggable", function (newValue) { attrs.$observe("uiDraggable", function (newValue) {
if(newValue){
element.attr("draggable", newValue); element.attr("draggable", newValue);
}
else{
element.removeAttr("draggable");
}
}); });
if (attrs.drag) { if (attrs.drag) {
@ -36,42 +55,16 @@ angular.module("ngDragDrop",[])
if (angular.isString(attrs.dragHandleClass)) { if (angular.isString(attrs.dragHandleClass)) {
isDragHandleUsed = true; isDragHandleUsed = true;
dragHandleClass = attrs.dragHandleClass.trim() || "drag-handle"; dragHandleClass = attrs.dragHandleClass.trim() || "drag-handle";
dragHandles = element.find('.' + dragHandleClass).toArray();
element.bind("mousedown", function (e) { element.bind("mousedown", function (e) {
dragTarget = e.target; dragTarget = e.target;
}); });
} }
element.bind("dragstart", function (e) { function dragendHandler(e) {
var isDragAllowed = !isDragHandleUsed || -1 != dragHandles.indexOf(dragTarget); setTimeout(function() {
element.unbind('$destroy', dragendHandler);
if (isDragAllowed) { }, 0);
var sendData = angular.toJson(dragData);
var sendChannel = attrs.dragChannel || "defaultchannel";
var dragImage = attrs.dragImage || null;
if (dragImage) {
var dragImageFn = $parse(attrs.dragImage);
scope.$apply(function() {
var dragImageParameters = dragImageFn(scope, {$event: e});
if (dragImageParameters && dragImageParameters.image) {
var xOffset = dragImageParameters.xOffset || 0,
yOffset = dragImageParameters.yOffset || 0;
e.dataTransfer.setDragImage(dragImageParameters.image, xOffset, yOffset);
}
});
}
e.dataTransfer.setData("text/plain", sendData);
e.dataTransfer.effectAllowed = "copyMove";
$rootScope.$broadcast("ANGULAR_DRAG_START", sendChannel);
}
else {
e.preventDefault();
}
});
element.bind("dragend", function (e) {
var sendChannel = attrs.dragChannel || "defaultchannel"; var sendChannel = attrs.dragChannel || "defaultchannel";
$rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel); $rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel);
if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") { if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") {
@ -80,11 +73,55 @@ angular.module("ngDragDrop",[])
scope.$apply(function () { scope.$apply(function () {
fn(scope, {$event: e}); fn(scope, {$event: e});
}); });
} else {
if (attrs.onDropFailure) {
var fn = $parse(attrs.onDropFailure);
scope.$apply(function () {
fn(scope, {$event: e});
});
}
}
}
}
element.bind("dragend", dragendHandler);
element.bind("dragstart", function (e) {
var isDragAllowed = !isDragHandleUsed || dragTarget.classList.contains(dragHandleClass);
if (isDragAllowed) {
var sendChannel = attrs.dragChannel || "defaultchannel";
var sendData = angular.toJson({ data: dragData, channel: sendChannel });
var dragImage = attrs.dragImage || null;
element.bind('$destroy', dragendHandler);
if (dragImage) {
var dragImageFn = $parse(attrs.dragImage);
scope.$apply(function() {
var dragImageParameters = dragImageFn(scope, {$event: e});
if (dragImageParameters) {
if (angular.isString(dragImageParameters)) {
dragImageParameters = $dragImage.generate(dragImageParameters);
}
if (dragImageParameters.image) {
var xOffset = dragImageParameters.xOffset || 0,
yOffset = dragImageParameters.yOffset || 0;
e.dataTransfer.setDragImage(dragImageParameters.image, xOffset, yOffset);
} }
} }
}); });
}
e.dataTransfer.setData("Text", sendData);
currentData = angular.fromJson(sendData);
e.dataTransfer.effectAllowed = "copyMove";
$rootScope.$broadcast("ANGULAR_DRAG_START", sendChannel);
}
else {
e.preventDefault();
}
});
}; };
} }
]) ])
@ -94,7 +131,7 @@ angular.module("ngDragDrop",[])
function ($parse, $rootScope) { function ($parse, $rootScope) {
return function (scope, element, attr) { return function (scope, element, attr) {
var dragging = 0; //Ref. http://stackoverflow.com/a/10906204 var dragging = 0; //Ref. http://stackoverflow.com/a/10906204
var dropChannel = "defaultchannel"; var dropChannel = attr.dropChannel || "defaultchannel" ;
var dragChannel = ""; var dragChannel = "";
var dragEnterClass = attr.dragEnterClass || "on-drag-enter"; var dragEnterClass = attr.dragEnterClass || "on-drag-enter";
var dragHoverClass = attr.dragHoverClass || "on-drag-hover"; var dragHoverClass = attr.dragHoverClass || "on-drag-hover";
@ -121,7 +158,7 @@ angular.module("ngDragDrop",[])
function onDragEnter(e) { function onDragEnter(e) {
dragging++; dragging++;
$rootScope.$broadcast("ANGULAR_HOVER", dropChannel); $rootScope.$broadcast("ANGULAR_HOVER", dragChannel);
element.addClass(dragHoverClass); element.addClass(dragHoverClass);
} }
@ -132,13 +169,16 @@ angular.module("ngDragDrop",[])
if (e.stopPropagation) { if (e.stopPropagation) {
e.stopPropagation(); // Necessary. Allows us to drop. e.stopPropagation(); // Necessary. Allows us to drop.
} }
var data = e.dataTransfer.getData("text/plain");
data = angular.fromJson(data); var sendData = e.dataTransfer.getData("Text");
sendData = angular.fromJson(sendData);
var fn = $parse(attr.uiOnDrop); var fn = $parse(attr.uiOnDrop);
scope.$apply(function () { scope.$apply(function () {
fn(scope, {$data: data, $event: e}); fn(scope, {$data: sendData.data, $event: e, $channel: sendData.channel});
}); });
element.removeClass(dragEnterClass); element.removeClass(dragEnterClass);
dragging = 0;
} }
function isDragChannelAccepted(dragChannel, dropChannel) { function isDragChannelAccepted(dragChannel, dropChannel) {
@ -151,9 +191,31 @@ angular.module("ngDragDrop",[])
return channelMatchPattern.test("," + dropChannel + ","); return channelMatchPattern.test("," + dropChannel + ",");
} }
$rootScope.$on("ANGULAR_DRAG_START", function (event, channel) { function preventNativeDnD(e) {
if (e.preventDefault) {
e.preventDefault();
}
if (e.stopPropagation) {
e.stopPropagation();
}
e.dataTransfer.dropEffect = "none";
return false;
}
var deregisterDragStart = $rootScope.$on("ANGULAR_DRAG_START", function (event, channel) {
dragChannel = channel; dragChannel = channel;
if (isDragChannelAccepted(dragChannel, dropChannel)) { if (isDragChannelAccepted(channel, dropChannel)) {
if (attr.dropValidate) {
var validateFn = $parse(attr.dropValidate);
var valid = validateFn(scope, {$data: currentData.data, $channel: currentData.channel});
if (!valid) {
element.bind("dragover", preventNativeDnD);
element.bind("dragenter", preventNativeDnD);
element.bind("dragleave", preventNativeDnD);
element.bind("drop", preventNativeDnD);
return;
}
}
element.bind("dragover", onDragOver); element.bind("dragover", onDragOver);
element.bind("dragenter", onDragEnter); element.bind("dragenter", onDragEnter);
@ -162,12 +224,18 @@ angular.module("ngDragDrop",[])
element.bind("drop", onDrop); element.bind("drop", onDrop);
element.addClass(dragEnterClass); element.addClass(dragEnterClass);
} }
else {
element.bind("dragover", preventNativeDnD);
element.bind("dragenter", preventNativeDnD);
element.bind("dragleave", preventNativeDnD);
element.bind("drop", preventNativeDnD);
}
}); });
$rootScope.$on("ANGULAR_DRAG_END", function (e, channel) { var deregisterDragEnd = $rootScope.$on("ANGULAR_DRAG_END", function (e, channel) {
dragChannel = ""; dragChannel = "";
if (isDragChannelAccepted(channel, dropChannel)) { if (isDragChannelAccepted(channel, dropChannel)) {
@ -179,16 +247,28 @@ angular.module("ngDragDrop",[])
element.removeClass(dragHoverClass); element.removeClass(dragHoverClass);
element.removeClass(dragEnterClass); element.removeClass(dragEnterClass);
} }
element.unbind("dragover", preventNativeDnD);
element.unbind("dragenter", preventNativeDnD);
element.unbind("dragleave", preventNativeDnD);
element.unbind("drop", preventNativeDnD);
}); });
$rootScope.$on("ANGULAR_HOVER", function (e, channel) { var deregisterDragHover = $rootScope.$on("ANGULAR_HOVER", function (e, channel) {
if (isDragChannelAccepted(channel, dropChannel)) { if (isDragChannelAccepted(channel, dropChannel)) {
element.removeClass(dragHoverClass); element.removeClass(dragHoverClass);
} }
}); });
scope.$on('$destroy', function () {
deregisterDragStart();
deregisterDragEnd();
deregisterDragHover();
});
attr.$observe('dropChannel', function (value) { attr.$observe('dropChannel', function (value) {
if (value) { if (value) {
dropChannel = value; dropChannel = value;
@ -198,4 +278,61 @@ angular.module("ngDragDrop",[])
}; };
} }
])
.constant("$dragImageConfig", {
height: 20,
width: 200,
padding: 10,
font: 'bold 11px Arial',
fontColor: '#eee8d5',
backgroundColor: '#93a1a1',
xOffset: 0,
yOffset: 0
})
.service("$dragImage", [
'$dragImageConfig',
function (defaultConfig) {
var ELLIPSIS = '…';
function fitString(canvas, text, config) {
var width = canvas.measureText(text).width;
if (width < config.width) {
return text;
}
while (width + config.padding > config.width) {
text = text.substring(0, text.length - 1);
width = canvas.measureText(text + ELLIPSIS).width;
}
return text + ELLIPSIS;
};
this.generate = function (text, options) {
var config = angular.extend({}, defaultConfig, options || {});
var el = document.createElement('canvas');
el.height = config.height;
el.width = config.width;
var canvas = el.getContext('2d');
canvas.fillStyle = config.backgroundColor;
canvas.fillRect(0, 0, config.width, config.height);
canvas.font = config.font;
canvas.fillStyle = config.fontColor;
var title = fitString(canvas, text, config);
canvas.fillText(title, 4, config.padding + 4);
var image = new Image();
image.src = el.toDataURL();
return {
image: image,
xOffset: config.xOffset,
yOffset: config.yOffset
};
}
}
]); ]);
}());