You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2015/03/20 14:11:23 UTC

ambari git commit: AMBARI-10153. Implement 'slider' UI widget for enhanced configs (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 1a89565f1 -> 91926434a


AMBARI-10153. Implement 'slider' UI widget for enhanced configs (onechiporenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/91926434
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/91926434
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/91926434

Branch: refs/heads/trunk
Commit: 91926434a0bc15c593dfc53801327a1fb2f9d8da
Parents: 1a89565
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Fri Mar 20 13:58:55 2015 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Fri Mar 20 13:58:55 2015 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/licenses/NOTICE.txt       |   3 +
 ambari-web/app/assets/test/tests.js             |   1 +
 ambari-web/app/styles/widgets.less              |  46 ++++++-
 .../configs/widgets/list_config_widget.hbs      |  16 ++-
 .../configs/widgets/slider_config_widget.hbs    |  40 ++++++
 ambari-web/app/views.js                         |   1 +
 .../configs/widgets/config_widget_view.js       |   4 +-
 .../configs/widgets/list_config_widget_view.js  |   4 +-
 .../widgets/slider_config_widget_view.js        | 137 +++++++++++++++++++
 ambari-web/config.coffee                        |   6 +-
 .../widgets/list_config_widget_view_test.js     |  18 +--
 .../widgets/slider_config_widget_view_test.js   |  97 +++++++++++++
 .../vendor/scripts/bootstrap-slider.min.js      |  29 ++++
 .../vendor/styles/bootstrap-slider.min.css      |  28 ++++
 14 files changed, 409 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/assets/licenses/NOTICE.txt
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/licenses/NOTICE.txt b/ambari-web/app/assets/licenses/NOTICE.txt
index e5d8ef5..a023423 100644
--- a/ambari-web/app/assets/licenses/NOTICE.txt
+++ b/ambari-web/app/assets/licenses/NOTICE.txt
@@ -45,3 +45,6 @@ Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
 This product includes Moment.js (https://github.com/moment/moment/ - MIT license)
 
 This product includes Ember QUnit (https://github.com/rwjblue/ember-qunit - MIT license)
+
+This product includes bootstrap-slider 4.5.6 (https://github.com/seiyria/bootstrap-slider - MIT License)
+Copyright (C) 2015 by Kyle Kemp, Rohit Kalkur, and contributors
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 9f3596a..25b04f2 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -164,6 +164,7 @@ var files = ['test/init_model_test',
   'test/utils/updater_test',
   'test/views/common/chart/linear_time_test',
   'test/views/common/configs/widgets/list_config_widget_view_test',
+  'test/views/common/configs/widgets/slider_config_widget_view_test',
   'test/views/common/ajax_default_error_popup_body_test',
   'test/views/common/filter_combo_cleanable_test',
   'test/views/common/filter_view_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/styles/widgets.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/widgets.less b/ambari-web/app/styles/widgets.less
index d8ef400..6065a3f 100644
--- a/ambari-web/app/styles/widgets.less
+++ b/ambari-web/app/styles/widgets.less
@@ -25,5 +25,49 @@
       color: #333 !important;
     }
   }
-
 }
+
+.slider-widget {
+
+  @slider-widget-border-color: #999;
+
+  .ui-slider-wrapper {
+    margin: 0 30px;
+  }
+
+  .slider-track {
+    height: 20px !important;
+    border: 1px solid @slider-widget-border-color;
+    border-radius: 10px;
+  }
+  .slider-tick {
+    margin-top: 6px !important;
+    width: 0px;
+    font-size: 8px;
+    margin-left: 0px !important;
+    &:before {
+      content: '|';
+    }
+    &:nth-of-type(1):before {
+      content: '$$$' !important;
+    }
+  }
+  .slider-handle {
+    margin-top: -2px !important;
+    height: 22px;
+    width: 22px;
+    margin-left: -12px !important;
+    background-color: transparent !important;
+    background-image: radial-gradient(#aaa 5px, #eee 5px) !important;
+    border: 1px solid @slider-widget-border-color;
+  }
+  .slider-tick-label {
+    font-size: 10px;
+  }
+  .slider-selection {
+    background-image: none;
+    background-color: lighten(@blue, 20%);
+    border-radius: 11px;
+    box-shadow: none;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/templates/common/configs/widgets/list_config_widget.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/list_config_widget.hbs b/ambari-web/app/templates/common/configs/widgets/list_config_widget.hbs
index 42bc923..7470130 100644
--- a/ambari-web/app/templates/common/configs/widgets/list_config_widget.hbs
+++ b/ambari-web/app/templates/common/configs/widgets/list_config_widget.hbs
@@ -16,20 +16,24 @@
 * limitations under the License.
 }}
 
-{{view.config.name}}
 <div class="widget list-widget">
+  {{view.config.name}}
   <div class="btn-group">
     <a class="btn dropdown-toggle" data-toggle="dropdown">{{view.displayVal}} <span class="caret"></span></a>
     {{#if view.valueIsChanged}}
-    <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
-      <i class="icon-undo"></i>
-    </a>
+      <div class="undo-button">
+        <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
+          <i class="icon-undo"></i>
+        </a>
+      </div>
     {{/if}}
     <ul class="dropdown-menu">
       {{#each option in view.options}}
         <li>
-          <a rel="tooltip" href="javascript:void(0);" {{action "toggleOption" option target="view"}} {{bindAttr data-original-title="option.description"}}>
-            <label class="checkbox">{{view view.checkBoxWithoutAction valueBinding="option.value" disabledBinding="option.isDisabled" checkedBinding="option.isSelected"}} {{option.label}}</label>
+          <a rel="tooltip"
+             href="javascript:void(0);" {{action "toggleOption" option target="view"}} {{bindAttr data-original-title="option.description"}}>
+            <label
+                class="checkbox">{{view view.checkBoxWithoutAction valueBinding="option.value" disabledBinding="option.isDisabled" checkedBinding="option.isSelected"}} {{option.label}}</label>
           </a>
         </li>
       {{/each}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs b/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
new file mode 100644
index 0000000..960bc72
--- /dev/null
+++ b/ambari-web/app/templates/common/configs/widgets/slider_config_widget.hbs
@@ -0,0 +1,40 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class="widget slider-widget">
+  <p>{{view.config.description}}</p>
+  <div {{bindAttr class="view.isMirrorValueValid::error :control-group :pull-left"}}>
+    <div {{bindAttr class="view.config.stackConfigProperty.valueAttributes.unit:input-append"}}>
+      {{view Ember.TextField valueBinding="view.mirrorValue" class="input-mini"}}
+      {{#if view.config.stackConfigProperty.valueAttributes.unit}}
+        <span class="add-on">{{view.config.stackConfigProperty.valueAttributes.unit}}</span>
+      {{/if}}
+    </div>
+  </div>
+  <div class="pull-left ui-slider-wrapper">
+    {{view Ember.TextField valueBinding="view.config.value" class="input-mini slider-input"}}
+  </div>
+  {{#if view.valueIsChanged}}
+    <div class="pull-left undo-button">
+      <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
+        <i class="icon-undo"></i>
+      </a>
+    </div>
+  {{/if}}
+  <div class="clearfix"></div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 26b5a7f..090d4ba 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -51,6 +51,7 @@ require('views/common/configs/config_history_flow');
 require('views/common/configs/custom_category_views/notification_configs_view');
 require('views/common/configs/widgets/config_widget_view');
 require('views/common/configs/widgets/list_config_widget_view');
+require('views/common/configs/widgets/slider_config_widget_view');
 require('views/common/filter_combobox');
 require('views/common/filter_combo_cleanable');
 require('views/common/table_view');

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/views/common/configs/widgets/config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/config_widget_view.js b/ambari-web/app/views/common/configs/widgets/config_widget_view.js
index 1dfca68..e8a0136 100644
--- a/ambari-web/app/views/common/configs/widgets/config_widget_view.js
+++ b/ambari-web/app/views/common/configs/widgets/config_widget_view.js
@@ -25,7 +25,7 @@ var App = require('app');
 App.ConfigWidgetView = Em.View.extend({
 
   /**
-   * @type {App.StackConfigProperty}
+   * @type {App.ConfigProperty}
    */
   config: null,
 
@@ -34,7 +34,7 @@ App.ConfigWidgetView = Em.View.extend({
    * @type {boolean}
    */
   valueIsChanged: function () {
-    return this.get('config.value') !== this.get('config.defaultValue');
+    return this.get('config.value') != this.get('config.defaultValue');
   }.property('config.value'),
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/views/common/configs/widgets/list_config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/list_config_widget_view.js b/ambari-web/app/views/common/configs/widgets/list_config_widget_view.js
index 669bede..770f746 100644
--- a/ambari-web/app/views/common/configs/widgets/list_config_widget_view.js
+++ b/ambari-web/app/views/common/configs/widgets/list_config_widget_view.js
@@ -124,7 +124,7 @@ App.ListConfigWidgetView = App.ConfigWidgetView.extend({
    * @method calculateOptions
    */
   calculateOptions: function () {
-    var valueAttributes = this.get('config.valueAttributes'),
+    var valueAttributes = this.get('config.stackConfigProperty.valueAttributes'),
       options = [];
     Em.assert('valueAttributes `entries`, `entry_label` and `entry_descriptions` should have the same length', valueAttributes.entries.length == valueAttributes.entry_labels.length && valueAttributes.entries.length == valueAttributes.entry_descriptions.length);
     valueAttributes.entries.forEach(function (entryValue, indx) {
@@ -193,7 +193,7 @@ App.ListConfigWidgetView = App.ConfigWidgetView.extend({
    * @method parseCardinality
    */
   parseCardinality: function () {
-    var cardinality = numberUtils.getCardinalityValue(this.get('config.valueAttributes.selection_cardinality'), true);
+    var cardinality = numberUtils.getCardinalityValue(this.get('config.stackConfigProperty.valueAttributes.selection_cardinality'), true);
     this.set('allowedToSelect', cardinality);
   },
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js b/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
new file mode 100644
index 0000000..05306f5
--- /dev/null
+++ b/ambari-web/app/views/common/configs/widgets/slider_config_widget_view.js
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+var validator = require('utils/validator');
+
+/**
+ * Slider-view for configs
+ * Used to numeric values
+ * Config value attributes should contain minimum and maximum limits for value
+ * @type {App.ConfigWidgetView}
+ */
+App.SliderConfigWidgetView = App.ConfigWidgetView.extend({
+
+  templateName: require('templates/common/configs/widgets/slider_config_widget'),
+
+  /**
+   * Slider-object created on the <code>initSlider</code>
+   * @type {Object}
+   */
+  slider: null,
+
+  /**
+   * Mirror of the config-value shown in the input on the left of the slider
+   * @type {number}
+   */
+  mirrorValue: 0,
+
+  /**
+   * Determines if used-input <code>mirrorValue</code> is valid
+   * Calculated on the <code>mirrorValueObs</code>
+   * @type {boolean}
+   */
+  isMirrorValueValid: true,
+
+  willInsertElement: function () {
+    this._super();
+    this.addObserver('mirrorValue', this, this.mirrorValueObs);
+  },
+
+  didInsertElement: function () {
+    this._super();
+    this.set('mirrorValue', this.get('config.value'));
+    this.initSlider();
+  },
+
+  /**
+   * Check if <code>mirrorValue</code> was updated by user
+   * Validate it. If value is correct, set it to slider and config.value
+   * @method mirrorValueObs
+   */
+  mirrorValueObs: function () {
+    var mirrorValue = this.get('mirrorValue'),
+      slider = this.get('slider'),
+      min = this.get('config.stackConfigProperty.valueAttributes.minimum'),
+      max = this.get('config.stackConfigProperty.valueAttributes.maximum'),
+      validationFunction = this.get('config.stackConfigProperty.valueAttributes.type') == 'int' ? validator.isValidInt : validator.isValidFloat,
+      parseFunction = this.get('config.stackConfigProperty.valueAttributes.type') == 'int' ? parseInt : parseFloat;
+    if (validationFunction(mirrorValue)) {
+      var parsed = parseFunction(mirrorValue);
+      if (parsed >= min && parsed <=max) {
+        this.set('isMirrorValueValid', true);
+        this.set('config.value', parsed);
+        if (slider) {
+          slider.setValue(this.get('config.value'));
+        }
+      }
+      else {
+        this.set('isMirrorValueValid', false);
+      }
+    }
+    else {
+      this.set('isMirrorValueValid', false);
+    }
+  },
+
+  /**
+   * Draw slider for current config
+   * @method initSlider
+   */
+  initSlider: function () {
+    var self = this,
+      config = this.get('config'),
+      valueAttributes = config.get('stackConfigProperty.valueAttributes'),
+      unit = valueAttributes.get('unit'),
+      ticks = [valueAttributes.minimum],
+      ticksLabels = [];
+    for (var i = 1; i <= 3; i++) {
+      ticks.push(Math.round((valueAttributes.minimum + valueAttributes.maximum) / 4 * i));
+    }
+    ticks.push(valueAttributes.maximum);
+    ticks.forEach(function (tick, indx) {
+      ticksLabels.push(indx  % 2===0 ? tick + ' ' + unit : '');
+    });
+    var slider = new Slider('#' + this.get('elementId') + ' input.slider-input', {
+      value: this.get('config.value'),
+      ticks: ticks,
+      tooltip: 'hide',
+      ticks_labels: ticksLabels,
+      ticks_snap_bounds: valueAttributes.get('type') === 'int' ? 1 : 0.1,
+      step: valueAttributes.get('type') === 'int' ? 1 : 0.1
+    });
+    slider.on('slide', function (newValue) {
+      self.set('config.value', newValue);
+      self.set('mirrorValue', newValue);
+    });
+    this.set('slider', slider);
+    this.$('.slider-tick:first, .slider-tick:last').hide(); // hide some ticks. can't do this via css
+  },
+
+  /**
+   * Restore <code>defaultValue</code> for config
+   * Restore <code>mirrorValue</code> too
+   * @method restoreValue
+   */
+  restoreValue: function () {
+    this._super();
+    this.get('slider').setValue(this.get('config.value'));
+    this.set('mirrorValue', this.get('config.value'));
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/config.coffee
----------------------------------------------------------------------
diff --git a/ambari-web/config.coffee b/ambari-web/config.coffee
index 6f1970d..25e1766 100644
--- a/ambari-web/config.coffee
+++ b/ambari-web/config.coffee
@@ -39,7 +39,8 @@ exports.config =
           'vendor/scripts/ember-data-latest.js',
           'vendor/scripts/ember-i18n-1.4.1.js',
           'vendor/scripts/bootstrap.js',
-          'vendor/scripts/bootstrap-combobox.js'
+          'vendor/scripts/bootstrap-combobox.js',
+          'vendor/scripts/bootstrap-slider.min.js',
           'vendor/scripts/d3.v2.js',
           'vendor/scripts/cubism.v1.js',
           'vendor/scripts/jquery.ui.core.js',
@@ -74,7 +75,8 @@ exports.config =
           'vendor/styles/font-awesome-ie7.css',
           'vendor/styles/cubism.css',
           'vendor/styles/rickshaw.css'
-          'vendor/styles/bootstrap-combobox.css'
+          'vendor/styles/bootstrap-combobox.css',
+          'vendor/styles/bootstrap-slider.min.css'
         ]
 
     templates:

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js
index 167389c..62d8ec1 100644
--- a/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js
+++ b/ambari-web/test/views/common/configs/widgets/list_config_widget_view_test.js
@@ -28,12 +28,14 @@ describe('App.ListConfigWidgetView', function () {
         name: 'a.b.c',
         defaultValue: '2,1',
         value: '2,1',
-        valueAttributes: {
-          entries: ['1', '2', '3', '4', '5'],
-          entry_labels: ['first label', 'second label', 'third label', '4th label', '5th label'],
-          entry_descriptions: ['1', '2', '3', '4', '5'],
-          selection_cardinality: '3'
-        }
+        stackConfigProperty: Em.Object.create({
+          valueAttributes: {
+            entries: ['1', '2', '3', '4', '5'],
+            entry_labels: ['first label', 'second label', 'third label', '4th label', '5th label'],
+            entry_descriptions: ['1', '2', '3', '4', '5'],
+            selection_cardinality: '3'
+          }
+        })
       })
     });
     view.willInsertElement();
@@ -62,14 +64,14 @@ describe('App.ListConfigWidgetView', function () {
   describe('#calculateOptions', function () {
 
     it('should trigger error', function () {
-      view.set('config.valueAttributes.entry_descriptions', ['1', '2', '3', '4']);
+      view.set('config.stackConfigProperty.valueAttributes.entry_descriptions', ['1', '2', '3', '4']);
       expect(view.calculateOptions.bind(view)).to.throw(Error, 'assertion failed');
     });
 
     it('should create options for each entry', function () {
       view.set('options', []);
       view.calculateOptions();
-      expect(view.get('options.length')).to.equal(view.get('config.valueAttributes.entries.length'));
+      expect(view.get('options.length')).to.equal(view.get('config.stackConfigProperty.valueAttributes.entries.length'));
     });
 
     it('should selected options basing on `value`-property', function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
new file mode 100644
index 0000000..f34fb8f
--- /dev/null
+++ b/ambari-web/test/views/common/configs/widgets/slider_config_widget_view_test.js
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+
+var viewInt, viewFloat;
+
+describe('App.SliderConfigWidgetView', function () {
+
+  beforeEach(function () {
+    viewInt = App.SliderConfigWidgetView.create({
+      initSlider: Em.K,
+      config: Em.Object.create({
+        name: 'a.b.c',
+        description: 'A B C',
+        value: 486,
+        defaultValue: 486,
+        stackConfigProperty: Em.Object.create({
+          valueAttributes: Em.Object.create({
+            type: 'int',
+            minimum: 0,
+            maximum: 2096,
+            unit: 'MB'
+          })
+        })
+      })
+    });
+    viewInt.willInsertElement();
+    viewInt.didInsertElement();
+    viewFloat = App.SliderConfigWidgetView.create({
+      initSlider: Em.K,
+      config: Em.Object.create({
+        name: 'a.b.c2',
+        description: 'A B C 2',
+        value: 72.2,
+        defaultValue: 72.2,
+        stackConfigProperty: Em.Object.create({
+          valueAttributes: Em.Object.create({
+            type: 'float',
+            minimum: 0,
+            maximum: 100,
+            unit: '%'
+          })
+        })
+      })
+    });
+    viewFloat.willInsertElement();
+    viewFloat.didInsertElement();
+  });
+
+  describe('#mirrorValue', function () {
+    it('should be equal to config.value after init', function () {
+      expect(viewInt.get('mirrorValue')).to.equal(viewInt.get('config.value'));
+      expect(viewFloat.get('mirrorValue')).to.equal(viewFloat.get('config.value'));
+    });
+  });
+
+  describe('#mirrorValueObs', function () {
+
+    it('check int', function () {
+      viewInt.set('mirrorValue', 1000);
+      expect(viewInt.get('isMirrorValueValid')).to.be.true;
+      expect(viewInt.get('config.value')).to.equal(1000);
+
+      viewInt.set('mirrorValue', 100500);
+      expect(viewInt.get('isMirrorValueValid')).to.be.false;
+      expect(viewInt.get('config.value')).to.equal(1000);
+    });
+
+    it('check float', function () {
+      viewFloat.set('mirrorValue', 55.5);
+      expect(viewFloat.get('isMirrorValueValid')).to.be.true;
+      expect(viewFloat.get('config.value')).to.equal(55.5);
+
+      viewFloat.set('mirrorValue', 100500.5);
+      expect(viewFloat.get('isMirrorValueValid')).to.be.false;
+      expect(viewFloat.get('config.value')).to.equal(55.5);
+    });
+
+  });
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/vendor/scripts/bootstrap-slider.min.js
----------------------------------------------------------------------
diff --git a/ambari-web/vendor/scripts/bootstrap-slider.min.js b/ambari-web/vendor/scripts/bootstrap-slider.min.js
new file mode 100644
index 0000000..ff5fe6d
--- /dev/null
+++ b/ambari-web/vendor/scripts/bootstrap-slider.min.js
@@ -0,0 +1,29 @@
+/*! =======================================================
+ VERSION  4.5.6
+ ========================================================= */
+/*! =========================================================
+ * bootstrap-slider.js
+ *
+ * Maintainers:
+ *		Kyle Kemp
+ *			- Twitter: @seiyria
+ *			- Github:  seiyria
+ *		Rohit Kalkur
+ *			- Twitter: @Rovolutionary
+ *			- Github:  rovolution
+ *
+ * =========================================================
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+!function(a,b){if("function"==typeof define&&define.amd)define(["jquery"],b);else if("object"==typeof module&&module.exports){var c;try{c=require("jquery")}catch(d){c=null}module.exports=b(c)}else a.Slider=b(a.jQuery)}(this,function(a){var b;return function(a){"use strict";function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="
 undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function c(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var f=Object.keys(this.defaultOptions),g=0;g<f.length;g++){var h=f[g],i=c[h];i="undefined"!=typeof i?i:d(this.element,h),i=null!==i?i:this.defaultOptions[h],this.options||(this.options={}),this.options[h]=i}var j,k,l,m,n,o=this.element.style.width,p=!1,q=this.element.parentNode;if(this.sliderElem)p=!0;else{this.sliderElem=document.createElement("div"),this.sliderElem.className="slider";var r=document.createElement("div");if(r.className="slider-track",k=document.createElement("div"),k.className="slider-track-low",j=document.createElement("div"),j.className="slider-selection",l=
 document.createElement("div"),l.className="slider-track-high",m=document.createElement("div"),m.className="slider-handle min-slider-handle",n=document.createElement("div"),n.className="slider-handle max-slider-handle",r.appendChild(k),r.appendChild(j),r.appendChild(l),this.ticks=[],Array.isArray(this.options.ticks)&&this.options.ticks.length>0){for(g=0;g<this.options.ticks.length;g++){var s=document.createElement("div");s.className="slider-tick",this.ticks.push(s),r.appendChild(s)}j.className+=" tick-slider-selection"}if(r.appendChild(m),r.appendChild(n),this.tickLabels=[],Array.isArray(this.options.ticks_labels)&&this.options.ticks_labels.length>0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",g=0;g<this.options.ticks_labels.length;g++){var t=document.createElement("div");t.className="slider-tick-label",t.innerHTML=this.options.ticks_labels[g],this.tickLabels.push(t),this.tickLabelContainer.appendChild(t)}va
 r u=function(a){var b=document.createElement("div");b.className="tooltip-arrow";var c=document.createElement("div");c.className="tooltip-inner",a.appendChild(b),a.appendChild(c)},v=document.createElement("div");v.className="tooltip tooltip-main",u(v);var w=document.createElement("div");w.className="tooltip tooltip-min",u(w);var x=document.createElement("div");x.className="tooltip tooltip-max",u(x),this.sliderElem.appendChild(r),this.sliderElem.appendChild(v),this.sliderElem.appendChild(w),this.sliderElem.appendChild(x),this.tickLabelContainer&&this.sliderElem.appendChild(this.tickLabelContainer),q.insertBefore(this.sliderElem,this.element),this.element.style.display="none"}if(a&&(this.$element=a(this.element),this.$sliderElem=a(this.sliderElem)),this.eventToCallbackMap={},this.sliderElem.id=this.options.id,this.touchCapable="ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,this.tooltip=this.sliderElem.querySelector(".tooltip-main"),this.tooltipI
 nner=this.tooltip.querySelector(".tooltip-inner"),this.tooltip_min=this.sliderElem.querySelector(".tooltip-min"),this.tooltipInner_min=this.tooltip_min.querySelector(".tooltip-inner"),this.tooltip_max=this.sliderElem.querySelector(".tooltip-max"),this.tooltipInner_max=this.tooltip_max.querySelector(".tooltip-inner"),e[this.options.scale]&&(this.options.scale=e[this.options.scale]),p===!0&&(this._removeClass(this.sliderElem,"slider-horizontal"),this._removeClass(this.sliderElem,"slider-vertical"),this._removeClass(this.tooltip,"hide"),this._removeClass(this.tooltip_min,"hide"),this._removeClass(this.tooltip_max,"hide"),["left","top","width","height"].forEach(function(a){this._removeProperty(this.trackLow,a),this._removeProperty(this.trackSelection,a),this._removeProperty(this.trackHigh,a)},this),[this.handle1,this.handle2].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"top")},this),[this.tooltip,this.tooltip_min,this.tooltip_max].forEach(function(a){this._
 removeProperty(a,"left"),this._removeProperty(a,"top"),this._removeProperty(a,"margin-left"),this._removeProperty(a,"margin-top"),this._removeClass(a,"right"),this._removeClass(a,"top")},this)),"vertical"===this.options.orientation?(this._addClass(this.sliderElem,"slider-vertical"),this.stylePos="top",this.mousePos="pageY",this.sizePos="offsetHeight",this._addClass(this.tooltip,"right"),this.tooltip.style.left="100%",this._addClass(this.tooltip_min,"right"),this.tooltip_min.style.left="100%",this._addClass(this.tooltip_max,"right"),this.tooltip_max.style.left="100%"):(this._addClass(this.sliderElem,"slider-horizontal"),this.sliderElem.style.width=o,this.options.orientation="horizontal",this.stylePos="left",this.mousePos="pageX",this.sizePos="offsetWidth",this._addClass(this.tooltip,"top"),this.tooltip.style.top=-this.tooltip.outerHeight-14+"px",this._addClass(this.tooltip_min,"top"),this.tooltip_min.style.top=-this.tooltip_min.outerHeight-14+"px",this._addClass(this.tooltip_max,"top
 "),this.tooltip_max.style.top=-this.tooltip_max.outerHeight-14+"px"),Array.isArray(this.options.ticks)&&this.options.ticks.length>0&&(this.options.max=Math.max.apply(Math,this.options.ticks),this.options.min=Math.min.apply(Math,this.options.ticks)),Array.isArray(this.options.value)?this.options.range=!0:this.options.range&&(this.options.value=[this.options.value,this.options.max]),this.trackLow=k||this.trackLow,this.trackSelection=j||this.trackSelection,this.trackHigh=l||this.trackHigh,"none"===this.options.selection&&(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")),this.handle1=m||this.handle1,this.handle2=n||this.handle2,p===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),g=0;g<this.ticks.length;g++)this._removeClass(this.ticks[g],"round triangle hide");var y=["round","triangle","custom"],z=-1!==y.indexOf(this.options.handle);if(z)for(this._addClass(
 this.handle1,this.options.handle),this._addClass(this.handle2,this.options.handle),g=0;g<this.ticks.length;g++)this._addClass(this.ticks[g],this.options.handle);this.offset=this._offset(this.sliderElem),this.size=this.sliderElem[this.sizePos],this.setValue(this.options.value),this.handle1Keydown=this._keydown.bind(this,0),this.handle1.addEventListener("keydown",this.handle1Keydown,!1),this.handle2Keydown=this._keydown.bind(this,1),this.handle2.addEventListener("keydown",this.handle2Keydown,!1),this.mousedown=this._mousedown.bind(this),this.touchCapable&&this.sliderElem.addEventListener("touchstart",this.mousedown,!1),this.sliderElem.addEventListener("mousedown",this.mousedown,!1),"hide"===this.options.tooltip?(this._addClass(this.tooltip,"hide"),this._addClass(this.tooltip_min,"hide"),this._addClass(this.tooltip_max,"hide")):"always"===this.options.tooltip?(this._showTooltip(),this._alwaysShowTooltip=!0):(this.showTooltip=this._showTooltip.bind(this),this.hideTooltip=this._hideToolt
 ip.bind(this),this.sliderElem.addEventListener("mouseenter",this.showTooltip,!1),this.sliderElem.addEventListener("mouseleave",this.hideTooltip,!1),this.handle1.addEventListener("focus",this.showTooltip,!1),this.handle1.addEventListener("blur",this.hideTooltip,!1),this.handle2.addEventListener("focus",this.showTooltip,!1),this.handle2.addEventListener("blur",this.hideTooltip,!1)),this.options.enabled?this.enable():this.disable()}var d={formatInvalidInputErrorMsg:function(a){return"Invalid input value '"+a+"' passed in"},callingContextNotSliderInstance:"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"},e={linear:{toValue:function(a){var b=a/100*(this.options.max-this.options.min),c=this.options.min+Math.round(b/this.options.step)*this.options.step;return c<this.options.min?this.options.min:c>this.options.max?this.options.max:c},toPercentage:fun
 ction(a){return this.options.max===this.options.min?0:100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=0===this.options.min?0:Math.log(this.options.min),c=Math.log(this.options.max);return Math.exp(b+(c-b)*a/100)},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=Math.log(this.options.max),c=0===this.options.min?0:Math.log(this.options.min),d=0===a?0:Math.log(a);return 100*(d-c)/(b-c)}}};if(b=function(a,b){return c.call(this,a,b),this},b.prototype={_init:function(){},constructor:b,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,handle:"round",reversed:!1,enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_labels:[],ticks_snap_bounds:0,scale:"linear"},over:!1,inDrag:!1,getValue:function(){return this.options.range?this.options.value:this.options.
 value[0]},setValue:function(a,b){a||(a=0);var c=this.getValue();this.options.value=this._validateInputValue(a);var d=this._applyPrecision.bind(this);this.options.range?(this.options.value[0]=d(this.options.value[0]),this.options.value[1]=d(this.options.value[1]),this.options.value[0]=Math.max(this.options.min,Math.min(this.options.max,this.options.value[0])),this.options.value[1]=Math.max(this.options.min,Math.min(this.options.max,this.options.value[1]))):(this.options.value=d(this.options.value),this.options.value=[Math.max(this.options.min,Math.min(this.options.max,this.options.value))],this._addClass(this.handle2,"hide"),this.options.value[1]="after"===this.options.selection?this.options.max:this.options.min),this.percentage=this.options.max>this.options.min?[this._toPercentage(this.options.value[0]),this._toPercentage(this.options.value[1]),100*this.options.step/(this.options.max-this.options.min)]:[0,0,100],this._layout();var e=this.options.range?this.options.value:this.options
 .value[0];return b===!0&&this._trigger("slide",e),c!==e&&this._trigger("change",{oldValue:c,newValue:e}),this._setDataVal(e),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),this.$element.removeData("slider"))},disable:function(){return this.options.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this.options.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this.options.enabled?this.disable():this.enable(),this},isEnabled:function(){return this.options.enabled},on:function(a,
 b){return this._bindNonQueryEventHandler(a,b),this},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(){return this._removeSliderEventHandlers(),c.call(this,this.element,this.options),a&&a.data(this.element,"slider",this),this},relayout:function(){return this._layout(),this},_removeSliderEventHandlers:function(){this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle1.removeEventListener("focus",this.showTooltip,!1),this.handle1.removeEventListener("blur",this.hideTooltip,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.handle2.removeEventListener("focus",this.handle2Keydown,!1),this.handle2.removeEventListener("blur",this.handle2Keydown,!1),this.sliderElem.removeEventListener("mouseenter",this.showTooltip,!1),this.sliderElem.removeEventListener("mouseleave",this.hideTooltip,!1),this.sliderElem.removeEventListener("touchstart",this.mousedown,!1),
 this.sliderElem.removeEventListener("mousedown",this.mousedown,!1)},_bindNonQueryEventHandler:function(a,b){void 0===this.eventToCallbackMap[a]&&(this.eventToCallbackMap[a]=[]),this.eventToCallbackMap[a].push(b)},_cleanUpEventCallbacksMap:function(){for(var a=Object.keys(this.eventToCallbackMap),b=0;b<a.length;b++){var c=a[b];this.eventToCallbackMap[c]=null}},_showTooltip:function(){this.options.tooltip_split===!1?this._addClass(this.tooltip,"in"):(this._addClass(this.tooltip_min,"in"),this._addClass(this.tooltip_max,"in")),this.over=!0},_hideTooltip:function(){this.inDrag===!1&&this.alwaysShowTooltip!==!0&&(this._removeClass(this.tooltip,"in"),this._removeClass(this.tooltip_min,"in"),this._removeClass(this.tooltip_max,"in")),this.over=!1},_layout:function(){var a;if(a=this.options.reversed?[100-this.percentage[0],this.percentage[1]]:[this.percentage[0],this.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle2.style[this.stylePos]=a[1]+"%",Array.isArray(this.option
 s.ticks)&&this.options.ticks.length>0){var b=Math.max.apply(Math,this.options.ticks),c=Math.min.apply(Math,this.options.ticks),d="vertical"===this.options.orientation?"height":"width",e="vertical"===this.options.orientation?"marginTop":"marginLeft",f=this.size/(this.options.ticks.length-1);if(this.tickLabelContainer&&(this.tickLabelContainer.style[e]=-f/2+"px","horizontal"===this.options.orientation)){var g=this.tickLabelContainer.offsetHeight-this.sliderElem.offsetHeight;this.sliderElem.style.marginBottom=g+"px"}for(var h=0;h<this.options.ticks.length;h++){var i=100*(this.options.ticks[h]-c)/(b-c);this.ticks[h].style[this.stylePos]=i+"%",this._removeClass(this.ticks[h],"in-selection"),i<=a[0]&&!this.options.range?this._addClass(this.ticks[h],"in-selection"):i>=a[0]&&i<=a[1]&&this._addClass(this.ticks[h],"in-selection"),this.tickLabels[h]&&(this.tickLabels[h].style[d]=f+"px")}}if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[
 0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%",this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var j=this.tooltip_min.getBoundingClientRect(),k=this.tooltip_max.getBoundingClientRect();j.right>k.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}var l;if(this.options.range){l=this.options.formatter(this.options.value),this._setText(this.toolti
 pInner,l),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px"),"vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px");var m=this.options.formatter(this.options.value[0]);this._setText(this.tooltipInner_min,m);var n=this.options.formatter(this.options.value[1]);this._setText(this.tooltipInner_max,n),this.tooltip_min.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip_min,"margin-top",-this.tooltip_min.offsetHeight/2+"px"):this._css(this.tooltip_min,"margin-left",-this.tooltip_min.offsetWidth/2+"px"),this.tooltip_max.style[this.stylePos]=a[1]+"%","vertical"===this.options.orientation?this._css(this.tooltip_max,"margin-top",-this.tooltip_max.offsetH
 eight/2+"px"):this._css(this.tooltip_max,"margin-left",-this.tooltip_max.offsetWidth/2+"px")}else l=this.options.formatter(this.options.value[0]),this._setText(this.tooltipInner,l),this.tooltip.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px")},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this.options.enabled)return!1;this._triggerFocusOnHandle(),this.offset=this._offset(this.sliderElem),this.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this.percentage[0]-b),d=Math.abs(this.percentage[1]-b);this.dragged=d>c?0:1}else this.dragged=0;this.percentage[this.dragged]=this.options.reversed?100-b:b,this._layout(),this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1)
 ,document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this._setDataVal(e),this.setValue(e),this._pauseEvent(a),!0},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this.options.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="vertical"===this.options.orientation&&!this.options.reversed
 ,e="horizontal"===this.options.orientation&&this.options.reversed;(d||e)&&(c=-c)}var f=this.options.value[a]+c*this.options.step;return this.options.range&&(f=[a?this.options.value[0]:f,a?f:this.options.value[1]]),this._trigger("slideStart",f),this._setDataVal(f),this.setValue(f,!0),this._trigger("slideStop",f),this._setDataVal(f),this._layout(),this._pauseEvent(b),!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this.options.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this.percentage[this.dragged]=this.options.reversed?100-b:b,this._layout();var c=this._calculateValue(!0);return this.setValue(c,!0),!1},_adjustPercentageForRangeSliders:function(a){this.options.range&&(0===this.dragged&&this.percentage[1]<a?(this.percentage[0]=this.percentage[1],this.dragged=1):1===this.dragged&&this.percentage[0]>a&&(this.percentage[1]=this
 .percentage[0],this.dragged=0))},_mouseup:function(){if(!this.options.enabled)return!1;this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this.inDrag=!1,this.over===!1&&this._hideTooltip();var a=this._calculateValue(!0);return this._layout(),this._trigger("slideStop",a),this._setDataVal(a),!1},_calculateValue:function(a){var b;if(this.options.range?(b=[this.options.min,this.options.max],0!==this.percentage[0]&&(b[0]=this._toValue(this.percentage[0]),b[0]=this._applyPrecision(b[0])),100!==this.percentage[1]&&(b[1]=this._toValue(this.percentage[1]),b[1]=this._applyPrecision(b[1]))):(b=this._toValue(this.percentage[0]),b=parseFloat(b),b=this._applyPrecision(b)),a){for(var c=[b,1/0],d=0;d<this.options.ticks.length;d++){var e=Math.abs(this.options.ticks[d]-b);e<=c[1]&&(c=[this.options.tic
 ks[d],e])}if(c[1]<=this.options.ticks_snap_bounds)return c[0]}return b},_applyPrecision:function(a){var b=this.options.precision||this._getNumDigitsAfterDecimalPlace(this.options.step);return this._applyToFixedAndParseFloat(a,b)},_getNumDigitsAfterDecimalPlace:function(a){var b=(""+a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return b?Math.max(0,(b[1]?b[1].length:0)-(b[2]?+b[2]:0)):0},_applyToFixedAndParseFloat:function(a,b){var c=a.toFixed(b);return parseFloat(c)},_getPercentage:function(a){!this.touchCapable||"touchstart"!==a.type&&"touchmove"!==a.type||(a=a.touches[0]);var b=a[this.mousePos],c=this.offset[this.stylePos],d=b-c,e=d/this.size*100;return e=Math.round(e/this.percentage[2])*this.percentage[2],Math.max(0,Math.min(100,e))},_validateInputValue:function(a){if("number"==typeof a)return a;if(Array.isArray(a))return this._validateArray(a),a;throw new Error(d.formatInvalidInputErrorMsg(a))},_validateArray:function(a){for(var b=0;b<a.length;b++){var c=a[b];if("number"!=typeof c
 )throw new Error(d.formatInvalidInputErrorMsg(c))}},_setDataVal:function(a){var b="value: '"+a+"'";this.element.setAttribute("data",b),this.element.setAttribute("value",a),this.element.value=a},_trigger:function(b,c){c=c||0===c?c:void 0;var d=this.eventToCallbackMap[b];if(d&&d.length)for(var e=0;e<d.length;e++){var f=d[e];f(c)}a&&this._triggerJQueryEvent(b,c)},_triggerJQueryEvent:function(a,b){var c={type:a,value:b};this.$element.trigger(c),this.$sliderElem.trigger(c)},_unbindJQueryEventHandlers:function(){this.$element.off(),this.$sliderElem.off()},_setText:function(a,b){"undefined"!=typeof a.innerText?a.innerText=b:"undefined"!=typeof a.textContent&&(a.textContent=b)},_removeClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)");d=d.replace(g," ")}a.className=d.trim()},_addClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)"),h=g.test(d
 );h||(d+=" "+f)}a.className=d.trim()},_offset:function(a){if("vertical"===this.options.orientation)return{left:a.offsetLeft,top:a.offsetTop};var b=a.getBoundingClientRect(),c=b.left,d=b.top;return{left:c,top:d}},_css:function(b,c,d){if(a)a.style(b,c,d);else{var e=c.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,b){return b.toUpperCase()});b.style[e]=d}},_toValue:function(a){return this.options.scale.toValue.apply(this,[a])},_toPercentage:function(a){return this.options.scale.toPercentage.apply(this,[a])}},a){var f=a.fn.slider?"bootstrapSlider":"slider";a.bridget(f,b)}}(a),b});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/91926434/ambari-web/vendor/styles/bootstrap-slider.min.css
----------------------------------------------------------------------
diff --git a/ambari-web/vendor/styles/bootstrap-slider.min.css b/ambari-web/vendor/styles/bootstrap-slider.min.css
new file mode 100644
index 0000000..ed7f3d9
--- /dev/null
+++ b/ambari-web/vendor/styles/bootstrap-slider.min.css
@@ -0,0 +1,28 @@
+/*! =======================================================
+                      VERSION  4.5.6
+========================================================= */
+/*! =========================================================
+ * bootstrap-slider.js
+ *
+ * Maintainers:
+ *		Kyle Kemp
+ *			- Twitter: @seiyria
+ *			- Github:  seiyria
+ *		Rohit Kalkur
+ *			- Twitter: @Rovolutionary
+ *			- Github:  rovolution
+ *
+ * =========================================================
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px;margin-top:-5px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#0480be;margin-top:0}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{margin-top:24px;display:inline-block;text-align:center}.slider.slider-vertical{height:210px;width:20px}.slider.sl
 ider-vertical .slider-track{width:10px;height:100%;margin-left:-5px;left:50%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-left:-5px;margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#0480be;margin-left:0}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-im
 age:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-sele
 ction{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;b
 ackground:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:-o-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:linear-gradient(to bottom,#149bdf 0,#0480be 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute
 ;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear
 -gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0);opacity:1}
\ No newline at end of file