add_graphite_func.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. define([
  2. 'angular',
  3. 'lodash',
  4. 'jquery',
  5. 'rst2html',
  6. 'tether-drop',
  7. ],
  8. function (angular, _, $, rst2html, Drop) {
  9. 'use strict';
  10. angular
  11. .module('grafana.directives')
  12. .directive('graphiteAddFunc', function($compile) {
  13. var inputTemplate = '<input type="text"'+
  14. ' class="gf-form-input"' +
  15. ' spellcheck="false" style="display:none"></input>';
  16. var buttonTemplate = '<a class="gf-form-label query-part dropdown-toggle"' +
  17. ' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
  18. '<i class="fa fa-plus"></i></a>';
  19. return {
  20. link: function($scope, elem) {
  21. var ctrl = $scope.ctrl;
  22. var $input = $(inputTemplate);
  23. var $button = $(buttonTemplate);
  24. $input.appendTo(elem);
  25. $button.appendTo(elem);
  26. ctrl.datasource.getFuncDefs().then(function(funcDefs) {
  27. var allFunctions = _.map(funcDefs, 'name').sort();
  28. $scope.functionMenu = createFunctionDropDownMenu(funcDefs);
  29. $input.attr('data-provide', 'typeahead');
  30. $input.typeahead({
  31. source: allFunctions,
  32. minLength: 1,
  33. items: 10,
  34. updater: function (value) {
  35. var funcDef = ctrl.datasource.getFuncDef(value);
  36. if (!funcDef) {
  37. // try find close match
  38. value = value.toLowerCase();
  39. funcDef = _.find(allFunctions, function(funcName) {
  40. return funcName.toLowerCase().indexOf(value) === 0;
  41. });
  42. if (!funcDef) { return; }
  43. }
  44. $scope.$apply(function() {
  45. ctrl.addFunction(funcDef);
  46. });
  47. $input.trigger('blur');
  48. return '';
  49. }
  50. });
  51. $button.click(function() {
  52. $button.hide();
  53. $input.show();
  54. $input.focus();
  55. });
  56. $input.keyup(function() {
  57. elem.toggleClass('open', $input.val() === '');
  58. });
  59. $input.blur(function() {
  60. // clicking the function dropdown menu wont
  61. // work if you remove class at once
  62. setTimeout(function() {
  63. $input.val('');
  64. $input.hide();
  65. $button.show();
  66. elem.removeClass('open');
  67. }, 200);
  68. });
  69. $compile(elem.contents())($scope);
  70. });
  71. var drops = [];
  72. $(elem)
  73. .on('mouseenter', 'ul.dropdown-menu li', function () {
  74. while (drops.length > 0) {
  75. drops.pop().remove();
  76. }
  77. var funcDef;
  78. try {
  79. funcDef = ctrl.datasource.getFuncDef($('a', this).text());
  80. } catch (e) {
  81. // ignore
  82. }
  83. if (funcDef && funcDef.description) {
  84. var shortDesc = funcDef.description;
  85. if (shortDesc.length > 500) {
  86. shortDesc = shortDesc.substring(0, 497) + '...';
  87. }
  88. var contentElement = document.createElement('div');
  89. contentElement.innerHTML = '<h4>' + funcDef.name + '</h4>' + rst2html(shortDesc);
  90. var drop = new Drop({
  91. target: this,
  92. content: contentElement,
  93. classes: 'drop-popover',
  94. openOn: 'always',
  95. tetherOptions: {
  96. attachment: 'bottom left',
  97. targetAttachment: 'bottom right',
  98. },
  99. });
  100. drops.push(drop);
  101. drop.open();
  102. }
  103. })
  104. .on('mouseout', 'ul.dropdown-menu li', function() {
  105. while (drops.length > 0) {
  106. drops.pop().remove();
  107. }
  108. });
  109. }
  110. };
  111. });
  112. function createFunctionDropDownMenu(funcDefs) {
  113. var categories = {};
  114. _.forEach(funcDefs, function(funcDef) {
  115. if (!funcDef.category) {
  116. return;
  117. }
  118. if (!categories[funcDef.category]) {
  119. categories[funcDef.category] = [];
  120. }
  121. categories[funcDef.category].push({
  122. text: funcDef.name,
  123. click: "ctrl.addFunction('" + funcDef.name + "')",
  124. });
  125. });
  126. return _.sortBy(_.map(categories, function(submenu, category) {
  127. return {
  128. text: category,
  129. submenu: _.sortBy(submenu, 'text')
  130. };
  131. }), 'text');
  132. }
  133. });