import {Component} from 'angular2/core';
import {
FORM_DIRECTIVES, FormBuilder, ControlGroup, ControlArray, Validators, NgForm, Control,
AbstractControl
} from 'angular2/common';
@Component({
selector: 'my-app',
templateUrl:'app/template_rule.html',
directives: [FORM_DIRECTIVES]
})
export class AppComponent {
userForm: ControlGroup;
constructor(private fb: FormBuilder) {
this.userForm = fb.group({
rules_list: new ControlArray([])
});
this.rules_list();
}
rules_list(){
this.userForm.controls['rules_list'].push(this.fb.group({
select_state: this.fb.control("",Validators.required),
rules: this.fb.control("", Validators.required),
pass_state: this.fb.control("", Validators.required),
fail_state: this.fb.control("", Validators.required)
}));
}
removeRules(ctrl) {
let rulesLists = (<Array>(<ControlGroup>this.userForm.controls['rules_list']).controls);
for(var i = 0; i < rulesLists.length; i++) {
console.log("each rules", ctrl);
if(rulesLists[i] == ctrl) {
console.log("rules to remove", rulesLists[i]);
rulesLists.splice(i, 1);
(<ControlGroup>this.userForm.controls['rules_list']).updateValueAndValidity();
break;
}
}
}
submitRules() {
console.log(this.userForm.value)
}
}
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
bootstrap(AppComponent);
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<!DOCTYPE html>
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/fontawesome/4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="query-builder.default.css">
<link rel="stylesheet" href="bootstrap-select.css">
<link rel="stylesheet" href="bootstrap-datepicker.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- 1. Load libraries -->
<!-- IE required polyfills, in this exact order -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system-polyfills.js"></script>
<script src="https://npmcdn.com/angular2@2.0.0-beta.15/es6/dev/src/testing/shims_for_IE.js"></script>
<script src="query-builder.standalone.js"></script>
<script src="bootstrap-datepicker.js"></script>
<script src="moment.js"></script>
<script src="bootbox.js"></script>
<script src="bootstrap-select.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.15/angular2-polyfills.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.26/system.js"></script>
<script src="https://npmcdn.com/typescript@1.8.10/lib/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.15/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.15/angular2.dev.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true },
packages: {'app': {defaultExtension: 'ts'}}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
<button type="button" class="btn btn-success fa fa-plus-circle" (click)="rules_list()"></button>
<div class="container">
<form class="form-inline" [ngFormModel]="userForm" >
<ul>
<li *ngFor="#ctrl of userForm.controls['rules_list'].controls; #i = index" [ngFormModel]="ctrl">
<blockquote> Rule : {{i}}</blockquote>
<div class="form-group">
<label>Select State:</label>
<select ngControl="select_state" #select_state="ngForm" class="form-control btn btn-primary">
<option>State1</option>
<option>State2</option>
<option>State3</option>
<option>State4</option>
</select>
<div class='error' *ngIf="select_state.control.touched">
<div *ngIf="select_state.control.hasError('required')">Please Select a State</div>
</div>
</div>
<label>Rule:</label>
<div class="form-group btn btn-warning" style="padding: 2px;">
<input ngControl="rules" class="form-control" #rules="ngForm" data-toggle="modal" data-target="#myModal" type="text" style="width: 171px !important;">
<div class="error" *ngIf="rules.control.touched">
<div *ngIf="rules.control.hasError('required')">Please Select a Rule</div>
</div>
</div>
<div class="form-group" style="padding-left: 11px">
<label>Pass State :</label>
<select ngControl="pass_state" #pass_state="ngForm" class="form-control btn btn-success">
<option>State1</option>
<option>State2</option>
<option>State3</option>
<option>State4</option>
</select>
<div class="error" *ngIf="pass_state.control.touched">
<div *ngIf="pass_state.control.hasError('required')">Please Select a Pass State</div>
</div>
</div>
<div class="form-group" style="padding-left: 14px;">
<label>Fail State:</label>
<select ngControl="fail_state" #fail_state="ngForm" class="form-control btn btn-danger">
<option>State1</option>
<option>State2</option>
<option>State3</option>
<option>State4</option>
</select>
<div class="error" *ngIf="fail_state.control.touched">
<div *ngIf="fail_state.control.hasError('required')">Please Select a Pass State</div>
</div>
</div>
<button type="button" class="btn btn-danger fa fa-minus-circle" (click)="removeRules(ctrl)" style="margin-left: 29px;"></button>
</li>
</ul>
<br />
<button type="button" class="btn btn-success" [disabled]='!userForm.valid' (click)="submitRules()">Submit</button>
<br />
<br />
<br />
{{ userForm.value|json }}
<p>Valid?: {{userForm.valid}}</p>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Rules Configuration</h4>
</div>
<div class="modal-body">
<!--Query Builder Starts-->
<div class="container">
<div class="col-md-12 col-lg-10 col-lg-offset-1">
<div id="builder"></div>
<div class="btn-group">
<button class="btn btn-danger reset">Reset</button>
</div>
<div class="btn-group">
<button class="btn btn-primary parse-json">Rule Definition</button>
<button class="btn btn-primary parse-sql" data-stmt="false">Rule</button>
</div>
</div>
</div>
<!--Query Builder Ends-->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
$('[data-toggle="tooltip"]').tooltip();
var $b = $('#builder');
var options = {
allow_empty: true,
// default_filter: 'name',
sort_filters: true,
optgroups: {
core: {
en: 'Core',
fr: 'Coeur'
}
},
plugins: {
'bt-tooltip-errors': { delay: 100 },
'sortable': null,
'filter-description': { mode: 'bootbox' },
'bt-selectpicker': null,
'unique-filter': null,
'bt-checkbox': { color: 'primary' },
'invert': null
},
filters: [{
id: 'employeeid',
label: 'Employee Id',
type: 'integer',
},
{
id: 'employeename',
label: 'Employee Name',
type: 'string'
}, {
id: 'salary',
label: 'Salary',
type: 'integer'
}, {
id: 'doj',
label: 'DOJ',
type: 'date',
validation: {
format: 'YYYY/MM/DD'
},
plugin: 'datepicker',
plugin_config: {
format: 'yyyy/mm/dd',
todayBtn: 'linked',
todayHighlight: true,
autoclose: true
}
}],
rules: {
"condition": "and",
"rules": [
{
"id": "employeename",
"field": "name",
"type": "string",
"input": "text",
"operator": "equal",
"value": "Senthil"
},
{
"condition": "and",
"rules": [
{
"id": "salary",
"field": "salary",
"type": "integer",
"input": "text",
"operator": "equal",
"value": "1000"
},
{
"id": "doj",
"field": "date",
"type": "date",
"input": "text",
"operator": "date_equal",
"value": "01/01/2000"
}
]
}
]
}
};
// init
$('#builder').queryBuilder(options);
$('#builder').on('afterCreateRuleInput.queryBuilder', function (e, rule) {
if (rule.filter.plugin == 'selectize') {
rule.$el.find('.rule-value-container').css('min-width', '200px')
.find('.selectize-control').removeClass('form-control');
}
});
// change language
$('[name=language]').selectpicker().on('change', function () {
var lang = $(this).val();
var done = function () {
var rules = $b.queryBuilder('getRules');
if (!$.isEmptyObject(rules)) {
options.rules = rules;
}
options.lang_code = lang;
$b.queryBuilder('destroy');
$('#builder').queryBuilder(options);
};
if ($.fn.queryBuilder.regional[lang] === undefined) {
$.getScript('../dist/i18n/query-builder.' + lang + '.js', done);
}
else {
done();
}
});
// change theme
$('.change-theme').on('click', function () {
$('#qb-theme').replaceWith('<link rel="stylesheet" href="' + $(this).data('qb') + '" id="qb-theme">');
$('#bt-theme').replaceWith('<link rel="stylesheet" href="' + $(this).data('bt') + '" id="bt-theme">');
});
// set rules
$('.set').on('click', function () {
$('#builder').queryBuilder('setRules', {
condition: 'AND',
flags: {
condition_readonly: true
},
rules: [{
id: 'price',
operator: 'between',
value: [10.25, 15.52],
flags: {
no_delete: true,
filter_readonly: true
},
data: {
unit: '€'
}
}, {
id: 'state',
operator: 'equal',
value: 'AK',
}, {
condition: 'OR',
flags: {
no_delete: true
},
rules: [{
id: 'category',
operator: 'equal',
value: 2
}, {
id: 'coord',
operator: 'equal',
value: 'B.3'
}]
}]
});
});
// set rules from MongoDB
$('.set-mongo').on('click', function () {
$('#builder').queryBuilder('setRulesFromMongo', {
"$and": [{
"name": {
"$regex": "^(?!Mistic)"
}
}, {
"price": { "$gte": 0, "$lte": 100 }
}, {
"$or": [{
"category": 2
}, {
"category": { "$in": [4, 5] }
}]
}]
});
});
// set rules from SQL
$('.set-sql').on('click', function () {
$('#builder').queryBuilder('setRulesFromSQL', 'name NOT LIKE "Mistic%" AND price BETWEEN 100 AND 200 AND (category IN(1, 2) OR rate <= 2)');
});
// reset builder
$('.reset').on('click', function () {
$('#builder').queryBuilder('reset');
$('#result').addClass('hide').find('pre').empty();
});
// get rules
$('.parse-json').on('click', function () {
$('#resultRuleDef').removeClass('hide')
.find('pre').html(JSON.stringify(
$('#builder').queryBuilder('getRules', { get_flags: true }),
undefined, 2
));
});
$('.parse-sql').on('click', function () {
var res = $('#builder').queryBuilder('getSQL', $(this).data('stmt'), false);
$('#resultRule').removeClass('hide')
.find('pre').html(
res.sql + (res.params ? '\n\n' + JSON.stringify(res.params, undefined, 2) : '')
);
});
$('.parse-mongo').on('click', function () {
$('#result').removeClass('hide')
.find('pre').html(JSON.stringify(
$('#builder').queryBuilder('getMongo'),
undefined, 2
));
});
// set filters
$('.set-filters').on('click', function () {
$(this).prop('disabled', true);
$(this).tooltip('hide');
// add a new filter after 'state'
$('#builder').queryBuilder('addFilter',
{
id: 'new_one',
label: 'New filter',
type: 'string'
},
'state'
);
// remove filter 'coord'
$('#builder').queryBuilder('removeFilter',
['coord', 'state', 'bson'],
true
);
// also available : 'setFilters'
});
</script>
/*!
* jQuery.extendext 0.1.1
*
* Copyright 2014 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
* Licensed under MIT (http://opensource.org/licenses/MIT)
*
* Based on jQuery.extend by jQuery Foundation, Inc. and other contributors
*/
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define('jQuery.extendext', ['jquery'], factory);
}
else {
factory(root.jQuery);
}
}(this, function($) {
"use strict";
$.extendext = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false,
arrayMode = 'default';
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// Skip the boolean and the target
target = arguments[ i++ ] || {};
}
// Handle array mode parameter
if ( typeof target === "string" ) {
arrayMode = $([target.toLowerCase(), 'default']).filter(['default','concat','replace','extend'])[0];
// Skip the string param
target = arguments[ i++ ] || {};
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !$.isFunction(target) ) {
target = {};
}
// Extend jQuery itself if only one argument is passed
if ( i === length ) {
target = this;
i--;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) !== null ) {
// Special operations for arrays
if ($.isArray(options) && arrayMode !== 'default') {
clone = target && $.isArray(target) ? target : [];
switch (arrayMode) {
case 'concat':
target = clone.concat( $.extend( deep, [], options ) );
break;
case 'replace':
target = $.extend( deep, [], options );
break;
case 'extend':
options.forEach(function(e, i) {
if (typeof e === 'object') {
var type = $.isArray(e) ? [] : {};
clone[i] = $.extendext( deep, arrayMode, clone[i] || type, e );
} else if (clone.indexOf(e) === -1) {
clone.push(e);
}
});
target = clone;
break;
}
} else {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( $.isPlainObject(copy) ||
(copyIsArray = $.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && $.isArray(src) ? src : [];
} else {
clone = src && $.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = $.extendext( deep, arrayMode, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
}
// Return the modified object
return target;
};
}));
// doT.js
// 2011-2014, Laura Doktorova, https://github.com/olado/doT
// Licensed under the MIT license.
(function() {
"use strict";
var doT = {
version: "1.0.3",
templateSettings: {
evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
encode: /\{\{!([\s\S]+?)\}\}/g,
use: /\{\{#([\s\S]+?)\}\}/g,
useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,
define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
defineParams:/^\s*([\w$]+):([\s\S]+)/,
conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
varname: "it",
strip: true,
append: true,
selfcontained: false,
doNotSkipEncoded: false
},
template: undefined, //fn, compile template
compile: undefined //fn, for express
}, _globals;
doT.encodeHTMLSource = function(doNotSkipEncoded) {
var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'", "/": "/" },
matchHTML = doNotSkipEncoded ? /[&<>"'\/]/g : /&(?!#?\w+;)|<|>|"|'|\//g;
return function(code) {
return code ? code.toString().replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : "";
};
};
_globals = (function(){ return this || (0,eval)("this"); }());
if (typeof module !== "undefined" && module.exports) {
module.exports = doT;
} else if (typeof define === "function" && define.amd) {
define('doT', function(){return doT;});
} else {
_globals.doT = doT;
}
var startend = {
append: { start: "'+(", end: ")+'", startencode: "'+encodeHTML(" },
split: { start: "';out+=(", end: ");out+='", startencode: "';out+=encodeHTML(" }
}, skip = /$^/;
function resolveDefs(c, block, def) {
return ((typeof block === "string") ? block : block.toString())
.replace(c.define || skip, function(m, code, assign, value) {
if (code.indexOf("def.") === 0) {
code = code.substring(4);
}
if (!(code in def)) {
if (assign === ":") {
if (c.defineParams) value.replace(c.defineParams, function(m, param, v) {
def[code] = {arg: param, text: v};
});
if (!(code in def)) def[code]= value;
} else {
new Function("def", "def['"+code+"']=" + value)(def);
}
}
return "";
})
.replace(c.use || skip, function(m, code) {
if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) {
if (def[d] && def[d].arg && param) {
var rw = (d+":"+param).replace(/'|\\/g, "_");
def.__exp = def.__exp || {};
def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2");
return s + "def.__exp['"+rw+"']";
}
});
var v = new Function("def", "return " + code)(def);
return v ? resolveDefs(c, v, def) : v;
});
}
function unescape(code) {
return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " ");
}
doT.template = function(tmpl, c, def) {
c = c || doT.templateSettings;
var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv,
str = (c.use || c.define) ? resolveDefs(c, tmpl, def || {}) : tmpl;
str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ")
.replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""): str)
.replace(/'|\\/g, "\\$&")
.replace(c.interpolate || skip, function(m, code) {
return cse.start + unescape(code) + cse.end;
})
.replace(c.encode || skip, function(m, code) {
needhtmlencode = true;
return cse.startencode + unescape(code) + cse.end;
})
.replace(c.conditional || skip, function(m, elsecase, code) {
return elsecase ?
(code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") :
(code ? "';if(" + unescape(code) + "){out+='" : "';}out+='");
})
.replace(c.iterate || skip, function(m, iterate, vname, iname) {
if (!iterate) return "';} } out+='";
sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate);
return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"<l"+sid+"){"
+vname+"=arr"+sid+"["+indv+"+=1];out+='";
})
.replace(c.evaluate || skip, function(m, code) {
return "';" + unescape(code) + "out+='";
})
+ "';return out;")
.replace(/\n/g, "\\n").replace(/\t/g, '\\t').replace(/\r/g, "\\r")
.replace(/(\s|;|\}|^|\{)out\+='';/g, '$1').replace(/\+''/g, "");
//.replace(/(\s|;|\}|^|\{)out\+=''\+/g,'$1out+=');
if (needhtmlencode) {
if (!c.selfcontained && _globals && !_globals._encodeHTML) _globals._encodeHTML = doT.encodeHTMLSource(c.doNotSkipEncoded);
str = "var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : ("
+ doT.encodeHTMLSource.toString() + "(" + (c.doNotSkipEncoded || '') + "));"
+ str;
}
try {
return new Function(c.varname, str);
} catch (e) {
if (typeof console !== "undefined") console.log("Could not create a template function: " + str);
throw e;
}
};
doT.compile = function(tmpl, def) {
return doT.template(tmpl, null, def);
};
}());
/*!
* jQuery QueryBuilder 2.3.3
* Copyright 2014-2016 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
* Licensed under MIT (http://opensource.org/licenses/MIT)
*/
// Languages: en
// Plugins: bt-checkbox, bt-selectpicker, bt-tooltip-errors, change-filters, filter-description, invert, mongodb-support, sortable, sql-support, unique-filter
(function(root, factory) {
if (typeof define == 'function' && define.amd) {
define('query-builder', ['jquery', 'doT', 'jQuery.extendext'], factory);
}
else {
factory(root.jQuery, root.doT);
}
}(this, function($, doT) {
"use strict";
// CLASS DEFINITION
// ===============================
var QueryBuilder = function($el, options) {
this.init($el, options);
};
// EVENTS SYSTEM
// ===============================
$.extend(QueryBuilder.prototype, {
change: function(type, value) {
var event = new $.Event(type + '.queryBuilder.filter', {
builder: this,
value: value
});
this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
return event.value;
},
trigger: function(type) {
var event = new $.Event(type + '.queryBuilder', {
builder: this
});
this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
return event;
},
on: function(type, cb) {
this.$el.on(type + '.queryBuilder', cb);
return this;
},
off: function(type, cb) {
this.$el.off(type + '.queryBuilder', cb);
return this;
},
once: function(type, cb) {
this.$el.one(type + '.queryBuilder', cb);
return this;
}
});
// PLUGINS SYSTEM
// ===============================
QueryBuilder.plugins = {};
/**
* Get or extend the default configuration
* @param options {object,optional} new configuration, leave undefined to get the default config
* @return {undefined|object} nothing or configuration object (copy)
*/
QueryBuilder.defaults = function(options) {
if (typeof options == 'object') {
$.extendext(true, 'replace', QueryBuilder.DEFAULTS, options);
}
else if (typeof options == 'string') {
if (typeof QueryBuilder.DEFAULTS[options] == 'object') {
return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
}
else {
return QueryBuilder.DEFAULTS[options];
}
}
else {
return $.extend(true, {}, QueryBuilder.DEFAULTS);
}
};
/**
* Define a new plugin
* @param {string}
* @param {function}
* @param {object,optional} default configuration
*/
QueryBuilder.define = function(name, fct, def) {
QueryBuilder.plugins[name] = {
fct: fct,
def: def || {}
};
};
/**
* Add new methods
* @param {object}
*/
QueryBuilder.extend = function(methods) {
$.extend(QueryBuilder.prototype, methods);
};
/**
* Init plugins for an instance
* @throws ConfigError
*/
QueryBuilder.prototype.initPlugins = function() {
if (!this.plugins) {
return;
}
if ($.isArray(this.plugins)) {
var tmp = {};
this.plugins.forEach(function(plugin) {
tmp[plugin] = null;
});
this.plugins = tmp;
}
Object.keys(this.plugins).forEach(function(plugin) {
if (plugin in QueryBuilder.plugins) {
this.plugins[plugin] = $.extend(true, {},
QueryBuilder.plugins[plugin].def,
this.plugins[plugin] || {}
);
QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
}
else {
Utils.error('Config', 'Unable to find plugin "{0}"', plugin);
}
}, this);
};
/**
* Allowed types and their internal representation
*/
QueryBuilder.types = {
'string': 'string',
'integer': 'number',
'double': 'number',
'date': 'datetime',
'time': 'datetime',
'datetime': 'datetime',
'boolean': 'boolean'
};
/**
* Allowed inputs
*/
QueryBuilder.inputs = [
'text',
'textarea',
'radio',
'checkbox',
'select'
];
/**
* Runtime modifiable options with `setOptions` method
*/
QueryBuilder.modifiable_options = [
'display_errors',
'allow_groups',
'allow_empty',
'default_condition',
'default_filter'
];
/**
* CSS selectors for common components
*/
var Selectors = QueryBuilder.selectors = {
group_container: '.rules-group-container',
rule_container: '.rule-container',
filter_container: '.rule-filter-container',
operator_container: '.rule-operator-container',
value_container: '.rule-value-container',
error_container: '.error-container',
condition_container: '.rules-group-header .group-conditions',
rule_header: '.rule-header',
group_header: '.rules-group-header',
group_actions: '.group-actions',
rule_actions: '.rule-actions',
rules_list: '.rules-group-body>.rules-list',
group_condition: '.rules-group-header [name$=_cond]',
rule_filter: '.rule-filter-container [name$=_filter]',
rule_operator: '.rule-operator-container [name$=_operator]',
rule_value: '.rule-value-container [name*=_value_]',
add_rule: '[data-add=rule]',
delete_rule: '[data-delete=rule]',
add_group: '[data-add=group]',
delete_group: '[data-delete=group]'
};
/**
* Template strings (see `template.js`)
*/
QueryBuilder.templates = {};
/**
* Localized strings (see `i18n/`)
*/
QueryBuilder.regional = {};
/**
* Default operators
*/
QueryBuilder.OPERATORS = {
equal: { type: 'equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
not_equal: { type: 'not_equal', nb_inputs: 1, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
in: { type: 'in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
not_in: { type: 'not_in', nb_inputs: 1, multiple: true, apply_to: ['string', 'number', 'datetime'] },
less: { type: 'less', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
less_or_equal: { type: 'less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
greater: { type: 'greater', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
greater_or_equal: { type: 'greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['number', 'datetime'] },
between: { type: 'between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
not_between: { type: 'not_between', nb_inputs: 2, multiple: false, apply_to: ['number', 'datetime'] },
begins_with: { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
not_begins_with: { type: 'not_begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
contains: { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
not_contains: { type: 'not_contains', nb_inputs: 1, multiple: false, apply_to: ['string'] },
ends_with: { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
not_ends_with: { type: 'not_ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] },
is_empty: { type: 'is_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
is_not_empty: { type: 'is_not_empty', nb_inputs: 0, multiple: false, apply_to: ['string'] },
is_null: { type: 'is_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
is_not_null: { type: 'is_not_null', nb_inputs: 0, multiple: false, apply_to: ['string', 'number', 'datetime', 'boolean'] },
date_equal: { type: 'date_equal', nb_inputs: 1, multiple: false, apply_to: ['datetime'] },
date_not_equal: { type: 'date_not_equal', nb_inputs: 1, multiple: false, apply_to: ['datetime'] },
date_less: { type: 'date_less', nb_inputs: 1, multiple: false, apply_to: ['datetime'] },
date_less_or_equal: { type: 'date_less_or_equal', nb_inputs: 1, multiple: false, apply_to: ['datetime'] },
date_greater: { type: 'date_greater', nb_inputs: 1, multiple: false, apply_to: ['datetime'] },
date_greater_or_equal: { type: 'date_greater_or_equal', nb_inputs: 1, multiple: false, apply_to: ['datetime'] }
};
/**
* Default configuration
*/
QueryBuilder.DEFAULTS = {
filters: [],
plugins: [],
sort_filters: false,
display_errors: true,
allow_groups: -1,
allow_empty: false,
conditions: ['and', 'or'],
default_condition: 'and',
inputs_separator: ' , ',
select_placeholder: '------',
display_empty_filter: true,
default_filter: null,
optgroups: {},
default_rule_flags: {
filter_readonly: false,
operator_readonly: false,
value_readonly: false,
no_delete: false
},
default_group_flags: {
condition_readonly: false,
no_delete: false
},
templates: {
group: null,
rule: null,
filterSelect: null,
operatorSelect: null
},
lang_code: 'en',
lang: {},
//operators: [
// 'equal',
// 'not_equal',
// 'in',
// 'not_in',
// 'less',
// 'less_or_equal',
// 'greater',
// 'greater_or_equal',
// 'between',
// 'not_between',
// 'begins_with',
// 'not_begins_with',
// 'contains',
// 'not_contains',
// 'ends_with',
// 'not_ends_with',
// 'is_empty',
// 'is_not_empty',
// 'is_null',
// 'is_not_null'
//],
operators: [
'equal',
'not_equal',
'less',
'less_or_equal',
'greater',
'greater_or_equal',
'is_empty',
'is_not_empty',
'date_equal',
'date_not_equal',
'date_less',
'date_less_or_equal',
'date_greater',
'date_greater_or_equal',
],
icons: {
add_group: 'glyphicon glyphicon-plus-sign',
add_rule: 'glyphicon glyphicon-plus',
remove_group: 'glyphicon glyphicon-remove',
remove_rule: 'glyphicon glyphicon-remove',
error: 'glyphicon glyphicon-warning-sign'
}
};
/**
* Init the builder
*/
QueryBuilder.prototype.init = function($el, options) {
$el[0].queryBuilder = this;
this.$el = $el;
// PROPERTIES
this.settings = $.extendext(true, 'replace', {}, QueryBuilder.DEFAULTS, options);
this.model = new Model();
this.status = {
group_id: 0,
rule_id: 0,
generated_id: false,
has_optgroup: false,
has_operator_oprgroup: false,
id: null,
updating_value: false
};
// "allow_groups" can be boolean or int
if (this.settings.allow_groups === false) {
this.settings.allow_groups = 0;
}
else if (this.settings.allow_groups === true) {
this.settings.allow_groups = -1;
}
// SETTINGS SHORTCUTS
this.filters = this.settings.filters;
this.icons = this.settings.icons;
this.operators = this.settings.operators;
this.templates = this.settings.templates;
this.plugins = this.settings.plugins;
// translations : english << 'lang_code' << custom
if (QueryBuilder.regional['en'] === undefined) {
Utils.error('Config', '"i18n/en.js" not loaded.');
}
this.lang = $.extendext(true, 'replace', {}, QueryBuilder.regional['en'], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
// init templates
Object.keys(this.templates).forEach(function(tpl) {
if (!this.templates[tpl]) {
this.templates[tpl] = QueryBuilder.templates[tpl];
}
if (typeof this.templates[tpl] == 'string') {
this.templates[tpl] = doT.template(this.templates[tpl]);
}
}, this);
// ensure we have a container id
if (!this.$el.attr('id')) {
this.$el.attr('id', 'qb_' + Math.floor(Math.random() * 99999));
this.status.generated_id = true;
}
this.status.id = this.$el.attr('id');
// INIT
this.$el.addClass('query-builder form-inline');
this.filters = this.checkFilters(this.filters);
this.operators = this.checkOperators(this.operators);
this.bindEvents();
this.initPlugins();
this.trigger('afterInit');
if (options.rules) {
this.setRules(options.rules);
delete this.settings.rules;
}
else {
this.setRoot(true);
}
};
/**
* Checks the configuration of each filter
* @throws ConfigError
*/
QueryBuilder.prototype.checkFilters = function(filters) {
var definedFilters = [];
if (!filters || filters.length === 0) {
Utils.error('Config', 'Missing filters list');
}
filters.forEach(function(filter, i) {
if (!filter.id) {
Utils.error('Config', 'Missing filter {0} id', i);
}
if (definedFilters.indexOf(filter.id) != -1) {
Utils.error('Config', 'Filter "{0}" already defined', filter.id);
}
definedFilters.push(filter.id);
if (!filter.type) {
filter.type = 'string';
}
else if (!QueryBuilder.types[filter.type]) {
Utils.error('Config', 'Invalid type "{0}"', filter.type);
}
if (!filter.input) {
filter.input = 'text';
}
else if (typeof filter.input != 'function' && QueryBuilder.inputs.indexOf(filter.input) == -1) {
Utils.error('Config', 'Invalid input "{0}"', filter.input);
}
if (filter.operators) {
filter.operators.forEach(function(operator) {
if (typeof operator != 'string') {
Utils.error('Config', 'Filter operators must be global operators types (string)');
}
});
}
if (!filter.field) {
filter.field = filter.id;
}
if (!filter.label) {
filter.label = filter.field;
}
if (!filter.optgroup) {
filter.optgroup = null;
}
else {
this.status.has_optgroup = true;
// register optgroup if needed
if (!this.settings.optgroups[filter.optgroup]) {
this.settings.optgroups[filter.optgroup] = filter.optgroup;
}
}
switch (filter.input) {
case 'radio': case 'checkbox':
if (!filter.values || filter.values.length < 1) {
Utils.error('Config', 'Missing filter "{0}" values', filter.id);
}
break;
case 'select':
if (filter.placeholder) {
if (filter.placeholder_value === undefined) {
filter.placeholder_value = -1;
}
Utils.iterateOptions(filter.values, function(key) {
if (key == filter.placeholder_value) {
Utils.error('Config', 'Placeholder of filter "{0}" overlaps with one of its values', filter.id);
}
});
}
break;
}
}, this);
if (this.settings.sort_filters) {
if (typeof this.settings.sort_filters == 'function') {
filters.sort(this.settings.sort_filters);
}
else {
var self = this;
filters.sort(function(a, b) {
return self.translateLabel(a.label).localeCompare(self.translateLabel(b.label));
});
}
}
if (this.status.has_optgroup) {
filters = Utils.groupSort(filters, 'optgroup');
}
return filters;
};
/**
* Checks the configuration of each operator
* @throws ConfigError
*/
QueryBuilder.prototype.checkOperators = function(operators) {
var definedOperators = [];
operators.forEach(function(operator, i) {
if (typeof operator == 'string') {
if (!QueryBuilder.OPERATORS[operator]) {
Utils.error('Config', 'Unknown operator "{0}"', operator);
}
operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator]);
}
else {
if (!operator.type) {
Utils.error('Config', 'Missing "type" for operator {0}', i);
}
if (QueryBuilder.OPERATORS[operator.type]) {
operators[i] = operator = $.extendext(true, 'replace', {}, QueryBuilder.OPERATORS[operator.type], operator);
}
if (operator.nb_inputs === undefined || operator.apply_to === undefined) {
Utils.error('Config', 'Missing "nb_inputs" and/or "apply_to" for operator "{0}"', operator.type);
}
}
if (definedOperators.indexOf(operator.type) != -1) {
Utils.error('Config', 'Operator "{0}" already defined', operator.type);
}
definedOperators.push(operator.type);
if (!operator.optgroup) {
operator.optgroup = null;
}
else {
this.status.has_operator_optgroup = true;
// register optgroup if needed
if (!this.settings.optgroups[operator.optgroup]) {
this.settings.optgroups[operator.optgroup] = operator.optgroup;
}
}
}, this);
if (this.status.has_operator_optgroup) {
operators = Utils.groupSort(operators, 'optgroup');
}
return operators;
};
/**
* Add all events listeners
*/
QueryBuilder.prototype.bindEvents = function() {
var self = this;
// group condition change
this.$el.on('change.queryBuilder', Selectors.group_condition, function() {
if ($(this).is(':checked')) {
var $group = $(this).closest(Selectors.group_container);
Model($group).condition = $(this).val();
}
});
// rule filter change
this.$el.on('change.queryBuilder', Selectors.rule_filter, function() {
var $rule = $(this).closest(Selectors.rule_container);
Model($rule).filter = self.getFilterById($(this).val());
});
// rule operator change
this.$el.on('change.queryBuilder', Selectors.rule_operator, function() {
var $rule = $(this).closest(Selectors.rule_container);
Model($rule).operator = self.getOperatorByType($(this).val());
});
// add rule button
this.$el.on('click.queryBuilder', Selectors.add_rule, function() {
var $group = $(this).closest(Selectors.group_container);
self.addRule(Model($group));
});
// delete rule button
this.$el.on('click.queryBuilder', Selectors.delete_rule, function() {
var $rule = $(this).closest(Selectors.rule_container);
self.deleteRule(Model($rule));
});
if (this.settings.allow_groups !== 0) {
// add group button
this.$el.on('click.queryBuilder', Selectors.add_group, function() {
var $group = $(this).closest(Selectors.group_container);
self.addGroup(Model($group));
});
// delete group button
this.$el.on('click.queryBuilder', Selectors.delete_group, function() {
var $group = $(this).closest(Selectors.group_container);
self.deleteGroup(Model($group));
});
}
// model events
this.model.on({
'drop': function(e, node) {
node.$el.remove();
self.refreshGroupsConditions();
},
'add': function(e, node, index) {
if (index === 0) {
node.$el.prependTo(node.parent.$el.find('>' + Selectors.rules_list));
}
else {
node.$el.insertAfter(node.parent.rules[index - 1].$el);
}
self.refreshGroupsConditions();
},
'move': function(e, node, group, index) {
node.$el.detach();
if (index === 0) {
node.$el.prependTo(group.$el.find('>' + Selectors.rules_list));
}
else {
node.$el.insertAfter(group.rules[index - 1].$el);
}
self.refreshGroupsConditions();
},
'update': function(e, node, field, value, oldValue) {
if (node instanceof Rule) {
switch (field) {
case 'error':
self.displayError(node);
break;
case 'flags':
self.applyRuleFlags(node);
break;
case 'filter':
self.updateRuleFilter(node);
break;
case 'operator':
self.updateRuleOperator(node, oldValue);
break;
case 'value':
self.updateRuleValue(node);
break;
}
}
else {
switch (field) {
case 'error':
self.displayError(node);
break;
case 'flags':
self.applyGroupFlags(node);
break;
case 'condition':
self.updateGroupCondition(node);
break;
}
}
}
});
};
/**
* Create the root group
* @param addRule {bool,optional} add a default empty rule
* @param data {mixed,optional} group custom data
* @param flags {object,optional} flags to apply to the group
* @return group {Root}
*/
QueryBuilder.prototype.setRoot = function(addRule, data, flags) {
addRule = (addRule === undefined || addRule === true);
var group_id = this.nextGroupId();
var $group = $(this.getGroupTemplate(group_id, 1));
this.$el.append($group);
this.model.root = new Group(null, $group);
this.model.root.model = this.model;
this.model.root.data = data;
this.model.root.flags = $.extend({}, this.settings.default_group_flags, flags);
this.trigger('afterAddGroup', this.model.root);
this.model.root.condition = this.settings.default_condition;
if (addRule) {
this.addRule(this.model.root);
}
return this.model.root;
};
/**
* Add a new group
* @param parent {Group}
* @param addRule {bool,optional} add a default empty rule
* @param data {mixed,optional} group custom data
* @param flags {object,optional} flags to apply to the group
* @return group {Group}
*/
QueryBuilder.prototype.addGroup = function(parent, addRule, data, flags) {
addRule = (addRule === undefined || addRule === true);
var level = parent.level + 1;
var e = this.trigger('beforeAddGroup', parent, addRule, level);
if (e.isDefaultPrevented()) {
return null;
}
var group_id = this.nextGroupId();
var $group = $(this.getGroupTemplate(group_id, level));
var model = parent.addGroup($group);
model.data = data;
model.flags = $.extend({}, this.settings.default_group_flags, flags);
this.trigger('afterAddGroup', model);
model.condition = this.settings.default_condition;
if (addRule) {
this.addRule(model);
}
return model;
};
/**
* Tries to delete a group. The group is not deleted if at least one rule is no_delete.
* @param group {Group}
* @return {boolean} true if the group has been deleted
*/
QueryBuilder.prototype.deleteGroup = function(group) {
if (group.isRoot()) {
return false;
}
var e = this.trigger('beforeDeleteGroup', group);
if (e.isDefaultPrevented()) {
return false;
}
var del = true;
group.each('reverse', function(rule) {
del&= this.deleteRule(rule);
}, function(group) {
del&= this.deleteGroup(group);
}, this);
if (del) {
group.drop();
this.trigger('afterDeleteGroup');
}
return del;
};
/**
* Changes the condition of a group
* @param group {Group}
*/
QueryBuilder.prototype.updateGroupCondition = function(group) {
group.$el.find('>' + Selectors.group_condition).each(function() {
var $this = $(this);
$this.prop('checked', $this.val() === group.condition);
$this.parent().toggleClass('active', $this.val() === group.condition);
});
this.trigger('afterUpdateGroupCondition', group);
};
/**
* Update visibility of conditions based on number of rules inside each group
*/
QueryBuilder.prototype.refreshGroupsConditions = function() {
(function walk(group) {
if (!group.flags || (group.flags && !group.flags.condition_readonly)) {
group.$el.find('>' + Selectors.group_condition).prop('disabled', group.rules.length <= 1)
.parent().toggleClass('disabled', group.rules.length <= 1);
}
group.each(function(rule) {}, function(group) {
walk(group);
}, this);
}(this.model.root));
};
/**
* Add a new rule
* @param parent {Group}
* @param data {mixed,optional} rule custom data
* @param flags {object,optional} flags to apply to the rule
* @return rule {Rule}
*/
QueryBuilder.prototype.addRule = function(parent, data, flags) {
var e = this.trigger('beforeAddRule', parent);
if (e.isDefaultPrevented()) {
return null;
}
var rule_id = this.nextRuleId();
var $rule = $(this.getRuleTemplate(rule_id));
var model = parent.addRule($rule);
if (data !== undefined) {
model.data = data;
}
model.flags = $.extend({}, this.settings.default_rule_flags, flags);
this.trigger('afterAddRule', model);
this.createRuleFilters(model);
if (this.settings.default_filter || !this.settings.display_empty_filter) {
model.filter = this.getFilterById(this.settings.default_filter || this.filters[0].id);
}
return model;
};
/**
* Delete a rule.
* @param rule {Rule}
* @return {boolean} true if the rule has been deleted
*/
QueryBuilder.prototype.deleteRule = function(rule) {
if (rule.flags.no_delete) {
return false;
}
var e = this.trigger('beforeDeleteRule', rule);
if (e.isDefaultPrevented()) {
return false;
}
rule.drop();
this.trigger('afterDeleteRule');
return true;
};
/**
* Create the filters <select> for a rule
* @param rule {Rule}
*/
QueryBuilder.prototype.createRuleFilters = function(rule) {
var filters = this.change('getRuleFilters', this.filters, rule);
var $filterSelect = $(this.getRuleFilterSelect(rule, filters));
rule.$el.find(Selectors.filter_container).html($filterSelect);
this.trigger('afterCreateRuleFilters', rule);
};
/**
* Create the operators <select> for a rule and init the rule operator
* @param rule {Rule}
*/
QueryBuilder.prototype.createRuleOperators = function(rule) {
var $operatorContainer = rule.$el.find(Selectors.operator_container).empty();
if (!rule.filter) {
return;
}
var operators = this.getOperators(rule.filter);
var $operatorSelect = $(this.getRuleOperatorSelect(rule, operators));
$operatorContainer.html($operatorSelect);
// set the operator without triggering update event
rule.__.operator = operators[0];
this.trigger('afterCreateRuleOperators', rule, operators);
};
/**
* Create the main input for a rule
* @param rule {Rule}
*/
QueryBuilder.prototype.createRuleInput = function(rule) {
var $valueContainer = rule.$el.find(Selectors.value_container).empty();
rule.__.value = undefined;
if (!rule.filter || !rule.operator || rule.operator.nb_inputs === 0) {
return;
}
var self = this;
var $inputs = $();
var filter = rule.filter;
for (var i = 0; i < rule.operator.nb_inputs; i++) {
var $ruleInput = $(this.getRuleInput(rule, i));
if (i > 0) $valueContainer.append(this.settings.inputs_separator);
$valueContainer.append($ruleInput);
$inputs = $inputs.add($ruleInput);
}
$valueContainer.show();
$inputs.on('change ' + (filter.input_event || ''), function() {
self.status.updating_value = true;
rule.value = self.getRuleValue(rule);
self.status.updating_value = false;
});
if (filter.plugin) {
$inputs[filter.plugin](filter.plugin_config || {});
}
this.trigger('afterCreateRuleInput', rule);
if (filter.default_value !== undefined) {
rule.value = filter.default_value;
}
else {
self.status.updating_value = true;
rule.value = self.getRuleValue(rule);
self.status.updating_value = false;
}
};
/**
* Perform action when rule's filter is changed
* @param rule {Rule}
*/
QueryBuilder.prototype.updateRuleFilter = function(rule) {
this.createRuleOperators(rule);
this.createRuleInput(rule);
rule.$el.find(Selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
this.trigger('afterUpdateRuleFilter', rule);
};
/**
* Update main <input> visibility when rule operator changes
* @param rule {Rule}
* @param previousOperator {object}
*/
QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) {
var $valueContainer = rule.$el.find(Selectors.value_container);
if (!rule.operator || rule.operator.nb_inputs === 0) {
$valueContainer.hide();
rule.__.value = undefined;
}
else {
$valueContainer.show();
if ($valueContainer.is(':empty') || rule.operator.nb_inputs !== previousOperator.nb_inputs) {
this.createRuleInput(rule);
}
}
if (rule.operator) {
rule.$el.find(Selectors.rule_operator).val(rule.operator.type);
}
this.trigger('afterUpdateRuleOperator', rule);
};
/**
* Perform action when rule's value is changed
* @param rule {Rule}
*/
QueryBuilder.prototype.updateRuleValue = function(rule) {
if (!this.status.updating_value) {
this.setRuleValue(rule, rule.value);
}
this.trigger('afterUpdateRuleValue', rule);
};
/**
* Change rules properties depending on flags.
* @param rule {Rule}
*/
QueryBuilder.prototype.applyRuleFlags = function(rule) {
var flags = rule.flags;
if (flags.filter_readonly) {
rule.$el.find(Selectors.rule_filter).prop('disabled', true);
}
if (flags.operator_readonly) {
rule.$el.find(Selectors.rule_operator).prop('disabled', true);
}
if (flags.value_readonly) {
rule.$el.find(Selectors.rule_value).prop('disabled', true);
}
if (flags.no_delete) {
rule.$el.find(Selectors.delete_rule).remove();
}
this.trigger('afterApplyRuleFlags', rule);
};
/**
* Change group properties depending on flags.
* @param group {Group}
*/
QueryBuilder.prototype.applyGroupFlags = function(group) {
var flags = group.flags;
if (flags.condition_readonly) {
group.$el.find('>' + Selectors.group_condition).prop('disabled', true)
.parent().addClass('readonly');
}
if (flags.no_delete) {
group.$el.find(Selectors.delete_group).remove();
}
this.trigger('afterApplyGroupFlags', group);
};
/**
* Clear all errors markers
* @param node {Node,optional} default is root Group
*/
QueryBuilder.prototype.clearErrors = function(node) {
node = node || this.model.root;
if (!node) {
return;
}
node.error = null;
if (node instanceof Group) {
node.each(function(rule) {
rule.error = null;
}, function(group) {
this.clearErrors(group);
}, this);
}
};
/**
* Add/Remove class .has-error and update error title
* @param node {Node}
*/
QueryBuilder.prototype.displayError = function(node) {
if (this.settings.display_errors) {
if (node.error === null) {
node.$el.removeClass('has-error');
}
else {
// translate the text without modifying event array
var error = $.extend([], node.error, [
this.lang.errors[node.error[0]] || node.error[0]
]);
node.$el.addClass('has-error')
.find(Selectors.error_container).eq(0)
.attr('title', Utils.fmt.apply(null, error));
}
}
};
/**
* Trigger a validation error event
* @param node {Node}
* @param error {array}
* @param value {mixed}
*/
QueryBuilder.prototype.triggerValidationError = function(node, error, value) {
if (!$.isArray(error)) {
error = [error];
}
var e = this.trigger('validationError', node, error, value);
if (!e.isDefaultPrevented()) {
node.error = error;
}
};
/**
* Destroy the plugin
*/
QueryBuilder.prototype.destroy = function() {
this.trigger('beforeDestroy');
if (this.status.generated_id) {
this.$el.removeAttr('id');
}
this.clear();
this.model = null;
this.$el
.off('.queryBuilder')
.removeClass('query-builder')
.removeData('queryBuilder');
delete this.$el[0].queryBuilder;
};
/**
* Reset the plugin
*/
QueryBuilder.prototype.reset = function() {
this.status.group_id = 1;
this.status.rule_id = 0;
this.model.root.empty();
this.addRule(this.model.root);
this.trigger('afterReset');
};
/**
* Clear the plugin
*/
QueryBuilder.prototype.clear = function() {
this.status.group_id = 0;
this.status.rule_id = 0;
if (this.model.root) {
this.model.root.drop();
this.model.root = null;
}
this.trigger('afterClear');
};
/**
* Modify the builder configuration
* Only options defined in QueryBuilder.modifiable_options are modifiable
* @param {object}
*/
QueryBuilder.prototype.setOptions = function(options) {
// use jQuery utils to filter options keys
$.makeArray($(Object.keys(options)).filter(QueryBuilder.modifiable_options))
.forEach(function(opt) {
this.settings[opt] = options[opt];
}, this);
};
/**
* Return the model associated to a DOM object, or root model
* @param {jQuery,optional}
* @return {Node}
*/
QueryBuilder.prototype.getModel = function(target) {
return !target ? this.model.root : Model(target);
};
/**
* Validate the whole builder
* @return {boolean}
*/
QueryBuilder.prototype.validate = function() {
this.clearErrors();
var self = this;
var valid = (function parse(group) {
var done = 0;
var errors = 0;
group.each(function(rule) {
if (!rule.filter) {
self.triggerValidationError(rule, 'no_filter', null);
errors++;
return;
}
if (rule.operator.nb_inputs !== 0) {
var valid = self.validateValue(rule, rule.value);
if (valid !== true) {
self.triggerValidationError(rule, valid, rule.value);
errors++;
return;
}
}
done++;
}, function(group) {
if (parse(group)) {
done++;
}
else {
errors++;
}
});
if (errors > 0) {
return false;
}
else if (done === 0 && (!self.settings.allow_empty || !group.isRoot())) {
self.triggerValidationError(group, 'empty_group', null);
return false;
}
return true;
}(this.model.root));
return this.change('validate', valid);
};
/**
* Get an object representing current rules
* @param {object} options
* - get_flags: false[default] | true(only changes from default flags) | 'all'
* @return {object}
*/
QueryBuilder.prototype.getRules = function(options) {
options = $.extend({
get_flags: false
}, options);
if (!this.validate()) {
return {};
}
var self = this;
var out = (function parse(group) {
var data = {
condition: group.condition,
rules: []
};
if (group.data) {
data.data = $.extendext(true, 'replace', {}, group.data);
}
if (options.get_flags) {
var flags = self.getGroupFlags(group.flags, options.get_flags === 'all');
if (!$.isEmptyObject(flags)) {
data.flags = flags;
}
}
group.each(function(model) {
var value = null;
if (model.operator.nb_inputs !== 0) {
value = model.value;
}
var rule = {
id: model.filter.id,
field: model.filter.field,
type: model.filter.type,
input: model.filter.input,
operator: model.operator.type,
value: value
};
if (model.filter.data || model.data) {
rule.data = $.extendext(true, 'replace', {}, model.filter.data, model.data);
}
if (options.get_flags) {
var flags = self.getRuleFlags(model.flags, options.get_flags === 'all');
if (!$.isEmptyObject(flags)) {
rule.flags = flags;
}
}
data.rules.push(rule);
}, function(model) {
data.rules.push(parse(model));
});
return data;
}(this.model.root));
return this.change('getRules', out);
};
/**
* Set rules from object
* @throws RulesError, UndefinedConditionError
* @param data {object}
*/
QueryBuilder.prototype.setRules = function(data) {
if ($.isArray(data)) {
data = {
condition: this.settings.default_condition,
rules: data
};
}
if (!data || !data.rules || (data.rules.length === 0 && !this.settings.allow_empty)) {
Utils.error('RulesParse', 'Incorrect data object passed');
}
this.clear();
this.setRoot(false, data.data, this.parseGroupFlags(data));
data = this.change('setRules', data);
var self = this;
(function add(data, group) {
if (group === null) {
return;
}
if (data.condition === undefined) {
data.condition = self.settings.default_condition;
}
else if (self.settings.conditions.indexOf(data.condition) == -1) {
Utils.error('UndefinedCondition', 'Invalid condition "{0}"', data.condition);
}
group.condition = data.condition;
data.rules.forEach(function(item) {
var model;
if (item.rules && item.rules.length > 0) {
if (self.settings.allow_groups !== -1 && self.settings.allow_groups < group.level) {
self.reset();
Utils.error('RulesParse', 'No more than {0} groups are allowed', self.settings.allow_groups);
}
else {
model = self.addGroup(group, false, item.data, self.parseGroupFlags(item));
if (model === null) {
return;
}
add(item, model);
}
}
else {
if (item.id === undefined) {
Utils.error('RulesParse', 'Missing rule field id');
}
if (item.operator === undefined) {
item.operator = 'equal';
}
model = self.addRule(group, item.data);
if (model === null) {
return;
}
model.filter = self.getFilterById(item.id);
model.operator = self.getOperatorByType(item.operator);
model.flags = self.parseRuleFlags(item);
if (model.operator.nb_inputs !== 0 && item.value !== undefined) {
model.value = item.value;
}
}
});
}(data, this.model.root));
};
/**
* Check if a value is correct for a filter
* @param rule {Rule}
* @param value {string|string[]|undefined}
* @return {array|true}
*/
QueryBuilder.prototype.validateValue = function(rule, value) {
var validation = rule.filter.validation || {};
var result = true;
if (validation.callback) {
result = validation.callback.call(this, value, rule);
}
else {
result = this.validateValueInternal(rule, value);
}
return this.change('validateValue', result, value, rule);
};
/**
* Default validation function
* @throws ConfigError
* @param rule {Rule}
* @param value {string|string[]|undefined}
* @return {array|true}
*/
QueryBuilder.prototype.validateValueInternal = function(rule, value) {
var filter = rule.filter;
var operator = rule.operator;
var validation = filter.validation || {};
var result = true;
var tmp;
if (rule.operator.nb_inputs === 1) {
value = [value];
}
else {
value = value;
}
for (var i = 0; i < operator.nb_inputs; i++) {
switch (filter.input) {
case 'radio':
if (value[i] === undefined) {
result = ['radio_empty'];
break;
}
break;
case 'checkbox':
if (value[i] === undefined || value[i].length === 0) {
result = ['checkbox_empty'];
break;
}
else if (!operator.multiple && value[i].length > 1) {
result = ['operator_not_multiple', operator.type];
break;
}
break;
case 'select':
if (filter.multiple) {
if (value[i] === undefined || value[i].length === 0 || (filter.placeholder && value[i] == filter.placeholder_value)) {
result = ['select_empty'];
break;
}
else if (!operator.multiple && value[i].length > 1) {
result = ['operator_not_multiple', operator.type];
break;
}
}
else {
if (value[i] === undefined || (filter.placeholder && value[i] == filter.placeholder_value)) {
result = ['select_empty'];
break;
}
}
break;
default:
switch (QueryBuilder.types[filter.type]) {
case 'string':
if (value[i] === undefined || value[i].length === 0) {
result = ['string_empty'];
break;
}
if (validation.min !== undefined) {
if (value[i].length < parseInt(validation.min)) {
result = ['string_exceed_min_length', validation.min];
break;
}
}
if (validation.max !== undefined) {
if (value[i].length > parseInt(validation.max)) {
result = ['string_exceed_max_length', validation.max];
break;
}
}
if (validation.format) {
if (typeof validation.format == 'string') {
validation.format = new RegExp(validation.format);
}
if (!validation.format.test(value[i])) {
result = ['string_invalid_format', validation.format];
break;
}
}
break;
case 'number':
if (value[i] === undefined || isNaN(value[i])) {
result = ['number_nan'];
break;
}
if (filter.type == 'integer') {
if (parseInt(value[i]) != value[i]) {
result = ['number_not_integer'];
break;
}
}
else {
if (parseFloat(value[i]) != value[i]) {
result = ['number_not_double'];
break;
}
}
if (validation.min !== undefined) {
if (value[i] < parseFloat(validation.min)) {
result = ['number_exceed_min', validation.min];
break;
}
}
if (validation.max !== undefined) {
if (value[i] > parseFloat(validation.max)) {
result = ['number_exceed_max', validation.max];
break;
}
}
if (validation.step !== undefined && validation.step !== 'any') {
var v = (value[i] / validation.step).toPrecision(14);
if (parseInt(v) != v) {
result = ['number_wrong_step', validation.step];
break;
}
}
break;
case 'datetime':
if (value[i] === undefined || value[i].length === 0) {
result = ['datetime_empty'];
break;
}
// we need MomentJS
if (validation.format) {
if (!('moment' in window)) {
Utils.error('MissingLibrary', 'MomentJS is required for Date/Time validation. Get it here http://momentjs.com');
}
var datetime = moment(value[i], validation.format);
if (!datetime.isValid()) {
result = ['datetime_invalid', validation.format];
break;
}
else {
if (validation.min) {
if (datetime < moment(validation.min, validation.format)) {
result = ['datetime_exceed_min', validation.min];
break;
}
}
if (validation.max) {
if (datetime > moment(validation.max, validation.format)) {
result = ['datetime_exceed_max', validation.max];
break;
}
}
}
}
break;
case 'boolean':
tmp = value[i].trim().toLowerCase();
if (tmp !== 'true' && tmp !== 'false' && tmp !== '1' && tmp !== '0' && value[i] !== 1 && value[i] !== 0) {
result = ['boolean_not_valid'];
break;
}
}
}
if (result !== true) {
break;
}
}
return result;
};
/**
* Returns an incremented group ID
* @return {string}
*/
QueryBuilder.prototype.nextGroupId = function() {
return this.status.id + '_group_' + (this.status.group_id++);
};
/**
* Returns an incremented rule ID
* @return {string}
*/
QueryBuilder.prototype.nextRuleId = function() {
return this.status.id + '_rule_' + (this.status.rule_id++);
};
/**
* Returns the operators for a filter
* @param filter {string|object} (filter id name or filter object)
* @return {object[]}
*/
QueryBuilder.prototype.getOperators = function(filter) {
if (typeof filter == 'string') {
filter = this.getFilterById(filter);
}
var result = [];
for (var i = 0, l = this.operators.length; i < l; i++) {
// filter operators check
if (filter.operators) {
if (filter.operators.indexOf(this.operators[i].type) == -1) {
continue;
}
}
// type check
else if (this.operators[i].apply_to.indexOf(QueryBuilder.types[filter.type]) == -1) {
continue;
}
result.push(this.operators[i]);
}
// keep sort order defined for the filter
if (filter.operators) {
result.sort(function(a, b) {
return filter.operators.indexOf(a.type) - filter.operators.indexOf(b.type);
});
}
return this.change('getOperators', result, filter);
};
/**
* Returns a particular filter by its id
* @throws UndefinedFilterError
* @param filterId {string}
* @return {object|null}
*/
QueryBuilder.prototype.getFilterById = function(id) {
if (id == '-1') {
return null;
}
for (var i = 0, l = this.filters.length; i < l; i++) {
if (this.filters[i].id == id) {
return this.filters[i];
}
}
Utils.error('UndefinedFilter', 'Undefined filter "{0}"', id);
};
/**
* Return a particular operator by its type
* @throws UndefinedOperatorError
* @param type {string}
* @return {object|null}
*/
QueryBuilder.prototype.getOperatorByType = function(type) {
if (type == '-1') {
return null;
}
for (var i = 0, l = this.operators.length; i < l; i++) {
if (this.operators[i].type == type) {
return this.operators[i];
}
}
Utils.error('UndefinedOperator', 'Undefined operator "{0}"', type);
};
/**
* Returns rule value
* @param rule {Rule}
* @return {mixed}
*/
QueryBuilder.prototype.getRuleValue = function(rule) {
var filter = rule.filter;
var operator = rule.operator;
var value = [];
if (filter.valueGetter) {
value = filter.valueGetter.call(this, rule);
}
else {
var $value = rule.$el.find(Selectors.value_container);
for (var i = 0; i < operator.nb_inputs; i++) {
var name = Utils.escapeElementId(rule.id + '_value_' + i);
var tmp;
switch (filter.input) {
case 'radio':
value.push($value.find('[name=' + name + ']:checked').val());
break;
case 'checkbox':
tmp = [];
$value.find('[name=' + name + ']:checked').each(function() {
tmp.push($(this).val());
});
value.push(tmp);
break;
case 'select':
if (filter.multiple) {
tmp = [];
$value.find('[name=' + name + '] option:selected').each(function() {
tmp.push($(this).val());
});
value.push(tmp);
}
else {
value.push($value.find('[name=' + name + '] option:selected').val());
}
break;
default:
value.push($value.find('[name=' + name + ']').val());
}
}
if (operator.nb_inputs === 1) {
value = value[0];
}
// @deprecated
if (filter.valueParser) {
value = filter.valueParser.call(this, rule, value);
}
}
return this.change('getRuleValue', value, rule);
};
/**
* Sets the value of a rule.
* @param rule {Rule}
* @param value {mixed}
*/
QueryBuilder.prototype.setRuleValue = function(rule, value) {
var filter = rule.filter;
var operator = rule.operator;
if (filter.valueSetter) {
filter.valueSetter.call(this, rule, value);
}
else {
var $value = rule.$el.find(Selectors.value_container);
if (operator.nb_inputs == 1) {
value = [value];
}
else {
value = value;
}
for (var i = 0; i < operator.nb_inputs; i++) {
var name = Utils.escapeElementId(rule.id + '_value_' + i);
switch (filter.input) {
case 'radio':
$value.find('[name=' + name + '][value="' + value[i] + '"]').prop('checked', true).trigger('change');
break;
case 'checkbox':
if (!$.isArray(value[i])) {
value[i] = [value[i]];
}
value[i].forEach(function(value) {
$value.find('[name=' + name + '][value="' + value + '"]').prop('checked', true).trigger('change');
});
break;
default:
$value.find('[name=' + name + ']').val(value[i]).trigger('change');
break;
}
}
}
};
/**
* Clean rule flags.
* @param rule {object}
* @return {object}
*/
QueryBuilder.prototype.parseRuleFlags = function(rule) {
var flags = $.extend({}, this.settings.default_rule_flags);
if (rule.readonly) {
$.extend(flags, {
filter_readonly: true,
operator_readonly: true,
value_readonly: true,
no_delete: true
});
}
if (rule.flags) {
$.extend(flags, rule.flags);
}
return this.change('parseRuleFlags', flags, rule);
};
/**
* Get a copy of flags of a rule.
* @param {object} flags
* @param {boolean} all - true to return all flags, false to return only changes from default
* @returns {object}
*/
QueryBuilder.prototype.getRuleFlags = function(flags, all) {
if (all) {
return $.extend({}, flags);
}
else {
var ret = {};
$.each(this.settings.default_rule_flags, function(key, value) {
if (flags[key] !== value) {
ret[key] = flags[key];
}
});
return ret;
}
};
/**
* Clean group flags.
* @param group {object}
* @return {object}
*/
QueryBuilder.prototype.parseGroupFlags = function(group) {
var flags = $.extend({}, this.settings.default_group_flags);
if (group.readonly) {
$.extend(flags, {
condition_readonly: true,
no_delete: true
});
}
if (group.flags) {
$.extend(flags, group.flags);
}
return this.change('parseGroupFlags', flags, group);
};
/**
* Get a copy of flags of a group.
* @param {object} flags
* @param {boolean} all - true to return all flags, false to return only changes from default
* @returns {object}
*/
QueryBuilder.prototype.getGroupFlags = function(flags, all) {
if (all) {
return $.extend({}, flags);
}
else {
var ret = {};
$.each(this.settings.default_group_flags, function(key, value) {
if (flags[key] !== value) {
ret[key] = flags[key];
}
});
return ret;
}
};
/**
* Translate a label
* @param label {string|object}
* @return string
*/
QueryBuilder.prototype.translateLabel = function(label) {
return typeof label == 'object' ? (label[this.settings.lang_code] || label['en']) : label;
};
QueryBuilder.templates.group = '\
<dl id="{{= it.group_id }}" class="rules-group-container"> \
<dt class="rules-group-header"> \
<div class="btn-group pull-right group-actions"> \
<button type="button" class="btn btn-xs btn-success" data-add="rule"> \
<i class="{{= it.icons.add_rule }}"></i> {{= it.lang.add_rule }} \
</button> \
{{? it.settings.allow_groups===-1 || it.settings.allow_groups>=it.level }} \
<button type="button" class="btn btn-xs btn-success" data-add="group"> \
<i class="{{= it.icons.add_group }}"></i> {{= it.lang.add_group }} \
</button> \
{{?}} \
{{? it.level>1 }} \
<button type="button" class="btn btn-xs btn-danger" data-delete="group"> \
<i class="{{= it.icons.remove_group }}"></i> {{= it.lang.delete_group }} \
</button> \
{{?}} \
</div> \
<div class="btn-group group-conditions"> \
{{~ it.conditions: condition }} \
<label class="btn btn-xs btn-primary"> \
<input type="radio" name="{{= it.group_id }}_cond" value="{{= condition }}"> {{= it.lang.conditions[condition] || condition }} \
</label> \
{{~}} \
</div> \
{{? it.settings.display_errors }} \
<div class="error-container"><i class="{{= it.icons.error }}"></i></div> \
{{?}} \
</dt> \
<dd class=rules-group-body> \
<ul class=rules-list></ul> \
</dd> \
</dl>';
QueryBuilder.templates.rule = '\
<li id="{{= it.rule_id }}" class="rule-container"> \
<div class="rule-header"> \
<div class="btn-group pull-right rule-actions"> \
<button type="button" class="btn btn-xs btn-danger" data-delete="rule"> \
<i class="{{= it.icons.remove_rule }}"></i> {{= it.lang.delete_rule }} \
</button> \
</div> \
</div> \
{{? it.settings.display_errors }} \
<div class="error-container"><i class="{{= it.icons.error }}"></i></div> \
{{?}} \
<div class="rule-filter-container"></div> \
<div class="rule-operator-container"></div> \
<div class="rule-value-container"></div> \
</li>';
QueryBuilder.templates.filterSelect = '\
{{ var optgroup = null; }} \
<select class="form-control" name="{{= it.rule.id }}_filter"> \
{{? it.settings.display_empty_filter }} \
<option value="-1">{{= it.settings.select_placeholder }}</option> \
{{?}} \
{{~ it.filters: filter }} \
{{? optgroup !== filter.optgroup }} \
{{? optgroup !== null }}</optgroup>{{?}} \
{{? (optgroup = filter.optgroup) !== null }} \
<optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}"> \
{{?}} \
{{?}} \
<option value="{{= filter.id }}">{{= it.translate(filter.label) }}</option> \
{{~}} \
{{? optgroup !== null }}</optgroup>{{?}} \
</select>';
QueryBuilder.templates.operatorSelect = '\
{{ var optgroup = null; }} \
<select class="form-control" name="{{= it.rule.id }}_operator"> \
{{~ it.operators: operator }} \
{{? optgroup !== operator.optgroup }} \
{{? optgroup !== null }}</optgroup>{{?}} \
{{? (optgroup = operator.optgroup) !== null }} \
<optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}"> \
{{?}} \
{{?}} \
<option value="{{= operator.type }}">{{= it.lang.operators[operator.type] || operator.type }}</option> \
{{~}} \
{{? optgroup !== null }}</optgroup>{{?}} \
</select>';
/**
* Returns group HTML
* @param group_id {string}
* @param level {int}
* @return {string}
*/
QueryBuilder.prototype.getGroupTemplate = function(group_id, level) {
var h = this.templates.group({
builder: this,
group_id: group_id,
level: level,
conditions: this.settings.conditions,
icons: this.icons,
lang: this.lang,
settings: this.settings
});
return this.change('getGroupTemplate', h, level);
};
/**
* Returns rule HTML
* @param rule_id {string}
* @return {string}
*/
QueryBuilder.prototype.getRuleTemplate = function(rule_id) {
var h = this.templates.rule({
builder: this,
rule_id: rule_id,
icons: this.icons,
lang: this.lang,
settings: this.settings
});
return this.change('getRuleTemplate', h);
};
/**
* Returns rule filter <select> HTML
* @param rule {Rule}
* @param filters {array}
* @return {string}
*/
QueryBuilder.prototype.getRuleFilterSelect = function(rule, filters) {
var h = this.templates.filterSelect({
builder: this,
rule: rule,
filters: filters,
icons: this.icons,
lang: this.lang,
settings: this.settings,
translate: this.translateLabel
});
return this.change('getRuleFilterSelect', h, rule);
};
/**
* Returns rule operator <select> HTML
* @param rule {Rule}
* @param operators {object}
* @return {string}
*/
QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) {
var h = this.templates.operatorSelect({
builder: this,
rule: rule,
operators: operators,
icons: this.icons,
lang: this.lang,
settings: this.settings,
translate: this.translateLabel
});
return this.change('getRuleOperatorSelect', h, rule);
};
/**
* Return the rule value HTML
* @param rule {Rule}
* @param filter {object}
* @param value_id {int}
* @return {string}
*/
QueryBuilder.prototype.getRuleInput = function(rule, value_id) {
var filter = rule.filter;
var validation = rule.filter.validation || {};
var name = rule.id + '_value_' + value_id;
var c = filter.vertical ? ' class=block' : '';
var h = '';
if (typeof filter.input == 'function') {
h = filter.input.call(this, rule, name);
}
else {
switch (filter.input) {
case 'radio': case 'checkbox':
Utils.iterateOptions(filter.values, function(key, val) {
h+= '<label' + c + '><input type="' + filter.input + '" name="' + name + '" value="' + key + '"> ' + val + '</label> ';
});
break;
case 'select':
h+= '<select class="form-control" name="' + name + '"' + (filter.multiple ? ' multiple' : '') + '>';
if (filter.placeholder) {
h+= '<option value="' + filter.placeholder_value + '" disabled selected>' + filter.placeholder + '</option>';
}
Utils.iterateOptions(filter.values, function(key, val) {
h+= '<option value="' + key + '">' + val + '</option> ';
});
h+= '</select>';
break;
case 'textarea':
h+= '<textarea class="form-control" name="' + name + '"';
if (filter.size) h+= ' cols="' + filter.size + '"';
if (filter.rows) h+= ' rows="' + filter.rows + '"';
if (validation.min !== undefined) h+= ' minlength="' + validation.min + '"';
if (validation.max !== undefined) h+= ' maxlength="' + validation.max + '"';
if (filter.placeholder) h+= ' placeholder="' + filter.placeholder + '"';
h+= '></textarea>';
break;
default:
switch (QueryBuilder.types[filter.type]) {
case 'number':
h+= '<input class="form-control" type="number" name="' + name + '"';
if (validation.step !== undefined) h+= ' step="' + validation.step + '"';
if (validation.min !== undefined) h+= ' min="' + validation.min + '"';
if (validation.max !== undefined) h+= ' max="' + validation.max + '"';
if (filter.placeholder) h+= ' placeholder="' + filter.placeholder + '"';
if (filter.size) h+= ' size="' + filter.size + '"';
h+= '>';
break;
default:
h+= '<input class="form-control" type="text" name="' + name + '"';
if (filter.placeholder) h+= ' placeholder="' + filter.placeholder + '"';
if (filter.type === 'string' && validation.min !== undefined) h+= ' minlength="' + validation.min + '"';
if (filter.type === 'string' && validation.max !== undefined) h+= ' maxlength="' + validation.max + '"';
if (filter.size) h+= ' size="' + filter.size + '"';
h+= '>';
}
}
}
return this.change('getRuleInput', h, rule, name);
};
// Model CLASS
// ===============================
/**
* Main object storing data model and emitting events
* ---------
* Access Node object stored in jQuery objects
* @param el {jQuery|Node}
* @return {Node}
*/
function Model(el) {
if (!(this instanceof Model)) {
return Model.getModel(el);
}
this.root = null;
this.$ = $(this);
}
$.extend(Model.prototype, {
trigger: function(type) {
this.$.triggerHandler(type, Array.prototype.slice.call(arguments, 1));
return this;
},
on: function() {
this.$.on.apply(this.$, Array.prototype.slice.call(arguments));
return this;
},
off: function() {
this.$.off.apply(this.$, Array.prototype.slice.call(arguments));
return this;
},
once: function() {
this.$.one.apply(this.$, Array.prototype.slice.call(arguments));
return this;
}
});
/**
* Access Node object stored in jQuery objects
* @param el {jQuery|Node}
* @return {Node}
*/
Model.getModel = function(el) {
if (!el) {
return null;
}
else if (el instanceof Node) {
return el;
}
else {
return $(el).data('queryBuilderModel');
}
};
/*
* Define Node properties with getter and setter
* Update events are emitted in the setter through root Model (if any)
*/
function defineModelProperties(obj, fields) {
fields.forEach(function(field) {
Object.defineProperty(obj.prototype, field, {
enumerable: true,
get: function() {
return this.__[field];
},
set: function(value) {
var oldValue = (this.__[field] !== null && typeof this.__[field] == 'object') ?
$.extend({}, this.__[field]) :
this.__[field];
this.__[field] = value;
if (this.model !== null) {
this.model.trigger('update', this, field, value, oldValue);
}
}
});
});
}
// Node abstract CLASS
// ===============================
/**
* @param {Node}
* @param {jQuery}
*/
var Node = function(parent, $el) {
if (!(this instanceof Node)) {
return new Node();
}
Object.defineProperty(this, '__', { value: {} });
$el.data('queryBuilderModel', this);
this.__.level = 1;
this.__.error = null;
this.__.data = undefined;
this.$el = $el;
this.id = $el[0].id;
this.model = null;
this.parent = parent;
};
defineModelProperties(Node, ['level', 'error', 'data', 'flags']);
Object.defineProperty(Node.prototype, 'parent', {
enumerable: true,
get: function() {
return this.__.parent;
},
set: function(value) {
this.__.parent = value;
this.level = value === null ? 1 : value.level + 1;
this.model = value === null ? null : value.model;
}
});
/**
* Check if this Node is the root
* @return {boolean}
*/
Node.prototype.isRoot = function() {
return (this.level === 1);
};
/**
* Return node position inside parent
* @return {int}
*/
Node.prototype.getPos = function() {
if (this.isRoot()) {
return -1;
}
else {
return this.parent.getNodePos(this);
}
};
/**
* Delete self
*/
Node.prototype.drop = function() {
var model = this.model;
if (!this.isRoot()) {
this.parent._removeNode(this);
}
if (model !== null) {
model.trigger('drop', this);
}
};
/**
* Move itself after another Node
* @param {Node}
* @return {Node} self
*/
Node.prototype.moveAfter = function(node) {
if (this.isRoot()) return;
this._move(node.parent, node.getPos() + 1);
return this;
};
/**
* Move itself at the beginning of parent or another Group
* @param {Group,optional}
* @return {Node} self
*/
Node.prototype.moveAtBegin = function(target) {
if (this.isRoot()) return;
if (target === undefined) {
target = this.parent;
}
this._move(target, 0);
return this;
};
/**
* Move itself at the end of parent or another Group
* @param {Group,optional}
* @return {Node} self
*/
Node.prototype.moveAtEnd = function(target) {
if (this.isRoot()) return;
if (target === undefined) {
target = this.parent;
}
this._move(target, target.length() - 1);
return this;
};
/**
* Move itself at specific position of Group
* @param {Group}
* @param {int}
*/
Node.prototype._move = function(group, index) {
this.parent._removeNode(this);
group._appendNode(this, index, false);
if (this.model !== null) {
this.model.trigger('move', this, group, index);
}
};
// GROUP CLASS
// ===============================
/**
* @param {Group}
* @param {jQuery}
*/
var Group = function(parent, $el) {
if (!(this instanceof Group)) {
return new Group(parent, $el);
}
Node.call(this, parent, $el);
this.rules = [];
this.__.condition = null;
};
Group.prototype = Object.create(Node.prototype);
Group.prototype.constructor = Group;
defineModelProperties(Group, ['condition']);
/**
* Empty the Group
*/
Group.prototype.empty = function() {
this.each('reverse', function(rule) {
rule.drop();
}, function(group) {
group.drop();
});
};
/**
* Delete self
*/
Group.prototype.drop = function() {
this.empty();
Node.prototype.drop.call(this);
};
/**
* Return the number of children
* @return {int}
*/
Group.prototype.length = function() {
return this.rules.length;
};
/**
* Add a Node at specified index
* @param {Node}
* @param {int,optional}
* @param {boolean,optional}
* @return {Node} the inserted node
*/
Group.prototype._appendNode = function(node, index, trigger) {
if (index === undefined) {
index = this.length();
}
this.rules.splice(index, 0, node);
node.parent = this;
if (trigger && this.model !== null) {
this.model.trigger('add', node, index);
}
return node;
};
/**
* Add a Group by jQuery element at specified index
* @param {jQuery}
* @param {int,optional}
* @return {Group} the inserted group
*/
Group.prototype.addGroup = function($el, index) {
return this._appendNode(new Group(this, $el), index, true);
};
/**
* Add a Rule by jQuery element at specified index
* @param {jQuery}
* @param {int,optional}
* @return {Rule} the inserted rule
*/
Group.prototype.addRule = function($el, index) {
return this._appendNode(new Rule(this, $el), index, true);
};
/**
* Delete a specific Node
* @param {Node}
* @return {Group} self
*/
Group.prototype._removeNode = function(node) {
var index = this.getNodePos(node);
if (index !== -1) {
node.parent = null;
this.rules.splice(index, 1);
}
return this;
};
/**
* Return position of a child Node
* @param {Node}
* @return {int}
*/
Group.prototype.getNodePos = function(node) {
return this.rules.indexOf(node);
};
/**
* Iterate over all Nodes
* @param {boolean,optional} iterate in reverse order, required if you delete nodes
* @param {function} callback for Rules
* @param {function,optional} callback for Groups
* @return {boolean}
*/
Group.prototype.each = function(reverse, cbRule, cbGroup, context) {
if (typeof reverse == 'function') {
context = cbGroup;
cbGroup = cbRule;
cbRule = reverse;
reverse = false;
}
context = context === undefined ? null : context;
var i = reverse ? this.rules.length - 1 : 0;
var l = reverse ? 0 : this.rules.length - 1;
var c = reverse ? -1 : 1;
var next = function() { return reverse ? i >= l : i <= l; };
var stop = false;
for (; next(); i+= c) {
if (this.rules[i] instanceof Group) {
if (cbGroup !== undefined) {
stop = cbGroup.call(context, this.rules[i]) === false;
}
}
else {
stop = cbRule.call(context, this.rules[i]) === false;
}
if (stop) {
break;
}
}
return !stop;
};
/**
* Return true if the group contains a particular Node
* @param {Node}
* @param {boolean,optional} recursive search
* @return {boolean}
*/
Group.prototype.contains = function(node, deep) {
if (this.getNodePos(node) !== -1) {
return true;
}
else if (!deep) {
return false;
}
else {
// the loop will return with false as soon as the Node is found
return !this.each(function(rule) {
return true;
}, function(group) {
return !group.contains(node, true);
});
}
};
// RULE CLASS
// ===============================
/**
* @param {Group}
* @param {jQuery}
*/
var Rule = function(parent, $el) {
if (!(this instanceof Rule)) {
return new Rule(parent, $el);
}
Node.call(this, parent, $el);
this.__.filter = null;
this.__.operator = null;
this.__.flags = {};
this.__.value = undefined;
};
Rule.prototype = Object.create(Node.prototype);
Rule.prototype.constructor = Rule;
defineModelProperties(Rule, ['filter', 'operator', 'value']);
// EXPORT
// ===============================
QueryBuilder.Group = Group;
QueryBuilder.Rule = Rule;
var Utils = QueryBuilder.utils = {};
/**
* Utility to iterate over radio/checkbox/selection options.
* it accept three formats: array of values, map, array of 1-element maps
*
* @param options {object|array}
* @param tpl {callable} (takes key and text)
*/
Utils.iterateOptions = function(options, tpl) {
if (options) {
if ($.isArray(options)) {
options.forEach(function(entry) {
// array of one-element maps
if ($.isPlainObject(entry)) {
$.each(entry, function(key, val) {
tpl(key, val);
return false; // break after first entry
});
}
// array of values
else {
tpl(entry, entry);
}
});
}
// unordered map
else {
$.each(options, function(key, val) {
tpl(key, val);
});
}
}
};
/**
* Replaces {0}, {1}, ... in a string
* @param str {string}
* @param args,... {mixed}
* @return {string}
*/
Utils.fmt = function(str/*, args*/) {
var args = Array.prototype.slice.call(arguments, 1);
return str.replace(/{([0-9]+)}/g, function(m, i) {
return args[parseInt(i)];
});
};
/**
* Throw an Error object with custom name
* @param type {string}
* @param message {string}
* @param args,... {mixed}
*/
Utils.error = function(type, message/*, args*/) {
var err = new Error(Utils.fmt.apply(null, Array.prototype.slice.call(arguments, 1)));
err.name = type + 'Error';
err.args = Array.prototype.slice.call(arguments, 2);
throw err;
};
/**
* Change type of a value to int or float
* @param value {mixed}
* @param type {string} 'integer', 'double' or anything else
* @param boolAsInt {boolean} return 0 or 1 for booleans
* @return {mixed}
*/
Utils.changeType = function(value, type, boolAsInt) {
switch (type) {
case 'integer': return parseInt(value);
case 'double': return parseFloat(value);
case 'boolean':
var bool = value.trim().toLowerCase() === 'true' || value.trim() === '1' || value === 1;
return boolAsInt ? (bool ? 1 : 0) : bool;
default: return value;
}
};
/**
* Escape string like mysql_real_escape_string
* @param value {string}
* @return {string}
*/
Utils.escapeString = function(value) {
if (typeof value != 'string') {
return value;
}
return value
.replace(/[\0\n\r\b\\\'\"]/g, function(s) {
switch (s) {
case '\0': return '\\0';
case '\n': return '\\n';
case '\r': return '\\r';
case '\b': return '\\b';
default: return '\\' + s;
}
})
// uglify compliant
.replace(/\t/g, '\\t')
.replace(/\x1a/g, '\\Z');
};
/**
* Escape value for use in regex
* @param value {string}
* @return {string}
*/
Utils.escapeRegExp = function(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
};
/**
* Escape HTML element id
* @param value {string}
* @return {string}
*/
Utils.escapeElementId = function(str) {
// Regex based on that suggested by:
// https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
// - escapes : . [ ] ,
// - avoids escaping already escaped values
return (str) ? str.replace(/(\\)?([:.\[\],])/g,
function( $0, $1, $2 ) { return $1 ? $0 : '\\' + $2; }) : str;
};
/**
* Sort objects by grouping them by {key}, preserving initial order when possible
* @param {object[]} items
* @param {string} key
* @returns {object[]}
*/
Utils.groupSort = function(items, key) {
var optgroups = [];
var newItems = [];
items.forEach(function(item) {
var idx;
if (item[key]) {
idx = optgroups.lastIndexOf(item[key]);
if (idx == -1) {
idx = optgroups.length;
}
else {
idx++;
}
}
else {
idx = optgroups.length;
}
optgroups.splice(idx, 0, item[key]);
newItems.splice(idx, 0, item);
});
return newItems;
};
$.fn.queryBuilder = function(option) {
if (this.length > 1) {
Utils.error('Config', 'Unable to initialize on multiple target');
}
var data = this.data('queryBuilder');
var options = (typeof option == 'object' && option) || {};
if (!data && option == 'destroy') {
return this;
}
if (!data) {
this.data('queryBuilder', new QueryBuilder(this, options));
}
if (typeof option == 'string') {
return data[option].apply(data, Array.prototype.slice.call(arguments, 1));
}
return this;
};
$.fn.queryBuilder.constructor = QueryBuilder;
$.fn.queryBuilder.defaults = QueryBuilder.defaults;
$.fn.queryBuilder.extend = QueryBuilder.extend;
$.fn.queryBuilder.define = QueryBuilder.define;
$.fn.queryBuilder.regional = QueryBuilder.regional;
/*!
* jQuery QueryBuilder Awesome Bootstrap Checkbox
* Applies Awesome Bootstrap Checkbox for checkbox and radio inputs.
*/
QueryBuilder.define('bt-checkbox', function(options) {
if (options.font == 'glyphicons') {
var injectCSS = document.createElement('style');
injectCSS.innerHTML = '\
.checkbox input[type=checkbox]:checked + label:after { \
font-family: "Glyphicons Halflings"; \
content: "\\e013"; \
} \
.checkbox label:after { \
padding-left: 4px; \
padding-top: 2px; \
font-size: 9px; \
}';
document.body.appendChild(injectCSS);
}
this.on('getRuleInput.filter', function(h, rule, name) {
var filter = rule.filter;
if ((filter.input === 'radio' || filter.input === 'checkbox') && !filter.plugin) {
h.value = '';
if (!filter.colors) {
filter.colors = {};
}
if (filter.color) {
filter.colors._def_ = filter.color;
}
var style = filter.vertical ? ' style="display:block"' : '';
var i = 0;
Utils.iterateOptions(filter.values, function(key, val) {
var color = filter.colors[key] || filter.colors._def_ || options.color;
var id = name + '_' + (i++);
h.value+= '\
<div' + style + ' class="' + filter.input + ' ' + filter.input + '-' + color + '"> \
<input type="' + filter.input + '" name="' + name + '" id="' + id + '" value="' + key + '"> \
<label for="' + id + '">' + val + '</label> \
</div>';
});
}
});
}, {
font: 'glyphicons',
color: 'default'
});
/*!
* jQuery QueryBuilder Bootstrap Selectpicker
* Applies Bootstrap Select on filters and operators combo-boxes.
*/
/**
* @throws ConfigError
*/
QueryBuilder.define('bt-selectpicker', function(options) {
if (!$.fn.selectpicker || !$.fn.selectpicker.Constructor) {
Utils.error('MissingLibrary', 'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');
}
// init selectpicker
this.on('afterCreateRuleFilters', function(e, rule) {
rule.$el.find(Selectors.rule_filter).removeClass('form-control').selectpicker(options);
});
this.on('afterCreateRuleOperators', function(e, rule) {
rule.$el.find(Selectors.rule_operator).removeClass('form-control').selectpicker(options);
});
// update selectpicker on change
this.on('afterUpdateRuleFilter', function(e, rule) {
rule.$el.find(Selectors.rule_filter).selectpicker('render');
});
this.on('afterUpdateRuleOperator', function(e, rule) {
rule.$el.find(Selectors.rule_operator).selectpicker('render');
});
}, {
container: 'body',
style: 'btn-inverse btn-xs',
width: 'auto',
showIcon: false
});
/*!
* jQuery QueryBuilder Bootstrap Tooltip errors
* Applies Bootstrap Tooltips on validation error messages.
*/
/**
* @throws ConfigError
*/
QueryBuilder.define('bt-tooltip-errors', function(options) {
if (!$.fn.tooltip || !$.fn.tooltip.Constructor || !$.fn.tooltip.Constructor.prototype.fixTitle) {
Utils.error('MissingLibrary', 'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');
}
var self = this;
// add BT Tooltip data
this.on('getRuleTemplate.filter getGroupTemplate.filter', function(h) {
var $h = $(h.value);
$h.find(Selectors.error_container).attr('data-toggle', 'tooltip');
h.value = $h.prop('outerHTML');
});
// init/refresh tooltip when title changes
this.model.on('update', function(e, node, field) {
if (field == 'error' && self.settings.display_errors) {
node.$el.find(Selectors.error_container).eq(0)
.tooltip(options)
.tooltip('hide')
.tooltip('fixTitle');
}
});
}, {
placement: 'right'
});
/*!
* jQuery QueryBuilder Change Filters
* Allows to change available filters after plugin initialization.
*/
QueryBuilder.extend({
/**
* Change the filters of the builder
* @throws ChangeFilterError
* @param {boolean,optional} delete rules using old filters
* @param {object[]} new filters
*/
setFilters: function(delete_orphans, filters) {
var self = this;
if (filters === undefined) {
filters = delete_orphans;
delete_orphans = false;
}
filters = this.checkFilters(filters);
filters = this.change('setFilters', filters);
var filtersIds = filters.map(function(filter) {
return filter.id;
});
// check for orphans
if (!delete_orphans) {
(function checkOrphans(node) {
node.each(
function(rule) {
if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
Utils.error('ChangeFilter', 'A rule is using filter "{0}"', rule.filter.id);
}
},
checkOrphans
);
}(this.model.root));
}
// replace filters
this.filters = filters;
// apply on existing DOM
(function updateBuilder(node) {
node.each(true,
function(rule) {
if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
rule.drop();
}
else {
self.createRuleFilters(rule);
rule.$el.find(Selectors.rule_filter).val(rule.filter ? rule.filter.id : '-1');
}
},
updateBuilder
);
}(this.model.root));
// update plugins
if (this.settings.plugins) {
if (this.settings.plugins['unique-filter']) {
this.updateDisabledFilters();
}
if (this.settings.plugins['bt-selectpicker']) {
this.$el.find(Selectors.rule_filter).selectpicker('render');
}
}
// reset the default_filter if does not exist anymore
if (this.settings.default_filter) {
try {
this.getFilterById(this.settings.default_filter);
}
catch (e) {
this.settings.default_filter = null;
}
}
this.trigger('afterSetFilters', filters);
},
/**
* Adds a new filter to the builder
* @param {object|object[]} the new filter
* @param {mixed,optional} numeric index or '#start' or '#end'
*/
addFilter: function(new_filters, position) {
if (position === undefined || position == '#end') {
position = this.filters.length;
}
else if (position == '#start') {
position = 0;
}
if (!$.isArray(new_filters)) {
new_filters = [new_filters];
}
var filters = $.extend(true, [], this.filters);
// numeric position
if (parseInt(position) == position) {
Array.prototype.splice.apply(filters, [position, 0].concat(new_filters));
}
else {
// after filter by its id
if (this.filters.some(function(filter, index) {
if (filter.id == position) {
position = index + 1;
return true;
}
})) {
Array.prototype.splice.apply(filters, [position, 0].concat(new_filters));
}
// defaults to end of list
else {
Array.prototype.push.apply(filters, new_filters);
}
}
this.setFilters(filters);
},
/**
* Removes a filter from the builder
* @param {string|string[]} the filter id
* @param {boolean,optional} delete rules using old filters
*/
removeFilter: function(filter_ids, delete_orphans) {
var filters = $.extend(true, [], this.filters);
if (typeof filter_ids === 'string') {
filter_ids = [filter_ids];
}
filters = filters.filter(function(filter) {
return filter_ids.indexOf(filter.id) === -1;
});
this.setFilters(delete_orphans, filters);
}
});
/*!
* jQuery QueryBuilder Filter Description
* Provides three ways to display a description about a filter: inline, Bootsrap Popover or Bootbox.
*/
/**
* @throws ConfigError
*/
QueryBuilder.define('filter-description', function(options) {
/**
* INLINE
*/
if (options.mode === 'inline') {
this.on('afterUpdateRuleFilter', function(e, rule) {
var $p = rule.$el.find('p.filter-description');
if (!rule.filter || !rule.filter.description) {
$p.hide();
}
else {
if ($p.length === 0) {
$p = $('<p class="filter-description"></p>');
$p.appendTo(rule.$el);
}
else {
$p.show();
}
$p.html('<i class="' + options.icon + '"></i> ' + rule.filter.description);
}
});
}
/**
* POPOVER
*/
else if (options.mode === 'popover') {
if (!$.fn.popover || !$.fn.popover.Constructor || !$.fn.popover.Constructor.prototype.fixTitle) {
Utils.error('MissingLibrary', 'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com');
}
this.on('afterUpdateRuleFilter', function(e, rule) {
var $b = rule.$el.find('button.filter-description');
if (!rule.filter || !rule.filter.description) {
$b.hide();
if ($b.data('bs.popover')) {
$b.popover('hide');
}
}
else {
if ($b.length === 0) {
$b = $('<button type="button" class="btn btn-xs btn-info filter-description" data-toggle="popover"><i class="' + options.icon + '"></i></button>');
$b.prependTo(rule.$el.find(Selectors.rule_actions));
$b.popover({
placement: 'left',
container: 'body',
html: true
});
$b.on('mouseout', function() {
$b.popover('hide');
});
}
else {
$b.show();
}
$b.data('bs.popover').options.content = rule.filter.description;
if ($b.attr('aria-describedby')) {
$b.popover('show');
}
}
});
}
/**
* BOOTBOX
*/
else if (options.mode === 'bootbox') {
if (!('bootbox' in window)) {
Utils.error('MissingLibrary', 'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com');
}
this.on('afterUpdateRuleFilter', function(e, rule) {
var $b = rule.$el.find('button.filter-description');
if (!rule.filter || !rule.filter.description) {
$b.hide();
}
else {
if ($b.length === 0) {
$b = $('<button type="button" class="btn btn-xs btn-info filter-description" data-toggle="bootbox"><i class="' + options.icon + '"></i></button>');
$b.prependTo(rule.$el.find(Selectors.rule_actions));
$b.on('click', function() {
bootbox.alert($b.data('description'));
});
}
$b.data('description', rule.filter.description);
}
});
}
}, {
icon: 'glyphicon glyphicon-info-sign',
mode: 'popover'
});
/*!
* jQuery QueryBuilder Invert
* Allows to invert a rule operator, a group condition or the entire builder.
*/
QueryBuilder.defaults({
operatorOpposites: {
'equal': 'not_equal',
'not_equal': 'equal',
'in': 'not_in',
'not_in': 'in',
'less': 'greater_or_equal',
'less_or_equal': 'greater',
'greater': 'less_or_equal',
'greater_or_equal': 'less',
'between': 'not_between',
'not_between': 'between',
'begins_with': 'not_begins_with',
'not_begins_with': 'begins_with',
'contains': 'not_contains',
'not_contains': 'contains',
'ends_with': 'not_ends_with',
'not_ends_with': 'ends_with',
'is_empty': 'is_not_empty',
'is_not_empty': 'is_empty',
'is_null': 'is_not_null',
'is_not_null': 'is_null',
'date_equal': 'date_not_equal',
'date_less': 'date_greater_or_equal',
'date_greater': 'date_less_or_equal',
'date_not_equal': 'date_equal',
'date_greater_or_equal': 'date_less',
'date_less_or_equal': 'date_greater'
},
conditionOpposites: {
'AND': 'OR',
'OR': 'AND'
}
});
QueryBuilder.define('invert', function(options) {
var self = this;
/**
* Bind events
*/
this.on('afterInit', function() {
self.$el.on('click.queryBuilder', '[data-invert=group]', function() {
var $group = $(this).closest(Selectors.group_container);
self.invert(Model($group), options);
});
if (options.display_rules_button && options.invert_rules) {
self.$el.on('click.queryBuilder', '[data-invert=rule]', function() {
var $rule = $(this).closest(Selectors.rule_container);
self.invert(Model($rule), options);
});
}
});
/**
* Modify templates
*/
this.on('getGroupTemplate.filter', function(h, level) {
var $h = $(h.value);
$h.find(Selectors.condition_container).after('<button type="button" class="btn btn-xs btn-default" data-invert="group"><i class="' + options.icon + '"></i> ' + self.lang.invert + '</button>');
h.value = $h.prop('outerHTML');
});
if (options.display_rules_button && options.invert_rules) {
this.on('getRuleTemplate.filter', function(h) {
var $h = $(h.value);
$h.find(Selectors.rule_actions).prepend('<button type="button" class="btn btn-xs btn-default" data-invert="rule"><i class="' + options.icon + '"></i> ' + self.lang.invert + '</button>');
h.value = $h.prop('outerHTML');
});
}
}, {
icon: 'glyphicon glyphicon-random',
recursive: true,
invert_rules: true,
display_rules_button: false,
silent_fail: false
});
QueryBuilder.extend({
/**
* Invert a Group, a Rule or the whole builder
* @throws InvertConditionError, InvertOperatorError
* @param {Node,optional}
* @param {object,optional}
*/
invert: function(node, options) {
if (!(node instanceof Node)) {
if (!this.model.root) return;
options = node;
node = this.model.root;
}
if (typeof options != 'object') options = {};
if (options.recursive === undefined) options.recursive = true;
if (options.invert_rules === undefined) options.invert_rules = true;
if (options.silent_fail === undefined) options.silent_fail = false;
if (options.trigger === undefined) options.trigger = true;
if (node instanceof Group) {
// invert group condition
if (this.settings.conditionOpposites[node.condition]) {
node.condition = this.settings.conditionOpposites[node.condition];
}
else if (!options.silent_fail) {
Utils.error('InvertCondition', 'Unknown inverse of condition "{0}"', node.condition);
}
// recursive call
if (options.recursive) {
var tempOpts = $.extend({}, options, { trigger: false });
node.each(function(rule) {
if (options.invert_rules) {
this.invert(rule, tempOpts);
}
}, function(group) {
this.invert(group, tempOpts);
}, this);
}
}
else if (node instanceof Rule) {
if (node.operator && !node.filter.no_invert) {
// invert rule operator
if (this.settings.operatorOpposites[node.operator.type]) {
var invert = this.settings.operatorOpposites[node.operator.type];
// check if the invert is "authorized"
if (!node.filter.operators || node.filter.operators.indexOf(invert) != -1) {
node.operator = this.getOperatorByType(invert);
}
}
else if (!options.silent_fail) {
Utils.error('InvertOperator', 'Unknown inverse of operator "{0}"', node.operator.type);
}
}
}
if (options.trigger) {
this.trigger('afterInvert', node, options);
}
}
});
/*!
* jQuery QueryBuilder MongoDB Support
* Allows to export rules as a MongoDB find object as well as populating the builder from a MongoDB object.
*/
// DEFAULT CONFIG
// ===============================
QueryBuilder.defaults({
mongoOperators: {
equal: function(v) { return v[0]; },
not_equal: function(v) { return { '$ne': v[0] }; },
in: function(v) { return { '$in': v }; },
not_in: function(v) { return { '$nin': v }; },
less: function(v) { return { '$lt': v[0] }; },
less_or_equal: function(v) { return { '$lte': v[0] }; },
greater: function(v) { return { '$gt': v[0] }; },
greater_or_equal: function(v) { return { '$gte': v[0] }; },
between: function(v) { return { '$gte': v[0], '$lte': v[1] }; },
not_between: function(v) { return { '$lt': v[0], '$gt': v[1] }; },
begins_with: function(v) { return { '$regex': '^' + Utils.escapeRegExp(v[0]) }; },
not_begins_with: function(v) { return { '$regex': '^(?!' + Utils.escapeRegExp(v[0]) + ')' }; },
contains: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) }; },
not_contains: function(v) { return { '$regex': '^((?!' + Utils.escapeRegExp(v[0]) + ').)*$', '$options': 's' }; },
ends_with: function(v) { return { '$regex': Utils.escapeRegExp(v[0]) + '$' }; },
not_ends_with: function(v) { return { '$regex': '(?<!' + Utils.escapeRegExp(v[0]) + ')$' }; },
is_empty: function(v) { return ''; },
is_not_empty: function(v) { return { '$ne': '' }; },
is_null: function(v) { return null; },
is_not_null: function(v) { return { '$ne': null }; }
},
mongoRuleOperators: {
$ne: function(v) {
v = v.$ne;
return {
'val': v,
'op': v === null ? 'is_not_null' : (v === '' ? 'is_not_empty' : 'not_equal')
};
},
eq: function(v) {
return {
'val': v,
'op': v === null ? 'is_null' : (v === '' ? 'is_empty' : 'equal')
};
},
$regex: function(v) {
v = v.$regex;
if (v.slice(0, 4) == '^(?!' && v.slice(-1) == ')') {
return { 'val': v.slice(4, -1), 'op': 'not_begins_with' };
}
else if (v.slice(0, 5) == '^((?!' && v.slice(-5) == ').)*$') {
return { 'val': v.slice(5, -5), 'op': 'not_contains' };
}
else if (v.slice(0, 4) == '(?<!' && v.slice(-2) == ')$') {
return { 'val': v.slice(4, -2), 'op': 'not_ends_with' };
}
else if (v.slice(-1) == '$') {
return { 'val': v.slice(0, -1), 'op': 'ends_with' };
}
else if (v.slice(0, 1) == '^') {
return { 'val': v.slice(1), 'op': 'begins_with' };
}
else {
return { 'val': v, 'op': 'contains' };
}
},
between: function(v) { return { 'val': [v.$gte, v.$lte], 'op': 'between' }; },
not_between: function(v) { return { 'val': [v.$lt, v.$gt], 'op': 'not_between' }; },
$in: function(v) { return { 'val': v.$in, 'op': 'in' }; },
$nin: function(v) { return { 'val': v.$nin, 'op': 'not_in' }; },
$lt: function(v) { return { 'val': v.$lt, 'op': 'less' }; },
$lte: function(v) { return { 'val': v.$lte, 'op': 'less_or_equal' }; },
$gt: function(v) { return { 'val': v.$gt, 'op': 'greater' }; },
$gte: function(v) { return { 'val': v.$gte, 'op': 'greater_or_equal' }; }
}
});
// PUBLIC METHODS
// ===============================
QueryBuilder.extend({
/**
* Get rules as MongoDB query
* @throws UndefinedMongoConditionError, UndefinedMongoOperatorError
* @param data {object} (optional) rules
* @return {object}
*/
getMongo: function(data) {
data = (data === undefined) ? this.getRules() : data;
var self = this;
return (function parse(data) {
if (!data.condition) {
data.condition = self.settings.default_condition;
}
if (['AND', 'OR'].indexOf(data.condition.toUpperCase()) === -1) {
Utils.error('UndefinedMongoCondition', 'Unable to build MongoDB query with condition "{0}"', data.condition);
}
if (!data.rules) {
return {};
}
var parts = [];
data.rules.forEach(function(rule) {
if (rule.rules && rule.rules.length > 0) {
parts.push(parse(rule));
}
else {
var mdb = self.settings.mongoOperators[rule.operator];
var ope = self.getOperatorByType(rule.operator);
var values = [];
if (mdb === undefined) {
Utils.error('UndefinedMongoOperator', 'Unknown MongoDB operation for operator "{0}"', rule.operator);
}
if (ope.nb_inputs !== 0) {
if (!(rule.value instanceof Array)) {
rule.value = [rule.value];
}
rule.value.forEach(function(v) {
values.push(Utils.changeType(v, rule.type, false));
});
}
var part = {};
part[rule.field] = mdb.call(self, values);
parts.push(part);
}
});
var res = {};
if (parts.length > 0) {
res['$' + data.condition.toLowerCase()] = parts;
}
return res;
}(data));
},
/**
* Convert MongoDB object to rules
* @throws MongoParseError, UndefinedMongoConditionError, UndefinedMongoOperatorError
* @param data {object} query object
* @return {object}
*/
getRulesFromMongo: function(data) {
if (data === undefined || data === null) {
return null;
}
var self = this;
var conditions = {
'$and': 'AND',
'$or': 'OR'
};
return (function parse(data) {
var topKeys = Object.keys(data);
if (topKeys.length > 1) {
Utils.error('MongoParse', 'Invalid MongoDB query format');
}
if (!conditions[topKeys[0].toLowerCase()]) {
Utils.error('UndefinedMongoCondition', 'Unable to build MongoDB query with condition "{0}"', topKeys[0]);
}
var rules = data[topKeys[0]];
var parts = [];
rules.forEach(function(rule) {
var keys = Object.keys(rule);
if (conditions[keys[0].toLowerCase()]) {
parts.push(parse(rule));
}
else {
var field = keys[0];
var value = rule[field];
var operator = determineMongoOperator(value, field);
if (operator === undefined) {
Utils.error('MongoParse', 'Invalid MongoDB query format');
}
var mdbrl = self.settings.mongoRuleOperators[operator];
if (mdbrl === undefined) {
Utils.error('UndefinedMongoOperator', 'JSON Rule operation unknown for operator "{0}"', operator);
}
var opVal = mdbrl.call(self, value);
parts.push({
id: self.change('getMongoDBFieldID', field, value),
field: field,
operator: opVal.op,
value: opVal.val
});
}
});
var res = {};
if (parts.length > 0) {
res.condition = conditions[topKeys[0].toLowerCase()];
res.rules = parts;
}
return res;
}(data));
},
/**
* Set rules from MongoDB object
* @param data {object}
*/
setRulesFromMongo: function(data) {
this.setRules(this.getRulesFromMongo(data));
}
});
/**
* Find which operator is used in a MongoDB sub-object
* @param {mixed} value
* @param {string} field
* @return {string|undefined}
*/
function determineMongoOperator(value, field) {
if (value !== null && typeof value == 'object') {
var subkeys = Object.keys(value);
if (subkeys.length === 1) {
return subkeys[0];
}
else {
if (value.$gte !== undefined && value.$lte !== undefined) {
return 'between';
}
if (value.$lt !== undefined && value.$gt !== undefined) {
return 'not_between';
}
else if (value.$regex !== undefined) { // optional $options
return '$regex';
}
else {
return;
}
}
}
else {
return 'eq';
}
}
/*!
* jQuery QueryBuilder Sortable
* Enables drag & drop sort of rules.
*/
Selectors.rule_and_group_containers = Selectors.rule_container + ', ' + Selectors.group_container;
QueryBuilder.define('sortable', function(options) {
/**
* Init HTML5 drag and drop
*/
this.on('afterInit', function(e) {
// configure jQuery to use dataTransfer
$.event.props.push('dataTransfer');
var placeholder;
var src;
var self = e.builder;
// only add "draggable" attribute when hovering drag handle
// preventing text select bug in Firefox
self.$el.on('mouseover.queryBuilder', '.drag-handle', function() {
self.$el.find(Selectors.rule_and_group_containers).attr('draggable', true);
});
self.$el.on('mouseout.queryBuilder', '.drag-handle', function() {
self.$el.find(Selectors.rule_and_group_containers).removeAttr('draggable');
});
// dragstart: create placeholder and hide current element
self.$el.on('dragstart.queryBuilder', '[draggable]', function(e) {
e.stopPropagation();
// notify drag and drop (only dummy text)
e.dataTransfer.setData('text', 'drag');
src = Model(e.target);
// Chrome glitchs
// - helper invisible if hidden immediately
// - "dragend" is called immediately if we modify the DOM directly
setTimeout(function() {
var ph = $('<div class="rule-placeholder"> </div>');
ph.css('min-height', src.$el.height());
placeholder = src.parent.addRule(ph, src.getPos());
src.$el.hide();
}, 0);
});
// dragenter: move the placeholder
self.$el.on('dragenter.queryBuilder', '[draggable]', function(e) {
e.preventDefault();
e.stopPropagation();
if (placeholder) {
moveSortableToTarget(placeholder, $(e.target));
}
});
// dragover: prevent glitches
self.$el.on('dragover.queryBuilder', '[draggable]', function(e) {
e.preventDefault();
e.stopPropagation();
});
// drop: move current element
self.$el.on('drop.queryBuilder', function(e) {
e.preventDefault();
e.stopPropagation();
moveSortableToTarget(src, $(e.target));
});
// dragend: show current element and delete placeholder
self.$el.on('dragend.queryBuilder', '[draggable]', function(e) {
e.preventDefault();
e.stopPropagation();
src.$el.show();
placeholder.drop();
self.$el.find(Selectors.rule_and_group_containers).removeAttr('draggable');
self.trigger('afterMove', src);
src = placeholder = null;
});
});
/**
* Remove drag handle from non-sortable rules
*/
this.on('parseRuleFlags.filter', function(flags) {
if (flags.value.no_sortable === undefined) {
flags.value.no_sortable = options.default_no_sortable;
}
});
this.on('afterApplyRuleFlags', function(e, rule) {
if (rule.flags.no_sortable) {
rule.$el.find('.drag-handle').remove();
}
});
/**
* Remove drag handle from non-sortable groups
*/
this.on('parseGroupFlags.filter', function(flags) {
if (flags.value.no_sortable === undefined) {
flags.value.no_sortable = options.default_no_sortable;
}
});
this.on('afterApplyGroupFlags', function(e, group) {
if (group.flags.no_sortable) {
group.$el.find('.drag-handle').remove();
}
});
/**
* Modify templates
*/
this.on('getGroupTemplate.filter', function(h, level) {
if (level > 1) {
var $h = $(h.value);
$h.find(Selectors.condition_container).after('<div class="drag-handle"><i class="' + options.icon + '"></i></div>');
h.value = $h.prop('outerHTML');
}
});
this.on('getRuleTemplate.filter', function(h) {
var $h = $(h.value);
$h.find(Selectors.rule_header).after('<div class="drag-handle"><i class="' + options.icon + '"></i></div>');
h.value = $h.prop('outerHTML');
});
}, {
default_no_sortable: false,
icon: 'glyphicon glyphicon-sort'
});
/**
* Move an element (placeholder or actual object) depending on active target
* @param {Node}
* @param {jQuery}
*/
function moveSortableToTarget(element, target) {
var parent;
// on rule
parent = target.closest(Selectors.rule_container);
if (parent.length) {
element.moveAfter(Model(parent));
return;
}
// on group header
parent = target.closest(Selectors.group_header);
if (parent.length) {
parent = target.closest(Selectors.group_container);
element.moveAtBegin(Model(parent));
return;
}
// on group
parent = target.closest(Selectors.group_container);
if (parent.length) {
element.moveAtEnd(Model(parent));
return;
}
}
/*!
* jQuery QueryBuilder SQL Support
* Allows to export rules as a SQL WHERE statement as well as populating the builder from an SQL query.
*/
// DEFAULT CONFIG
// ===============================
QueryBuilder.defaults({
/* operators for internal -> SQL conversion */
sqlOperators: {
equal: { op: '= ?' },
not_equal: { op: '!= ?' },
in: { op: 'IN(?)', sep: ', ' },
not_in: { op: 'NOT IN(?)', sep: ', ' },
less: { op: '< ?' },
less_or_equal: { op: '<= ?' },
greater: { op: '> ?' },
greater_or_equal: { op: '>= ?' },
between: { op: 'BETWEEN ?', sep: ' and ' },
not_between: { op: 'NOT BETWEEN ?', sep: ' and ' },
begins_with: { op: 'LIKE(?)', mod: '{0}%' },
not_begins_with: { op: 'NOT LIKE(?)', mod: '{0}%' },
contains: { op: 'LIKE(?)', mod: '%{0}%' },
not_contains: { op: 'NOT LIKE(?)', mod: '%{0}%' },
ends_with: { op: 'LIKE(?)', mod: '%{0}' },
not_ends_with: { op: 'NOT LIKE(?)', mod: '%{0}' },
is_empty: { op: '= \'\'' },
is_not_empty: { op: '!= \'\'' },
is_null: { op: 'IS NULL' },
is_not_null: { op: 'IS NOT NULL' },
date_equal: { op: '=?', mod: '#{0}#' },
date_not_equal: { op: '!=?', mod: '#{0}#' },
date_less: { op: '<?', mod: '#{0}#' },
date_less_or_equal: { op: '<= ?', mod: '#{0}#' },
date_greater: { op: '>?', mod: '#{0}#' },
date_greater_or_equal: { op: '>=?', mod: '#{0}#' }
},
/* operators for SQL -> internal conversion */
sqlRuleOperator: {
'=': function(v) {
return {
val: v,
op: v === '' ? 'is_empty' : 'equal'
};
},
'!=': function(v) {
return {
val: v,
op: v === '' ? 'is_not_empty' : 'not_equal'
};
},
'LIKE': function(v) {
if (v.slice(0, 1) == '%' && v.slice(-1) == '%') {
return {
val: v.slice(1, -1),
op: 'contains'
};
}
else if (v.slice(0, 1) == '%') {
return {
val: v.slice(1),
op: 'ends_with'
};
}
else if (v.slice(-1) == '%') {
return {
val: v.slice(0, -1),
op: 'begins_with'
};
}
else {
Utils.error('SQLParse', 'Invalid value for LIKE operator "{0}"', v);
}
},
'IN': function(v) { return { val: v, op: 'in' }; },
'NOT IN': function(v) { return { val: v, op: 'not_in' }; },
'<': function(v) { return { val: v, op: 'less' }; },
'<=': function(v) { return { val: v, op: 'less_or_equal' }; },
'>': function(v) { return { val: v, op: 'greater' }; },
'>=': function(v) { return { val: v, op: 'greater_or_equal' }; },
'BETWEEN': function(v) { return { val: v, op: 'between' }; },
'NOT BETWEEN': function(v) { return { val: v, op: 'not_between' }; },
'IS': function(v) {
if (v !== null) {
Utils.error('SQLParse', 'Invalid value for IS operator');
}
return { val: null, op: 'is_null' };
},
'IS NOT': function(v) {
if (v !== null) {
Utils.error('SQLParse', 'Invalid value for IS operator');
}
return { val: null, op: 'is_not_null' };
}
},
/* statements for internal -> SQL conversion */
sqlStatements: {
'question_mark': function() {
var params = [];
return {
add: function(rule, value) {
params.push(value);
return '?';
},
run: function() {
return params;
}
};
},
'numbered': function(char) {
if (!char || char.length > 1) char = '$';
var index = 0;
var params = [];
return {
add: function(rule, value) {
params.push(value);
index++;
return char + index;
},
run: function() {
return params;
}
};
},
'named': function(char) {
if (!char || char.length > 1) char = ':';
var indexes = {};
var params = {};
return {
add: function(rule, value) {
if (!indexes[rule.field]) indexes[rule.field] = 1;
var key = rule.field + '_' + (indexes[rule.field]++);
params[key] = value;
return char + key;
},
run: function() {
return params;
}
};
}
},
/* statements for SQL -> internal conversion */
sqlRuleStatement: {
'question_mark': function(values) {
var index = 0;
return {
parse: function(v) {
return v == '?' ? values[index++] : v;
},
esc: function(sql) {
return sql.replace(/\?/g, '\'?\'');
}
};
},
'numbered': function(values, char) {
if (!char || char.length > 1) char = '$';
var regex1 = new RegExp('^\\' + char + '[0-9]+$');
var regex2 = new RegExp('\\' + char + '([0-9]+)', 'g');
return {
parse: function(v) {
return regex1.test(v) ? values[v.slice(1) - 1] : v;
},
esc: function(sql) {
return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
}
};
},
'named': function(values, char) {
if (!char || char.length > 1) char = ':';
var regex1 = new RegExp('^\\' + char);
var regex2 = new RegExp('\\' + char + '(' + Object.keys(values).join('|') + ')', 'g');
return {
parse: function(v) {
return regex1.test(v) ? values[v.slice(1)] : v;
},
esc: function(sql) {
return sql.replace(regex2, '\'' + (char == '$' ? '$$' : char) + '$1\'');
}
};
}
}
});
// PUBLIC METHODS
// ===============================
QueryBuilder.extend({
/**
* Get rules as SQL query
* @throws UndefinedSQLConditionError, UndefinedSQLOperatorError
* @param stmt {boolean|string} use prepared statements - false, 'question_mark', 'numbered', 'numbered(@)', 'named', 'named(@)'
* @param nl {bool} output with new lines
* @param data {object} (optional) rules
* @return {object}
*/
getSQL: function(stmt, nl, data) {
data = (data === undefined) ? this.getRules() : data;
nl = (nl === true) ? '\n' : ' ';
if (stmt === true) stmt = 'question_mark';
if (typeof stmt == 'string') {
var config = getStmtConfig(stmt);
stmt = this.settings.sqlStatements[config[1]](config[2]);
}
var self = this;
var sql = (function parse(data) {
if (!data.condition) {
data.condition = self.settings.default_condition;
}
if (['AND', 'OR'].indexOf(data.condition.toUpperCase()) === -1) {
Utils.error('UndefinedSQLCondition', 'Unable to build SQL query with condition "{0}"', data.condition);
}
if (!data.rules) {
return '';
}
var parts = [];
data.rules.forEach(function(rule) {
if (rule.rules && rule.rules.length > 0) {
parts.push('(' + nl + parse(rule) + nl + ')' + nl);
}
else {
var sql = self.settings.sqlOperators[rule.operator];
var ope = self.getOperatorByType(rule.operator);
var value = '';
if (sql === undefined) {
Utils.error('UndefinedSQLOperator', 'Unknown SQL operation for operator "{0}"', rule.operator);
}
if (ope.nb_inputs !== 0) {
if (!(rule.value instanceof Array)) {
rule.value = [rule.value];
}
rule.value.forEach(function(v, i) {
if (i > 0) {
value+= sql.sep;
}
if (rule.type == 'integer' || rule.type == 'double' || rule.type == 'boolean') {
v = Utils.changeType(v, rule.type, true);
}
else if (!stmt) {
v = Utils.escapeString(v);
}
if (sql.mod) {
v = Utils.fmt(sql.mod, v);
}
if (stmt) {
value+= stmt.add(rule, v);
}
else {
if (typeof v == 'string') {
v = '\'' + v + '\'';
}
value+= v;
}
});
}
parts.push(rule.field + ' ' + sql.op.replace(/\?/, value));
}
});
return parts.join(' ' + data.condition + nl);
}(data));
if (stmt) {
return {
sql: sql,
params: stmt.run()
};
}
else {
return {
sql: sql
};
}
},
/**
* Convert SQL to rules
* @throws ConfigError, SQLParseError, UndefinedSQLOperatorError
* @param data {object} query object
* @param stmt {boolean|string} use prepared statements - false, 'question_mark', 'numbered', 'numbered(@)', 'named', 'named(@)'
* @return {object}
*/
getRulesFromSQL: function(data, stmt) {
if (!('SQLParser' in window)) {
Utils.error('MissingLibrary', 'SQLParser is required to parse SQL queries. Get it here https://github.com/mistic100/sql-parser');
}
var self = this;
if (typeof data == 'string') {
data = { sql: data };
}
if (stmt === true) stmt = 'question_mark';
if (typeof stmt == 'string') {
var config = getStmtConfig(stmt);
stmt = this.settings.sqlRuleStatement[config[1]](data.params, config[2]);
}
if (stmt) {
data.sql = stmt.esc(data.sql);
}
if (data.sql.toUpperCase().indexOf('SELECT') !== 0) {
data.sql = 'SELECT * FROM table WHERE ' + data.sql;
}
var parsed = SQLParser.parse(data.sql);
if (!parsed.where) {
Utils.error('SQLParse', 'No WHERE clause found');
}
var out = {
condition: this.settings.default_condition,
rules: []
};
var curr = out;
(function flatten(data, i) {
// it's a node
if (['AND', 'OR'].indexOf(data.operation.toUpperCase()) !== -1) {
// create a sub-group if the condition is not the same and it's not the first level
if (i > 0 && curr.condition != data.operation.toUpperCase()) {
curr.rules.push({
condition: self.settings.default_condition,
rules: []
});
curr = curr.rules[curr.rules.length - 1];
}
curr.condition = data.operation.toUpperCase();
i++;
// some magic !
var next = curr;
flatten(data.left, i);
curr = next;
flatten(data.right, i);
}
// it's a leaf
else {
if (data.left.value === undefined || data.right.value === undefined) {
Utils.error('SQLParse', 'Missing field and/or value');
}
if ($.isPlainObject(data.right.value)) {
Utils.error('SQLParse', 'Value format not supported for {0}.', data.left.value);
}
// convert array
var value;
if ($.isArray(data.right.value)) {
value = data.right.value.map(function(v) {
return v.value;
});
}
else {
value = data.right.value;
}
// get actual values
if (stmt) {
if ($.isArray(value)) {
value = value.map(stmt.parse);
}
else {
value = stmt.parse(value);
}
}
// convert operator
var operator = data.operation.toUpperCase();
if (operator == '<>') operator = '!=';
var sqlrl;
if (operator == 'NOT LIKE') {
sqlrl = self.settings.sqlRuleOperator['LIKE'];
}
else {
sqlrl = self.settings.sqlRuleOperator[operator];
}
if (sqlrl === undefined) {
Utils.error('UndefinedSQLOperator', 'Invalid SQL operation "{0}".', data.operation);
}
var opVal = sqlrl.call(this, value, data.operation);
if (operator == 'NOT LIKE') opVal.op = 'not_' + opVal.op;
var left_value = data.left.values.join('.');
curr.rules.push({
id: self.change('getSQLFieldID', left_value, value),
field: left_value,
operator: opVal.op,
value: opVal.val
});
}
}(parsed.where.conditions, 0));
return out;
},
/**
* Set rules from SQL
* @param data {object}
*/
setRulesFromSQL: function(data, stmt) {
this.setRules(this.getRulesFromSQL(data, stmt));
}
});
function getStmtConfig(stmt) {
var config = stmt.match(/(question_mark|numbered|named)(?:\((.)\))?/);
if (!config) config = [null, 'question_mark', undefined];
return config;
}
/*!
* jQuery QueryBuilder Unique Filter
* Allows to define some filters as "unique": ie which can be used for only one rule, globally or in the same group.
*/
QueryBuilder.define('unique-filter', function() {
this.status.used_filters = {};
this.on('afterUpdateRuleFilter', this.updateDisabledFilters);
this.on('afterDeleteRule', this.updateDisabledFilters);
this.on('afterCreateRuleFilters', this.applyDisabledFilters);
this.on('afterReset', this.clearDisabledFilters);
this.on('afterClear', this.clearDisabledFilters);
});
QueryBuilder.extend({
updateDisabledFilters: function(e) {
var self = e ? e.builder : this;
self.status.used_filters = {};
if (!self.model) {
return;
}
// get used filters
(function walk(group) {
group.each(function(rule) {
if (rule.filter && rule.filter.unique) {
if (!self.status.used_filters[rule.filter.id]) {
self.status.used_filters[rule.filter.id] = [];
}
if (rule.filter.unique == 'group') {
self.status.used_filters[rule.filter.id].push(rule.parent);
}
}
}, function(group) {
walk(group);
});
}(self.model.root));
self.applyDisabledFilters(e);
},
clearDisabledFilters: function(e) {
var self = e ? e.builder : this;
self.status.used_filters = {};
self.applyDisabledFilters(e);
},
applyDisabledFilters: function(e) {
var self = e ? e.builder : this;
// re-enable everything
self.$el.find(Selectors.filter_container + ' option').prop('disabled', false);
// disable some
$.each(self.status.used_filters, function(filterId, groups) {
if (groups.length === 0) {
self.$el.find(Selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
}
else {
groups.forEach(function(group) {
group.each(function(rule) {
rule.$el.find(Selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop('disabled', true);
});
});
}
});
// update Selectpicker
if (self.settings.plugins && self.settings.plugins['bt-selectpicker']) {
self.$el.find(Selectors.rule_filter).selectpicker('render');
}
}
});
/*!
* jQuery QueryBuilder 2.3.3
* Locale: English (en)
* Author: Damien "Mistic" Sorel, http://www.strangeplanet.fr
* Licensed under MIT (http://opensource.org/licenses/MIT)
*/
QueryBuilder.regional['en'] = {
"__locale": "English (en)",
"__author": "Damien \"Mistic\" Sorel, http://www.strangeplanet.fr",
"add_rule": "Add rule",
"add_group": "Add group",
"delete_rule": "Delete",
"delete_group": "Delete",
"conditions": {
"AND": "AND",
"OR": "OR"
},
"operators": {
"equal": "equal",
"not_equal": "not equal",
"in": "in",
"not_in": "not in",
"less": "less",
"less_or_equal": "less or equal",
"greater": "greater",
"greater_or_equal": "greater or equal",
"between": "between",
"not_between": "not between",
"begins_with": "begins with",
"not_begins_with": "doesn't begin with",
"contains": "contains",
"not_contains": "doesn't contain",
"ends_with": "ends with",
"not_ends_with": "doesn't end with",
"is_empty": "is empty",
"is_not_empty": "is not empty",
"is_null": "is null",
"is_not_null": "is not null",
"date_equal": "date equal",
"date_not_equal": "date not equal",
"date_less": "date less",
"date_less_or_equal": "date less or equal",
"date_greater": "date greater",
"date_greater_or_equal": "date greater or equal"
},
"errors": {
"no_filter": "No filter selected",
"empty_group": "The group is empty",
"radio_empty": "No value selected",
"checkbox_empty": "No value selected",
"select_empty": "No value selected",
"string_empty": "Empty value",
"string_exceed_min_length": "Must contain at least {0} characters",
"string_exceed_max_length": "Must not contain more than {0} characters",
"string_invalid_format": "Invalid format ({0})",
"number_nan": "Not a number",
"number_not_integer": "Not an integer",
"number_not_double": "Not a real number",
"number_exceed_min": "Must be greater than {0}",
"number_exceed_max": "Must be lower than {0}",
"number_wrong_step": "Must be a multiple of {0}",
"datetime_empty": "Empty value",
"datetime_invalid": "Invalid date format ({0})",
"datetime_exceed_min": "Must be after {0}",
"datetime_exceed_max": "Must be before {0}",
"boolean_not_valid": "Not a boolean",
"operator_not_multiple": "Operator {0} cannot accept multiple values"
},
"invert": "Invert"
};
QueryBuilder.defaults({ lang_code: 'en' });
}));
(function($,undefined){var $window=$(window);function UTCDate(){return new Date(Date.UTC.apply(Date,arguments))}function UTCToday(){var today=new Date;return UTCDate(today.getFullYear(),today.getMonth(),today.getDate())}function alias(method){return function(){return this[method].apply(this,arguments)}}var DateArray=function(){var extras={get:function(i){return this.slice(i)[0]},contains:function(d){var val=d&&d.valueOf();for(var i=0,l=this.length;i<l;i++)if(this[i].valueOf()===val)return i;return-1},remove:function(i){this.splice(i,1)},replace:function(new_array){if(!new_array)return;if(!$.isArray(new_array))new_array=[new_array];this.clear();this.push.apply(this,new_array)},clear:function(){this.splice(0)},copy:function(){var a=new DateArray;a.replace(this);return a}};return function(){var a=[];a.push.apply(a,arguments);$.extend(a,extras);return a}}();var Datepicker=function(element,options){this.dates=new DateArray;this.viewDate=UTCToday();this.focusDate=null;this._process_options(options);this.element=$(element);this.isInline=false;this.isInput=this.element.is("input");this.component=this.element.is(".date")?this.element.find(".add-on, .input-group-addon, .btn"):false;this.hasInput=this.component&&this.element.find("input").length;if(this.component&&this.component.length===0)this.component=false;this.picker=$(DPGlobal.template);this._buildEvents();this._attachEvents();if(this.isInline){this.picker.addClass("datepicker-inline").appendTo(this.element)}else{this.picker.addClass("datepicker-dropdown dropdown-menu")}if(this.o.rtl){this.picker.addClass("datepicker-rtl")}this.viewMode=this.o.startView;if(this.o.calendarWeeks)this.picker.find("tfoot th.today").attr("colspan",function(i,val){return parseInt(val)+1});this._allow_update=false;this.setStartDate(this._o.startDate);this.setEndDate(this._o.endDate);this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);this.fillDow();this.fillMonths();this._allow_update=true;this.update();this.showMode();if(this.isInline){this.show()}};Datepicker.prototype={constructor:Datepicker,_process_options:function(opts){this._o=$.extend({},this._o,opts);var o=this.o=$.extend({},this._o);var lang=o.language;if(!dates[lang]){lang=lang.split("-")[0];if(!dates[lang])lang=defaults.language}o.language=lang;switch(o.startView){case 2:case"decade":o.startView=2;break;case 1:case"year":o.startView=1;break;default:o.startView=0}switch(o.minViewMode){case 1:case"months":o.minViewMode=1;break;case 2:case"years":o.minViewMode=2;break;default:o.minViewMode=0}o.startView=Math.max(o.startView,o.minViewMode);if(o.multidate!==true){o.multidate=Number(o.multidate)||false;if(o.multidate!==false)o.multidate=Math.max(0,o.multidate);else o.multidate=1}o.multidateSeparator=String(o.multidateSeparator);o.weekStart%=7;o.weekEnd=(o.weekStart+6)%7;var format=DPGlobal.parseFormat(o.format);if(o.startDate!==-Infinity){if(!!o.startDate){if(o.startDate instanceof Date)o.startDate=this._local_to_utc(this._zero_time(o.startDate));else o.startDate=DPGlobal.parseDate(o.startDate,format,o.language)}else{o.startDate=-Infinity}}if(o.endDate!==Infinity){if(!!o.endDate){if(o.endDate instanceof Date)o.endDate=this._local_to_utc(this._zero_time(o.endDate));else o.endDate=DPGlobal.parseDate(o.endDate,format,o.language)}else{o.endDate=Infinity}}o.daysOfWeekDisabled=o.daysOfWeekDisabled||[];if(!$.isArray(o.daysOfWeekDisabled))o.daysOfWeekDisabled=o.daysOfWeekDisabled.split(/[,\s]*/);o.daysOfWeekDisabled=$.map(o.daysOfWeekDisabled,function(d){return parseInt(d,10)});var plc=String(o.orientation).toLowerCase().split(/\s+/g),_plc=o.orientation.toLowerCase();plc=$.grep(plc,function(word){return/^auto|left|right|top|bottom$/.test(word)});o.orientation={x:"auto",y:"auto"};if(!_plc||_plc==="auto");else if(plc.length===1){switch(plc[0]){case"top":case"bottom":o.orientation.y=plc[0];break;case"left":case"right":o.orientation.x=plc[0];break}}else{_plc=$.grep(plc,function(word){return/^left|right$/.test(word)});o.orientation.x=_plc[0]||"auto";_plc=$.grep(plc,function(word){return/^top|bottom$/.test(word)});o.orientation.y=_plc[0]||"auto"}},_events:[],_secondaryEvents:[],_applyEvents:function(evs){for(var i=0,el,ch,ev;i<evs.length;i++){el=evs[i][0];if(evs[i].length===2){ch=undefined;ev=evs[i][1]}else if(evs[i].length===3){ch=evs[i][1];ev=evs[i][2]}el.on(ev,ch)}},_unapplyEvents:function(evs){for(var i=0,el,ev,ch;i<evs.length;i++){el=evs[i][0];if(evs[i].length===2){ch=undefined;ev=evs[i][1]}else if(evs[i].length===3){ch=evs[i][1];ev=evs[i][2]}el.off(ev,ch)}},_buildEvents:function(){if(this.isInput){this._events=[[this.element,{focus:$.proxy(this.show,this),keyup:$.proxy(function(e){if($.inArray(e.keyCode,[27,37,39,38,40,32,13,9])===-1)this.update()},this),keydown:$.proxy(this.keydown,this)}]]}else if(this.component&&this.hasInput){this._events=[[this.element.find("input"),{focus:$.proxy(this.show,this),keyup:$.proxy(function(e){if($.inArray(e.keyCode,[27,37,39,38,40,32,13,9])===-1)this.update()},this),keydown:$.proxy(this.keydown,this)}],[this.component,{click:$.proxy(this.show,this)}]]}else if(this.element.is("div")){this.isInline=true}else{this._events=[[this.element,{click:$.proxy(this.show,this)}]]}this._events.push([this.element,"*",{blur:$.proxy(function(e){this._focused_from=e.target},this)}],[this.element,{blur:$.proxy(function(e){this._focused_from=e.target},this)}]);this._secondaryEvents=[[this.picker,{click:$.proxy(this.click,this)}],[$(window),{resize:$.proxy(this.place,this)}],[$(document),{"mousedown touchstart":$.proxy(function(e){if(!(this.element.is(e.target)||this.element.find(e.target).length||this.picker.is(e.target)||this.picker.find(e.target).length)){this.hide()}},this)}]]},_attachEvents:function(){this._detachEvents();this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents();this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(event,altdate){var date=altdate||this.dates.get(-1),local_date=this._utc_to_local(date);this.element.trigger({type:event,date:local_date,dates:$.map(this.dates,this._utc_to_local),format:$.proxy(function(ix,format){if(arguments.length===0){ix=this.dates.length-1;format=this.o.format}else if(typeof ix==="string"){format=ix;ix=this.dates.length-1}format=format||this.o.format;var date=this.dates.get(ix);return DPGlobal.formatDate(date,format,this.o.language)},this)})},show:function(){if(!this.isInline)this.picker.appendTo("body");this.picker.show();this.place();this._attachSecondaryEvents();this._trigger("show")},hide:function(){if(this.isInline)return;if(!this.picker.is(":visible"))return;this.focusDate=null;this.picker.hide().detach();this._detachSecondaryEvents();this.viewMode=this.o.startView;this.showMode();if(this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val()))this.setValue();this._trigger("hide")},remove:function(){this.hide();this._detachEvents();this._detachSecondaryEvents();this.picker.remove();delete this.element.data().datepicker;if(!this.isInput){delete this.element.data().date}},_utc_to_local:function(utc){return utc&&new Date(utc.getTime()+utc.getTimezoneOffset()*6e4)},_local_to_utc:function(local){return local&&new Date(local.getTime()-local.getTimezoneOffset()*6e4)},_zero_time:function(local){return local&&new Date(local.getFullYear(),local.getMonth(),local.getDate())},_zero_utc_time:function(utc){return utc&&new Date(Date.UTC(utc.getUTCFullYear(),utc.getUTCMonth(),utc.getUTCDate()))},getDates:function(){return $.map(this.dates,this._utc_to_local)},getUTCDates:function(){return $.map(this.dates,function(d){return new Date(d)})},getDate:function(){return this._utc_to_local(this.getUTCDate())},getUTCDate:function(){return new Date(this.dates.get(-1))},setDates:function(){var args=$.isArray(arguments[0])?arguments[0]:arguments;this.update.apply(this,args);this._trigger("changeDate");this.setValue()},setUTCDates:function(){var args=$.isArray(arguments[0])?arguments[0]:arguments;this.update.apply(this,$.map(args,this._utc_to_local));this._trigger("changeDate");this.setValue()},setDate:alias("setDates"),setUTCDate:alias("setUTCDates"),setValue:function(){var formatted=this.getFormattedDate();if(!this.isInput){if(this.component){this.element.find("input").val(formatted).change()}}else{this.element.val(formatted).change()}},getFormattedDate:function(format){if(format===undefined)format=this.o.format;var lang=this.o.language;return $.map(this.dates,function(d){return DPGlobal.formatDate(d,format,lang)}).join(this.o.multidateSeparator)},setStartDate:function(startDate){this._process_options({startDate:startDate});this.update();this.updateNavArrows()},setEndDate:function(endDate){this._process_options({endDate:endDate});this.update();this.updateNavArrows()},setDaysOfWeekDisabled:function(daysOfWeekDisabled){this._process_options({daysOfWeekDisabled:daysOfWeekDisabled});this.update();this.updateNavArrows()},place:function(){if(this.isInline)return;var calendarWidth=this.picker.outerWidth(),calendarHeight=this.picker.outerHeight(),visualPadding=10,windowWidth=$window.width(),windowHeight=$window.height(),scrollTop=$window.scrollTop();var zIndex=parseInt(this.element.parents().filter(function(){return $(this).css("z-index")!=="auto"}).first().css("z-index"))+10;var offset=this.component?this.component.parent().offset():this.element.offset();var height=this.component?this.component.outerHeight(true):this.element.outerHeight(false);var width=this.component?this.component.outerWidth(true):this.element.outerWidth(false);var left=offset.left,top=offset.top;this.picker.removeClass("datepicker-orient-top datepicker-orient-bottom "+"datepicker-orient-right datepicker-orient-left");if(this.o.orientation.x!=="auto"){this.picker.addClass("datepicker-orient-"+this.o.orientation.x);if(this.o.orientation.x==="right")left-=calendarWidth-width}else{this.picker.addClass("datepicker-orient-left");if(offset.left<0)left-=offset.left-visualPadding;else if(offset.left+calendarWidth>windowWidth)left=windowWidth-calendarWidth-visualPadding}var yorient=this.o.orientation.y,top_overflow,bottom_overflow;if(yorient==="auto"){top_overflow=-scrollTop+offset.top-calendarHeight;bottom_overflow=scrollTop+windowHeight-(offset.top+height+calendarHeight);if(Math.max(top_overflow,bottom_overflow)===bottom_overflow)yorient="top";else yorient="bottom"}this.picker.addClass("datepicker-orient-"+yorient);if(yorient==="top")top+=height;else top-=calendarHeight+parseInt(this.picker.css("padding-top"));this.picker.css({top:top,left:left,zIndex:zIndex})},_allow_update:true,update:function(){if(!this._allow_update)return;var oldDates=this.dates.copy(),dates=[],fromArgs=false;if(arguments.length){$.each(arguments,$.proxy(function(i,date){if(date instanceof Date)date=this._local_to_utc(date);dates.push(date)},this));fromArgs=true}else{dates=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val();if(dates&&this.o.multidate)dates=dates.split(this.o.multidateSeparator);else dates=[dates];delete this.element.data().date}dates=$.map(dates,$.proxy(function(date){return DPGlobal.parseDate(date,this.o.format,this.o.language)},this));dates=$.grep(dates,$.proxy(function(date){return date<this.o.startDate||date>this.o.endDate||!date},this),true);this.dates.replace(dates);if(this.dates.length)this.viewDate=new Date(this.dates.get(-1));else if(this.viewDate<this.o.startDate)this.viewDate=new Date(this.o.startDate);else if(this.viewDate>this.o.endDate)this.viewDate=new Date(this.o.endDate);if(fromArgs){this.setValue()}else if(dates.length){if(String(oldDates)!==String(this.dates))this._trigger("changeDate")}if(!this.dates.length&&oldDates.length)this._trigger("clearDate");this.fill()},fillDow:function(){var dowCnt=this.o.weekStart,html="<tr>";if(this.o.calendarWeeks){var cell='<th class="cw"> </th>';html+=cell;this.picker.find(".datepicker-days thead tr:first-child").prepend(cell)}while(dowCnt<this.o.weekStart+7){html+='<th class="dow">'+dates[this.o.language].daysMin[dowCnt++%7]+"</th>"}html+="</tr>";this.picker.find(".datepicker-days thead").append(html)},fillMonths:function(){var html="",i=0;while(i<12){html+='<span class="month">'+dates[this.o.language].monthsShort[i++]+"</span>"}this.picker.find(".datepicker-months td").html(html)},setRange:function(range){if(!range||!range.length)delete this.range;else this.range=$.map(range,function(d){return d.valueOf()});this.fill()},getClassNames:function(date){var cls=[],year=this.viewDate.getUTCFullYear(),month=this.viewDate.getUTCMonth(),today=new Date;if(date.getUTCFullYear()<year||date.getUTCFullYear()===year&&date.getUTCMonth()<month){cls.push("old")}else if(date.getUTCFullYear()>year||date.getUTCFullYear()===year&&date.getUTCMonth()>month){cls.push("new")}if(this.focusDate&&date.valueOf()===this.focusDate.valueOf())cls.push("focused");if(this.o.todayHighlight&&date.getUTCFullYear()===today.getFullYear()&&date.getUTCMonth()===today.getMonth()&&date.getUTCDate()===today.getDate()){cls.push("today")}if(this.dates.contains(date)!==-1)cls.push("active");if(date.valueOf()<this.o.startDate||date.valueOf()>this.o.endDate||$.inArray(date.getUTCDay(),this.o.daysOfWeekDisabled)!==-1){cls.push("disabled")}if(this.range){if(date>this.range[0]&&date<this.range[this.range.length-1]){cls.push("range")}if($.inArray(date.valueOf(),this.range)!==-1){cls.push("selected")}}return cls},fill:function(){var d=new Date(this.viewDate),year=d.getUTCFullYear(),month=d.getUTCMonth(),startYear=this.o.startDate!==-Infinity?this.o.startDate.getUTCFullYear():-Infinity,startMonth=this.o.startDate!==-Infinity?this.o.startDate.getUTCMonth():-Infinity,endYear=this.o.endDate!==Infinity?this.o.endDate.getUTCFullYear():Infinity,endMonth=this.o.endDate!==Infinity?this.o.endDate.getUTCMonth():Infinity,todaytxt=dates[this.o.language].today||dates["en"].today||"",cleartxt=dates[this.o.language].clear||dates["en"].clear||"",tooltip;this.picker.find(".datepicker-days thead th.datepicker-switch").text(dates[this.o.language].months[month]+" "+year);this.picker.find("tfoot th.today").text(todaytxt).toggle(this.o.todayBtn!==false);this.picker.find("tfoot th.clear").text(cleartxt).toggle(this.o.clearBtn!==false);this.updateNavArrows();this.fillMonths();var prevMonth=UTCDate(year,month-1,28),day=DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(),prevMonth.getUTCMonth());prevMonth.setUTCDate(day);prevMonth.setUTCDate(day-(prevMonth.getUTCDay()-this.o.weekStart+7)%7);var nextMonth=new Date(prevMonth);nextMonth.setUTCDate(nextMonth.getUTCDate()+42);nextMonth=nextMonth.valueOf();var html=[];var clsName;while(prevMonth.valueOf()<nextMonth){if(prevMonth.getUTCDay()===this.o.weekStart){html.push("<tr>");if(this.o.calendarWeeks){var ws=new Date(+prevMonth+(this.o.weekStart-prevMonth.getUTCDay()-7)%7*864e5),th=new Date(Number(ws)+(7+4-ws.getUTCDay())%7*864e5),yth=new Date(Number(yth=UTCDate(th.getUTCFullYear(),0,1))+(7+4-yth.getUTCDay())%7*864e5),calWeek=(th-yth)/864e5/7+1;html.push('<td class="cw">'+calWeek+"</td>")}}clsName=this.getClassNames(prevMonth);clsName.push("day");if(this.o.beforeShowDay!==$.noop){var before=this.o.beforeShowDay(this._utc_to_local(prevMonth));if(before===undefined)before={};else if(typeof before==="boolean")before={enabled:before};else if(typeof before==="string")before={classes:before};if(before.enabled===false)clsName.push("disabled");if(before.classes)clsName=clsName.concat(before.classes.split(/\s+/));if(before.tooltip)tooltip=before.tooltip}clsName=$.unique(clsName);html.push('<td class="'+clsName.join(" ")+'"'+(tooltip?' title="'+tooltip+'"':"")+">"+prevMonth.getUTCDate()+"</td>");if(prevMonth.getUTCDay()===this.o.weekEnd){html.push("</tr>")}prevMonth.setUTCDate(prevMonth.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(html.join(""));var months=this.picker.find(".datepicker-months").find("th:eq(1)").text(year).end().find("span").removeClass("active");$.each(this.dates,function(i,d){if(d.getUTCFullYear()===year)months.eq(d.getUTCMonth()).addClass("active")});if(year<startYear||year>endYear){months.addClass("disabled")}if(year===startYear){months.slice(0,startMonth).addClass("disabled")}if(year===endYear){months.slice(endMonth+1).addClass("disabled")}html="";year=parseInt(year/10,10)*10;var yearCont=this.picker.find(".datepicker-years").find("th:eq(1)").text(year+"-"+(year+9)).end().find("td");year-=1;var years=$.map(this.dates,function(d){return d.getUTCFullYear()}),classes;for(var i=-1;i<11;i++){classes=["year"];if(i===-1)classes.push("old");else if(i===10)classes.push("new");if($.inArray(year,years)!==-1)classes.push("active");if(year<startYear||year>endYear)classes.push("disabled");html+='<span class="'+classes.join(" ")+'">'+year+"</span>";year+=1}yearCont.html(html)},updateNavArrows:function(){if(!this._allow_update)return;var d=new Date(this.viewDate),year=d.getUTCFullYear(),month=d.getUTCMonth();switch(this.viewMode){case 0:if(this.o.startDate!==-Infinity&&year<=this.o.startDate.getUTCFullYear()&&month<=this.o.startDate.getUTCMonth()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.o.endDate!==Infinity&&year>=this.o.endDate.getUTCFullYear()&&month>=this.o.endDate.getUTCMonth()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break;case 1:case 2:if(this.o.startDate!==-Infinity&&year<=this.o.startDate.getUTCFullYear()){this.picker.find(".prev").css({visibility:"hidden"})}else{this.picker.find(".prev").css({visibility:"visible"})}if(this.o.endDate!==Infinity&&year>=this.o.endDate.getUTCFullYear()){this.picker.find(".next").css({visibility:"hidden"})}else{this.picker.find(".next").css({visibility:"visible"})}break}},click:function(e){e.preventDefault();var target=$(e.target).closest("span, td, th"),year,month,day;if(target.length===1){switch(target[0].nodeName.toLowerCase()){case"th":switch(target[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var dir=DPGlobal.modes[this.viewMode].navStep*(target[0].className==="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,dir);this._trigger("changeMonth",this.viewDate);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,dir);if(this.viewMode===1)this._trigger("changeYear",this.viewDate);break}this.fill();break;case"today":var date=new Date;date=UTCDate(date.getFullYear(),date.getMonth(),date.getDate(),0,0,0);this.showMode(-2);var which=this.o.todayBtn==="linked"?null:"view";this._setDate(date,which);break;case"clear":var element;if(this.isInput)element=this.element;else if(this.component)element=this.element.find("input");if(element)element.val("").change();this.update();this._trigger("changeDate");if(this.o.autoclose)this.hide();break}break;case"span":if(!target.is(".disabled")){this.viewDate.setUTCDate(1);if(target.is(".month")){day=1;month=target.parent().find("span").index(target);year=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(month);this._trigger("changeMonth",this.viewDate);if(this.o.minViewMode===1){this._setDate(UTCDate(year,month,day))}}else{day=1;month=0;year=parseInt(target.text(),10)||0;this.viewDate.setUTCFullYear(year);this._trigger("changeYear",this.viewDate);if(this.o.minViewMode===2){this._setDate(UTCDate(year,month,day))}}this.showMode(-1);this.fill()}break;case"td":if(target.is(".day")&&!target.is(".disabled")){day=parseInt(target.text(),10)||1;year=this.viewDate.getUTCFullYear();month=this.viewDate.getUTCMonth();if(target.is(".old")){if(month===0){month=11;year-=1}else{month-=1}}else if(target.is(".new")){if(month===11){month=0;year+=1}else{month+=1}}this._setDate(UTCDate(year,month,day))}break}}if(this.picker.is(":visible")&&this._focused_from){$(this._focused_from).focus()}delete this._focused_from},_toggle_multidate:function(date){var ix=this.dates.contains(date);if(!date){this.dates.clear()}else if(ix!==-1){this.dates.remove(ix)}else{this.dates.push(date)}if(typeof this.o.multidate==="number")while(this.dates.length>this.o.multidate)this.dates.remove(0)},_setDate:function(date,which){if(!which||which==="date")this._toggle_multidate(date&&new Date(date));if(!which||which==="view")this.viewDate=date&&new Date(date);this.fill();this.setValue();this._trigger("changeDate");var element;if(this.isInput){element=this.element}else if(this.component){element=this.element.find("input")}if(element){element.change()}if(this.o.autoclose&&(!which||which==="date")){this.hide()}},moveMonth:function(date,dir){if(!date)return undefined;if(!dir)return date;var new_date=new Date(date.valueOf()),day=new_date.getUTCDate(),month=new_date.getUTCMonth(),mag=Math.abs(dir),new_month,test;dir=dir>0?1:-1;if(mag===1){test=dir===-1?function(){return new_date.getUTCMonth()===month}:function(){return new_date.getUTCMonth()!==new_month};new_month=month+dir;new_date.setUTCMonth(new_month);if(new_month<0||new_month>11)new_month=(new_month+12)%12}else{for(var i=0;i<mag;i++)new_date=this.moveMonth(new_date,dir);new_month=new_date.getUTCMonth();new_date.setUTCDate(day);test=function(){return new_month!==new_date.getUTCMonth()}}while(test()){new_date.setUTCDate(--day);new_date.setUTCMonth(new_month)}return new_date},moveYear:function(date,dir){return this.moveMonth(date,dir*12)},dateWithinRange:function(date){return date>=this.o.startDate&&date<=this.o.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){if(e.keyCode===27)this.show();return}var dateChanged=false,dir,newDate,newViewDate,focusDate=this.focusDate||this.viewDate;switch(e.keyCode){case 27:if(this.focusDate){this.focusDate=null;this.viewDate=this.dates.get(-1)||this.viewDate;this.fill()}else this.hide();e.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;dir=e.keyCode===37?-1:1;if(e.ctrlKey){newDate=this.moveYear(this.dates.get(-1)||UTCToday(),dir);newViewDate=this.moveYear(focusDate,dir);this._trigger("changeYear",this.viewDate)}else if(e.shiftKey){newDate=this.moveMonth(this.dates.get(-1)||UTCToday(),dir);newViewDate=this.moveMonth(focusDate,dir);this._trigger("changeMonth",this.viewDate)}else{newDate=new Date(this.dates.get(-1)||UTCToday());newDate.setUTCDate(newDate.getUTCDate()+dir);newViewDate=new Date(focusDate);newViewDate.setUTCDate(focusDate.getUTCDate()+dir)}if(this.dateWithinRange(newDate)){this.focusDate=this.viewDate=newViewDate;this.setValue();this.fill();e.preventDefault()}break;case 38:case 40:if(!this.o.keyboardNavigation)break;dir=e.keyCode===38?-1:1;if(e.ctrlKey){newDate=this.moveYear(this.dates.get(-1)||UTCToday(),dir);newViewDate=this.moveYear(focusDate,dir);this._trigger("changeYear",this.viewDate)}else if(e.shiftKey){newDate=this.moveMonth(this.dates.get(-1)||UTCToday(),dir);newViewDate=this.moveMonth(focusDate,dir);this._trigger("changeMonth",this.viewDate)}else{newDate=new Date(this.dates.get(-1)||UTCToday());newDate.setUTCDate(newDate.getUTCDate()+dir*7);newViewDate=new Date(focusDate);newViewDate.setUTCDate(focusDate.getUTCDate()+dir*7)}if(this.dateWithinRange(newDate)){this.focusDate=this.viewDate=newViewDate;this.setValue();this.fill();e.preventDefault()}break;case 32:break;case 13:focusDate=this.focusDate||this.dates.get(-1)||this.viewDate;this._toggle_multidate(focusDate);dateChanged=true;this.focusDate=null;this.viewDate=this.dates.get(-1)||this.viewDate;this.setValue();this.fill();if(this.picker.is(":visible")){e.preventDefault();if(this.o.autoclose)this.hide()}break;case 9:this.focusDate=null;this.viewDate=this.dates.get(-1)||this.viewDate;this.fill();this.hide();break}if(dateChanged){if(this.dates.length)this._trigger("changeDate");else this._trigger("clearDate");var element;if(this.isInput){element=this.element}else if(this.component){element=this.element.find("input")}if(element){element.change()}}},showMode:function(dir){if(dir){this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+dir))}this.picker.find(">div").hide().filter(".datepicker-"+DPGlobal.modes[this.viewMode].clsName).css("display","block");this.updateNavArrows()}};var DateRangePicker=function(element,options){this.element=$(element);this.inputs=$.map(options.inputs,function(i){return i.jquery?i[0]:i});delete options.inputs;$(this.inputs).datepicker(options).bind("changeDate",$.proxy(this.dateUpdated,this));this.pickers=$.map(this.inputs,function(i){return $(i).data("datepicker")});this.updateDates()};DateRangePicker.prototype={updateDates:function(){this.dates=$.map(this.pickers,function(i){return i.getUTCDate()});this.updateRanges()},updateRanges:function(){var range=$.map(this.dates,function(d){return d.valueOf()});$.each(this.pickers,function(i,p){p.setRange(range)})},dateUpdated:function(e){if(this.updating)return;this.updating=true;var dp=$(e.target).data("datepicker"),new_date=dp.getUTCDate(),i=$.inArray(e.target,this.inputs),l=this.inputs.length;if(i===-1)return;$.each(this.pickers,function(i,p){if(!p.getUTCDate())p.setUTCDate(new_date)});if(new_date<this.dates[i]){while(i>=0&&new_date<this.dates[i]){this.pickers[i--].setUTCDate(new_date)}}else if(new_date>this.dates[i]){while(i<l&&new_date>this.dates[i]){this.pickers[i++].setUTCDate(new_date)}}this.updateDates();delete this.updating},remove:function(){$.map(this.pickers,function(p){p.remove()});delete this.element.data().datepicker}};function opts_from_el(el,prefix){var data=$(el).data(),out={},inkey,replace=new RegExp("^"+prefix.toLowerCase()+"([A-Z])");prefix=new RegExp("^"+prefix.toLowerCase());function re_lower(_,a){return a.toLowerCase()}for(var key in data)if(prefix.test(key)){inkey=key.replace(replace,re_lower);out[inkey]=data[key]}return out}function opts_from_locale(lang){var out={};if(!dates[lang]){lang=lang.split("-")[0];if(!dates[lang])return}var d=dates[lang];$.each(locale_opts,function(i,k){if(k in d)out[k]=d[k]});return out}var old=$.fn.datepicker;$.fn.datepicker=function(option){var args=Array.apply(null,arguments);args.shift();var internal_return;this.each(function(){var $this=$(this),data=$this.data("datepicker"),options=typeof option==="object"&&option;if(!data){var elopts=opts_from_el(this,"date"),xopts=$.extend({},defaults,elopts,options),locopts=opts_from_locale(xopts.language),opts=$.extend({},defaults,locopts,elopts,options);if($this.is(".input-daterange")||opts.inputs){var ropts={inputs:opts.inputs||$this.find("input").toArray()};$this.data("datepicker",data=new DateRangePicker(this,$.extend(opts,ropts)))}else{$this.data("datepicker",data=new Datepicker(this,opts))}}if(typeof option==="string"&&typeof data[option]==="function"){internal_return=data[option].apply(data,args);if(internal_return!==undefined)return false}});if(internal_return!==undefined)return internal_return;else return this};var defaults=$.fn.datepicker.defaults={autoclose:false,beforeShowDay:$.noop,calendarWeeks:false,clearBtn:false,daysOfWeekDisabled:[],endDate:Infinity,forceParse:true,format:"mm/dd/yyyy",keyboardNavigation:true,language:"en",minViewMode:0,multidate:false,multidateSeparator:",",orientation:"auto",rtl:false,startDate:-Infinity,startView:0,todayBtn:false,todayHighlight:false,weekStart:0};var locale_opts=$.fn.datepicker.locale_opts=["format","rtl","weekStart"];$.fn.datepicker.Constructor=Datepicker;var dates=$.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}};var DPGlobal={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(year){return year%4===0&&year%100!==0||year%400===0},getDaysInMonth:function(year,month){return[31,DPGlobal.isLeapYear(year)?29:28,31,30,31,30,31,31,30,31,30,31][month]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(format){var separators=format.replace(this.validParts,"\x00").split("\x00"),parts=format.match(this.validParts);if(!separators||!separators.length||!parts||parts.length===0){throw new Error("Invalid date format.")}return{separators:separators,parts:parts}},parseDate:function(date,format,language){if(!date)return undefined;if(date instanceof Date)return date;if(typeof format==="string")format=DPGlobal.parseFormat(format);var part_re=/([\-+]\d+)([dmwy])/,parts=date.match(/([\-+]\d+)([dmwy])/g),part,dir,i;if(/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){date=new Date;for(i=0;i<parts.length;i++){part=part_re.exec(parts[i]);dir=parseInt(part[1]);switch(part[2]){case"d":date.setUTCDate(date.getUTCDate()+dir);break;case"m":date=Datepicker.prototype.moveMonth.call(Datepicker.prototype,date,dir);break;case"w":date.setUTCDate(date.getUTCDate()+dir*7);break;case"y":date=Datepicker.prototype.moveYear.call(Datepicker.prototype,date,dir);break}}return UTCDate(date.getUTCFullYear(),date.getUTCMonth(),date.getUTCDate(),0,0,0)}parts=date&&date.match(this.nonpunctuation)||[];date=new Date;var parsed={},setters_order=["yyyy","yy","M","MM","m","mm","d","dd"],setters_map={yyyy:function(d,v){return d.setUTCFullYear(v)},yy:function(d,v){return d.setUTCFullYear(2e3+v)},m:function(d,v){if(isNaN(d))return d;v-=1;while(v<0)v+=12;v%=12;d.setUTCMonth(v);while(d.getUTCMonth()!==v)d.setUTCDate(d.getUTCDate()-1);return d},d:function(d,v){return d.setUTCDate(v)}},val,filtered;setters_map["M"]=setters_map["MM"]=setters_map["mm"]=setters_map["m"];setters_map["dd"]=setters_map["d"];date=UTCDate(date.getFullYear(),date.getMonth(),date.getDate(),0,0,0);var fparts=format.parts.slice();if(parts.length!==fparts.length){fparts=$(fparts).filter(function(i,p){return $.inArray(p,setters_order)!==-1}).toArray()}function match_part(){var m=this.slice(0,parts[i].length),p=parts[i].slice(0,m.length);return m===p}if(parts.length===fparts.length){var cnt;for(i=0,cnt=fparts.length;i<cnt;i++){val=parseInt(parts[i],10);part=fparts[i];if(isNaN(val)){switch(part){case"MM":filtered=$(dates[language].months).filter(match_part);val=$.inArray(filtered[0],dates[language].months)+1;break;case"M":filtered=$(dates[language].monthsShort).filter(match_part);val=$.inArray(filtered[0],dates[language].monthsShort)+1;break}}parsed[part]=val}var _date,s;for(i=0;i<setters_order.length;i++){s=setters_order[i];if(s in parsed&&!isNaN(parsed[s])){_date=new Date(date);setters_map[s](_date,parsed[s]);if(!isNaN(_date))date=_date}}}return date},formatDate:function(date,format,language){if(!date)return"";if(typeof format==="string")format=DPGlobal.parseFormat(format);var val={d:date.getUTCDate(),D:dates[language].daysShort[date.getUTCDay()],DD:dates[language].days[date.getUTCDay()],m:date.getUTCMonth()+1,M:dates[language].monthsShort[date.getUTCMonth()],MM:dates[language].months[date.getUTCMonth()],yy:date.getUTCFullYear().toString().substring(2),yyyy:date.getUTCFullYear()};val.dd=(val.d<10?"0":"")+val.d;val.mm=(val.m<10?"0":"")+val.m;date=[];var seps=$.extend([],format.separators);for(var i=0,cnt=format.parts.length;i<=cnt;i++){if(seps.length)date.push(seps.shift());date.push(val[format.parts[i]])}return date.join("")},headTemplate:"<thead>"+"<tr>"+'<th class="prev">«</th>'+'<th colspan="5" class="datepicker-switch"></th>'+'<th class="next">»</th>'+"</tr>"+"</thead>",contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:"<tfoot>"+"<tr>"+'<th colspan="7" class="today"></th>'+"</tr>"+"<tr>"+'<th colspan="7" class="clear"></th>'+"</tr>"+"</tfoot>"};DPGlobal.template='<div class="datepicker">'+'<div class="datepicker-days">'+'<table class=" table-condensed">'+DPGlobal.headTemplate+"<tbody></tbody>"+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+DPGlobal.headTemplate+DPGlobal.contTemplate+DPGlobal.footTemplate+"</table>"+"</div>"+"</div>";
$.fn.datepicker.DPGlobal=DPGlobal;$.fn.datepicker.noConflict=function(){$.fn.datepicker=old;return this};$(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(e){var $this=$(this);if($this.data("datepicker"))return;e.preventDefault();$this.datepicker("show")});$(function(){$('[data-provide="datepicker-inline"]').datepicker()})})(window.jQuery);
//! moment.js
//! version : 2.13.0
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
global.moment = factory()
}(this, function () { 'use strict';
var hookCallback;
function utils_hooks__hooks () {
return hookCallback.apply(null, arguments);
}
// This is done to register the method called with moment()
// without creating circular dependencies.
function setHookCallback (callback) {
hookCallback = callback;
}
function isArray(input) {
return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
}
function isDate(input) {
return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
}
function map(arr, fn) {
var res = [], i;
for (i = 0; i < arr.length; ++i) {
res.push(fn(arr[i], i));
}
return res;
}
function hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
}
function extend(a, b) {
for (var i in b) {
if (hasOwnProp(b, i)) {
a[i] = b[i];
}
}
if (hasOwnProp(b, 'toString')) {
a.toString = b.toString;
}
if (hasOwnProp(b, 'valueOf')) {
a.valueOf = b.valueOf;
}
return a;
}
function create_utc__createUTC (input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, true).utc();
}
function defaultParsingFlags() {
// We need to deep clone this object.
return {
empty : false,
unusedTokens : [],
unusedInput : [],
overflow : -2,
charsLeftOver : 0,
nullInput : false,
invalidMonth : null,
invalidFormat : false,
userInvalidated : false,
iso : false,
parsedDateParts : [],
meridiem : null
};
}
function getParsingFlags(m) {
if (m._pf == null) {
m._pf = defaultParsingFlags();
}
return m._pf;
}
var some;
if (Array.prototype.some) {
some = Array.prototype.some;
} else {
some = function (fun) {
var t = Object(this);
var len = t.length >>> 0;
for (var i = 0; i < len; i++) {
if (i in t && fun.call(this, t[i], i, t)) {
return true;
}
}
return false;
};
}
function valid__isValid(m) {
if (m._isValid == null) {
var flags = getParsingFlags(m);
var parsedParts = some.call(flags.parsedDateParts, function (i) {
return i != null;
});
m._isValid = !isNaN(m._d.getTime()) &&
flags.overflow < 0 &&
!flags.empty &&
!flags.invalidMonth &&
!flags.invalidWeekday &&
!flags.nullInput &&
!flags.invalidFormat &&
!flags.userInvalidated &&
(!flags.meridiem || (flags.meridiem && parsedParts));
if (m._strict) {
m._isValid = m._isValid &&
flags.charsLeftOver === 0 &&
flags.unusedTokens.length === 0 &&
flags.bigHour === undefined;
}
}
return m._isValid;
}
function valid__createInvalid (flags) {
var m = create_utc__createUTC(NaN);
if (flags != null) {
extend(getParsingFlags(m), flags);
}
else {
getParsingFlags(m).userInvalidated = true;
}
return m;
}
function isUndefined(input) {
return input === void 0;
}
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var momentProperties = utils_hooks__hooks.momentProperties = [];
function copyConfig(to, from) {
var i, prop, val;
if (!isUndefined(from._isAMomentObject)) {
to._isAMomentObject = from._isAMomentObject;
}
if (!isUndefined(from._i)) {
to._i = from._i;
}
if (!isUndefined(from._f)) {
to._f = from._f;
}
if (!isUndefined(from._l)) {
to._l = from._l;
}
if (!isUndefined(from._strict)) {
to._strict = from._strict;
}
if (!isUndefined(from._tzm)) {
to._tzm = from._tzm;
}
if (!isUndefined(from._isUTC)) {
to._isUTC = from._isUTC;
}
if (!isUndefined(from._offset)) {
to._offset = from._offset;
}
if (!isUndefined(from._pf)) {
to._pf = getParsingFlags(from);
}
if (!isUndefined(from._locale)) {
to._locale = from._locale;
}
if (momentProperties.length > 0) {
for (i in momentProperties) {
prop = momentProperties[i];
val = from[prop];
if (!isUndefined(val)) {
to[prop] = val;
}
}
}
return to;
}
var updateInProgress = false;
// Moment prototype object
function Moment(config) {
copyConfig(this, config);
this._d = new Date(config._d != null ? config._d.getTime() : NaN);
// Prevent infinite loop in case updateOffset creates new moment
// objects.
if (updateInProgress === false) {
updateInProgress = true;
utils_hooks__hooks.updateOffset(this);
updateInProgress = false;
}
}
function isMoment (obj) {
return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
}
function absFloor (number) {
if (number < 0) {
return Math.ceil(number);
} else {
return Math.floor(number);
}
}
function toInt(argumentForCoercion) {
var coercedNumber = +argumentForCoercion,
value = 0;
if (coercedNumber !== 0 && isFinite(coercedNumber)) {
value = absFloor(coercedNumber);
}
return value;
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
var len = Math.min(array1.length, array2.length),
lengthDiff = Math.abs(array1.length - array2.length),
diffs = 0,
i;
for (i = 0; i < len; i++) {
if ((dontConvert && array1[i] !== array2[i]) ||
(!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
diffs++;
}
}
return diffs + lengthDiff;
}
function warn(msg) {
if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
(typeof console !== 'undefined') && console.warn) {
console.warn('Deprecation warning: ' + msg);
}
}
function deprecate(msg, fn) {
var firstTime = true;
return extend(function () {
if (utils_hooks__hooks.deprecationHandler != null) {
utils_hooks__hooks.deprecationHandler(null, msg);
}
if (firstTime) {
warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
firstTime = false;
}
return fn.apply(this, arguments);
}, fn);
}
var deprecations = {};
function deprecateSimple(name, msg) {
if (utils_hooks__hooks.deprecationHandler != null) {
utils_hooks__hooks.deprecationHandler(name, msg);
}
if (!deprecations[name]) {
warn(msg);
deprecations[name] = true;
}
}
utils_hooks__hooks.suppressDeprecationWarnings = false;
utils_hooks__hooks.deprecationHandler = null;
function isFunction(input) {
return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
}
function isObject(input) {
return Object.prototype.toString.call(input) === '[object Object]';
}
function locale_set__set (config) {
var prop, i;
for (i in config) {
prop = config[i];
if (isFunction(prop)) {
this[i] = prop;
} else {
this['_' + i] = prop;
}
}
this._config = config;
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _ordinalParseLenient.
this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
}
function mergeConfigs(parentConfig, childConfig) {
var res = extend({}, parentConfig), prop;
for (prop in childConfig) {
if (hasOwnProp(childConfig, prop)) {
if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
res[prop] = {};
extend(res[prop], parentConfig[prop]);
extend(res[prop], childConfig[prop]);
} else if (childConfig[prop] != null) {
res[prop] = childConfig[prop];
} else {
delete res[prop];
}
}
}
return res;
}
function Locale(config) {
if (config != null) {
this.set(config);
}
}
var keys;
if (Object.keys) {
keys = Object.keys;
} else {
keys = function (obj) {
var i, res = [];
for (i in obj) {
if (hasOwnProp(obj, i)) {
res.push(i);
}
}
return res;
};
}
// internal storage for locale config files
var locales = {};
var globalLocale;
function normalizeLocale(key) {
return key ? key.toLowerCase().replace('_', '-') : key;
}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function chooseLocale(names) {
var i = 0, j, next, locale, split;
while (i < names.length) {
split = normalizeLocale(names[i]).split('-');
j = split.length;
next = normalizeLocale(names[i + 1]);
next = next ? next.split('-') : null;
while (j > 0) {
locale = loadLocale(split.slice(0, j).join('-'));
if (locale) {
return locale;
}
if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
//the next array item is better than a shallower substring of this one
break;
}
j--;
}
i++;
}
return null;
}
function loadLocale(name) {
var oldLocale = null;
// TODO: Find a better way to register and load all the locales in Node
if (!locales[name] && (typeof module !== 'undefined') &&
module && module.exports) {
try {
oldLocale = globalLocale._abbr;
require('./locale/' + name);
// because defineLocale currently also sets the global locale, we
// want to undo that for lazy loaded locales
locale_locales__getSetGlobalLocale(oldLocale);
} catch (e) { }
}
return locales[name];
}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function locale_locales__getSetGlobalLocale (key, values) {
var data;
if (key) {
if (isUndefined(values)) {
data = locale_locales__getLocale(key);
}
else {
data = defineLocale(key, values);
}
if (data) {
// moment.duration._locale = moment._locale = data;
globalLocale = data;
}
}
return globalLocale._abbr;
}
function defineLocale (name, config) {
if (config !== null) {
config.abbr = name;
if (locales[name] != null) {
deprecateSimple('defineLocaleOverride',
'use moment.updateLocale(localeName, config) to change ' +
'an existing locale. moment.defineLocale(localeName, ' +
'config) should only be used for creating a new locale');
config = mergeConfigs(locales[name]._config, config);
} else if (config.parentLocale != null) {
if (locales[config.parentLocale] != null) {
config = mergeConfigs(locales[config.parentLocale]._config, config);
} else {
// treat as if there is no base config
deprecateSimple('parentLocaleUndefined',
'specified parentLocale is not defined yet');
}
}
locales[name] = new Locale(config);
// backwards compat for now: also set the locale
locale_locales__getSetGlobalLocale(name);
return locales[name];
} else {
// useful for testing
delete locales[name];
return null;
}
}
function updateLocale(name, config) {
if (config != null) {
var locale;
if (locales[name] != null) {
config = mergeConfigs(locales[name]._config, config);
}
locale = new Locale(config);
locale.parentLocale = locales[name];
locales[name] = locale;
// backwards compat for now: also set the locale
locale_locales__getSetGlobalLocale(name);
} else {
// pass null for config to unupdate, useful for tests
if (locales[name] != null) {
if (locales[name].parentLocale != null) {
locales[name] = locales[name].parentLocale;
} else if (locales[name] != null) {
delete locales[name];
}
}
}
return locales[name];
}
// returns locale data
function locale_locales__getLocale (key) {
var locale;
if (key && key._locale && key._locale._abbr) {
key = key._locale._abbr;
}
if (!key) {
return globalLocale;
}
if (!isArray(key)) {
//short-circuit everything else
locale = loadLocale(key);
if (locale) {
return locale;
}
key = [key];
}
return chooseLocale(key);
}
function locale_locales__listLocales() {
return keys(locales);
}
var aliases = {};
function addUnitAlias (unit, shorthand) {
var lowerCase = unit.toLowerCase();
aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
}
function normalizeUnits(units) {
return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
}
function normalizeObjectUnits(inputObject) {
var normalizedInput = {},
normalizedProp,
prop;
for (prop in inputObject) {
if (hasOwnProp(inputObject, prop)) {
normalizedProp = normalizeUnits(prop);
if (normalizedProp) {
normalizedInput[normalizedProp] = inputObject[prop];
}
}
}
return normalizedInput;
}
function makeGetSet (unit, keepTime) {
return function (value) {
if (value != null) {
get_set__set(this, unit, value);
utils_hooks__hooks.updateOffset(this, keepTime);
return this;
} else {
return get_set__get(this, unit);
}
};
}
function get_set__get (mom, unit) {
return mom.isValid() ?
mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
}
function get_set__set (mom, unit, value) {
if (mom.isValid()) {
mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
}
}
// MOMENTS
function getSet (units, value) {
var unit;
if (typeof units === 'object') {
for (unit in units) {
this.set(unit, units[unit]);
}
} else {
units = normalizeUnits(units);
if (isFunction(this[units])) {
return this[units](value);
}
}
return this;
}
function zeroFill(number, targetLength, forceSign) {
var absNumber = '' + Math.abs(number),
zerosToFill = targetLength - absNumber.length,
sign = number >= 0;
return (sign ? (forceSign ? '+' : '') : '-') +
Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
}
var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
var formatFunctions = {};
var formatTokenFunctions = {};
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function addFormatToken (token, padded, ordinal, callback) {
var func = callback;
if (typeof callback === 'string') {
func = function () {
return this[callback]();
};
}
if (token) {
formatTokenFunctions[token] = func;
}
if (padded) {
formatTokenFunctions[padded[0]] = function () {
return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
};
}
if (ordinal) {
formatTokenFunctions[ordinal] = function () {
return this.localeData().ordinal(func.apply(this, arguments), token);
};
}
}
function removeFormattingTokens(input) {
if (input.match(/\[[\s\S]/)) {
return input.replace(/^\[|\]$/g, '');
}
return input.replace(/\\/g, '');
}
function makeFormatFunction(format) {
var array = format.match(formattingTokens), i, length;
for (i = 0, length = array.length; i < length; i++) {
if (formatTokenFunctions[array[i]]) {
array[i] = formatTokenFunctions[array[i]];
} else {
array[i] = removeFormattingTokens(array[i]);
}
}
return function (mom) {
var output = '', i;
for (i = 0; i < length; i++) {
output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
}
return output;
};
}
// format date using native date object
function formatMoment(m, format) {
if (!m.isValid()) {
return m.localeData().invalidDate();
}
format = expandFormat(format, m.localeData());
formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
return formatFunctions[format](m);
}
function expandFormat(format, locale) {
var i = 5;
function replaceLongDateFormatTokens(input) {
return locale.longDateFormat(input) || input;
}
localFormattingTokens.lastIndex = 0;
while (i >= 0 && localFormattingTokens.test(format)) {
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
localFormattingTokens.lastIndex = 0;
i -= 1;
}
return format;
}
var match1 = /\d/; // 0 - 9
var match2 = /\d\d/; // 00 - 99
var match3 = /\d{3}/; // 000 - 999
var match4 = /\d{4}/; // 0000 - 9999
var match6 = /[+-]?\d{6}/; // -999999 - 999999
var match1to2 = /\d\d?/; // 0 - 99
var match3to4 = /\d\d\d\d?/; // 999 - 9999
var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
var match1to3 = /\d{1,3}/; // 0 - 999
var match1to4 = /\d{1,4}/; // 0 - 9999
var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
var matchUnsigned = /\d+/; // 0 - inf
var matchSigned = /[+-]?\d+/; // -inf - inf
var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
// any word (or two) characters or numbers including two/three word month in arabic.
// includes scottish gaelic two word and hyphenated months
var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
var regexes = {};
function addRegexToken (token, regex, strictRegex) {
regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
return (isStrict && strictRegex) ? strictRegex : regex;
};
}
function getParseRegexForToken (token, config) {
if (!hasOwnProp(regexes, token)) {
return new RegExp(unescapeFormat(token));
}
return regexes[token](config._strict, config._locale);
}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function unescapeFormat(s) {
return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
return p1 || p2 || p3 || p4;
}));
}
function regexEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
var tokens = {};
function addParseToken (token, callback) {
var i, func = callback;
if (typeof token === 'string') {
token = [token];
}
if (typeof callback === 'number') {
func = function (input, array) {
array[callback] = toInt(input);
};
}
for (i = 0; i < token.length; i++) {
tokens[token[i]] = func;
}
}
function addWeekParseToken (token, callback) {
addParseToken(token, function (input, array, config, token) {
config._w = config._w || {};
callback(input, config._w, config, token);
});
}
function addTimeToArrayFromToken(token, input, config) {
if (input != null && hasOwnProp(tokens, token)) {
tokens[token](input, config._a, config, token);
}
}
var YEAR = 0;
var MONTH = 1;
var DATE = 2;
var HOUR = 3;
var MINUTE = 4;
var SECOND = 5;
var MILLISECOND = 6;
var WEEK = 7;
var WEEKDAY = 8;
var indexOf;
if (Array.prototype.indexOf) {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function (o) {
// I know
var i;
for (i = 0; i < this.length; ++i) {
if (this[i] === o) {
return i;
}
}
return -1;
};
}
function daysInMonth(year, month) {
return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
}
// FORMATTING
addFormatToken('M', ['MM', 2], 'Mo', function () {
return this.month() + 1;
});
addFormatToken('MMM', 0, 0, function (format) {
return this.localeData().monthsShort(this, format);
});
addFormatToken('MMMM', 0, 0, function (format) {
return this.localeData().months(this, format);
});
// ALIASES
addUnitAlias('month', 'M');
// PARSING
addRegexToken('M', match1to2);
addRegexToken('MM', match1to2, match2);
addRegexToken('MMM', function (isStrict, locale) {
return locale.monthsShortRegex(isStrict);
});
addRegexToken('MMMM', function (isStrict, locale) {
return locale.monthsRegex(isStrict);
});
addParseToken(['M', 'MM'], function (input, array) {
array[MONTH] = toInt(input) - 1;
});
addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
var month = config._locale.monthsParse(input, token, config._strict);
// if we didn't find a month name, mark the date as invalid.
if (month != null) {
array[MONTH] = month;
} else {
getParsingFlags(config).invalidMonth = input;
}
});
// LOCALES
var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
function localeMonths (m, format) {
return isArray(this._months) ? this._months[m.month()] :
this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
}
var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
function localeMonthsShort (m, format) {
return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
}
function units_month__handleStrictParse(monthName, format, strict) {
var i, ii, mom, llc = monthName.toLocaleLowerCase();
if (!this._monthsParse) {
// this is not used
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
for (i = 0; i < 12; ++i) {
mom = create_utc__createUTC([2000, i]);
this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'MMM') {
ii = indexOf.call(this._shortMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._longMonthsParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._longMonthsParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortMonthsParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeMonthsParse (monthName, format, strict) {
var i, mom, regex;
if (this._monthsParseExact) {
return units_month__handleStrictParse.call(this, monthName, format, strict);
}
if (!this._monthsParse) {
this._monthsParse = [];
this._longMonthsParse = [];
this._shortMonthsParse = [];
}
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = create_utc__createUTC([2000, i]);
if (strict && !this._longMonthsParse[i]) {
this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
}
if (!strict && !this._monthsParse[i]) {
regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
return i;
} else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
return i;
} else if (!strict && this._monthsParse[i].test(monthName)) {
return i;
}
}
}
// MOMENTS
function setMonth (mom, value) {
var dayOfMonth;
if (!mom.isValid()) {
// No op
return mom;
}
if (typeof value === 'string') {
if (/^\d+$/.test(value)) {
value = toInt(value);
} else {
value = mom.localeData().monthsParse(value);
// TODO: Another silent failure?
if (typeof value !== 'number') {
return mom;
}
}
}
dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
return mom;
}
function getSetMonth (value) {
if (value != null) {
setMonth(this, value);
utils_hooks__hooks.updateOffset(this, true);
return this;
} else {
return get_set__get(this, 'Month');
}
}
function getDaysInMonth () {
return daysInMonth(this.year(), this.month());
}
var defaultMonthsShortRegex = matchWord;
function monthsShortRegex (isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsShortStrictRegex;
} else {
return this._monthsShortRegex;
}
} else {
return this._monthsShortStrictRegex && isStrict ?
this._monthsShortStrictRegex : this._monthsShortRegex;
}
}
var defaultMonthsRegex = matchWord;
function monthsRegex (isStrict) {
if (this._monthsParseExact) {
if (!hasOwnProp(this, '_monthsRegex')) {
computeMonthsParse.call(this);
}
if (isStrict) {
return this._monthsStrictRegex;
} else {
return this._monthsRegex;
}
} else {
return this._monthsStrictRegex && isStrict ?
this._monthsStrictRegex : this._monthsRegex;
}
}
function computeMonthsParse () {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var shortPieces = [], longPieces = [], mixedPieces = [],
i, mom;
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
mom = create_utc__createUTC([2000, i]);
shortPieces.push(this.monthsShort(mom, ''));
longPieces.push(this.months(mom, ''));
mixedPieces.push(this.months(mom, ''));
mixedPieces.push(this.monthsShort(mom, ''));
}
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
for (i = 0; i < 12; i++) {
shortPieces[i] = regexEscape(shortPieces[i]);
longPieces[i] = regexEscape(longPieces[i]);
mixedPieces[i] = regexEscape(mixedPieces[i]);
}
this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._monthsShortRegex = this._monthsRegex;
this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
}
function checkOverflow (m) {
var overflow;
var a = m._a;
if (a && getParsingFlags(m).overflow === -2) {
overflow =
a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
-1;
if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
overflow = DATE;
}
if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
overflow = WEEK;
}
if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
overflow = WEEKDAY;
}
getParsingFlags(m).overflow = overflow;
}
return m;
}
// iso 8601 regex
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
var isoDates = [
['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
['GGGG-[W]WW', /\d{4}-W\d\d/, false],
['YYYY-DDD', /\d{4}-\d{3}/],
['YYYY-MM', /\d{4}-\d\d/, false],
['YYYYYYMMDD', /[+-]\d{10}/],
['YYYYMMDD', /\d{8}/],
// YYYYMM is NOT allowed by the standard
['GGGG[W]WWE', /\d{4}W\d{3}/],
['GGGG[W]WW', /\d{4}W\d{2}/, false],
['YYYYDDD', /\d{7}/]
];
// iso time formats and regexes
var isoTimes = [
['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
['HH:mm:ss', /\d\d:\d\d:\d\d/],
['HH:mm', /\d\d:\d\d/],
['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
['HHmmss', /\d\d\d\d\d\d/],
['HHmm', /\d\d\d\d/],
['HH', /\d\d/]
];
var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
// date from iso format
function configFromISO(config) {
var i, l,
string = config._i,
match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
allowTime, dateFormat, timeFormat, tzFormat;
if (match) {
getParsingFlags(config).iso = true;
for (i = 0, l = isoDates.length; i < l; i++) {
if (isoDates[i][1].exec(match[1])) {
dateFormat = isoDates[i][0];
allowTime = isoDates[i][2] !== false;
break;
}
}
if (dateFormat == null) {
config._isValid = false;
return;
}
if (match[3]) {
for (i = 0, l = isoTimes.length; i < l; i++) {
if (isoTimes[i][1].exec(match[3])) {
// match[2] should be 'T' or space
timeFormat = (match[2] || ' ') + isoTimes[i][0];
break;
}
}
if (timeFormat == null) {
config._isValid = false;
return;
}
}
if (!allowTime && timeFormat != null) {
config._isValid = false;
return;
}
if (match[4]) {
if (tzRegex.exec(match[4])) {
tzFormat = 'Z';
} else {
config._isValid = false;
return;
}
}
config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
configFromStringAndFormat(config);
} else {
config._isValid = false;
}
}
// date from iso format or fallback
function configFromString(config) {
var matched = aspNetJsonRegex.exec(config._i);
if (matched !== null) {
config._d = new Date(+matched[1]);
return;
}
configFromISO(config);
if (config._isValid === false) {
delete config._isValid;
utils_hooks__hooks.createFromInputFallback(config);
}
}
utils_hooks__hooks.createFromInputFallback = deprecate(
'moment construction falls back to js Date. This is ' +
'discouraged and will be removed in upcoming major ' +
'release. Please refer to ' +
'https://github.com/moment/moment/issues/1407 for more info.',
function (config) {
config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
}
);
function createDate (y, m, d, h, M, s, ms) {
//can't just apply() to create a date:
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
var date = new Date(y, m, d, h, M, s, ms);
//the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
date.setFullYear(y);
}
return date;
}
function createUTCDate (y) {
var date = new Date(Date.UTC.apply(null, arguments));
//the Date.UTC function remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
date.setUTCFullYear(y);
}
return date;
}
// FORMATTING
addFormatToken('Y', 0, 0, function () {
var y = this.year();
return y <= 9999 ? '' + y : '+' + y;
});
addFormatToken(0, ['YY', 2], 0, function () {
return this.year() % 100;
});
addFormatToken(0, ['YYYY', 4], 0, 'year');
addFormatToken(0, ['YYYYY', 5], 0, 'year');
addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
// ALIASES
addUnitAlias('year', 'y');
// PARSING
addRegexToken('Y', matchSigned);
addRegexToken('YY', match1to2, match2);
addRegexToken('YYYY', match1to4, match4);
addRegexToken('YYYYY', match1to6, match6);
addRegexToken('YYYYYY', match1to6, match6);
addParseToken(['YYYYY', 'YYYYYY'], YEAR);
addParseToken('YYYY', function (input, array) {
array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
});
addParseToken('YY', function (input, array) {
array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
});
addParseToken('Y', function (input, array) {
array[YEAR] = parseInt(input, 10);
});
// HELPERS
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
// HOOKS
utils_hooks__hooks.parseTwoDigitYear = function (input) {
return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
};
// MOMENTS
var getSetYear = makeGetSet('FullYear', true);
function getIsLeapYear () {
return isLeapYear(this.year());
}
// start-of-first-week - start-of-year
function firstWeekOffset(year, dow, doy) {
var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
fwd = 7 + dow - doy,
// first-week day local weekday -- which local weekday is fwd
fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
return -fwdlw + fwd - 1;
}
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
var localWeekday = (7 + weekday - dow) % 7,
weekOffset = firstWeekOffset(year, dow, doy),
dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
resYear, resDayOfYear;
if (dayOfYear <= 0) {
resYear = year - 1;
resDayOfYear = daysInYear(resYear) + dayOfYear;
} else if (dayOfYear > daysInYear(year)) {
resYear = year + 1;
resDayOfYear = dayOfYear - daysInYear(year);
} else {
resYear = year;
resDayOfYear = dayOfYear;
}
return {
year: resYear,
dayOfYear: resDayOfYear
};
}
function weekOfYear(mom, dow, doy) {
var weekOffset = firstWeekOffset(mom.year(), dow, doy),
week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
resWeek, resYear;
if (week < 1) {
resYear = mom.year() - 1;
resWeek = week + weeksInYear(resYear, dow, doy);
} else if (week > weeksInYear(mom.year(), dow, doy)) {
resWeek = week - weeksInYear(mom.year(), dow, doy);
resYear = mom.year() + 1;
} else {
resYear = mom.year();
resWeek = week;
}
return {
week: resWeek,
year: resYear
};
}
function weeksInYear(year, dow, doy) {
var weekOffset = firstWeekOffset(year, dow, doy),
weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
}
// Pick the first defined of two or three arguments.
function defaults(a, b, c) {
if (a != null) {
return a;
}
if (b != null) {
return b;
}
return c;
}
function currentDateArray(config) {
// hooks is actually the exported moment object
var nowValue = new Date(utils_hooks__hooks.now());
if (config._useUTC) {
return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
}
return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function configFromArray (config) {
var i, date, input = [], currentDate, yearToUse;
if (config._d) {
return;
}
currentDate = currentDateArray(config);
//compute day of the year from weeks and weekdays
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
dayOfYearFromWeekInfo(config);
}
//if the day of the year is set, figure out what it is
if (config._dayOfYear) {
yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
if (config._dayOfYear > daysInYear(yearToUse)) {
getParsingFlags(config)._overflowDayOfYear = true;
}
date = createUTCDate(yearToUse, 0, config._dayOfYear);
config._a[MONTH] = date.getUTCMonth();
config._a[DATE] = date.getUTCDate();
}
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for (i = 0; i < 3 && config._a[i] == null; ++i) {
config._a[i] = input[i] = currentDate[i];
}
// Zero out whatever was not defaulted, including time
for (; i < 7; i++) {
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
}
// Check for 24:00:00.000
if (config._a[HOUR] === 24 &&
config._a[MINUTE] === 0 &&
config._a[SECOND] === 0 &&
config._a[MILLISECOND] === 0) {
config._nextDay = true;
config._a[HOUR] = 0;
}
config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
if (config._tzm != null) {
config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
}
if (config._nextDay) {
config._a[HOUR] = 24;
}
}
function dayOfYearFromWeekInfo(config) {
var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
w = config._w;
if (w.GG != null || w.W != null || w.E != null) {
dow = 1;
doy = 4;
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
week = defaults(w.W, 1);
weekday = defaults(w.E, 1);
if (weekday < 1 || weekday > 7) {
weekdayOverflow = true;
}
} else {
dow = config._locale._week.dow;
doy = config._locale._week.doy;
weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
week = defaults(w.w, 1);
if (w.d != null) {
// weekday -- low day numbers are considered next week
weekday = w.d;
if (weekday < 0 || weekday > 6) {
weekdayOverflow = true;
}
} else if (w.e != null) {
// local weekday -- counting starts from begining of week
weekday = w.e + dow;
if (w.e < 0 || w.e > 6) {
weekdayOverflow = true;
}
} else {
// default to begining of week
weekday = dow;
}
}
if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
getParsingFlags(config)._overflowWeeks = true;
} else if (weekdayOverflow != null) {
getParsingFlags(config)._overflowWeekday = true;
} else {
temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
config._a[YEAR] = temp.year;
config._dayOfYear = temp.dayOfYear;
}
}
// constant that refers to the ISO standard
utils_hooks__hooks.ISO_8601 = function () {};
// date from string and format string
function configFromStringAndFormat(config) {
// TODO: Move this to another part of the creation flow to prevent circular deps
if (config._f === utils_hooks__hooks.ISO_8601) {
configFromISO(config);
return;
}
config._a = [];
getParsingFlags(config).empty = true;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var string = '' + config._i,
i, parsedInput, tokens, token, skipped,
stringLength = string.length,
totalParsedInputLength = 0;
tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
// console.log('token', token, 'parsedInput', parsedInput,
// 'regex', getParseRegexForToken(token, config));
if (parsedInput) {
skipped = string.substr(0, string.indexOf(parsedInput));
if (skipped.length > 0) {
getParsingFlags(config).unusedInput.push(skipped);
}
string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
totalParsedInputLength += parsedInput.length;
}
// don't parse if it's not a known token
if (formatTokenFunctions[token]) {
if (parsedInput) {
getParsingFlags(config).empty = false;
}
else {
getParsingFlags(config).unusedTokens.push(token);
}
addTimeToArrayFromToken(token, parsedInput, config);
}
else if (config._strict && !parsedInput) {
getParsingFlags(config).unusedTokens.push(token);
}
}
// add remaining unparsed input length to the string
getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
if (string.length > 0) {
getParsingFlags(config).unusedInput.push(string);
}
// clear _12h flag if hour is <= 12
if (getParsingFlags(config).bigHour === true &&
config._a[HOUR] <= 12 &&
config._a[HOUR] > 0) {
getParsingFlags(config).bigHour = undefined;
}
getParsingFlags(config).parsedDateParts = config._a.slice(0);
getParsingFlags(config).meridiem = config._meridiem;
// handle meridiem
config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
configFromArray(config);
checkOverflow(config);
}
function meridiemFixWrap (locale, hour, meridiem) {
var isPm;
if (meridiem == null) {
// nothing to do
return hour;
}
if (locale.meridiemHour != null) {
return locale.meridiemHour(hour, meridiem);
} else if (locale.isPM != null) {
// Fallback
isPm = locale.isPM(meridiem);
if (isPm && hour < 12) {
hour += 12;
}
if (!isPm && hour === 12) {
hour = 0;
}
return hour;
} else {
// this is not supposed to happen
return hour;
}
}
// date from string and array of format strings
function configFromStringAndArray(config) {
var tempConfig,
bestMoment,
scoreToBeat,
i,
currentScore;
if (config._f.length === 0) {
getParsingFlags(config).invalidFormat = true;
config._d = new Date(NaN);
return;
}
for (i = 0; i < config._f.length; i++) {
currentScore = 0;
tempConfig = copyConfig({}, config);
if (config._useUTC != null) {
tempConfig._useUTC = config._useUTC;
}
tempConfig._f = config._f[i];
configFromStringAndFormat(tempConfig);
if (!valid__isValid(tempConfig)) {
continue;
}
// if there is any input that was not parsed add a penalty for that format
currentScore += getParsingFlags(tempConfig).charsLeftOver;
//or tokens
currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
getParsingFlags(tempConfig).score = currentScore;
if (scoreToBeat == null || currentScore < scoreToBeat) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
}
}
extend(config, bestMoment || tempConfig);
}
function configFromObject(config) {
if (config._d) {
return;
}
var i = normalizeObjectUnits(config._i);
config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
return obj && parseInt(obj, 10);
});
configFromArray(config);
}
function createFromConfig (config) {
var res = new Moment(checkOverflow(prepareConfig(config)));
if (res._nextDay) {
// Adding is smart enough around DST
res.add(1, 'd');
res._nextDay = undefined;
}
return res;
}
function prepareConfig (config) {
var input = config._i,
format = config._f;
config._locale = config._locale || locale_locales__getLocale(config._l);
if (input === null || (format === undefined && input === '')) {
return valid__createInvalid({nullInput: true});
}
if (typeof input === 'string') {
config._i = input = config._locale.preparse(input);
}
if (isMoment(input)) {
return new Moment(checkOverflow(input));
} else if (isArray(format)) {
configFromStringAndArray(config);
} else if (format) {
configFromStringAndFormat(config);
} else if (isDate(input)) {
config._d = input;
} else {
configFromInput(config);
}
if (!valid__isValid(config)) {
config._d = null;
}
return config;
}
function configFromInput(config) {
var input = config._i;
if (input === undefined) {
config._d = new Date(utils_hooks__hooks.now());
} else if (isDate(input)) {
config._d = new Date(input.valueOf());
} else if (typeof input === 'string') {
configFromString(config);
} else if (isArray(input)) {
config._a = map(input.slice(0), function (obj) {
return parseInt(obj, 10);
});
configFromArray(config);
} else if (typeof(input) === 'object') {
configFromObject(config);
} else if (typeof(input) === 'number') {
// from milliseconds
config._d = new Date(input);
} else {
utils_hooks__hooks.createFromInputFallback(config);
}
}
function createLocalOrUTC (input, format, locale, strict, isUTC) {
var c = {};
if (typeof(locale) === 'boolean') {
strict = locale;
locale = undefined;
}
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
c._isAMomentObject = true;
c._useUTC = c._isUTC = isUTC;
c._l = locale;
c._i = input;
c._f = format;
c._strict = strict;
return createFromConfig(c);
}
function local__createLocal (input, format, locale, strict) {
return createLocalOrUTC(input, format, locale, strict, false);
}
var prototypeMin = deprecate(
'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
function () {
var other = local__createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other < this ? this : other;
} else {
return valid__createInvalid();
}
}
);
var prototypeMax = deprecate(
'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
function () {
var other = local__createLocal.apply(null, arguments);
if (this.isValid() && other.isValid()) {
return other > this ? this : other;
} else {
return valid__createInvalid();
}
}
);
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function pickBy(fn, moments) {
var res, i;
if (moments.length === 1 && isArray(moments[0])) {
moments = moments[0];
}
if (!moments.length) {
return local__createLocal();
}
res = moments[0];
for (i = 1; i < moments.length; ++i) {
if (!moments[i].isValid() || moments[i][fn](res)) {
res = moments[i];
}
}
return res;
}
// TODO: Use [].sort instead?
function min () {
var args = [].slice.call(arguments, 0);
return pickBy('isBefore', args);
}
function max () {
var args = [].slice.call(arguments, 0);
return pickBy('isAfter', args);
}
var now = function () {
return Date.now ? Date.now() : +(new Date());
};
function Duration (duration) {
var normalizedInput = normalizeObjectUnits(duration),
years = normalizedInput.year || 0,
quarters = normalizedInput.quarter || 0,
months = normalizedInput.month || 0,
weeks = normalizedInput.week || 0,
days = normalizedInput.day || 0,
hours = normalizedInput.hour || 0,
minutes = normalizedInput.minute || 0,
seconds = normalizedInput.second || 0,
milliseconds = normalizedInput.millisecond || 0;
// representation for dateAddRemove
this._milliseconds = +milliseconds +
seconds * 1e3 + // 1000
minutes * 6e4 + // 1000 * 60
hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days = +days +
weeks * 7;
// It is impossible translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months = +months +
quarters * 3 +
years * 12;
this._data = {};
this._locale = locale_locales__getLocale();
this._bubble();
}
function isDuration (obj) {
return obj instanceof Duration;
}
// FORMATTING
function offset (token, separator) {
addFormatToken(token, 0, 0, function () {
var offset = this.utcOffset();
var sign = '+';
if (offset < 0) {
offset = -offset;
sign = '-';
}
return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
});
}
offset('Z', ':');
offset('ZZ', '');
// PARSING
addRegexToken('Z', matchShortOffset);
addRegexToken('ZZ', matchShortOffset);
addParseToken(['Z', 'ZZ'], function (input, array, config) {
config._useUTC = true;
config._tzm = offsetFromString(matchShortOffset, input);
});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var chunkOffset = /([\+\-]|\d\d)/gi;
function offsetFromString(matcher, string) {
var matches = ((string || '').match(matcher) || []);
var chunk = matches[matches.length - 1] || [];
var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
var minutes = +(parts[1] * 60) + toInt(parts[2]);
return parts[0] === '+' ? minutes : -minutes;
}
// Return a moment from input, that is local/utc/zone equivalent to model.
function cloneWithOffset(input, model) {
var res, diff;
if (model._isUTC) {
res = model.clone();
diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
// Use low-level api, because this fn is low-level api.
res._d.setTime(res._d.valueOf() + diff);
utils_hooks__hooks.updateOffset(res, false);
return res;
} else {
return local__createLocal(input).local();
}
}
function getDateOffset (m) {
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
}
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
utils_hooks__hooks.updateOffset = function () {};
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function getSetOffset (input, keepLocalTime) {
var offset = this._offset || 0,
localAdjust;
if (!this.isValid()) {
return input != null ? this : NaN;
}
if (input != null) {
if (typeof input === 'string') {
input = offsetFromString(matchShortOffset, input);
} else if (Math.abs(input) < 16) {
input = input * 60;
}
if (!this._isUTC && keepLocalTime) {
localAdjust = getDateOffset(this);
}
this._offset = input;
this._isUTC = true;
if (localAdjust != null) {
this.add(localAdjust, 'm');
}
if (offset !== input) {
if (!keepLocalTime || this._changeInProgress) {
add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
} else if (!this._changeInProgress) {
this._changeInProgress = true;
utils_hooks__hooks.updateOffset(this, true);
this._changeInProgress = null;
}
}
return this;
} else {
return this._isUTC ? offset : getDateOffset(this);
}
}
function getSetZone (input, keepLocalTime) {
if (input != null) {
if (typeof input !== 'string') {
input = -input;
}
this.utcOffset(input, keepLocalTime);
return this;
} else {
return -this.utcOffset();
}
}
function setOffsetToUTC (keepLocalTime) {
return this.utcOffset(0, keepLocalTime);
}
function setOffsetToLocal (keepLocalTime) {
if (this._isUTC) {
this.utcOffset(0, keepLocalTime);
this._isUTC = false;
if (keepLocalTime) {
this.subtract(getDateOffset(this), 'm');
}
}
return this;
}
function setOffsetToParsedOffset () {
if (this._tzm) {
this.utcOffset(this._tzm);
} else if (typeof this._i === 'string') {
this.utcOffset(offsetFromString(matchOffset, this._i));
}
return this;
}
function hasAlignedHourOffset (input) {
if (!this.isValid()) {
return false;
}
input = input ? local__createLocal(input).utcOffset() : 0;
return (this.utcOffset() - input) % 60 === 0;
}
function isDaylightSavingTime () {
return (
this.utcOffset() > this.clone().month(0).utcOffset() ||
this.utcOffset() > this.clone().month(5).utcOffset()
);
}
function isDaylightSavingTimeShifted () {
if (!isUndefined(this._isDSTShifted)) {
return this._isDSTShifted;
}
var c = {};
copyConfig(c, this);
c = prepareConfig(c);
if (c._a) {
var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
this._isDSTShifted = this.isValid() &&
compareArrays(c._a, other.toArray()) > 0;
} else {
this._isDSTShifted = false;
}
return this._isDSTShifted;
}
function isLocal () {
return this.isValid() ? !this._isUTC : false;
}
function isUtcOffset () {
return this.isValid() ? this._isUTC : false;
}
function isUtc () {
return this.isValid() ? this._isUTC && this._offset === 0 : false;
}
// ASP.NET json date format regex
var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
// and further modified to allow for strings containing both week and day
var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
function create__createDuration (input, key) {
var duration = input,
// matching against regexp is expensive, do it on demand
match = null,
sign,
ret,
diffRes;
if (isDuration(input)) {
duration = {
ms : input._milliseconds,
d : input._days,
M : input._months
};
} else if (typeof input === 'number') {
duration = {};
if (key) {
duration[key] = input;
} else {
duration.milliseconds = input;
}
} else if (!!(match = aspNetRegex.exec(input))) {
sign = (match[1] === '-') ? -1 : 1;
duration = {
y : 0,
d : toInt(match[DATE]) * sign,
h : toInt(match[HOUR]) * sign,
m : toInt(match[MINUTE]) * sign,
s : toInt(match[SECOND]) * sign,
ms : toInt(match[MILLISECOND]) * sign
};
} else if (!!(match = isoRegex.exec(input))) {
sign = (match[1] === '-') ? -1 : 1;
duration = {
y : parseIso(match[2], sign),
M : parseIso(match[3], sign),
w : parseIso(match[4], sign),
d : parseIso(match[5], sign),
h : parseIso(match[6], sign),
m : parseIso(match[7], sign),
s : parseIso(match[8], sign)
};
} else if (duration == null) {// checks for null or undefined
duration = {};
} else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
duration = {};
duration.ms = diffRes.milliseconds;
duration.M = diffRes.months;
}
ret = new Duration(duration);
if (isDuration(input) && hasOwnProp(input, '_locale')) {
ret._locale = input._locale;
}
return ret;
}
create__createDuration.fn = Duration.prototype;
function parseIso (inp, sign) {
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var res = inp && parseFloat(inp.replace(',', '.'));
// apply sign while we're at it
return (isNaN(res) ? 0 : res) * sign;
}
function positiveMomentsDifference(base, other) {
var res = {milliseconds: 0, months: 0};
res.months = other.month() - base.month() +
(other.year() - base.year()) * 12;
if (base.clone().add(res.months, 'M').isAfter(other)) {
--res.months;
}
res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
return res;
}
function momentsDifference(base, other) {
var res;
if (!(base.isValid() && other.isValid())) {
return {milliseconds: 0, months: 0};
}
other = cloneWithOffset(other, base);
if (base.isBefore(other)) {
res = positiveMomentsDifference(base, other);
} else {
res = positiveMomentsDifference(other, base);
res.milliseconds = -res.milliseconds;
res.months = -res.months;
}
return res;
}
function absRound (number) {
if (number < 0) {
return Math.round(-1 * number) * -1;
} else {
return Math.round(number);
}
}
// TODO: remove 'name' arg after deprecation is removed
function createAdder(direction, name) {
return function (val, period) {
var dur, tmp;
//invert the arguments, but complain about it
if (period !== null && !isNaN(+period)) {
deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
tmp = val; val = period; period = tmp;
}
val = typeof val === 'string' ? +val : val;
dur = create__createDuration(val, period);
add_subtract__addSubtract(this, dur, direction);
return this;
};
}
function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
var milliseconds = duration._milliseconds,
days = absRound(duration._days),
months = absRound(duration._months);
if (!mom.isValid()) {
// No op
return;
}
updateOffset = updateOffset == null ? true : updateOffset;
if (milliseconds) {
mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
}
if (days) {
get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
}
if (months) {
setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
}
if (updateOffset) {
utils_hooks__hooks.updateOffset(mom, days || months);
}
}
var add_subtract__add = createAdder(1, 'add');
var add_subtract__subtract = createAdder(-1, 'subtract');
function moment_calendar__calendar (time, formats) {
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var now = time || local__createLocal(),
sod = cloneWithOffset(now, this).startOf('day'),
diff = this.diff(sod, 'days', true),
format = diff < -6 ? 'sameElse' :
diff < -1 ? 'lastWeek' :
diff < 0 ? 'lastDay' :
diff < 1 ? 'sameDay' :
diff < 2 ? 'nextDay' :
diff < 7 ? 'nextWeek' : 'sameElse';
var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
}
function clone () {
return new Moment(this);
}
function isAfter (input, units) {
var localInput = isMoment(input) ? input : local__createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
if (units === 'millisecond') {
return this.valueOf() > localInput.valueOf();
} else {
return localInput.valueOf() < this.clone().startOf(units).valueOf();
}
}
function isBefore (input, units) {
var localInput = isMoment(input) ? input : local__createLocal(input);
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
if (units === 'millisecond') {
return this.valueOf() < localInput.valueOf();
} else {
return this.clone().endOf(units).valueOf() < localInput.valueOf();
}
}
function isBetween (from, to, units, inclusivity) {
inclusivity = inclusivity || '()';
return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
(inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
}
function isSame (input, units) {
var localInput = isMoment(input) ? input : local__createLocal(input),
inputMs;
if (!(this.isValid() && localInput.isValid())) {
return false;
}
units = normalizeUnits(units || 'millisecond');
if (units === 'millisecond') {
return this.valueOf() === localInput.valueOf();
} else {
inputMs = localInput.valueOf();
return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
}
}
function isSameOrAfter (input, units) {
return this.isSame(input, units) || this.isAfter(input,units);
}
function isSameOrBefore (input, units) {
return this.isSame(input, units) || this.isBefore(input,units);
}
function diff (input, units, asFloat) {
var that,
zoneDelta,
delta, output;
if (!this.isValid()) {
return NaN;
}
that = cloneWithOffset(input, this);
if (!that.isValid()) {
return NaN;
}
zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
units = normalizeUnits(units);
if (units === 'year' || units === 'month' || units === 'quarter') {
output = monthDiff(this, that);
if (units === 'quarter') {
output = output / 3;
} else if (units === 'year') {
output = output / 12;
}
} else {
delta = this - that;
output = units === 'second' ? delta / 1e3 : // 1000
units === 'minute' ? delta / 6e4 : // 1000 * 60
units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
delta;
}
return asFloat ? output : absFloor(output);
}
function monthDiff (a, b) {
// difference in months
var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
anchor = a.clone().add(wholeMonthDiff, 'months'),
anchor2, adjust;
if (b - anchor < 0) {
anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor - anchor2);
} else {
anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
// linear across the month
adjust = (b - anchor) / (anchor2 - anchor);
}
//check for negative zero, return zero if negative zero
return -(wholeMonthDiff + adjust) || 0;
}
utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
function toString () {
return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
}
function moment_format__toISOString () {
var m = this.clone().utc();
if (0 < m.year() && m.year() <= 9999) {
if (isFunction(Date.prototype.toISOString)) {
// native implementation is ~50x faster, use it when we can
return this.toDate().toISOString();
} else {
return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
}
} else {
return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
}
}
function format (inputString) {
if (!inputString) {
inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
}
var output = formatMoment(this, inputString);
return this.localeData().postformat(output);
}
function from (time, withoutSuffix) {
if (this.isValid() &&
((isMoment(time) && time.isValid()) ||
local__createLocal(time).isValid())) {
return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function fromNow (withoutSuffix) {
return this.from(local__createLocal(), withoutSuffix);
}
function to (time, withoutSuffix) {
if (this.isValid() &&
((isMoment(time) && time.isValid()) ||
local__createLocal(time).isValid())) {
return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
} else {
return this.localeData().invalidDate();
}
}
function toNow (withoutSuffix) {
return this.to(local__createLocal(), withoutSuffix);
}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function locale (key) {
var newLocaleData;
if (key === undefined) {
return this._locale._abbr;
} else {
newLocaleData = locale_locales__getLocale(key);
if (newLocaleData != null) {
this._locale = newLocaleData;
}
return this;
}
}
var lang = deprecate(
'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
function (key) {
if (key === undefined) {
return this.localeData();
} else {
return this.locale(key);
}
}
);
function localeData () {
return this._locale;
}
function startOf (units) {
units = normalizeUnits(units);
// the following switch intentionally omits break keywords
// to utilize falling through the cases.
switch (units) {
case 'year':
this.month(0);
/* falls through */
case 'quarter':
case 'month':
this.date(1);
/* falls through */
case 'week':
case 'isoWeek':
case 'day':
case 'date':
this.hours(0);
/* falls through */
case 'hour':
this.minutes(0);
/* falls through */
case 'minute':
this.seconds(0);
/* falls through */
case 'second':
this.milliseconds(0);
}
// weeks are a special case
if (units === 'week') {
this.weekday(0);
}
if (units === 'isoWeek') {
this.isoWeekday(1);
}
// quarters are also special
if (units === 'quarter') {
this.month(Math.floor(this.month() / 3) * 3);
}
return this;
}
function endOf (units) {
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond') {
return this;
}
// 'date' is an alias for 'day', so it should be considered as such.
if (units === 'date') {
units = 'day';
}
return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
}
function to_type__valueOf () {
return this._d.valueOf() - ((this._offset || 0) * 60000);
}
function unix () {
return Math.floor(this.valueOf() / 1000);
}
function toDate () {
return this._offset ? new Date(this.valueOf()) : this._d;
}
function toArray () {
var m = this;
return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
}
function toObject () {
var m = this;
return {
years: m.year(),
months: m.month(),
date: m.date(),
hours: m.hours(),
minutes: m.minutes(),
seconds: m.seconds(),
milliseconds: m.milliseconds()
};
}
function toJSON () {
// new Date(NaN).toJSON() === null
return this.isValid() ? this.toISOString() : null;
}
function moment_valid__isValid () {
return valid__isValid(this);
}
function parsingFlags () {
return extend({}, getParsingFlags(this));
}
function invalidAt () {
return getParsingFlags(this).overflow;
}
function creationData() {
return {
input: this._i,
format: this._f,
locale: this._locale,
isUTC: this._isUTC,
strict: this._strict
};
}
// FORMATTING
addFormatToken(0, ['gg', 2], 0, function () {
return this.weekYear() % 100;
});
addFormatToken(0, ['GG', 2], 0, function () {
return this.isoWeekYear() % 100;
});
function addWeekYearFormatToken (token, getter) {
addFormatToken(0, [token, token.length], 0, getter);
}
addWeekYearFormatToken('gggg', 'weekYear');
addWeekYearFormatToken('ggggg', 'weekYear');
addWeekYearFormatToken('GGGG', 'isoWeekYear');
addWeekYearFormatToken('GGGGG', 'isoWeekYear');
// ALIASES
addUnitAlias('weekYear', 'gg');
addUnitAlias('isoWeekYear', 'GG');
// PARSING
addRegexToken('G', matchSigned);
addRegexToken('g', matchSigned);
addRegexToken('GG', match1to2, match2);
addRegexToken('gg', match1to2, match2);
addRegexToken('GGGG', match1to4, match4);
addRegexToken('gggg', match1to4, match4);
addRegexToken('GGGGG', match1to6, match6);
addRegexToken('ggggg', match1to6, match6);
addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
week[token.substr(0, 2)] = toInt(input);
});
addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
});
// MOMENTS
function getSetWeekYear (input) {
return getSetWeekYearHelper.call(this,
input,
this.week(),
this.weekday(),
this.localeData()._week.dow,
this.localeData()._week.doy);
}
function getSetISOWeekYear (input) {
return getSetWeekYearHelper.call(this,
input, this.isoWeek(), this.isoWeekday(), 1, 4);
}
function getISOWeeksInYear () {
return weeksInYear(this.year(), 1, 4);
}
function getWeeksInYear () {
var weekInfo = this.localeData()._week;
return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
}
function getSetWeekYearHelper(input, week, weekday, dow, doy) {
var weeksTarget;
if (input == null) {
return weekOfYear(this, dow, doy).year;
} else {
weeksTarget = weeksInYear(input, dow, doy);
if (week > weeksTarget) {
week = weeksTarget;
}
return setWeekAll.call(this, input, week, weekday, dow, doy);
}
}
function setWeekAll(weekYear, week, weekday, dow, doy) {
var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
this.year(date.getUTCFullYear());
this.month(date.getUTCMonth());
this.date(date.getUTCDate());
return this;
}
// FORMATTING
addFormatToken('Q', 0, 'Qo', 'quarter');
// ALIASES
addUnitAlias('quarter', 'Q');
// PARSING
addRegexToken('Q', match1);
addParseToken('Q', function (input, array) {
array[MONTH] = (toInt(input) - 1) * 3;
});
// MOMENTS
function getSetQuarter (input) {
return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
}
// FORMATTING
addFormatToken('w', ['ww', 2], 'wo', 'week');
addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
// ALIASES
addUnitAlias('week', 'w');
addUnitAlias('isoWeek', 'W');
// PARSING
addRegexToken('w', match1to2);
addRegexToken('ww', match1to2, match2);
addRegexToken('W', match1to2);
addRegexToken('WW', match1to2, match2);
addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
week[token.substr(0, 1)] = toInt(input);
});
// HELPERS
// LOCALES
function localeWeek (mom) {
return weekOfYear(mom, this._week.dow, this._week.doy).week;
}
var defaultLocaleWeek = {
dow : 0, // Sunday is the first day of the week.
doy : 6 // The week that contains Jan 1st is the first week of the year.
};
function localeFirstDayOfWeek () {
return this._week.dow;
}
function localeFirstDayOfYear () {
return this._week.doy;
}
// MOMENTS
function getSetWeek (input) {
var week = this.localeData().week(this);
return input == null ? week : this.add((input - week) * 7, 'd');
}
function getSetISOWeek (input) {
var week = weekOfYear(this, 1, 4).week;
return input == null ? week : this.add((input - week) * 7, 'd');
}
// FORMATTING
addFormatToken('D', ['DD', 2], 'Do', 'date');
// ALIASES
addUnitAlias('date', 'D');
// PARSING
addRegexToken('D', match1to2);
addRegexToken('DD', match1to2, match2);
addRegexToken('Do', function (isStrict, locale) {
return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
});
addParseToken(['D', 'DD'], DATE);
addParseToken('Do', function (input, array) {
array[DATE] = toInt(input.match(match1to2)[0], 10);
});
// MOMENTS
var getSetDayOfMonth = makeGetSet('Date', true);
// FORMATTING
addFormatToken('d', 0, 'do', 'day');
addFormatToken('dd', 0, 0, function (format) {
return this.localeData().weekdaysMin(this, format);
});
addFormatToken('ddd', 0, 0, function (format) {
return this.localeData().weekdaysShort(this, format);
});
addFormatToken('dddd', 0, 0, function (format) {
return this.localeData().weekdays(this, format);
});
addFormatToken('e', 0, 0, 'weekday');
addFormatToken('E', 0, 0, 'isoWeekday');
// ALIASES
addUnitAlias('day', 'd');
addUnitAlias('weekday', 'e');
addUnitAlias('isoWeekday', 'E');
// PARSING
addRegexToken('d', match1to2);
addRegexToken('e', match1to2);
addRegexToken('E', match1to2);
addRegexToken('dd', function (isStrict, locale) {
return locale.weekdaysMinRegex(isStrict);
});
addRegexToken('ddd', function (isStrict, locale) {
return locale.weekdaysShortRegex(isStrict);
});
addRegexToken('dddd', function (isStrict, locale) {
return locale.weekdaysRegex(isStrict);
});
addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
var weekday = config._locale.weekdaysParse(input, token, config._strict);
// if we didn't get a weekday name, mark the date as invalid
if (weekday != null) {
week.d = weekday;
} else {
getParsingFlags(config).invalidWeekday = input;
}
});
addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
week[token] = toInt(input);
});
// HELPERS
function parseWeekday(input, locale) {
if (typeof input !== 'string') {
return input;
}
if (!isNaN(input)) {
return parseInt(input, 10);
}
input = locale.weekdaysParse(input);
if (typeof input === 'number') {
return input;
}
return null;
}
// LOCALES
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
function localeWeekdays (m, format) {
return isArray(this._weekdays) ? this._weekdays[m.day()] :
this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
}
var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
function localeWeekdaysShort (m) {
return this._weekdaysShort[m.day()];
}
var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
function localeWeekdaysMin (m) {
return this._weekdaysMin[m.day()];
}
function day_of_week__handleStrictParse(weekdayName, format, strict) {
var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._shortWeekdaysParse = [];
this._minWeekdaysParse = [];
for (i = 0; i < 7; ++i) {
mom = create_utc__createUTC([2000, 1]).day(i);
this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
}
}
if (strict) {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
} else {
if (format === 'dddd') {
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else if (format === 'ddd') {
ii = indexOf.call(this._shortWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._minWeekdaysParse, llc);
return ii !== -1 ? ii : null;
} else {
ii = indexOf.call(this._minWeekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._weekdaysParse, llc);
if (ii !== -1) {
return ii;
}
ii = indexOf.call(this._shortWeekdaysParse, llc);
return ii !== -1 ? ii : null;
}
}
}
function localeWeekdaysParse (weekdayName, format, strict) {
var i, mom, regex;
if (this._weekdaysParseExact) {
return day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
}
if (!this._weekdaysParse) {
this._weekdaysParse = [];
this._minWeekdaysParse = [];
this._shortWeekdaysParse = [];
this._fullWeekdaysParse = [];
}
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = create_utc__createUTC([2000, 1]).day(i);
if (strict && !this._fullWeekdaysParse[i]) {
this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
}
if (!this._weekdaysParse[i]) {
regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
return i;
} else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
return i;
}
}
}
// MOMENTS
function getSetDayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
if (input != null) {
input = parseWeekday(input, this.localeData());
return this.add(input - day, 'd');
} else {
return day;
}
}
function getSetLocaleDayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
return input == null ? weekday : this.add(input - weekday, 'd');
}
function getSetISODayOfWeek (input) {
if (!this.isValid()) {
return input != null ? this : NaN;
}
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
}
var defaultWeekdaysRegex = matchWord;
function weekdaysRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysStrictRegex;
} else {
return this._weekdaysRegex;
}
} else {
return this._weekdaysStrictRegex && isStrict ?
this._weekdaysStrictRegex : this._weekdaysRegex;
}
}
var defaultWeekdaysShortRegex = matchWord;
function weekdaysShortRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysShortStrictRegex;
} else {
return this._weekdaysShortRegex;
}
} else {
return this._weekdaysShortStrictRegex && isStrict ?
this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
}
}
var defaultWeekdaysMinRegex = matchWord;
function weekdaysMinRegex (isStrict) {
if (this._weekdaysParseExact) {
if (!hasOwnProp(this, '_weekdaysRegex')) {
computeWeekdaysParse.call(this);
}
if (isStrict) {
return this._weekdaysMinStrictRegex;
} else {
return this._weekdaysMinRegex;
}
} else {
return this._weekdaysMinStrictRegex && isStrict ?
this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
}
}
function computeWeekdaysParse () {
function cmpLenRev(a, b) {
return b.length - a.length;
}
var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
i, mom, minp, shortp, longp;
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
mom = create_utc__createUTC([2000, 1]).day(i);
minp = this.weekdaysMin(mom, '');
shortp = this.weekdaysShort(mom, '');
longp = this.weekdays(mom, '');
minPieces.push(minp);
shortPieces.push(shortp);
longPieces.push(longp);
mixedPieces.push(minp);
mixedPieces.push(shortp);
mixedPieces.push(longp);
}
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
minPieces.sort(cmpLenRev);
shortPieces.sort(cmpLenRev);
longPieces.sort(cmpLenRev);
mixedPieces.sort(cmpLenRev);
for (i = 0; i < 7; i++) {
shortPieces[i] = regexEscape(shortPieces[i]);
longPieces[i] = regexEscape(longPieces[i]);
mixedPieces[i] = regexEscape(mixedPieces[i]);
}
this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._weekdaysShortRegex = this._weekdaysRegex;
this._weekdaysMinRegex = this._weekdaysRegex;
this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
}
// FORMATTING
addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
// ALIASES
addUnitAlias('dayOfYear', 'DDD');
// PARSING
addRegexToken('DDD', match1to3);
addRegexToken('DDDD', match3);
addParseToken(['DDD', 'DDDD'], function (input, array, config) {
config._dayOfYear = toInt(input);
});
// HELPERS
// MOMENTS
function getSetDayOfYear (input) {
var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
}
// FORMATTING
function hFormat() {
return this.hours() % 12 || 12;
}
function kFormat() {
return this.hours() || 24;
}
addFormatToken('H', ['HH', 2], 0, 'hour');
addFormatToken('h', ['hh', 2], 0, hFormat);
addFormatToken('k', ['kk', 2], 0, kFormat);
addFormatToken('hmm', 0, 0, function () {
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
});
addFormatToken('hmmss', 0, 0, function () {
return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2);
});
addFormatToken('Hmm', 0, 0, function () {
return '' + this.hours() + zeroFill(this.minutes(), 2);
});
addFormatToken('Hmmss', 0, 0, function () {
return '' + this.hours() + zeroFill(this.minutes(), 2) +
zeroFill(this.seconds(), 2);
});
function meridiem (token, lowercase) {
addFormatToken(token, 0, 0, function () {
return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
});
}
meridiem('a', true);
meridiem('A', false);
// ALIASES
addUnitAlias('hour', 'h');
// PARSING
function matchMeridiem (isStrict, locale) {
return locale._meridiemParse;
}
addRegexToken('a', matchMeridiem);
addRegexToken('A', matchMeridiem);
addRegexToken('H', match1to2);
addRegexToken('h', match1to2);
addRegexToken('HH', match1to2, match2);
addRegexToken('hh', match1to2, match2);
addRegexToken('hmm', match3to4);
addRegexToken('hmmss', match5to6);
addRegexToken('Hmm', match3to4);
addRegexToken('Hmmss', match5to6);
addParseToken(['H', 'HH'], HOUR);
addParseToken(['a', 'A'], function (input, array, config) {
config._isPm = config._locale.isPM(input);
config._meridiem = input;
});
addParseToken(['h', 'hh'], function (input, array, config) {
array[HOUR] = toInt(input);
getParsingFlags(config).bigHour = true;
});
addParseToken('hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
getParsingFlags(config).bigHour = true;
});
addParseToken('hmmss', function (input, array, config) {
var pos1 = input.length - 4;
var pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
getParsingFlags(config).bigHour = true;
});
addParseToken('Hmm', function (input, array, config) {
var pos = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos));
array[MINUTE] = toInt(input.substr(pos));
});
addParseToken('Hmmss', function (input, array, config) {
var pos1 = input.length - 4;
var pos2 = input.length - 2;
array[HOUR] = toInt(input.substr(0, pos1));
array[MINUTE] = toInt(input.substr(pos1, 2));
array[SECOND] = toInt(input.substr(pos2));
});
// LOCALES
function localeIsPM (input) {
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return ((input + '').toLowerCase().charAt(0) === 'p');
}
var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
function localeMeridiem (hours, minutes, isLower) {
if (hours > 11) {
return isLower ? 'pm' : 'PM';
} else {
return isLower ? 'am' : 'AM';
}
}
// MOMENTS
// Setting the hour should keep the time, because the user explicitly
// specified which hour he wants. So trying to maintain the same hour (in
// a new timezone) makes sense. Adding/subtracting hours does not follow
// this rule.
var getSetHour = makeGetSet('Hours', true);
// FORMATTING
addFormatToken('m', ['mm', 2], 0, 'minute');
// ALIASES
addUnitAlias('minute', 'm');
// PARSING
addRegexToken('m', match1to2);
addRegexToken('mm', match1to2, match2);
addParseToken(['m', 'mm'], MINUTE);
// MOMENTS
var getSetMinute = makeGetSet('Minutes', false);
// FORMATTING
addFormatToken('s', ['ss', 2], 0, 'second');
// ALIASES
addUnitAlias('second', 's');
// PARSING
addRegexToken('s', match1to2);
addRegexToken('ss', match1to2, match2);
addParseToken(['s', 'ss'], SECOND);
// MOMENTS
var getSetSecond = makeGetSet('Seconds', false);
// FORMATTING
addFormatToken('S', 0, 0, function () {
return ~~(this.millisecond() / 100);
});
addFormatToken(0, ['SS', 2], 0, function () {
return ~~(this.millisecond() / 10);
});
addFormatToken(0, ['SSS', 3], 0, 'millisecond');
addFormatToken(0, ['SSSS', 4], 0, function () {
return this.millisecond() * 10;
});
addFormatToken(0, ['SSSSS', 5], 0, function () {
return this.millisecond() * 100;
});
addFormatToken(0, ['SSSSSS', 6], 0, function () {
return this.millisecond() * 1000;
});
addFormatToken(0, ['SSSSSSS', 7], 0, function () {
return this.millisecond() * 10000;
});
addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
return this.millisecond() * 100000;
});
addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
return this.millisecond() * 1000000;
});
// ALIASES
addUnitAlias('millisecond', 'ms');
// PARSING
addRegexToken('S', match1to3, match1);
addRegexToken('SS', match1to3, match2);
addRegexToken('SSS', match1to3, match3);
var token;
for (token = 'SSSS'; token.length <= 9; token += 'S') {
addRegexToken(token, matchUnsigned);
}
function parseMs(input, array) {
array[MILLISECOND] = toInt(('0.' + input) * 1000);
}
for (token = 'S'; token.length <= 9; token += 'S') {
addParseToken(token, parseMs);
}
// MOMENTS
var getSetMillisecond = makeGetSet('Milliseconds', false);
// FORMATTING
addFormatToken('z', 0, 0, 'zoneAbbr');
addFormatToken('zz', 0, 0, 'zoneName');
// MOMENTS
function getZoneAbbr () {
return this._isUTC ? 'UTC' : '';
}
function getZoneName () {
return this._isUTC ? 'Coordinated Universal Time' : '';
}
var momentPrototype__proto = Moment.prototype;
momentPrototype__proto.add = add_subtract__add;
momentPrototype__proto.calendar = moment_calendar__calendar;
momentPrototype__proto.clone = clone;
momentPrototype__proto.diff = diff;
momentPrototype__proto.endOf = endOf;
momentPrototype__proto.format = format;
momentPrototype__proto.from = from;
momentPrototype__proto.fromNow = fromNow;
momentPrototype__proto.to = to;
momentPrototype__proto.toNow = toNow;
momentPrototype__proto.get = getSet;
momentPrototype__proto.invalidAt = invalidAt;
momentPrototype__proto.isAfter = isAfter;
momentPrototype__proto.isBefore = isBefore;
momentPrototype__proto.isBetween = isBetween;
momentPrototype__proto.isSame = isSame;
momentPrototype__proto.isSameOrAfter = isSameOrAfter;
momentPrototype__proto.isSameOrBefore = isSameOrBefore;
momentPrototype__proto.isValid = moment_valid__isValid;
momentPrototype__proto.lang = lang;
momentPrototype__proto.locale = locale;
momentPrototype__proto.localeData = localeData;
momentPrototype__proto.max = prototypeMax;
momentPrototype__proto.min = prototypeMin;
momentPrototype__proto.parsingFlags = parsingFlags;
momentPrototype__proto.set = getSet;
momentPrototype__proto.startOf = startOf;
momentPrototype__proto.subtract = add_subtract__subtract;
momentPrototype__proto.toArray = toArray;
momentPrototype__proto.toObject = toObject;
momentPrototype__proto.toDate = toDate;
momentPrototype__proto.toISOString = moment_format__toISOString;
momentPrototype__proto.toJSON = toJSON;
momentPrototype__proto.toString = toString;
momentPrototype__proto.unix = unix;
momentPrototype__proto.valueOf = to_type__valueOf;
momentPrototype__proto.creationData = creationData;
// Year
momentPrototype__proto.year = getSetYear;
momentPrototype__proto.isLeapYear = getIsLeapYear;
// Week Year
momentPrototype__proto.weekYear = getSetWeekYear;
momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
// Quarter
momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
// Month
momentPrototype__proto.month = getSetMonth;
momentPrototype__proto.daysInMonth = getDaysInMonth;
// Week
momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek;
momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek;
momentPrototype__proto.weeksInYear = getWeeksInYear;
momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
// Day
momentPrototype__proto.date = getSetDayOfMonth;
momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek;
momentPrototype__proto.weekday = getSetLocaleDayOfWeek;
momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
momentPrototype__proto.dayOfYear = getSetDayOfYear;
// Hour
momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
// Minute
momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
// Second
momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
// Millisecond
momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
// Offset
momentPrototype__proto.utcOffset = getSetOffset;
momentPrototype__proto.utc = setOffsetToUTC;
momentPrototype__proto.local = setOffsetToLocal;
momentPrototype__proto.parseZone = setOffsetToParsedOffset;
momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
momentPrototype__proto.isDST = isDaylightSavingTime;
momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted;
momentPrototype__proto.isLocal = isLocal;
momentPrototype__proto.isUtcOffset = isUtcOffset;
momentPrototype__proto.isUtc = isUtc;
momentPrototype__proto.isUTC = isUtc;
// Timezone
momentPrototype__proto.zoneAbbr = getZoneAbbr;
momentPrototype__proto.zoneName = getZoneName;
// Deprecations
momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
var momentPrototype = momentPrototype__proto;
function moment__createUnix (input) {
return local__createLocal(input * 1000);
}
function moment__createInZone () {
return local__createLocal.apply(null, arguments).parseZone();
}
var defaultCalendar = {
sameDay : '[Today at] LT',
nextDay : '[Tomorrow at] LT',
nextWeek : 'dddd [at] LT',
lastDay : '[Yesterday at] LT',
lastWeek : '[Last] dddd [at] LT',
sameElse : 'L'
};
function locale_calendar__calendar (key, mom, now) {
var output = this._calendar[key];
return isFunction(output) ? output.call(mom, now) : output;
}
var defaultLongDateFormat = {
LTS : 'h:mm:ss A',
LT : 'h:mm A',
L : 'MM/DD/YYYY',
LL : 'MMMM D, YYYY',
LLL : 'MMMM D, YYYY h:mm A',
LLLL : 'dddd, MMMM D, YYYY h:mm A'
};
function longDateFormat (key) {
var format = this._longDateFormat[key],
formatUpper = this._longDateFormat[key.toUpperCase()];
if (format || !formatUpper) {
return format;
}
this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
return val.slice(1);
});
return this._longDateFormat[key];
}
var defaultInvalidDate = 'Invalid date';
function invalidDate () {
return this._invalidDate;
}
var defaultOrdinal = '%d';
var defaultOrdinalParse = /\d{1,2}/;
function ordinal (number) {
return this._ordinal.replace('%d', number);
}
function preParsePostFormat (string) {
return string;
}
var defaultRelativeTime = {
future : 'in %s',
past : '%s ago',
s : 'a few seconds',
m : 'a minute',
mm : '%d minutes',
h : 'an hour',
hh : '%d hours',
d : 'a day',
dd : '%d days',
M : 'a month',
MM : '%d months',
y : 'a year',
yy : '%d years'
};
function relative__relativeTime (number, withoutSuffix, string, isFuture) {
var output = this._relativeTime[string];
return (isFunction(output)) ?
output(number, withoutSuffix, string, isFuture) :
output.replace(/%d/i, number);
}
function pastFuture (diff, output) {
var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
return isFunction(format) ? format(output) : format.replace(/%s/i, output);
}
var prototype__proto = Locale.prototype;
prototype__proto._calendar = defaultCalendar;
prototype__proto.calendar = locale_calendar__calendar;
prototype__proto._longDateFormat = defaultLongDateFormat;
prototype__proto.longDateFormat = longDateFormat;
prototype__proto._invalidDate = defaultInvalidDate;
prototype__proto.invalidDate = invalidDate;
prototype__proto._ordinal = defaultOrdinal;
prototype__proto.ordinal = ordinal;
prototype__proto._ordinalParse = defaultOrdinalParse;
prototype__proto.preparse = preParsePostFormat;
prototype__proto.postformat = preParsePostFormat;
prototype__proto._relativeTime = defaultRelativeTime;
prototype__proto.relativeTime = relative__relativeTime;
prototype__proto.pastFuture = pastFuture;
prototype__proto.set = locale_set__set;
// Month
prototype__proto.months = localeMonths;
prototype__proto._months = defaultLocaleMonths;
prototype__proto.monthsShort = localeMonthsShort;
prototype__proto._monthsShort = defaultLocaleMonthsShort;
prototype__proto.monthsParse = localeMonthsParse;
prototype__proto._monthsRegex = defaultMonthsRegex;
prototype__proto.monthsRegex = monthsRegex;
prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
prototype__proto.monthsShortRegex = monthsShortRegex;
// Week
prototype__proto.week = localeWeek;
prototype__proto._week = defaultLocaleWeek;
prototype__proto.firstDayOfYear = localeFirstDayOfYear;
prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
// Day of Week
prototype__proto.weekdays = localeWeekdays;
prototype__proto._weekdays = defaultLocaleWeekdays;
prototype__proto.weekdaysMin = localeWeekdaysMin;
prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin;
prototype__proto.weekdaysShort = localeWeekdaysShort;
prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
prototype__proto.weekdaysParse = localeWeekdaysParse;
prototype__proto._weekdaysRegex = defaultWeekdaysRegex;
prototype__proto.weekdaysRegex = weekdaysRegex;
prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
prototype__proto.weekdaysShortRegex = weekdaysShortRegex;
prototype__proto._weekdaysMinRegex = defaultWeekdaysMinRegex;
prototype__proto.weekdaysMinRegex = weekdaysMinRegex;
// Hours
prototype__proto.isPM = localeIsPM;
prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
prototype__proto.meridiem = localeMeridiem;
function lists__get (format, index, field, setter) {
var locale = locale_locales__getLocale();
var utc = create_utc__createUTC().set(setter, index);
return locale[field](utc, format);
}
function listMonthsImpl (format, index, field) {
if (typeof format === 'number') {
index = format;
format = undefined;
}
format = format || '';
if (index != null) {
return lists__get(format, index, field, 'month');
}
var i;
var out = [];
for (i = 0; i < 12; i++) {
out[i] = lists__get(format, i, field, 'month');
}
return out;
}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function listWeekdaysImpl (localeSorted, format, index, field) {
if (typeof localeSorted === 'boolean') {
if (typeof format === 'number') {
index = format;
format = undefined;
}
format = format || '';
} else {
format = localeSorted;
index = format;
localeSorted = false;
if (typeof format === 'number') {
index = format;
format = undefined;
}
format = format || '';
}
var locale = locale_locales__getLocale(),
shift = localeSorted ? locale._week.dow : 0;
if (index != null) {
return lists__get(format, (index + shift) % 7, field, 'day');
}
var i;
var out = [];
for (i = 0; i < 7; i++) {
out[i] = lists__get(format, (i + shift) % 7, field, 'day');
}
return out;
}
function lists__listMonths (format, index) {
return listMonthsImpl(format, index, 'months');
}
function lists__listMonthsShort (format, index) {
return listMonthsImpl(format, index, 'monthsShort');
}
function lists__listWeekdays (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
}
function lists__listWeekdaysShort (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
}
function lists__listWeekdaysMin (localeSorted, format, index) {
return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
}
locale_locales__getSetGlobalLocale('en', {
ordinalParse: /\d{1,2}(th|st|nd|rd)/,
ordinal : function (number) {
var b = number % 10,
output = (toInt(number % 100 / 10) === 1) ? 'th' :
(b === 1) ? 'st' :
(b === 2) ? 'nd' :
(b === 3) ? 'rd' : 'th';
return number + output;
}
});
// Side effect imports
utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
var mathAbs = Math.abs;
function duration_abs__abs () {
var data = this._data;
this._milliseconds = mathAbs(this._milliseconds);
this._days = mathAbs(this._days);
this._months = mathAbs(this._months);
data.milliseconds = mathAbs(data.milliseconds);
data.seconds = mathAbs(data.seconds);
data.minutes = mathAbs(data.minutes);
data.hours = mathAbs(data.hours);
data.months = mathAbs(data.months);
data.years = mathAbs(data.years);
return this;
}
function duration_add_subtract__addSubtract (duration, input, value, direction) {
var other = create__createDuration(input, value);
duration._milliseconds += direction * other._milliseconds;
duration._days += direction * other._days;
duration._months += direction * other._months;
return duration._bubble();
}
// supports only 2.0-style add(1, 's') or add(duration)
function duration_add_subtract__add (input, value) {
return duration_add_subtract__addSubtract(this, input, value, 1);
}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function duration_add_subtract__subtract (input, value) {
return duration_add_subtract__addSubtract(this, input, value, -1);
}
function absCeil (number) {
if (number < 0) {
return Math.floor(number);
} else {
return Math.ceil(number);
}
}
function bubble () {
var milliseconds = this._milliseconds;
var days = this._days;
var months = this._months;
var data = this._data;
var seconds, minutes, hours, years, monthsFromDays;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
(milliseconds <= 0 && days <= 0 && months <= 0))) {
milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
days = 0;
months = 0;
}
// The following code bubbles up values, see the tests for
// examples of what that means.
data.milliseconds = milliseconds % 1000;
seconds = absFloor(milliseconds / 1000);
data.seconds = seconds % 60;
minutes = absFloor(seconds / 60);
data.minutes = minutes % 60;
hours = absFloor(minutes / 60);
data.hours = hours % 24;
days += absFloor(hours / 24);
// convert days to months
monthsFromDays = absFloor(daysToMonths(days));
months += monthsFromDays;
days -= absCeil(monthsToDays(monthsFromDays));
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
data.days = days;
data.months = months;
data.years = years;
return this;
}
function daysToMonths (days) {
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return days * 4800 / 146097;
}
function monthsToDays (months) {
// the reverse of daysToMonths
return months * 146097 / 4800;
}
function as (units) {
var days;
var months;
var milliseconds = this._milliseconds;
units = normalizeUnits(units);
if (units === 'month' || units === 'year') {
days = this._days + milliseconds / 864e5;
months = this._months + daysToMonths(days);
return units === 'month' ? months : months / 12;
} else {
// handle milliseconds separately because of floating point math errors (issue #1867)
days = this._days + Math.round(monthsToDays(this._months));
switch (units) {
case 'week' : return days / 7 + milliseconds / 6048e5;
case 'day' : return days + milliseconds / 864e5;
case 'hour' : return days * 24 + milliseconds / 36e5;
case 'minute' : return days * 1440 + milliseconds / 6e4;
case 'second' : return days * 86400 + milliseconds / 1000;
// Math.floor prevents floating point math errors here
case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
default: throw new Error('Unknown unit ' + units);
}
}
}
// TODO: Use this.as('ms')?
function duration_as__valueOf () {
return (
this._milliseconds +
this._days * 864e5 +
(this._months % 12) * 2592e6 +
toInt(this._months / 12) * 31536e6
);
}
function makeAs (alias) {
return function () {
return this.as(alias);
};
}
var asMilliseconds = makeAs('ms');
var asSeconds = makeAs('s');
var asMinutes = makeAs('m');
var asHours = makeAs('h');
var asDays = makeAs('d');
var asWeeks = makeAs('w');
var asMonths = makeAs('M');
var asYears = makeAs('y');
function duration_get__get (units) {
units = normalizeUnits(units);
return this[units + 's']();
}
function makeGetter(name) {
return function () {
return this._data[name];
};
}
var milliseconds = makeGetter('milliseconds');
var seconds = makeGetter('seconds');
var minutes = makeGetter('minutes');
var hours = makeGetter('hours');
var days = makeGetter('days');
var months = makeGetter('months');
var years = makeGetter('years');
function weeks () {
return absFloor(this.days() / 7);
}
var round = Math.round;
var thresholds = {
s: 45, // seconds to minute
m: 45, // minutes to hour
h: 22, // hours to day
d: 26, // days to month
M: 11 // months to year
};
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
}
function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
var duration = create__createDuration(posNegDuration).abs();
var seconds = round(duration.as('s'));
var minutes = round(duration.as('m'));
var hours = round(duration.as('h'));
var days = round(duration.as('d'));
var months = round(duration.as('M'));
var years = round(duration.as('y'));
var a = seconds < thresholds.s && ['s', seconds] ||
minutes <= 1 && ['m'] ||
minutes < thresholds.m && ['mm', minutes] ||
hours <= 1 && ['h'] ||
hours < thresholds.h && ['hh', hours] ||
days <= 1 && ['d'] ||
days < thresholds.d && ['dd', days] ||
months <= 1 && ['M'] ||
months < thresholds.M && ['MM', months] ||
years <= 1 && ['y'] || ['yy', years];
a[2] = withoutSuffix;
a[3] = +posNegDuration > 0;
a[4] = locale;
return substituteTimeAgo.apply(null, a);
}
// This function allows you to set a threshold for relative time strings
function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
if (thresholds[threshold] === undefined) {
return false;
}
if (limit === undefined) {
return thresholds[threshold];
}
thresholds[threshold] = limit;
return true;
}
function humanize (withSuffix) {
var locale = this.localeData();
var output = duration_humanize__relativeTime(this, !withSuffix, locale);
if (withSuffix) {
output = locale.pastFuture(+this, output);
}
return locale.postformat(output);
}
var iso_string__abs = Math.abs;
function iso_string__toISOString() {
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
var seconds = iso_string__abs(this._milliseconds) / 1000;
var days = iso_string__abs(this._days);
var months = iso_string__abs(this._months);
var minutes, hours, years;
// 3600 seconds -> 60 minutes -> 1 hour
minutes = absFloor(seconds / 60);
hours = absFloor(minutes / 60);
seconds %= 60;
minutes %= 60;
// 12 months -> 1 year
years = absFloor(months / 12);
months %= 12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var Y = years;
var M = months;
var D = days;
var h = hours;
var m = minutes;
var s = seconds;
var total = this.asSeconds();
if (!total) {
// this is the same as C#'s (Noda) and python (isodate)...
// but not other JS (goog.date)
return 'P0D';
}
return (total < 0 ? '-' : '') +
'P' +
(Y ? Y + 'Y' : '') +
(M ? M + 'M' : '') +
(D ? D + 'D' : '') +
((h || m || s) ? 'T' : '') +
(h ? h + 'H' : '') +
(m ? m + 'M' : '') +
(s ? s + 'S' : '');
}
var duration_prototype__proto = Duration.prototype;
duration_prototype__proto.abs = duration_abs__abs;
duration_prototype__proto.add = duration_add_subtract__add;
duration_prototype__proto.subtract = duration_add_subtract__subtract;
duration_prototype__proto.as = as;
duration_prototype__proto.asMilliseconds = asMilliseconds;
duration_prototype__proto.asSeconds = asSeconds;
duration_prototype__proto.asMinutes = asMinutes;
duration_prototype__proto.asHours = asHours;
duration_prototype__proto.asDays = asDays;
duration_prototype__proto.asWeeks = asWeeks;
duration_prototype__proto.asMonths = asMonths;
duration_prototype__proto.asYears = asYears;
duration_prototype__proto.valueOf = duration_as__valueOf;
duration_prototype__proto._bubble = bubble;
duration_prototype__proto.get = duration_get__get;
duration_prototype__proto.milliseconds = milliseconds;
duration_prototype__proto.seconds = seconds;
duration_prototype__proto.minutes = minutes;
duration_prototype__proto.hours = hours;
duration_prototype__proto.days = days;
duration_prototype__proto.weeks = weeks;
duration_prototype__proto.months = months;
duration_prototype__proto.years = years;
duration_prototype__proto.humanize = humanize;
duration_prototype__proto.toISOString = iso_string__toISOString;
duration_prototype__proto.toString = iso_string__toISOString;
duration_prototype__proto.toJSON = iso_string__toISOString;
duration_prototype__proto.locale = locale;
duration_prototype__proto.localeData = localeData;
// Deprecations
duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
duration_prototype__proto.lang = lang;
// Side effect imports
// FORMATTING
addFormatToken('X', 0, 0, 'unix');
addFormatToken('x', 0, 0, 'valueOf');
// PARSING
addRegexToken('x', matchSigned);
addRegexToken('X', matchTimestamp);
addParseToken('X', function (input, array, config) {
config._d = new Date(parseFloat(input, 10) * 1000);
});
addParseToken('x', function (input, array, config) {
config._d = new Date(toInt(input));
});
// Side effect imports
utils_hooks__hooks.version = '2.13.0';
setHookCallback(local__createLocal);
utils_hooks__hooks.fn = momentPrototype;
utils_hooks__hooks.min = min;
utils_hooks__hooks.max = max;
utils_hooks__hooks.now = now;
utils_hooks__hooks.utc = create_utc__createUTC;
utils_hooks__hooks.unix = moment__createUnix;
utils_hooks__hooks.months = lists__listMonths;
utils_hooks__hooks.isDate = isDate;
utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale;
utils_hooks__hooks.invalid = valid__createInvalid;
utils_hooks__hooks.duration = create__createDuration;
utils_hooks__hooks.isMoment = isMoment;
utils_hooks__hooks.weekdays = lists__listWeekdays;
utils_hooks__hooks.parseZone = moment__createInZone;
utils_hooks__hooks.localeData = locale_locales__getLocale;
utils_hooks__hooks.isDuration = isDuration;
utils_hooks__hooks.monthsShort = lists__listMonthsShort;
utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin;
utils_hooks__hooks.defineLocale = defineLocale;
utils_hooks__hooks.updateLocale = updateLocale;
utils_hooks__hooks.locales = locale_locales__listLocales;
utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort;
utils_hooks__hooks.normalizeUnits = normalizeUnits;
utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
utils_hooks__hooks.prototype = momentPrototype;
var _moment = utils_hooks__hooks;
return _moment;
}));
/**
* bootbox.js v4.4.0
*
* http://bootboxjs.com/license.txt
*/
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"<div class='bootbox modal' tabindex='-1' role='dialog'><div class='modal-dialog'><div class='modal-content'><div class='modal-body'><div class='bootbox-body'></div></div></div></div></div>",header:"<div class='modal-header'><h4 class='modal-title'></h4></div>",footer:"<div class='modal-footer'></div>",closeButton:"<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>×</button>",form:"<form class='bootbox-form'></form>",inputs:{text:"<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",textarea:"<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",email:"<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",select:"<select class='bootbox-input bootbox-input-select form-control'></select>",checkbox:"<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",date:"<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",time:"<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",number:"<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",password:"<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("<optgroup/>").attr("label",d.group)),e=o[d.group]),e.append("<option value='"+d.value+"'>"+d.text+"</option>")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("<div/>"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="<button data-bb-handler='"+a+"' type='button' class='btn "+b.className+"'>"+b.label+"</button>",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p});
/*!
* Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2016 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b.replace(this.re,this.ch)}),b}function c(a){var b={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},c="(?:"+Object.keys(b).join("|")+")",d=new RegExp(c),e=new RegExp(c,"g"),f=null==a?"":""+a;return d.test(f)?f.replace(e,function(a){return b[a]}):f}function d(b,c){var d=arguments,f=b,g=c;[].shift.apply(d);var h,i=this.each(function(){var b=a(this);if(b.is("select")){var c=b.data("selectpicker"),i="object"==typeof f&&f;if(c){if(i)for(var j in i)i.hasOwnProperty(j)&&(c.options[j]=i[j])}else{var k=a.extend({},e.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),i);k.template=a.extend({},e.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,i.template),b.data("selectpicker",c=new e(this,k,g))}"string"==typeof f&&(h=c[f]instanceof Function?c[f].apply(c,d):c.options[f])}});return"undefined"!=typeof h?h:i}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),c="".indexOf,d=function(b){if(null==this)throw new TypeError;var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw new TypeError;var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return g+j>e?!1:-1!=c.call(d,f,i)};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(d){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j<f;)if(c.charCodeAt(i+j)!=e.charCodeAt(j))return!1;return!0};a?a(String.prototype,"startsWith",{value:c,configurable:!0,writable:!0}):String.prototype.startsWith=c}(),Object.keys||(Object.keys=function(a,b,c){c=[];for(b in a)c.hasOwnProperty.call(a,b)&&c.push(b);return c}),a.fn.triggerNative=function(a){var b,c=this[0];c.dispatchEvent?("function"==typeof Event?b=new Event(a,{bubbles:!0}):(b=document.createEvent("Event"),b.initEvent(a,!0,!1)),c.dispatchEvent(b)):(c.fireEvent&&(b=document.createEventObject(),b.eventType=a,c.fireEvent("on"+a,b)),this.trigger(a))},a.expr[":"].icontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].ibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())},a.expr[":"].aicontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.includes(d[3].toUpperCase())},a.expr[":"].aibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toUpperCase();return f.startsWith(d[3].toUpperCase())};var e=function(b,c,d){d&&(d.stopPropagation(),d.preventDefault()),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title")),this.val=e.prototype.val,this.render=e.prototype.render,this.refresh=e.prototype.refresh,this.setStyle=e.prototype.setStyle,this.selectAll=e.prototype.selectAll,this.deselectAll=e.prototype.deselectAll,this.destroy=e.prototype.destroy,this.remove=e.prototype.remove,this.show=e.prototype.show,this.hide=e.prototype.hide,this.init()};e.VERSION="1.10.0",e.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",showTick:!1,template:{caret:'<span class="caret"></span>'},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1},e.prototype={constructor:e,init:function(){var b=this,c=this.$element.attr("id");this.$element.addClass("bs-select-hidden"),this.liObj={},this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createView(),this.$element.after(this.$newElement).appendTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(".dropdown-menu"),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element.removeClass("bs-select-hidden"),this.options.dropdownAlignRight&&this.$menu.addClass("dropdown-menu-right"),"undefined"!=typeof c&&(this.$button.attr("data-id",c),a('label[for="'+c+'"]').click(function(a){a.preventDefault(),b.$button.focus()})),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.setStyle(),this.setWidth(),this.options.container&&this.selectPosition(),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(a){b.$element.trigger("hide.bs.select",a)},"hidden.bs.dropdown":function(a){b.$element.trigger("hidden.bs.select",a)},"show.bs.dropdown":function(a){b.$element.trigger("show.bs.select",a)},"shown.bs.dropdown":function(a){b.$element.trigger("shown.bs.select",a)}}),b.$element[0].hasAttribute("required")&&this.$element.on("invalid",function(){b.$button.addClass("bs-invalid").focus(),b.$element.on({"focus.bs.select":function(){b.$button.focus(),b.$element.off("focus.bs.select")},"shown.bs.select":function(){b.$element.val(b.$element.val()).off("shown.bs.select")},"rendered.bs.select":function(){this.validity.valid&&b.$button.removeClass("bs-invalid"),b.$element.off("rendered.bs.select")}})}),setTimeout(function(){b.$element.trigger("loaded.bs.select")})},createDropdown:function(){var b=this.multiple||this.options.showTick?" show-tick":"",d=this.$element.parent().hasClass("input-group")?" input-group-btn":"",e=this.autofocus?" autofocus":"",f=this.options.header?'<div class="popover-title"><button type="button" class="close" aria-hidden="true">×</button>'+this.options.header+"</div>":"",g=this.options.liveSearch?'<div class="bs-searchbox"><input type="text" class="form-control" autocomplete="off"'+(null===this.options.liveSearchPlaceholder?"":' placeholder="'+c(this.options.liveSearchPlaceholder)+'"')+"></div>":"",h=this.multiple&&this.options.actionsBox?'<div class="bs-actionsbox"><div class="btn-group btn-group-sm btn-block"><button type="button" class="actions-btn bs-select-all btn btn-default">'+this.options.selectAllText+'</button><button type="button" class="actions-btn bs-deselect-all btn btn-default">'+this.options.deselectAllText+"</button></div></div>":"",i=this.multiple&&this.options.doneButton?'<div class="bs-donebutton"><div class="btn-group btn-block"><button type="button" class="btn btn-sm btn-default">'+this.options.doneButtonText+"</button></div></div>":"",j='<div class="btn-group bootstrap-select'+b+d+'"><button type="button" class="'+this.options.styleBase+' dropdown-toggle" data-toggle="dropdown"'+e+'><span class="filter-option pull-left"></span> <span class="bs-caret">'+this.options.template.caret+'</span></button><div class="dropdown-menu open">'+f+g+h+'<ul class="dropdown-menu inner" role="menu"></ul>'+i+"</div></div>";return a(j)},createView:function(){var a=this.createDropdown(),b=this.createLi();return a.find("ul")[0].innerHTML=b,a},reloadLi:function(){this.destroyLi();var a=this.createLi();this.$menuInner[0].innerHTML=a},destroyLi:function(){this.$menu.find("li").remove()},createLi:function(){var d=this,e=[],f=0,g=document.createElement("option"),h=-1,i=function(a,b,c,d){return"<li"+("undefined"!=typeof c&""!==c?' class="'+c+'"':"")+("undefined"!=typeof b&null!==b?' data-original-index="'+b+'"':"")+("undefined"!=typeof d&null!==d?'data-optgroup="'+d+'"':"")+">"+a+"</li>"},j=function(a,e,f,g){return'<a tabindex="0"'+("undefined"!=typeof e?' class="'+e+'"':"")+("undefined"!=typeof f?' style="'+f+'"':"")+(d.options.liveSearchNormalize?' data-normalized-text="'+b(c(a))+'"':"")+("undefined"!=typeof g||null!==g?' data-tokens="'+g+'"':"")+">"+a+'<span class="'+d.options.iconBase+" "+d.options.tickIcon+' check-mark"></span></a>'};if(this.options.title&&!this.multiple&&(h--,!this.$element.find(".bs-title-option").length)){var k=this.$element[0];g.className="bs-title-option",g.appendChild(document.createTextNode(this.options.title)),g.value="",k.insertBefore(g,k.firstChild),void 0===a(k.options[k.selectedIndex]).attr("selected")&&(g.selected=!0)}return this.$element.find("option").each(function(b){var c=a(this);if(h++,!c.hasClass("bs-title-option")){var g=this.className||"",k=this.style.cssText,l=c.data("content")?c.data("content"):c.html(),m=c.data("tokens")?c.data("tokens"):null,n="undefined"!=typeof c.data("subtext")?'<small class="text-muted">'+c.data("subtext")+"</small>":"",o="undefined"!=typeof c.data("icon")?'<span class="'+d.options.iconBase+" "+c.data("icon")+'"></span> ':"",p="OPTGROUP"===this.parentNode.tagName,q=this.disabled||p&&this.parentNode.disabled;if(""!==o&&q&&(o="<span>"+o+"</span>"),d.options.hideDisabled&&q&&!p)return void h--;if(c.data("content")||(l=o+'<span class="text">'+l+n+"</span>"),p&&c.data("divider")!==!0){var r=" "+this.parentNode.className||"";if(0===c.index()){f+=1;var s=this.parentNode.label,t="undefined"!=typeof c.parent().data("subtext")?'<small class="text-muted">'+c.parent().data("subtext")+"</small>":"",u=c.parent().data("icon")?'<span class="'+d.options.iconBase+" "+c.parent().data("icon")+'"></span> ':"";s=u+'<span class="text">'+s+t+"</span>",0!==b&&e.length>0&&(h++,e.push(i("",null,"divider",f+"div"))),h++,e.push(i(s,null,"dropdown-header"+r,f))}if(d.options.hideDisabled&&q)return void h--;e.push(i(j(l,"opt "+g+r,k,m),b,"",f))}else c.data("divider")===!0?e.push(i("",b,"divider")):c.data("hidden")===!0?e.push(i(j(l,g,k,m),b,"hidden is-hidden")):(this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName&&(h++,e.push(i("",null,"divider",f+"div"))),e.push(i(j(l,g,k,m),b)));d.liObj[b]=h}}),this.multiple||0!==this.$element.find("option:selected").length||this.options.title||this.$element.find("option").eq(0).prop("selected",!0).attr("selected","selected"),e.join("")},findLis:function(){return null==this.$lis&&(this.$lis=this.$menu.find("li")),this.$lis},render:function(b){var c,d=this;b!==!1&&this.$element.find("option").each(function(a){var b=d.findLis().eq(d.liObj[a]);d.setDisabled(a,this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled,b),d.setSelected(a,this.selected,b)}),this.tabIndex();var e=this.$element.find("option").map(function(){if(this.selected){if(d.options.hideDisabled&&(this.disabled||"OPTGROUP"===this.parentNode.tagName&&this.parentNode.disabled))return;var b,c=a(this),e=c.data("icon")&&d.options.showIcon?'<i class="'+d.options.iconBase+" "+c.data("icon")+'"></i> ':"";return b=d.options.showSubtext&&c.data("subtext")&&!d.multiple?' <small class="text-muted">'+c.data("subtext")+"</small>":"","undefined"!=typeof c.attr("title")?c.attr("title"):c.data("content")&&d.options.showContent?c.data("content"):e+c.html()+b}}).toArray(),f=this.multiple?e.join(this.options.multipleSeparator):e[0];if(this.multiple&&this.options.selectedTextFormat.indexOf("count")>-1){var g=this.options.selectedTextFormat.split(">");if(g.length>1&&e.length>g[1]||1==g.length&&e.length>=2){c=this.options.hideDisabled?", [disabled]":"";var h=this.$element.find("option").not('[data-divider="true"], [data-hidden="true"]'+c).length,i="function"==typeof this.options.countSelectedText?this.options.countSelectedText(e.length,h):this.options.countSelectedText;f=i.replace("{0}",e.length.toString()).replace("{1}",h.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(f=this.options.title),f||(f="undefined"!=typeof this.options.title?this.options.title:this.options.noneSelectedText),this.$button.attr("title",a.trim(f.replace(/<[^>]*>?/g,""))),this.$button.children(".filter-option").html(f),this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a?a:this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||this.options.size!==!1&&!this.sizeInfo){var c=document.createElement("div"),d=document.createElement("div"),e=document.createElement("ul"),f=document.createElement("li"),g=document.createElement("li"),h=document.createElement("a"),i=document.createElement("span"),j=this.options.header&&this.$menu.find(".popover-title").length>0?this.$menu.find(".popover-title")[0].cloneNode(!0):null,k=this.options.liveSearch?document.createElement("div"):null,l=this.options.actionsBox&&this.multiple&&this.$menu.find(".bs-actionsbox").length>0?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,m=this.options.doneButton&&this.multiple&&this.$menu.find(".bs-donebutton").length>0?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(i.className="text",c.className=this.$menu[0].parentNode.className+" open",d.className="dropdown-menu open",e.className="dropdown-menu inner",f.className="divider",i.appendChild(document.createTextNode("Inner text")),h.appendChild(i),g.appendChild(h),e.appendChild(g),e.appendChild(f),j&&d.appendChild(j),k){var n=document.createElement("span");k.className="bs-searchbox",n.className="form-control",k.appendChild(n),d.appendChild(k)}l&&d.appendChild(l),d.appendChild(e),m&&d.appendChild(m),c.appendChild(d),document.body.appendChild(c);var o=h.offsetHeight,p=j?j.offsetHeight:0,q=k?k.offsetHeight:0,r=l?l.offsetHeight:0,s=m?m.offsetHeight:0,t=a(f).outerHeight(!0),u="function"==typeof getComputedStyle?getComputedStyle(d):!1,v=u?null:a(d),w=parseInt(u?u.paddingTop:v.css("paddingTop"))+parseInt(u?u.paddingBottom:v.css("paddingBottom"))+parseInt(u?u.borderTopWidth:v.css("borderTopWidth"))+parseInt(u?u.borderBottomWidth:v.css("borderBottomWidth")),x=w+parseInt(u?u.marginTop:v.css("marginTop"))+parseInt(u?u.marginBottom:v.css("marginBottom"))+2;document.body.removeChild(c),this.sizeInfo={liHeight:o,headerHeight:p,searchHeight:q,actionsHeight:r,doneButtonHeight:s,dividerHeight:t,menuPadding:w,menuExtras:x}}},setSize:function(){if(this.findLis(),this.liHeight(),this.options.header&&this.$menu.css("padding-top",0),this.options.size!==!1){var b,c,d,e,f=this,g=this.$menu,h=this.$menuInner,i=a(window),j=this.$newElement[0].offsetHeight,k=this.sizeInfo.liHeight,l=this.sizeInfo.headerHeight,m=this.sizeInfo.searchHeight,n=this.sizeInfo.actionsHeight,o=this.sizeInfo.doneButtonHeight,p=this.sizeInfo.dividerHeight,q=this.sizeInfo.menuPadding,r=this.sizeInfo.menuExtras,s=this.options.hideDisabled?".disabled":"",t=function(){d=f.$newElement.offset().top-i.scrollTop(),e=i.height()-d-j};if(t(),"auto"===this.options.size){var u=function(){var i,j=function(b,c){return function(d){return c?d.classList?d.classList.contains(b):a(d).hasClass(b):!(d.classList?d.classList.contains(b):a(d).hasClass(b))}},p=f.$menuInner[0].getElementsByTagName("li"),s=Array.prototype.filter?Array.prototype.filter.call(p,j("hidden",!1)):f.$lis.not(".hidden"),u=Array.prototype.filter?Array.prototype.filter.call(s,j("dropdown-header",!0)):s.filter(".dropdown-header");t(),b=e-r,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&f.$newElement.toggleClass("dropup",d>e&&c>b-r),f.$newElement.hasClass("dropup")&&(b=d-r),i=s.length+u.length>3?3*k+r-2:0,g.css({"max-height":b+"px",overflow:"hidden","min-height":i+l+m+n+o+"px"}),h.css({"max-height":b-l-m-n-o-q+"px","overflow-y":"auto","min-height":Math.max(i-q,0)+"px"})};u(),this.$searchbox.off("input.getSize propertychange.getSize").on("input.getSize propertychange.getSize",u),i.off("resize.getSize scroll.getSize").on("resize.getSize scroll.getSize",u)}else if(this.options.size&&"auto"!=this.options.size&&this.$lis.not(s).length>this.options.size){var v=this.$lis.not(".divider").not(s).children().slice(0,this.options.size).last().parent().index(),w=this.$lis.slice(0,v+1).filter(".divider").length;b=k*this.options.size+w*p+q,f.options.container?(g.data("height")||g.data("height",g.height()),c=g.data("height")):c=g.height(),f.options.dropupAuto&&this.$newElement.toggleClass("dropup",d>e&&c>b-r),g.css({"max-height":b+l+m+n+o+"px",overflow:"hidden","min-height":""}),h.css({"max-height":b-q+"px","overflow-y":"auto","min-height":""})}}},setWidth:function(){if("auto"===this.options.width){this.$menu.css("min-width","0");var a=this.$menu.parent().clone().appendTo("body"),b=this.options.container?this.$newElement.clone().appendTo("body"):a,c=a.children(".dropdown-menu").outerWidth(),d=b.css("width","auto").children("button").outerWidth();a.remove(),b.remove(),this.$newElement.css("width",Math.max(c,d)+"px")}else"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width",""));this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){this.$bsContainer=a('<div class="bs-container" />');var b,c,d=this,e=function(a){d.$bsContainer.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass("dropup",a.hasClass("dropup")),b=a.offset(),c=a.hasClass("dropup")?0:a[0].offsetHeight,d.$bsContainer.css({top:b.top+c,left:b.left,width:a[0].offsetWidth})};this.$button.on("click",function(){var b=a(this);d.isDisabled()||(e(d.$newElement),d.$bsContainer.appendTo(d.options.container).toggleClass("open",!b.hasClass("open")).append(d.$menu))}),a(window).on("resize scroll",function(){e(d.$newElement)}),this.$element.on("hide.bs.select",function(){d.$menu.data("height",d.$menu.height()),d.$bsContainer.detach()})},setSelected:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),c.toggleClass("selected",b)},setDisabled:function(a,b,c){c||(c=this.findLis().eq(this.liObj[a])),b?c.addClass("disabled").children("a").attr("href","#").attr("tabindex",-1):c.removeClass("disabled").children("a").removeAttr("href").attr("tabindex",0)},isDisabled:function(){return this.$element[0].disabled},checkDisabled:function(){var a=this;this.isDisabled()?(this.$newElement.addClass("disabled"),this.$button.addClass("disabled").attr("tabindex",-1)):(this.$button.hasClass("disabled")&&(this.$newElement.removeClass("disabled"),this.$button.removeClass("disabled")),-1!=this.$button.attr("tabindex")||this.$element.data("tabindex")||this.$button.removeAttr("tabindex")),this.$button.click(function(){return!a.isDisabled()})},tabIndex:function(){this.$element.data("tabindex")!==this.$element.attr("tabindex")&&-98!==this.$element.attr("tabindex")&&"-98"!==this.$element.attr("tabindex")&&(this.$element.data("tabindex",this.$element.attr("tabindex")),this.$button.attr("tabindex",this.$element.data("tabindex"))),this.$element.attr("tabindex",-98)},clickListener:function(){var b=this,c=a(document);this.$newElement.on("touchstart.dropdown",".dropdown-menu",function(a){a.stopPropagation()}),c.data("spaceSelect",!1),this.$button.on("keyup",function(a){/(32)/.test(a.keyCode.toString(10))&&c.data("spaceSelect")&&(a.preventDefault(),c.data("spaceSelect",!1))}),this.$button.on("click",function(){b.setSize()}),this.$element.on("shown.bs.select",function(){if(b.options.liveSearch||b.multiple){if(!b.multiple){var a=b.liObj[b.$element[0].selectedIndex];if("number"!=typeof a||b.options.size===!1)return;var c=b.$lis.eq(a)[0].offsetTop-b.$menuInner[0].offsetTop;c=c-b.$menuInner[0].offsetHeight/2+b.sizeInfo.liHeight/2,b.$menuInner[0].scrollTop=c}}else b.$menuInner.find(".selected a").focus()}),this.$menuInner.on("click","li a",function(c){var d=a(this),e=d.parent().data("originalIndex"),f=b.$element.val(),g=b.$element.prop("selectedIndex");if(b.multiple&&c.stopPropagation(),c.preventDefault(),!b.isDisabled()&&!d.parent().hasClass("disabled")){var h=b.$element.find("option"),i=h.eq(e),j=i.prop("selected"),k=i.parent("optgroup"),l=b.options.maxOptions,m=k.data("maxOptions")||!1;if(b.multiple){if(i.prop("selected",!j),b.setSelected(e,!j),d.blur(),l!==!1||m!==!1){var n=l<h.filter(":selected").length,o=m<k.find("option:selected").length;if(l&&n||m&&o)if(l&&1==l)h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);else if(m&&1==m){k.find("option:selected").prop("selected",!1),i.prop("selected",!0);var p=d.parent().data("optgroup");b.$menuInner.find('[data-optgroup="'+p+'"]').removeClass("selected"),b.setSelected(e,!0)}else{var q="function"==typeof b.options.maxOptionsText?b.options.maxOptionsText(l,m):b.options.maxOptionsText,r=q[0].replace("{n}",l),s=q[1].replace("{n}",m),t=a('<div class="notify"></div>');q[2]&&(r=r.replace("{var}",q[2][l>1?0:1]),s=s.replace("{var}",q[2][m>1?0:1])),i.prop("selected",!1),b.$menu.append(t),l&&n&&(t.append(a("<div>"+r+"</div>")),b.$element.trigger("maxReached.bs.select")),m&&o&&(t.append(a("<div>"+s+"</div>")),b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(e,!1)},10),t.delay(750).fadeOut(300,function(){a(this).remove()})}}}else h.prop("selected",!1),i.prop("selected",!0),b.$menuInner.find(".selected").removeClass("selected"),b.setSelected(e,!0);b.multiple?b.options.liveSearch&&b.$searchbox.focus():b.$button.focus(),(f!=b.$element.val()&&b.multiple||g!=b.$element.prop("selectedIndex")&&!b.multiple)&&b.$element.trigger("changed.bs.select",[e,i.prop("selected"),j]).triggerNative("change")}}),this.$menu.on("click","li.disabled a, .popover-title, .popover-title :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menuInner.on("click",".divider, .dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click",".popover-title .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll()}),this.$element.change(function(){b.render(!1)})},liveSearchListener:function(){var d=this,e=a('<li class="no-results"></li>');this.$button.on("click.dropdown.data-api touchstart.dropdown.data-api",function(){d.$menuInner.find(".active").removeClass("active"),d.$searchbox.val()&&(d.$searchbox.val(""),d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove()),d.multiple||d.$menuInner.find(".selected").addClass("active"),setTimeout(function(){d.$searchbox.focus()},10)}),this.$searchbox.on("click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){if(d.$searchbox.val()){var f=d.$lis.not(".is-hidden").removeClass("hidden").children("a");f=d.options.liveSearchNormalize?f.not(":a"+d._searchStyle()+'("'+b(d.$searchbox.val())+'")'):f.not(":"+d._searchStyle()+'("'+d.$searchbox.val()+'")'),f.parent().addClass("hidden"),d.$lis.filter(".dropdown-header").each(function(){var b=a(this),c=b.data("optgroup");0===d.$lis.filter("[data-optgroup="+c+"]").not(b).not(".hidden").length&&(b.addClass("hidden"),d.$lis.filter("[data-optgroup="+c+"div]").addClass("hidden"))});var g=d.$lis.not(".hidden");g.each(function(b){var c=a(this);c.hasClass("divider")&&(c.index()===g.first().index()||c.index()===g.last().index()||g.eq(b+1).hasClass("divider"))&&c.addClass("hidden")}),d.$lis.not(".hidden, .no-results").length?e.parent().length&&e.remove():(e.parent().length&&e.remove(),e.html(d.options.noneResultsText.replace("{0}",'"'+c(d.$searchbox.val())+'"')).show(),d.$menuInner.append(e))}else d.$lis.not(".is-hidden").removeClass("hidden"),e.parent().length&&e.remove();d.$lis.filter(".active").removeClass("active"),d.$searchbox.val()&&d.$lis.not(".hidden, .divider, .dropdown-header").eq(0).addClass("active").children("a").focus(),a(this).focus()})},_searchStyle:function(){var a={begins:"ibegins",startsWith:"ibegins"};return a[this.options.liveSearchStyle]||"icontains"},val:function(a){return"undefined"!=typeof a?(this.$element.val(a),this.render(),this.$element):this.$element.val()},changeAll:function(b){"undefined"==typeof b&&(b=!0),this.findLis();for(var c=this.$element.find("option"),d=this.$lis.not(".divider, .dropdown-header, .disabled, .hidden").toggleClass("selected",b),e=d.length,f=[],g=0;e>g;g++){var h=d[g].getAttribute("data-original-index");f[f.length]=c.eq(h)[0]}a(f).prop("selected",b),this.render(!1),this.$element.trigger("changed.bs.select").triggerNative("change")},selectAll:function(){return this.changeAll(!0)},deselectAll:function(){return this.changeAll(!1)},toggle:function(a){a=a||window.event,a&&a.stopPropagation(),this.$button.trigger("click")},keydown:function(c){var d,e,f,g,h,i,j,k,l,m=a(this),n=m.is("input")?m.parent().parent():m.parent(),o=n.data("this"),p=":not(.disabled, .hidden, .dropdown-header, .divider)",q={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};if(o.options.liveSearch&&(n=m.parent().parent()),o.options.container&&(n=o.$menu),d=a("[role=menu] li",n),l=o.$newElement.hasClass("open"),!l&&(c.keyCode>=48&&c.keyCode<=57||c.keyCode>=96&&c.keyCode<=105||c.keyCode>=65&&c.keyCode<=90)&&(o.options.container?o.$button.trigger("click"):(o.setSize(),o.$menu.parent().addClass("open"),l=!0),o.$searchbox.focus()),o.options.liveSearch&&(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&0===o.$menu.find(".active").length&&(c.preventDefault(),o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus()),d=a("[role=menu] li"+p,n),m.val()||/(38|40)/.test(c.keyCode.toString(10))||0===d.filter(".active").length&&(d=o.$menuInner.find("li"),d=o.options.liveSearchNormalize?d.filter(":a"+o._searchStyle()+"("+b(q[c.keyCode])+")"):d.filter(":"+o._searchStyle()+"("+q[c.keyCode]+")"))),d.length){if(/(38|40)/.test(c.keyCode.toString(10)))e=d.index(d.find("a").filter(":focus").parent()),g=d.filter(p).first().index(),h=d.filter(p).last().index(),f=d.eq(e).nextAll(p).eq(0).index(),i=d.eq(e).prevAll(p).eq(0).index(),j=d.eq(f).prevAll(p).eq(0).index(),o.options.liveSearch&&(d.each(function(b){a(this).hasClass("disabled")||a(this).data("index",b)}),e=d.index(d.filter(".active")),g=d.first().data("index"),h=d.last().data("index"),f=d.eq(e).nextAll().eq(0).data("index"),i=d.eq(e).prevAll().eq(0).data("index"),j=d.eq(f).prevAll().eq(0).data("index")),k=m.data("prevIndex"),38==c.keyCode?(o.options.liveSearch&&e--,e!=j&&e>i&&(e=i),g>e&&(e=g),e==k&&(e=h)):40==c.keyCode&&(o.options.liveSearch&&e++,-1==e&&(e=0),e!=j&&f>e&&(e=f),e>h&&(e=h),e==k&&(e=g)),m.data("prevIndex",e),o.options.liveSearch?(c.preventDefault(),m.hasClass("dropdown-toggle")||(d.removeClass("active").eq(e).addClass("active").children("a").focus(),m.focus())):d.eq(e).children("a").focus();else if(!m.is("input")){var r,s,t=[];d.each(function(){a(this).hasClass("disabled")||a.trim(a(this).children("a").text().toLowerCase()).substring(0,1)==q[c.keyCode]&&t.push(a(this).index())}),r=a(document).data("keycount"),r++,a(document).data("keycount",r),s=a.trim(a(":focus").text().toLowerCase()).substring(0,1),s!=q[c.keyCode]?(r=1,a(document).data("keycount",r)):r>=t.length&&(a(document).data("keycount",0),r>t.length&&(r=1)),d.eq(t[r-1]).children("a").focus()}if((/(13|32)/.test(c.keyCode.toString(10))||/(^9$)/.test(c.keyCode.toString(10))&&o.options.selectOnTab)&&l){if(/(32)/.test(c.keyCode.toString(10))||c.preventDefault(),o.options.liveSearch)/(32)/.test(c.keyCode.toString(10))||(o.$menuInner.find(".active a").click(),m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var f=a.fn.selectpicker;a.fn.selectpicker=d,a.fn.selectpicker.Constructor=e,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=f,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',e.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="menu"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);d.call(b,b.data())})})}(a)});
//# sourceMappingURL=bootstrap-select.js.map
/*!
* jQuery QueryBuilder 2.3.3
* Copyright 2014-2016 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
* Licensed under MIT (http://opensource.org/licenses/MIT)
*/
.query-builder .rule-container,.query-builder .rule-placeholder,.query-builder .rules-group-container{position:relative;margin:4px 0;border-radius:5px;padding:5px;border:1px solid #EEE;background:rgba(255,255,255,.9)}.query-builder .drag-handle,.query-builder .error-container,.query-builder .rule-container .rule-filter-container,.query-builder .rule-container .rule-operator-container,.query-builder .rule-container .rule-value-container{display:inline-block;margin:0 5px 0 0;vertical-align:middle}.query-builder .rules-group-container{padding:10px 10px 6px;border:1px solid #DCC896;background:rgba(250,240,210,.5)}.query-builder .rules-group-header{margin-bottom:10px}.query-builder .rules-group-header .group-conditions .btn.readonly:not(.active),.query-builder .rules-group-header .group-conditions input[name$=_cond]{display:none}.query-builder .rules-group-header .group-conditions .btn.readonly{border-radius:3px}.query-builder .rules-list{list-style:none;padding:0 0 0 15px;margin:0}.query-builder .rule-value-container{border-left:1px solid #DDD;padding-left:5px}.query-builder .rule-value-container label{margin-bottom:0;font-weight:400}.query-builder .rule-value-container label.block{display:block}.query-builder .rule-value-container input[type=number],.query-builder .rule-value-container input[type=text],.query-builder .rule-value-container select{padding:1px}.query-builder .error-container{display:none;cursor:help;color:red}.query-builder .has-error{background-color:#FDD;border-color:#F99}.query-builder .has-error .error-container{display:inline-block!important}.query-builder .rules-list>::after,.query-builder .rules-list>::before{content:'';position:absolute;left:-10px;width:10px;height:calc(50% + 4px);border-color:#CCC;border-style:solid}.query-builder .rules-list>::before{top:-4px;border-width:0 0 2px 2px}.query-builder .rules-list>::after{top:50%;border-width:0 0 0 2px}.query-builder .rules-list>:first-child::before{top:-12px;height:calc(50% + 14px)}.query-builder .rules-list>:last-child::before{border-radius:0 0 0 4px}.query-builder .rules-list>:last-child::after{display:none}.query-builder .error-container+.tooltip .tooltip-inner{color:#F99!important}.query-builder p.filter-description{margin:5px 0 0;background:#D9EDF7;border:1px solid #BCE8F1;color:#31708F;border-radius:5px;padding:2.5px 5px;font-size:.8em}.query-builder .rules-group-header [data-invert]{margin-left:5px}.query-builder .drag-handle{cursor:move;vertical-align:middle;margin-left:5px}.query-builder .dragged{opacity:.5}.query-builder .rule-placeholder{border:1px dashed #BBB;opacity:.7}
/*!
* Bootstrap-select v1.10.0 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2016 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/
select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\9}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group.bs-container{position:absolute}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid rgba(204,204,204,.2);position:absolute;bottom:-4px;left:9px;display:none}.bootstrap-select.show-menu-arrow .dropdown-toggle:after{content:'';border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;bottom:-4px;left:10px;display:none}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:before{bottom:auto;top:-3px;border-top:7px solid rgba(204,204,204,.2);border-bottom:0}.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after{bottom:auto;top:-3px;border-top:6px solid #fff;border-bottom:0}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:before{right:12px;left:auto}.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle:after{right:13px;left:auto}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:after,.bootstrap-select.show-menu-arrow.open>.dropdown-toggle:before{display:block}.bs-actionsbox,.bs-donebutton,.bs-searchbox{padding:4px 8px}.bs-actionsbox{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-actionsbox .btn-group button{width:50%}.bs-donebutton{float:left;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-donebutton .btn-group button{width:100%}.bs-searchbox+.bs-actionsbox{padding:0 8px 4px}.bs-searchbox .form-control{margin-bottom:0;width:100%;float:none}
/*!
* Datepicker for Bootstrap v1.6.1 (https://github.com/eternicode/bootstrap-datepicker)
*
* Copyright 2012 Stefan Petre
* Improvements by Andrew Rowls
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/
.datepicker {
padding: 4px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
direction: ltr;
}
.datepicker-inline {
width: 220px;
}
.datepicker.datepicker-rtl {
direction: rtl;
}
.datepicker.datepicker-rtl table tr td span {
float: right;
}
.datepicker-dropdown {
top: 0;
left: 0;
}
.datepicker-dropdown:before {
content: '';
display: inline-block;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #999999;
border-top: 0;
border-bottom-color: rgba(0, 0, 0, 0.2);
position: absolute;
}
.datepicker-dropdown:after {
content: '';
display: inline-block;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #ffffff;
border-top: 0;
position: absolute;
}
.datepicker-dropdown.datepicker-orient-left:before {
left: 6px;
}
.datepicker-dropdown.datepicker-orient-left:after {
left: 7px;
}
.datepicker-dropdown.datepicker-orient-right:before {
right: 6px;
}
.datepicker-dropdown.datepicker-orient-right:after {
right: 7px;
}
.datepicker-dropdown.datepicker-orient-bottom:before {
top: -7px;
}
.datepicker-dropdown.datepicker-orient-bottom:after {
top: -6px;
}
.datepicker-dropdown.datepicker-orient-top:before {
bottom: -7px;
border-bottom: 0;
border-top: 7px solid #999999;
}
.datepicker-dropdown.datepicker-orient-top:after {
bottom: -6px;
border-bottom: 0;
border-top: 6px solid #ffffff;
}
.datepicker > div {
display: none;
}
.datepicker table {
margin: 0;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.datepicker td,
.datepicker th {
text-align: center;
width: 20px;
height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
border: none;
}
.table-striped .datepicker table tr td,
.table-striped .datepicker table tr th {
background-color: transparent;
}
.datepicker table tr td.day:hover,
.datepicker table tr td.day.focused {
background: #eeeeee;
cursor: pointer;
}
.datepicker table tr td.old,
.datepicker table tr td.new {
color: #999999;
}
.datepicker table tr td.disabled,
.datepicker table tr td.disabled:hover {
background: none;
color: #999999;
cursor: default;
}
.datepicker table tr td.highlighted {
background: #d9edf7;
border-radius: 0;
}
.datepicker table tr td.today,
.datepicker table tr td.today:hover,
.datepicker table tr td.today.disabled,
.datepicker table tr td.today.disabled:hover {
background-color: #fde19a;
background-image: -moz-linear-gradient(to bottom, #fdd49a, #fdf59a);
background-image: -ms-linear-gradient(to bottom, #fdd49a, #fdf59a);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
background-image: -webkit-linear-gradient(to bottom, #fdd49a, #fdf59a);
background-image: -o-linear-gradient(to bottom, #fdd49a, #fdf59a);
background-image: linear-gradient(to bottom, #fdd49a, #fdf59a);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
border-color: #fdf59a #fdf59a #fbed50;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
color: #000;
}
.datepicker table tr td.today:hover,
.datepicker table tr td.today:hover:hover,
.datepicker table tr td.today.disabled:hover,
.datepicker table tr td.today.disabled:hover:hover,
.datepicker table tr td.today:active,
.datepicker table tr td.today:hover:active,
.datepicker table tr td.today.disabled:active,
.datepicker table tr td.today.disabled:hover:active,
.datepicker table tr td.today.active,
.datepicker table tr td.today:hover.active,
.datepicker table tr td.today.disabled.active,
.datepicker table tr td.today.disabled:hover.active,
.datepicker table tr td.today.disabled,
.datepicker table tr td.today:hover.disabled,
.datepicker table tr td.today.disabled.disabled,
.datepicker table tr td.today.disabled:hover.disabled,
.datepicker table tr td.today[disabled],
.datepicker table tr td.today:hover[disabled],
.datepicker table tr td.today.disabled[disabled],
.datepicker table tr td.today.disabled:hover[disabled] {
background-color: #fdf59a;
}
.datepicker table tr td.today:active,
.datepicker table tr td.today:hover:active,
.datepicker table tr td.today.disabled:active,
.datepicker table tr td.today.disabled:hover:active,
.datepicker table tr td.today.active,
.datepicker table tr td.today:hover.active,
.datepicker table tr td.today.disabled.active,
.datepicker table tr td.today.disabled:hover.active {
background-color: #fbf069 \9;
}
.datepicker table tr td.today:hover:hover {
color: #000;
}
.datepicker table tr td.today.active:hover {
color: #fff;
}
.datepicker table tr td.range,
.datepicker table tr td.range:hover,
.datepicker table tr td.range.disabled,
.datepicker table tr td.range.disabled:hover {
background: #eeeeee;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.datepicker table tr td.range.today,
.datepicker table tr td.range.today:hover,
.datepicker table tr td.range.today.disabled,
.datepicker table tr td.range.today.disabled:hover {
background-color: #f3d17a;
background-image: -moz-linear-gradient(to bottom, #f3c17a, #f3e97a);
background-image: -ms-linear-gradient(to bottom, #f3c17a, #f3e97a);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
background-image: -webkit-linear-gradient(to bottom, #f3c17a, #f3e97a);
background-image: -o-linear-gradient(to bottom, #f3c17a, #f3e97a);
background-image: linear-gradient(to bottom, #f3c17a, #f3e97a);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
border-color: #f3e97a #f3e97a #edde34;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
}
.datepicker table tr td.range.today:hover,
.datepicker table tr td.range.today:hover:hover,
.datepicker table tr td.range.today.disabled:hover,
.datepicker table tr td.range.today.disabled:hover:hover,
.datepicker table tr td.range.today:active,
.datepicker table tr td.range.today:hover:active,
.datepicker table tr td.range.today.disabled:active,
.datepicker table tr td.range.today.disabled:hover:active,
.datepicker table tr td.range.today.active,
.datepicker table tr td.range.today:hover.active,
.datepicker table tr td.range.today.disabled.active,
.datepicker table tr td.range.today.disabled:hover.active,
.datepicker table tr td.range.today.disabled,
.datepicker table tr td.range.today:hover.disabled,
.datepicker table tr td.range.today.disabled.disabled,
.datepicker table tr td.range.today.disabled:hover.disabled,
.datepicker table tr td.range.today[disabled],
.datepicker table tr td.range.today:hover[disabled],
.datepicker table tr td.range.today.disabled[disabled],
.datepicker table tr td.range.today.disabled:hover[disabled] {
background-color: #f3e97a;
}
.datepicker table tr td.range.today:active,
.datepicker table tr td.range.today:hover:active,
.datepicker table tr td.range.today.disabled:active,
.datepicker table tr td.range.today.disabled:hover:active,
.datepicker table tr td.range.today.active,
.datepicker table tr td.range.today:hover.active,
.datepicker table tr td.range.today.disabled.active,
.datepicker table tr td.range.today.disabled:hover.active {
background-color: #efe24b \9;
}
.datepicker table tr td.selected,
.datepicker table tr td.selected:hover,
.datepicker table tr td.selected.disabled,
.datepicker table tr td.selected.disabled:hover {
background-color: #9e9e9e;
background-image: -moz-linear-gradient(to bottom, #b3b3b3, #808080);
background-image: -ms-linear-gradient(to bottom, #b3b3b3, #808080);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
background-image: -webkit-linear-gradient(to bottom, #b3b3b3, #808080);
background-image: -o-linear-gradient(to bottom, #b3b3b3, #808080);
background-image: linear-gradient(to bottom, #b3b3b3, #808080);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
border-color: #808080 #808080 #595959;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td.selected:hover,
.datepicker table tr td.selected:hover:hover,
.datepicker table tr td.selected.disabled:hover,
.datepicker table tr td.selected.disabled:hover:hover,
.datepicker table tr td.selected:active,
.datepicker table tr td.selected:hover:active,
.datepicker table tr td.selected.disabled:active,
.datepicker table tr td.selected.disabled:hover:active,
.datepicker table tr td.selected.active,
.datepicker table tr td.selected:hover.active,
.datepicker table tr td.selected.disabled.active,
.datepicker table tr td.selected.disabled:hover.active,
.datepicker table tr td.selected.disabled,
.datepicker table tr td.selected:hover.disabled,
.datepicker table tr td.selected.disabled.disabled,
.datepicker table tr td.selected.disabled:hover.disabled,
.datepicker table tr td.selected[disabled],
.datepicker table tr td.selected:hover[disabled],
.datepicker table tr td.selected.disabled[disabled],
.datepicker table tr td.selected.disabled:hover[disabled] {
background-color: #808080;
}
.datepicker table tr td.selected:active,
.datepicker table tr td.selected:hover:active,
.datepicker table tr td.selected.disabled:active,
.datepicker table tr td.selected.disabled:hover:active,
.datepicker table tr td.selected.active,
.datepicker table tr td.selected:hover.active,
.datepicker table tr td.selected.disabled.active,
.datepicker table tr td.selected.disabled:hover.active {
background-color: #666666 \9;
}
.datepicker table tr td.active,
.datepicker table tr td.active:hover,
.datepicker table tr td.active.disabled,
.datepicker table tr td.active.disabled:hover {
background-color: #006dcc;
background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: linear-gradient(to bottom, #0088cc, #0044cc);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td.active:hover,
.datepicker table tr td.active:hover:hover,
.datepicker table tr td.active.disabled:hover,
.datepicker table tr td.active.disabled:hover:hover,
.datepicker table tr td.active:active,
.datepicker table tr td.active:hover:active,
.datepicker table tr td.active.disabled:active,
.datepicker table tr td.active.disabled:hover:active,
.datepicker table tr td.active.active,
.datepicker table tr td.active:hover.active,
.datepicker table tr td.active.disabled.active,
.datepicker table tr td.active.disabled:hover.active,
.datepicker table tr td.active.disabled,
.datepicker table tr td.active:hover.disabled,
.datepicker table tr td.active.disabled.disabled,
.datepicker table tr td.active.disabled:hover.disabled,
.datepicker table tr td.active[disabled],
.datepicker table tr td.active:hover[disabled],
.datepicker table tr td.active.disabled[disabled],
.datepicker table tr td.active.disabled:hover[disabled] {
background-color: #0044cc;
}
.datepicker table tr td.active:active,
.datepicker table tr td.active:hover:active,
.datepicker table tr td.active.disabled:active,
.datepicker table tr td.active.disabled:hover:active,
.datepicker table tr td.active.active,
.datepicker table tr td.active:hover.active,
.datepicker table tr td.active.disabled.active,
.datepicker table tr td.active.disabled:hover.active {
background-color: #003399 \9;
}
.datepicker table tr td span {
display: block;
width: 23%;
height: 54px;
line-height: 54px;
float: left;
margin: 1%;
cursor: pointer;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.datepicker table tr td span:hover,
.datepicker table tr td span.focused {
background: #eeeeee;
}
.datepicker table tr td span.disabled,
.datepicker table tr td span.disabled:hover {
background: none;
color: #999999;
cursor: default;
}
.datepicker table tr td span.active,
.datepicker table tr td span.active:hover,
.datepicker table tr td span.active.disabled,
.datepicker table tr td span.active.disabled:hover {
background-color: #006dcc;
background-image: -moz-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -ms-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
background-image: -webkit-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: -o-linear-gradient(to bottom, #0088cc, #0044cc);
background-image: linear-gradient(to bottom, #0088cc, #0044cc);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
border-color: #0044cc #0044cc #002a80;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.datepicker table tr td span.active:hover,
.datepicker table tr td span.active:hover:hover,
.datepicker table tr td span.active.disabled:hover,
.datepicker table tr td span.active.disabled:hover:hover,
.datepicker table tr td span.active:active,
.datepicker table tr td span.active:hover:active,
.datepicker table tr td span.active.disabled:active,
.datepicker table tr td span.active.disabled:hover:active,
.datepicker table tr td span.active.active,
.datepicker table tr td span.active:hover.active,
.datepicker table tr td span.active.disabled.active,
.datepicker table tr td span.active.disabled:hover.active,
.datepicker table tr td span.active.disabled,
.datepicker table tr td span.active:hover.disabled,
.datepicker table tr td span.active.disabled.disabled,
.datepicker table tr td span.active.disabled:hover.disabled,
.datepicker table tr td span.active[disabled],
.datepicker table tr td span.active:hover[disabled],
.datepicker table tr td span.active.disabled[disabled],
.datepicker table tr td span.active.disabled:hover[disabled] {
background-color: #0044cc;
}
.datepicker table tr td span.active:active,
.datepicker table tr td span.active:hover:active,
.datepicker table tr td span.active.disabled:active,
.datepicker table tr td span.active.disabled:hover:active,
.datepicker table tr td span.active.active,
.datepicker table tr td span.active:hover.active,
.datepicker table tr td span.active.disabled.active,
.datepicker table tr td span.active.disabled:hover.active {
background-color: #003399 \9;
}
.datepicker table tr td span.old,
.datepicker table tr td span.new {
color: #999999;
}
.datepicker .datepicker-switch {
width: 145px;
}
.datepicker .datepicker-switch,
.datepicker .prev,
.datepicker .next,
.datepicker tfoot tr th {
cursor: pointer;
}
.datepicker .datepicker-switch:hover,
.datepicker .prev:hover,
.datepicker .next:hover,
.datepicker tfoot tr th:hover {
background: #eeeeee;
}
.datepicker .cw {
font-size: 10px;
width: 12px;
padding: 0 2px 0 5px;
vertical-align: middle;
}
.input-append.date .add-on,
.input-prepend.date .add-on {
cursor: pointer;
}
.input-append.date .add-on i,
.input-prepend.date .add-on i {
margin-top: 3px;
}
.input-daterange input {
text-align: center;
}
.input-daterange input:first-child {
-webkit-border-radius: 3px 0 0 3px;
-moz-border-radius: 3px 0 0 3px;
border-radius: 3px 0 0 3px;
}
.input-daterange input:last-child {
-webkit-border-radius: 0 3px 3px 0;
-moz-border-radius: 0 3px 3px 0;
border-radius: 0 3px 3px 0;
}
.input-daterange .add-on {
display: inline-block;
width: auto;
min-width: 16px;
height: 18px;
padding: 4px 5px;
font-weight: normal;
line-height: 18px;
text-align: center;
text-shadow: 0 1px 0 #ffffff;
vertical-align: middle;
background-color: #eeeeee;
border: 1px solid #ccc;
margin-left: -5px;
margin-right: -5px;
}
/*# sourceMappingURL=bootstrap-datepicker.css.map */