Introduce scope "switch" type, allow options to be passed

This commit is contained in:
Samuel Georges 2016-04-27 19:09:19 +10:00
parent 28a8f84692
commit 0d8a30730e
12 changed files with 325 additions and 60 deletions

View File

@ -343,7 +343,8 @@ return [
'email' => 'Email' 'email' => 'Email'
], ],
'filter' => [ 'filter' => [
'all' => 'all' 'all' => 'all',
'options_method_not_exists' => "The model class :model must define a method :method() returning options for the ':filter' filter."
], ],
'import_export' => [ 'import_export' => [
'upload_csv_file' => '1. Upload a CSV file', 'upload_csv_file' => '1. Upload a CSV file',

View File

@ -1,6 +1,8 @@
<?php namespace Backend\Widgets; <?php namespace Backend\Widgets;
use Db; use Db;
use Str;
use Lang;
use Event; use Event;
use DbDongle; use DbDongle;
use Backend\Classes\WidgetBase; use Backend\Classes\WidgetBase;
@ -126,6 +128,11 @@ class Filter extends WidgetBase
$checked = post('value') == 'true' ? true : false; $checked = post('value') == 'true' ? true : false;
$this->setScopeValue($scope, $checked); $this->setScopeValue($scope, $checked);
break; break;
case 'switch':
$value = post('value');
$this->setScopeValue($scope, $value);
break;
} }
/* /*
@ -179,12 +186,12 @@ class Filter extends WidgetBase
*/ */
protected function getAvailableOptions($scope, $searchQuery = null) protected function getAvailableOptions($scope, $searchQuery = null)
{ {
if (count($scope->options)) { if ($scope->options) {
return $scope->options; return $this->getOptionsFromArray($scope, $searchQuery);
} }
$available = []; $available = [];
$nameColumn = $this->getScopeNameColumn($scope); $nameColumn = $this->getScopeNameFrom($scope);
$options = $this->getOptionsFromModel($scope, $searchQuery); $options = $this->getOptionsFromModel($scope, $searchQuery);
foreach ($options as $option) { foreach ($options as $option) {
$available[$option->getKey()] = $option->{$nameColumn}; $available[$option->getKey()] = $option->{$nameColumn};
@ -216,6 +223,7 @@ class Filter extends WidgetBase
/** /**
* Looks at the model for defined scope items. * Looks at the model for defined scope items.
* @return Collection
*/ */
protected function getOptionsFromModel($scope, $searchQuery = null) protected function getOptionsFromModel($scope, $searchQuery = null)
{ {
@ -232,10 +240,97 @@ class Filter extends WidgetBase
return $query->get(); return $query->get();
} }
$searchFields = [$model->getKeyName(), $this->getScopeNameColumn($scope)]; $searchFields = [$model->getKeyName(), $this->getScopeNameFrom($scope)];
return $query->searchWhere($searchQuery, $searchFields)->get(); return $query->searchWhere($searchQuery, $searchFields)->get();
} }
/**
* Look at the defined set of options for scope items, or the model method.
* @return array
*/
protected function getOptionsFromArray($scope, $searchQuery = null)
{
/*
* Load the data
*/
$options = $scope->options;
if (is_scalar($options)) {
$model = $this->scopeModels[$scope->scopeName];
$methodName = $options;
if (!$model->methodExists($methodName)) {
throw new ApplicationException(Lang::get(
'backend::lang.filter.options_method_not_exists',
['model'=>get_class($model), 'method'=>$methodName, 'filter'=>$scope->scopeName]
));
}
$options = $model->$methodName();
}
elseif (!is_array($options)) {
$options = [];
}
/*
* Apply the search
*/
$searchQuery = Str::lower($searchQuery);
if (strlen($searchQuery)) {
$options = $this->filterOptionsBySearch($options, $searchQuery);
}
return $options;
}
/**
* Filters an array of options by a search term.
* @param array $options
* @param string $query
* @return array
*/
protected function filterOptionsBySearch($options, $query)
{
$filteredOptions = [];
$optionMatchesSearch = function($words, $option) {
foreach ($words as $word) {
$word = trim($word);
if (!strlen($word)) {
continue;
}
if (!Str::contains(Str::lower($option), $word)) {
return false;
}
}
return true;
};
/*
* Exact
*/
foreach ($options as $index => $option) {
if (Str::is(Str::lower($option), $query)) {
$filteredOptions[$index] = $option;
unset($options[$index]);
}
}
/*
* Fuzzy
*/
$words = explode(' ', $query);
foreach ($options as $index => $option) {
if ($optionMatchesSearch($words, $option)) {
$filteredOptions[$index] = $option;
}
}
return $filteredOptions;
}
/** /**
* Creates a flat array of filter scopes from the configuration. * Creates a flat array of filter scopes from the configuration.
*/ */
@ -362,6 +457,15 @@ class Filter extends WidgetBase
* Condition * Condition
*/ */
if ($scopeConditions = $scope->conditions) { if ($scopeConditions = $scope->conditions) {
/*
* Switch scope: multiple conditions, value either 1 or 2
*/
if (is_array($scopeConditions)) {
$conditionNum = is_array($value) ? 0 : $value - 1;
list($scopeConditions) = array_slice($scopeConditions, $conditionNum);
}
if (is_array($value)) { if (is_array($value)) {
$filtered = implode(',', array_build($value, function ($key, $_value) { $filtered = implode(',', array_build($value, function ($key, $_value) {
return [$key, Db::getPdo()->quote($_value)]; return [$key, Db::getPdo()->quote($_value)];
@ -444,7 +548,7 @@ class Filter extends WidgetBase
* @param string $scope * @param string $scope
* @return string * @return string
*/ */
public function getScopeNameColumn($scope) public function getScopeNameFrom($scope)
{ {
if (is_string($scope)) { if (is_string($scope)) {
$scope = $this->getScope($scope); $scope = $this->getScope($scope);

View File

@ -0,0 +1,7 @@
<!-- Switch scope -->
<div
class="filter-scope checkbox custom-checkbox is-indeterminate"
data-scope-name="<?= $scope->scopeName ?>">
<input type="checkbox" id="<?= $scope->getId() ?>" data-checked="<?= $scope->value ?: '0' ?>" />
<label for="<?= $scope->getId() ?>"><?= e(trans($scope->label)) ?></label>
</div>

View File

@ -1,6 +1,7 @@
<?php <?php
$fieldOptions = $field->options(); $fieldOptions = $field->options();
$checkedValues = (array) $field->value; $checkedValues = (array) $field->value;
$isScrollable = count($fieldOptions) > 10;
?> ?>
<!-- Checkbox List --> <!-- Checkbox List -->
<?php if ($this->previewMode && $field->value): ?> <?php if ($this->previewMode && $field->value): ?>
@ -34,8 +35,8 @@
<?php elseif (!$this->previewMode && count($fieldOptions)): ?> <?php elseif (!$this->previewMode && count($fieldOptions)): ?>
<div class="field-checkboxlist"> <div class="field-checkboxlist <?= $isScrollable ? 'is-scrollable' : '' ?>">
<?php if (count($fieldOptions) > 10): ?> <?php if ($isScrollable): ?>
<!-- Quick selection --> <!-- Quick selection -->
<small> <small>
<?= e(trans('backend::lang.form.select')) ?>: <?= e(trans('backend::lang.form.select')) ?>:
@ -76,7 +77,7 @@
</div> </div>
<?php endforeach ?> <?php endforeach ?>
<?php if (count($fieldOptions) > 10): ?> <?php if ($isScrollable): ?>
</div> </div>
</div> </div>
<?php endif ?> <?php endif ?>

View File

@ -322,7 +322,7 @@ class TemplateList extends WidgetBase
return true; return true;
} }
protected function itemContainsWord($word, $item , $exact = false) protected function itemContainsWord($word, $item, $exact = false)
{ {
$operator = $exact ? 'is' : 'contains'; $operator = $exact ? 'is' : 'contains';

View File

@ -24,4 +24,68 @@
} }
}) })
//
// Intermediate checkboxes
//
$(document).render(function() {
$('div.custom-checkbox.is-indeterminate > input').each(function() {
var $el = $(this),
checked = $el.data('checked')
switch (checked) {
// Unchecked
case 1:
$el.prop('indeterminate', true)
break
// Checked
case 2:
$el.prop('indeterminate', false)
$el.prop('checked', true)
break
// Unchecked
default:
$el.prop('indeterminate', false)
$el.prop('checked', false)
}
})
})
$(document).on('click', 'div.custom-checkbox.is-indeterminate > label', function() {
var $el = $(this).parent().find('input:first'),
checked = $el.data('checked')
if (checked === undefined) {
checked = $el.is(':checked') ? 1 : 0
}
switch (checked) {
// Unchecked, going indeterminate
case 0:
$el.data('checked', 1)
$el.prop('indeterminate', true)
break
// Indeterminate, going checked
case 1:
$el.data('checked', 2)
$el.prop('indeterminate', false)
$el.prop('checked', true)
break
// Checked, going unchecked
default:
$el.data('checked', 0)
$el.prop('indeterminate', false)
$el.prop('checked', false)
}
$el.trigger('change')
return false
})
})(jQuery); })(jQuery);

View File

@ -82,14 +82,14 @@
var self = this var self = this
this.$el.on('change', '.filter-scope input[type="checkbox"]', function(){ this.$el.on('change', '.filter-scope input[type="checkbox"]', function(){
var isChecked = $(this).is(':checked'), var $scope = $(this).closest('.filter-scope')
$scope = $(this).closest('.filter-scope'),
scopeName = $scope.data('scope-name')
self.scopeValues[scopeName] = isChecked if ($scope.hasClass('is-indeterminate')) {
self.checkboxToggle(scopeName, isChecked) self.switchToggle($(this))
}
$scope.toggleClass('active', isChecked) else {
self.checkboxToggle($(this))
}
}) })
$('.filter-scope input[type="checkbox"]', this.$el).each(function() { $('.filter-scope input[type="checkbox"]', this.$el).each(function() {
@ -351,22 +351,54 @@
}) })
} }
FilterWidget.prototype.checkboxToggle = function(scopeName, isChecked) { FilterWidget.prototype.checkboxToggle = function($el) {
if (!this.options.updateHandler) var isChecked = $el.is(':checked'),
return $scope = $el.closest('.filter-scope'),
scopeName = $scope.data('scope-name')
var $form = this.$el.closest('form'), this.scopeValues[scopeName] = isChecked
data = {
scopeName: scopeName,
value: isChecked
}
$.oc.stripeLoadIndicator.show() if (this.options.updateHandler) {
$form.request(this.options.updateHandler, { var $form = this.$el.closest('form'),
data: data data = {
}).always(function(){ scopeName: scopeName,
$.oc.stripeLoadIndicator.hide() value: isChecked
}) }
$.oc.stripeLoadIndicator.show()
$form.request(this.options.updateHandler, {
data: data
}).always(function(){
$.oc.stripeLoadIndicator.hide()
})
}
$scope.toggleClass('active', isChecked)
}
FilterWidget.prototype.switchToggle = function($el) {
var switchValue = $el.data('checked'),
$scope = $el.closest('.filter-scope'),
scopeName = $scope.data('scope-name')
this.scopeValues[scopeName] = switchValue
if (this.options.updateHandler) {
var $form = this.$el.closest('form'),
data = {
scopeName: scopeName,
value: switchValue
}
$.oc.stripeLoadIndicator.show()
$form.request(this.options.updateHandler, {
data: data
}).always(function(){
$.oc.stripeLoadIndicator.hide()
})
}
$scope.toggleClass('active', !!switchValue)
} }

View File

@ -71,7 +71,7 @@
top: 0; top: 0;
background-color: #FFFFFF; background-color: #FFFFFF;
border: 1px solid @color-checkbox-border; border: 1px solid @color-checkbox-border;
.box-shadow(~"inset 0 1px 0 @{input-border}, 0 1px 0 #fff"); .box-shadow(~"inset 0 1px 0 @{input-border}, 0 1px 0 rgba(255,255,255,.5)");
} }
&:hover:before { &:hover:before {
border-color: darken(@color-checkbox-border, 10%); border-color: darken(@color-checkbox-border, 10%);
@ -123,8 +123,8 @@
} }
} }
input[type=checkbox]:indeterminate + label:before,
input[type=checkbox]:checked + label:before { input[type=checkbox]:checked + label:before {
.icon(@check);
border-color: @color-checkbox-checked; border-color: @color-checkbox-checked;
background-color: @color-checkbox-checked; background-color: @color-checkbox-checked;
font-size: 12px; font-size: 12px;
@ -133,6 +133,22 @@
.box-shadow(none); .box-shadow(none);
} }
input[type=checkbox]:checked + label:before {
.icon(@check);
}
input[type=checkbox]:indeterminate + label:before {
.icon(@minus);
}
input:disabled + label:before {
border: 1px solid @color-checkbox-border !important;
}
input:disabled:checked + label:before {
background-color: #999;
}
&:focus { &:focus {
outline: none; outline: none;
label:before { label:before {

View File

@ -79,10 +79,6 @@
label { label {
padding-left: 25px; padding-left: 25px;
&:before {
top: -1px;
}
} }
&:after { &:after {
@ -116,6 +112,7 @@
border: none; border: none;
border-bottom: 1px solid @color-filter-border; border-bottom: 1px solid @color-filter-border;
.border-bottom-radius(0); .border-bottom-radius(0);
.box-shadow(none);
background-color: transparent; background-color: transparent;
} }
@ -159,7 +156,7 @@
} }
.filter-items { .filter-items {
height: 100px; max-height: 135px;
overflow: auto; overflow: auto;
background-color: @color-filter-items-bg; background-color: @color-filter-items-bg;
@ -191,7 +188,7 @@
@media (max-width: @screen-xs) { @media (max-width: @screen-xs) {
.control-filter-popover { .control-filter-popover {
.filter-items { .filter-items {
height: 200px; max-height: 200px;
} }
.filter-search { .filter-search {
input { input {

View File

@ -153,6 +153,10 @@
margin-top: -5px; margin-top: -5px;
} }
&.field-align-above {
margin-top: -5px;
}
&.field-slim { &.field-slim {
&.span-left, &.span-right { &.span-left, &.span-right {
width: 50%; width: 50%;
@ -287,18 +291,25 @@
&.size-giant { min-height: @size-giant; } &.size-giant { min-height: @size-giant; }
} }
.field-checkboxlist { .field-checkboxlist:not(.is-scrollable) {
padding: 20px 20px 2px 20px; padding: 20px 20px 2px 20px;
.border-radius(@border-radius-base); .border-radius(@border-radius-base);
background: @color-form-checkboxlist-background; background: @color-form-checkboxlist-background;
border: 1px solid @color-form-checkboxlist-border;
.checkbox:last-of-type { //.checkbox:last-of-type {
margin-bottom: 0; // margin-bottom: 0;
//}
}
.field-checkboxlist.is-scrollable {
small {
color: @text-muted;
} }
} }
.field-checkboxlist-scrollable { .field-checkboxlist-scrollable {
background: white; background: @color-form-checkboxlist-background;
border: 1px solid @color-form-checkboxlist-border; border: 1px solid @color-form-checkboxlist-border;
padding-left: 15px; padding-left: 15px;
height: @size-large + 100; height: @size-large + 100;

View File

@ -1925,7 +1925,29 @@ return
$cb.get(0).checked=!$cb.get(0).checked $cb.get(0).checked=!$cb.get(0).checked
$cb.data('oc-space-timestamp',e.timeStamp) $cb.data('oc-space-timestamp',e.timeStamp)
$cb.trigger('change') $cb.trigger('change')
return false}})})(jQuery);+function($){"use strict";var BalloonSelector=function(element,options){this.$el=$(element) return false}})
$(document).render(function(){$('div.custom-checkbox.is-indeterminate > input').each(function(){var $el=$(this),checked=$el.data('checked')
switch(checked){case 1:$el.prop('indeterminate',true)
break
case 2:$el.prop('indeterminate',false)
$el.prop('checked',true)
break
default:$el.prop('indeterminate',false)
$el.prop('checked',false)}})})
$(document).on('click','div.custom-checkbox.is-indeterminate > label',function(){var $el=$(this).parent().find('input:first'),checked=$el.data('checked')
if(checked===undefined){checked=$el.is(':checked')?1:0}
switch(checked){case 0:$el.data('checked',1)
$el.prop('indeterminate',true)
break
case 1:$el.data('checked',2)
$el.prop('indeterminate',false)
$el.prop('checked',true)
break
default:$el.data('checked',0)
$el.prop('indeterminate',false)
$el.prop('checked',false)}
$el.trigger('change')
return false})})(jQuery);+function($){"use strict";var BalloonSelector=function(element,options){this.$el=$(element)
this.$field=$('input',this.$el) this.$field=$('input',this.$el)
this.options=options||{};var self=this;$('li',this.$el).click(function(){if(self.$el.hasClass('control-disabled')) this.options=options||{};var self=this;$('li',this.$el).click(function(){if(self.$el.hasClass('control-disabled'))
return return
@ -2076,10 +2098,9 @@ FilterWidget.prototype.getPopoverTemplate=function(){return'
</form> \ </form> \
'} '}
FilterWidget.prototype.init=function(){var self=this FilterWidget.prototype.init=function(){var self=this
this.$el.on('change','.filter-scope input[type="checkbox"]',function(){var isChecked=$(this).is(':checked'),$scope=$(this).closest('.filter-scope'),scopeName=$scope.data('scope-name') this.$el.on('change','.filter-scope input[type="checkbox"]',function(){var $scope=$(this).closest('.filter-scope')
self.scopeValues[scopeName]=isChecked if($scope.hasClass('is-indeterminate')){self.switchToggle($(this))}
self.checkboxToggle(scopeName,isChecked) else{self.checkboxToggle($(this))}})
$scope.toggleClass('active',isChecked)})
$('.filter-scope input[type="checkbox"]',this.$el).each(function(){$(this).closest('.filter-scope').toggleClass('active',$(this).is(':checked'))}) $('.filter-scope input[type="checkbox"]',this.$el).each(function(){$(this).closest('.filter-scope').toggleClass('active',$(this).is(':checked'))})
this.$el.on('click','a.filter-scope',function(){var $scope=$(this),scopeName=$scope.data('scope-name') this.$el.on('click','a.filter-scope',function(){var $scope=$(this),scopeName=$scope.data('scope-name')
if($scope.hasClass('filter-scope-open'))return if($scope.hasClass('filter-scope-open'))return
@ -2166,11 +2187,18 @@ return
var $form=this.$el.closest('form'),data={scopeName:scopeName,options:this.scopeValues[scopeName]} var $form=this.$el.closest('form'),data={scopeName:scopeName,options:this.scopeValues[scopeName]}
$.oc.stripeLoadIndicator.show() $.oc.stripeLoadIndicator.show()
$form.request(this.options.updateHandler,{data:data}).always(function(){$.oc.stripeLoadIndicator.hide()})} $form.request(this.options.updateHandler,{data:data}).always(function(){$.oc.stripeLoadIndicator.hide()})}
FilterWidget.prototype.checkboxToggle=function(scopeName,isChecked){if(!this.options.updateHandler) FilterWidget.prototype.checkboxToggle=function($el){var isChecked=$el.is(':checked'),$scope=$el.closest('.filter-scope'),scopeName=$scope.data('scope-name')
return this.scopeValues[scopeName]=isChecked
var $form=this.$el.closest('form'),data={scopeName:scopeName,value:isChecked} if(this.options.updateHandler){var $form=this.$el.closest('form'),data={scopeName:scopeName,value:isChecked}
$.oc.stripeLoadIndicator.show() $.oc.stripeLoadIndicator.show()
$form.request(this.options.updateHandler,{data:data}).always(function(){$.oc.stripeLoadIndicator.hide()})} $form.request(this.options.updateHandler,{data:data}).always(function(){$.oc.stripeLoadIndicator.hide()})}
$scope.toggleClass('active',isChecked)}
FilterWidget.prototype.switchToggle=function($el){var switchValue=$el.data('checked'),$scope=$el.closest('.filter-scope'),scopeName=$scope.data('scope-name')
this.scopeValues[scopeName]=switchValue
if(this.options.updateHandler){var $form=this.$el.closest('form'),data={scopeName:scopeName,value:switchValue}
$.oc.stripeLoadIndicator.show()
$form.request(this.options.updateHandler,{data:data}).always(function(){$.oc.stripeLoadIndicator.hide()})}
$scope.toggleClass('active',!!switchValue)}
var old=$.fn.filterWidget var old=$.fn.filterWidget
$.fn.filterWidget=function(option){var args=arguments,result $.fn.filterWidget=function(option){var args=arguments,result
this.each(function(){var $this=$(this) this.each(function(){var $this=$(this)

View File

@ -2348,7 +2348,7 @@ html.cssanimations .cursor-loading-indicator.hide{display:none}
.custom-checkbox,.custom-radio{padding-left:23px;margin-top:0} .custom-checkbox,.custom-radio{padding-left:23px;margin-top:0}
.custom-checkbox input[type=radio],.custom-radio input[type=radio],.custom-checkbox input[type=checkbox],.custom-radio input[type=checkbox]{display:none} .custom-checkbox input[type=radio],.custom-radio input[type=radio],.custom-checkbox input[type=checkbox],.custom-radio input[type=checkbox]{display:none}
.custom-checkbox label,.custom-radio label{display:inline-block;cursor:pointer;position:relative;padding-left:25px;margin-right:15px;margin-left:-20px;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} .custom-checkbox label,.custom-radio label{display:inline-block;cursor:pointer;position:relative;padding-left:25px;margin-right:15px;margin-left:-20px;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
.custom-checkbox label:before,.custom-radio label:before{content:"";display:inline-block;text-align:center;color:#ffffff;width:18px;height:18px;margin-right:15px;position:absolute;left:-3px;top:0;background-color:#FFFFFF;border:1px solid #bdc3c7;-webkit-box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff;box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff} .custom-checkbox label:before,.custom-radio label:before{content:"";display:inline-block;text-align:center;color:#ffffff;width:18px;height:18px;margin-right:15px;position:absolute;left:-3px;top:0;background-color:#FFFFFF;border:1px solid #bdc3c7;-webkit-box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 rgba(255,255,255,.5);box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 rgba(255,255,255,.5)}
.custom-checkbox label:hover:before,.custom-radio label:hover:before{border-color:#a1aab0} .custom-checkbox label:hover:before,.custom-radio label:hover:before{border-color:#a1aab0}
.custom-checkbox label:active:before,.custom-radio label:active:before{border-color:#869198;border-width:2px} .custom-checkbox label:active:before,.custom-radio label:active:before{border-color:#869198;border-width:2px}
.custom-checkbox input[type=radio]:checked + label:before,.custom-radio input[type=radio]:checked + label:before{border-color:#1f99dc;line-height:17px;border-width:2px} .custom-checkbox input[type=radio]:checked + label:before,.custom-radio input[type=radio]:checked + label:before{border-color:#1f99dc;line-height:17px;border-width:2px}
@ -2357,7 +2357,11 @@ html.cssanimations .cursor-loading-indicator.hide{display:none}
.custom-checkbox input[type=radio][data-radio-color=green]:checked + label:after,.custom-radio input[type=radio][data-radio-color=green]:checked + label:after{background-color:#76a544} .custom-checkbox input[type=radio][data-radio-color=green]:checked + label:after,.custom-radio input[type=radio][data-radio-color=green]:checked + label:after{background-color:#76a544}
.custom-checkbox input[type=radio][data-radio-color=red]:checked + label:before,.custom-radio input[type=radio][data-radio-color=red]:checked + label:before{border-color:#bb2424} .custom-checkbox input[type=radio][data-radio-color=red]:checked + label:before,.custom-radio input[type=radio][data-radio-color=red]:checked + label:before{border-color:#bb2424}
.custom-checkbox input[type=radio][data-radio-color=red]:checked + label:after,.custom-radio input[type=radio][data-radio-color=red]:checked + label:after{background-color:#bb2424} .custom-checkbox input[type=radio][data-radio-color=red]:checked + label:after,.custom-radio input[type=radio][data-radio-color=red]:checked + label:after{background-color:#bb2424}
.custom-checkbox input[type=checkbox]:checked + label:before,.custom-radio input[type=checkbox]:checked + label:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f00c";border-color:#1f99dc;background-color:#1f99dc;font-size:12px;line-height:17px;border-width:2px;-webkit-box-shadow:none;box-shadow:none} .custom-checkbox input[type=checkbox]:indeterminate + label:before,.custom-radio input[type=checkbox]:indeterminate + label:before,.custom-checkbox input[type=checkbox]:checked + label:before,.custom-radio input[type=checkbox]:checked + label:before{border-color:#1f99dc;background-color:#1f99dc;font-size:12px;line-height:17px;border-width:2px;-webkit-box-shadow:none;box-shadow:none}
.custom-checkbox input[type=checkbox]:checked + label:before,.custom-radio input[type=checkbox]:checked + label:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f00c"}
.custom-checkbox input[type=checkbox]:indeterminate + label:before,.custom-radio input[type=checkbox]:indeterminate + label:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f068"}
.custom-checkbox input:disabled + label:before,.custom-radio input:disabled + label:before{border:1px solid #bdc3c7 !important}
.custom-checkbox input:disabled:checked + label:before,.custom-radio input:disabled:checked + label:before{background-color:#999}
.custom-checkbox:focus,.custom-radio:focus{outline:none} .custom-checkbox:focus,.custom-radio:focus{outline:none}
.custom-checkbox:focus label:before,.custom-radio:focus label:before{border-color:#3498db} .custom-checkbox:focus label:before,.custom-radio:focus label:before{border-color:#3498db}
.custom-checkbox p.help-block,.custom-radio p.help-block{padding-left:6px;margin-bottom:17px} .custom-checkbox p.help-block,.custom-radio p.help-block{padding-left:6px;margin-bottom:17px}
@ -2409,6 +2413,7 @@ html.cssanimations .cursor-loading-indicator.hide{display:none}
.form-group.checkbox-field{padding-bottom:5px} .form-group.checkbox-field{padding-bottom:5px}
.form-group.number-field > .form-control{text-align:right} .form-group.number-field > .form-control{text-align:right}
.form-group.checkbox-align{padding-left:28px;margin-top:-5px} .form-group.checkbox-align{padding-left:28px;margin-top:-5px}
.form-group.field-align-above{margin-top:-5px}
.form-group.field-slim.span-left,.form-group.field-slim.span-right{width:50%} .form-group.field-slim.span-left,.form-group.field-slim.span-right{width:50%}
.form-group.field-indent{padding-left:23px} .form-group.field-indent{padding-left:23px}
.form-group.input-sidebar-control{padding-right:35px} .form-group.input-sidebar-control{padding-right:35px}
@ -2438,9 +2443,9 @@ html.cssanimations .cursor-loading-indicator.hide{display:none}
.field-textarea.size-large{min-height:200px} .field-textarea.size-large{min-height:200px}
.field-textarea.size-huge{min-height:250px} .field-textarea.size-huge{min-height:250px}
.field-textarea.size-giant{min-height:350px} .field-textarea.size-giant{min-height:350px}
.field-checkboxlist{padding:20px 20px 2px 20px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background:#ffffff} .field-checkboxlist:not(.is-scrollable){padding:20px 20px 2px 20px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background:#ffffff;border:1px solid #e2e2e2}
.field-checkboxlist .checkbox:last-of-type{margin-bottom:0} .field-checkboxlist.is-scrollable small{color:#999999}
.field-checkboxlist-scrollable{background:white;border:1px solid #e2e2e2;padding-left:15px;height:300px} .field-checkboxlist-scrollable{background:#ffffff;border:1px solid #e2e2e2;padding-left:15px;height:300px}
.field-checkboxlist-scrollable .checkbox{margin-top:15px;margin-bottom:5px} .field-checkboxlist-scrollable .checkbox{margin-top:15px;margin-bottom:5px}
.field-checkboxlist-scrollable .checkbox ~ .checkbox{margin-top:0} .field-checkboxlist-scrollable .checkbox ~ .checkbox{margin-top:0}
.field-recordfinder{background-color:#ffffff;border:1px solid #bdc3c7;overflow:hidden;position:relative;-webkit-box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff;box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .field-recordfinder{background-color:#ffffff;border:1px solid #bdc3c7;overflow:hidden;position:relative;-webkit-box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff;box-shadow:inset 0 1px 0 #bdc3c7,0 1px 0 #fff;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
@ -2753,14 +2758,13 @@ ul.autocomplete.dropdown-menu.inspector-autocomplete li a{padding:5px 12px;white
.control-filter > .filter-scope.checkbox{padding-left:35px} .control-filter > .filter-scope.checkbox{padding-left:35px}
.control-filter > .filter-scope.checkbox,.control-filter > .filter-scope.checkbox label{margin-bottom:0} .control-filter > .filter-scope.checkbox,.control-filter > .filter-scope.checkbox label{margin-bottom:0}
.control-filter > .filter-scope.checkbox label{padding-left:25px} .control-filter > .filter-scope.checkbox label{padding-left:25px}
.control-filter > .filter-scope.checkbox label:before{top:-1px}
.control-filter > .filter-scope.checkbox:after{content:''} .control-filter > .filter-scope.checkbox:after{content:''}
.control-filter > .filter-scope:hover,.control-filter > .filter-scope.active,.control-filter > .filter-scope:hover.custom-checkbox label,.control-filter > .filter-scope.active.custom-checkbox label{color:#000000} .control-filter > .filter-scope:hover,.control-filter > .filter-scope.active,.control-filter > .filter-scope:hover.custom-checkbox label,.control-filter > .filter-scope.active.custom-checkbox label{color:#000000}
.control-filter > .filter-scope:hover .filter-label,.control-filter > .filter-scope.active .filter-label{color:#000000} .control-filter > .filter-scope:hover .filter-label,.control-filter > .filter-scope.active .filter-label{color:#000000}
.control-filter > .filter-scope:hover.active .filter-setting,.control-filter > .filter-scope.active.active .filter-setting{background-color:#5f9a4c} .control-filter > .filter-scope:hover.active .filter-setting,.control-filter > .filter-scope.active.active .filter-setting{background-color:#5f9a4c}
.control-filter-popover{min-width:275px} .control-filter-popover{min-width:275px}
.control-filter-popover .filter-search{min-height:36px} .control-filter-popover .filter-search{min-height:36px}
.control-filter-popover .filter-search input{min-height:36px;border:none;border-bottom:1px solid #d7dbdd;border-bottom-right-radius:0;border-bottom-left-radius:0;background-color:transparent} .control-filter-popover .filter-search input{min-height:36px;border:none;border-bottom:1px solid #d7dbdd;border-bottom-right-radius:0;border-bottom-left-radius:0;-webkit-box-shadow:none;box-shadow:none;background-color:transparent}
.control-filter-popover .filter-search .form-control.icon.search{background-position:right -81px} .control-filter-popover .filter-search .form-control.icon.search{background-position:right -81px}
.control-filter-popover .filter-search .close{display:none} .control-filter-popover .filter-search .close{display:none}
.control-filter-popover .filter-items,.control-filter-popover .filter-active-items{color:rgba(0,0,0,0.6);font-size:13px} .control-filter-popover .filter-items,.control-filter-popover .filter-active-items{color:rgba(0,0,0,0.6);font-size:13px}
@ -2769,14 +2773,14 @@ ul.autocomplete.dropdown-menu.inspector-autocomplete li a{padding:5px 12px;white
.control-filter-popover .filter-items a,.control-filter-popover .filter-active-items a{text-decoration:none;color:rgba(0,0,0,0.6);display:block;padding:7px 15px} .control-filter-popover .filter-items a,.control-filter-popover .filter-active-items a{text-decoration:none;color:rgba(0,0,0,0.6);display:block;padding:7px 15px}
.control-filter-popover .filter-items a:before,.control-filter-popover .filter-active-items a:before{margin-right:8px;display:inline-block;vertical-align:baseline} .control-filter-popover .filter-items a:before,.control-filter-popover .filter-active-items a:before{margin-right:8px;display:inline-block;vertical-align:baseline}
.control-filter-popover .filter-items a:hover,.control-filter-popover .filter-active-items a:hover{background-color:#4da7e8;color:#FFFFFF} .control-filter-popover .filter-items a:hover,.control-filter-popover .filter-active-items a:hover{background-color:#4da7e8;color:#FFFFFF}
.control-filter-popover .filter-items{height:100px;overflow:auto;background-color:#fafafa;border-bottom:1px solid #d7dbdd} .control-filter-popover .filter-items{max-height:135px;overflow:auto;background-color:#fafafa;border-bottom:1px solid #d7dbdd}
.control-filter-popover .filter-items a:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f067"} .control-filter-popover .filter-items a:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f067"}
.control-filter-popover .filter-items li.loading{padding:7px} .control-filter-popover .filter-items li.loading{padding:7px}
.control-filter-popover .filter-items li.loading > span{display:block;height:20px;width:20px;background-image:url('images/loader-transparent.svg');background-size:20px 20px;background-position:50% 50%;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite} .control-filter-popover .filter-items li.loading > span{display:block;height:20px;width:20px;background-image:url('images/loader-transparent.svg');background-size:20px 20px;background-position:50% 50%;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}
.control-filter-popover .filter-items li.animate-enter{-webkit-animation:fadeInUp 0.5s;animation:fadeInUp 0.5s} .control-filter-popover .filter-items li.animate-enter{-webkit-animation:fadeInUp 0.5s;animation:fadeInUp 0.5s}
.control-filter-popover .filter-active-items a:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f00d"} .control-filter-popover .filter-active-items a:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f00d"}
.control-filter-popover .filter-active-items li.animate-enter{-webkit-animation:fadeInDown 0.5s;animation:fadeInDown 0.5s} .control-filter-popover .filter-active-items li.animate-enter{-webkit-animation:fadeInDown 0.5s;animation:fadeInDown 0.5s}
@media (max-width:480px){.control-filter-popover .filter-items{height:200px} @media (max-width:480px){.control-filter-popover .filter-items{max-height:200px}
.control-filter-popover .filter-search input{padding-left:36px;padding-right:36px} .control-filter-popover .filter-search input{padding-left:36px;padding-right:36px}
.control-filter-popover .filter-search .form-control.icon.search{background-position:0 -81px} .control-filter-popover .filter-search .form-control.icon.search{background-position:0 -81px}
.control-filter-popover .filter-search .close{width:30px;display:block;position:absolute;top:5px;right:5px;font-size:28px;z-index:2} .control-filter-popover .filter-search .close{width:30px;display:block;position:absolute;top:5px;right:5px;font-size:28px;z-index:2}