funcEditor.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. define([
  2. 'angular',
  3. 'lodash',
  4. 'jquery',
  5. ],
  6. function (angular, _, $) {
  7. 'use strict';
  8. angular
  9. .module('grafana.directives')
  10. .directive('influxdbFuncEditor', function($compile) {
  11. var funcSpanTemplate = '<a gf-dropdown="functionMenu" class="dropdown-toggle" ' +
  12. 'data-toggle="dropdown">{{field.func}}</a><span>(</span>';
  13. var paramTemplate = '<input type="text" style="display:none"' +
  14. ' class="input-mini tight-form-func-param"></input>';
  15. var functionList = [
  16. 'count', 'mean', 'sum', 'min', 'max', 'mode', 'distinct', 'median',
  17. 'derivative', 'non_negative_derivative', 'stddev', 'first', 'last', 'difference'
  18. ];
  19. var functionMenu = _.map(functionList, function(func) {
  20. return { text: func, click: "changeFunction('" + func + "');" };
  21. });
  22. return {
  23. restrict: 'A',
  24. scope: {
  25. field: "=",
  26. getFields: "&",
  27. onChange: "&",
  28. },
  29. link: function postLink($scope, elem) {
  30. var $funcLink = $(funcSpanTemplate);
  31. $scope.functionMenu = functionMenu;
  32. $scope.changeFunction = function(func) {
  33. $scope.field.func = func;
  34. $scope.onChange();
  35. };
  36. function clickFuncParam() {
  37. /*jshint validthis:true */
  38. var $link = $(this);
  39. var $input = $link.next();
  40. $input.val($scope.field.name);
  41. $input.css('width', ($link.width() + 16) + 'px');
  42. $link.hide();
  43. $input.show();
  44. $input.focus();
  45. $input.select();
  46. var typeahead = $input.data('typeahead');
  47. if (typeahead) {
  48. $input.val('');
  49. typeahead.lookup();
  50. }
  51. }
  52. function inputBlur() {
  53. /*jshint validthis:true */
  54. var $input = $(this);
  55. var $link = $input.prev();
  56. if ($input.val() !== '') {
  57. $link.text($input.val());
  58. $scope.field.name = $input.val();
  59. $scope.$apply($scope.onChange());
  60. }
  61. $input.hide();
  62. $link.show();
  63. }
  64. function inputKeyPress(e) {
  65. /*jshint validthis:true */
  66. if(e.which === 13) {
  67. inputBlur.call(this);
  68. }
  69. }
  70. function inputKeyDown() {
  71. /*jshint validthis:true */
  72. this.style.width = (3 + this.value.length) * 8 + 'px';
  73. }
  74. function addTypeahead($input) {
  75. $input.attr('data-provide', 'typeahead');
  76. $input.typeahead({
  77. source: function (query, callback) {
  78. return $scope.getFields().then(function(results) {
  79. callback(results);
  80. });
  81. },
  82. minLength: 0,
  83. items: 20,
  84. updater: function (value) {
  85. setTimeout(function() {
  86. inputBlur.call($input[0]);
  87. }, 0);
  88. return value;
  89. }
  90. });
  91. var typeahead = $input.data('typeahead');
  92. typeahead.lookup = function () {
  93. var items;
  94. this.query = this.$element.val() || '';
  95. items = this.source(this.query, $.proxy(this.process, this));
  96. return items ? this.process(items) : items;
  97. };
  98. }
  99. function addElementsAndCompile() {
  100. $funcLink.appendTo(elem);
  101. var $paramLink = $('<a ng-click="" class="graphite-func-param-link">' + $scope.field.name + '</a>');
  102. var $input = $(paramTemplate);
  103. $paramLink.appendTo(elem);
  104. $input.appendTo(elem);
  105. $input.blur(inputBlur);
  106. $input.keyup(inputKeyDown);
  107. $input.keypress(inputKeyPress);
  108. $paramLink.click(clickFuncParam);
  109. addTypeahead($input);
  110. $('<span>)</span>').appendTo(elem);
  111. $compile(elem.contents())($scope);
  112. }
  113. addElementsAndCompile();
  114. }
  115. };
  116. });
  117. });