query_part_editor.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. define([
  2. 'angular',
  3. 'lodash',
  4. 'jquery',
  5. ],
  6. function (angular, _, $) {
  7. 'use strict';
  8. angular
  9. .module('grafana.directives')
  10. .directive('influxQueryPartEditor', function($compile, templateSrv) {
  11. var paramTemplate = '<input type="text" style="display:none"' +
  12. ' class="input-mini tight-form-func-param"></input>';
  13. return {
  14. restrict: 'E',
  15. templateUrl: 'public/app/plugins/datasource/influxdb/partials/query_part.html',
  16. scope: {
  17. part: "=",
  18. removeAction: "&",
  19. partUpdated: "&",
  20. getOptions: "&",
  21. },
  22. link: function postLink($scope, elem) {
  23. var part = $scope.part;
  24. var partDef = part.def;
  25. var $paramsContainer = elem.find('.query-part-parameters');
  26. var $controlsContainer = elem.find('.tight-form-func-controls');
  27. function clickFuncParam(paramIndex) {
  28. /*jshint validthis:true */
  29. var $link = $(this);
  30. var $input = $link.next();
  31. $input.val(part.params[paramIndex]);
  32. $input.css('width', ($link.width() + 16) + 'px');
  33. $link.hide();
  34. $input.show();
  35. $input.focus();
  36. $input.select();
  37. var typeahead = $input.data('typeahead');
  38. if (typeahead) {
  39. $input.val('');
  40. typeahead.lookup();
  41. }
  42. }
  43. function inputBlur(paramIndex) {
  44. /*jshint validthis:true */
  45. var $input = $(this);
  46. var $link = $input.prev();
  47. var newValue = $input.val();
  48. if (newValue !== '' || part.def.params[paramIndex].optional) {
  49. $link.html(templateSrv.highlightVariablesAsHtml(newValue));
  50. part.updateParam($input.val(), paramIndex);
  51. $scope.$apply($scope.partUpdated);
  52. }
  53. $input.hide();
  54. $link.show();
  55. }
  56. function inputKeyPress(paramIndex, e) {
  57. /*jshint validthis:true */
  58. if(e.which === 13) {
  59. inputBlur.call(this, paramIndex);
  60. }
  61. }
  62. function inputKeyDown() {
  63. /*jshint validthis:true */
  64. this.style.width = (3 + this.value.length) * 8 + 'px';
  65. }
  66. function addTypeahead($input, param, paramIndex) {
  67. if (!param.options && !param.dynamicLookup) {
  68. return;
  69. }
  70. var typeaheadSource = function (query, callback) {
  71. if (param.options) { return param.options; }
  72. $scope.$apply(function() {
  73. $scope.getOptions().then(function(result) {
  74. var dynamicOptions = _.map(result, function(op) { return op.value; });
  75. callback(dynamicOptions);
  76. });
  77. });
  78. };
  79. $input.attr('data-provide', 'typeahead');
  80. var options = param.options;
  81. if (param.type === 'int') {
  82. options = _.map(options, function(val) { return val.toString(); });
  83. }
  84. $input.typeahead({
  85. source: typeaheadSource,
  86. minLength: 0,
  87. items: 1000,
  88. updater: function (value) {
  89. setTimeout(function() {
  90. inputBlur.call($input[0], paramIndex);
  91. }, 0);
  92. return value;
  93. }
  94. });
  95. var typeahead = $input.data('typeahead');
  96. typeahead.lookup = function () {
  97. this.query = this.$element.val() || '';
  98. var items = this.source(this.query, $.proxy(this.process, this));
  99. return items ? this.process(items) : items;
  100. };
  101. }
  102. $scope.toggleControls = function() {
  103. var targetDiv = elem.closest('.tight-form');
  104. if (elem.hasClass('show-function-controls')) {
  105. elem.removeClass('show-function-controls');
  106. targetDiv.removeClass('has-open-function');
  107. $controlsContainer.hide();
  108. return;
  109. }
  110. elem.addClass('show-function-controls');
  111. targetDiv.addClass('has-open-function');
  112. $controlsContainer.show();
  113. };
  114. $scope.removeActionInternal = function() {
  115. $scope.toggleControls();
  116. $scope.removeAction();
  117. };
  118. function addElementsAndCompile() {
  119. _.each(partDef.params, function(param, index) {
  120. if (param.optional && part.params.length <= index) {
  121. return;
  122. }
  123. if (index > 0) {
  124. $('<span>, </span>').appendTo($paramsContainer);
  125. }
  126. var paramValue = templateSrv.highlightVariablesAsHtml(part.params[index]);
  127. var $paramLink = $('<a class="graphite-func-param-link pointer">' + paramValue + '</a>');
  128. var $input = $(paramTemplate);
  129. $paramLink.appendTo($paramsContainer);
  130. $input.appendTo($paramsContainer);
  131. $input.blur(_.partial(inputBlur, index));
  132. $input.keyup(inputKeyDown);
  133. $input.keypress(_.partial(inputKeyPress, index));
  134. $paramLink.click(_.partial(clickFuncParam, index));
  135. addTypeahead($input, param, index);
  136. });
  137. }
  138. function relink() {
  139. $paramsContainer.empty();
  140. addElementsAndCompile();
  141. }
  142. relink();
  143. }
  144. };
  145. });
  146. });