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/26 12:40:24 UTC

ambari git commit: AMBARI-10183. Implement toggle and combo widget for config (onechiporenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk 5d035d51e -> aaf4233c1


AMBARI-10183. Implement toggle and combo widget for config (onechiporenko)


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

Branch: refs/heads/trunk
Commit: aaf4233c15a5e0d6ec6fc06cfc8cba06a375a7fc
Parents: 5d035d5
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Thu Mar 26 13:36:56 2015 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Thu Mar 26 13:36:56 2015 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/licenses/NOTICE.txt       |   5 +-
 ambari-web/app/assets/test/tests.js             |   2 +
 .../controllers/global/cluster_controller.js    |   1 -
 ambari-web/app/styles/widgets.less              |  44 +++++-
 .../configs/widgets/combo_config_widget.hbs     |  42 ++++++
 .../configs/widgets/time_interval_spinner.hbs   |   2 +-
 .../configs/widgets/toggle_config_widget.hbs    |  30 ++++
 ambari-web/app/views.js                         |   2 +
 .../configs/widgets/combo_config_widget_view.js | 113 +++++++++++++++
 .../widgets/time_interval_spinner_view.js       |   1 +
 .../widgets/toggle_config_widget_view.js        | 108 ++++++++++++++
 .../widgets/combo_config_widget_view_test.js    | 141 +++++++++++++++++++
 .../widgets/toggle_config_widget_view_test.js   |  70 +++++++++
 .../vendor/scripts/bootstrap-switch.min.js      |  22 +++
 .../vendor/styles/bootstrap-switch.min.css      |  22 +++
 15 files changed, 598 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/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 a023423..7c00e58 100644
--- a/ambari-web/app/assets/licenses/NOTICE.txt
+++ b/ambari-web/app/assets/licenses/NOTICE.txt
@@ -47,4 +47,7 @@ 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
+Copyright (C) 2015 by Kyle Kemp, Rohit Kalkur, and contributors
+
+This product includes bootstrap-slider 3.3.2 (https://github.com/nostalgiaz/bootstrap-switch - Apache License, Version 2.0)
+Copyright (C) 2015 by Mattia Larentis (mattia [at] larentis [*dot*] eu)

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/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 6267af3..de14b7c 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -165,9 +165,11 @@ var files = ['test/init_model_test',
   'test/utils/ui_effects_test',
   'test/utils/updater_test',
   'test/views/common/chart/linear_time_test',
+  'test/views/common/configs/widgets/combo_config_widget_view_test',
   'test/views/common/configs/widgets/config_widget_view_test',
   'test/views/common/configs/widgets/list_config_widget_view_test',
   'test/views/common/configs/widgets/slider_config_widget_view_test',
+  'test/views/common/configs/widgets/toggle_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/aaf4233c/ambari-web/app/controllers/global/cluster_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js
index f17364d..9fd1a46 100644
--- a/ambari-web/app/controllers/global/cluster_controller.js
+++ b/ambari-web/app/controllers/global/cluster_controller.js
@@ -280,7 +280,6 @@ App.ClusterController = Em.Controller.extend({
         });
 
         updater.updateServiceMetric(function () {
-          App.config.loadConfigsFromStack(App.Service.find().mapProperty('serviceName'));
           if (App.get('supports.enhancedConfigs')) {
             App.config.loadConfigsFromStack(App.Service.find().mapProperty('serviceName'));
           }

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/styles/widgets.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/widgets.less b/ambari-web/app/styles/widgets.less
index 9c1a286..aba89d8 100644
--- a/ambari-web/app/styles/widgets.less
+++ b/ambari-web/app/styles/widgets.less
@@ -17,9 +17,12 @@
  */
 @import 'common.less';
 
+@undo-btn-margin: 20px;
+@combo-widget-width: 100px;
+
 .widget {
   .action-button {
-    margin-left: 20px;
+    margin-left: @undo-btn-margin;
   }
 }
 
@@ -72,7 +75,6 @@
     border-radius: 11px;
     box-shadow: none;
   }
-
 }
 
 .spinner-input-widget {
@@ -110,8 +112,42 @@
     }
   }
 
-  .restore-btn {
+  .undo-button {
     padding: 2px 10px;
     float: left;
   }
-}
\ No newline at end of file
+}
+
+.toggle-widget {
+  .undo-button {
+    margin-left: @undo-btn-margin;
+  }
+}
+
+.combo-widget {
+  .input-append {
+
+    > input {
+      border-radius: 3px 0 0 3px;
+      width: @combo-widget-width;
+
+      &[disabled] {
+        background: #fff;
+        cursor: default;
+      }
+    }
+
+    .btn-group {
+      display: inline-block;
+      margin-left: -1px;
+
+      .btn {
+        border-radius: 0 3px 3px 0;
+      }
+    }
+  }
+
+  .action-button {
+    margin-left: @undo-btn-margin;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/templates/common/configs/widgets/combo_config_widget.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/combo_config_widget.hbs b/ambari-web/app/templates/common/configs/widgets/combo_config_widget.hbs
new file mode 100644
index 0000000..f9c4588
--- /dev/null
+++ b/ambari-web/app/templates/common/configs/widgets/combo_config_widget.hbs
@@ -0,0 +1,42 @@
+{{!
+* 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.
+}}
+
+<p>{{view.config.name}}</p>
+<div class="input-append pull-left">
+  {{view Em.TextField valueBinding="view.content.value" disabled="disabled"}}
+  <div class="dropdown btn-group">
+    <button class="btn dropdown-toggle" data-toggle="dropdown">
+      <span class="caret"></span>
+    </button>
+    <ul class="dropdown-menu">
+      {{#each item in view.content.valuesList}}
+        <li>
+          <a href="#" {{action setConfigValue item.configValue target="view"}}>{{item.widgetValue}}</a>
+        </li>
+      {{/each}}
+    </ul>
+  </div>
+</div>
+{{#if view.valueIsChanged}}
+  <div class="action-button pull-left">
+    <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
+      <i class="icon-undo"></i>
+    </a>
+  </div>
+{{/if}}
+<div class="clearfix"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/templates/common/configs/widgets/time_interval_spinner.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/time_interval_spinner.hbs b/ambari-web/app/templates/common/configs/widgets/time_interval_spinner.hbs
index 2e42a9f..c343200 100644
--- a/ambari-web/app/templates/common/configs/widgets/time_interval_spinner.hbs
+++ b/ambari-web/app/templates/common/configs/widgets/time_interval_spinner.hbs
@@ -20,7 +20,7 @@
   {{view App.SpinnerInputView contentBinding="spinnerContent" disabledBinding="view.disabled"}}
 {{/each}}
 {{#if view.valueIsChanged}}
-  <div class="restore-btn">
+  <div class="action-button">
     <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
       <i class="icon-undo"></i>
     </a>

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/templates/common/configs/widgets/toggle_config_widget.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/widgets/toggle_config_widget.hbs b/ambari-web/app/templates/common/configs/widgets/toggle_config_widget.hbs
new file mode 100644
index 0000000..f492689
--- /dev/null
+++ b/ambari-web/app/templates/common/configs/widgets/toggle_config_widget.hbs
@@ -0,0 +1,30 @@
+{{!
+* 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.
+}}
+
+<p>{{view.config.name}}</p>
+<div class="pull-left">
+  {{view Ember.Checkbox checkedBinding="view.switcherValue"}}
+</div>
+{{#if view.valueIsChanged}}
+  <div class="pull-left action-button">
+    <a class="btn btn-small" href="#" {{action "restoreValue" target="view"}}>
+      <i class="icon-undo"></i>
+    </a>
+  </div>
+{{/if}}
+<div class="clearfix"></div>

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index d96d857..8d099b1 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -52,9 +52,11 @@ require('views/common/configs/compare_property_view');
 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/combo_config_widget_view');
 require('views/common/configs/widgets/list_config_widget_view');
 require('views/common/configs/widgets/slider_config_widget_view');
 require('views/common/configs/widgets/time_interval_spinner_view');
+require('views/common/configs/widgets/toggle_config_widget_view');
 require('views/common/configs/widgets/overrides/slider_config_widget_override_view');
 require('views/common/configs/service_config_layout_tab_view');
 require('views/common/filter_combobox');

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/views/common/configs/widgets/combo_config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/combo_config_widget_view.js b/ambari-web/app/views/common/configs/widgets/combo_config_widget_view.js
new file mode 100644
index 0000000..921e3e9
--- /dev/null
+++ b/ambari-web/app/views/common/configs/widgets/combo_config_widget_view.js
@@ -0,0 +1,113 @@
+/**
+ * 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');
+
+/**
+ * Combo box widget view for config property.
+ * @type {Em.View}
+ */
+App.ComboConfigWidgetView = App.ConfigWidgetView.extend({
+  templateName: require('templates/common/configs/widgets/combo_config_widget'),
+  classNames: ['widget', 'combo-widget'],
+
+  /**
+   * Object with following structure:
+   * {String} .value - value in widget format
+   * {Object[]} .valuesList - map of entries and entry_labels
+   *   {String} .configValue - value in config format
+   *   {String} .widgetValue - value in widget format
+   *
+   * @property content
+   * @type {Em.Object}
+   */
+  content: null,
+
+  didInsertElement: function() {
+    this.generateContent();
+  },
+
+  /**
+   * Generate content for view. Set values map and current value.
+   *
+   * @method generateContent
+   */
+  generateContent: function() {
+    this.set('content', Em.Object.create({}));
+    this.set('content.valuesList', this.convertToWidgetUnits(this.get('config.stackConfigProperty.valueAttributes')));
+    this.set('content.value', this.generateWidgetValue(this.get('config.value')));
+  },
+
+  /**
+   * Generate values map according to widget/value format.
+   *
+   * @method convertToWidgetUnits
+   * @params {Object} valueAttributes
+   * @returns {Object[]} - values list map @see content.valuesList
+   */
+  convertToWidgetUnits: function(valueAttributes) {
+    return Em.get(valueAttributes, 'entries').map(function(item, index) {
+      return Em.Object.create({
+        configValue: item,
+        widgetValue: Em.get(valueAttributes, 'entry_labels.' + index)
+      });
+    });
+  },
+
+  /**
+   * Get widget value by specified config value.
+   *
+   * @method generateWidgetValue
+   * @param {String} value - value in config property format
+   * @returns {String}
+   */
+  generateWidgetValue: function(value) {
+    return this.get('content.valuesList').findProperty('configValue', value).get('widgetValue');
+  },
+
+  /**
+   * Get config value by specified widget value.
+   *
+   * @method generateConfigValue
+   * @param {String} value - value in widget property format
+   * @returns {String}
+   */
+  generateConfigValue: function(value) {
+    return this.get('content.valuesList').findProperty('widgetValue', value).get('configValue');
+  },
+
+  /**
+   * Action to set config value.
+   *
+   * @method setConfigValue
+   * @param {Object} e
+   */
+  setConfigValue: function(e) {
+    this.set('config.value', e.context);
+    this.set('content.value', this.generateWidgetValue(e.context));
+  },
+
+  /**
+   * @override App.ConfigWidgetView.restoreValue
+   * @method restoreValue
+   */
+  restoreValue: function() {
+    this.setConfigValue({ context: this.get('config.defaultValue') });
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js b/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
index 880d3d3..83881e1 100644
--- a/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
+++ b/ambari-web/app/views/common/configs/widgets/time_interval_spinner_view.js
@@ -131,6 +131,7 @@ App.TimeIntervalSpinnerView = App.ConfigWidgetView.extend({
     var propertyUnit = property.get('stackConfigProperty.valueAttributes').unit;
     return this.convertToWidgetUnits(value, propertyUnit, widgetUnits);
   },
+
   /**
    * Convert property value to widget format units.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/app/views/common/configs/widgets/toggle_config_widget_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/configs/widgets/toggle_config_widget_view.js b/ambari-web/app/views/common/configs/widgets/toggle_config_widget_view.js
new file mode 100644
index 0000000..0eb22b2
--- /dev/null
+++ b/ambari-web/app/views/common/configs/widgets/toggle_config_widget_view.js
@@ -0,0 +1,108 @@
+/**
+ * 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');
+
+/**
+ * Toggle wiget view for config property.
+ * @type {Em.View}
+ */
+App.ToggleConfigWidgetView = App.ConfigWidgetView.extend({
+  templateName: require('templates/common/configs/widgets/toggle_config_widget'),
+  classNames: ['widget', 'toggle-widget'],
+
+  /**
+   * Saved switcher for current config.
+   *
+   * @property switcher
+   */
+  switcher: null,
+
+  /**
+   * Value used in the checkbox.
+   * <code>config.value</code> can't be used because it's string.
+   *
+   * @property switcherValue
+   * @type {boolean}
+   */
+  switcherValue: false,
+
+  /**
+   * Update config value using <code>switcherValue</code>.
+   * switcherValue is boolean, but config value should be a string 'true'|'false'.
+   *
+   * @method updateConfigValue
+   */
+  updateConfigValue: function () {
+    this.set('config.value', '' + this.get('switcherValue'));
+  },
+
+  /**
+   * Get value for <code>switcherValue</code> (boolean) using <code>config.value</code> (string).
+   *
+   * @param configValue
+   * @returns {boolean} true for 'true', false for 'false'
+   * @method getNewSwitcherValue
+   */
+  getNewSwitcherValue: function (configValue) {
+    return 'true' === configValue;
+  },
+
+  didInsertElement: function () {
+    this.set('switcherValue', this.getNewSwitcherValue(this.get('config.value')));
+    // plugin should be initiated after applying binding for switcherValue
+    Em.run.later('sync', function() {
+      this.initSwitcher();
+    }.bind(this), 10);
+    this.addObserver('switcherValue', this.updateConfigValue);
+  },
+
+  /**
+   * Init switcher plugin.
+   *
+   * @method initSwitcher
+   */
+  initSwitcher: function () {
+    var labels = this.get('config.stackConfigProperty.valueAttributes.entry_labels'),
+      self = this;
+    var switcher = this.$("input").bootstrapSwitch({
+      onText: labels[0],
+      offText: labels[1],
+      offColor: 'danger',
+      handleWidth: 85,
+      onSwitchChange: function (event, state) {
+        self.set('switcherValue', state);
+      }
+    });
+    this.set('switcher', switcher);
+  },
+
+  /**
+   * Restore default config value and toggle switcher.
+   *
+   * @override App.ConfigWidgetView.restoreValue
+   * @method restoreValue
+   */
+  restoreValue: function () {
+    this._super();
+    var value = this.getNewSwitcherValue(this.get('config.value'));
+    this.get('switcher').bootstrapSwitch('toggleState', value);
+    this.set('switcherValue', value);
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/test/views/common/configs/widgets/combo_config_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/combo_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/combo_config_widget_view_test.js
new file mode 100644
index 0000000..e6f231c
--- /dev/null
+++ b/ambari-web/test/views/common/configs/widgets/combo_config_widget_view_test.js
@@ -0,0 +1,141 @@
+/**
+ * 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');
+
+describe('App.ComboConfigWidgetView', function() {
+
+  beforeEach(function() {
+    this.view = App.ComboConfigWidgetView.create({});
+  });
+
+  afterEach(function() {
+    this.view.destroy();
+    this.view = null;
+  });
+
+  describe('#convertToWidgetUnits', function() {
+    var tests = [
+      {
+        valueAttributes: {
+          entry_labels: ["Item A", "Item B"],
+          entries: ["a", "b"]
+        },
+        e: [
+          {
+            configValue: "a",
+            widgetValue: "Item A"
+          },
+          {
+            configValue: "b",
+            widgetValue: "Item B"
+          }
+        ]
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it('should convert {0} to {1}'.format(JSON.stringify(test.valueAttributes), JSON.stringify(test.e)), function() {
+        var result = this.view.convertToWidgetUnits(test.valueAttributes);
+        expect(JSON.parse(JSON.stringify(result))).to.eql(test.e);
+      });
+    });
+  });
+
+  describe('#generateWidgetValue', function() {
+    var tests = [
+      {
+        valuesList: [
+          Em.Object.create({
+            configValue: 'a',
+            widgetValue: 'Item A'
+          }),
+          Em.Object.create({
+            configValue: 'b',
+            widgetValue: 'Item B'
+          })
+        ],
+        value: 'a',
+        e: 'Item A'
+      },
+      {
+        valuesList: [
+          Em.Object.create({
+            configValue: 'a',
+            widgetValue: 'Item A'
+          }),
+          Em.Object.create({
+            configValue: 'b',
+            widgetValue: 'Item B'
+          })
+        ],
+        value: 'b',
+        e: 'Item B'
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it('should convert config value: `{0}` to widget value: `{1}`'.format(test.value, test.e), function() {
+        this.view.set('content', {});
+        this.view.set('content.valuesList', Em.A(test.valuesList));
+        expect(this.view.generateWidgetValue(test.value)).to.be.equal(test.e);
+      });
+    });
+  });
+
+  describe('#generateConfigValue', function() {
+    var tests = [
+      {
+        valuesList: [
+          Em.Object.create({
+            configValue: 'a',
+            widgetValue: 'Item A'
+          }),
+          Em.Object.create({
+            configValue: 'b',
+            widgetValue: 'Item B'
+          })
+        ],
+        value: 'Item A',
+        e: 'a'
+      },
+      {
+        valuesList: [
+          Em.Object.create({
+            configValue: 'a',
+            widgetValue: 'Item A'
+          }),
+          Em.Object.create({
+            configValue: 'b',
+            widgetValue: 'Item B'
+          })
+        ],
+        value: 'Item B',
+        e: 'b'
+      }
+    ];
+
+    tests.forEach(function(test) {
+      it('should convert widget value: `{0}` to config value: `{1}`'.format(test.value, test.e), function() {
+        this.view.set('content', {});
+        this.view.set('content.valuesList', Em.A(test.valuesList));
+        expect(this.view.generateConfigValue(test.value)).to.be.equal(test.e);
+      });
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/test/views/common/configs/widgets/toggle_config_widget_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/common/configs/widgets/toggle_config_widget_view_test.js b/ambari-web/test/views/common/configs/widgets/toggle_config_widget_view_test.js
new file mode 100644
index 0000000..d2db911
--- /dev/null
+++ b/ambari-web/test/views/common/configs/widgets/toggle_config_widget_view_test.js
@@ -0,0 +1,70 @@
+/**
+ * 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');
+
+describe('App.ToggleConfigWidgetView', function () {
+
+  beforeEach(function () {
+
+    this.view = App.ToggleConfigWidgetView.create({
+      initSwitcher: Em.K,
+      config: Em.Object.create({
+        name: 'a.b.c',
+        value: 'true',
+        defaultValue: 'true',
+        stackConfigProperty: Em.Object.create({
+          valueAttributes: {
+            "type": "value-list",
+            "entries": ["true", "false"],
+            "entry_labels": ["Active", "Inactive"],
+            "entries_editable": "false",
+            "selection_cardinality": 1
+          }
+        })
+      })
+    });
+    this.view.didInsertElement();
+  });
+
+  afterEach(function() {
+    this.view.destroy();
+    this.view = null;
+  });
+
+  describe('#getNewSwitcherValue', function () {
+
+    it('should represent string value to boolean', function () {
+      expect(this.view.getNewSwitcherValue('false')).to.be.false;
+      expect(this.view.getNewSwitcherValue('true')).to.be.true;
+    });
+
+  });
+
+  describe('#updateConfigValue', function () {
+
+    it('should represent boolean value to string', function () {
+      this.view.set('switcherValue', false);
+      expect(this.view.get('config.value')).to.equal('false');
+      this.view.set('switcherValue', true);
+      expect(this.view.get('config.value')).to.equal('true');
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/vendor/scripts/bootstrap-switch.min.js
----------------------------------------------------------------------
diff --git a/ambari-web/vendor/scripts/bootstrap-switch.min.js b/ambari-web/vendor/scripts/bootstrap-switch.min.js
new file mode 100644
index 0000000..c9386bc
--- /dev/null
+++ b/ambari-web/vendor/scripts/bootstrap-switch.min.js
@@ -0,0 +1,22 @@
+/* ========================================================================
+ * bootstrap-switch - v3.3.2
+ * http://www.bootstrap-switch.org
+ * ========================================================================
+ * Copyright 2012-2013 Mattia Larentis
+ *
+ * ========================================================================
+ * 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(){var t=[].slice;!function(e,i){"use strict";var n;return n=function(){function t(t,i){null==i&&(i={}),this.$element=e(t),this.options=e.extend({},e.fn.bootstrapSwitch.defaults,{state:this.$element.is(":checked"),size:this.$element.data("size"),animate:this.$element.data("animate"),disabled:this.$element.is(":disabled"),readonly:this.$element.is("[readonly]"),indeterminate:this.$element.data("indeterminate"),inverse:this.$element.data("inverse"),radioAllOff:this.$element.data("radio-all-off"),onColor:this.$element.data("on-color"),offColor:this.$element.data("off-color"),onText:this.$element.data("on-text"),offText:this.$element.data("off-text"),labelText:this.$element.data("label-text"),handleWidth:this.$element.data("handle-width"),labelWidth:this.$element.data("label-width"),baseClass:this.$element.data("base-class"),wrapperClass:this.$element.data("wrapper-class")},i),this.$wrapper=e("<div>",{"class":function(t){return function(){var e;return e=[""+t.options.baseClass]
 .concat(t._getClasses(t.options.wrapperClass)),e.push(t.options.state?""+t.options.baseClass+"-on":""+t.options.baseClass+"-off"),null!=t.options.size&&e.push(""+t.options.baseClass+"-"+t.options.size),t.options.disabled&&e.push(""+t.options.baseClass+"-disabled"),t.options.readonly&&e.push(""+t.options.baseClass+"-readonly"),t.options.indeterminate&&e.push(""+t.options.baseClass+"-indeterminate"),t.options.inverse&&e.push(""+t.options.baseClass+"-inverse"),t.$element.attr("id")&&e.push(""+t.options.baseClass+"-id-"+t.$element.attr("id")),e.join(" ")}}(this)()}),this.$container=e("<div>",{"class":""+this.options.baseClass+"-container"}),this.$on=e("<span>",{html:this.options.onText,"class":""+this.options.baseClass+"-handle-on "+this.options.baseClass+"-"+this.options.onColor}),this.$off=e("<span>",{html:this.options.offText,"class":""+this.options.baseClass+"-handle-off "+this.options.baseClass+"-"+this.options.offColor}),this.$label=e("<span>",{html:this.options.labelText,"class":
 ""+this.options.baseClass+"-label"}),this.$element.on("init.bootstrapSwitch",function(e){return function(){return e.options.onInit.apply(t,arguments)}}(this)),this.$element.on("switchChange.bootstrapSwitch",function(e){return function(){return e.options.onSwitchChange.apply(t,arguments)}}(this)),this.$container=this.$element.wrap(this.$container).parent(),this.$wrapper=this.$container.wrap(this.$wrapper).parent(),this.$element.before(this.options.inverse?this.$off:this.$on).before(this.$label).before(this.options.inverse?this.$on:this.$off),this.options.indeterminate&&this.$element.prop("indeterminate",!0),this._init(),this._elementHandlers(),this._handleHandlers(),this._labelHandlers(),this._formHandler(),this._externalLabelHandler(),this.$element.trigger("init.bootstrapSwitch")}return t.prototype._constructor=t,t.prototype.state=function(t,e){return"undefined"==typeof t?this.options.state:this.options.disabled||this.options.readonly?this.$element:this.options.state&&!this.options.
 radioAllOff&&this.$element.is(":radio")?this.$element:(this.options.indeterminate&&this.indeterminate(!1),t=!!t,this.$element.prop("checked",t).trigger("change.bootstrapSwitch",e),this.$element)},t.prototype.toggleState=function(t){return this.options.disabled||this.options.readonly?this.$element:this.options.indeterminate?(this.indeterminate(!1),this.state(!0)):this.$element.prop("checked",!this.options.state).trigger("change.bootstrapSwitch",t)},t.prototype.size=function(t){return"undefined"==typeof t?this.options.size:(null!=this.options.size&&this.$wrapper.removeClass(""+this.options.baseClass+"-"+this.options.size),t&&this.$wrapper.addClass(""+this.options.baseClass+"-"+t),this._width(),this._containerPosition(),this.options.size=t,this.$element)},t.prototype.animate=function(t){return"undefined"==typeof t?this.options.animate:(t=!!t,t===this.options.animate?this.$element:this.toggleAnimate())},t.prototype.toggleAnimate=function(){return this.options.animate=!this.options.anima
 te,this.$wrapper.toggleClass(""+this.options.baseClass+"-animate"),this.$element},t.prototype.disabled=function(t){return"undefined"==typeof t?this.options.disabled:(t=!!t,t===this.options.disabled?this.$element:this.toggleDisabled())},t.prototype.toggleDisabled=function(){return this.options.disabled=!this.options.disabled,this.$element.prop("disabled",this.options.disabled),this.$wrapper.toggleClass(""+this.options.baseClass+"-disabled"),this.$element},t.prototype.readonly=function(t){return"undefined"==typeof t?this.options.readonly:(t=!!t,t===this.options.readonly?this.$element:this.toggleReadonly())},t.prototype.toggleReadonly=function(){return this.options.readonly=!this.options.readonly,this.$element.prop("readonly",this.options.readonly),this.$wrapper.toggleClass(""+this.options.baseClass+"-readonly"),this.$element},t.prototype.indeterminate=function(t){return"undefined"==typeof t?this.options.indeterminate:(t=!!t,t===this.options.indeterminate?this.$element:this.toggleIndet
 erminate())},t.prototype.toggleIndeterminate=function(){return this.options.indeterminate=!this.options.indeterminate,this.$element.prop("indeterminate",this.options.indeterminate),this.$wrapper.toggleClass(""+this.options.baseClass+"-indeterminate"),this._containerPosition(),this.$element},t.prototype.inverse=function(t){return"undefined"==typeof t?this.options.inverse:(t=!!t,t===this.options.inverse?this.$element:this.toggleInverse())},t.prototype.toggleInverse=function(){var t,e;return this.$wrapper.toggleClass(""+this.options.baseClass+"-inverse"),e=this.$on.clone(!0),t=this.$off.clone(!0),this.$on.replaceWith(t),this.$off.replaceWith(e),this.$on=t,this.$off=e,this.options.inverse=!this.options.inverse,this.$element},t.prototype.onColor=function(t){var e;return e=this.options.onColor,"undefined"==typeof t?e:(null!=e&&this.$on.removeClass(""+this.options.baseClass+"-"+e),this.$on.addClass(""+this.options.baseClass+"-"+t),this.options.onColor=t,this.$element)},t.prototype.offColor
 =function(t){var e;return e=this.options.offColor,"undefined"==typeof t?e:(null!=e&&this.$off.removeClass(""+this.options.baseClass+"-"+e),this.$off.addClass(""+this.options.baseClass+"-"+t),this.options.offColor=t,this.$element)},t.prototype.onText=function(t){return"undefined"==typeof t?this.options.onText:(this.$on.html(t),this._width(),this._containerPosition(),this.options.onText=t,this.$element)},t.prototype.offText=function(t){return"undefined"==typeof t?this.options.offText:(this.$off.html(t),this._width(),this._containerPosition(),this.options.offText=t,this.$element)},t.prototype.labelText=function(t){return"undefined"==typeof t?this.options.labelText:(this.$label.html(t),this._width(),this.options.labelText=t,this.$element)},t.prototype.handleWidth=function(t){return"undefined"==typeof t?this.options.handleWidth:(this.options.handleWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.labelWidth=function(t){return"undefined"==typeof t?this.options.la
 belWidth:(this.options.labelWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.baseClass=function(){return this.options.baseClass},t.prototype.wrapperClass=function(t){return"undefined"==typeof t?this.options.wrapperClass:(t||(t=e.fn.bootstrapSwitch.defaults.wrapperClass),this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(" ")),this.$wrapper.addClass(this._getClasses(t).join(" ")),this.options.wrapperClass=t,this.$element)},t.prototype.radioAllOff=function(t){return"undefined"==typeof t?this.options.radioAllOff:(t=!!t,t===this.options.radioAllOff?this.$element:(this.options.radioAllOff=t,this.$element))},t.prototype.onInit=function(t){return"undefined"==typeof t?this.options.onInit:(t||(t=e.fn.bootstrapSwitch.defaults.onInit),this.options.onInit=t,this.$element)},t.prototype.onSwitchChange=function(t){return"undefined"==typeof t?this.options.onSwitchChange:(t||(t=e.fn.bootstrapSwitch.defaults.onSwitchChange),this.options.onSwitchChang
 e=t,this.$element)},t.prototype.destroy=function(){var t;return t=this.$element.closest("form"),t.length&&t.off("reset.bootstrapSwitch").removeData("bootstrap-switch"),this.$container.children().not(this.$element).remove(),this.$element.unwrap().unwrap().off(".bootstrapSwitch").removeData("bootstrap-switch"),this.$element},t.prototype._width=function(){var t,e;return t=this.$on.add(this.$off),t.add(this.$label).css("width",""),e="auto"===this.options.handleWidth?Math.max(this.$on.width(),this.$off.width()):this.options.handleWidth,t.width(e),this.$label.width(function(t){return function(i,n){return"auto"!==t.options.labelWidth?t.options.labelWidth:e>n?e:n}}(this)),this._handleWidth=this.$on.outerWidth(),this._labelWidth=this.$label.outerWidth(),this.$container.width(2*this._handleWidth+this._labelWidth),this.$wrapper.width(this._handleWidth+this._labelWidth)},t.prototype._containerPosition=function(t,e){return null==t&&(t=this.options.state),this.$container.css("margin-left",functio
 n(e){return function(){var i;return i=[0,"-"+e._handleWidth+"px"],e.options.indeterminate?"-"+e._handleWidth/2+"px":t?e.options.inverse?i[1]:i[0]:e.options.inverse?i[0]:i[1]}}(this)),e?setTimeout(function(){return e()},50):void 0},t.prototype._init=function(){var t,e;return t=function(t){return function(){return t._width(),t._containerPosition(null,function(){return t.options.animate?t.$wrapper.addClass(""+t.options.baseClass+"-animate"):void 0})}}(this),this.$wrapper.is(":visible")?t():e=i.setInterval(function(n){return function(){return n.$wrapper.is(":visible")?(t(),i.clearInterval(e)):void 0}}(this),50)},t.prototype._elementHandlers=function(){return this.$element.on({"change.bootstrapSwitch":function(t){return function(i,n){var o;return i.preventDefault(),i.stopImmediatePropagation(),o=t.$element.is(":checked"),t._containerPosition(o),o!==t.options.state?(t.options.state=o,t.$wrapper.toggleClass(""+t.options.baseClass+"-off").toggleClass(""+t.options.baseClass+"-on"),n?void 0:(
 t.$element.is(":radio")&&e("[name='"+t.$element.attr("name")+"']").not(t.$element).prop("checked",!1).trigger("change.bootstrapSwitch",!0),t.$element.trigger("switchChange.bootstrapSwitch",[o]))):void 0}}(this),"focus.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.addClass(""+t.options.baseClass+"-focused")}}(this),"blur.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.removeClass(""+t.options.baseClass+"-focused")}}(this),"keydown.bootstrapSwitch":function(t){return function(e){if(e.which&&!t.options.disabled&&!t.options.readonly)switch(e.which){case 37:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!1);case 39:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!0)}}}(this)})},t.prototype._handleHandlers=function(){return this.$on.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!1),t.$element.trigger("focus.bootstrapSw
 itch")}}(this)),this.$off.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!0),t.$element.trigger("focus.bootstrapSwitch")}}(this))},t.prototype._labelHandlers=function(){return this.$label.on({"mousedown.bootstrapSwitch touchstart.bootstrapSwitch":function(t){return function(e){return t._dragStart||t.options.disabled||t.options.readonly?void 0:(e.preventDefault(),e.stopPropagation(),t._dragStart=(e.pageX||e.originalEvent.touches[0].pageX)-parseInt(t.$container.css("margin-left"),10),t.options.animate&&t.$wrapper.removeClass(""+t.options.baseClass+"-animate"),t.$element.trigger("focus.bootstrapSwitch"))}}(this),"mousemove.bootstrapSwitch touchmove.bootstrapSwitch":function(t){return function(e){var i;if(null!=t._dragStart&&(e.preventDefault(),i=(e.pageX||e.originalEvent.touches[0].pageX)-t._dragStart,!(i<-t._handleWidth||i>0)))return t._dragEnd=i,t.$container.css("margin-left",""+t._dragEnd+"px")}}(this),"mouseup.bootstr
 apSwitch touchend.bootstrapSwitch":function(t){return function(e){var i;if(t._dragStart)return e.preventDefault(),t.options.animate&&t.$wrapper.addClass(""+t.options.baseClass+"-animate"),t._dragEnd?(i=t._dragEnd>-(t._handleWidth/2),t._dragEnd=!1,t.state(t.options.inverse?!i:i)):t.state(!t.options.state),t._dragStart=!1}}(this),"mouseleave.bootstrapSwitch":function(t){return function(){return t.$label.trigger("mouseup.bootstrapSwitch")}}(this)})},t.prototype._externalLabelHandler=function(){var t;return t=this.$element.closest("label"),t.on("click",function(e){return function(i){return i.preventDefault(),i.stopImmediatePropagation(),i.target===t[0]?e.toggleState():void 0}}(this))},t.prototype._formHandler=function(){var t;return t=this.$element.closest("form"),t.data("bootstrap-switch")?void 0:t.on("reset.bootstrapSwitch",function(){return i.setTimeout(function(){return t.find("input").filter(function(){return e(this).data("bootstrap-switch")}).each(function(){return e(this).bootstr
 apSwitch("state",this.checked)})},1)}).data("bootstrap-switch",!0)},t.prototype._getClasses=function(t){var i,n,o,s;if(!e.isArray(t))return[""+this.options.baseClass+"-"+t];for(n=[],o=0,s=t.length;s>o;o++)i=t[o],n.push(""+this.options.baseClass+"-"+i);return n},t}(),e.fn.bootstrapSwitch=function(){var i,o,s;return o=arguments[0],i=2<=arguments.length?t.call(arguments,1):[],s=this,this.each(function(){var t,a;return t=e(this),a=t.data("bootstrap-switch"),a||t.data("bootstrap-switch",a=new n(this,o)),"string"==typeof o?s=a[o].apply(a,i):void 0}),s},e.fn.bootstrapSwitch.Constructor=n,e.fn.bootstrapSwitch.defaults={state:!0,size:null,animate:!0,disabled:!1,readonly:!1,indeterminate:!1,inverse:!1,radioAllOff:!1,onColor:"primary",offColor:"default",onText:"ON",offText:"OFF",labelText:"&nbsp;",handleWidth:"auto",labelWidth:"auto",baseClass:"bootstrap-switch",wrapperClass:"wrapper",onInit:function(){},onSwitchChange:function(){}}}(window.jQuery,window)}).call(this);

http://git-wip-us.apache.org/repos/asf/ambari/blob/aaf4233c/ambari-web/vendor/styles/bootstrap-switch.min.css
----------------------------------------------------------------------
diff --git a/ambari-web/vendor/styles/bootstrap-switch.min.css b/ambari-web/vendor/styles/bootstrap-switch.min.css
new file mode 100644
index 0000000..9a89b03
--- /dev/null
+++ b/ambari-web/vendor/styles/bootstrap-switch.min.css
@@ -0,0 +1,22 @@
+/* ========================================================================
+ * bootstrap-switch - v3.3.2
+ * http://www.bootstrap-switch.org
+ * ========================================================================
+ * Copyright 2012-2013 Mattia Larentis
+ *
+ * ========================================================================
+ * 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.
+ * ========================================================================
+ */
+
+.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;border:1px solid;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color eas
 e-in-out .15s,box-shadow ease-in-out .15s}.bootstrap-switch .bootstrap-switch-container{display:inline-block;top:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on,.bootstrap-switch .bootstrap-switch-label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:inline-block!important;height:100%;padding:4px 8px;font-size:14px;line-height:20px}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on{text-align:center;z-index:1}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#005fcc;background-image:-moz-line
 ar-gradient(top,#04c,#08c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#04c),to(#08c));background-image:-webkit-linear-gradient(top,#04c,#08c);background-image:-o-linear-gradient(top,#04c,#08c);background-image:linear-gradient(to bottom,#04c,#08c);background-repeat:repeat-x;border-color:#08c #08c #005580;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary.active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary.disabled,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary[disabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary.active
 ,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary:hover,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary[disabled]{color:#fff;background-color:#08c}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#41a7c5;background-image:-moz-linear-gradient(top,#2f96b4,#5bc0de);background-image:-webkit-gradient(linear,0 0,0 100%,from(#2f96b4),to(#5bc0de));background-image:-webkit-linear-gradient(top,#2f96b4,#5bc0de);background-image:-o-linear-gradient(top,#2f96b4,#5bc0de);background-image:linear-gradient(to bottom,#2f96b4,#5bc0de);background-repeat:repeat-x;border-color:#5b
 c0de #5bc0de #28a1c5;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info.active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info.disabled,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info[disabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info.active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info:hover,.bootstrap-switch 
 .bootstrap-switch-handle-on.bootstrap-switch-info[disabled]{color:#fff;background-color:#5bc0de}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#58b058;background-image:-moz-linear-gradient(top,#51a351,#62c462);background-image:-webkit-gradient(linear,0 0,0 100%,from(#51a351),to(#62c462));background-image:-webkit-linear-gradient(top,#51a351,#62c462);background-image:-o-linear-gradient(top,#51a351,#62c462);background-image:linear-gradient(to bottom,#51a351,#62c462);background-repeat:repeat-x;border-color:#62c462 #62c462 #3b9e3b;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success.active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success.disabled,.bootstrap-switch .b
 ootstrap-switch-handle-off.bootstrap-switch-success:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success[disabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success.active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success:hover,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success[disabled]{color:#fff;background-color:#62c462}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);ba
 ckground-color:#f9a123;background-image:-moz-linear-gradient(top,#f89406,#fbb450);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f89406),to(#fbb450));background-image:-webkit-linear-gradient(top,#f89406,#fbb450);background-image:-o-linear-gradient(top,#f89406,#fbb450);background-image:linear-gradient(to bottom,#f89406,#fbb450);background-repeat:repeat-x;border-color:#fbb450 #fbb450 #f89406;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning.active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning.disabled,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning[di
 sabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning.active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning:hover,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning[disabled]{color:#fff;background-color:#fbb450}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#d14641;background-image:-moz-linear-gradient(top,#bd362f,#ee5f5b);background-image:-webkit-gradient(linear,0 0,0 100%,from(#bd362f),to(#ee5f5b));background-image:-webkit-linear-gradient(top,#bd362f,#ee5f5b);background-image:-o-linear-gradient(top,#bd362f,#ee5f5b);background-
 image:linear-gradient(to bottom,#bd362f,#ee5f5b);background-repeat:repeat-x;border-color:#ee5f5b #ee5f5b #e51d18;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger.active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger.disabled,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger[disabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger.active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-
 switch-danger:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger:hover,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger[disabled]{color:#fff;background-color:#ee5f5b}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default{color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);background-color:#f0f0f0;background-image:-moz-linear-gradient(top,#e6e6e6,#fff);background-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#fff));background-image:-webkit-linear-gradient(top,#e6e6e6,#fff);background-image:-o-linear-gradient(top,#e6e6e6,#fff);background-image:linear-gradient(to bottom,#e6e6e6,#fff);background-repeat:repeat-x;border-color:#fff #fff #d9d9d9;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default.active
 ,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default.disabled,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default:active,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default:focus,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default:hover,.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default[disabled],.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default.active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default.disabled,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default:active,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default:focus,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default:hover,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default[disabled]{color:#333;background-color:#fff}.bootstrap-switch .bootstrap-switch-label{text-align:center;margin-top:-1px;margin-bottom:-1px
 ;z-index:100;border-left:1px solid #ccc;border-right:1px solid #ccc;color:#333;text-shadow:0 -1px 0 rgba(0,0,0,.25);background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.bootstrap-switch .bootstrap-switch-label.active,.bootstrap-switch .bootstrap-switch-label.disabled,.bootstrap-switch .bootstrap-switch-label:active,.bootstrap-switch .bootstrap-switch-label:focus,.bootstrap-switch .bootstrap-switch-label:hover,.bootstrap-switch .bootstrap-switch-label[disabled]{color:#333;background-color:#e6e6e6}.bootstrap-switch .bootstrap-swit
 ch-handle-on{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px}.bootstrap-switch .bootstrap-switch-handle-off{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px}.bootstrap-switch input[type=radio],.bootstrap-switch input[type=checkbox]{position:absolute!important;top:0;left:0;opacity:0;filter:alpha(opacity=0);z-index:-1}.bootstrap-switch input[type=radio].form-control,.bootstrap-switch input[type=checkbox].form-control{height:auto}.bootstrap-switch.bootstrap-switch-mini{min-width:71px}.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label{padding:3px
  6px;font-size:10px;line-height:9px}.bootstrap-switch.bootstrap-switch-small{min-width:79px}.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label{padding:3px 6px;font-size:12px;line-height:18px}.bootstrap-switch.bootstrap-switch-large{min-width:120px}.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label{padding:9px 12px;font-size:16px;line-height:normal}.bootstrap-switch.bootstrap-switch-disabled,.bootstrap-switch.bootstrap-switch-indeterminate,.bootstrap-switch.bootstrap-switch-readonly{cursor:default!important}.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch
 -disabled .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label{opacity:.5;filter:alpha(opacity=50);cursor:default!important}.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container{-webkit-transition:margin-left .5s;-moz-transition:margin-left .5s;-o-transition:margin-left .5s;transition:margin-left .5s}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on{-moz-border-radius-topleft:0;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.bootst
 rap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off{-moz-border-radius-topright:0;border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius-bottomright:0;-moz-border-radius-topleft:4px;-moz-border-radius-bottomleft:4px}.bootstrap-switch.bootstrap-switch-focused{border-color:rgba(82,168,236,.8);outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6)}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-swit
 ch-label,.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px}