Commit c018db65 by Billy Larru

configurando datatatable y datepicker

parent 3edc4df7
btn-green{
background-color: #26A69A;
}
\ No newline at end of file
}
/*!
* Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2017 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/
select.bs-select-hidden,
select.selectpicker {
display: none !important;
height: 32px;
}
.bootstrap-select {
width: 220px \0;
/*IE9 and below*/
}
.bootstrap-select > .dropdown-toggle {
width: 100%;
padding-right: 25px;
z-index: 1;
height: 32px;
}
.bootstrap-select > .dropdown-toggle.bs-placeholder,
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
/*color: #999;*/
}
.bootstrap-select > select {
position: absolute !important;
bottom: 0;
left: 50%;
display: block !important;
width: 0.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;
}
.has-error .bootstrap-select .dropdown-toggle,
.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 #333333 !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.form-control.input-group-btn:not(:first-child):not(:last-child) > .btn {
border-radius: 0;
}
.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-inline .bootstrap-select.btn-group,
.form-horizontal .bootstrap-select.btn-group,
.form-group .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-group-lg .bootstrap-select.btn-group.form-control .dropdown-toggle,
.form-group-sm .bootstrap-select.btn-group.form-control .dropdown-toggle {
height: 100%;
font-size: inherit;
line-height: inherit;
border-radius: inherit;
}
.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: none !important;
}
.bootstrap-select.btn-group.bs-container {
position: absolute;
height: 0 !important;
padding: 0 !important;
}
.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: 0.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, 0.05);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
pointer-events: none;
opacity: 0.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, 0.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 white;
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, 0.2);
border-bottom: 0;
}
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle:after {
bottom: auto;
top: -3px;
border-top: 6px solid white;
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:before,
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle:after {
display: block;
}
.bs-searchbox,
.bs-actionsbox,
.bs-donebutton {
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;
}
/*# sourceMappingURL=bootstrap-select.css.map */
\ No newline at end of file
......@@ -4,7 +4,8 @@ const PATH_IP = 'http://172.16.2.102:7070/Asistencia/';
//PRODUCCION
const PATH_DOMAIN = '';
const CODIGO_PROYECTO_ASISTENCIA = '7';
const PATH_SERVICIO_REST = 'http://172.16.2.53:8080/security-rest/api/'//'http://app8.sacooliveros.edu.pe:8080/security-rest/api/';
//const PATH_SERVICIO_REST = 'http://172.16.2.53:8080/security-rest/api/'//'http://app8.sacooliveros.edu.pe:8080/security-rest/api/';
const PATH_SERVICIO_REST = 'http://app9.sacooliveros.edu.pe:8080/security-rest/api/';
/*Ajax genral*/
const ajaxRequestSendBody = obj => {
......@@ -149,4 +150,81 @@ let logOut = () => {
document.querySelector('#logOut').addEventListener('click', (e) => {
window.location.href = '../vistas/logout';
});
};
\ No newline at end of file
};
function defaultConfigDataTable() {
$.extend($.fn.dataTable.defaults, {
autoWidth: false,
searching: false,
lengthChange: false,
responsive: true,
bSort: false,
dom: '<"datatable-header"fl><"datatable-scroll"t><"datatable-footer"ip>',
language: {
"paginate": {
'first': 'First',
'last': 'Last',
'next': '&rarr;',
'previous': '&larr;'
},
"sProcessing": "Procesando...",
"sLengthMenu": "Mostrar _MENU_ registros",
"sZeroRecords": "No se encontraron resultados",
"sEmptyTable": "Ningún dato disponible en esta tabla",
"sInfo": "Mostrando registros del _START_ al _END_ de un total de _TOTAL_ registros",
"sInfoEmpty": "Mostrando registros del 0 al 0 de un total de 0 registros",
"sInfoFiltered": "(filtrado de un total de _MAX_ registros)",
"sInfoPostFix": "",
"sSearch": "Buscar:",
"sUrl": "",
"sInfoThousands": ",",
"sLoadingRecords": "Cargando...",
"oPaginate": {
"sFirst": "Primero",
"sLast": "Último",
"sNext": "Siguiente",
"sPrevious": "Anterior"
},
"oAria": {
"sSortAscending": ": Activar para ordenar la columna de manera ascendente",
"sSortDescending": ": Activar para ordenar la columna de manera descendente"
}
},
drawCallback: function () {
$(this).find('tbody tr').slice(-3).find('.dropdown, .btn-group').addClass('dropup');
},
preDrawCallback: function () {
$(this).find('tbody tr').slice(-3).find('.dropdown, .btn-group').removeClass('dropup');
},
rowCallback: function (row, data, index) {
if ($(row).hasClass('odd')) {
$(row).css('background-color', '#e8f4f4');
}
}
});
}
function defaultConfigDatePicker() {
$.datepicker.regional['es'] = {
closeText: 'Cerrar',
prevText: '<Ant',
nextText: 'Sig>',
currentText: 'Hoy',
monthNames: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
monthNamesShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'],
dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
dayNamesShort: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'],
dayNamesMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sá'],
weekHeader: 'Sm',
dateFormat: 'dd/mm/yy',
firstDay: 1,
isRTL: false,
showMonthAfterYear: false,
yearSuffix: ''
};
$.datepicker.setDefaults($.datepicker.regional['es']);
}
\ No newline at end of file
/*!
* Bootstrap-select v1.12.4 (http://silviomoreto.github.io/bootstrap-select)
*
* Copyright 2013-2017 bootstrap-select
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define(["jquery"], function (a0) {
return (factory(a0));
});
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("jquery"));
} else {
factory(root["jQuery"]);
}
}(this, function (jQuery) {
(function ($) {
'use strict';
//<editor-fold desc="Shims">
if (!String.prototype.includes) {
(function () {
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
var toString = {}.toString;
var defineProperty = (function () {
// IE 8 only supports `Object.defineProperty` on DOM elements
try {
var object = {};
var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty;
} catch (error) {
}
return result;
}());
var indexOf = ''.indexOf;
var includes = function (search) {
if (this == null) {
throw new TypeError();
}
var string = String(this);
if (search && toString.call(search) == '[object RegExp]') {
throw new TypeError();
}
var stringLength = string.length;
var searchString = String(search);
var searchLength = searchString.length;
var position = arguments.length > 1 ? arguments[1] : undefined;
// `ToInteger`
var pos = position ? Number(position) : 0;
if (pos != pos) { // better `isNaN`
pos = 0;
}
var start = Math.min(Math.max(pos, 0), stringLength);
// Avoid the `indexOf` call if no match is possible
if (searchLength + start > stringLength) {
return false;
}
return indexOf.call(string, searchString, pos) != -1;
};
if (defineProperty) {
defineProperty(String.prototype, 'includes', {
'value': includes,
'configurable': true,
'writable': true
});
} else {
String.prototype.includes = includes;
}
}());
}
if (!String.prototype.startsWith) {
(function () {
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
var defineProperty = (function () {
// IE 8 only supports `Object.defineProperty` on DOM elements
try {
var object = {};
var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty;
} catch (error) {
}
return result;
}());
var toString = {}.toString;
var startsWith = function (search) {
if (this == null) {
throw new TypeError();
}
var string = String(this);
if (search && toString.call(search) == '[object RegExp]') {
throw new TypeError();
}
var stringLength = string.length;
var searchString = String(search);
var searchLength = searchString.length;
var position = arguments.length > 1 ? arguments[1] : undefined;
// `ToInteger`
var pos = position ? Number(position) : 0;
if (pos != pos) { // better `isNaN`
pos = 0;
}
var start = Math.min(Math.max(pos, 0), stringLength);
// Avoid the `indexOf` call if no match is possible
if (searchLength + start > stringLength) {
return false;
}
var index = -1;
while (++index < searchLength) {
if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
return false;
}
}
return true;
};
if (defineProperty) {
defineProperty(String.prototype, 'startsWith', {
'value': startsWith,
'configurable': true,
'writable': true
});
} else {
String.prototype.startsWith = startsWith;
}
}());
}
if (!Object.keys) {
Object.keys = function (
o, // object
k, // key
r // result array
){
// initialize object and result
r=[];
// iterate over object keys
for (k in o)
// fill result array with non-prototypical keys
r.hasOwnProperty.call(o, k) && r.push(k);
// return result
return r;
};
}
// set data-selected on select element if the value has been programmatically selected
// prior to initialization of bootstrap-select
// * consider removing or replacing an alternative method *
var valHooks = {
useDefault: false,
_set: $.valHooks.select.set
};
$.valHooks.select.set = function(elem, value) {
if (value && !valHooks.useDefault) $(elem).data('selected', true);
return valHooks._set.apply(this, arguments);
};
var changed_arguments = null;
var EventIsSupported = (function() {
try {
new Event('change');
return true;
} catch (e) {
return false;
}
})();
$.fn.triggerNative = function (eventName) {
var el = this[0],
event;
if (el.dispatchEvent) { // for modern browsers & IE9+
if (EventIsSupported) {
// For modern browsers
event = new Event(eventName, {
bubbles: true
});
} else {
// For IE since it doesn't support Event constructor
event = document.createEvent('Event');
event.initEvent(eventName, true, false);
}
el.dispatchEvent(event);
} else if (el.fireEvent) { // for IE8
event = document.createEventObject();
event.eventType = eventName;
el.fireEvent('on' + eventName, event);
} else {
// fall back to jQuery.trigger
this.trigger(eventName);
}
};
//</editor-fold>
// Case insensitive contains search
$.expr.pseudos.icontains = function (obj, index, meta) {
var $obj = $(obj).find('a');
var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
return haystack.includes(meta[3].toUpperCase());
};
// Case insensitive begins search
$.expr.pseudos.ibegins = function (obj, index, meta) {
var $obj = $(obj).find('a');
var haystack = ($obj.data('tokens') || $obj.text()).toString().toUpperCase();
return haystack.startsWith(meta[3].toUpperCase());
};
// Case and accent insensitive contains search
$.expr.pseudos.aicontains = function (obj, index, meta) {
var $obj = $(obj).find('a');
var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
return haystack.includes(meta[3].toUpperCase());
};
// Case and accent insensitive begins search
$.expr.pseudos.aibegins = function (obj, index, meta) {
var $obj = $(obj).find('a');
var haystack = ($obj.data('tokens') || $obj.data('normalizedText') || $obj.text()).toString().toUpperCase();
return haystack.startsWith(meta[3].toUpperCase());
};
/**
* Remove all diatrics from the given text.
* @access private
* @param {String} text
* @returns {String}
*/
function normalizeToBase(text) {
var rExps = [
{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"}
];
$.each(rExps, function () {
text = text ? text.replace(this.re, this.ch) : '';
});
return text;
}
// List of HTML entities for escaping.
var escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;'
};
var unescapeMap = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#x27;': "'",
'&#x60;': '`'
};
// Functions for escaping and unescaping strings to/from HTML interpolation.
var createEscaper = function(map) {
var escaper = function(match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped.
var source = '(?:' + Object.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
var htmlEscape = createEscaper(escapeMap);
var htmlUnescape = createEscaper(unescapeMap);
var Selectpicker = function (element, options) {
// bootstrap-select has been initialized - revert valHooks.select.set back to its original function
if (!valHooks.useDefault) {
$.valHooks.select.set = valHooks._set;
valHooks.useDefault = true;
}
this.$element = $(element);
this.$newElement = null;
this.$button = null;
this.$menu = null;
this.$lis = null;
this.options = options;
// If we have no title yet, try to pull it from the html title attribute (jQuery doesnt' pick it up as it's not a
// data-attribute)
if (this.options.title === null) {
this.options.title = this.$element.attr('title');
}
// Format window padding
var winPad = this.options.windowPadding;
if (typeof winPad === 'number') {
this.options.windowPadding = [winPad, winPad, winPad, winPad];
}
//Expose public methods
this.val = Selectpicker.prototype.val;
this.render = Selectpicker.prototype.render;
this.refresh = Selectpicker.prototype.refresh;
this.setStyle = Selectpicker.prototype.setStyle;
this.selectAll = Selectpicker.prototype.selectAll;
this.deselectAll = Selectpicker.prototype.deselectAll;
this.destroy = Selectpicker.prototype.destroy;
this.remove = Selectpicker.prototype.remove;
this.show = Selectpicker.prototype.show;
this.hide = Selectpicker.prototype.hide;
this.init();
};
Selectpicker.VERSION = '1.12.4';
// part of this is duplicated in i18n/defaults-en_US.js. Make sure to update both.
Selectpicker.DEFAULTS = {
noneSelectedText: '[SELECCIONE]',
noneResultsText: 'Sin resultados {0}',
countSelectedText: function (numSelected, numTotal) {
return (numSelected == 1) ? "{0} item selected" : "{0} items selected";
},
maxOptionsText: function (numAll, numGroup) {
return [
(numAll == 1) ? 'Limit reached ({n} item max)' : 'Limit reached ({n} items max)',
(numGroup == 1) ? 'Group limit reached ({n} item max)' : 'Group limit reached ({n} items max)'
];
},
selectAllText: 'Todos',
deselectAllText: 'Deseleccionar',
doneButton: false,
doneButtonText: 'Close',
multipleSeparator: ', ',
styleBase: 'btn',
style: 'btn-default',
size: 'auto',
title: null,
selectedTextFormat: 'values',
width: false,
container: false,
hideDisabled: false,
showSubtext: false,
showIcon: true,
showContent: true,
dropupAuto: false,
header: false,
liveSearch: true,
liveSearchPlaceholder: null,
liveSearchNormalize: false,
liveSearchStyle: 'contains',
actionsBox: true,
iconBase: 'glyphicon',
tickIcon: 'glyphicon-ok',
showTick: false,
template: {
caret: '<span class="caret"></span>'
},
maxOptions: false,
mobile: false,
selectOnTab: false,
dropdownAlignRight: false,
windowPadding: 0
};
Selectpicker.prototype = {
constructor: Selectpicker,
init: function () {
var that = this,
id = this.$element.attr('id');
this.$element.addClass('bs-select-hidden');
// store originalIndex (key) and newIndex (value) in this.liObj for fast accessibility
// allows us to do this.$lis.eq(that.liObj[index]) instead of this.$lis.filter('[data-original-index="' + index + '"]')
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');
if (this.options.dropdownAlignRight === true) this.$menu.addClass('dropdown-menu-right');
if (typeof id !== 'undefined') {
this.$button.attr('data-id', id);
$('label[for="' + id + '"]').click(function (e) {
e.preventDefault();
that.$button.focus();
});
}
this.checkDisabled();
this.clickListener();
if (this.options.liveSearch) this.liveSearchListener();
this.render();
this.setStyle();
this.setWidth();
if (this.options.container) this.selectPosition();
this.$menu.data('this', this);
this.$newElement.data('this', this);
if (this.options.mobile) this.mobile();
this.$newElement.on({
'hide.bs.dropdown': function (e) {
that.$menuInner.attr('aria-expanded', false);
that.$element.trigger('hide.bs.select', e);
},
'hidden.bs.dropdown': function (e) {
that.$element.trigger('hidden.bs.select', e);
},
'show.bs.dropdown': function (e) {
that.$menuInner.attr('aria-expanded', true);
that.$element.trigger('show.bs.select', e);
},
'shown.bs.dropdown': function (e) {
that.$element.trigger('shown.bs.select', e);
}
});
if (that.$element[0].hasAttribute('required')) {
this.$element.on('invalid', function () {
that.$button.addClass('bs-invalid');
that.$element.on({
'focus.bs.select': function () {
that.$button.focus();
that.$element.off('focus.bs.select');
},
'shown.bs.select': function () {
that.$element
.val(that.$element.val()) // set the value to hide the validation message in Chrome when menu is opened
.off('shown.bs.select');
},
'rendered.bs.select': function () {
// if select is no longer invalid, remove the bs-invalid class
if (this.validity.valid) that.$button.removeClass('bs-invalid');
that.$element.off('rendered.bs.select');
}
});
that.$button.on('blur.bs.select', function() {
that.$element.focus().blur();
that.$button.off('blur.bs.select');
});
});
}
setTimeout(function () {
that.$element.trigger('loaded.bs.select');
});
},
createDropdown: function () {
// Options
// If we are multiple or showTick option is set, then add the show-tick class
var showTick = (this.multiple || this.options.showTick) ? ' show-tick' : '',
inputGroup = this.$element.parent().hasClass('input-group') ? ' input-group-btn' : '',
autofocus = this.autofocus ? ' autofocus' : '';
// Elements
var header = this.options.header ? '<div class="popover-title"><button type="button" class="close" aria-hidden="true">&times;</button>' + this.options.header + '</div>' : '';
var searchbox = this.options.liveSearch ?
'<div class="bs-searchbox">' +
'<input type="text" class="form-control" autocomplete="off"' +
(null === this.options.liveSearchPlaceholder ? '' : ' placeholder="' + htmlEscape(this.options.liveSearchPlaceholder) + '"') + ' role="textbox" aria-label="Search">' +
'</div>'
: '';
var actionsbox = 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>'
: '';
var donebutton = 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>'
: '';
var drop =
'<div class="btn-group bootstrap-select' + showTick + inputGroup + '">' +
'<button type="button" class="' + this.options.styleBase + ' dropdown-toggle" data-toggle="dropdown"' + autofocus + ' role="button">' +
'<span class="filter-option pull-left"></span>&nbsp;' +
'<span class="bs-caret">' +
this.options.template.caret +
'</span>' +
'</button>' +
'<div class="dropdown-menu open" role="combobox">' +
header +
searchbox +
actionsbox +
'<ul class="dropdown-menu inner" role="listbox" aria-expanded="false">' +
'</ul>' +
donebutton +
'</div>' +
'</div>';
return $(drop);
},
createView: function () {
var $drop = this.createDropdown(),
li = this.createLi();
$drop.find('ul')[0].innerHTML = li;
return $drop;
},
reloadLi: function () {
// rebuild
var li = this.createLi();
this.$menuInner[0].innerHTML = li;
},
createLi: function () {
var that = this,
_li = [],
optID = 0,
titleOption = document.createElement('option'),
liIndex = -1; // increment liIndex whenever a new <li> element is created to ensure liObj is correct
// Helper functions
/**
* @param content
* @param [index]
* @param [classes]
* @param [optgroup]
* @returns {string}
*/
var generateLI = function (content, index, classes, optgroup) {
return '<li' +
((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
'>' + content + '</li>';
};
/**
* @param text
* @param [classes]
* @param [inline]
* @param [tokens]
* @returns {string}
*/
var generateA = function (text, classes, inline, tokens) {
return '<a tabindex="0"' +
(typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
(inline ? ' style="' + inline + '"' : '') +
(that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
(typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
' role="option">' + text +
'<span class="' + that.options.iconBase + ' ' + that.options.tickIcon + ' check-mark"></span>' +
'</a>';
};
if (this.options.title && !this.multiple) {
// this option doesn't create a new <li> element, but does add a new option, so liIndex is decreased
// since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
liIndex--;
if (!this.$element.find('.bs-title-option').length) {
// Use native JS to prepend option (faster)
var element = this.$element[0];
titleOption.className = 'bs-title-option';
titleOption.innerHTML = this.options.title;
titleOption.value = '';
element.insertBefore(titleOption, element.firstChild);
// Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
// the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
// if so, the select will have the data-selected attribute
var $opt = $(element.options[element.selectedIndex]);
if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
titleOption.selected = true;
}
}
}
var $selectOptions = this.$element.find('option');
$selectOptions.each(function (index) {
var $this = $(this);
liIndex++;
if ($this.hasClass('bs-title-option')) return;
// Get the class and text for the option
var optionClass = this.className || '',
inline = htmlEscape(this.style.cssText),
text = $this.data('content') ? $this.data('content') : $this.html(),
tokens = $this.data('tokens') ? $this.data('tokens') : null,
subtext = typeof $this.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $this.data('subtext') + '</small>' : '',
icon = typeof $this.data('icon') !== 'undefined' ? '<span class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></span> ' : '',
$parent = $this.parent(),
isOptgroup = $parent[0].tagName === 'OPTGROUP',
isOptgroupDisabled = isOptgroup && $parent[0].disabled,
isDisabled = this.disabled || isOptgroupDisabled,
prevHiddenIndex;
if (icon !== '' && isDisabled) {
icon = '<span>' + icon + '</span>';
}
if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
// set prevHiddenIndex - the index of the first hidden option in a group of hidden options
// used to determine whether or not a divider should be placed after an optgroup if there are
// hidden options between the optgroup and the first visible option
prevHiddenIndex = $this.data('prevHiddenIndex');
$this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
liIndex--;
return;
}
if (!$this.data('content')) {
// Prepend any icon and append any subtext to the main text.
text = icon + '<span class="text">' + text + subtext + '</span>';
}
if (isOptgroup && $this.data('divider') !== true) {
if (that.options.hideDisabled && isDisabled) {
if ($parent.data('allOptionsDisabled') === undefined) {
var $options = $parent.children();
$parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
}
if ($parent.data('allOptionsDisabled')) {
liIndex--;
return;
}
}
var optGroupClass = ' ' + $parent[0].className || '';
if ($this.index() === 0) { // Is it the first option of the optgroup?
optID += 1;
// Get the opt group label
var label = $parent[0].label,
labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '<small class="text-muted">' + $parent.data('subtext') + '</small>' : '',
labelIcon = $parent.data('icon') ? '<span class="' + that.options.iconBase + ' ' + $parent.data('icon') + '"></span> ' : '';
label = labelIcon + '<span class="text">' + htmlEscape(label) + labelSubtext + '</span>';
if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
liIndex++;
_li.push(generateLI('', null, 'divider', optID + 'div'));
}
liIndex++;
_li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
}
if (that.options.hideDisabled && isDisabled) {
liIndex--;
return;
}
_li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
} else if ($this.data('divider') === true) {
_li.push(generateLI('', index, 'divider'));
} else if ($this.data('hidden') === true) {
// set prevHiddenIndex - the index of the first hidden option in a group of hidden options
// used to determine whether or not a divider should be placed after an optgroup if there are
// hidden options between the optgroup and the first visible option
prevHiddenIndex = $this.data('prevHiddenIndex');
$this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
_li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
} else {
var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
// if previous element is not an optgroup and hideDisabled is true
if (!showDivider && that.options.hideDisabled) {
prevHiddenIndex = $this.data('prevHiddenIndex');
if (prevHiddenIndex !== undefined) {
// select the element **before** the first hidden element in the group
var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
showDivider = true;
}
}
}
if (showDivider) {
liIndex++;
_li.push(generateLI('', null, 'divider', optID + 'div'));
}
_li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
}
that.liObj[index] = liIndex;
});
//If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
if (!this.multiple && this.$element.find('option:selected').length === 0 && !this.options.title) {
this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
}
return _li.join('');
},
findLis: function () {
if (this.$lis == null) this.$lis = this.$menu.find('li');
return this.$lis;
},
/**
* @param [updateLi] defaults to true
*/
render: function (updateLi) {
var that = this,
notDisabled,
$selectOptions = this.$element.find('option');
//Update the LI to match the SELECT
if (updateLi !== false) {
$selectOptions.each(function (index) {
var $lis = that.findLis().eq(that.liObj[index]);
that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
that.setSelected(index, this.selected, $lis);
});
}
this.togglePlaceholder();
this.tabIndex();
var selectedItems = $selectOptions.map(function () {
if (this.selected) {
if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
var $this = $(this),
icon = $this.data('icon') && that.options.showIcon ? '<i class="' + that.options.iconBase + ' ' + $this.data('icon') + '"></i> ' : '',
subtext;
if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
subtext = ' <small class="text-muted">' + $this.data('subtext') + '</small>';
} else {
subtext = '';
}
if (typeof $this.attr('title') !== 'undefined') {
return $this.attr('title');
} else if ($this.data('content') && that.options.showContent) {
return $this.data('content').toString();
} else {
return icon + $this.html() + subtext;
}
}
}).toArray();
//Fixes issue in IE10 occurring when no default option is selected and at least one option is disabled
//Convert all the values into a comma delimited string
var title = !this.multiple ? selectedItems[0] : selectedItems.join(this.options.multipleSeparator);
//If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
if (this.multiple && this.options.selectedTextFormat.indexOf('count') > -1) {
var max = this.options.selectedTextFormat.split('>');
if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
}
}
if (this.options.title == undefined) {
this.options.title = this.$element.attr('title');
}
if (this.options.selectedTextFormat == 'static') {
title = this.options.title;
}
//If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
if (!title) {
title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
}
//strip all HTML tags and trim the result, then unescape any escaped tags
this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
this.$button.children('.filter-option').html(title);
this.$element.trigger('rendered.bs.select');
},
/**
* @param [style]
* @param [status]
*/
setStyle: function (style, status) {
if (this.$element.attr('class')) {
this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
}
var buttonClass = style ? style : this.options.style;
if (status == 'add') {
this.$button.addClass(buttonClass);
} else if (status == 'remove') {
this.$button.removeClass(buttonClass);
} else {
this.$button.removeClass(this.options.style);
this.$button.addClass(buttonClass);
}
},
liHeight: function (refresh) {
if (!refresh && (this.options.size === false || this.sizeInfo)) return;
var newElement = document.createElement('div'),
menu = document.createElement('div'),
menuInner = document.createElement('ul'),
divider = document.createElement('li'),
li = document.createElement('li'),
a = document.createElement('a'),
text = document.createElement('span'),
header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
search = this.options.liveSearch ? document.createElement('div') : null,
actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
text.className = 'text';
newElement.className = this.$menu[0].parentNode.className + ' open';
menu.className = 'dropdown-menu open';
menuInner.className = 'dropdown-menu inner';
divider.className = 'divider';
text.appendChild(document.createTextNode('Inner text'));
a.appendChild(text);
li.appendChild(a);
menuInner.appendChild(li);
menuInner.appendChild(divider);
if (header) menu.appendChild(header);
if (search) {
var input = document.createElement('input');
search.className = 'bs-searchbox';
input.className = 'form-control';
search.appendChild(input);
menu.appendChild(search);
}
if (actions) menu.appendChild(actions);
menu.appendChild(menuInner);
if (doneButton) menu.appendChild(doneButton);
newElement.appendChild(menu);
document.body.appendChild(newElement);
var liHeight = a.offsetHeight,
headerHeight = header ? header.offsetHeight : 0,
searchHeight = search ? search.offsetHeight : 0,
actionsHeight = actions ? actions.offsetHeight : 0,
doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
dividerHeight = $(divider).outerHeight(true),
// fall back to jQuery if getComputedStyle is not supported
menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
$menu = menuStyle ? null : $(menu),
menuPadding = {
vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
},
menuExtras = {
vert: menuPadding.vert +
parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
horiz: menuPadding.horiz +
parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
}
document.body.removeChild(newElement);
this.sizeInfo = {
liHeight: liHeight,
headerHeight: headerHeight,
searchHeight: searchHeight,
actionsHeight: actionsHeight,
doneButtonHeight: doneButtonHeight,
dividerHeight: dividerHeight,
menuPadding: menuPadding,
menuExtras: menuExtras
};
},
setSize: function () {
this.findLis();
this.liHeight();
if (this.options.header) this.$menu.css('padding-top', 0);
if (this.options.size === false) return;
var that = this,
$menu = this.$menu,
$menuInner = this.$menuInner,
$window = $(window),
selectHeight = this.$newElement[0].offsetHeight,
selectWidth = this.$newElement[0].offsetWidth,
liHeight = this.sizeInfo['liHeight'],
headerHeight = this.sizeInfo['headerHeight'],
searchHeight = this.sizeInfo['searchHeight'],
actionsHeight = this.sizeInfo['actionsHeight'],
doneButtonHeight = this.sizeInfo['doneButtonHeight'],
divHeight = this.sizeInfo['dividerHeight'],
menuPadding = this.sizeInfo['menuPadding'],
menuExtras = this.sizeInfo['menuExtras'],
notDisabled = this.options.hideDisabled ? '.disabled' : '',
menuHeight,
menuWidth,
getHeight,
getWidth,
selectOffsetTop,
selectOffsetBot,
selectOffsetLeft,
selectOffsetRight,
getPos = function() {
var pos = that.$newElement.offset(),
$container = $(that.options.container),
containerPos;
if (that.options.container && !$container.is('body')) {
containerPos = $container.offset();
containerPos.top += parseInt($container.css('borderTopWidth'));
containerPos.left += parseInt($container.css('borderLeftWidth'));
} else {
containerPos = { top: 0, left: 0 };
}
var winPad = that.options.windowPadding;
selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
selectOffsetTop -= winPad[0];
selectOffsetLeft -= winPad[3];
};
getPos();
if (this.options.size === 'auto') {
var getSize = function () {
var minHeight,
hasClass = function (className, include) {
return function (element) {
if (include) {
return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
} else {
return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
}
};
},
lis = that.$menuInner[0].getElementsByTagName('li'),
lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
getPos();
menuHeight = selectOffsetBot - menuExtras.vert;
menuWidth = selectOffsetRight - menuExtras.horiz;
if (that.options.container) {
if (!$menu.data('height')) $menu.data('height', $menu.height());
getHeight = $menu.data('height');
if (!$menu.data('width')) $menu.data('width', $menu.width());
getWidth = $menu.data('width');
} else {
getHeight = $menu.height();
getWidth = $menu.width();
}
if (that.options.dropupAuto) {
that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
}
if (that.$newElement.hasClass('dropup')) {
menuHeight = selectOffsetTop - menuExtras.vert;
}
if (that.options.dropdownAlignRight === 'auto') {
$menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
}
if ((lisVisible.length + optGroup.length) > 3) {
minHeight = liHeight * 3 + menuExtras.vert - 2;
} else {
minHeight = 0;
}
$menu.css({
'max-height': menuHeight + 'px',
'overflow': 'hidden',
'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
});
$menuInner.css({
'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
'overflow-y': 'auto',
'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
});
};
getSize();
this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
$window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
} else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
if (that.options.container) {
if (!$menu.data('height')) $menu.data('height', $menu.height());
getHeight = $menu.data('height');
} else {
getHeight = $menu.height();
}
if (that.options.dropupAuto) {
//noinspection JSUnusedAssignment
this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
}
$menu.css({
'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
'overflow': 'hidden',
'min-height': ''
});
$menuInner.css({
'max-height': menuHeight - menuPadding.vert + 'px',
'overflow-y': 'auto',
'min-height': ''
});
}
},
setWidth: function () {
if (this.options.width === 'auto') {
this.$menu.css('min-width', '0');
// Get correct width if element is hidden
var $selectClone = this.$menu.parent().clone().appendTo('body'),
$selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
$selectClone.remove();
$selectClone2.remove();
// Set width to whatever's larger, button title or longest option
this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
} else if (this.options.width === 'fit') {
// Remove inline min-width so width can be changed from 'auto'
this.$menu.css('min-width', '');
this.$newElement.css('width', '').addClass('fit-width');
} else if (this.options.width) {
// Remove inline min-width so width can be changed from 'auto'
this.$menu.css('min-width', '');
this.$newElement.css('width', this.options.width);
} else {
// Remove inline min-width/width so width can be changed
this.$menu.css('min-width', '');
this.$newElement.css('width', '');
}
// Remove fit-width class if width is changed programmatically
if (this.$newElement.hasClass('fit-width') && this.options.width !== 'fit') {
this.$newElement.removeClass('fit-width');
}
},
selectPosition: function () {
this.$bsContainer = $('<div class="bs-container" />');
var that = this,
$container = $(this.options.container),
pos,
containerPos,
actualHeight,
getPlacement = function ($element) {
that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
pos = $element.offset();
if (!$container.is('body')) {
containerPos = $container.offset();
containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
} else {
containerPos = { top: 0, left: 0 };
}
actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
that.$bsContainer.css({
'top': pos.top - containerPos.top + actualHeight,
'left': pos.left - containerPos.left,
'width': $element[0].offsetWidth
});
};
this.$button.on('click', function () {
var $this = $(this);
if (that.isDisabled()) {
return;
}
getPlacement(that.$newElement);
that.$bsContainer
.appendTo(that.options.container)
.toggleClass('open', !$this.hasClass('open'))
.append(that.$menu);
});
$(window).on('resize scroll', function () {
getPlacement(that.$newElement);
});
this.$element.on('hide.bs.select', function () {
that.$menu.data('height', that.$menu.height());
that.$bsContainer.detach();
});
},
/**
* @param {number} index - the index of the option that is being changed
* @param {boolean} selected - true if the option is being selected, false if being deselected
* @param {JQuery} $lis - the 'li' element that is being modified
*/
setSelected: function (index, selected, $lis) {
if (!$lis) {
this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
$lis = this.findLis().eq(this.liObj[index]);
}
$lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
},
/**
* @param {number} index - the index of the option that is being disabled
* @param {boolean} disabled - true if the option is being disabled, false if being enabled
* @param {JQuery} $lis - the 'li' element that is being modified
*/
setDisabled: function (index, disabled, $lis) {
if (!$lis) {
$lis = this.findLis().eq(this.liObj[index]);
}
if (disabled) {
$lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
} else {
$lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
}
},
isDisabled: function () {
return this.$element[0].disabled;
},
checkDisabled: function () {
var that = this;
if (this.isDisabled()) {
this.$newElement.addClass('disabled');
this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
} else {
if (this.$button.hasClass('disabled')) {
this.$newElement.removeClass('disabled');
this.$button.removeClass('disabled').attr('aria-disabled', false);
}
if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
this.$button.removeAttr('tabindex');
}
}
this.$button.click(function () {
return !that.isDisabled();
});
},
togglePlaceholder: function () {
var value = this.$element.val();
this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
},
tabIndex: function () {
if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
(this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
this.$element.data('tabindex', this.$element.attr('tabindex'));
this.$button.attr('tabindex', this.$element.data('tabindex'));
}
this.$element.attr('tabindex', -98);
},
clickListener: function () {
var that = this,
$document = $(document);
$document.data('spaceSelect', false);
this.$button.on('keyup', function (e) {
if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
e.preventDefault();
$document.data('spaceSelect', false);
}
});
this.$button.on('click', function () {
that.setSize();
});
this.$element.on('shown.bs.select', function () {
if (!that.options.liveSearch && !that.multiple) {
that.$menuInner.find('.selected a').focus();
} else if (!that.multiple) {
var selectedIndex = that.liObj[that.$element[0].selectedIndex];
if (typeof selectedIndex !== 'number' || that.options.size === false) return;
// scroll to selected option
var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
that.$menuInner[0].scrollTop = offset;
}
});
this.$menuInner.on('click', 'li a', function (e) {
var $this = $(this),
clickedIndex = $this.parent().data('originalIndex'),
prevValue = that.$element.val(),
prevIndex = that.$element.prop('selectedIndex'),
triggerChange = true;
// Don't close on multi choice menu
if (that.multiple && that.options.maxOptions !== 1) {
e.stopPropagation();
}
e.preventDefault();
//Don't run if we have been disabled
if (!that.isDisabled() && !$this.parent().hasClass('disabled')) {
var $options = that.$element.find('option'),
$option = $options.eq(clickedIndex),
state = $option.prop('selected'),
$optgroup = $option.parent('optgroup'),
maxOptions = that.options.maxOptions,
maxOptionsGrp = $optgroup.data('maxOptions') || false;
if (!that.multiple) { // Deselect all others if not multi select box
$options.prop('selected', false);
$option.prop('selected', true);
that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
that.setSelected(clickedIndex, true);
} else { // Toggle the one we have chosen if we are multi select.
$option.prop('selected', !state);
that.setSelected(clickedIndex, !state);
$this.blur();
if (maxOptions !== false || maxOptionsGrp !== false) {
var maxReached = maxOptions < $options.filter(':selected').length,
maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
if ((maxOptions && maxReached) || (maxOptionsGrp && maxReachedGrp)) {
if (maxOptions && maxOptions == 1) {
$options.prop('selected', false);
$option.prop('selected', true);
that.$menuInner.find('.selected').removeClass('selected');
that.setSelected(clickedIndex, true);
} else if (maxOptionsGrp && maxOptionsGrp == 1) {
$optgroup.find('option:selected').prop('selected', false);
$option.prop('selected', true);
var optgroupID = $this.parent().data('optgroup');
that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
that.setSelected(clickedIndex, true);
} else {
var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
$notify = $('<div class="notify"></div>');
// If {var} is set in array, replace it
/** @deprecated */
if (maxOptionsArr[2]) {
maxTxt = maxTxt.replace('{var}', maxOptionsArr[2][maxOptions > 1 ? 0 : 1]);
maxTxtGrp = maxTxtGrp.replace('{var}', maxOptionsArr[2][maxOptionsGrp > 1 ? 0 : 1]);
}
$option.prop('selected', false);
that.$menu.append($notify);
if (maxOptions && maxReached) {
$notify.append($('<div>' + maxTxt + '</div>'));
triggerChange = false;
that.$element.trigger('maxReached.bs.select');
}
if (maxOptionsGrp && maxReachedGrp) {
$notify.append($('<div>' + maxTxtGrp + '</div>'));
triggerChange = false;
that.$element.trigger('maxReachedGrp.bs.select');
}
setTimeout(function () {
that.setSelected(clickedIndex, false);
}, 10);
$notify.delay(750).fadeOut(300, function () {
$(this).remove();
});
}
}
}
}
if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
that.$button.focus();
} else if (that.options.liveSearch) {
that.$searchbox.focus();
}
// Trigger select 'change'
if (triggerChange) {
if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
// $option.prop('selected') is current option state (selected/unselected). state is previous option state.
changed_arguments = [clickedIndex, $option.prop('selected'), state];
that.$element
.triggerNative('change');
}
}
}
});
this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
if (e.currentTarget == this) {
e.preventDefault();
e.stopPropagation();
if (that.options.liveSearch && !$(e.target).hasClass('close')) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
}
});
this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
e.preventDefault();
e.stopPropagation();
if (that.options.liveSearch) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
});
this.$menu.on('click', '.popover-title .close', function () {
that.$button.click();
});
this.$searchbox.on('click', function (e) {
e.stopPropagation();
});
this.$menu.on('click', '.actions-btn', function (e) {
if (that.options.liveSearch) {
that.$searchbox.focus();
} else {
that.$button.focus();
}
e.preventDefault();
e.stopPropagation();
if ($(this).hasClass('bs-select-all')) {
that.selectAll();
} else {
that.deselectAll();
}
});
this.$element.change(function () {
that.render(false);
that.$element.trigger('changed.bs.select', changed_arguments);
changed_arguments = null;
});
},
liveSearchListener: function () {
var that = this,
$no_results = $('<li class="no-results"></li>');
this.$button.on('click.dropdown.data-api', function () {
that.$menuInner.find('.active').removeClass('active');
if (!!that.$searchbox.val()) {
that.$searchbox.val('');
that.$lis.not('.is-hidden').removeClass('hidden');
if (!!$no_results.parent().length) $no_results.remove();
}
if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
setTimeout(function () {
that.$searchbox.focus();
}, 10);
});
this.$searchbox.on('click.dropdown.data-api focus.dropdown.data-api touchend.dropdown.data-api', function (e) {
e.stopPropagation();
});
this.$searchbox.on('input propertychange', function () {
that.$lis.not('.is-hidden').removeClass('hidden');
that.$lis.filter('.active').removeClass('active');
$no_results.remove();
if (that.$searchbox.val()) {
var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
$hideItems;
if (that.options.liveSearchNormalize) {
$hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
} else {
$hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
}
if ($hideItems.length === $searchBase.length) {
$no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
that.$menuInner.append($no_results);
that.$lis.addClass('hidden');
} else {
$hideItems.addClass('hidden');
var $lisVisible = that.$lis.not('.hidden'),
$foundDiv;
// hide divider if first or last visible, or if followed by another divider
$lisVisible.each(function (index) {
var $this = $(this);
if ($this.hasClass('divider')) {
if ($foundDiv === undefined) {
$this.addClass('hidden');
} else {
if ($foundDiv) $foundDiv.addClass('hidden');
$foundDiv = $this;
}
} else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
$this.addClass('hidden');
} else {
$foundDiv = null;
}
});
if ($foundDiv) $foundDiv.addClass('hidden');
$searchBase.not('.hidden').first().addClass('active');
that.$menuInner.scrollTop(0);
}
}
});
},
_searchStyle: function () {
var styles = {
begins: 'ibegins',
startsWith: 'ibegins'
};
return styles[this.options.liveSearchStyle] || 'icontains';
},
val: function (value) {
if (typeof value !== 'undefined') {
this.$element.val(value);
this.render();
return this.$element;
} else {
return this.$element.val();
}
},
changeAll: function (status) {
if (!this.multiple) return;
if (typeof status === 'undefined') status = true;
this.findLis();
var $options = this.$element.find('option'),
$lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
lisVisLen = $lisVisible.length,
selectedOptions = [];
if (status) {
if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
} else {
if ($lisVisible.filter('.selected').length === 0) return;
}
$lisVisible.toggleClass('selected', status);
for (var i = 0; i < lisVisLen; i++) {
var origIndex = $lisVisible[i].getAttribute('data-original-index');
selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
}
$(selectedOptions).prop('selected', status);
this.render(false);
this.togglePlaceholder();
this.$element
.triggerNative('change');
},
selectAll: function () {
return this.changeAll(true);
},
deselectAll: function () {
return this.changeAll(false);
},
toggle: function (e) {
e = e || window.event;
if (e) e.stopPropagation();
this.$button.trigger('click');
},
keydown: function (e) {
var $this = $(this),
$parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
$items,
that = $parent.data('this'),
index,
prevIndex,
isActive,
selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
keyCodeMap = {
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'
};
isActive = that.$newElement.hasClass('open');
if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
if (!that.options.container) {
that.setSize();
that.$menu.parent().addClass('open');
isActive = true;
} else {
that.$button.trigger('click');
}
that.$searchbox.focus();
return;
}
if (that.options.liveSearch) {
if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
e.preventDefault();
e.stopPropagation();
that.$menuInner.click();
that.$button.focus();
}
}
if (/(38|40)/.test(e.keyCode.toString(10))) {
$items = that.$lis.filter(selector);
if (!$items.length) return;
if (!that.options.liveSearch) {
index = $items.index($items.find('a').filter(':focus').parent());
} else {
index = $items.index($items.filter('.active'));
}
prevIndex = that.$menuInner.data('prevIndex');
if (e.keyCode == 38) {
if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
if (index < 0) index += $items.length;
} else if (e.keyCode == 40) {
if (that.options.liveSearch || index == prevIndex) index++;
index = index % $items.length;
}
that.$menuInner.data('prevIndex', index);
if (!that.options.liveSearch) {
$items.eq(index).children('a').focus();
} else {
e.preventDefault();
if (!$this.hasClass('dropdown-toggle')) {
$items.removeClass('active').eq(index).addClass('active').children('a').focus();
$this.focus();
}
}
} else if (!$this.is('input')) {
var keyIndex = [],
count,
prevKey;
$items = that.$lis.filter(selector);
$items.each(function (i) {
if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
keyIndex.push(i);
}
});
count = $(document).data('keycount');
count++;
$(document).data('keycount', count);
prevKey = $.trim($(':focus').text().toLowerCase()).substring(0, 1);
if (prevKey != keyCodeMap[e.keyCode]) {
count = 1;
$(document).data('keycount', count);
} else if (count >= keyIndex.length) {
$(document).data('keycount', 0);
if (count > keyIndex.length) count = 1;
}
$items.eq(keyIndex[count - 1]).children('a').focus();
}
// Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
if (!that.options.liveSearch) {
var elem = $(':focus');
elem.click();
// Bring back focus for multiselects
elem.focus();
// Prevent screen from scrolling if the user hit the spacebar
e.preventDefault();
// Fixes spacebar selection of dropdown items in FF & IE
$(document).data('spaceSelect', true);
} else if (!/(32)/.test(e.keyCode.toString(10))) {
that.$menuInner.find('.active a').click();
$this.focus();
}
$(document).data('keycount', 0);
}
if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
that.$menu.parent().removeClass('open');
if (that.options.container) that.$newElement.removeClass('open');
that.$button.focus();
}
},
mobile: function () {
this.$element.addClass('mobile-device');
},
refresh: function () {
this.$lis = null;
this.liObj = {};
this.reloadLi();
this.render();
this.checkDisabled();
this.liHeight(true);
this.setStyle();
this.setWidth();
if (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();
if (this.$bsContainer) {
this.$bsContainer.remove();
} else {
this.$menu.remove();
}
this.$element
.off('.bs.select')
.removeData('selectpicker')
.removeClass('bs-select-hidden selectpicker');
}
};
// SELECTPICKER PLUGIN DEFINITION
// ==============================
function Plugin(option) {
// get the args of the outer function..
var args = arguments;
// The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
// to get lost/corrupted in android 2.3 and IE9 #715 #775
var _option = option;
[].shift.apply(args);
var value;
var chain = this.each(function () {
var $this = $(this);
if ($this.is('select')) {
var data = $this.data('selectpicker'),
options = typeof _option == 'object' && _option;
if (!data) {
var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
$this.data('selectpicker', (data = new Selectpicker(this, config)));
} else if (options) {
for (var i in options) {
if (options.hasOwnProperty(i)) {
data.options[i] = options[i];
}
}
}
if (typeof _option == 'string') {
if (data[_option] instanceof Function) {
value = data[_option].apply(data, args);
} else {
value = data.options[_option];
}
}
}
});
if (typeof value !== 'undefined') {
//noinspection JSUnusedAssignment
return value;
} else {
return chain;
}
}
var old = $.fn.selectpicker;
$.fn.selectpicker = Plugin;
$.fn.selectpicker.Constructor = Selectpicker;
// SELECTPICKER NO CONFLICT
// ========================
$.fn.selectpicker.noConflict = function () {
$.fn.selectpicker = old;
return this;
};
$(document)
.data('keycount', 0)
.on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
.on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
e.stopPropagation();
});
// SELECTPICKER DATA-API
// =====================
$(window).on('load.bs.select.data-api', function () {
$('.selectpicker').each(function () {
var $selectpicker = $(this);
Plugin.call($selectpicker, $selectpicker.data());
})
});
})(jQuery);
}));
// Underscore.js 1.9.1
// http://underscorejs.org
// (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function() {
// Baseline setup
// --------------
// Establish the root object, `window` (`self`) in the browser, `global`
// on the server, or `this` in some virtual machines. We use `self`
// instead of `window` for `WebWorker` support.
var root = typeof self == 'object' && self.self === self && self ||
typeof global == 'object' && global.global === global && global ||
this ||
{};
// Save the previous value of the `_` variable.
var previousUnderscore = root._;
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype;
var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null;
// Create quick reference variables for speed access to core prototypes.
var push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below.
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for their old module API. If we're in
// the browser, add `_` as a global object.
// (`nodeType` is checked to ensure that `module`
// and `exports` are not HTML elements.)
if (typeof exports != 'undefined' && !exports.nodeType) {
if (typeof module != 'undefined' && !module.nodeType && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
// Current version.
_.VERSION = '1.9.1';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
// The 2-argument case is omitted because we’re not using it.
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
var builtinIteratee;
// An internal function to generate callbacks that can be applied to each
// element in a collection, returning the desired result — either `identity`,
// an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value) && !_.isArray(value)) return _.matcher(value);
return _.property(value);
};
// External wrapper for our callback generator. Users may customize
// `_.iteratee` if they want additional predicate/iteratee shorthand styles.
// This abstraction hides the internal-only argCount argument.
_.iteratee = builtinIteratee = function(value, context) {
return cb(value, context, Infinity);
};
// Some functions take a variable number of arguments, or a few expected
// arguments at the beginning and then a variable number of values to operate
// on. This helper accumulates all remaining arguments past the function’s
// argument length (or an explicit `startIndex`), into an array that becomes
// the last argument. Similar to ES6’s "rest parameter".
var restArguments = function(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0),
rest = Array(length),
index = 0;
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
switch (startIndex) {
case 0: return func.call(this, rest);
case 1: return func.call(this, arguments[0], rest);
case 2: return func.call(this, arguments[0], arguments[1], rest);
}
var args = Array(startIndex + 1);
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
args[startIndex] = rest;
return func.apply(this, args);
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
var shallowProperty = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
var has = function(obj, path) {
return obj != null && hasOwnProperty.call(obj, path);
}
var deepGet = function(obj, path) {
var length = path.length;
for (var i = 0; i < length; i++) {
if (obj == null) return void 0;
obj = obj[path[i]];
}
return length ? obj : void 0;
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object.
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var getLength = shallowProperty('length');
var isArrayLike = function(collection) {
var length = getLength(collection);
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles raw objects in addition to array-likes. Treats all
// sparse array-likes as if they were dense.
_.each = _.forEach = function(obj, iteratee, context) {
iteratee = optimizeCb(iteratee, context);
var i, length;
if (isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
// Return the results of applying the iteratee to each element.
_.map = _.collect = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
results = Array(length);
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Create a reducing function iterating left or right.
var createReduce = function(dir) {
// Wrap code that reassigns argument variables in a separate function than
// the one that accesses `arguments.length` to avoid a perf hit. (#1991)
var reducer = function(obj, iteratee, memo, initial) {
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
index = dir > 0 ? 0 : length - 1;
if (!initial) {
memo = obj[keys ? keys[index] : index];
index += dir;
}
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
};
return function(obj, iteratee, memo, context) {
var initial = arguments.length >= 3;
return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial);
};
};
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) {
var keyFinder = isArrayLike(obj) ? _.findIndex : _.findKey;
var key = keyFinder(obj, predicate, context);
if (key !== void 0 && key !== -1) return obj[key];
};
// Return all the elements that pass a truth test.
// Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) {
var results = [];
predicate = cb(predicate, context);
_.each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) {
return _.filter(obj, _.negate(cb(predicate)), context);
};
// Determine whether all of the elements match a truth test.
// Aliased as `all`.
_.every = _.all = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
};
// Determine if at least one element in the object matches a truth test.
// Aliased as `any`.
_.some = _.any = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (predicate(obj[currentKey], currentKey, obj)) return true;
}
return false;
};
// Determine if the array or object contains a given item (using `===`).
// Aliased as `includes` and `include`.
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
return _.indexOf(obj, item, fromIndex) >= 0;
};
// Invoke a method (with arguments) on every item in a collection.
_.invoke = restArguments(function(obj, path, args) {
var contextPath, func;
if (_.isFunction(path)) {
func = path;
} else if (_.isArray(path)) {
contextPath = path.slice(0, -1);
path = path[path.length - 1];
}
return _.map(obj, function(context) {
var method = func;
if (!method) {
if (contextPath && contextPath.length) {
context = deepGet(context, contextPath);
}
if (context == null) return void 0;
method = context[path];
}
return method == null ? method : method.apply(context, args);
});
});
// Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) {
return _.map(obj, _.property(key));
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
_.where = function(obj, attrs) {
return _.filter(obj, _.matcher(attrs));
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {
return _.find(obj, _.matcher(attrs));
};
// Return the maximum element (or element-based computation).
_.max = function(obj, iteratee, context) {
var result = -Infinity, lastComputed = -Infinity,
value, computed;
if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value != null && value > result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(v, index, list) {
computed = iteratee(v, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = v;
lastComputed = computed;
}
});
}
return result;
};
// Return the minimum element (or element-based computation).
_.min = function(obj, iteratee, context) {
var result = Infinity, lastComputed = Infinity,
value, computed;
if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value != null && value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(v, index, list) {
computed = iteratee(v, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = v;
lastComputed = computed;
}
});
}
return result;
};
// Shuffle a collection.
_.shuffle = function(obj) {
return _.sample(obj, Infinity);
};
// Sample **n** random values from a collection using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (n == null || guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
var sample = isArrayLike(obj) ? _.clone(obj) : _.values(obj);
var length = getLength(sample);
n = Math.max(Math.min(n, length), 0);
var last = length - 1;
for (var index = 0; index < n; index++) {
var rand = _.random(index, last);
var temp = sample[index];
sample[index] = sample[rand];
sample[rand] = temp;
}
return sample.slice(0, n);
};
// Sort the object's values by a criterion produced by an iteratee.
_.sortBy = function(obj, iteratee, context) {
var index = 0;
iteratee = cb(iteratee, context);
return _.pluck(_.map(obj, function(value, key, list) {
return {
value: value,
index: index++,
criteria: iteratee(value, key, list)
};
}).sort(function(left, right) {
var a = left.criteria;
var b = right.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
}), 'value');
};
// An internal function used for aggregate "group by" operations.
var group = function(behavior, partition) {
return function(obj, iteratee, context) {
var result = partition ? [[], []] : {};
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, value, key) {
if (has(result, key)) result[key].push(value); else result[key] = [value];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_.indexBy = group(function(result, value, key) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_.countBy = group(function(result, value, key) {
if (has(result, key)) result[key]++; else result[key] = 1;
});
var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;
// Safely create a real, live array from anything iterable.
_.toArray = function(obj) {
if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj);
if (_.isString(obj)) {
// Keep surrogate pair characters together
return obj.match(reStrSymbol);
}
if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj);
};
// Return the number of elements in an object.
_.size = function(obj) {
if (obj == null) return 0;
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = group(function(result, value, pass) {
result[pass ? 0 : 1].push(value);
}, true);
// Array Functions
// ---------------
// Get the first element of an array. Passing **n** will return the first N
// values in the array. Aliased as `head` and `take`. The **guard** check
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null || array.length < 1) return n == null ? void 0 : [];
if (n == null || guard) return array[0];
return _.initial(array, array.length - n);
};
// Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N.
_.initial = function(array, n, guard) {
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
};
// Get the last element of an array. Passing **n** will return the last N
// values in the array.
_.last = function(array, n, guard) {
if (array == null || array.length < 1) return n == null ? void 0 : [];
if (n == null || guard) return array[array.length - 1];
return _.rest(array, Math.max(0, array.length - n));
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array.
_.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, n == null || guard ? 1 : n);
};
// Trim out all falsy values from an array.
_.compact = function(array) {
return _.filter(array, Boolean);
};
// Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, strict, output) {
output = output || [];
var idx = output.length;
for (var i = 0, length = getLength(input); i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
// Flatten current level of array or arguments object.
if (shallow) {
var j = 0, len = value.length;
while (j < len) output[idx++] = value[j++];
} else {
flatten(value, shallow, strict, output);
idx = output.length;
}
} else if (!strict) {
output[idx++] = value;
}
}
return output;
};
// Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
};
// Return a version of the array that does not contain the specified value(s).
_.without = restArguments(function(array, otherArrays) {
return _.difference(array, otherArrays);
});
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// The faster algorithm will not work with an iteratee if the iteratee
// is not a one-to-one function, so providing an iteratee will disable
// the faster algorithm.
// Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (!_.isBoolean(isSorted)) {
context = iteratee;
iteratee = isSorted;
isSorted = false;
}
if (iteratee != null) iteratee = cb(iteratee, context);
var result = [];
var seen = [];
for (var i = 0, length = getLength(array); i < length; i++) {
var value = array[i],
computed = iteratee ? iteratee(value, i, array) : value;
if (isSorted && !iteratee) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
}
} else if (!_.contains(result, value)) {
result.push(value);
}
}
return result;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_.union = restArguments(function(arrays) {
return _.uniq(flatten(arrays, true, true));
});
// Produce an array that contains every item shared between all the
// passed-in arrays.
_.intersection = function(array) {
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = getLength(array); i < length; i++) {
var item = array[i];
if (_.contains(result, item)) continue;
var j;
for (j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
};
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_.difference = restArguments(function(array, rest) {
rest = flatten(rest, true, true);
return _.filter(array, function(value){
return !_.contains(rest, value);
});
});
// Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices.
_.unzip = function(array) {
var length = array && _.max(array, getLength).length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
}
return result;
};
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = restArguments(_.unzip);
// Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values. Passing by pairs is the reverse of _.pairs.
_.object = function(list, values) {
var result = {};
for (var i = 0, length = getLength(list); i < length; i++) {
if (values) {
result[list[i]] = values[i];
} else {
result[list[i][0]] = list[i][1];
}
}
return result;
};
// Generator function to create the findIndex and findLastIndex functions.
var createPredicateIndexFinder = function(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
};
// Returns the first index on an array-like that passes a predicate test.
_.findIndex = createPredicateIndexFinder(1);
_.findLastIndex = createPredicateIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = getLength(array);
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generator function to create the indexOf and lastIndexOf functions.
var createIndexFinder = function(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
};
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
// Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range).
_.range = function(start, stop, step) {
if (stop == null) {
stop = start || 0;
start = 0;
}
if (!step) {
step = stop < start ? -1 : 1;
}
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
// Chunk a single array into multiple arrays, each containing `count` or fewer
// items.
_.chunk = function(array, count) {
if (count == null || count < 1) return [];
var result = [];
var i = 0, length = array.length;
while (i < length) {
result.push(slice.call(array, i, i += count));
}
return result;
};
// Function (ahem) Functions
// ------------------
// Determines whether to execute a function as a constructor
// or a normal function with the provided arguments.
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available.
_.bind = restArguments(function(func, context, args) {
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
var bound = restArguments(function(callArgs) {
return executeBound(func, bound, context, this, args.concat(callArgs));
});
return bound;
});
// Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder by default, allowing any combination of arguments to be
// pre-filled. Set `_.partial.placeholder` for a custom placeholder argument.
_.partial = restArguments(function(func, boundArgs) {
var placeholder = _.partial.placeholder;
var bound = function() {
var position = 0, length = boundArgs.length;
var args = Array(length);
for (var i = 0; i < length; i++) {
args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i];
}
while (position < arguments.length) args.push(arguments[position++]);
return executeBound(func, bound, this, this, args);
};
return bound;
});
_.partial.placeholder = _;
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = restArguments(function(obj, keys) {
keys = flatten(keys, false, false);
var index = keys.length;
if (index < 1) throw new Error('bindAll must be passed function names');
while (index--) {
var key = keys[index];
obj[key] = _.bind(obj[key], obj);
}
});
// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
var memoize = function(key) {
var cache = memoize.cache;
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
if (!has(cache, address)) cache[address] = func.apply(this, arguments);
return cache[address];
};
memoize.cache = {};
return memoize;
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = restArguments(function(func, wait, args) {
return setTimeout(function() {
return func.apply(null, args);
}, wait);
});
// Defers a function, scheduling it to run after the current call stack has
// cleared.
_.defer = _.partial(_.delay, _, 1);
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
var timeout, context, args, result;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
throttled.cancel = function() {
clearTimeout(timeout);
previous = 0;
timeout = context = args = null;
};
return throttled;
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return _.partial(wrapper, func);
};
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
// Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
_.restArguments = restArguments;
// Object Functions
// ----------------
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
var collectNonEnumProps = function(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = _.isFunction(constructor) && constructor.prototype || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
};
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`.
_.keys = function(obj) {
if (!_.isObject(obj)) return [];
if (nativeKeys) return nativeKeys(obj);
var keys = [];
for (var key in obj) if (has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve the values of an object's properties.
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values;
};
// Returns the results of applying the iteratee to each element of the object.
// In contrast to _.map it returns an object.
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {};
for (var index = 0; index < length; index++) {
var currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs.
// The opposite of _.object.
_.pairs = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var pairs = Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs;
};
// Invert the keys and values of an object. The values must be serializable.
_.invert = function(obj) {
var result = {};
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result;
};
// Return a sorted list of the function names available on the object.
// Aliased as `methods`.
_.functions = _.methods = function(obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, defaults) {
return function(obj) {
var length = arguments.length;
if (defaults) obj = Object(obj);
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!defaults || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// Extend a given object with all the properties in passed-in object(s).
_.extend = createAssigner(_.allKeys);
// Assigns a given object with all the own properties in the passed-in object(s).
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
_.extendOwn = _.assign = createAssigner(_.keys);
// Returns the first key on an object that passes a predicate test.
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
}
};
// Internal pick helper function to determine if `obj` has key `key`.
var keyInObj = function(value, key, obj) {
return key in obj;
};
// Return a copy of the object only containing the whitelisted properties.
_.pick = restArguments(function(obj, keys) {
var result = {}, iteratee = keys[0];
if (obj == null) return result;
if (_.isFunction(iteratee)) {
if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]);
keys = _.allKeys(obj);
} else {
iteratee = keyInObj;
keys = flatten(keys, false, false);
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
});
// Return a copy of the object without the blacklisted properties.
_.omit = restArguments(function(obj, keys) {
var iteratee = keys[0], context;
if (_.isFunction(iteratee)) {
iteratee = _.negate(iteratee);
if (keys.length > 1) context = keys[1];
} else {
keys = _.map(flatten(keys, false, false), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
}
return _.pick(obj, iteratee, context);
});
// Fill in a given object with default properties.
_.defaults = createAssigner(_.allKeys, true);
// Creates an object that inherits from the given prototype object.
// If additional properties are provided then they will be added to the
// created object.
_.create = function(prototype, props) {
var result = baseCreate(prototype);
if (props) _.extendOwn(result, props);
return result;
};
// Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) {
if (!_.isObject(obj)) return obj;
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
// Invokes interceptor with the obj, and then returns obj.
// The primary purpose of this method is to "tap into" a method chain, in
// order to perform operations on intermediate results within the chain.
_.tap = function(obj, interceptor) {
interceptor(obj);
return obj;
};
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`.
var eq, deepEq;
eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a === 1 / b;
// `null` or `undefined` only equal to itself (strict comparison).
if (a == null || b == null) return false;
// `NaN`s are equivalent, but non-reflexive.
if (a !== a) return b !== b;
// Exhaust primitive checks
var type = typeof a;
if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
return deepEq(a, b, aStack, bStack);
};
// Internal recursive comparison function for `isEqual`.
deepEq = function(a, b, aStack, bStack) {
// Unwrap any wrapped objects.
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className !== toString.call(b)) return false;
switch (className) {
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return '' + a === '' + b;
case '[object Number]':
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN.
if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return +a === +b;
case '[object Symbol]':
return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b);
}
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
// Recursively compare objects and arrays.
if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary.
length = a.length;
if (length !== b.length) return false;
// Deep compare the contents, ignoring non-numeric properties.
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
// Deep compare objects.
var keys = _.keys(a), key;
length = keys.length;
// Ensure that both objects contain the same number of properties before comparing deep equality.
if (_.keys(b).length !== length) return false;
while (length--) {
// Deep compare each member
key = keys[length];
if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return true;
};
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
return eq(a, b);
};
// Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) {
if (obj == null) return true;
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
return _.keys(obj).length === 0;
};
// Is a given value a DOM element?
_.isElement = function(obj) {
return !!(obj && obj.nodeType === 1);
};
// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) {
return toString.call(obj) === '[object Array]';
};
// Is a given variable an object?
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError, isMap, isWeakMap, isSet, isWeakSet.
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error', 'Symbol', 'Map', 'WeakMap', 'Set', 'WeakSet'], function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) === '[object ' + name + ']';
};
});
// Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type.
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
return has(obj, 'callee');
};
}
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
// IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236).
var nodelist = root.document && root.document.childNodes;
if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') {
_.isFunction = function(obj) {
return typeof obj == 'function' || false;
};
}
// Is a given object a finite number?
_.isFinite = function(obj) {
return !_.isSymbol(obj) && isFinite(obj) && !isNaN(parseFloat(obj));
};
// Is the given value `NaN`?
_.isNaN = function(obj) {
return _.isNumber(obj) && isNaN(obj);
};
// Is a given value a boolean?
_.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
};
// Is a given value equal to null?
_.isNull = function(obj) {
return obj === null;
};
// Is a given variable undefined?
_.isUndefined = function(obj) {
return obj === void 0;
};
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, path) {
if (!_.isArray(path)) {
return has(obj, path);
}
var length = path.length;
for (var i = 0; i < length; i++) {
var key = path[i];
if (obj == null || !hasOwnProperty.call(obj, key)) {
return false;
}
obj = obj[key];
}
return !!length;
};
// Utility Functions
// -----------------
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
// previous owner. Returns a reference to the Underscore object.
_.noConflict = function() {
root._ = previousUnderscore;
return this;
};
// Keep the identity function around for default iteratees.
_.identity = function(value) {
return value;
};
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) {
return function() {
return value;
};
};
_.noop = function(){};
// Creates a function that, when passed an object, will traverse that object’s
// properties down the given `path`, specified as an array of keys or indexes.
_.property = function(path) {
if (!_.isArray(path)) {
return shallowProperty(path);
}
return function(obj) {
return deepGet(obj, path);
};
};
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
if (obj == null) {
return function(){};
}
return function(path) {
return !_.isArray(path) ? obj[path] : deepGet(obj, path);
};
};
// Returns a predicate for checking whether an object has a given set of
// `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) {
return _.isMatch(obj, attrs);
};
};
// Run a function **n** times.
_.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n));
iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum;
};
// Return a random integer between min and max (inclusive).
_.random = function(min, max) {
if (max == null) {
max = min;
min = 0;
}
return min + Math.floor(Math.random() * (max - min + 1));
};
// A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping.
var escapeMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;'
};
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation.
var createEscaper = function(map) {
var escaper = function(match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped.
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// Traverses the children of `obj` along `path`. If a child is a function, it
// is invoked with its parent as context. Returns the value of the final
// child, or `fallback` if any child is undefined.
_.result = function(obj, path, fallback) {
if (!_.isArray(path)) path = [path];
var length = path.length;
if (!length) {
return _.isFunction(fallback) ? fallback.call(obj) : fallback;
}
for (var i = 0; i < length; i++) {
var prop = obj == null ? void 0 : obj[path[i]];
if (prop === void 0) {
prop = fallback;
i = length; // Ensure we don't continue iterating.
}
obj = _.isFunction(prop) ? prop.call(obj) : prop;
}
return obj;
};
// Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids.
var idCounter = 0;
_.uniqueId = function(prefix) {
var id = ++idCounter + '';
return prefix ? prefix + id : id;
};
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate: /<%([\s\S]+?)%>/g,
interpolate: /<%=([\s\S]+?)%>/g,
escape: /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
// NB: `oldSettings` only exists for backwards compatibility.
_.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
index = offset + match.length;
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} else if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
// Adobe VMs need the match returned to produce the correct offset.
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
var render;
try {
render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled source as a convenience for precompilation.
var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template;
};
// Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) {
var instance = _(obj);
instance._chain = true;
return instance;
};
// OOP
// ---------------
// If Underscore is called as a function, it returns a wrapped object that
// can be used OO-style. This wrapper holds altered versions of all the
// underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results.
var chainResult = function(instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return chainResult(this, func.apply(_, args));
};
});
return _;
};
// Add all of the Underscore functions to the wrapper object.
_.mixin(_);
// Add all mutator Array functions to the wrapper.
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
var obj = this._wrapped;
method.apply(obj, arguments);
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return chainResult(this, obj);
};
});
// Add all accessor Array functions to the wrapper.
_.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
return chainResult(this, method.apply(this._wrapped, arguments));
};
});
// Extracts the result from a wrapped and chained object.
_.prototype.value = function() {
return this._wrapped;
};
// Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return String(this._wrapped);
};
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define == 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}());
\ No newline at end of file
let asistencias = [];
function buscar() {
let busqueda = "";
$("#tblAsistenciaDocentes").DataTable().destroy();
$("#tblAsistenciaDocentes").DataTable({
iDisplayLength: 50,
bStateSave: false,
autoWidth: false,
responsive: true,
stateSave: true,
columnDefs: [{
orderable: false,
width: '100px',
targets: [8]
}],
dom: '<"datatable-header"fl><"datatable-scroll-wrap"t><"datatable-footer"ip>',
"processing": true,
"serverSide": false,
"data": asistencias,
"columns": [{"data": "fila"},
{"data": "nombres"},
{"data": "dni"},
// {"data": "sede"},
{"data": "area"},
{"data": "cargo"},
{
"data": "fecha_asistencia",
"className": 'text-center'
},
{
"data": "hora_ingreso",
"className": 'text-center'
},
{
"data": "hora_salida",
"className": 'text-center'
},
{
"data": "observacion",
"className": 'text-center',
render: function (data) {
let label = '';
let obs = ['', 'Asistió', 'No marcó', 'Falta con aviso', 'Falta sin aviso', 'Tardanza', 'Vacaciones', 'Feriado', 'LSGH', 'LCGH'];
debugger
switch (data) {
case "1"://Asistió
label = "label label-success";
break;
case "2"://No marco
label = 'label label-info';
break;
case "3"://'Falta con aviso'
case "4"://'Falta sin aviso'
label = 'label label-danger';
break;
case "5"://'Tardanza'
label = 'label label-warning';
break;
case "6"://'Vacaciones'
case "7"://'Feriado'
case "8"://'LSGH'
case "9"://'LCGH'
label = 'label label-primary';
break;
default:
label = 'label label-default';
}
debugger
console.log(label);
return `<span class="${label}" style="font-size: 12px">${obs[data]}</span>`;
}
}
],
fnInitComplete: function (settings, data) {
console.log(data);
}
});
}
//$("#dp").datepicker({
// minDate: new Date(1900, 1 - 1, 1), maxDate: '-18Y',
// dateFormat: 'dd/mm/yy',
// defaultDate: new Date(1970, 1 - 1, 1),
// changeMonth: true,
// changeYear: true,
// yearRange: '-110:-18',
// onSelect: function () {
// $(this).valid();
// }
//});
//$("#dtpFechaInicio").datepicker('setDate', 'now');
$().ready(function () {
console.log("awsdfasdf");
defaultConfigDataTable();
$('.selectpicker').selectpicker({
style: 'btn-info',
size: 4
});
$(".btn.dropdown-toggle.bs-placeholder").removeClass("btn-info");
$(".btn.dropdown-toggle.bs-placeholder").css({
border: "1px solid #ddd",
backgroundColor: "#fff"
});
$("#dpFechaInicio").datepicker({
minDate: new Date(2000, 1 - 1, 1), maxDate: new Date(),
dateFormat: 'dd/mm/yy',
defaultDate: new Date(),
changeMonth: true,
changeYear: true,
yearRange: '-18:+0',
onSelect: function () {
// $(this).valid();
}
});
$("#dpFechaInicio").datepicker('setDate', 'now');
$("#dpFechaFin").datepicker({
minDate: new Date(2000, 1 - 1, 1), maxDate: new Date(),
dateFormat: 'dd/mm/yy',
defaultDate: new Date(),
changeMonth: true,
changeYear: true,
yearRange: '-18:+0',
onSelect: function () {
// $(this).valid();
}
});
$("#dpFechaFin").datepicker('setDate', 'now');
defaultConfigDatePicker();
});
\ No newline at end of file
<%@include file="templates/validar.jsp" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@include file="templates/header.jsp" %>
<!--template-core-->
<!--css de la pagina-->
<!--<link href="../css/lib/bootstrap-select/bootstrap-select.min.css" rel="stylesheet" type="text/css"/>-->
<!--css-->
</head>
<body>
<%@include file="templates/header-body.jsp" %>
<!-- content -->
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h5 class="panel-title">Control de Asistencia de Docentes</h5>
</div>
<form id="frmAsistenciaDocentes" onsubmit="return false;" autocomplete="off">
<div class="panel-body">
<div class="row">
<div class="col-md-6 form-group">
<label>Fecha Inicio</label>
<div class="input-group">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
<input type="text" class="form-control" id="dpFechaInicio" name="dpFechaInicio" placeholder="Fecha inicio &hellip;">
</div>
</div>
<div class="col-md-6 form-group">
<label>Fecha Fin</label>
<div class="input-group">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
<input type="text" class="form-control" id="dpFechaFin" name="dpFechaFin" placeholder="Fecha fin &hellip;">
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 form-group">
<label>Criterio</label>
<select class="form-control">
<option>SEDE</option>
<option>APELLIDOS</option>
<option>DNI</option>
</select>
</div>
<div class="col-md-9 form-group">
<label>Busqueda</label>
<input type="text" class="form-control"/>
</div>
</div>
<div class="row">
<div class="col-md-10 form-group">
<label>Estado</label>
<select class="selectpicker form-control" name="cboSedes" id="cboSedes" multiple>
<option>PENDIENTE</option>
<option>FCA</option>
<option>FSA</option>
<option>TEMPRANO</option>
<option>TARDANZA</option>
<option>NO MARCÓ</option>
</select>
</div>
</div>
</div>
<div class="panel-footer">
<div class="text-center">
<button class="btn btn-primary" id="btnBuscar"><i class="fa fa-search"></i> Buscar</button>&nbsp;
<button class="btn btn-warning" id="btnLimpiar"><i class="fa fa-eraser"></i> Limpiar</button>
</div>
</div>
</form>
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-primary card-3" style="margin-top: 30px">
<div class="panel-heading" style="padding: 8px 15px">
<h6 class="panel-title" style="font-size: 15px; font-family: inherit"><i class="icon icon-search4"></i>&nbsp; LISTADO DE ASISTENCIAS</h6>
</div>
<div>
<table class="table dataTable table-striped table-hover table-sm table-bordered" id="tblAsistenciaDocentes">
<thead>
<tr>
<th></th>
<!--<th>SEDE</th>-->
<th>APELLIDOS Y NOMBRES</th>
<th>FECHA</th>
<th>HORARIO</th>
<th>HORA MARCACIÓN</th>
<th>AULAS</th>
<th>ESTADO</th>
<th>ACCIONES</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>HUAMANI TAIPE, FRANCISCO</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>07:35</td>
<td>1A-2A-3A-4A</td>
<td><span class="label label-success">TEMPRANO</span></td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>LEON GOMEZ, MARIO JOSIMAR</td>
<td>26/06/2018</td>
<td>07:50 - 09:35</td>
<td>07:56</td>
<td>1A</td>
<td><span class="label label-warning">TARDANZA</span></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-danger">FCA</span></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-danger">FSA</span></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-default">NO MARCÓ</span></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-info">VAC</span></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-info">FER</span></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td>-</td>
<td>1A</td>
<td><span class="label label-info">LCGH</span></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>ALVITES MARIN, VICTOR MANUEL</td>
<td>26/06/2018</td>
<td>07:50 - 14:30</td>
<td></td>
<td>1A</td>
<td><span class="label bg-purple">PENDIENTE</span></td>
<td>
<span data-toggle="tooltip" data-placement="left" title="Editar" style="cursor: pointer"> <i class='registrar icon-plus-circle2 text-success-700'></i>&nbsp;&nbsp; </span>
<span data-toggle="tooltip" data-placement="left" title="Editar" style="cursor: pointer"> <i class='editar icon-pencil text-slate-800'></i>&nbsp;&nbsp; </span>
<span data-toggle="tooltip" data-placement="left" title="Aprobar" style="cursor: pointer"> <i class='aprobar icon-checkmark-circle text-success-700'></i>&nbsp;&nbsp; </span>
<span data-toggle="tooltip" data-placement="left" title="Anular" style="cursor: pointer"> <i class='anular icon-cancel-circle2 text-danger-700'></i>&nbsp;&nbsp; </span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- / content -->
<%@include file="templates/footer-body.jsp"%>
<!--js de la pagina-->
<script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap.min.js"></script>
<script src="../js/lib/bootstrap-select/bootstrap-select.min.js" type="text/javascript"></script>
<script type="text/javascript" src="../plantilla/assets/js/core/libraries/jquery_ui/widgets.min.js"></script>
<script src="../js/pages/controlAsistenciaDocentes.js" type="text/javascript"></script>
<!--js-->
</body>
</html>
\ No newline at end of file
......@@ -25,7 +25,7 @@
<script type="text/javascript" src="../plantilla/assets/js/plugins/forms/styling/switchery.min.js"></script>
<script type="text/javascript" src="../plantilla/assets/js/plugins/forms/styling/uniform.min.js"></script>
<script type="text/javascript" src="../plantilla/assets/js/plugins/forms/selects/bootstrap_multiselect.js"></script>
<!--<script type="text/javascript" src="../plantilla/assets/js/plugins/forms/selects/bootstrap_multiselect.js"></script>-->
<script type="text/javascript" src="../plantilla/assets/js/core/app.js"></script>
<!-- /core JS files -->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment