mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tech: removed jquery-ui and jquiery-ui-angular-drag-drop, replaced with native drag drop for angular, saved ~50kb in js libs, much cleaner & simpler usage, Also changed some behavior for drag drop, now panels are replaced when droped on (switch places), Closes #920
This commit is contained in:
parent
ce46ca2f39
commit
7463f91878
@ -29,7 +29,6 @@ require.config({
|
||||
bootstrap: '../vendor/bootstrap/bootstrap',
|
||||
|
||||
jquery: '../vendor/jquery/jquery-2.1.1.min',
|
||||
'jquery-ui': '../vendor/jquery/jquery-ui-1.10.3',
|
||||
|
||||
'extend-jquery': 'components/extend-jquery',
|
||||
|
||||
@ -76,7 +75,6 @@ require.config({
|
||||
|
||||
// simple dependency declaration
|
||||
//
|
||||
'jquery-ui': ['jquery'],
|
||||
'jquery.flot': ['jquery'],
|
||||
'jquery.flot.pie': ['jquery', 'jquery.flot'],
|
||||
'jquery.flot.events': ['jquery', 'jquery.flot'],
|
||||
@ -86,7 +84,7 @@ require.config({
|
||||
'jquery.flot.time': ['jquery', 'jquery.flot'],
|
||||
'jquery.flot.crosshair':['jquery', 'jquery.flot'],
|
||||
'angular-cookies': ['angular'],
|
||||
'angular-dragdrop': ['jquery','jquery-ui','angular'],
|
||||
'angular-dragdrop': ['jquery', 'angular'],
|
||||
'angular-loader': ['angular'],
|
||||
'angular-mocks': ['angular'],
|
||||
'angular-resource': ['angular'],
|
||||
|
@ -18,7 +18,6 @@ function (angular, $, config, _) {
|
||||
templateValuesSrv,
|
||||
dashboardSrv,
|
||||
dashboardViewStateSrv,
|
||||
panelMoveSrv,
|
||||
$timeout) {
|
||||
|
||||
$scope.editor = { index: 0 };
|
||||
@ -51,7 +50,6 @@ function (angular, $, config, _) {
|
||||
// init services
|
||||
timeSrv.init($scope.dashboard);
|
||||
templateValuesSrv.init($scope.dashboard, $scope.dashboardViewState);
|
||||
panelMoveSrv.init($scope.dashboard, $scope);
|
||||
|
||||
$scope.checkFeatureToggles();
|
||||
dashboardKeybindings.shortcuts($scope);
|
||||
@ -128,5 +126,24 @@ function (angular, $, config, _) {
|
||||
return $scope.editorTabs;
|
||||
};
|
||||
|
||||
$scope.onDrop = function(panelId, row, dropTarget) {
|
||||
var info = $scope.dashboard.getPanelInfoById(panelId);
|
||||
if (dropTarget) {
|
||||
var dropInfo = $scope.dashboard.getPanelInfoById(dropTarget.id);
|
||||
dropInfo.row.panels[dropInfo.index] = info.panel;
|
||||
info.row.panels[info.index] = dropTarget;
|
||||
var dragSpan = info.panel.span;
|
||||
info.panel.span = dropTarget.span;
|
||||
dropTarget.span = dragSpan;
|
||||
}
|
||||
else {
|
||||
info.row.panels.splice(info.index, 1);
|
||||
info.panel.span = 12 - $scope.dashboard.rowSpan(row);
|
||||
row.panels.push(info.panel);
|
||||
}
|
||||
|
||||
$rootScope.$broadcast('render');
|
||||
};
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -145,13 +145,18 @@ function (angular, app, _) {
|
||||
|
||||
module.directive('panelDropZone', function() {
|
||||
return function(scope, element) {
|
||||
scope.$watch('dashboard.$$panelDragging', function(newVal) {
|
||||
if (newVal && scope.dashboard.rowSpan(scope.row) < 10) {
|
||||
scope.$on("ANGULAR_DRAG_START", function() {
|
||||
var dropZoneSpan = 12 - scope.dashboard.rowSpan(scope.row);
|
||||
|
||||
if (dropZoneSpan > 0) {
|
||||
element.find('.panel-container').css('height', scope.row.height);
|
||||
element[0].style.width = ((dropZoneSpan / 1.2) * 10) + '%';
|
||||
element.show();
|
||||
}
|
||||
else {
|
||||
element.hide();
|
||||
}
|
||||
});
|
||||
|
||||
scope.$on("ANGULAR_DRAG_END", function() {
|
||||
element.hide();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ function (angular, $) {
|
||||
'<i class="icon-spinner icon-spin icon-large"></i>' +
|
||||
'</span>' +
|
||||
|
||||
'<div class="panel-title-container" panel-menu></div>' +
|
||||
'<div class="panel-title-container drag-handle" panel-menu></div>' +
|
||||
'</div>'+
|
||||
'</div>';
|
||||
|
||||
|
@ -9,15 +9,7 @@ function (angular, $, _) {
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('panelMenu', function($compile) {
|
||||
var linkTemplate = '<a class="panel-title">{{panel.title | interpolateTemplateVars}}</a>';
|
||||
var moveAttributes = ' data-drag=true data-jqyoui-options="kbnJqUiDraggableOptions"'+
|
||||
' jqyoui-draggable="{'+
|
||||
'animate:false,'+
|
||||
'mutate:false,'+
|
||||
'index:{{$index}},'+
|
||||
'onStart:\'panelMoveStart\','+
|
||||
'onStop:\'panelMoveStop\''+
|
||||
'}" ng-model="panel" ';
|
||||
var linkTemplate = '<a class="panel-title drag-handle">{{panel.title | interpolateTemplateVars}}</a>';
|
||||
|
||||
function createMenuTemplate($scope) {
|
||||
var template = '<div class="panel-menu small">';
|
||||
@ -26,7 +18,6 @@ function (angular, $, _) {
|
||||
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(-1)"><i class="icon-minus"></i></a>';
|
||||
template += '<a class="panel-menu-icon pull-left" ng-click="updateColumnSpan(1)"><i class="icon-plus"></i></a>';
|
||||
template += '<a class="panel-menu-icon pull-right" ng-click="remove_panel_from_row(row, panel)"><i class="icon-remove"></i></a>';
|
||||
template += '<a class="panel-menu-icon pull-right" ' + moveAttributes + '><i class="icon-move"></i></a>';
|
||||
template += '<div class="clearfix"></div>';
|
||||
template += '</div>';
|
||||
|
||||
|
@ -77,29 +77,25 @@
|
||||
<div class="panels-wrapper" ng-if="!row.collapse">
|
||||
<div class="row-text pointer" ng-click="toggle_row(row)" ng-if="row.showTitle" ng-bind="row.title">
|
||||
</div>
|
||||
<div class="panel-menu-container" data-menu-container>
|
||||
<!-- <a class="pointer"><i class="icon-eye-open"></i> <span>view</span></a> -->
|
||||
<!-- <a class="pointer"><i class="icon-cog"></i> <span>edit</span></a> -->
|
||||
<!-- <a class="pointer"><i class="icon-resize-horizontal"></i> <span>span</span></a> -->
|
||||
<!-- <a class="pointer"><i class="icon-copy"></i> <span>duplicate</span></a> -->
|
||||
<!-- <a class="pointer"><i class="icon-share"></i> <span>share</span></a> -->
|
||||
<!-- <a class="pointer"><i class="icon-remove"></i> <span>remove</span></a> -->
|
||||
</div>
|
||||
|
||||
<!-- Panels -->
|
||||
<div ng-repeat="(name, panel) in row.panels"
|
||||
class="panel nospace"
|
||||
style="position:relative"
|
||||
data-drop="true"
|
||||
panel-width
|
||||
ng-model="panel"
|
||||
data-jqyoui-options
|
||||
jqyoui-droppable="{index:$index,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}"
|
||||
ng-class="{'dragInProgress':dashboard.$$panelDragging}">
|
||||
class="panel"
|
||||
ui-draggable="true" drag="panel.id"
|
||||
ui-on-Drop="onDrop($data, row, panel)"
|
||||
drag-handle-class="drag-handle" panel-width ng-model="panel">
|
||||
|
||||
<grafana-panel type="panel.type" ng-cloak></grafana-panel>
|
||||
</div>
|
||||
|
||||
<div panel-drop-zone class="panel dragInProgress" style="margin:5px;width:30%;background:rgba(100,100,100,0.50)" ng-style="{height:row.height}" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:row.panels.length,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver',onOut:'panelMoveOut'}">
|
||||
<div panel-drop-zone class="panel panel-drop-zone"
|
||||
ui-on-drop="onDrop($data, row)"
|
||||
data-drop="true">
|
||||
<div class="panel-container" style="background: transparent">
|
||||
<div style="text-align: center">
|
||||
<em>Drop here</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
@ -7,7 +7,6 @@ define([
|
||||
'./templateValuesSrv',
|
||||
'./panelSrv',
|
||||
'./timer',
|
||||
'./panelMove',
|
||||
'./keyboardManager',
|
||||
'./annotationsSrv',
|
||||
'./playlistSrv',
|
||||
|
@ -91,6 +91,21 @@ function (angular, $, kbn, _, moment) {
|
||||
row.panels.push(panel);
|
||||
};
|
||||
|
||||
p.getPanelInfoById = function(panelId) {
|
||||
var result = {};
|
||||
_.each(this.rows, function(row) {
|
||||
_.each(row.panels, function(panel, index) {
|
||||
if (panel.id === panelId) {
|
||||
result.panel = panel;
|
||||
result.row = row;
|
||||
result.index = index;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
p.duplicatePanel = function(panel, row) {
|
||||
var rowIndex = _.indexOf(this.rows, row);
|
||||
var newPanel = angular.copy(panel);
|
||||
|
@ -1,85 +0,0 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash'
|
||||
],
|
||||
function (angular, _) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.services');
|
||||
|
||||
module.service('panelMoveSrv', function($rootScope) {
|
||||
|
||||
function PanelMoveSrv(dashboard) {
|
||||
this.dashboard = dashboard;
|
||||
_.bindAll(this, 'onStart', 'onOver', 'onOut', 'onDrop', 'onStop', 'cleanup');
|
||||
}
|
||||
|
||||
var p = PanelMoveSrv.prototype;
|
||||
|
||||
/* each of these can take event,ui,data parameters */
|
||||
p.onStart = function() {
|
||||
this.dashboard.$$panelDragging = true;
|
||||
$rootScope.$apply();
|
||||
};
|
||||
|
||||
p.onOver = function() {
|
||||
$rootScope.$apply();
|
||||
};
|
||||
|
||||
p.onOut = function() {
|
||||
$rootScope.$apply();
|
||||
};
|
||||
|
||||
/*
|
||||
Use our own drop logic. the $parent.$parent this is ugly.
|
||||
*/
|
||||
p.onDrop = function(event,ui,data) {
|
||||
var
|
||||
dragRow = data.draggableScope.$parent.$parent.row.panels,
|
||||
dropRow = data.droppableScope.$parent.$parent.row.panels,
|
||||
dragIndex = data.dragSettings.index,
|
||||
dropIndex = data.dropSettings.index;
|
||||
|
||||
// Remove panel from source row
|
||||
dragRow.splice(dragIndex,1);
|
||||
|
||||
// Add to destination row
|
||||
if (!_.isUndefined(dropRow)) {
|
||||
dropRow.splice(dropIndex,0,data.dragItem);
|
||||
}
|
||||
|
||||
this.dashboard.$$panelDragging = false;
|
||||
// Cleanup nulls/undefined left behind
|
||||
this.cleanup();
|
||||
$rootScope.$apply();
|
||||
$rootScope.$broadcast('render');
|
||||
};
|
||||
|
||||
p.onStop = function() {
|
||||
this.dashboard.$$panelDragging = false;
|
||||
this.cleanup();
|
||||
$rootScope.$apply();
|
||||
};
|
||||
|
||||
p.cleanup = function () {
|
||||
_.each(this.dashboard.rows, function(row) {
|
||||
row.panels = _.without(row.panels,{});
|
||||
row.panels = _.compact(row.panels);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: function(dashboard, scope) {
|
||||
var panelMove = new PanelMoveSrv(dashboard);
|
||||
|
||||
scope.panelMoveDrop = panelMove.onDrop;
|
||||
scope.panelMoveStart = panelMove.onStart;
|
||||
scope.panelMoveStop = panelMove.onStop;
|
||||
scope.panelMoveOver = panelMove.onOver;
|
||||
scope.panelMoveOut = panelMove.onOut;
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -231,10 +231,6 @@ form input.ng-invalid {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.dragInProgress .panel-container {
|
||||
border: 3px solid rgba(100,100,100,0.50);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: @linkColor;
|
||||
cursor: pointer;
|
||||
|
@ -2,6 +2,7 @@
|
||||
display: inline-block;
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.panel-container {
|
||||
@ -98,3 +99,16 @@
|
||||
.panel-highlight {
|
||||
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(82,168,236, 0.8)");
|
||||
}
|
||||
|
||||
.on-drag-hover {
|
||||
.panel-container {
|
||||
.box-shadow(~"inset 0 1px 1px rgba(0,0,0,.075), 0 0 5px rgba(82,168,236, 0.8)");
|
||||
}
|
||||
}
|
||||
|
||||
.panel-drop-zone {
|
||||
display: none;
|
||||
.panel-container {
|
||||
border: 1px solid @grayDark;
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,6 @@ require.config({
|
||||
bootstrap: '../vendor/bootstrap/bootstrap',
|
||||
'bootstrap-tagsinput': '../vendor/tagsinput/bootstrap-tagsinput',
|
||||
|
||||
'jquery-ui': '../vendor/jquery/jquery-ui-1.10.3',
|
||||
|
||||
'extend-jquery': 'components/extend-jquery',
|
||||
|
||||
'jquery.flot': '../vendor/jquery/jquery.flot',
|
||||
@ -82,7 +80,7 @@ require.config({
|
||||
|
||||
'angular-route': ['angular'],
|
||||
'angular-cookies': ['angular'],
|
||||
'angular-dragdrop': ['jquery','jquery-ui','angular'],
|
||||
'angular-dragdrop': ['jquery', 'angular'],
|
||||
'angular-loader': ['angular'],
|
||||
'angular-mocks': ['angular'],
|
||||
'angular-resource': ['angular'],
|
||||
|
643
src/vendor/angular/angular-dragdrop.js
vendored
643
src/vendor/angular/angular-dragdrop.js
vendored
@ -1,338 +1,341 @@
|
||||
/**
|
||||
* 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.
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: Ganaraj.Pr
|
||||
* Date: 11/10/13
|
||||
* Time: 11:27
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementing Drag and Drop functionality in AngularJS is easier than ever.
|
||||
* Demo: http://codef0rmer.github.com/angular-dragdrop/
|
||||
*
|
||||
* @version 1.0.4
|
||||
*
|
||||
* (c) 2013 Amit Gharat a.k.a codef0rmer <amit.2006.it@gmail.com> - amitgharat.wordpress.com
|
||||
*/
|
||||
(function(){
|
||||
|
||||
/**
|
||||
* This has been modified from the default angular-draganddrop to provide the original
|
||||
* model and some other stuff as the 'data' arguement to callEventCallback
|
||||
*/
|
||||
function isDnDsSupported(){
|
||||
return 'draggable' in document.createElement("span");
|
||||
}
|
||||
|
||||
(function (window, angular, undefined) {
|
||||
'use strict';
|
||||
if(!isDnDsSupported()){
|
||||
return;
|
||||
}
|
||||
|
||||
var jqyoui = angular.module('ngDragDrop', []).service('ngDragDropService', ['$timeout', '$parse', function($timeout, $parse) {
|
||||
this.callEventCallback = function (scope, callbackName, event, ui, data) {
|
||||
if (!callbackName) {
|
||||
return;
|
||||
}
|
||||
var args = [event, ui, data];
|
||||
var match = callbackName.match(/^(.+)\((.+)\)$/);
|
||||
if (match !== null) {
|
||||
callbackName = match[1];
|
||||
var values = eval('[' + match[0].replace(/^(.+)\(/, '').replace(/\)/, '') + ']');
|
||||
args.push.apply(args, values);
|
||||
}
|
||||
if(scope[callbackName]) {
|
||||
scope[callbackName].apply(scope, args);
|
||||
}
|
||||
};
|
||||
if (window.jQuery && (-1 == window.jQuery.event.props.indexOf("dataTransfer"))) {
|
||||
window.jQuery.event.props.push("dataTransfer");
|
||||
}
|
||||
|
||||
this.invokeDrop = function ($draggable, $droppable, event, ui) {
|
||||
var dragModel = '',
|
||||
dropModel = '',
|
||||
dragSettings = {},
|
||||
dropSettings = {},
|
||||
jqyoui_pos = null,
|
||||
dragItem = {},
|
||||
dropItem = {},
|
||||
dragModelValue,
|
||||
dropModelValue,
|
||||
$droppableDraggable = null,
|
||||
droppableScope = $droppable.scope(),
|
||||
draggableScope = $draggable.scope(),
|
||||
data = {};
|
||||
var currentData;
|
||||
|
||||
dragModel = $draggable.ngattr('ng-model');
|
||||
dropModel = $droppable.ngattr('ng-model');
|
||||
dragModelValue = draggableScope.$eval(dragModel);
|
||||
dropModelValue = droppableScope.$eval(dropModel);
|
||||
angular.module("ngDragDrop",[])
|
||||
.directive("uiDraggable", [
|
||||
'$parse',
|
||||
'$rootScope',
|
||||
'$dragImage',
|
||||
function ($parse, $rootScope, $dragImage) {
|
||||
return function (scope, element, attrs) {
|
||||
var dragData = "",
|
||||
isDragHandleUsed = false,
|
||||
dragHandleClass,
|
||||
draggingClass = attrs.draggingClass || "on-dragging",
|
||||
dragTarget;
|
||||
|
||||
$droppableDraggable = $droppable.find('[jqyoui-draggable]:last');
|
||||
dropSettings = droppableScope.$eval($droppable.attr('jqyoui-droppable')) || [];
|
||||
dragSettings = draggableScope.$eval($draggable.attr('jqyoui-draggable')) || [];
|
||||
element.attr("draggable", false);
|
||||
|
||||
// Helps pick up the right item
|
||||
dragSettings.index = this.fixIndex(draggableScope, dragSettings, dragModelValue);
|
||||
dropSettings.index = this.fixIndex(droppableScope, dropSettings, dropModelValue);
|
||||
attrs.$observe("uiDraggable", function (newValue) {
|
||||
if(newValue){
|
||||
element.attr("draggable", newValue);
|
||||
}
|
||||
else{
|
||||
element.removeAttr("draggable");
|
||||
}
|
||||
|
||||
jqyoui_pos = angular.isArray(dragModelValue) ? dragSettings.index : null;
|
||||
dragItem = angular.isArray(dragModelValue) ? dragModelValue[jqyoui_pos] : dragModelValue;
|
||||
});
|
||||
|
||||
if (angular.isArray(dropModelValue) && dropSettings && dropSettings.index !== undefined) {
|
||||
dropItem = dropModelValue[dropSettings.index];
|
||||
} else if (!angular.isArray(dropModelValue)) {
|
||||
dropItem = dropModelValue;
|
||||
} else {
|
||||
dropItem = {};
|
||||
}
|
||||
|
||||
data = {
|
||||
dragModel: dragModel,
|
||||
dropModel: dropModel,
|
||||
dragSettings: dragSettings,
|
||||
dropSettings: dropSettings,
|
||||
jqyoui_pos: jqyoui_pos,
|
||||
dragItem: dragItem,
|
||||
dropItem: dropItem,
|
||||
dragModelValue: dragModelValue,
|
||||
dropModelValue: dropModelValue,
|
||||
droppableScope: $droppable.scope(),
|
||||
draggableScope: $draggable.scope()
|
||||
};
|
||||
|
||||
|
||||
if (dragSettings.animate === true) {
|
||||
|
||||
this.move($draggable, $droppableDraggable.length > 0 ? $droppableDraggable : $droppable, null, 'fast', dropSettings, null);
|
||||
this.move($droppableDraggable.length > 0 && !dropSettings.multiple ? $droppableDraggable : [], $draggable.parent('[jqyoui-droppable]'), jqyoui.startXY, 'fast', dropSettings, function() {
|
||||
$timeout(function() {
|
||||
// Do not move this into move() to avoid flickering issue
|
||||
$draggable.css({'position': 'relative', 'left': '', 'top': ''});
|
||||
$droppableDraggable.css({'position': 'relative', 'left': '', 'top': ''});
|
||||
|
||||
if(dragSettings.mutate !== false) {
|
||||
this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);
|
||||
}
|
||||
|
||||
if(dropSettings.mutate !== false) {
|
||||
this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);
|
||||
}
|
||||
|
||||
this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui, data);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
} else {
|
||||
$timeout(function() {
|
||||
|
||||
if(dragSettings.mutate !== false) {
|
||||
this.mutateDraggable(draggableScope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable);
|
||||
}
|
||||
|
||||
if(dropSettings.mutate !== false) {
|
||||
this.mutateDroppable(droppableScope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos);
|
||||
}
|
||||
|
||||
this.callEventCallback(droppableScope, dropSettings.onDrop, event, ui, data);
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
this.move = function($fromEl, $toEl, toPos, duration, dropSettings, callback) {
|
||||
if ($fromEl.length === 0) {
|
||||
if (callback) {
|
||||
window.setTimeout(function() {
|
||||
callback();
|
||||
}, 300);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var zIndex = 9999,
|
||||
fromPos = $fromEl.offset(),
|
||||
wasVisible = $toEl && $toEl.is(':visible');
|
||||
|
||||
if (toPos === null && $toEl.length > 0) {
|
||||
if ($toEl.attr('jqyoui-draggable') !== undefined && $toEl.ngattr('ng-model') !== undefined && $toEl.is(':visible') && dropSettings && dropSettings.multiple) {
|
||||
toPos = $toEl.offset();
|
||||
if (dropSettings.stack === false) {
|
||||
toPos.left+= $toEl.outerWidth(true);
|
||||
} else {
|
||||
toPos.top+= $toEl.outerHeight(true);
|
||||
}
|
||||
} else {
|
||||
toPos = $toEl.css({'visibility': 'hidden', 'display': 'block'}).offset();
|
||||
$toEl.css({'visibility': '','display': wasVisible ? '' : 'none'});
|
||||
}
|
||||
}
|
||||
|
||||
$fromEl.css({'position': 'absolute', 'z-index': zIndex})
|
||||
.css(fromPos)
|
||||
.animate(toPos, duration, function() {
|
||||
if (callback) callback();
|
||||
});
|
||||
};
|
||||
|
||||
this.mutateDroppable = function(scope, dropSettings, dragSettings, dropModel, dragItem, jqyoui_pos) {
|
||||
var dropModelValue = scope.$eval(dropModel);
|
||||
|
||||
scope.__dragItem = dragItem;
|
||||
|
||||
if (angular.isArray(dropModelValue)) {
|
||||
if (dropSettings && dropSettings.index >= 0) {
|
||||
dropModelValue[dropSettings.index] = dragItem;
|
||||
} else {
|
||||
dropModelValue.push(dragItem);
|
||||
}
|
||||
if (dragSettings && dragSettings.placeholder === true) {
|
||||
dropModelValue[dropModelValue.length - 1]['jqyoui_pos'] = jqyoui_pos;
|
||||
}
|
||||
} else {
|
||||
$parse(dropModel + ' = __dragItem')(scope);
|
||||
if (dragSettings && dragSettings.placeholder === true) {
|
||||
dropModelValue['jqyoui_pos'] = jqyoui_pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.mutateDraggable = function(scope, dropSettings, dragSettings, dragModel, dropModel, dropItem, $draggable) {
|
||||
var isEmpty = angular.equals(angular.copy(dropItem), {}),
|
||||
dragModelValue = scope.$eval(dragModel);
|
||||
|
||||
scope.__dropItem = dropItem;
|
||||
|
||||
if (dragSettings && dragSettings.placeholder) {
|
||||
if (dragSettings.placeholder != 'keep'){
|
||||
if (angular.isArray(dragModelValue) && dragSettings.index !== undefined) {
|
||||
dragModelValue[dragSettings.index] = dropItem;
|
||||
} else {
|
||||
$parse(dragModel + ' = __dropItem')(scope);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (angular.isArray(dragModelValue)) {
|
||||
if (isEmpty) {
|
||||
if (dragSettings && ( dragSettings.placeholder !== true && dragSettings.placeholder !== 'keep' )) {
|
||||
dragModelValue.splice(dragSettings.index, 1);
|
||||
}
|
||||
} else {
|
||||
dragModelValue[dragSettings.index] = dropItem;
|
||||
}
|
||||
} else {
|
||||
// Fix: LIST(object) to LIST(array) - model does not get updated using just scope[dragModel] = {...}
|
||||
// P.S.: Could not figure out why it happened
|
||||
$parse(dragModel + ' = __dropItem')(scope);
|
||||
if (scope.$parent) {
|
||||
$parse(dragModel + ' = __dropItem')(scope.$parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$draggable.css({'z-index': '', 'left': '', 'top': ''});
|
||||
};
|
||||
|
||||
this.fixIndex = function(scope, settings, modelValue) {
|
||||
if (settings.applyFilter && angular.isArray(modelValue) && modelValue.length > 0) {
|
||||
var dragModelValueFiltered = scope[settings.applyFilter](),
|
||||
lookup = dragModelValueFiltered[settings.index],
|
||||
actualIndex = undefined;
|
||||
|
||||
modelValue.forEach(function(item, i) {
|
||||
if (angular.equals(item, lookup)) {
|
||||
actualIndex = i;
|
||||
}
|
||||
});
|
||||
|
||||
return actualIndex;
|
||||
}
|
||||
|
||||
return settings.index;
|
||||
};
|
||||
}]).directive('jqyouiDraggable', ['ngDragDropService', function(ngDragDropService) {
|
||||
return {
|
||||
require: '?jqyouiDroppable',
|
||||
restrict: 'A',
|
||||
link: function(scope, element, attrs) {
|
||||
// grafana change, remove watcher after first evaluation
|
||||
var dragSettings, zIndex, removeWatcher;
|
||||
var updateDraggable = function(newValue, oldValue) {
|
||||
if (newValue) {
|
||||
removeWatcher();
|
||||
dragSettings = scope.$eval(element.attr('jqyoui-draggable')) || [];
|
||||
element
|
||||
.draggable({disabled: false})
|
||||
.draggable(scope.$eval(attrs.jqyouiOptions) || {})
|
||||
.draggable({
|
||||
start: function(event, ui) {
|
||||
zIndex = angular.element(this).css('z-index');
|
||||
angular.element(this).css('z-index', 99999);
|
||||
jqyoui.startXY = angular.element(this).offset();
|
||||
ngDragDropService.callEventCallback(scope, dragSettings.onStart, event, ui);
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
angular.element(this).css('z-index', zIndex);
|
||||
ngDragDropService.callEventCallback(scope, dragSettings.onStop, event, ui);
|
||||
},
|
||||
drag: function(event, ui) {
|
||||
ngDragDropService.callEventCallback(scope, dragSettings.onDrag, event, ui);
|
||||
if (attrs.drag) {
|
||||
scope.$watch(attrs.drag, function (newValue) {
|
||||
dragData = newValue || "";
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
element.draggable({disabled: true});
|
||||
}
|
||||
};
|
||||
removeWatcher = scope.$watch(function() { return scope.$eval(attrs.drag); }, updateDraggable);
|
||||
updateDraggable();
|
||||
}
|
||||
};
|
||||
}]).directive('jqyouiDroppable', ['ngDragDropService', function(ngDragDropService) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority: 1,
|
||||
link: function(scope, element, attrs) {
|
||||
// grafana change, remove watcher after first evaluation
|
||||
var removeWatcher;
|
||||
var updateDroppable = function(newValue, oldValue) {
|
||||
if (newValue) {
|
||||
removeWatcher();
|
||||
element
|
||||
.droppable({disabled: false})
|
||||
.droppable(scope.$eval(attrs.jqyouiOptions) || {})
|
||||
.droppable({
|
||||
over: function(event, ui) {
|
||||
var dropSettings = scope.$eval(angular.element(this).attr('jqyoui-droppable')) || [];
|
||||
ngDragDropService.callEventCallback(scope, dropSettings.onOver, event, ui);
|
||||
},
|
||||
out: function(event, ui) {
|
||||
var dropSettings = scope.$eval(angular.element(this).attr('jqyoui-droppable')) || [];
|
||||
ngDragDropService.callEventCallback(scope, dropSettings.onOut, event, ui);
|
||||
},
|
||||
drop: function(event, ui) {
|
||||
if (angular.element(ui.draggable).ngattr('ng-model') && attrs.ngModel) {
|
||||
ngDragDropService.invokeDrop(angular.element(ui.draggable), angular.element(this), event, ui);
|
||||
} else {
|
||||
ngDragDropService.callEventCallback(scope, (scope.$eval(angular.element(this).attr('jqyoui-droppable')) || []).onDrop, event, ui);
|
||||
|
||||
if (angular.isString(attrs.dragHandleClass)) {
|
||||
isDragHandleUsed = true;
|
||||
dragHandleClass = attrs.dragHandleClass.trim() || "drag-handle";
|
||||
|
||||
element.bind("mousedown", function (e) {
|
||||
dragTarget = e.target;
|
||||
});
|
||||
}
|
||||
|
||||
function dragendHandler(e) {
|
||||
setTimeout(function() {
|
||||
element.unbind('$destroy', dragendHandler);
|
||||
}, 0);
|
||||
var sendChannel = attrs.dragChannel || "defaultchannel";
|
||||
$rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel);
|
||||
if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") {
|
||||
if (attrs.onDropSuccess) {
|
||||
var fn = $parse(attrs.onDropSuccess);
|
||||
scope.$apply(function () {
|
||||
fn(scope, {$event: e});
|
||||
});
|
||||
} else {
|
||||
if (attrs.onDropFailure) {
|
||||
var fn = $parse(attrs.onDropFailure);
|
||||
scope.$apply(function () {
|
||||
fn(scope, {$event: e});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
element.removeClass(draggingClass);
|
||||
}
|
||||
|
||||
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.addClass(draggingClass);
|
||||
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();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
])
|
||||
.directive("uiOnDrop", [
|
||||
'$parse',
|
||||
'$rootScope',
|
||||
function ($parse, $rootScope) {
|
||||
return function (scope, element, attr) {
|
||||
var dragging = 0; //Ref. http://stackoverflow.com/a/10906204
|
||||
var dropChannel = attr.dropChannel || "defaultchannel" ;
|
||||
var dragChannel = "";
|
||||
var dragEnterClass = attr.dragEnterClass || "on-drag-enter";
|
||||
var dragHoverClass = attr.dragHoverClass || "on-drag-hover";
|
||||
|
||||
function onDragOver(e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault(); // Necessary. Allows us to drop.
|
||||
}
|
||||
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
e.dataTransfer.dropEffect = e.shiftKey ? 'copy' : 'move';
|
||||
return false;
|
||||
}
|
||||
|
||||
function onDragLeave(e) {
|
||||
dragging--;
|
||||
if (dragging == 0) {
|
||||
element.removeClass(dragHoverClass);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
element.droppable({disabled: true});
|
||||
}
|
||||
};
|
||||
|
||||
removeWatcher = scope.$watch(function() { return scope.$eval(attrs.drop); }, updateDroppable);
|
||||
updateDroppable();
|
||||
}
|
||||
};
|
||||
}]);
|
||||
function onDragEnter(e) {
|
||||
dragging++;
|
||||
$rootScope.$broadcast("ANGULAR_HOVER", dragChannel);
|
||||
element.addClass(dragHoverClass);
|
||||
}
|
||||
|
||||
$.fn.ngattr = function(name, value) {
|
||||
var element = angular.element(this).get(0);
|
||||
function onDrop(e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault(); // Necessary. Allows us to drop.
|
||||
}
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation(); // Necessary. Allows us to drop.
|
||||
}
|
||||
|
||||
return element.getAttribute(name) || element.getAttribute('data-' + name);
|
||||
};
|
||||
})(window, window.angular);
|
||||
var sendData = e.dataTransfer.getData("Text");
|
||||
sendData = angular.fromJson(sendData);
|
||||
|
||||
var fn = $parse(attr.uiOnDrop);
|
||||
scope.$apply(function () {
|
||||
fn(scope, {$data: sendData.data, $event: e, $channel: sendData.channel});
|
||||
});
|
||||
element.removeClass(dragEnterClass);
|
||||
dragging = 0;
|
||||
}
|
||||
|
||||
function isDragChannelAccepted(dragChannel, dropChannel) {
|
||||
if (dropChannel === "*") {
|
||||
return true;
|
||||
}
|
||||
|
||||
var channelMatchPattern = new RegExp("(\\s|[,])+(" + dragChannel + ")(\\s|[,])+", "i");
|
||||
|
||||
return channelMatchPattern.test("," + dropChannel + ",");
|
||||
}
|
||||
|
||||
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;
|
||||
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("dragenter", onDragEnter);
|
||||
element.bind("dragleave", onDragLeave);
|
||||
|
||||
element.bind("drop", onDrop);
|
||||
element.addClass(dragEnterClass);
|
||||
}
|
||||
else {
|
||||
element.bind("dragover", preventNativeDnD);
|
||||
element.bind("dragenter", preventNativeDnD);
|
||||
element.bind("dragleave", preventNativeDnD);
|
||||
element.bind("drop", preventNativeDnD);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
var deregisterDragEnd = $rootScope.$on("ANGULAR_DRAG_END", function (e, channel) {
|
||||
dragChannel = "";
|
||||
if (isDragChannelAccepted(channel, dropChannel)) {
|
||||
|
||||
element.unbind("dragover", onDragOver);
|
||||
element.unbind("dragenter", onDragEnter);
|
||||
element.unbind("dragleave", onDragLeave);
|
||||
|
||||
element.unbind("drop", onDrop);
|
||||
element.removeClass(dragHoverClass);
|
||||
element.removeClass(dragEnterClass);
|
||||
}
|
||||
|
||||
element.unbind("dragover", preventNativeDnD);
|
||||
element.unbind("dragenter", preventNativeDnD);
|
||||
element.unbind("dragleave", preventNativeDnD);
|
||||
element.unbind("drop", preventNativeDnD);
|
||||
});
|
||||
|
||||
|
||||
var deregisterDragHover = $rootScope.$on("ANGULAR_HOVER", function (e, channel) {
|
||||
if (isDragChannelAccepted(channel, dropChannel)) {
|
||||
element.removeClass(dragHoverClass);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
scope.$on('$destroy', function () {
|
||||
deregisterDragStart();
|
||||
deregisterDragEnd();
|
||||
deregisterDragHover();
|
||||
});
|
||||
|
||||
|
||||
attr.$observe('dropChannel', function (value) {
|
||||
if (value) {
|
||||
dropChannel = value;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
])
|
||||
.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
|
||||
};
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
}());
|
||||
|
5253
src/vendor/jquery/jquery-ui-1.10.3.js
vendored
5253
src/vendor/jquery/jquery-ui-1.10.3.js
vendored
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user