slider_config_widget_view.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var validator = require('utils/validator');
  20. /**
  21. * Slider-view for configs
  22. * Used to numeric values
  23. * Config value attributes should contain minimum and maximum limits for value
  24. * @type {App.ConfigWidgetView}
  25. */
  26. App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
  27. templateName: require('templates/common/configs/widgets/slider_config_widget'),
  28. /**
  29. * Slider-object created on the <code>initSlider</code>
  30. * @type {Object}
  31. */
  32. slider: null,
  33. /**
  34. * Determines if widget controls should be disabled
  35. * @type {boolean}
  36. */
  37. disabled: false,
  38. /**
  39. * Mirror of the config-value shown in the input on the left of the slider
  40. * @type {number}
  41. */
  42. mirrorValue: 0,
  43. /**
  44. * Determines if used-input <code>mirrorValue</code> is valid
  45. * Calculated on the <code>mirrorValueObs</code>
  46. * @type {boolean}
  47. */
  48. isMirrorValueValid: true,
  49. /**
  50. * Function used to parse config value (based on <code>config.stackConfigProperty.valueAttributes.type</code>)
  51. * For integer - parseInt, for float - parseFloat
  52. * @type {Function}
  53. */
  54. parseFunction: function () {
  55. return this.get('config.stackConfigProperty.valueAttributes.type') === 'int' ? parseInt : parseFloat;
  56. }.property('config.stackConfigProperty.valueAttributes.type'),
  57. /**
  58. * Function used to validate config value (based on <code>config.stackConfigProperty.valueAttributes.type</code>)
  59. * For integer - validator.isValidInt, for float - validator.isValidFloat
  60. * @type {Function}
  61. */
  62. validateFunction: function () {
  63. return this.get('config.stackConfigProperty.valueAttributes.type') === 'int' ? validator.isValidInt : validator.isValidFloat;
  64. }.property('config.stackConfigProperty.valueAttributes.type'),
  65. /**
  66. * Enable/disable slider state
  67. * @method toggleWidgetState
  68. */
  69. toggleWidgetState: function () {
  70. var slider = this.get('slider');
  71. this.get('config.isEditable') ? slider.enable() : slider.disable();
  72. this.set('disabled', !this.get('config.isEditable'));
  73. }.observes('config.isEditable'),
  74. willInsertElement: function () {
  75. this._super();
  76. this.addObserver('mirrorValue', this, this.mirrorValueObs);
  77. },
  78. didInsertElement: function () {
  79. this._super();
  80. this.set('mirrorValue', this.get('config.value'));
  81. this.prepareValueAttributes();
  82. this.initSlider();
  83. this.toggleWidgetState();
  84. this.initPopover();
  85. },
  86. /**
  87. * view class for text box that is used with slider widget
  88. * @type {Em.TextField}
  89. */
  90. MirrorValueView: Em.TextField.extend({
  91. focusOut: function() {
  92. this.get('parentView').sendRequestRorDependentConfigs(this.get('parentView.config'));
  93. }
  94. }),
  95. /**
  96. * Check if <code>mirrorValue</code> was updated by user
  97. * Validate it. If value is correct, set it to slider and config.value
  98. * @method mirrorValueObs
  99. */
  100. mirrorValueObs: function () {
  101. var mirrorValue = this.get('mirrorValue'),
  102. slider = this.get('slider'),
  103. min = this.get('config.stackConfigProperty.valueAttributes.minimum'),
  104. max = this.get('config.stackConfigProperty.valueAttributes.maximum'),
  105. validationFunction = this.get('validateFunction'),
  106. parseFunction = this.get('parseFunction');
  107. if (validationFunction(mirrorValue)) {
  108. var parsed = parseFunction(mirrorValue);
  109. if (parsed >= min && parsed <= max) {
  110. this.set('isMirrorValueValid', true);
  111. this.set('config.errorMessage', '');
  112. this.set('config.value', '' + parsed);
  113. if (slider) {
  114. slider.setValue(parsed);
  115. }
  116. }
  117. else {
  118. this.set('isMirrorValueValid', false);
  119. this.set('config.errorMessage', 'Invalid value');
  120. }
  121. }
  122. else {
  123. this.set('isMirrorValueValid', false);
  124. this.set('config.errorMessage', 'Invalid value');
  125. }
  126. },
  127. /**
  128. * @override
  129. * @method setValue
  130. * set widget value same as config value
  131. */
  132. setValue: function() {
  133. this.set('mirrorValue', this.get('config.value'));
  134. },
  135. /**
  136. * valueAttributes are strings, but should be numbers
  137. * parse them using <code>parseFunction</code>
  138. * @method prepareValueAttributes
  139. */
  140. prepareValueAttributes: function () {
  141. var valueAttributes = this.get('config.stackConfigProperty.valueAttributes'),
  142. parseFunction = this.get('parseFunction');
  143. if (!valueAttributes) return;
  144. Em.set(valueAttributes, 'maximum', parseFunction(valueAttributes.maximum));
  145. Em.set(valueAttributes, 'minimum', parseFunction(valueAttributes.minimum));
  146. },
  147. /**
  148. * Draw slider for current config
  149. * @method initSlider
  150. */
  151. initSlider: function () {
  152. var self = this,
  153. config = this.get('config'),
  154. valueAttributes = config.get('stackConfigProperty.valueAttributes'),
  155. unit = Em.getWithDefault(valueAttributes, 'unit', ''),
  156. parseFunction = this.get('parseFunction'),
  157. ticks = [valueAttributes.minimum],
  158. ticksLabels = [];
  159. // ticks and labels
  160. for (var i = 1; i <= 3; i++) {
  161. var val = (valueAttributes.minimum + valueAttributes.maximum) / 4 * i;
  162. // if value's type is float, ticks may be float too
  163. ticks.push(valueAttributes.type === 'int' ? Math.round(val) : parseFloat(val.toFixed(1)));
  164. }
  165. ticks.push(valueAttributes.maximum);
  166. ticks.forEach(function (tick, index) {
  167. ticksLabels.push(index % 2 === 0 ? tick + ' ' + unit : '');
  168. });
  169. var slider = new Slider(this.$('input.slider-input')[0], {
  170. value: parseFunction(this.get('config.value')),
  171. ticks: ticks,
  172. tooltip: 'hide',
  173. ticks_labels: ticksLabels,
  174. ticks_snap_bounds: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1,
  175. step: Em.get(valueAttributes, 'type') === 'int' ? 1 : 0.1
  176. });
  177. slider.on('change', function (obj) {
  178. var val = parseFunction(obj.newValue);
  179. self.set('config.value', '' + val);
  180. self.set('mirrorValue', val);
  181. });
  182. /**
  183. * action to run sendRequestRorDependentConfigs when
  184. * we have changed config value within slider
  185. */
  186. slider.on('slideStop', function() {
  187. self.sendRequestRorDependentConfigs(self.get('config'));
  188. });
  189. this.set('slider', slider);
  190. // hide some ticks. can't do this via css
  191. this.$('.slider-tick:first, .slider-tick:last').hide();
  192. },
  193. /**
  194. * Restore <code>defaultValue</code> for config
  195. * Restore <code>mirrorValue</code> too
  196. * @method restoreValue
  197. */
  198. restoreValue: function () {
  199. this._super();
  200. var parseFunction = this.get('parseFunction'),
  201. val = parseFunction(this.get('config.value'));
  202. this.get('slider').setValue(val);
  203. this.set('mirrorValue', val);
  204. }
  205. });