Commit e9d33750 by Torkel Ödegaard Committed by Dan Cech

fix: graphite func editor fixes, this component is messy and ugly as hell

parent 1a6bf692
define([ define(['angular', 'lodash', 'jquery', 'rst2html', 'tether-drop'], function(angular, _, $, rst2html, Drop) {
'angular',
'lodash',
'jquery',
'rst2html',
'tether-drop',
],
function (angular, _, $, rst2html, Drop) {
'use strict'; 'use strict';
angular angular.module('grafana.directives').directive('graphiteAddFunc', function($compile) {
.module('grafana.directives') var inputTemplate =
.directive('graphiteAddFunc', function($compile) { '<input type="text"' + ' class="gf-form-input"' + ' spellcheck="false" style="display:none"></input>';
var inputTemplate = '<input type="text"'+
' class="gf-form-input"' + var buttonTemplate =
' spellcheck="false" style="display:none"></input>'; '<a class="gf-form-label query-part dropdown-toggle"' +
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
var buttonTemplate = '<a class="gf-form-label query-part dropdown-toggle"' + '<i class="fa fa-plus"></i></a>';
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
'<i class="fa fa-plus"></i></a>'; return {
link: function($scope, elem) {
return { var ctrl = $scope.ctrl;
link: function($scope, elem) {
var ctrl = $scope.ctrl; var $input = $(inputTemplate);
var $button = $(buttonTemplate);
var $input = $(inputTemplate);
var $button = $(buttonTemplate); $input.appendTo(elem);
$button.appendTo(elem);
$input.appendTo(elem);
$button.appendTo(elem); ctrl.datasource.getFuncDefs().then(function(funcDefs) {
var allFunctions = _.map(funcDefs, 'name').sort();
ctrl.datasource.getFuncDefs().then(function(funcDefs) {
var allFunctions = _.map(funcDefs, 'name').sort(); $scope.functionMenu = createFunctionDropDownMenu(funcDefs);
$scope.functionMenu = createFunctionDropDownMenu(funcDefs); $input.attr('data-provide', 'typeahead');
$input.typeahead({
source: allFunctions,
minLength: 1,
items: 10,
updater: function(value) {
var funcDef = ctrl.datasource.getFuncDef(value);
if (!funcDef) {
// try find close match
value = value.toLowerCase();
funcDef = _.find(allFunctions, function(funcName) {
return funcName.toLowerCase().indexOf(value) === 0;
});
$input.attr('data-provide', 'typeahead');
$input.typeahead({
source: allFunctions,
minLength: 1,
items: 10,
updater: function (value) {
var funcDef = ctrl.datasource.getFuncDef(value);
if (!funcDef) { if (!funcDef) {
// try find close match return;
value = value.toLowerCase();
funcDef = _.find(allFunctions, function(funcName) {
return funcName.toLowerCase().indexOf(value) === 0;
});
if (!funcDef) { return; }
} }
}
$scope.$apply(function() { $scope.$apply(function() {
ctrl.addFunction(funcDef); ctrl.addFunction(funcDef);
}); });
$input.trigger('blur'); $input.trigger('blur');
return ''; return '';
} },
});
$button.click(function() {
$button.hide();
$input.show();
$input.focus();
});
$input.keyup(function() {
elem.toggleClass('open', $input.val() === '');
});
$input.blur(function() {
// clicking the function dropdown menu wont
// work if you remove class at once
setTimeout(function() {
$input.val('');
$input.hide();
$button.show();
elem.removeClass('open');
}, 200);
});
$compile(elem.contents())($scope);
}); });
var drops = []; $button.click(function() {
$button.hide();
$(elem) $input.show();
.on('mouseenter', 'ul.dropdown-menu li', function () { $input.focus();
while (drops.length > 0) { });
drops.pop().remove();
}
var funcDef; $input.keyup(function() {
try { elem.toggleClass('open', $input.val() === '');
funcDef = ctrl.datasource.getFuncDef($('a', this).text()); });
} catch (e) {
// ignore
}
if (funcDef && funcDef.description) { $input.blur(function() {
var shortDesc = funcDef.description; // clicking the function dropdown menu wont
if (shortDesc.length > 500) { // work if you remove class at once
shortDesc = shortDesc.substring(0, 497) + '...'; setTimeout(function() {
} $input.val('');
$input.hide();
$button.show();
elem.removeClass('open');
}, 200);
});
var contentElement = document.createElement('div'); $compile(elem.contents())($scope);
contentElement.innerHTML = '<h4>' + funcDef.name + '</h4>' + rst2html(shortDesc); });
var drop = new Drop({ var drop;
target: this, var cleanUpDrop = function() {
content: contentElement, if (drop) {
classes: 'drop-popover', drop.destroy();
openOn: 'always', drop = null;
tetherOptions: { }
attachment: 'bottom left', };
targetAttachment: 'bottom right',
}, $(elem)
}); .on('mouseenter', 'ul.dropdown-menu li', function() {
cleanUpDrop();
var funcDef;
try {
funcDef = ctrl.datasource.getFuncDef($('a', this).text());
} catch (e) {
// ignore
}
if (funcDef && funcDef.description) {
var shortDesc = funcDef.description;
if (shortDesc.length > 500) {
shortDesc = shortDesc.substring(0, 497) + '...';
}
drops.push(drop); var contentElement = document.createElement('div');
contentElement.innerHTML = '<h4>' + funcDef.name + '</h4>' + rst2html(shortDesc);
drop = new Drop({
target: this,
content: contentElement,
classes: 'drop-popover',
openOn: 'always',
tetherOptions: {
attachment: 'bottom left',
targetAttachment: 'bottom right',
},
});
}
})
.on('mouseout', 'ul.dropdown-menu li', function() {
cleanUpDrop();
});
drop.open(); $scope.$on('$destroy', cleanUpDrop);
} },
}) };
.on('mouseout', 'ul.dropdown-menu li', function() { });
while (drops.length > 0) {
drops.pop().remove();
}
});
}
};
});
function createFunctionDropDownMenu(funcDefs) { function createFunctionDropDownMenu(funcDefs) {
var categories = {}; var categories = {};
...@@ -149,11 +142,14 @@ function (angular, _, $, rst2html, Drop) { ...@@ -149,11 +142,14 @@ function (angular, _, $, rst2html, Drop) {
}); });
}); });
return _.sortBy(_.map(categories, function(submenu, category) { return _.sortBy(
return { _.map(categories, function(submenu, category) {
text: category, return {
submenu: _.sortBy(submenu, 'text') text: category,
}; submenu: _.sortBy(submenu, 'text'),
}), 'text'); };
}),
'text'
);
} }
}); });
...@@ -32,6 +32,7 @@ function (angular, _, $, rst2html) { ...@@ -32,6 +32,7 @@ function (angular, _, $, rst2html) {
var func = $scope.func; var func = $scope.func;
var scheduledRelink = false; var scheduledRelink = false;
var paramCountAtLink = 0; var paramCountAtLink = 0;
var cancelBlur = null;
function clickFuncParam(paramIndex) { function clickFuncParam(paramIndex) {
/*jshint validthis:true */ /*jshint validthis:true */
...@@ -79,41 +80,54 @@ function (angular, _, $, rst2html) { ...@@ -79,41 +80,54 @@ function (angular, _, $, rst2html) {
return {}; return {};
} }
function inputBlur(paramIndex) { function switchToLink(inputElem, paramIndex) {
/*jshint validthis:true */ /*jshint validthis:true */
var $input = $(this); var $input = $(inputElem);
if ($input.data('typeahead') && $input.data('typeahead').shown) {
return; clearTimeout(cancelBlur);
} cancelBlur = null;
var $link = $input.prev(); var $link = $input.prev();
var $comma = $link.prev('.comma'); var $comma = $link.prev('.comma');
var newValue = $input.val(); var newValue = $input.val();
// remove optional empty params
if (newValue !== '' || paramDef(paramIndex).optional) { if (newValue !== '' || paramDef(paramIndex).optional) {
$link.html(templateSrv.highlightVariablesAsHtml(newValue));
func.updateParam(newValue, paramIndex); func.updateParam(newValue, paramIndex);
scheduledRelinkIfNeeded(); }
$scope.$apply(function() { $link.html(templateSrv.highlightVariablesAsHtml(newValue));
ctrl.targetChanged(); scheduledRelinkIfNeeded();
});
if ($link.hasClass('last') && newValue === '') { $scope.$apply(function() {
$comma.addClass('last'); ctrl.targetChanged();
} else { });
$link.removeClass('last');
} if ($link.hasClass('last') && newValue === '') {
$input.hide(); $comma.addClass('last');
$link.show(); } else {
$link.removeClass('last');
} }
$input.hide();
$link.show();
}
// this = input element
function inputBlur(paramIndex) {
/*jshint validthis:true */
var inputElem = this;
// happens long before the click event on the typeahead options
// need to have long delay because the blur
cancelBlur = setTimeout(function() {
switchToLink(inputElem, paramIndex);
}, 200);
} }
function inputKeyPress(paramIndex, e) { function inputKeyPress(paramIndex, e) {
/*jshint validthis:true */ /*jshint validthis:true */
if(e.which === 13) { if(e.which === 13) {
inputBlur.call(this, paramIndex); $(this).blur();
} }
} }
...@@ -135,9 +149,8 @@ function (angular, _, $, rst2html) { ...@@ -135,9 +149,8 @@ function (angular, _, $, rst2html) {
minLength: 0, minLength: 0,
items: 20, items: 20,
updater: function (value) { updater: function (value) {
setTimeout(function() { $input.val(value);
inputBlur.call($input[0], paramIndex); switchToLink($input[0], paramIndex);
}, 0);
return value; return value;
} }
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment