-/**
- * Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect)
- *
- * Apache License, Version 2.0:
- * Copyright (c) 2012 - 2015 David Stutz
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a
- * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- * BSD 3-Clause License:
- * Copyright (c) 2012 - 2015 David Stutz
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of David Stutz nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-!function ($) {
- "use strict";// jshint ;_;
-
- if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
- ko.bindingHandlers.multiselect = {
- after: ['options', 'value', 'selectedOptions', 'enable', 'disable'],
-
- init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
- var $element = $(element);
- var config = ko.toJS(valueAccessor());
-
- $element.multiselect(config);
-
- if (allBindings.has('options')) {
- var options = allBindings.get('options');
- if (ko.isObservable(options)) {
- ko.computed({
- read: function() {
- options();
- setTimeout(function() {
- var ms = $element.data('multiselect');
- if (ms)
- ms.updateOriginalOptions();//Not sure how beneficial this is.
- $element.multiselect('rebuild');
- }, 1);
- },
- disposeWhenNodeIsRemoved: element
- });
- }
- }
-
- //value and selectedOptions are two-way, so these will be triggered even by our own actions.
- //It needs some way to tell if they are triggered because of us or because of outside change.
- //It doesn't loop but it's a waste of processing.
- if (allBindings.has('value')) {
- var value = allBindings.get('value');
- if (ko.isObservable(value)) {
- ko.computed({
- read: function() {
- value();
- setTimeout(function() {
- $element.multiselect('refresh');
- }, 1);
- },
- disposeWhenNodeIsRemoved: element
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
- }
- }
-
- //Switched from arrayChange subscription to general subscription using 'refresh'.
- //Not sure performance is any better using 'select' and 'deselect'.
- if (allBindings.has('selectedOptions')) {
- var selectedOptions = allBindings.get('selectedOptions');
- if (ko.isObservable(selectedOptions)) {
- ko.computed({
- read: function() {
- selectedOptions();
- setTimeout(function() {
- $element.multiselect('refresh');
- }, 1);
- },
- disposeWhenNodeIsRemoved: element
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
- }
- }
-
- var setEnabled = function (enable) {
- setTimeout(function () {
- if (enable)
- $element.multiselect('enable');
- else
- $element.multiselect('disable');
- });
- };
-
- if (allBindings.has('enable')) {
- var enable = allBindings.get('enable');
- if (ko.isObservable(enable)) {
- ko.computed({
- read: function () {
- setEnabled(enable());
- },
- disposeWhenNodeIsRemoved: element
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
- } else {
- setEnabled(enable);
- }
- }
-
- if (allBindings.has('disable')) {
- var disable = allBindings.get('disable');
- if (ko.isObservable(disable)) {
- ko.computed({
- read: function () {
- setEnabled(!disable());
- },
- disposeWhenNodeIsRemoved: element
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
- } else {
- setEnabled(!disable);
- }
- }
-
- ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
- $element.multiselect('destroy');
- });
- },
-
- update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
- var $element = $(element);
- var config = ko.toJS(valueAccessor());
-
- $element.multiselect('setOptions', config);
- $element.multiselect('rebuild');
- }
- };
- }
-
- function forEach(array, callback) {
- for (var index = 0; index < array.length; ++index) {
- callback(array[index], index);
- }
- }
-
- /**
- * Constructor to create a new multiselect using the given select.
- *
- * @param {jQuery} select
- * @param {Object} options
- * @returns {Multiselect}
- */
- function Multiselect(select, options) {
-
- this.$select = $(select);
- this.options = this.mergeOptions($.extend({}, options, this.$select.data()));
-
- // Placeholder via data attributes
- if (this.$select.attr("data-placeholder")) {
- this.options.nonSelectedText = this.$select.data("placeholder");
- }
-
- // Initialization.
- // We have to clone to create a new reference.
- this.originalOptions = this.$select.clone()[0].options;
- this.query = '';
- this.searchTimeout = null;
- this.lastToggledInput = null;
-
- this.options.multiple = this.$select.attr('multiple') === "multiple";
- this.options.onChange = $.proxy(this.options.onChange, this);
- this.options.onSelectAll = $.proxy(this.options.onSelectAll, this);
- this.options.onDeselectAll = $.proxy(this.options.onDeselectAll, this);
- this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);
- this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);
- this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this);
- this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this);
- this.options.onInitialized = $.proxy(this.options.onInitialized, this);
- this.options.onFiltering = $.proxy(this.options.onFiltering, this);
-
- // Build select all if enabled.
- this.buildContainer();
- this.buildButton();
- this.buildDropdown();
- this.buildSelectAll();
- this.buildDropdownOptions();
- this.buildFilter();
-
- this.updateButtonText();
- this.updateSelectAll(true);
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- this.options.wasDisabled = this.$select.prop('disabled');
- if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
- this.disable();
- }
-
- this.$select.wrap('<span class="multiselect-native-select" />').after(this.$container);
- this.options.onInitialized(this.$select, this.$container);
- }
-
- Multiselect.prototype = {
-
- defaults: {
- /**
- * Default text function will either print 'None selected' in case no
- * option is selected or a list of the selected options up to a length
- * of 3 selected options.
- *
- * @param {jQuery} options
- * @param {jQuery} select
- * @returns {String}
- */
- buttonText: function(options, select) {
- if (this.disabledText.length > 0
- && (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) {
-
- return this.disabledText;
- }
- else if (options.length === 0) {
- return this.nonSelectedText;
- }
- else if (this.allSelectedText
- && options.length === $('option', $(select)).length
- && $('option', $(select)).length !== 1
- && this.multiple) {
-
- if (this.selectAllNumber) {
- return this.allSelectedText + ' (' + options.length + ')';
- }
- else {
- return this.allSelectedText;
- }
- }
- else if (options.length > this.numberDisplayed) {
- return options.length + ' ' + this.nSelectedText;
- }
- else {
- var selected = '';
- var delimiter = this.delimiterText;
-
- options.each(function() {
- var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
- selected += label + delimiter;
- });
-
- return selected.substr(0, selected.length - this.delimiterText.length);
- }
- },
- /**
- * Updates the title of the button similar to the buttonText function.
- *
- * @param {jQuery} options
- * @param {jQuery} select
- * @returns {@exp;selected@call;substr}
- */
- buttonTitle: function(options, select) {
- if (options.length === 0) {
- return this.nonSelectedText;
- }
- else {
- var selected = '';
- var delimiter = this.delimiterText;
-
- options.each(function () {
- var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
- selected += label + delimiter;
- });
- return selected.substr(0, selected.length - this.delimiterText.length);
- }
- },
- checkboxName: function(option) {
- return false; // no checkbox name
- },
- /**
- * Create a label.
- *
- * @param {jQuery} element
- * @returns {String}
- */
- optionLabel: function(element){
- return $(element).attr('label') || $(element).text();
- },
- /**
- * Create a class.
- *
- * @param {jQuery} element
- * @returns {String}
- */
- optionClass: function(element) {
- return $(element).attr('class') || '';
- },
- /**
- * Triggered on change of the multiselect.
- *
- * Not triggered when selecting/deselecting options manually.
- *
- * @param {jQuery} option
- * @param {Boolean} checked
- */
- onChange : function(option, checked) {
-
- },
- /**
- * Triggered when the dropdown is shown.
- *
- * @param {jQuery} event
- */
- onDropdownShow: function(event) {
-
- },
- /**
- * Triggered when the dropdown is hidden.
- *
- * @param {jQuery} event
- */
- onDropdownHide: function(event) {
-
- },
- /**
- * Triggered after the dropdown is shown.
- *
- * @param {jQuery} event
- */
- onDropdownShown: function(event) {
-
- },
- /**
- * Triggered after the dropdown is hidden.
- *
- * @param {jQuery} event
- */
- onDropdownHidden: function(event) {
-
- },
- /**
- * Triggered on select all.
- */
- onSelectAll: function() {
-
- },
- /**
- * Triggered on deselect all.
- */
- onDeselectAll: function() {
-
- },
- /**
- * Triggered after initializing.
- *
- * @param {jQuery} $select
- * @param {jQuery} $container
- */
- onInitialized: function($select, $container) {
-
- },
- /**
- * Triggered on filtering.
- *
- * @param {jQuery} $filter
- */
- onFiltering: function($filter) {
-
- },
- enableHTML: false,
- buttonClass: 'btn btn-default',
- inheritClass: false,
- buttonWidth: 'auto',
- buttonContainer: '<div class="btn-group" />',
- dropRight: false,
- dropUp: false,
- selectedClass: 'active',
- // Maximum height of the dropdown menu.
- // If maximum height is exceeded a scrollbar will be displayed.
- maxHeight: false,
- includeSelectAllOption: false,
- includeSelectAllIfMoreThan: 0,
- selectAllText: ' Select all',
- selectAllValue: 'multiselect-all',
- selectAllName: false,
- selectAllNumber: true,
- selectAllJustVisible: true,
- enableFiltering: false,
- enableCaseInsensitiveFiltering: false,
- enableFullValueFiltering: false,
- enableClickableOptGroups: false,
- enableCollapsibleOptGroups: false,
- filterPlaceholder: 'Search',
- // possible options: 'text', 'value', 'both'
- filterBehavior: 'text',
- includeFilterClearBtn: true,
- preventInputChangeEvent: false,
- nonSelectedText: 'None selected',
- nSelectedText: 'selected',
- allSelectedText: 'All selected',
- numberDisplayed: 3,
- disableIfEmpty: false,
- disabledText: '',
- delimiterText: ', ',
- templates: {
- button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span> <b class="caret"></b></button>',
- ul: '<ul class="multiselect-container dropdown-menu"></ul>',
- filter: '<li class="multiselect-item multiselect-filter"><div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div></li>',
- filterClearBtn: '<span class="input-group-btn"><button class="btn btn-default multiselect-clear-filter" type="button"><i class="glyphicon glyphicon-remove-circle"></i></button></span>',
- li: '<li><a tabindex="0"><label></label></a></li>',
- divider: '<li class="multiselect-item divider"></li>',
- liGroup: '<li class="multiselect-item multiselect-group"><label></label></li>'
- }
- },
-
- constructor: Multiselect,
-
- /**
- * Builds the container of the multiselect.
- */
- buildContainer: function() {
- this.$container = $(this.options.buttonContainer);
- this.$container.on('show.bs.dropdown', this.options.onDropdownShow);
- this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
- this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);
- this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);
- },
-
- /**
- * Builds the button of the multiselect.
- */
- buildButton: function() {
- this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);
- if (this.$select.attr('class') && this.options.inheritClass) {
- this.$button.addClass(this.$select.attr('class'));
- }
- // Adopt active state.
- if (this.$select.prop('disabled')) {
- this.disable();
- }
- else {
- this.enable();
- }
-
- // Manually add button width if set.
- if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {
- this.$button.css({
- 'width' : '100%', //this.options.buttonWidth,
- 'overflow' : 'hidden',
- 'text-overflow' : 'ellipsis'
- });
- this.$container.css({
- 'width': this.options.buttonWidth
- });
- }
-
- // Keep the tab index from the select.
- var tabindex = this.$select.attr('tabindex');
- if (tabindex) {
- this.$button.attr('tabindex', tabindex);
- }
-
- this.$container.prepend(this.$button);
- },
-
- /**
- * Builds the ul representing the dropdown menu.
- */
- buildDropdown: function() {
-
- // Build ul.
- this.$ul = $(this.options.templates.ul);
-
- if (this.options.dropRight) {
- this.$ul.addClass('pull-right');
- }
-
- // Set max height of dropdown menu to activate auto scrollbar.
- if (this.options.maxHeight) {
- // TODO: Add a class for this option to move the css declarations.
- this.$ul.css({
- 'max-height': this.options.maxHeight + 'px',
- 'overflow-y': 'auto',
- 'overflow-x': 'hidden'
- });
- }
-
- if (this.options.dropUp) {
-
- var height = Math.min(this.options.maxHeight, $('option[data-role!="divider"]', this.$select).length*26 + $('option[data-role="divider"]', this.$select).length*19 + (this.options.includeSelectAllOption ? 26 : 0) + (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering ? 44 : 0));
- var moveCalc = height + 34;
-
- this.$ul.css({
- 'max-height': height + 'px',
- 'overflow-y': 'auto',
- 'overflow-x': 'hidden',
- 'margin-top': "-" + moveCalc + 'px'
- });
- }
-
- this.$container.append(this.$ul);
- },
-
- /**
- * Build the dropdown options and binds all necessary events.
- *
- * Uses createDivider and createOptionValue to create the necessary options.
- */
- buildDropdownOptions: function() {
-
- this.$select.children().each($.proxy(function(index, element) {
-
- var $element = $(element);
- // Support optgroups and options without a group simultaneously.
- var tag = $element.prop('tagName')
- .toLowerCase();
-
- if ($element.prop('value') === this.options.selectAllValue) {
- return;
- }
-
- if (tag === 'optgroup') {
- this.createOptgroup(element);
- }
- else if (tag === 'option') {
-
- if ($element.data('role') === 'divider') {
- this.createDivider();
- }
- else {
- this.createOptionValue(element);
- }
-
- }
-
- // Other illegal tags will be ignored.
- }, this));
-
- // Bind the change event on the dropdown elements.
- $('li:not(.multiselect-group) input', this.$ul).on('change', $.proxy(function(event) {
- var $target = $(event.target);
-
- var checked = $target.prop('checked') || false;
- var isSelectAllOption = $target.val() === this.options.selectAllValue;
-
- // Apply or unapply the configured selected class.
- if (this.options.selectedClass) {
- if (checked) {
- $target.closest('li')
- .addClass(this.options.selectedClass);
- }
- else {
- $target.closest('li')
- .removeClass(this.options.selectedClass);
- }
- }
-
- // Get the corresponding option.
- var value = $target.val();
- var $option = this.getOptionByValue(value);
-
- var $optionsNotThis = $('option', this.$select).not($option);
- var $checkboxesNotThis = $('input', this.$container).not($target);
-
- if (isSelectAllOption) {
-
- if (checked) {
- this.selectAll(this.options.selectAllJustVisible, true);
- }
- else {
- this.deselectAll(this.options.selectAllJustVisible, true);
- }
- }
- else {
- if (checked) {
- $option.prop('selected', true);
-
- if (this.options.multiple) {
- // Simply select additional option.
- $option.prop('selected', true);
- }
- else {
- // Unselect all other options and corresponding checkboxes.
- if (this.options.selectedClass) {
- $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass);
- }
-
- $($checkboxesNotThis).prop('checked', false);
- $optionsNotThis.prop('selected', false);
-
- // It's a single selection, so close.
- this.$button.click();
- }
-
- if (this.options.selectedClass === "active") {
- $optionsNotThis.closest("a").css("outline", "");
- }
- }
- else {
- // Unselect option.
- $option.prop('selected', false);
- }
-
- // To prevent select all from firing onChange: #575
- this.options.onChange($option, checked);
-
- // Do not update select all or optgroups on select all change!
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
- }
-
- this.$select.change();
- this.updateButtonText();
-
- if(this.options.preventInputChangeEvent) {
- return false;
- }
- }, this));
-
- $('li a', this.$ul).on('mousedown', function(e) {
- if (e.shiftKey) {
- // Prevent selecting text by Shift+click
- return false;
- }
- });
-
- $('li a', this.$ul).on('touchstart click', $.proxy(function(event) {
- event.stopPropagation();
-
- var $target = $(event.target);
-
- if (event.shiftKey && this.options.multiple) {
- if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)
- event.preventDefault();
- $target = $target.find("input");
- $target.prop("checked", !$target.prop("checked"));
- }
- var checked = $target.prop('checked') || false;
-
- if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
- var from = $target.closest("li").index();
- var to = this.lastToggledInput.closest("li").index();
-
- if (from > to) { // Swap the indices
- var tmp = to;
- to = from;
- from = tmp;
- }
-
- // Make sure we grab all elements since slice excludes the last index
- ++to;
-
- // Change the checkboxes and underlying options
- var range = this.$ul.find("li").slice(from, to).find("input");
-
- range.prop('checked', checked);
-
- if (this.options.selectedClass) {
- range.closest('li')
- .toggleClass(this.options.selectedClass, checked);
- }
-
- for (var i = 0, j = range.length; i < j; i++) {
- var $checkbox = $(range[i]);
-
- var $option = this.getOptionByValue($checkbox.val());
-
- $option.prop('selected', checked);
- }
- }
-
- // Trigger the select "change" event
- $target.trigger("change");
- }
-
- // Remembers last clicked option
- if($target.is("input") && !$target.closest("li").is(".multiselect-item")){
- this.lastToggledInput = $target;
- }
-
- $target.blur();
- }, this));
-
- // Keyboard support.
- this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {
- if ($('input[type="text"]', this.$container).is(':focus')) {
- return;
- }
-
- if (event.keyCode === 9 && this.$container.hasClass('open')) {
- this.$button.click();
- }
- else {
- var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible");
-
- if (!$items.length) {
- return;
- }
-
- var index = $items.index($items.filter(':focus'));
-
- // Navigation up.
- if (event.keyCode === 38 && index > 0) {
- index--;
- }
- // Navigate down.
- else if (event.keyCode === 40 && index < $items.length - 1) {
- index++;
- }
- else if (!~index) {
- index = 0;
- }
-
- var $current = $items.eq(index);
- $current.focus();
-
- if (event.keyCode === 32 || event.keyCode === 13) {
- var $checkbox = $current.find('input');
-
- $checkbox.prop("checked", !$checkbox.prop("checked"));
- $checkbox.change();
- }
-
- event.stopPropagation();
- event.preventDefault();
- }
- }, this));
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- $("li.multiselect-group input", this.$ul).on("change", $.proxy(function(event) {
- event.stopPropagation();
-
- var $target = $(event.target);
- var checked = $target.prop('checked') || false;
-
- var $li = $(event.target).closest('li');
- var $group = $li.nextUntil("li.multiselect-group")
- .not('.multiselect-filter-hidden')
- .not('.disabled');
-
- var $inputs = $group.find("input");
-
- var values = [];
- var $options = [];
-
- if (this.options.selectedClass) {
- if (checked) {
- $li.addClass(this.options.selectedClass);
- }
- else {
- $li.removeClass(this.options.selectedClass);
- }
- }
-
- $.each($inputs, $.proxy(function(index, input) {
- var value = $(input).val();
- var $option = this.getOptionByValue(value);
-
- if (checked) {
- $(input).prop('checked', true);
- $(input).closest('li')
- .addClass(this.options.selectedClass);
-
- $option.prop('selected', true);
- }
- else {
- $(input).prop('checked', false);
- $(input).closest('li')
- .removeClass(this.options.selectedClass);
-
- $option.prop('selected', false);
- }
-
- $options.push(this.getOptionByValue(value));
- }, this))
-
- // Cannot use select or deselect here because it would call updateOptGroups again.
-
- this.options.onChange($options, checked);
-
- this.updateButtonText();
- this.updateSelectAll();
- }, this));
- }
-
- if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
- $("li.multiselect-group .caret-container", this.$ul).on("click", $.proxy(function(event) {
- var $li = $(event.target).closest('li');
- var $inputs = $li.nextUntil("li.multiselect-group")
- .not('.multiselect-filter-hidden');
-
- var visible = true;
- $inputs.each(function() {
- visible = visible && $(this).is(':visible');
- });
-
- if (visible) {
- $inputs.hide()
- .addClass('multiselect-collapsible-hidden');
- }
- else {
- $inputs.show()
- .removeClass('multiselect-collapsible-hidden');
- }
- }, this));
-
- $("li.multiselect-all", this.$ul).css('background', '#f3f3f3').css('border-bottom', '1px solid #eaeaea');
- $("li.multiselect-all > a > label.checkbox", this.$ul).css('padding', '3px 20px 3px 35px');
- $("li.multiselect-group > a > input", this.$ul).css('margin', '4px 0px 5px -20px');
- }
- },
-
- /**
- * Create an option using the given select option.
- *
- * @param {jQuery} element
- */
- createOptionValue: function(element) {
- var $element = $(element);
- if ($element.is(':selected')) {
- $element.prop('selected', true);
- }
-
- // Support the label attribute on options.
- var label = this.options.optionLabel(element);
- var classes = this.options.optionClass(element);
- var value = $element.val();
- var inputType = this.options.multiple ? "checkbox" : "radio";
-
- var $li = $(this.options.templates.li);
- var $label = $('label', $li);
- $label.addClass(inputType);
- $li.addClass(classes);
-
- if (this.options.enableHTML) {
- $label.html(" " + label);
- }
- else {
- $label.text(" " + label);
- }
-
- var $checkbox = $('<input/>').attr('type', inputType);
-
- var name = this.options.checkboxName($element);
- if (name) {
- $checkbox.attr('name', name);
- }
-
- $label.prepend($checkbox);
-
- var selected = $element.prop('selected') || false;
- $checkbox.val(value);
-
- if (value === this.options.selectAllValue) {
- $li.addClass("multiselect-item multiselect-all");
- $checkbox.parent().parent()
- .addClass('multiselect-all');
- }
-
- $label.attr('title', $element.attr('title'));
-
- this.$ul.append($li);
-
- if ($element.is(':disabled')) {
- $checkbox.attr('disabled', 'disabled')
- .prop('disabled', true)
- .closest('a')
- .attr("tabindex", "-1")
- .closest('li')
- .addClass('disabled');
- }
-
- $checkbox.prop('checked', selected);
-
- if (selected && this.options.selectedClass) {
- $checkbox.closest('li')
- .addClass(this.options.selectedClass);
- }
- },
-
- /**
- * Creates a divider using the given select option.
- *
- * @param {jQuery} element
- */
- createDivider: function(element) {
- var $divider = $(this.options.templates.divider);
- this.$ul.append($divider);
- },
-
- /**
- * Creates an optgroup.
- *
- * @param {jQuery} group
- */
- createOptgroup: function(group) {
- var label = $(group).attr("label");
- var value = $(group).attr("value");
- var $li = $('<li class="multiselect-item multiselect-group"><a href="javascript:void(0);"><label><b></b></label></a></li>');
-
- var classes = this.options.optionClass(group);
- $li.addClass(classes);
-
- if (this.options.enableHTML) {
- $('label b', $li).html(" " + label);
- }
- else {
- $('label b', $li).text(" " + label);
- }
-
- if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
- $('a', $li).append('<span class="caret-container"><b class="caret"></b></span>');
- }
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- $('a label', $li).prepend('<input type="checkbox" value="' + value + '"/>');
- }
-
- if ($(group).is(':disabled')) {
- $li.addClass('disabled');
- }
-
- this.$ul.append($li);
-
- $("option", group).each($.proxy(function($, group) {
- this.createOptionValue(group);
- }, this))
- },
-
- /**
- * Build the select all.
- *
- * Checks if a select all has already been created.
- */
- buildSelectAll: function() {
- if (typeof this.options.selectAllValue === 'number') {
- this.options.selectAllValue = this.options.selectAllValue.toString();
- }
-
- var alreadyHasSelectAll = this.hasSelectAll();
-
- if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
- && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {
-
- // Check whether to add a divider after the select all.
- if (this.options.includeSelectAllDivider) {
- this.$ul.prepend($(this.options.templates.divider));
- }
-
- var $li = $(this.options.templates.li);
- $('label', $li).addClass("checkbox");
-
- if (this.options.enableHTML) {
- $('label', $li).html(" " + this.options.selectAllText);
- }
- else {
- $('label', $li).text(" " + this.options.selectAllText);
- }
-
- if (this.options.selectAllName) {
- $('label', $li).prepend('<input type="checkbox" name="' + this.options.selectAllName + '" />');
- }
- else {
- $('label', $li).prepend('<input type="checkbox" />');
- }
-
- var $checkbox = $('input', $li);
- $checkbox.val(this.options.selectAllValue);
-
- $li.addClass("multiselect-item multiselect-all");
- $checkbox.parent().parent()
- .addClass('multiselect-all');
-
- this.$ul.prepend($li);
-
- $checkbox.prop('checked', false);
- }
- },
-
- /**
- * Builds the filter.
- */
- buildFilter: function() {
-
- // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
- if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
- var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);
-
- if (this.$select.find('option').length >= enableFilterLength) {
-
- this.$filter = $(this.options.templates.filter);
- $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
-
- // Adds optional filter clear button
- if(this.options.includeFilterClearBtn) {
- var clearBtn = $(this.options.templates.filterClearBtn);
- clearBtn.on('click', $.proxy(function(event){
- clearTimeout(this.searchTimeout);
-
- this.$filter.find('.multiselect-search').val('');
- $('li', this.$ul).show().removeClass('multiselect-filter-hidden');
-
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- }, this));
- this.$filter.find('.input-group').append(clearBtn);
- }
-
- this.$ul.prepend(this.$filter);
-
- this.$filter.val(this.query).on('click', function(event) {
- event.stopPropagation();
- }).on('input keydown', $.proxy(function(event) {
- // Cancel enter key default behaviour
- if (event.which === 13) {
- event.preventDefault();
- }
-
- // This is useful to catch "keydown" events after the browser has updated the control.
- clearTimeout(this.searchTimeout);
-
- this.searchTimeout = this.asyncFunction($.proxy(function() {
-
- if (this.query !== event.target.value) {
- this.query = event.target.value;
-
- var currentGroup, currentGroupVisible;
- $.each($('li', this.$ul), $.proxy(function(index, element) {
- var value = $('input', element).length > 0 ? $('input', element).val() : "";
- var text = $('label', element).text();
-
- var filterCandidate = '';
- if ((this.options.filterBehavior === 'text')) {
- filterCandidate = text;
- }
- else if ((this.options.filterBehavior === 'value')) {
- filterCandidate = value;
- }
- else if (this.options.filterBehavior === 'both') {
- filterCandidate = text + '\n' + value;
- }
-
- if (value !== this.options.selectAllValue && text) {
-
- // By default lets assume that element is not
- // interesting for this search.
- var showElement = false;
-
- if (this.options.enableCaseInsensitiveFiltering) {
- filterCandidate = filterCandidate.toLowerCase();
- this.query = this.query.toLowerCase();
- }
-
- if (this.options.enableFullValueFiltering && this.options.filterBehavior !== 'both') {
- var valueToMatch = filterCandidate.trim().substring(0, this.query.length);
- if (this.query.indexOf(valueToMatch) > -1) {
- showElement = true;
- }
- }
- else if (filterCandidate.indexOf(this.query) > -1) {
- showElement = true;
- }
-
- // Toggle current element (group or group item) according to showElement boolean.
- $(element).toggle(showElement)
- .toggleClass('multiselect-filter-hidden', !showElement);
-
- // Differentiate groups and group items.
- if ($(element).hasClass('multiselect-group')) {
- // Remember group status.
- currentGroup = element;
- currentGroupVisible = showElement;
- }
- else {
- // Show group name when at least one of its items is visible.
- if (showElement) {
- $(currentGroup).show()
- .removeClass('multiselect-filter-hidden');
- }
-
- // Show all group items when group name satisfies filter.
- if (!showElement && currentGroupVisible) {
- $(element).show()
- .removeClass('multiselect-filter-hidden');
- }
- }
- }
- }, this));
- }
-
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- this.options.onFiltering(event.target);
-
- }, this), 300, this);
- }, this));
- }
- }
- },
-
- /**
- * Unbinds the whole plugin.
- */
- destroy: function() {
- this.$container.remove();
- this.$select.show();
-
- // reset original state
- this.$select.prop('disabled', this.options.wasDisabled);
-
- this.$select.data('multiselect', null);
- },
-
- /**
- * Refreshs the multiselect based on the selected options of the select.
- */
- refresh: function () {
- var inputs = $.map($('li input', this.$ul), $);
-
- $('option', this.$select).each($.proxy(function (index, element) {
- var $elem = $(element);
- var value = $elem.val();
- var $input;
- for (var i = inputs.length; 0 < i--; /**/) {
- if (value !== ($input = inputs[i]).val())
- continue; // wrong li
-
- if ($elem.is(':selected')) {
- $input.prop('checked', true);
-
- if (this.options.selectedClass) {
- $input.closest('li')
- .addClass(this.options.selectedClass);
- }
- }
- else {
- $input.prop('checked', false);
-
- if (this.options.selectedClass) {
- $input.closest('li')
- .removeClass(this.options.selectedClass);
- }
- }
-
- if ($elem.is(":disabled")) {
- $input.attr('disabled', 'disabled')
- .prop('disabled', true)
- .closest('li')
- .addClass('disabled');
- }
- else {
- $input.prop('disabled', false)
- .closest('li')
- .removeClass('disabled');
- }
- break; // assumes unique values
- }
- }, this));
-
- this.updateButtonText();
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
- },
-
- /**
- * Select all options of the given values.
- *
- * If triggerOnChange is set to true, the on change event is triggered if
- * and only if one value is passed.
- *
- * @param {Array} selectValues
- * @param {Boolean} triggerOnChange
- */
- select: function(selectValues, triggerOnChange) {
- if(!$.isArray(selectValues)) {
- selectValues = [selectValues];
- }
-
- for (var i = 0; i < selectValues.length; i++) {
- var value = selectValues[i];
-
- if (value === null || value === undefined) {
- continue;
- }
-
- var $option = this.getOptionByValue(value);
- var $checkbox = this.getInputByValue(value);
-
- if($option === undefined || $checkbox === undefined) {
- continue;
- }
-
- if (!this.options.multiple) {
- this.deselectAll(false);
- }
-
- if (this.options.selectedClass) {
- $checkbox.closest('li')
- .addClass(this.options.selectedClass);
- }
-
- $checkbox.prop('checked', true);
- $option.prop('selected', true);
-
- if (triggerOnChange) {
- this.options.onChange($option, true);
- }
- }
-
- this.updateButtonText();
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
- },
-
- /**
- * Clears all selected items.
- */
- clearSelection: function () {
- this.deselectAll(false);
- this.updateButtonText();
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
- },
-
- /**
- * Deselects all options of the given values.
- *
- * If triggerOnChange is set to true, the on change event is triggered, if
- * and only if one value is passed.
- *
- * @param {Array} deselectValues
- * @param {Boolean} triggerOnChange
- */
- deselect: function(deselectValues, triggerOnChange) {
- if(!$.isArray(deselectValues)) {
- deselectValues = [deselectValues];
- }
-
- for (var i = 0; i < deselectValues.length; i++) {
- var value = deselectValues[i];
-
- if (value === null || value === undefined) {
- continue;
- }
-
- var $option = this.getOptionByValue(value);
- var $checkbox = this.getInputByValue(value);
-
- if($option === undefined || $checkbox === undefined) {
- continue;
- }
-
- if (this.options.selectedClass) {
- $checkbox.closest('li')
- .removeClass(this.options.selectedClass);
- }
-
- $checkbox.prop('checked', false);
- $option.prop('selected', false);
-
- if (triggerOnChange) {
- this.options.onChange($option, false);
- }
- }
-
- this.updateButtonText();
- this.updateSelectAll();
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
- },
-
- /**
- * Selects all enabled & visible options.
- *
- * If justVisible is true or not specified, only visible options are selected.
- *
- * @param {Boolean} justVisible
- * @param {Boolean} triggerOnSelectAll
- */
- selectAll: function (justVisible, triggerOnSelectAll) {
-
- var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
- var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
- var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
-
- if(justVisible) {
- $('input:enabled' , visibleLis).prop('checked', true);
- visibleLis.addClass(this.options.selectedClass);
-
- $('input:enabled' , visibleLis).each($.proxy(function(index, element) {
- var value = $(element).val();
- var option = this.getOptionByValue(value);
- $(option).prop('selected', true);
- }, this));
- }
- else {
- $('input:enabled' , allLis).prop('checked', true);
- allLis.addClass(this.options.selectedClass);
-
- $('input:enabled' , allLis).each($.proxy(function(index, element) {
- var value = $(element).val();
- var option = this.getOptionByValue(value);
- $(option).prop('selected', true);
- }, this));
- }
-
- $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', true);
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- if (triggerOnSelectAll) {
- this.options.onSelectAll();
- }
- },
-
- /**
- * Deselects all options.
- *
- * If justVisible is true or not specified, only visible options are deselected.
- *
- * @param {Boolean} justVisible
- */
- deselectAll: function (justVisible, triggerOnDeselectAll) {
-
- var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
- var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
- var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
-
- if(justVisible) {
- $('input[type="checkbox"]:enabled' , visibleLis).prop('checked', false);
- visibleLis.removeClass(this.options.selectedClass);
-
- $('input[type="checkbox"]:enabled' , visibleLis).each($.proxy(function(index, element) {
- var value = $(element).val();
- var option = this.getOptionByValue(value);
- $(option).prop('selected', false);
- }, this));
- }
- else {
- $('input[type="checkbox"]:enabled' , allLis).prop('checked', false);
- allLis.removeClass(this.options.selectedClass);
-
- $('input[type="checkbox"]:enabled' , allLis).each($.proxy(function(index, element) {
- var value = $(element).val();
- var option = this.getOptionByValue(value);
- $(option).prop('selected', false);
- }, this));
- }
-
- $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', false);
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- if (triggerOnDeselectAll) {
- this.options.onDeselectAll();
- }
- },
-
- /**
- * Rebuild the plugin.
- *
- * Rebuilds the dropdown, the filter and the select all option.
- */
- rebuild: function() {
- this.$ul.html('');
-
- // Important to distinguish between radios and checkboxes.
- this.options.multiple = this.$select.attr('multiple') === "multiple";
-
- this.buildSelectAll();
- this.buildDropdownOptions();
- this.buildFilter();
-
- this.updateButtonText();
- this.updateSelectAll(true);
-
- if (this.options.enableClickableOptGroups && this.options.multiple) {
- this.updateOptGroups();
- }
-
- if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
- this.disable();
- }
- else {
- this.enable();
- }
-
- if (this.options.dropRight) {
- this.$ul.addClass('pull-right');
- }
- },
-
- /**
- * The provided data will be used to build the dropdown.
- */
- dataprovider: function(dataprovider) {
-
- var groupCounter = 0;
- var $select = this.$select.empty();
-
- $.each(dataprovider, function (index, option) {
- var $tag;
-
- if ($.isArray(option.children)) { // create optiongroup tag
- groupCounter++;
-
- $tag = $('<optgroup/>').attr({
- label: option.label || 'Group ' + groupCounter,
- disabled: !!option.disabled
- });
-
- forEach(option.children, function(subOption) { // add children option tags
- var attributes = {
- value: subOption.value,
- label: subOption.label || subOption.value,
- title: subOption.title,
- selected: !!subOption.selected,
- disabled: !!subOption.disabled
- };
-
- //Loop through attributes object and add key-value for each attribute
- for (var key in subOption.attributes) {
- attributes['data-' + key] = subOption.attributes[key];
- }
- //Append original attributes + new data attributes to option
- $tag.append($('<option/>').attr(attributes));
- });
- }
- else {
-
- var attributes = {
- 'value': option.value,
- 'label': option.label || option.value,
- 'title': option.title,
- 'class': option.class,
- 'selected': !!option.selected,
- 'disabled': !!option.disabled
- };
- //Loop through attributes object and add key-value for each attribute
- for (var key in option.attributes) {
- attributes['data-' + key] = option.attributes[key];
- }
- //Append original attributes + new data attributes to option
- $tag = $('<option/>').attr(attributes);
-
- $tag.text(option.label || option.value);
- }
-
- $select.append($tag);
- });
-
- this.rebuild();
- },
-
- /**
- * Enable the multiselect.
- */
- enable: function() {
- this.$select.prop('disabled', false);
- this.$button.prop('disabled', false)
- .removeClass('disabled');
- },
-
- /**
- * Disable the multiselect.
- */
- disable: function() {
- this.$select.prop('disabled', true);
- this.$button.prop('disabled', true)
- .addClass('disabled');
- },
-
- /**
- * Set the options.
- *
- * @param {Array} options
- */
- setOptions: function(options) {
- this.options = this.mergeOptions(options);
- },
-
- /**
- * Merges the given options with the default options.
- *
- * @param {Array} options
- * @returns {Array}
- */
- mergeOptions: function(options) {
- return $.extend(true, {}, this.defaults, this.options, options);
- },
-
- /**
- * Checks whether a select all checkbox is present.
- *
- * @returns {Boolean}
- */
- hasSelectAll: function() {
- return $('li.multiselect-all', this.$ul).length > 0;
- },
-
- /**
- * Update opt groups.
- */
- updateOptGroups: function() {
- var $groups = $('li.multiselect-group', this.$ul)
- var selectedClass = this.options.selectedClass;
-
- $groups.each(function() {
- var $options = $(this).nextUntil('li.multiselect-group')
- .not('.multiselect-filter-hidden')
- .not('.disabled');
-
- var checked = true;
- $options.each(function() {
- var $input = $('input', this);
-
- if (!$input.prop('checked')) {
- checked = false;
- }
- });
-
- if (selectedClass) {
- if (checked) {
- $(this).addClass(selectedClass);
- }
- else {
- $(this).removeClass(selectedClass);
- }
- }
-
- $('input', this).prop('checked', checked);
- });
- },
-
- /**
- * Updates the select all checkbox based on the currently displayed and selected checkboxes.
- */
- updateSelectAll: function(notTriggerOnSelectAll) {
- if (this.hasSelectAll()) {
- var allBoxes = $("li:not(.multiselect-item):not(.multiselect-filter-hidden):not(.multiselect-group):not(.disabled) input:enabled", this.$ul);
- var allBoxesLength = allBoxes.length;
- var checkedBoxesLength = allBoxes.filter(":checked").length;
- var selectAllLi = $("li.multiselect-all", this.$ul);
- var selectAllInput = selectAllLi.find("input");
-
- if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
- selectAllInput.prop("checked", true);
- selectAllLi.addClass(this.options.selectedClass);
- }
- else {
- selectAllInput.prop("checked", false);
- selectAllLi.removeClass(this.options.selectedClass);
- }
- }
- },
-
- /**
- * Update the button text and its title based on the currently selected options.
- */
- updateButtonText: function() {
- var options = this.getSelected();
-
- // First update the displayed button text.
- if (this.options.enableHTML) {
- $('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));
- }
- else {
- $('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));
- }
-
- // Now update the title attribute of the button.
- $('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
- },
-
- /**
- * Get all selected options.
- *
- * @returns {jQUery}
- */
- getSelected: function() {
- return $('option', this.$select).filter(":selected");
- },
-
- /**
- * Gets a select option by its value.
- *
- * @param {String} value
- * @returns {jQuery}
- */
- getOptionByValue: function (value) {
-
- var options = $('option', this.$select);
- var valueToCompare = value.toString();
-
- for (var i = 0; i < options.length; i = i + 1) {
- var option = options[i];
- if (option.value === valueToCompare) {
- return $(option);
- }
- }
- },
-
- /**
- * Get the input (radio/checkbox) by its value.
- *
- * @param {String} value
- * @returns {jQuery}
- */
- getInputByValue: function (value) {
-
- var checkboxes = $('li input:not(.multiselect-search)', this.$ul);
- var valueToCompare = value.toString();
-
- for (var i = 0; i < checkboxes.length; i = i + 1) {
- var checkbox = checkboxes[i];
- if (checkbox.value === valueToCompare) {
- return $(checkbox);
- }
- }
- },
-
- /**
- * Used for knockout integration.
- */
- updateOriginalOptions: function() {
- this.originalOptions = this.$select.clone()[0].options;
- },
-
- asyncFunction: function(callback, timeout, self) {
- var args = Array.prototype.slice.call(arguments, 3);
- return setTimeout(function() {
- callback.apply(self || window, args);
- }, timeout);
- },
-
- setAllSelectedText: function(allSelectedText) {
- this.options.allSelectedText = allSelectedText;
- this.updateButtonText();
- }
- };
-
- $.fn.multiselect = function(option, parameter, extraOptions) {
- return this.each(function() {
- var data = $(this).data('multiselect');
- var options = typeof option === 'object' && option;
-
- // Initialize the multiselect.
- if (!data) {
- data = new Multiselect(this, options);
- $(this).data('multiselect', data);
- }
-
- // Call multiselect method.
- if (typeof option === 'string') {
- data[option](parameter, extraOptions);
-
- if (option === 'destroy') {
- $(this).data('multiselect', false);
- }
- }
- });
- };
-
- $.fn.multiselect.Constructor = Multiselect;
-
- $(function() {
- $("select[data-role=multiselect]").multiselect();
- });
-
-}(window.jQuery);
+/**\r
+ * Bootstrap Multiselect (https://github.com/davidstutz/bootstrap-multiselect)\r
+ *\r
+ * Apache License, Version 2.0:\r
+ * Copyright (c) 2012 - 2015 David Stutz\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a\r
+ * copy of the License at http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations\r
+ * under the License.\r
+ *\r
+ * BSD 3-Clause License:\r
+ * Copyright (c) 2012 - 2015 David Stutz\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ * - Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ * - Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ * - Neither the name of David Stutz nor the names of its contributors may be\r
+ * used to endorse or promote products derived from this software without\r
+ * specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+!function ($) {\r
+ "use strict";// jshint ;_;\r
+\r
+ if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {\r
+ ko.bindingHandlers.multiselect = {\r
+ after: ['options', 'value', 'selectedOptions', 'enable', 'disable'],\r
+\r
+ init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {\r
+ var $element = $(element);\r
+ var config = ko.toJS(valueAccessor());\r
+\r
+ $element.multiselect(config);\r
+\r
+ if (allBindings.has('options')) {\r
+ var options = allBindings.get('options');\r
+ if (ko.isObservable(options)) {\r
+ ko.computed({\r
+ read: function() {\r
+ options();\r
+ setTimeout(function() {\r
+ var ms = $element.data('multiselect');\r
+ if (ms)\r
+ ms.updateOriginalOptions();//Not sure how beneficial this is.\r
+ $element.multiselect('rebuild');\r
+ }, 1);\r
+ },\r
+ disposeWhenNodeIsRemoved: element\r
+ });\r
+ }\r
+ }\r
+\r
+ //value and selectedOptions are two-way, so these will be triggered even by our own actions.\r
+ //It needs some way to tell if they are triggered because of us or because of outside change.\r
+ //It doesn't loop but it's a waste of processing.\r
+ if (allBindings.has('value')) {\r
+ var value = allBindings.get('value');\r
+ if (ko.isObservable(value)) {\r
+ ko.computed({\r
+ read: function() {\r
+ value();\r
+ setTimeout(function() {\r
+ $element.multiselect('refresh');\r
+ }, 1);\r
+ },\r
+ disposeWhenNodeIsRemoved: element\r
+ }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\r
+ }\r
+ }\r
+\r
+ //Switched from arrayChange subscription to general subscription using 'refresh'.\r
+ //Not sure performance is any better using 'select' and 'deselect'.\r
+ if (allBindings.has('selectedOptions')) {\r
+ var selectedOptions = allBindings.get('selectedOptions');\r
+ if (ko.isObservable(selectedOptions)) {\r
+ ko.computed({\r
+ read: function() {\r
+ selectedOptions();\r
+ setTimeout(function() {\r
+ $element.multiselect('refresh');\r
+ }, 1);\r
+ },\r
+ disposeWhenNodeIsRemoved: element\r
+ }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\r
+ }\r
+ }\r
+\r
+ var setEnabled = function (enable) {\r
+ setTimeout(function () {\r
+ if (enable)\r
+ $element.multiselect('enable');\r
+ else\r
+ $element.multiselect('disable');\r
+ });\r
+ };\r
+\r
+ if (allBindings.has('enable')) {\r
+ var enable = allBindings.get('enable');\r
+ if (ko.isObservable(enable)) {\r
+ ko.computed({\r
+ read: function () {\r
+ setEnabled(enable());\r
+ },\r
+ disposeWhenNodeIsRemoved: element\r
+ }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\r
+ } else {\r
+ setEnabled(enable);\r
+ }\r
+ }\r
+\r
+ if (allBindings.has('disable')) {\r
+ var disable = allBindings.get('disable');\r
+ if (ko.isObservable(disable)) {\r
+ ko.computed({\r
+ read: function () {\r
+ setEnabled(!disable());\r
+ },\r
+ disposeWhenNodeIsRemoved: element\r
+ }).extend({ rateLimit: 100, notifyWhenChangesStop: true });\r
+ } else {\r
+ setEnabled(!disable);\r
+ }\r
+ }\r
+\r
+ ko.utils.domNodeDisposal.addDisposeCallback(element, function() {\r
+ $element.multiselect('destroy');\r
+ });\r
+ },\r
+\r
+ update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {\r
+ var $element = $(element);\r
+ var config = ko.toJS(valueAccessor());\r
+\r
+ $element.multiselect('setOptions', config);\r
+ $element.multiselect('rebuild');\r
+ }\r
+ };\r
+ }\r
+\r
+ function forEach(array, callback) {\r
+ for (var index = 0; index < array.length; ++index) {\r
+ callback(array[index], index);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Constructor to create a new multiselect using the given select.\r
+ *\r
+ * @param {jQuery} select\r
+ * @param {Object} options\r
+ * @returns {Multiselect}\r
+ */\r
+ function Multiselect(select, options) {\r
+\r
+ this.$select = $(select);\r
+ this.options = this.mergeOptions($.extend({}, options, this.$select.data()));\r
+\r
+ // Placeholder via data attributes\r
+ if (this.$select.attr("data-placeholder")) {\r
+ this.options.nonSelectedText = this.$select.data("placeholder");\r
+ }\r
+\r
+ // Initialization.\r
+ // We have to clone to create a new reference.\r
+ this.originalOptions = this.$select.clone()[0].options;\r
+ this.query = '';\r
+ this.searchTimeout = null;\r
+ this.lastToggledInput = null;\r
+\r
+ this.options.multiple = this.$select.attr('multiple') === "multiple";\r
+ this.options.onChange = $.proxy(this.options.onChange, this);\r
+ this.options.onSelectAll = $.proxy(this.options.onSelectAll, this);\r
+ this.options.onDeselectAll = $.proxy(this.options.onDeselectAll, this);\r
+ this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);\r
+ this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);\r
+ this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this);\r
+ this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this);\r
+ this.options.onInitialized = $.proxy(this.options.onInitialized, this);\r
+ this.options.onFiltering = $.proxy(this.options.onFiltering, this);\r
+\r
+ // Build select all if enabled.\r
+ this.buildContainer();\r
+ this.buildButton();\r
+ this.buildDropdown();\r
+ this.buildSelectAll();\r
+ this.buildDropdownOptions();\r
+ this.buildFilter();\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll(true);\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ this.options.wasDisabled = this.$select.prop('disabled');\r
+ if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {\r
+ this.disable();\r
+ }\r
+\r
+ this.$select.wrap('<span class="multiselect-native-select" />').after(this.$container);\r
+ this.options.onInitialized(this.$select, this.$container);\r
+ }\r
+\r
+ Multiselect.prototype = {\r
+\r
+ defaults: {\r
+ /**\r
+ * Default text function will either print 'None selected' in case no\r
+ * option is selected or a list of the selected options up to a length\r
+ * of 3 selected options.\r
+ *\r
+ * @param {jQuery} options\r
+ * @param {jQuery} select\r
+ * @returns {String}\r
+ */\r
+ buttonText: function(options, select) {\r
+ if (this.disabledText.length > 0\r
+ && (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) {\r
+\r
+ return this.disabledText;\r
+ }\r
+ else if (options.length === 0) {\r
+ return this.nonSelectedText;\r
+ }\r
+ else if (this.allSelectedText\r
+ && options.length === $('option', $(select)).length\r
+ && $('option', $(select)).length !== 1\r
+ && this.multiple) {\r
+\r
+ if (this.selectAllNumber) {\r
+ return this.allSelectedText + ' (' + options.length + ')';\r
+ }\r
+ else {\r
+ return this.allSelectedText;\r
+ }\r
+ }\r
+ else if (options.length > this.numberDisplayed) {\r
+ return options.length + ' ' + this.nSelectedText;\r
+ }\r
+ else {\r
+ var selected = '';\r
+ var delimiter = this.delimiterText;\r
+\r
+ options.each(function() {\r
+ var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();\r
+ selected += label + delimiter;\r
+ });\r
+\r
+ return selected.substr(0, selected.length - this.delimiterText.length);\r
+ }\r
+ },\r
+ /**\r
+ * Updates the title of the button similar to the buttonText function.\r
+ *\r
+ * @param {jQuery} options\r
+ * @param {jQuery} select\r
+ * @returns {@exp;selected@call;substr}\r
+ */\r
+ buttonTitle: function(options, select) {\r
+ if (options.length === 0) {\r
+ return this.nonSelectedText;\r
+ }\r
+ else {\r
+ var selected = '';\r
+ var delimiter = this.delimiterText;\r
+\r
+ options.each(function () {\r
+ var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();\r
+ selected += label + delimiter;\r
+ });\r
+ return selected.substr(0, selected.length - this.delimiterText.length);\r
+ }\r
+ },\r
+ checkboxName: function(option) {\r
+ return false; // no checkbox name\r
+ },\r
+ /**\r
+ * Create a label.\r
+ *\r
+ * @param {jQuery} element\r
+ * @returns {String}\r
+ */\r
+ optionLabel: function(element){\r
+ return $(element).attr('label') || $(element).text();\r
+ },\r
+ /**\r
+ * Create a class.\r
+ *\r
+ * @param {jQuery} element\r
+ * @returns {String}\r
+ */\r
+ optionClass: function(element) {\r
+ return $(element).attr('class') || '';\r
+ },\r
+ /**\r
+ * Triggered on change of the multiselect.\r
+ *\r
+ * Not triggered when selecting/deselecting options manually.\r
+ *\r
+ * @param {jQuery} option\r
+ * @param {Boolean} checked\r
+ */\r
+ onChange : function(option, checked) {\r
+\r
+ },\r
+ /**\r
+ * Triggered when the dropdown is shown.\r
+ *\r
+ * @param {jQuery} event\r
+ */\r
+ onDropdownShow: function(event) {\r
+\r
+ },\r
+ /**\r
+ * Triggered when the dropdown is hidden.\r
+ *\r
+ * @param {jQuery} event\r
+ */\r
+ onDropdownHide: function(event) {\r
+\r
+ },\r
+ /**\r
+ * Triggered after the dropdown is shown.\r
+ *\r
+ * @param {jQuery} event\r
+ */\r
+ onDropdownShown: function(event) {\r
+\r
+ },\r
+ /**\r
+ * Triggered after the dropdown is hidden.\r
+ *\r
+ * @param {jQuery} event\r
+ */\r
+ onDropdownHidden: function(event) {\r
+\r
+ },\r
+ /**\r
+ * Triggered on select all.\r
+ */\r
+ onSelectAll: function() {\r
+\r
+ },\r
+ /**\r
+ * Triggered on deselect all.\r
+ */\r
+ onDeselectAll: function() {\r
+\r
+ },\r
+ /**\r
+ * Triggered after initializing.\r
+ *\r
+ * @param {jQuery} $select\r
+ * @param {jQuery} $container\r
+ */\r
+ onInitialized: function($select, $container) {\r
+\r
+ },\r
+ /**\r
+ * Triggered on filtering.\r
+ *\r
+ * @param {jQuery} $filter\r
+ */\r
+ onFiltering: function($filter) {\r
+\r
+ },\r
+ enableHTML: false,\r
+ buttonClass: 'btn btn-default',\r
+ inheritClass: false,\r
+ buttonWidth: 'auto',\r
+ buttonContainer: '<div class="btn-group" />',\r
+ dropRight: false,\r
+ dropUp: false,\r
+ selectedClass: 'active',\r
+ // Maximum height of the dropdown menu.\r
+ // If maximum height is exceeded a scrollbar will be displayed.\r
+ maxHeight: false,\r
+ includeSelectAllOption: false,\r
+ includeSelectAllIfMoreThan: 0,\r
+ selectAllText: ' Select all',\r
+ selectAllValue: 'multiselect-all',\r
+ selectAllName: false,\r
+ selectAllNumber: true,\r
+ selectAllJustVisible: true,\r
+ enableFiltering: false,\r
+ enableCaseInsensitiveFiltering: false,\r
+ enableFullValueFiltering: false,\r
+ enableClickableOptGroups: false,\r
+ enableCollapsibleOptGroups: false,\r
+ filterPlaceholder: 'Search',\r
+ // possible options: 'text', 'value', 'both'\r
+ filterBehavior: 'text',\r
+ includeFilterClearBtn: true,\r
+ preventInputChangeEvent: false,\r
+ nonSelectedText: 'None selected',\r
+ nSelectedText: 'selected',\r
+ allSelectedText: 'All selected',\r
+ numberDisplayed: 3,\r
+ disableIfEmpty: false,\r
+ disabledText: '',\r
+ delimiterText: ', ',\r
+ templates: {\r
+ button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span> <b class="caret"></b></button>',\r
+ ul: '<ul class="multiselect-container dropdown-menu"></ul>',\r
+ filter: '<li class="multiselect-item multiselect-filter"><div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div></li>',\r
+ filterClearBtn: '<span class="input-group-btn"><button class="btn btn-default multiselect-clear-filter" type="button"><i class="glyphicon glyphicon-remove-circle"></i></button></span>',\r
+ li: '<li><a tabindex="0"><label></label></a></li>',\r
+ divider: '<li class="multiselect-item divider"></li>',\r
+ liGroup: '<li class="multiselect-item multiselect-group"><label></label></li>'\r
+ }\r
+ },\r
+\r
+ constructor: Multiselect,\r
+\r
+ /**\r
+ * Builds the container of the multiselect.\r
+ */\r
+ buildContainer: function() {\r
+ this.$container = $(this.options.buttonContainer);\r
+ this.$container.on('show.bs.dropdown', this.options.onDropdownShow);\r
+ this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);\r
+ this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);\r
+ this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);\r
+ },\r
+\r
+ /**\r
+ * Builds the button of the multiselect.\r
+ */\r
+ buildButton: function() {\r
+ this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);\r
+ if (this.$select.attr('class') && this.options.inheritClass) {\r
+ this.$button.addClass(this.$select.attr('class'));\r
+ }\r
+ // Adopt active state.\r
+ if (this.$select.prop('disabled')) {\r
+ this.disable();\r
+ }\r
+ else {\r
+ this.enable();\r
+ }\r
+\r
+ // Manually add button width if set.\r
+ if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {\r
+ this.$button.css({\r
+ 'width' : '100%', //this.options.buttonWidth,\r
+ 'overflow' : 'hidden',\r
+ 'text-overflow' : 'ellipsis'\r
+ });\r
+ this.$container.css({\r
+ 'width': this.options.buttonWidth\r
+ });\r
+ }\r
+\r
+ // Keep the tab index from the select.\r
+ var tabindex = this.$select.attr('tabindex');\r
+ if (tabindex) {\r
+ this.$button.attr('tabindex', tabindex);\r
+ }\r
+\r
+ this.$container.prepend(this.$button);\r
+ },\r
+\r
+ /**\r
+ * Builds the ul representing the dropdown menu.\r
+ */\r
+ buildDropdown: function() {\r
+\r
+ // Build ul.\r
+ this.$ul = $(this.options.templates.ul);\r
+\r
+ if (this.options.dropRight) {\r
+ this.$ul.addClass('pull-right');\r
+ }\r
+\r
+ // Set max height of dropdown menu to activate auto scrollbar.\r
+ if (this.options.maxHeight) {\r
+ // TODO: Add a class for this option to move the css declarations.\r
+ this.$ul.css({\r
+ 'max-height': this.options.maxHeight + 'px',\r
+ 'overflow-y': 'auto',\r
+ 'overflow-x': 'hidden'\r
+ });\r
+ }\r
+\r
+ if (this.options.dropUp) {\r
+\r
+ var height = Math.min(this.options.maxHeight, $('option[data-role!="divider"]', this.$select).length*26 + $('option[data-role="divider"]', this.$select).length*19 + (this.options.includeSelectAllOption ? 26 : 0) + (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering ? 44 : 0));\r
+ var moveCalc = height + 34;\r
+\r
+ this.$ul.css({\r
+ 'max-height': height + 'px',\r
+ 'overflow-y': 'auto',\r
+ 'overflow-x': 'hidden',\r
+ 'margin-top': "-" + moveCalc + 'px'\r
+ });\r
+ }\r
+\r
+ this.$container.append(this.$ul);\r
+ },\r
+\r
+ /**\r
+ * Build the dropdown options and binds all necessary events.\r
+ *\r
+ * Uses createDivider and createOptionValue to create the necessary options.\r
+ */\r
+ buildDropdownOptions: function() {\r
+\r
+ this.$select.children().each($.proxy(function(index, element) {\r
+\r
+ var $element = $(element);\r
+ // Support optgroups and options without a group simultaneously.\r
+ var tag = $element.prop('tagName')\r
+ .toLowerCase();\r
+\r
+ if ($element.prop('value') === this.options.selectAllValue) {\r
+ return;\r
+ }\r
+\r
+ if (tag === 'optgroup') {\r
+ this.createOptgroup(element);\r
+ }\r
+ else if (tag === 'option') {\r
+\r
+ if ($element.data('role') === 'divider') {\r
+ this.createDivider();\r
+ }\r
+ else {\r
+ this.createOptionValue(element);\r
+ }\r
+\r
+ }\r
+\r
+ // Other illegal tags will be ignored.\r
+ }, this));\r
+\r
+ // Bind the change event on the dropdown elements.\r
+ $('li:not(.multiselect-group) input', this.$ul).on('change', $.proxy(function(event) {\r
+ var $target = $(event.target);\r
+\r
+ var checked = $target.prop('checked') || false;\r
+ var isSelectAllOption = $target.val() === this.options.selectAllValue;\r
+\r
+ // Apply or unapply the configured selected class.\r
+ if (this.options.selectedClass) {\r
+ if (checked) {\r
+ $target.closest('li')\r
+ .addClass(this.options.selectedClass);\r
+ }\r
+ else {\r
+ $target.closest('li')\r
+ .removeClass(this.options.selectedClass);\r
+ }\r
+ }\r
+\r
+ // Get the corresponding option.\r
+ var value = $target.val();\r
+ var $option = this.getOptionByValue(value);\r
+\r
+ var $optionsNotThis = $('option', this.$select).not($option);\r
+ var $checkboxesNotThis = $('input', this.$container).not($target);\r
+\r
+ if (isSelectAllOption) {\r
+\r
+ if (checked) {\r
+ this.selectAll(this.options.selectAllJustVisible, true);\r
+ }\r
+ else {\r
+ this.deselectAll(this.options.selectAllJustVisible, true);\r
+ }\r
+ }\r
+ else {\r
+ if (checked) {\r
+ $option.prop('selected', true);\r
+\r
+ if (this.options.multiple) {\r
+ // Simply select additional option.\r
+ $option.prop('selected', true);\r
+ }\r
+ else {\r
+ // Unselect all other options and corresponding checkboxes.\r
+ if (this.options.selectedClass) {\r
+ $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass);\r
+ }\r
+\r
+ $($checkboxesNotThis).prop('checked', false);\r
+ $optionsNotThis.prop('selected', false);\r
+\r
+ // It's a single selection, so close.\r
+ this.$button.click();\r
+ }\r
+\r
+ if (this.options.selectedClass === "active") {\r
+ $optionsNotThis.closest("a").css("outline", "");\r
+ }\r
+ }\r
+ else {\r
+ // Unselect option.\r
+ $option.prop('selected', false);\r
+ }\r
+\r
+ // To prevent select all from firing onChange: #575\r
+ this.options.onChange($option, checked);\r
+\r
+ // Do not update select all or optgroups on select all change!\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+ }\r
+\r
+ this.$select.change();\r
+ this.updateButtonText();\r
+\r
+ if(this.options.preventInputChangeEvent) {\r
+ return false;\r
+ }\r
+ }, this));\r
+\r
+ $('li a', this.$ul).on('mousedown', function(e) {\r
+ if (e.shiftKey) {\r
+ // Prevent selecting text by Shift+click\r
+ return false;\r
+ }\r
+ });\r
+\r
+ $('li a', this.$ul).on('touchstart click', $.proxy(function(event) {\r
+ event.stopPropagation();\r
+\r
+ var $target = $(event.target);\r
+\r
+ if (event.shiftKey && this.options.multiple) {\r
+ if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)\r
+ event.preventDefault();\r
+ $target = $target.find("input");\r
+ $target.prop("checked", !$target.prop("checked"));\r
+ }\r
+ var checked = $target.prop('checked') || false;\r
+\r
+ if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range\r
+ var from = $target.closest("li").index();\r
+ var to = this.lastToggledInput.closest("li").index();\r
+\r
+ if (from > to) { // Swap the indices\r
+ var tmp = to;\r
+ to = from;\r
+ from = tmp;\r
+ }\r
+\r
+ // Make sure we grab all elements since slice excludes the last index\r
+ ++to;\r
+\r
+ // Change the checkboxes and underlying options\r
+ var range = this.$ul.find("li").slice(from, to).find("input");\r
+\r
+ range.prop('checked', checked);\r
+\r
+ if (this.options.selectedClass) {\r
+ range.closest('li')\r
+ .toggleClass(this.options.selectedClass, checked);\r
+ }\r
+\r
+ for (var i = 0, j = range.length; i < j; i++) {\r
+ var $checkbox = $(range[i]);\r
+\r
+ var $option = this.getOptionByValue($checkbox.val());\r
+\r
+ $option.prop('selected', checked);\r
+ }\r
+ }\r
+\r
+ // Trigger the select "change" event\r
+ $target.trigger("change");\r
+ }\r
+\r
+ // Remembers last clicked option\r
+ if($target.is("input") && !$target.closest("li").is(".multiselect-item")){\r
+ this.lastToggledInput = $target;\r
+ }\r
+\r
+ $target.blur();\r
+ }, this));\r
+\r
+ // Keyboard support.\r
+ this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {\r
+ if ($('input[type="text"]', this.$container).is(':focus')) {\r
+ return;\r
+ }\r
+\r
+ if (event.keyCode === 9 && this.$container.hasClass('open')) {\r
+ this.$button.click();\r
+ }\r
+ else {\r
+ var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible");\r
+\r
+ if (!$items.length) {\r
+ return;\r
+ }\r
+\r
+ var index = $items.index($items.filter(':focus'));\r
+\r
+ // Navigation up.\r
+ if (event.keyCode === 38 && index > 0) {\r
+ index--;\r
+ }\r
+ // Navigate down.\r
+ else if (event.keyCode === 40 && index < $items.length - 1) {\r
+ index++;\r
+ }\r
+ else if (!~index) {\r
+ index = 0;\r
+ }\r
+\r
+ var $current = $items.eq(index);\r
+ $current.focus();\r
+\r
+ if (event.keyCode === 32 || event.keyCode === 13) {\r
+ var $checkbox = $current.find('input');\r
+\r
+ $checkbox.prop("checked", !$checkbox.prop("checked"));\r
+ $checkbox.change();\r
+ }\r
+\r
+ event.stopPropagation();\r
+ event.preventDefault();\r
+ }\r
+ }, this));\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ $("li.multiselect-group input", this.$ul).on("change", $.proxy(function(event) {\r
+ event.stopPropagation();\r
+\r
+ var $target = $(event.target);\r
+ var checked = $target.prop('checked') || false;\r
+\r
+ var $li = $(event.target).closest('li');\r
+ var $group = $li.nextUntil("li.multiselect-group")\r
+ .not('.multiselect-filter-hidden')\r
+ .not('.disabled');\r
+\r
+ var $inputs = $group.find("input");\r
+\r
+ var values = [];\r
+ var $options = [];\r
+\r
+ if (this.options.selectedClass) {\r
+ if (checked) {\r
+ $li.addClass(this.options.selectedClass);\r
+ }\r
+ else {\r
+ $li.removeClass(this.options.selectedClass);\r
+ }\r
+ }\r
+\r
+ $.each($inputs, $.proxy(function(index, input) {\r
+ var value = $(input).val();\r
+ var $option = this.getOptionByValue(value);\r
+\r
+ if (checked) {\r
+ $(input).prop('checked', true);\r
+ $(input).closest('li')\r
+ .addClass(this.options.selectedClass);\r
+\r
+ $option.prop('selected', true);\r
+ }\r
+ else {\r
+ $(input).prop('checked', false);\r
+ $(input).closest('li')\r
+ .removeClass(this.options.selectedClass);\r
+\r
+ $option.prop('selected', false);\r
+ }\r
+\r
+ $options.push(this.getOptionByValue(value));\r
+ }, this))\r
+\r
+ // Cannot use select or deselect here because it would call updateOptGroups again.\r
+\r
+ this.options.onChange($options, checked);\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll();\r
+ }, this));\r
+ }\r
+\r
+ if (this.options.enableCollapsibleOptGroups && this.options.multiple) {\r
+ $("li.multiselect-group .caret-container", this.$ul).on("click", $.proxy(function(event) {\r
+ var $li = $(event.target).closest('li');\r
+ var $inputs = $li.nextUntil("li.multiselect-group")\r
+ .not('.multiselect-filter-hidden');\r
+\r
+ var visible = true;\r
+ $inputs.each(function() {\r
+ visible = visible && $(this).is(':visible');\r
+ });\r
+\r
+ if (visible) {\r
+ $inputs.hide()\r
+ .addClass('multiselect-collapsible-hidden');\r
+ }\r
+ else {\r
+ $inputs.show()\r
+ .removeClass('multiselect-collapsible-hidden');\r
+ }\r
+ }, this));\r
+\r
+ $("li.multiselect-all", this.$ul).css('background', '#f3f3f3').css('border-bottom', '1px solid #eaeaea');\r
+ $("li.multiselect-all > a > label.checkbox", this.$ul).css('padding', '3px 20px 3px 35px');\r
+ $("li.multiselect-group > a > input", this.$ul).css('margin', '4px 0px 5px -20px');\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Create an option using the given select option.\r
+ *\r
+ * @param {jQuery} element\r
+ */\r
+ createOptionValue: function(element) {\r
+ var $element = $(element);\r
+ if ($element.is(':selected')) {\r
+ $element.prop('selected', true);\r
+ }\r
+\r
+ // Support the label attribute on options.\r
+ var label = this.options.optionLabel(element);\r
+ var classes = this.options.optionClass(element);\r
+ var value = $element.val();\r
+ var inputType = this.options.multiple ? "checkbox" : "radio";\r
+\r
+ var $li = $(this.options.templates.li);\r
+ var $label = $('label', $li);\r
+ $label.addClass(inputType);\r
+ $li.addClass(classes);\r
+\r
+ if (this.options.enableHTML) {\r
+ $label.html(" " + label);\r
+ }\r
+ else {\r
+ $label.text(" " + label);\r
+ }\r
+\r
+ var $checkbox = $('<input/>').attr('type', inputType);\r
+\r
+ var name = this.options.checkboxName($element);\r
+ if (name) {\r
+ $checkbox.attr('name', name);\r
+ }\r
+\r
+ $label.prepend($checkbox);\r
+\r
+ var selected = $element.prop('selected') || false;\r
+ $checkbox.val(value);\r
+\r
+ if (value === this.options.selectAllValue) {\r
+ $li.addClass("multiselect-item multiselect-all");\r
+ $checkbox.parent().parent()\r
+ .addClass('multiselect-all');\r
+ }\r
+\r
+ $label.attr('title', $element.attr('title'));\r
+\r
+ this.$ul.append($li);\r
+\r
+ if ($element.is(':disabled')) {\r
+ $checkbox.attr('disabled', 'disabled')\r
+ .prop('disabled', true)\r
+ .closest('a')\r
+ .attr("tabindex", "-1")\r
+ .closest('li')\r
+ .addClass('disabled');\r
+ }\r
+\r
+ $checkbox.prop('checked', selected);\r
+\r
+ if (selected && this.options.selectedClass) {\r
+ $checkbox.closest('li')\r
+ .addClass(this.options.selectedClass);\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Creates a divider using the given select option.\r
+ *\r
+ * @param {jQuery} element\r
+ */\r
+ createDivider: function(element) {\r
+ var $divider = $(this.options.templates.divider);\r
+ this.$ul.append($divider);\r
+ },\r
+\r
+ /**\r
+ * Creates an optgroup.\r
+ *\r
+ * @param {jQuery} group\r
+ */\r
+ createOptgroup: function(group) {\r
+ var label = $(group).attr("label");\r
+ var value = $(group).attr("value");\r
+ var $li = $('<li class="multiselect-item multiselect-group"><a href="javascript:void(0);"><label><b></b></label></a></li>');\r
+\r
+ var classes = this.options.optionClass(group);\r
+ $li.addClass(classes);\r
+\r
+ if (this.options.enableHTML) {\r
+ $('label b', $li).html(" " + label);\r
+ }\r
+ else {\r
+ $('label b', $li).text(" " + label);\r
+ }\r
+\r
+ if (this.options.enableCollapsibleOptGroups && this.options.multiple) {\r
+ $('a', $li).append('<span class="caret-container"><b class="caret"></b></span>');\r
+ }\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ $('a label', $li).prepend('<input type="checkbox" value="' + value + '"/>');\r
+ }\r
+\r
+ if ($(group).is(':disabled')) {\r
+ $li.addClass('disabled');\r
+ }\r
+\r
+ this.$ul.append($li);\r
+\r
+ $("option", group).each($.proxy(function($, group) {\r
+ this.createOptionValue(group);\r
+ }, this))\r
+ },\r
+\r
+ /**\r
+ * Build the select all.\r
+ *\r
+ * Checks if a select all has already been created.\r
+ */\r
+ buildSelectAll: function() {\r
+ if (typeof this.options.selectAllValue === 'number') {\r
+ this.options.selectAllValue = this.options.selectAllValue.toString();\r
+ }\r
+\r
+ var alreadyHasSelectAll = this.hasSelectAll();\r
+\r
+ if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple\r
+ && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {\r
+\r
+ // Check whether to add a divider after the select all.\r
+ if (this.options.includeSelectAllDivider) {\r
+ this.$ul.prepend($(this.options.templates.divider));\r
+ }\r
+\r
+ var $li = $(this.options.templates.li);\r
+ $('label', $li).addClass("checkbox");\r
+\r
+ if (this.options.enableHTML) {\r
+ $('label', $li).html(" " + this.options.selectAllText);\r
+ }\r
+ else {\r
+ $('label', $li).text(" " + this.options.selectAllText);\r
+ }\r
+\r
+ if (this.options.selectAllName) {\r
+ $('label', $li).prepend('<input type="checkbox" name="' + this.options.selectAllName + '" />');\r
+ }\r
+ else {\r
+ $('label', $li).prepend('<input type="checkbox" />');\r
+ }\r
+\r
+ var $checkbox = $('input', $li);\r
+ $checkbox.val(this.options.selectAllValue);\r
+\r
+ $li.addClass("multiselect-item multiselect-all");\r
+ $checkbox.parent().parent()\r
+ .addClass('multiselect-all');\r
+\r
+ this.$ul.prepend($li);\r
+\r
+ $checkbox.prop('checked', false);\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Builds the filter.\r
+ */\r
+ buildFilter: function() {\r
+\r
+ // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.\r
+ if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {\r
+ var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);\r
+\r
+ if (this.$select.find('option').length >= enableFilterLength) {\r
+\r
+ this.$filter = $(this.options.templates.filter);\r
+ $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);\r
+\r
+ // Adds optional filter clear button\r
+ if(this.options.includeFilterClearBtn) {\r
+ var clearBtn = $(this.options.templates.filterClearBtn);\r
+ clearBtn.on('click', $.proxy(function(event){\r
+ clearTimeout(this.searchTimeout);\r
+\r
+ this.$filter.find('.multiselect-search').val('');\r
+ $('li', this.$ul).show().removeClass('multiselect-filter-hidden');\r
+\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ }, this));\r
+ this.$filter.find('.input-group').append(clearBtn);\r
+ }\r
+\r
+ this.$ul.prepend(this.$filter);\r
+\r
+ this.$filter.val(this.query).on('click', function(event) {\r
+ event.stopPropagation();\r
+ }).on('input keydown', $.proxy(function(event) {\r
+ // Cancel enter key default behaviour\r
+ if (event.which === 13) {\r
+ event.preventDefault();\r
+ }\r
+\r
+ // This is useful to catch "keydown" events after the browser has updated the control.\r
+ clearTimeout(this.searchTimeout);\r
+\r
+ this.searchTimeout = this.asyncFunction($.proxy(function() {\r
+\r
+ if (this.query !== event.target.value) {\r
+ this.query = event.target.value;\r
+\r
+ var currentGroup, currentGroupVisible;\r
+ $.each($('li', this.$ul), $.proxy(function(index, element) {\r
+ var value = $('input', element).length > 0 ? $('input', element).val() : "";\r
+ var text = $('label', element).text();\r
+\r
+ var filterCandidate = '';\r
+ if ((this.options.filterBehavior === 'text')) {\r
+ filterCandidate = text;\r
+ }\r
+ else if ((this.options.filterBehavior === 'value')) {\r
+ filterCandidate = value;\r
+ }\r
+ else if (this.options.filterBehavior === 'both') {\r
+ filterCandidate = text + '\n' + value;\r
+ }\r
+\r
+ if (value !== this.options.selectAllValue && text) {\r
+\r
+ // By default lets assume that element is not\r
+ // interesting for this search.\r
+ var showElement = false;\r
+\r
+ if (this.options.enableCaseInsensitiveFiltering) {\r
+ filterCandidate = filterCandidate.toLowerCase();\r
+ this.query = this.query.toLowerCase();\r
+ }\r
+\r
+ if (this.options.enableFullValueFiltering && this.options.filterBehavior !== 'both') {\r
+ var valueToMatch = filterCandidate.trim().substring(0, this.query.length);\r
+ if (this.query.indexOf(valueToMatch) > -1) {\r
+ showElement = true;\r
+ }\r
+ }\r
+ else if (filterCandidate.indexOf(this.query) > -1) {\r
+ showElement = true;\r
+ }\r
+\r
+ // Toggle current element (group or group item) according to showElement boolean.\r
+ $(element).toggle(showElement)\r
+ .toggleClass('multiselect-filter-hidden', !showElement);\r
+\r
+ // Differentiate groups and group items.\r
+ if ($(element).hasClass('multiselect-group')) {\r
+ // Remember group status.\r
+ currentGroup = element;\r
+ currentGroupVisible = showElement;\r
+ }\r
+ else {\r
+ // Show group name when at least one of its items is visible.\r
+ if (showElement) {\r
+ $(currentGroup).show()\r
+ .removeClass('multiselect-filter-hidden');\r
+ }\r
+\r
+ // Show all group items when group name satisfies filter.\r
+ if (!showElement && currentGroupVisible) {\r
+ $(element).show()\r
+ .removeClass('multiselect-filter-hidden');\r
+ }\r
+ }\r
+ }\r
+ }, this));\r
+ }\r
+\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ this.options.onFiltering(event.target);\r
+\r
+ }, this), 300, this);\r
+ }, this));\r
+ }\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Unbinds the whole plugin.\r
+ */\r
+ destroy: function() {\r
+ this.$container.remove();\r
+ this.$select.show();\r
+\r
+ // reset original state\r
+ this.$select.prop('disabled', this.options.wasDisabled);\r
+\r
+ this.$select.data('multiselect', null);\r
+ },\r
+\r
+ /**\r
+ * Refreshs the multiselect based on the selected options of the select.\r
+ */\r
+ refresh: function () {\r
+ var inputs = $.map($('li input', this.$ul), $);\r
+\r
+ $('option', this.$select).each($.proxy(function (index, element) {\r
+ var $elem = $(element);\r
+ var value = $elem.val();\r
+ var $input;\r
+ for (var i = inputs.length; 0 < i--; /**/) {\r
+ if (value !== ($input = inputs[i]).val())\r
+ continue; // wrong li\r
+\r
+ if ($elem.is(':selected')) {\r
+ $input.prop('checked', true);\r
+\r
+ if (this.options.selectedClass) {\r
+ $input.closest('li')\r
+ .addClass(this.options.selectedClass);\r
+ }\r
+ }\r
+ else {\r
+ $input.prop('checked', false);\r
+\r
+ if (this.options.selectedClass) {\r
+ $input.closest('li')\r
+ .removeClass(this.options.selectedClass);\r
+ }\r
+ }\r
+\r
+ if ($elem.is(":disabled")) {\r
+ $input.attr('disabled', 'disabled')\r
+ .prop('disabled', true)\r
+ .closest('li')\r
+ .addClass('disabled');\r
+ }\r
+ else {\r
+ $input.prop('disabled', false)\r
+ .closest('li')\r
+ .removeClass('disabled');\r
+ }\r
+ break; // assumes unique values\r
+ }\r
+ }, this));\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Select all options of the given values.\r
+ *\r
+ * If triggerOnChange is set to true, the on change event is triggered if\r
+ * and only if one value is passed.\r
+ *\r
+ * @param {Array} selectValues\r
+ * @param {Boolean} triggerOnChange\r
+ */\r
+ select: function(selectValues, triggerOnChange) {\r
+ if(!$.isArray(selectValues)) {\r
+ selectValues = [selectValues];\r
+ }\r
+\r
+ for (var i = 0; i < selectValues.length; i++) {\r
+ var value = selectValues[i];\r
+\r
+ if (value === null || value === undefined) {\r
+ continue;\r
+ }\r
+\r
+ var $option = this.getOptionByValue(value);\r
+ var $checkbox = this.getInputByValue(value);\r
+\r
+ if($option === undefined || $checkbox === undefined) {\r
+ continue;\r
+ }\r
+\r
+ if (!this.options.multiple) {\r
+ this.deselectAll(false);\r
+ }\r
+\r
+ if (this.options.selectedClass) {\r
+ $checkbox.closest('li')\r
+ .addClass(this.options.selectedClass);\r
+ }\r
+\r
+ $checkbox.prop('checked', true);\r
+ $option.prop('selected', true);\r
+\r
+ if (triggerOnChange) {\r
+ this.options.onChange($option, true);\r
+ }\r
+ }\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Clears all selected items.\r
+ */\r
+ clearSelection: function () {\r
+ this.deselectAll(false);\r
+ this.updateButtonText();\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Deselects all options of the given values.\r
+ *\r
+ * If triggerOnChange is set to true, the on change event is triggered, if\r
+ * and only if one value is passed.\r
+ *\r
+ * @param {Array} deselectValues\r
+ * @param {Boolean} triggerOnChange\r
+ */\r
+ deselect: function(deselectValues, triggerOnChange) {\r
+ if(!$.isArray(deselectValues)) {\r
+ deselectValues = [deselectValues];\r
+ }\r
+\r
+ for (var i = 0; i < deselectValues.length; i++) {\r
+ var value = deselectValues[i];\r
+\r
+ if (value === null || value === undefined) {\r
+ continue;\r
+ }\r
+\r
+ var $option = this.getOptionByValue(value);\r
+ var $checkbox = this.getInputByValue(value);\r
+\r
+ if($option === undefined || $checkbox === undefined) {\r
+ continue;\r
+ }\r
+\r
+ if (this.options.selectedClass) {\r
+ $checkbox.closest('li')\r
+ .removeClass(this.options.selectedClass);\r
+ }\r
+\r
+ $checkbox.prop('checked', false);\r
+ $option.prop('selected', false);\r
+\r
+ if (triggerOnChange) {\r
+ this.options.onChange($option, false);\r
+ }\r
+ }\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll();\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Selects all enabled & visible options.\r
+ *\r
+ * If justVisible is true or not specified, only visible options are selected.\r
+ *\r
+ * @param {Boolean} justVisible\r
+ * @param {Boolean} triggerOnSelectAll\r
+ */\r
+ selectAll: function (justVisible, triggerOnSelectAll) {\r
+\r
+ var justVisible = typeof justVisible === 'undefined' ? true : justVisible;\r
+ var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);\r
+ var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');\r
+\r
+ if(justVisible) {\r
+ $('input:enabled' , visibleLis).prop('checked', true);\r
+ visibleLis.addClass(this.options.selectedClass);\r
+\r
+ $('input:enabled' , visibleLis).each($.proxy(function(index, element) {\r
+ var value = $(element).val();\r
+ var option = this.getOptionByValue(value);\r
+ $(option).prop('selected', true);\r
+ }, this));\r
+ }\r
+ else {\r
+ $('input:enabled' , allLis).prop('checked', true);\r
+ allLis.addClass(this.options.selectedClass);\r
+\r
+ $('input:enabled' , allLis).each($.proxy(function(index, element) {\r
+ var value = $(element).val();\r
+ var option = this.getOptionByValue(value);\r
+ $(option).prop('selected', true);\r
+ }, this));\r
+ }\r
+\r
+ $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', true);\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ if (triggerOnSelectAll) {\r
+ this.options.onSelectAll();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Deselects all options.\r
+ *\r
+ * If justVisible is true or not specified, only visible options are deselected.\r
+ *\r
+ * @param {Boolean} justVisible\r
+ */\r
+ deselectAll: function (justVisible, triggerOnDeselectAll) {\r
+\r
+ var justVisible = typeof justVisible === 'undefined' ? true : justVisible;\r
+ var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);\r
+ var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');\r
+\r
+ if(justVisible) {\r
+ $('input[type="checkbox"]:enabled' , visibleLis).prop('checked', false);\r
+ visibleLis.removeClass(this.options.selectedClass);\r
+\r
+ $('input[type="checkbox"]:enabled' , visibleLis).each($.proxy(function(index, element) {\r
+ var value = $(element).val();\r
+ var option = this.getOptionByValue(value);\r
+ $(option).prop('selected', false);\r
+ }, this));\r
+ }\r
+ else {\r
+ $('input[type="checkbox"]:enabled' , allLis).prop('checked', false);\r
+ allLis.removeClass(this.options.selectedClass);\r
+\r
+ $('input[type="checkbox"]:enabled' , allLis).each($.proxy(function(index, element) {\r
+ var value = $(element).val();\r
+ var option = this.getOptionByValue(value);\r
+ $(option).prop('selected', false);\r
+ }, this));\r
+ }\r
+\r
+ $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', false);\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ if (triggerOnDeselectAll) {\r
+ this.options.onDeselectAll();\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Rebuild the plugin.\r
+ *\r
+ * Rebuilds the dropdown, the filter and the select all option.\r
+ */\r
+ rebuild: function() {\r
+ this.$ul.html('');\r
+\r
+ // Important to distinguish between radios and checkboxes.\r
+ this.options.multiple = this.$select.attr('multiple') === "multiple";\r
+\r
+ this.buildSelectAll();\r
+ this.buildDropdownOptions();\r
+ this.buildFilter();\r
+\r
+ this.updateButtonText();\r
+ this.updateSelectAll(true);\r
+\r
+ if (this.options.enableClickableOptGroups && this.options.multiple) {\r
+ this.updateOptGroups();\r
+ }\r
+\r
+ if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {\r
+ this.disable();\r
+ }\r
+ else {\r
+ this.enable();\r
+ }\r
+\r
+ if (this.options.dropRight) {\r
+ this.$ul.addClass('pull-right');\r
+ }\r
+ },\r
+\r
+ /**\r
+ * The provided data will be used to build the dropdown.\r
+ */\r
+ dataprovider: function(dataprovider) {\r
+\r
+ var groupCounter = 0;\r
+ var $select = this.$select.empty();\r
+\r
+ $.each(dataprovider, function (index, option) {\r
+ var $tag;\r
+\r
+ if ($.isArray(option.children)) { // create optiongroup tag\r
+ groupCounter++;\r
+\r
+ $tag = $('<optgroup/>').attr({\r
+ label: option.label || 'Group ' + groupCounter,\r
+ disabled: !!option.disabled\r
+ });\r
+\r
+ forEach(option.children, function(subOption) { // add children option tags\r
+ var attributes = {\r
+ value: subOption.value,\r
+ label: subOption.label || subOption.value,\r
+ title: subOption.title,\r
+ selected: !!subOption.selected,\r
+ disabled: !!subOption.disabled\r
+ };\r
+\r
+ //Loop through attributes object and add key-value for each attribute\r
+ for (var key in subOption.attributes) {\r
+ attributes['data-' + key] = subOption.attributes[key];\r
+ }\r
+ //Append original attributes + new data attributes to option\r
+ $tag.append($('<option/>').attr(attributes));\r
+ });\r
+ }\r
+ else {\r
+\r
+ var attributes = {\r
+ 'value': option.value,\r
+ 'label': option.label || option.value,\r
+ 'title': option.title,\r
+ 'class': option.class,\r
+ 'selected': !!option.selected,\r
+ 'disabled': !!option.disabled\r
+ };\r
+ //Loop through attributes object and add key-value for each attribute\r
+ for (var key in option.attributes) {\r
+ attributes['data-' + key] = option.attributes[key];\r
+ }\r
+ //Append original attributes + new data attributes to option\r
+ $tag = $('<option/>').attr(attributes);\r
+\r
+ $tag.text(option.label || option.value);\r
+ }\r
+\r
+ $select.append($tag);\r
+ });\r
+\r
+ this.rebuild();\r
+ },\r
+\r
+ /**\r
+ * Enable the multiselect.\r
+ */\r
+ enable: function() {\r
+ this.$select.prop('disabled', false);\r
+ this.$button.prop('disabled', false)\r
+ .removeClass('disabled');\r
+ },\r
+\r
+ /**\r
+ * Disable the multiselect.\r
+ */\r
+ disable: function() {\r
+ this.$select.prop('disabled', true);\r
+ this.$button.prop('disabled', true)\r
+ .addClass('disabled');\r
+ },\r
+\r
+ /**\r
+ * Set the options.\r
+ *\r
+ * @param {Array} options\r
+ */\r
+ setOptions: function(options) {\r
+ this.options = this.mergeOptions(options);\r
+ },\r
+\r
+ /**\r
+ * Merges the given options with the default options.\r
+ *\r
+ * @param {Array} options\r
+ * @returns {Array}\r
+ */\r
+ mergeOptions: function(options) {\r
+ return $.extend(true, {}, this.defaults, this.options, options);\r
+ },\r
+\r
+ /**\r
+ * Checks whether a select all checkbox is present.\r
+ *\r
+ * @returns {Boolean}\r
+ */\r
+ hasSelectAll: function() {\r
+ return $('li.multiselect-all', this.$ul).length > 0;\r
+ },\r
+\r
+ /**\r
+ * Update opt groups.\r
+ */\r
+ updateOptGroups: function() {\r
+ var $groups = $('li.multiselect-group', this.$ul)\r
+ var selectedClass = this.options.selectedClass;\r
+\r
+ $groups.each(function() {\r
+ var $options = $(this).nextUntil('li.multiselect-group')\r
+ .not('.multiselect-filter-hidden')\r
+ .not('.disabled');\r
+\r
+ var checked = true;\r
+ $options.each(function() {\r
+ var $input = $('input', this);\r
+\r
+ if (!$input.prop('checked')) {\r
+ checked = false;\r
+ }\r
+ });\r
+\r
+ if (selectedClass) {\r
+ if (checked) {\r
+ $(this).addClass(selectedClass);\r
+ }\r
+ else {\r
+ $(this).removeClass(selectedClass);\r
+ }\r
+ }\r
+\r
+ $('input', this).prop('checked', checked);\r
+ });\r
+ },\r
+\r
+ /**\r
+ * Updates the select all checkbox based on the currently displayed and selected checkboxes.\r
+ */\r
+ updateSelectAll: function(notTriggerOnSelectAll) {\r
+ if (this.hasSelectAll()) {\r
+ var allBoxes = $("li:not(.multiselect-item):not(.multiselect-filter-hidden):not(.multiselect-group):not(.disabled) input:enabled", this.$ul);\r
+ var allBoxesLength = allBoxes.length;\r
+ var checkedBoxesLength = allBoxes.filter(":checked").length;\r
+ var selectAllLi = $("li.multiselect-all", this.$ul);\r
+ var selectAllInput = selectAllLi.find("input");\r
+\r
+ if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {\r
+ selectAllInput.prop("checked", true);\r
+ selectAllLi.addClass(this.options.selectedClass);\r
+ }\r
+ else {\r
+ selectAllInput.prop("checked", false);\r
+ selectAllLi.removeClass(this.options.selectedClass);\r
+ }\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Update the button text and its title based on the currently selected options.\r
+ */\r
+ updateButtonText: function() {\r
+ var options = this.getSelected();\r
+\r
+ // First update the displayed button text.\r
+ if (this.options.enableHTML) {\r
+ $('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));\r
+ }\r
+ else {\r
+ $('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));\r
+ }\r
+\r
+ // Now update the title attribute of the button.\r
+ $('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));\r
+ },\r
+\r
+ /**\r
+ * Get all selected options.\r
+ *\r
+ * @returns {jQUery}\r
+ */\r
+ getSelected: function() {\r
+ return $('option', this.$select).filter(":selected");\r
+ },\r
+\r
+ /**\r
+ * Gets a select option by its value.\r
+ *\r
+ * @param {String} value\r
+ * @returns {jQuery}\r
+ */\r
+ getOptionByValue: function (value) {\r
+\r
+ var options = $('option', this.$select);\r
+ var valueToCompare = value.toString();\r
+\r
+ for (var i = 0; i < options.length; i = i + 1) {\r
+ var option = options[i];\r
+ if (option.value === valueToCompare) {\r
+ return $(option);\r
+ }\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Get the input (radio/checkbox) by its value.\r
+ *\r
+ * @param {String} value\r
+ * @returns {jQuery}\r
+ */\r
+ getInputByValue: function (value) {\r
+\r
+ var checkboxes = $('li input:not(.multiselect-search)', this.$ul);\r
+ var valueToCompare = value.toString();\r
+\r
+ for (var i = 0; i < checkboxes.length; i = i + 1) {\r
+ var checkbox = checkboxes[i];\r
+ if (checkbox.value === valueToCompare) {\r
+ return $(checkbox);\r
+ }\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Used for knockout integration.\r
+ */\r
+ updateOriginalOptions: function() {\r
+ this.originalOptions = this.$select.clone()[0].options;\r
+ },\r
+\r
+ asyncFunction: function(callback, timeout, self) {\r
+ var args = Array.prototype.slice.call(arguments, 3);\r
+ return setTimeout(function() {\r
+ callback.apply(self || window, args);\r
+ }, timeout);\r
+ },\r
+\r
+ setAllSelectedText: function(allSelectedText) {\r
+ this.options.allSelectedText = allSelectedText;\r
+ this.updateButtonText();\r
+ }\r
+ };\r
+\r
+ $.fn.multiselect = function(option, parameter, extraOptions) {\r
+ return this.each(function() {\r
+ var data = $(this).data('multiselect');\r
+ var options = typeof option === 'object' && option;\r
+\r
+ // Initialize the multiselect.\r
+ if (!data) {\r
+ data = new Multiselect(this, options);\r
+ $(this).data('multiselect', data);\r
+ }\r
+\r
+ // Call multiselect method.\r
+ if (typeof option === 'string') {\r
+ data[option](parameter, extraOptions);\r
+\r
+ if (option === 'destroy') {\r
+ $(this).data('multiselect', false);\r
+ }\r
+ }\r
+ });\r
+ };\r
+\r
+ $.fn.multiselect.Constructor = Multiselect;\r
+\r
+ $(function() {\r
+ $("select[data-role=multiselect]").multiselect();\r
+ });\r
+\r
+}(window.jQuery);\r
limitations under the License.
============LICENSE_END============================================
===================================================================
- ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
-->
-
<style>
+#deleteStringMatch{
+ height:34px;
+ background-color:#dddd;
+}
+
+.disabled{
+ background-color: #dddd;
+}
.fileUpload {
position: relative;
overflow: hidden;
}
.form-group {
- /* height:24px; */
- /* box-sizing:border-box; */
- margin-bottom: 20px;
-
+/* height:24px; */
+/* box-sizing:border-box; */
+ margin-bottom:20px;
+}
+
+.modelSearchBox{
+ position:absolute;
+ padding: 25px 12px;
+}
+
+label{
+ text-align:right;
+ vertical-align:middle;
+}
+
+.leftStringMatchPanel{
+ padding: 0 10px 0 0;
+}
+
+#createNewStringMatch{
+ height:34px;
+ width:120px; /*84*/
+ background-color:#f2bfab;
}
- #paramsWarn {
- display: none;
+
+.idError{
+ color:red;
+ padding:50px 0px;
+ text-align:center;
+ display:none;
}
-label{text-align:right;
- padding-top:8px;
- }
+#rgname{
+ height:28px;
+ margin-left:-5px;
+}
+.stringMatchPanel{
+ background-color: #f5f5f5;
+ padding: 10px 5px;
+}
+
+#stringMatchSearch{
+ height: 33px;
+ font-size: 12px;
+ padding: 2px 2px 2px 30px;
+ margin-bottom: 5px;
+ width:100%;
+}
+#stringMatchTable{
+ cursor: pointer;
+ width:100%;
+}
+
+#stringMatchTable tr{
+ border-bottom: 1px solid #ddd;
+ border-collapse: collapse;
+ text-align: left;
+ font-size: 12px;
+ font-weight: normal;
+}
+
+#stringMatchTable td{
+ padding: 8px 10px;
+}
+
+#stringMatchTable tr.highlight{
+ background-color: #f5f5f5;
+ font-weight: bold;
+ font-size: 13px;
+}
+
+#stringMatchTableHolder{
+ height:200px;
+ width: 100%;
+ overflow:auto;
+}
+
+#timeout{
+ height:28px;
+ margin-left:10px;
+}
</style>
}
function disableSVN() {
- var selectLength = document.querySelectorAll(".disabled-block-container .tab-close-popup");
+ var selectLength = document.querySelectorAll(".disabled-block-container .tab-close-popup");
if(selectLength && selectLength.length>0){
for(var i = 0; i< selectLength.length ; i++){
selectLength[i].disabled = true;
}
}
-
-
document.getElementById("schemaLocation").disabled = true;
document.getElementById("userID").disabled = true;
</script>
-<div attribute-test="stringmatchproperties" id="configure-widgets" class="disabled-block-container">
- <div attribute-test="stringmatchpropertiesh" class="modal-header">
+<div attribute-test="stringMatchwindowproperties" id="configure-widgets" class="disabled-block-container">
+ <div attribute-test="stringMatchwindowpropertiesh" class="modal-header">
<button type="button" class="close" ng-click="close(false)"
aria-hidden="true" style="margin-top: -3px">×</button>
<h4>String Matching Micro Service</h4>
</div>
- <div attribute-test="stringmatchpropertiesb" class="modal-body">
- <div class="alert alert-danger" role="alert" id='paramsWarn'>
- <strong>Ooops!</strong> Unable to load properties for <span id='servName'>. Would you like to</span>
- <a href="javascript:void(0);" class="btn-link" id='paramsRetry'>Retry </a> /
- <a href="javascript:void(0);" class="btn-link" id='paramsCancel'>Cancel</a>
- </div>
- <div style="height: 10px"></div>
- <div class="panel panel-default">
- <form id="topicPublish" class="form-horizontal">
- <div>
-
- <div class="form-group">
- <label for="userID" class="col-sm-4 control-label"> Topic
- Publishes</label>
-
- <div class="col-sm-8">
- <select class="form-control" id="topicPublishes"
- name="topicPublishes">
- </select>
- </div>
+
+
+ <div class="modal-body">
+ <div attribute-test="stringMatchwindowpropertiesb" class="modal-body row">
+
+ <div class="leftStringMatchPanel">
+ <div class="panel panel-default">
+ <i class="modelSearchBox"></i> <input type="text"
+ id="stringMatchSearch" onkeyup="searchStringMatchList()"
+ placeholder="Search ...">
+ <div id="stringMatchTableHolder">
+ <table id="stringMatchTable"></table>
</div>
</div>
- </form>
- <div class="panel-heading">
- <ul id="nav_Tabs" class="nav nav-tabs">
- <li class><a id="add_one_more" href="#desc_tab"><span
- class="glyphicon glyphicon-plus" aria-hidden="true"></span></a></li>
- </ul>
- </div>
- <div class="panel-body">
- <div class="tab-content">
- <div id="properties_tab" class="tab-pane fade in active"></div>
-
+ <div style="float: left">
+ <button type="button" id="createNewStringMatch" class="btn btn-sm">New Group</button>
+ </span>
</div>
-
+ <div style="float: right">
+ <button type="button" id="deleteStringMatch" class="btn btn-sm glyphicon glyphicon-trash" disabled></button>
+ </span>
+ </div>
+ <div id="repeatIdError" class="idError">Error: This Group name is already taken.</div>
+ <div id="newIdError" class="idError">Error: Please rename your new Group.</div>
</div>
- </div>
- <span id="formSpan" style="display: none">
- <form class="saveProps" class="form-horizontal clearfix">
- <div>
- <div class="form-group clearfix">
- <label for="aaiMatchingFields" class="col-sm-4 control-label">AAI
- Fields Matching </label>
- <div class="col-sm-8">
- <select type="text" class="form-control "
- name="aaiMatchingFields" id="aaiMatchingFields" multiple="" size=2></select>
- </div>
+ <div class="panel panel-default col-sm-9 stringMatchPanel"
+ style="display: none;">
+ <form id="topicPublish" class="form-horizontal">
+ <div>
+<!-- As per the last minute new requirements for 1707 the ID needs to be hidden and we need to have a friendly name instead -->
+ <div style="display: none;">
+ <div class="form-group clearfix">
+ <label class="col-sm-4 control-label">Resource Group Id</label>
+ <div class="col-sm-8">
+ <input class="form-control" id="rgname" name="rgname" readOnly> </input>
+ </div>
+ </div>
+ </div>
+
+ <div>
+ <div class="form-group clearfix">
+ <label class="col-sm-4 control-label">Resource Group</label>
+ <div class="col-sm-8">
+ <input class="form-control" maxlength="48" placeholder="Enter Unique Name" id="rgfriendlyname" name="rgfriendlyname"> </input>
+ </div>
+ </div>
+ </div>
+
+ <!--Policy's drop down box -->
+ <div class="form-group clearfix">
+ <label class="col-sm-4 control-label">Ops Policy:</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="policyName" name="policyName"
+ autofocus="autofocus" required ng-trim="true">
+ <option ng-repeat="x in policyNames" value="{{x}}">{{x}}</option>
+ </select>
+ </div>
+ </div>
+
</div>
- <div class="form-group clearfix">
- <label for="aaiSendFields" class="col-sm-4 control-label">
- AAI Fields Send (Select Multiple)</label>
-
- <div class="col-sm-8 ">
- <select class="form-control"
- id="aaiSendFields" name="aaiSendFields" multiple size=2>
+ </form>
+
+ <div class="panel-heading" style="background-color: white;">
+ <ul id="nav_Tabs" class="nav nav-tabs">
+ <li class><a id="add_one_more" href="#desc_tab"><span
+ class="glyphicon glyphicon-plus" aria-hidden="true"></span></a></li>
+ </ul>
+ </div>
+ <div class="panel-body">
+ <div class="tab-content">
+ <div id="properties_tab" class="tab-pane fade in active"></div>
+ </div>
+ </div>
+ </div>
- </select>
+ <span id="formSpan" style="display: none">
+ <form class="saveProps" class="form-horizontal">
+ <div>
+ <div class="form-group clearfix">
+ <label for="aaiMatchingFields" class="col-sm-4 control-label">AAI Fields Matching </label>
+ <div class="col-sm-8">
+ <select class="form-control" name="aaiMatchingFields" id="aaiMatchingFields" multiple size=2></select>
+ </div>
+
</div>
- </div>
- <div class="form-group clearfix">
- <label for="groupNumber" class="col-sm-4 control-label">
- Resource-Group</label>
+ <div class="form-group clearfix">
+ <label for="aaiSendFields" class="col-sm-4 control-label">AAI Fields Send (Select Multiple)</label>
- <div class="col-sm-8">
- <input type="number" class="form-control" id="groupNumber" name="groupNumber" min="0" >
-
- </input>
+ <div class="col-sm-8 ">
+ <select class="form-control" id="aaiSendFields"
+ name="aaiSendFields" multiple size=2>
+ </select>
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="vfc" class="col-sm-4 control-label">
- Resource-VFC</label>
+<!-- <div class="form-group clearfix"> -->
+<!-- <label for="groupNumber" class="col-sm-4 control-label"> -->
+<!-- Resource-Group</label> -->
- <div class="col-sm-8">
- <select class="form-control" id="vfc" name="vfc">
+<!-- <div class="col-sm-8"> -->
+<!-- <input type="number" class="form-control" id="groupNumber" -->
+<!-- name="groupNumber" min="0"> </input> -->
- </select>
+<!-- </div> -->
+<!-- </div> -->
+ <div class="form-group clearfix">
+ <label for="vfc" class="col-sm-4 control-label">Resource-VFC</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="vfc" name="vfc">
- </div>
- </div>
- <div class="form-group clearfix">
- <label for="alarmCondition" class="col-sm-4 control-label">
- Alarm Condition</label>
+ </select>
- <div class="col-sm-8">
- <select class="form-control" id="alarmCondition"
- name="alarmCondition"></select>
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="eventSeverity" class="col-sm-4 control-label">
- Event Severity</label>
- <div class="col-sm-8">
- <select class="form-control" id="eventSeverity"
- name="eventSeverity" enableFilter="false"></select>
+ <div class="form-group clearfix">
+ <label for="alarmCondition" class="col-sm-4 control-label">Alarm Condition</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="alarmCondition" name="alarmCondition">
+
+ </select>
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="eventSourceType" class="col-sm-4 control-label">
- Event Source Type</label>
- <div class="col-sm-8">
- <input type="text" class="form-control" id="eventSourceType"
- name="eventSourceType" readOnly ></input>
+ <div class="form-group clearfix">
+ <label for="eventSeverity" class="col-sm-4 control-label">Event Severity</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="eventSeverity"
+ name="eventSeverity" enableFilter="false"></select>
+ </div>
+ </div>
+ <div class="form-group clearfix">
+ <label for="eventSourceType" class="col-sm-4 control-label">
+ Event Source Type</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" id="eventSourceType"
+ name="eventSourceType" readOnly></input>
+ </div>
</div>
- </div>
-
- <div class="form-group clearfix">
- <label for="timeWindow" class="col-sm-4 control-label">
- Time Window</label>
-
- <div class="col-sm-8">
- <input type="number" min="0" class="form-control" id="timeWindow"
- name="timeWindow" />
+ <div class="form-group clearfix">
+ <label for="timeWindow" class="col-sm-4 control-label">
+ Time Window</label>
+ <div class="col-sm-8">
+ <input type="text" maxlength="5" class="form-control"
+ onkeypress="return isNumberKey(event)"
+ id="timeWindow" name="timeWindow" />
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="ageLimit" class="col-sm-4 control-label"> Age
- Limit</label>
-
- <div class="col-sm-8">
- <input type="number" min="0" class="form-control" id="ageLimit"
- name="ageLimit" />
+ <div class="form-group clearfix">
+ <label for="ageLimit" class="col-sm-4 control-label"> Age
+ Limit</label>
+
+ <div class="col-sm-8">
+ <input type="text" maxlength="5" class="form-control" id="ageLimit"
+ onkeypress="return isNumberKey(event)"
+ name="ageLimit" />
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="createClosedLoopEventId"
- class="col-sm-4 control-label"> Create CL Event ID</label>
- <div class="col-sm-8">
- <select class="form-control" id="createClosedLoopEventId"
- name="createClosedLoopEventId" enableFilter="false">
- </select>
-
+ <div class="form-group clearfix">
+ <label for="createClosedLoopEventId"
+ class="col-sm-4 control-label"> Create CL Event ID</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="createClosedLoopEventId"
+ name="createClosedLoopEventId" enableFilter="false">
+ </select>
+
+ </div>
</div>
- </div>
- <div class="form-group clearfix">
- <label for="outputEventName" class="col-sm-4 control-label">
- Output Event Name</label>
+ <div class="form-group clearfix">
+ <label for="outputEventName" class="col-sm-4 control-label">
+ Output Event Name</label>
- <div class="col-sm-8">
- <select class="form-control" id="outputEventName"
- name="outputEventName" enableFilter="false"></select>
+ <div class="col-sm-8">
+ <select class="form-control" id="outputEventName"
+ name="outputEventName" enableFilter="false"></select>
+ </div>
</div>
</div>
- </div>
- </form>
- </span>
+
+
+
+ </form>
+ </span>
+ </div>
</div>
- <div attribute-test="stringmatchpropertiesf" class="modal-footer">
+ <div attribute-test="stringMatchwindowpropertiesf" class="modal-footer">
<!--<button ng-click="reset()" class="btn btn-primary" style="float:left">Reset</button>-->
<button id="savePropsBtn" class="btn btn-primary">Close</button>
<button ng-click="close(true)" id="close_button"
class="btn btn-primary">Cancel</button>
-
</div>
+
<script>
+
//Basically this method will add a new form. All forms share the same class. When you want one form to show(active form) the other forms get the
// css attribute display:none
- $("#paramsRetry").on('click', function () {
- $("#paramsWarn").hide();
- $("#ridinSpinners").css("display","")
- var bool=loadSharedPropertyByService();
- $("#ridinSpinners").css("display","none")
- });
- $("#paramsCancel").on('click', function () {
- loadSharedPropertyByServiceProperties();
- $("#paramsWarn").hide();
-
- });
-
-
-
$("#add_one_more").click(function(event) {
- //alert("lol");
event.preventDefault();
add_one_more();
- //I have uncomment the below code becoz there is no refreshItems method.
-
- //refreshItems();
setMultiSelect();
-
- })
- loadPropertyWindow("string_match")
+ });
+
+
+ //This method will load the existing Strin Match onto the screen
+ loadPropertyWindow("string_match");
setASDCFields();
- var arr = elementMap[lastElementSelected];
+
+ // By default, parentStringMatchConditions is disabled
+ $("#parentStringMatchConditions").prop('disabled', 'disabled');
+
+
+ var parent_stringMatch = {}
+ var stringMatch_ids = {}
+ var loadingId = false;
+ var allSMatch = {};
var vfc_temp=""
var alarm_conditions_temp=""
var event_severity_temp=""
- var event_type_source_temp=""
- if (arr !== undefined && arr[1]!==undefined) {
- var el = arr[1]['serviceConfigurations']
- for (var i = 0; i < el.length; i++) {
- var num = add_one_more();
- for (var j = 0; j < el[i].length; j++) {
- if (el[i][j]["stringSet"] !== undefined) {
- var ss = el[i][j]["stringSet"]
- for (var o = 0; o < ss.length; o++) {
- if(ss[o].hasOwnProperty("name")){
- if(ss[o].name==="alarmCondition"){
- alarm_conditions_temp=ss[o].value
- }else if(ss[o].name==="eventSeverity"){
- event_severity_temp=ss[o].value;
- }else if(ss[o].name==="eventSourceType"){
- event_type_source_temp=ss[o].value;
+ var event_type_source_temp=""
+
+ //Grab saved values for dropdowns
+ var obj = elementMap[lastElementSelected];
+
+ if (!($.isEmptyObject(obj))) {
+ allSMatch = jQuery.extend({}, obj);
+ for ( var x in allSMatch) {
+ $("#stringMatchTable").prepend(
+ "<tr><td>" + x + "</td></tr>");
+ }
+ }
+
+
+ //Load properties_tab for a chosen String Match
+ function disperseConfig(stringMatchObj, id) {
+ //remove old gui forms
+ for (var i = 1; i < ($(".formId").length + 1); i++) {
+ $("#go_properties_tab" + i).parent().remove();
+ }
+ $(".formId").remove();
+
+ if (stringMatchObj !== undefined) {
+ var el = stringMatchObj[id][4]['serviceConfigurations']
+ for (var i = 0; i < el.length; i++) {
+ loadingId = true;
+ var num = add_one_more();
+ loadingId = false;
+ for (var j = 0; j < el[i].length; j++) {
+ if (el[i][j]["stringSet"] !== undefined) {
+ var ss = el[i][j]["stringSet"]
+ for (var o = 0; o < ss.length; o++) {
+ if(ss[o].hasOwnProperty("name")){
+ if(ss[o].name==="alarmCondition"){
+ alarm_conditions_temp=ss[o].value
+ }else if(ss[o].name==="eventSeverity"){
+ event_severity_temp=ss[o].value;
+ }else if(ss[o].name==="eventSourceType"){
+ event_type_source_temp=ss[o].value;
+ }
+ else
+ $("#formId" + num + " #" + ss[o].name).val(ss[o].value);
}
- else
- $("#formId" + num + " #" + ss[o].name).val(ss[o].value);
+
+ }
+ }else if(el[i][j].hasOwnProperty("name") && el[i][j].name==="vfc"){
+ vfc_temp=el[i][j].value
+ }
+ else if (el[i][j].name === 'outputEventName' && el[i][j].value.toString() !== '') {
+ $("#go_properties_tab" + num).text(el[i][j].value);
+ $("#formId" + num + " #" + el[i][j].name).val(el[i][j].value);
+ }
+ else {
+ if(el[i][j].hasOwnProperty("name")){
+ $("#formId" + num + " #" + el[i][j].name).val(
+ el[i][j].value);
}
-
}
- }else if(el[i][j].hasOwnProperty("name") && el[i][j].name==="vfc"){
- //alert(el[i][j].value)
- vfc_temp=el[i][j].value
}
- else {
- if(el[i][j].hasOwnProperty("name")){
- $("#formId" + num + " #" + el[i][j].name).val(
- el[i][j].value);
+ set_vfc_alarm_event(num);
+ vfc_temp="";
+ alarm_conditions_temp="";
+ event_severity_temp="";
+ event_type_source_temp="";
+ }
+
+ //Adding all the ids for parent String options
+ for (var i = 1; i <= $(".formId").length; i++) {
+ for (k in stringMatch_ids) {
+ if ($("#formId" + i + " #_id").val() !== stringMatch_ids[k].toString() && $(k + " #recipe").val() !== undefined && $(k + " #recipe").val() !== "") {
+ $("#formId" + i + " #parentStringMatch").append("<option value=\""+stringMatch_ids[k]+"\">"+ $(k + " #recipe").val()+ "</option>");
}
}
}
- changeTab(num);
- set_vfc_alarm_event(num)
- vfc_temp=""
- alarm_conditions_temp=""
- event_severity_temp=""
- event_type_source_temp=""
- }
- if(arr[0] && arr[0][0] && arr[0][0].name){
- $("#" + arr[0][0].name).val(arr[0][0].value);
- }
+ for (k in parent_stringMatch) {
+ $("#formId" + k + " #parentStringMatch").val(parent_stringMatch[k]);
+ // force the change event
+ $("#formId" + k + " #parentStringMatch").change();
+ }
- }
-
- //this will populate alarmcondition,vfc,eventtypesource if they are saved in elementmap
- function set_vfc_alarm_event (count){
- //alert("lol")
- //alert(alarm_conditions_temp)
- //alert(alarm_conditions_temp!=="" && alarm_conditions_temp!==undefined)
- if(vfc_temp!=="" && vfc_temp!==undefined){
- $("#formId"+count+" #vfc").val(vfc_temp)
+ if (stringMatchObj[id][0]) {
+ $("#" + stringMatchObj[id][0].name).val(stringMatchObj[id][0].value);
+ }
- if(alarm_conditions_temp!=="" && alarm_conditions_temp!==undefined){
- setAlarmConditions(vfc_temp,count)
- $("#formId"+count+" #alarmCondition").val(alarm_conditions_temp)
-
- if(event_severity_temp!=="" && event_severity_temp!==undefined){
- setEventSourceType(alarm_conditions_temp,count)
- $("#formId"+count+" #eventSeverity").val(event_severity_temp)
- if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
- $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
- }
- }
- if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
- setEventSourceType(alarm_conditions_temp,count)
- $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
- if(event_severity_temp!=="" && event_severity_temp!==undefined){
- $("#formId"+count+" #eventSeverity").val(event_severity_temp)
- }
- }
+ if (stringMatchObj[id][1]) {
+ $("#" + stringMatchObj[id][1].name).val(stringMatchObj[id][1].value);
+ }
+
+ if (stringMatchObj[id][2]) {
+ $("#" + stringMatchObj[id][2].name).val(stringMatchObj[id][2].value);
}
}
+
+ setMultiSelect();
-
+ if (readOnly||readMOnly){
+ $('select[multiple] option').each(function() {
+ var input = $('input[value="' + $(this).val() + '"]');
+ input.prop('disabled', true);
+ input.parent('li').addClass('disabled');
+ });
+ $('input[value="multiselect-all"]').prop('disabled', true).parent('li').addClass('disabled');
+ }
}
-
-
+
+
+ //This is ensure there are no repeated keys in the map
function noRepeats(form) {
+ //triggered per String.
var select = {};
for (var i = 0; i < form.length; i++) {
- if(form[i].hasOwnProperty("name")){
if (select[form[i].name] === undefined)
select[form[i].name] = []
select[form[i].name].push(form[i].value);
}
- }
var arr = []
for (s in select) {
var f = {}
}
return arr
}
- function setStringSet(form) {
- var arr = []
- var alarmCondition = {}
- var eventSeverity = {}
- var eventSourceType = {}
- for (var i = 0; i < form.length; i++) {
- if (form[i].name === "alarmCondition") {
- alarmCondition = form[i]
- } else if (form[i].name === "eventSeverity") {
- eventSeverity = form[i];
- } else if (form[i].name === "eventSourceType") {
- eventSourceType = form[i];
- } else {
- arr.push(form[i])
+ $("#savePropsBtn").click(function(event) {
+ $(".idError").hide();
+ if ($("#stringMatchTable .highlight td").html() !== $("#rgfriendlyname").val()){
+ //repeated name
+ if ($.inArray($("#rgfriendlyname").val(), Object.keys(allSMatch)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ delete allSMatch[$("#stringMatchTable .highlight td").html()];
}
-
}
- var stringSet = {};
- stringSet['stringSet'] = []
- stringSet['stringSet'].push(alarmCondition);
- stringSet['stringSet'].push(eventSeverity);
- stringSet['stringSet'].push(eventSourceType);
- arr.push(stringSet)
-
- return arr;
- }
- $("#savePropsBtn").click(function(event) {
-
- var form = []
- var properties = $(".saveProps").not("#formSpan .saveProps")
- var topicP = $("#topicPublish").serializeArray()
- form.push(topicP)
- var d = {}
- d["serviceConfigurations"] = [];
-
- for (var i = 0; i < properties.length; i++) {
- var ser = $(properties[i]).serializeArray();
- var s = noRepeats(ser)
- var newSer = setStringSet(s)
-
- d["serviceConfigurations"].push(newSer)
+ /* //Saves edits
+ if ($("#stringMatchTable .highlight").length > 0) {
+ saveLastStringMatchLocally($("#stringMatchTable .highlight td").html());
+ } */
+ if ($("#rgfriendlyname").val().trim() == "New_Group"){
+ $("#newIdError").show();
+ return;
}
- form.push(d)
- saveProperties(form)
+ startNextItem();
+ //Removes outdated (deleted) resource Groups by checking against left menu
+ var finalSaveList = {};
+ $("#stringMatchTable td").each(function() {
+ var tableVal = $(this).text();
+ if (tableVal in allSMatch) {
+ finalSaveList[tableVal] = allSMatch[tableVal];
+ }
+ });
+ saveProperties(finalSaveList);
$("#close_button").click();
-
})
-
-
-
-
-
+
function add_one_more() {
$("#nav_Tabs li").removeClass("active");
+
+ //FormSpan contains a block of the form that is not being displayed. We will create clones of that and add them to tabs
var form = $($("#formSpan").children()[0]).clone()
var count = 0;
- //alert($(".formId").length>0)
+ //Each new tab will have the formId class attached to it. This way we can track how many forms we currently have out there and assign listeners to them
if ($(".formId").length > 0) {
var greatest = 0;
var s = $(".formId");
- //alert("here1")
for (var i = 0; i < s.length; i++) {
if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
greatest = parseInt($(s[i]).attr("id").substring(6))
}
}
count = greatest + 1;
- //alert(count)
$("#properties_tab").append(
('<span class="formId" id="formId'+count+'"></span>'));
} else {
- //alert("here2")
count++;
$("#properties_tab").append(
'<span class="formId" id="formId1"></span>');
}
+
+ //$(form).find("#stringMatchName").val("Recipe "+makid(2))
+ //TODO change up how we auto assign stringMatchName. There could be the case where we do this and it will have repeats
+ //alert($(form).find("#_id").val())
+ //stringMatchNameChangeListener(form)
+
$("#add_one_more")
.parent()
.before(
$("#formId" + count).append(form);
$(".formId").not($("#formId" + count)).css("display", "none")
addCustListen(count)
- addEventNameList(count)
- add_vfc_alarm_event_listener(count);
+ addTabListen(count)
+
+ // This is for when the process is not loading from map but being created
+ if (!loadingId) {
+ var l = makeid()
+ $(form).find("#_id").val(l)
+ stringMatch_ids["#formId" + count] = l
+ var answers = {}
+
+ for (k in answers) {
+ $(k).val(answers[k])
+ }
+ }
return count;
}
- function addCustListen(count) {
+ function add_new_stringMatch(issueNewNames) {
+ //remove old gui forms
+ for (var i = 1; i < ($(".formId").length + 1); i++) {
+ $("#go_properties_tab" + i).parent().remove();
+ }
+ $(".formId").remove();
+
+ //Reset header
+ var ms = new Date().getTime();
+ var defSMatch = ms;
+ $("#rgname").val(defSMatch);
+
+ $("#rgfriendlyname").val("New_Group");
+
+ $("#add_one_more").click();
+ return defSMatch;
+ }
+
+ //listener will change the tab name to the recipe
+ function addTabListen(count) {
+ $("#formId" + count + " #recipe").on("change",function() {
+ if ($("#formId" + count + " #recipe").val().toString() !== "") {
+ $('#go_properties_tab' + count).text($("#formId" + count + " #recipe").val())
+ } else
+ $('#go_properties_tab' + count).text("String");
+
+ var answers = {}
+
+ for (var i = 1; i <= greatestIdNum(); i++) {
+ if ($("#formId" + i).length > 0) {
+
+ answers["#formId" + i + " #parentStringMatch"] = $("#formId" + i + " #parentStringMatch").val()
+ $("#formId" + i + " #parentStringMatch").empty();
+
+ for (k in stringMatch_ids) {
+ if ($("#formId" + i + " #_id").val().toString() !== stringMatch_ids[k] && $(k + " #recipe").val() !== 'undefined' && $(k + " #recipe").val() !== "") {
+ $("#formId" + i + " #parentStringMatch").append("<option value='"+stringMatch_ids[k]+"''> "+ $(k+ " #recipe").val()+ "</option>")
+ }
+ }
+ $("#formId" + i + " #parentStringMatch").prepend("<option value=''></option>")
+ }
+ }
+ for (k in answers) {
+ $(k).val(answers[k])
+ }
+ })
+
+ // disable parentStringMatchConditions when a parentStringMatch is not selected
+ $("#formId" + count + " #parentStringMatch").on("change",function() {
+ if ($("#formId" + count + " #parentStringMatch").val().toString() == "") {
+ // deselect all options
+ $("#formId"+ count+ " #parentStringMatchConditions option:selected").prop("selected", false);
+ // disable the select box
+ $("#formId"+ count+ " #parentStringMatchConditions").prop('disabled', 'disabled');
+ } else {
+ $("#formId"+ count+ " #parentStringMatchConditions").prop('disabled', false);
+ }
+ })
+ }
+
+ function addCustListen(count) {
$('#go_properties_tab' + count).click(function(event) {
$("#nav_Tabs li").removeClass("active");
$(this).parent().addClass("active");
})
$('#tab_close' + count).click(function(event) {
- if(document.getElementById("topicPublishes").disabled){
- return false;
- }
+
$(this).parent().remove();
+ delete stringMatch_ids["#formId" + count + " #_id"]
$("#formId" + count).remove();
})
}
+
+ function setStringSet(form) {
+ var arr = []
+ var alarmCondition = {}
+ var eventSeverity = {}
+ var eventSourceType = {}
+ for (var i = 0; i < form.length; i++) {
+ if (form[i].name === "alarmCondition") {
+ alarmCondition = form[i]
+ } else if (form[i].name === "eventSeverity") {
+ eventSeverity = form[i];
+ } else if (form[i].name === "eventSourceType") {
+ eventSourceType = form[i];
+ } else {
- function changeTab(count){
- var output = $('#formId' + count + " #outputEventName");
- var group = $('#formId' + count + " #groupNumber");
- var outputValue="";
- var groupValue="";
- if(output.val()!=="")
- outputValue=output.val();
- if(output.val()!=="" && group.val()!=="")
- groupValue=group.val()+":";
- else if(group.val()!=="")
- groupValue=group.val();
-
- var tabText="Condition"
- if(groupValue+outputValue!=="")
- tabText=groupValue+outputValue;
- $("#go_properties_tab" + count).text(tabText);
+ arr.push(form[i])
+ }
+
+ }
+ var stringSet = {};
+ stringSet['stringSet'] = []
+ stringSet['stringSet'].push(alarmCondition);
+ stringSet['stringSet'].push(eventSeverity);
+ stringSet['stringSet'].push(eventSourceType);
+ arr.push(stringSet)
+
+ return arr;
}
- function addEventNameList(count) {
+ //this will populate alarmcondition,vfc,eventtypesource if they are saved in elementmap
+ function set_vfc_alarm_event (count){
+ if(vfc_temp!=="" && vfc_temp!==undefined){
+ $("#formId"+count+" #vfc").val(vfc_temp)
+
+ if(alarm_conditions_temp!=="" && alarm_conditions_temp!==undefined){
+ setAlarmConditions(vfc_temp,count)
+ $("#formId"+count+" #alarmCondition").val(alarm_conditions_temp);
+
+ if(event_severity_temp!=="" && event_severity_temp!==undefined){
+ setEventSourceType(alarm_conditions_temp,count)
+ $("#formId"+count+" #eventSeverity").val(event_severity_temp)
+ if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
+ $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
+ }
+ }
+ if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
+ setEventSourceType(alarm_conditions_temp,count)
+ $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
+ if(event_severity_temp!=="" && event_severity_temp!==undefined){
+ $("#formId"+count+" #eventSeverity").val(event_severity_temp)
+ }
+ }
+ }
+ }
+ }
+
+ function setAlarmConditions(vfcID, count){
+ var alarmCondition={}
+
+ if($("#formId"+count+" #vfc").val()!==""){
+ if(vf_Services['shared'] && vf_Services['shared']['byVfc'] && vf_Services['shared']['byVfc'][vfcID]){
+ alarmCondition=vf_Services['shared']['byVfc'][vfcID]['alarmCondition']
+ }
+ }
- $('#formId' + count + " #outputEventName").on('change',function(){changeTab(count)})
- $('#formId' + count + " #groupNumber").on('change',function(){changeTab(count)});
+ $("#formId"+count+" #alarmCondition").empty();
+ $("#formId"+count+" #alarmCondition").append("<option value=\"\"></opton>");
+ if(alarmCondition && _.keys(alarmCondition).length>0){
+ for(key in alarmCondition){
+ var safestring = $('<div>').text(key).html();
+ $("#formId"+count+" #alarmCondition").append("<option value='"+safestring+"'>"+alarmCondition[key]+"</opton>");
+ }
+ $("#formId"+count+" #alarmCondition").multiselect("rebuild");
+ }
+ }
+ function setEventSourceType(alarm, count){
+ var eventSourceTypSeverity={}
+ if($("#formId"+count+" #alarmCondition").val()!==""){
+ if(vf_Services && vf_Services['shared'] && vf_Services['shared']['byAlarmCondition'] && vf_Services['shared']['byAlarmCondition'][alarm]){
+ eventSourceTypSeverity=vf_Services['shared']['byAlarmCondition'][alarm]
+ }
+
+ }
+
+ $("#formId"+count+" #eventSourceType").val(eventSourceTypSeverity.eventSourceType);
+ $("#formId"+count+" #eventSeverity").val(eventSourceTypSeverity.eventSeverity);
+ $("#formId"+count+" #eventSeverity").multiselect("rebuild");
+ }
+
+ function greatestIdNum() {
+ var greatest = 0;
+ var s = $(".formId");
+ for (var i = 0; i < s.length; i++) {
+ if (parseInt($(s[i]).attr("id").substring(6)) > greatest) {
+ greatest = parseInt($(s[i]).attr("id").substring(6))
+ }
+ }
+ return greatest;
}
-
-
-function setAlarmConditions(vfcID, count){
- var alarmCondition={}
-
- if($("#formId"+count+" #vfc").val()!==""){
- if(vf_Services['shared'] && vf_Services['shared']['byVfc'] && vf_Services['shared']['byVfc'][vfcID]){
- alarmCondition=vf_Services['shared']['byVfc'][vfcID]['alarmCondition']
+
+ //Generate random id for each String
+ //Also made sure ids couldnt be repeated
+ function makeid(num) {
+
+ var text = "";
+ var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ if (num == null)
+ num = 7;
+ for (var i = 0; i < 7; i++)
+ text += possible.charAt(Math.floor(Math.random()
+ * possible.length));
+ var hasValue = false;
+ for (k in stringMatch_ids) {
+ if (text === stringMatch_ids[k])
+ hasValue = true
+ }
+ if (hasValue)
+ return makeid(num);
+ else
+ return text
}
-
- }
-
- $("#formId"+count+" #alarmCondition").empty();
- $("#formId"+count+" #alarmCondition").append("<option value=\"\"></opton>")
- if(alarmCondition && _.keys(alarmCondition).length>0){
- for(key in alarmCondition){
- var safestring = $('<div>').text(key).html();
- $("#formId"+count+" #alarmCondition").append("<option value='"+safestring+"'>"+alarmCondition[key]+"</opton>")
+
+ var ParentStringMatch = function(id, name) {
+ this.id = id
+ this.name = name
}
- }
-}
-function setEventSourceType(alarm, count){
- var eventSourceTypSeverity={}
- if($("#formId"+count+" #alarmCondition").val()!==""){
- if(vf_Services && vf_Services['shared'] && vf_Services['shared']['byAlarmCondition'] && vf_Services['shared']['byAlarmCondition'][alarm]){
- eventSourceTypSeverity=vf_Services['shared']['byAlarmCondition'][alarm]
+ //String table search filter
+ function searchStringMatchList() {
+ var search = document.getElementById("stringMatchSearch");
+ var row = document.getElementsByTagName("td");
+ for (var i = 0; i < row.length; i++) {
+ if (row[i].innerHTML.toUpperCase().indexOf(
+ search.value.toUpperCase()) > -1) {
+ row[i].style.display = "";
+ } else {
+ row[i].style.display = "none";
+ }
+ }
}
-
- }
-
- $("#formId"+count+" #eventSourceType").val(eventSourceTypSeverity.eventSourceType);
- $("#formId"+count+" #eventSeverity").val(eventSourceTypSeverity.eventSeverity);
-
-}
-function add_vfc_alarm_event_listener(count) {
+
+ function saveLastStringMatchLocally(lastStringMatchId) {
+ var polForm = []
+
+ var properties = $(".saveProps").not("#formSpan .saveProps")
- $("#formId"+count+" #vfc").on('focus', function () {
- // Store the current value on focus and on change
- previous = this.value;
- }).change(function(){
+ var topicPublish = $("#topicPublish").serializeArray();
- setAlarmConditions($("#formId"+count+" #vfc").val(), count);
- $("#formId"+count+" #eventSourceType").val("");
- $("#formId"+count+" #eventSeverity").val("")
+ for (var i = 0; i < topicPublish.length; i++) {
+ polForm.push(topicPublish[i]);
+ }
+
+ //The below three lines are added to make sure resource group can be save correctly even if the policy is not present
+ if (topicPublish.length == 2){
+ var pname = {name:"policyName", value:""};
+ polForm.push(pname);
+ var pid = {name:"policyId", value:""};
+ polForm.push(pid);
+ }else{
+ var selectedPName = topicPublish[2]["value"];
+ var pid = {name:"policyId", value:allPolicies[selectedPName][1]["value"]};
+ polForm.push(pid);
+ }
+ var d = {}
+ d["serviceConfigurations"] = [];
+ for (var i = 0; i < properties.length; i++) {
+ var ser = $(properties[i]).serializeArray();
+ var s = noRepeats(ser)
+ var newSer = setStringSet(s);
+ d["serviceConfigurations"].push(newSer);
+ }
+ polForm.push(d);
+ allSMatch[lastStringMatchId] = polForm;
+ }
+
+ $("#deleteStringMatch").on('click', function() {
+ $(".idError").hide();
+ var deleteId = $("#stringMatchTable .highlight td").html();
+ delete allSMatch.deleteId;
+ $("#stringMatchTable .highlight").remove();
+ $("#rgfriendlyname").val('');
+ expandTable();
});
-
- $("#formId"+count+" #alarmCondition").on('focus', function () {
- // Store the current value on focus and on change
- previous = this.value;
- }).change(function(){
-
+
+ $('#stringMatchTable').on('click', 'tr', function(event) {
+ $(".idError").hide();
+ //edited name
+ if ($("#stringMatchTable .highlight td").html() !== $("#rgfriendlyname").val()){
+ //repeated name
+ if ($.inArray($("#rgfriendlyname").val(), Object.keys(allSMatch)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ $("#repeatIdError").hide();
+ delete allSMatch[$("#stringMatchTable .highlight td").html()];
+ }
+ }
+ if ($("#rgfriendlyname").val().trim() == "New_Group"){
+ $("#newIdError").show();
+ return;
+ }
+ if (!(readOnly||readMOnly)){
+ startNextItem();
+ } else {
+ if ($("#stringMatchTable .highlight").length == 0){
+ collapseTable();
+ }
+ }
+
+ $(this).addClass('highlight').siblings().removeClass('highlight');
+ disperseConfig(allSMatch, $(this).find("td").html());
+ });
+
+
+ $('#createNewStringMatch').on('click', function() {
+ $(".idError").hide();
+ //edited name
+ if ($("#stringMatchTable .highlight td").html() !== $("#rgfriendlyname").val()){
+ //repeated name
+ if ($.inArray($("#rgfriendlyname").val(), Object.keys(allSMatch)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ $("#repeatIdError").hide();
+ delete allSMatch[$("#stringMatchTable .highlight td").html()];
+ }
+ }
+ if ($("#rgfriendlyname").val().trim() == "New_Group"){
+ $("#newIdError").show();
+ return;
+ }
+ startNextItem();
+ var defSMatch = add_new_stringMatch();
+
+ if (("#stringMatchTable .highlight").length > 0) {
+ $('#stringMatchTable tr.highlight').removeClass('highlight');
+ }
+ //$("#stringMatchTable").prepend("<tr class='highlight' id='" +defSMatch+ "''><td>"+ defSMatch + "</td></tr>");
+ $("#stringMatchTable").prepend("<tr class='highlight'><td>New_Group</td></tr>");
- setEventSourceType($("#formId"+count+" #alarmCondition").val().toString(),count);
});
+
+ function isNumberKey(event){
+ var charCode = (event.which) ? event.which : event.keyCode
+ if (charCode > 31 && (charCode < 48 || charCode > 57)){
+ return false;
+ }
+ return true;
};
- </script>
-</div>
+
+ function startNextItem() {
+ //save last item before transitioning
+ var lastItem = $("#stringMatchTable .highlight");
+
+
+ if (lastItem.length > 0) {
+ saveLastStringMatchLocally($("#rgfriendlyname").val());
+ //lastItem.attr("id", $("#rgfriendlyname").val());
+ if($("#rgfriendlyname").val() != ''){
+ lastItem.find("td").html($("#rgfriendlyname").val());
+ }
+ } else {
+ collapseTable();
+ }
+
+ //allow deleting
+ if ($("#deleteStringMatch").prop("disabled")) {
+ $("#deleteStringMatch").prop("disabled", false);
+ }
+ }
+ //Show table panel only
+ function expandTable() {
+ $(".stringMatchPanel").css("display", "none");
+ $(".leftStringMatchPanel").removeClass("col-sm-3");
+ $(".modelSearchBox").css("padding", "25px 12px");
+ if (!($("#deleteStringMatch").prop("disabled"))) {
+ $("#deleteStringMatch").prop("disabled", true);
+ }
+ }
+
+ //Show both menus
+ function collapseTable() {
+ $(".leftStringMatchPanel").addClass("col-sm-3");
+ $(".glyphicon-search").css("padding", "10px 12px");
+ $(".stringMatchPanel").css("display", "unset");
+ }
+ </script>
+</div>
\ No newline at end of file
-->
<style>
+#createNewThresh{
+ height:34px;
+ width:120px; /*84*/
+ background-color:#f2bfab;
+}
+
+#deleteThresh{
+ height:34px;
+ background-color:#dddd;
+}
+
.fileUpload {
position: relative;
overflow: hidden;
}
.form-group {
- margin-bottom:20px;
+ margin-bottom:15px;
+ display:-webkit-flex;
+ display: flex;
+ align-items: center;
+}
+
+#tcaEditHolder{
+ height:260px;
+ background-color: #f5f5f5;
+ padding:10px 0px;
+ margin: 15px 15px 0 0;
+ float: right;
+}
+.tcaErr{
+ display:none;
+ text-align:center;
+ margin-bottom:20px;
+ color:red;"
+}
+
+.tcaParentItems {
+ padding-left: 20px;
+}
+
+.tcaParentItems label{
+ margin-bottom: 0px;
+}
+
+#tcaTable{
+ cursor: pointer;
+ width:100%;
+}
+
+#tcaTable tr{
+ border-bottom: 1px solid #ddd;
+ border-collapse: collapse;
+ text-align: center;
+ font-size: 12px;
+ font-weight: normal;
+}
+
+#tcaTable td{
+ padding: 8px 10px;
+}
+
+#tcaTable tr.highlight{
+ background-color: #f5f5f5;
+ font-weight: bold;
+ font-size: 13px;
+}
+
+#tcaTableHolder{
+ height:160px;
+ width: 100%;
+ overflow:auto;
}
</style>
</div>
<div class="modal-body">
<div style="height: 10px"></div>
- <div class="panel panel-default">
- <form id="topicPublish" class="form-horizontal">
- <div>
-
- <div class="form-group">
- <label for="userID" class="col-sm-4 control-label"> Topic Publishes</label>
-
- <div class="col-sm-8">
- <select class="form-control" id="topicPublishes"
- name="topicPublishes">
- </select>
- </div>
- </div>
- </div>
- </form>
+ <div class="panel panel-default" id="panelHolder">
+
<div class="panel-heading">
<ul id="nav_Tabs" class="nav nav-tabs">
<li class><a id="add_one_more" href="#desc_tab"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a></li>
</ul>
</div>
+
+ <span id="formSpan" style="display:none;">
<div class="panel-body">
- <div class="tab-content">
- <div id="properties_tab" class="tab-pane fade in active"></div>
-
- </div>
-
- </div>
- </div>
- <span id="formSpan" style="display: none">
- <form class="saveProps" class="form-horizontal">
- <div>
-
- <div class="form-group">
- <label class="col-sm-4 control-label">Field Path / Counter</label>
- <div class="col-sm-8">
- <select class="form-control" id="fieldPath" name="fieldPath"></select>
+
+ <form class="tcaParentItems">
+ <div class="row">
+ <div class="col-sm-8 form-group">
+ <label class="col-sm-3"> Name </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <input class="form-control" type="text" maxlength="48" id="tname" name="tname"></input>
+ </div>
+ </div>
+
+ <div class="col-sm-8 form-group" style="display:none;">
+ <label class="col-sm-3"> UUID </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <input class="form-control" onkeydown="return false;" type="text" id="tuuid" name="tuuid"></input>
+ </div>
+ </div>
+
+ <div class="col-sm-8 form-group" style="display:none;">
+ <label class="col-sm-3"> NF Code </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <input class="form-control" onkeydown="return false;" type="text" id="tnfc" name="tnfc"></input>
+ </div>
+ </div>
+
+ <div class="col-sm-3 form-group">
+ <label class="col-sm-8"> Enable </label>
+ <input class="col-sm-4" type="checkbox" style="height:21px;
+ width:21px; margin:6px;" checked="checked" id="tcaEnab" name="tcaEnab"></input>
</div>
</div>
- <div class="form-group">
- <label class="col-sm-4 control-label">Threshold</label>
- <div class="col-sm-8">
- <input type="number" min="0" class="form-control"
- name="threshold" id="threshold">
- </input>
+ <div class="row">
+ <div class="col-sm-8 form-group">
+ <label class="col-sm-3"> Policy </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <select name="tcaPol" id="tcaPol" enableFilter="false"></select>
+ </div>
+ </div>
+
+ <div class="col-sm-8 form-group" style="display:none;">
+ <label class="col-sm-3"> Policy ID </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <input class="form-control" onkeydown="return false;" type="text" id="tcaPolId" name="tcaPolId"></input>
+ </div>
+ </div>
+
+ <div class="col-sm-3 form-group">
+ <label class="col-sm-8">Max Intervals</label>
+ <input class="col-sm-4 form-control" style="width:80%" type="text" maxlength="3"
+ id="tcaInt" onkeypress="return isNumberKey(event)" name="tcaInt"></input>
</div>
</div>
-
-
- <div class="form-group">
- <label class="col-sm-4 control-label">Operator</label>
- <div class="col-sm-8">
- <select class="form-control" id="operator" name="operator"></select>
+ <div class="row">
+ <div class="col-sm-8 form-group">
+ <label class="col-sm-3"> Severity </label>
+ <div class="col-sm-9" style="padding:0px;">
+ <select name="tcaSev" id="tcaSev" enableFilter="false">
+ </select>
+ </div>
+ </div>
+
+ <div class="col-sm-3 form-group">
+ <label class="col-sm-8">Min Violations</label>
+ <input class="col-sm-4 form-control" style="width:80%" type="text" maxlength="3"
+ id="tcaVio" onkeypress="return isNumberKey(event)" name="tcaVio"></input>
</div>
</div>
+ </form>
+
+ <div class="tcaBody row">
+ <div class="col-sm-5" style="padding:0px 5px; margin: 15px;">
+ <div class="panel panel-default" id="tcaTableHolder">
+ <table id="tcaTable">
+ </table>
+ </div>
+ <div id="tcaError" class="tcaErr">Error: Please define/delete this new threshold</div>
+ <div id="tcaUnique" class="tcaErr">Error: Duplicate Set Name Found</div>
+ <div style="float:left">
+ <button type="button" id="createNewThresh" class="btn btn-sm">New Threshold</button>
+ </div>
+ <div style="float:right">
+ <button type="button" id="deleteThresh" class="btn btn-sm glyphicon glyphicon-trash" disabled></button>
+ </div>
+
+ </div>
-
-
- <div class="form-group">
- <label class="col-sm-4 control-label">Ops Policy</label>
-
- <div class="col-sm-8">
- <select class="form-control" id="opsPolicy" name="opsPolicy"
- enableFilter="false" ></select>
+ <div id="tcaEditHolder" class="panel panel-default col-sm-6">
+ <div class="tab-content">
+ <div id="properties_tab" style="padding:10px;" class="form-horizontal">
+ <div style="margin-bottom:20px;">
+ <label class="control-label">Metric</label>
+ <div>
+ <select id="fieldPathM" name="fieldPathM"></select>
+ </div>
+ </div>
+ <div style="margin-bottom:20px;">
+ <label class="control-label">Operator</label>
+ <div>
+ <select id="operator" name="operator"></select>
+ </div>
+ </div>
+ <div style="margin-bottom:20px;">
+ <label class="control-label">Threshold</label>
+ <div>
+ <input type="text" maxlength="10" class="form-control" name="threshold"
+ onkeypress="return isNumberKey(event)" id="threshold"></input>
+ </div>
+ </div>
+ </div>
</div>
</div>
</div>
-
- </form>
- </span>
+
+ </div>
+ </span>
+
+ </div>
</div>
+</div>
<div class="modal-footer">
<!--<button ng-click="reset()" class="btn btn-primary" style="float:left">Reset</button>-->
<button id="savePropsBtn" class="btn btn-primary">Close</button>
<button ng-click="close(true)" id="close_button"
class="btn btn-primary">Cancel</button>
-
</div>
+
<script>
- //Basically this method will add a new form. All forms share the same class. When you want one form to show(active form) the other forms get the
- // css attribute display:none
- $("#add_one_more").click(function(event) {
+ var generateTUUID = function(count){
+ var d = new Date().getTime();
+ var tuuid = 'xxxxxxxx-xxxx-txxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function(c){
+ var r = (d + Math.random()*16)%16 | 0;
+ d = Math.floor(d/16);
+ return (c == 'x' ? r : (r*0x3|0*8)).toString(16);
+ });
+ $("#formId" + count + " #tuuid").val(tuuid);
+ }
+
+ $("#add_one_more").click(function(event) {
event.preventDefault();
- add_one_more();
- setMultiSelect();
+ if ($("#nav_Tabs li.active").length>0){
+ var oldCount = $("#nav_Tabs li.active").find("a").attr("id").slice(-1);
+ if (($('#formId'+oldCount+' #tcaTable .highlight').length > 0 ) &&
+ (!($('#formId'+oldCount+' #threshold').val()) || !($('#formId'+oldCount+' #fieldPathM').val())) ) {
+ $('#formId'+oldCount+' #tcaError').show();
+ return;
+ } else {
+ $('#formId'+oldCount+' .tcaErr').hide();
+ if ($('#formId'+oldCount+' #tcaTable .highlight').length > 0){
+ $('#formId'+oldCount+' #tcaTable .highlight td').text(
+ $('#formId'+oldCount+' #fieldPathM').val() + ' ' +
+ $('#formId'+oldCount+' #operator').val() + ' ' +
+ $('#formId'+oldCount+' #threshold').val());
+ }
+ $("#formId"+oldCount+" #tcaTable .highlight").removeClass("highlight")
+ }
+ }
+ var count = add_one_more();
+ generateTUUID(count);
})
- loadPropertyWindow("tca")
+ loadPropertyWindow("tca");
+
+ //load dropdown with policy options
+ if (typeof allPolicies !== "undefined"){
+ $.each(Object.keys(allPolicies), function(val, text) {
+ $('#tcaPol').append($('<option></option>').val(text).html(text));
+ });
+ } else if (typeof elementMap !== "undefined"){
+ for (key in elementMap){
+ if (key.indexOf("Policy")>-1){
+ $.each(Object.keys(elementMap[key]), function(val, text){
+ $('#tcaPol').append(
+ $('<option></option>').val(text).html(text)
+ );
+ });
+ }
+ }
+ }
+
setASDCFields();
+
+ //load metrics dropdown
+ if (elementMap["global"]){
+ for (var i = 0; i < (elementMap["global"].length); i++){
+ if ((elementMap["global"][i]["name"]) == "vf"){
+ var vfSel = elementMap["global"][i]["value"];
+ if (vf_Services["shared"]["byVf"][vfSel]["kpi"]){
+ $.each((vf_Services["shared"]["byVf"][vfSel]["kpi"]), function(val, text) {
+ $('#fieldPathM').append(
+ $('<option></option>').val(val).html(text)
+ );
+ });
+ }
+ break;
+ };
+ };
+ };
+
var arr = elementMap[lastElementSelected];
- var vfc_temp=""
- var alarm_conditions_temp=""
- var event_severity_temp=""
- var event_type_source_temp=""
+
if (arr !== undefined) {
- //arr[0]
- var el=arr[1]['serviceConfigurations']
- for (var i = 0; i < el.length; i++) {
- var num=add_one_more();
- for(var j=0;j<el[i].length;j++){
- if(el[i][j].name==="vfc"){
- vfc_temp=el[i][j].value
- }else if(el[i][j].name==="alarmCondition"){
- alarm_conditions_temp=el[i][j].value
- }else if(el[i][j].name==="eventSeverity"){
- event_severity_temp=el[i][j].value;
- }else if(el[i][j].name==="eventSourceType"){
- event_type_source_temp=el[i][j].value;
+ for (var x in arr){
+ var num = add_one_more();
+ var setCheck = true;
+ for (var i=0; i< arr[x].length; i++){
+ if (arr[x][i].name=='tcaEnab'){
+ $("#formId" + num + " #tcaEnab").prop("checked","true");
+ setCheck = false;
}
- else
- $("#formId"+num+" #" + el[i][j].name).val(el[i][j].value);
-
- }
-
- set_vfc_alarm_event(num)
- vfc_temp=""
- alarm_conditions_temp=""
- event_severity_temp=""
- event_type_source_temp=""
-
- }
-
- $("#"+ arr[0][0].name).val(arr[0][0].value);
-
-
- }
-
- function set_vfc_alarm_event (count){
- if(vfc_temp!=="" && vfc_temp!==undefined){
- $("#formId"+count+" #vfc").val(vfc_temp)
-
- if(alarm_conditions_temp!=="" && alarm_conditions_temp!==undefined){
- setAlarmConditions(vfc_temp,count)
- $("#formId"+count+" #alarmCondition").val(alarm_conditions_temp)
-
- if(event_severity_temp!=="" && event_severity_temp!==undefined){
- setEventSourceType(alarm_conditions_temp,count)
- $("#formId"+count+" #eventSeverity").val(event_severity_temp)
- if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
- $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
- }
- }
- if(event_type_source_temp!=="" && event_type_source_temp!==undefined){
- setEventSourceType(alarm_conditions_temp,count)
- $("#formId"+count+" #eventSourceType").val(event_type_source_temp)
- if(event_severity_temp!=="" && event_severity_temp!==undefined){
- $("#formId"+count+" #eventSeverity").val(event_severity_temp)
+ if (arr[x][i].hasOwnProperty('serviceConfigurations')){
+ for (var j=0; j<arr[x][i]["serviceConfigurations"].length; j++){
+ $("#formId" + num + " #tcaTable").prepend("<tr><td>"
+ +arr[x][i]["serviceConfigurations"][j][0]+" "
+ //+(defaults_props['tca']['operator']).getKey(arr[x][i]["serviceConfigurations"][j][1])+" "
+ +(Object.keys(defaults_props['tca']['operator']).find(key => defaults_props['tca']['operator'][key] == (arr[x][i]["serviceConfigurations"][j][1])))+ " "
+ +arr[x][i]["serviceConfigurations"][j][2]+"</td></tr>");
}
+ } else {
+ $("#formId" + num + " #"+arr[x][i].name).val(arr[x][i].value);
}
}
+ if (setCheck){
+ $("#formId" + num + " #tcaEnab").prop("checked",false);
+ }
+ $('#go_properties_tab'+num).text($('#formId' +num+ ' #tname').val());
+ $("#formId"+num + " #properties_tab").hide();
}
-
-
- }
-
-
- function noRepeats(form){
- var select={};
- for(var i=0;i<form.length;i++){
- if(select[form[i].name]===undefined)
- select[form[i].name]=[]
- select[form[i].name].push(form[i].value);
- }
- var arr=[]
- for(s in select){
- var f={}
- f.name=s
- f.value=select[s]
- arr.push(f)
- }
- return arr
- }
+ }
$("#savePropsBtn").click(function(event) {
- var form=[]
- var properties=$(".saveProps").not("#formSpan .saveProps")
- var topicP=$("#topicPublish").serializeArray()
- form.push(topicP)
- var d={}
- d["serviceConfigurations"]=[];
-
- for(var i=0;i<properties.length;i++){
- var ser=$(properties[i]).serializeArray();
- var s=noRepeats(ser)
+ var num = $('#nav_Tabs .active a').attr('id').slice(-1);
+ var tabs = [];
+ $('#nav_Tabs li:not(:last)').each(function(){
+ tabs.push($(this).text());
+ });
+ var nonunique = uniquet(tabs);
+ if (($('#formId'+num+' #tcaTable .highlight').length > 0 ) &&
+ (!($('#formId'+num+' #threshold').val()) || !($('#formId'+num+' #fieldPathM').val())) ) {
+ $('#formId'+num+' #tcaError').show();
+ return;
+ } else if (nonunique){
+ $('#formId'+num+' #tcaUnique').show();
+ return;
+ } else {
+ $('#formId'+num+' .tcaErr').hide();
+ if ($('#formId'+num+' #tcaTable .highlight').length > 0){
+ $('#formId'+num+' #tcaTable .highlight td').text(
+ $('#formId'+num+' #fieldPathM').val() + ' ' +
+ $('#formId'+num+' #operator').val() + ' ' +
+ $('#formId'+num+' #threshold').val());
+ }
+ var saveP = {};
+ $('.formId').each(function(){
+ var count = $(this).attr('id').slice(-1);
+ var header = $(this).find('.tcaParentItems').serializeArray();
+ var sconf = {};
+ var sconfa = [];
+ var checkNF = true;
+ $('#formId' +count+' #tcaTable tr').each(function(){
+ $('td', this).each(function(){
+ var splitTd = $(this).text().split(' ');
+ splitTd[1]=defaults_props['tca']['operator'][splitTd[1]];
+ var checkByKpi = vf_Services["shared"]["byKpi"][splitTd[0].replace(/\s/g, "")];
+ if (checkByKpi["fieldPath"]){
+ splitTd.push(Object.keys(vf_Services["shared"]["byKpi"][splitTd[0].replace(/\s/g, "")]["fieldPath"])[0]);
+ };
+ if ((checkByKpi["nfNamingCode"]) && (checkNF)){
+ $.grep(header, function(e,i){
+ if (e.name == "tnfc"){
+ header[i]["value"] = (Object.keys(checkByKpi["nfNamingCode"])[0]);
+ }
+ });
+ checkNF = false;
+ }
+ sconfa.push(splitTd);
+ });
+
+ });
+ var polSel = $(this).find('.tcaParentItems #tcaPol').val();
+ $.grep(header, function(e,i){
+ if (e.name == "tcaPolId"){
+ if (polSel){
+ if (typeof allPolicies !== "undefined"){
+ header[i]["value"] = allPolicies[polSel][1]["value"];
+ } else if (typeof elementMap !== "undefined"){
+ for (key in elementMap){
+ if (key.indexOf("Policy")>-1){
+ header[i]["value"] = elementMap[key][polSel][1]["value"];
+ }
+ }
+ }
+ } else {
+ header[i]["value"]="";
+ }
+ }
+ });
+
+ sconf["serviceConfigurations"]=sconfa;
+ header.push(sconf);
+ saveP[$(this).find('.tcaParentItems #tname').val()] = header;
+ });
-
- d["serviceConfigurations"].push(s)
+ saveProperties(saveP);
+ $("#close_button").click();
}
- form.push(d)
- saveProperties(form)
-
- $("#close_button").click();
-
})
+ function uniquet(arr) {
+ var a = [];
+ for (var i=0, l=arr.length; i<l; i++){
+ if (a.indexOf(arr[i]) === -1 && arr[i] !== ''){
+ a.push(arr[i]);
+ }
+ }
+ if (a.length==arr.length){
+ return false;
+ } else {
+ return true;
+ }
+ }
function add_one_more(){
$("#nav_Tabs li").removeClass("active");
- var form=$($("#formSpan").children()[0]).clone()
+ var form=$($("#formSpan").children()[0]).clone();
var count=0;
if($(".formId").length>0){
var greatest=0;
}
}
count=greatest+1;
- $("#properties_tab").append(('<span class="formId" id="formId'+count+'"></span>'));
+ $("#panelHolder").append(('<span class="formId" id="formId'+count+'"></span>'));
}else{
count++;
- $("#properties_tab").append('<span class="formId" id="formId1"></span>');
+ $("#panelHolder").append('<span class="formId" id="formId1"></span>');
}
- $("#add_one_more").parent().before(' <li class="active"><a id="go_properties_tab'+count+'">Condition</a><button id="tab_close'+count+'" type="button" class="close tab-close-popup" aria-hidden="true" style="margin-top: -30px;margin-right: 5px">×</button></li>');
+
+ $("#add_one_more").parent().before(' <li class="active"><a id="go_properties_tab'+count+'">New_Set</a><button id="tab_close'+count+'" type="button" class="close tab-close-popup" aria-hidden="true" style="margin-top: -30px;margin-right: 5px">×</button></li>');
$("#formId"+count).append(form);
- $(".formId").not($("#formId"+count)).css("display","none")
- addCustListen(count)
- add_vfc_alarm_event_listener(count)
+ $('#formId'+count+ ' #properties_tab').hide();
+ $(".formId").not($("#formId"+count)).css("display","none");
+ addCustListen(count);
+ setMultiSelect();
return count;
}
-
- function addCustListen(count) {
+
+ function isNumberKey(event){
+ var charCode = (event.which) ? event.which : event.keyCode
+ if (charCode > 31 && (charCode < 48 || charCode > 57)){
+ return false;
+ }
+ return true;
+ };
+
+ function addCustListen(count) {
$('#go_properties_tab' + count).click(function(event) {
+ if ($("#nav_Tabs li.active").length>0){
+ var oldCount = $("#nav_Tabs li.active").find("a").attr("id").slice(-1);
+ if (($('#formId'+oldCount+' #tcaTable .highlight').length > 0 ) &&
+ (!($('#formId'+oldCount+' #threshold').val()) || !($('#formId'+oldCount+' #fieldPathM').val())) ) {
+ $('#formId'+oldCount+' #tcaError').show();
+ return;
+ } else {
+ $('#formId'+oldCount+' .tcaErr').hide();
+ if ($('#formId'+oldCount+' #tcaTable .highlight').length > 0){
+ $('#formId'+oldCount+' #tcaTable .highlight td').text(
+ $('#formId'+oldCount+' #fieldPathM').val() + ' ' +
+ $('#formId'+oldCount+' #operator').val() + ' ' +
+ $('#formId'+oldCount+' #threshold').val());
+ }
+ $("#formId"+oldCount+" #tcaTable .highlight").removeClass("highlight")
+ }
+ }
+
$("#nav_Tabs li").removeClass("active");
$(this).parent().addClass("active");
- $("#formId"+count).css("display","")
- $(".formId").not($("#formId"+count)).css("display","none")
-
- })
+ $("#formId"+count).css("display","");
+ $(".formId").not($("#formId"+count)).css("display","none");
+ });
+
$('#tab_close'+count).click(function(event){
- if(document.getElementById("topicPublishes").disabled){
- return false;
- }
$(this).parent().remove();
$("#formId"+count).remove();
- })
- }
-
-function setAlarmConditions(vfcID, count){
- var alarmCondition={}
-
- /*if($("#formId"+count+" #vfc").val()!=="")
- alarmCondition=vf_Services['shared']['byVfc'][vfcID]['alarmCondition']*/
-
- if($("#formId"+count+" #vfc").val()!==""){
- if(vf_Services && vf_Services['shared'] && vf_Services['shared']['byVfc'] && vf_Services['shared']['byVfc'][vfcID]){
- alarmCondition=vf_Services['shared']['byVfc'][vfcID]['alarmCondition'];
- }
- }
-
- $("#formId"+count+" #alarmCondition").empty();
- $("#formId"+count+" #alarmCondition").append("<option value=\"\"></opton>")
- if(alarmCondition && _.keys(alarmCondition).length>0){
- for(key in alarmCondition){
- var safestring = $('<div>').text(key).html();
- $("#formId"+count+" #alarmCondition").append("<option value='"+safestring+"'>"+alarmCondition[key]+"</opton>")
-
- }
- }
-
-}
-
-function setEventSourceType(alarm, count){
- var eventSourceTypSeverity={}
- if($("#formId"+count+" #alarmCondition").val()!=="") {
- if(vf_Services && vf_Services['shared'] && vf_Services['shared']['byAlarmCondition'] && vf_Services['shared']['byAlarmCondition'][alarm]){
-
- eventSourceTypSeverity=vf_Services['shared']['byAlarmCondition'][alarm]
- }
- }
-
- $("#formId"+count+" #eventSourceType").val(eventSourceTypSeverity.eventSourceType);
- $("#formId"+count+" #eventSeverity").val(eventSourceTypSeverity.eventSeverity);
-
-}
-
- function add_vfc_alarm_event_listener(count) {
-
- $("#formId"+count+" #vfc").on('focus', function () {
- // Store the current value on focus and on change
- previous = this.value;
- }).change(function(){
-
- setAlarmConditions($("#formId"+count+" #vfc").val(), count);
- $("#formId"+count+" #eventSourceType").val("");
- $("#formId"+count+" #eventSeverity").val("")
-
- });
-
- $("#formId"+count+" #alarmCondition").on('focus', function () {
- // Store the current value on focus and on change
- previous = this.value;
- }).change(function(){
+ });
+
+ $('#formId'+count+' #tcaTable').on('click', 'tr', function(event){
+ if (($('#formId'+count+' #tcaTable .highlight').length > 0 ) &&
+ (!($('#formId'+count+' #threshold').val()) || !($('#formId'+count+' #fieldPathM').val())) ) {
+ $('#formId'+count+' #tcaError').show();
+ return;
+ } else {
+ $('#formId'+count+' .tcaErr').hide();
+ if ($('#formId'+count+' #tcaTable .highlight').length > 0){
+ $('#formId'+count+' #tcaTable .highlight td').text(
+ $('#formId'+count+' #fieldPathM').val() + ' ' +
+ $('#formId'+count+' #operator').val() + ' ' +
+ $('#formId'+count+' #threshold').val());
+ }
+ //$('#formId'+count+' #tcaTable .highlight').text();
+ $(this).addClass('highlight').siblings().removeClass('highlight');
+ var str = $(this).text().split(' ');
+ $('#formId'+count + ' #properties_tab').show();
+ if (str.length == 3){
+ $('#formId'+count+' #fieldPathM').val(str[0]).multiselect('refresh');
+ $('#formId'+count+' #operator').val(str[1]).multiselect('refresh');
+ $('#formId'+count+' #threshold').val(str[2]);
+ }
+ if ((!(readOnly||readMOnly)) && ($('#formId'+count + ' #deleteThresh').prop('disabled'))) {
+ $('#formId'+count + ' #deleteThresh').prop('disabled', false);
+ }
+ }
+ });
+
+ $('#formId'+count+' #deleteThresh').on('click', function(){
+ $('#formId'+num+' .tcaErr').hide();
+ $('#formId'+count+ ' #properties_tab').hide();
+ $('#formId'+count+ ' #tcaTable .highlight').remove();
+ $('#formId'+count+ ' #deleteThresh').prop('disabled', true);
+ });
+
+ $('#formId'+count+' #createNewThresh').on('click', function(){
+ if (($('#formId'+count+' #tcaTable .highlight').length > 0 ) &&
+ (!($('#formId'+count+' #threshold').val()) || !($('#formId'+count+' #fieldPathM').val())) ){
+ $('#formId'+count+' #tcaError').show();
+ return;
+ } else {
+ $('#formId'+count+' .tcaErr').hide();
+ if ($('#formId'+count+' #tcaTable .highlight').length > 0){
+ $('#formId'+count+' #tcaTable .highlight td').text(
+ $('#formId'+count+' #fieldPathM').val() + ' ' +
+ $('#formId'+count+' #operator').val() + ' ' +
+ $('#formId'+count+' #threshold').val());
+ }
+ $('#formId'+count+ ' #properties_tab').show();
+ if (('#formId'+count+' #tcaTable .highlight').length > 0 ){
+ $('#formId'+count+' #tcaTable tr.highlight').removeClass('highlight');
+ }
+ $('#formId'+count+' #tcaTable').prepend('<tr class="highlight"><td>New Threshold</td></tr>');
+ $('#formId'+count+' #fieldPathM').prop("selectedIndex", 0).multiselect('refresh');
+ $('#formId'+count+' #operator').prop("selectedIndex", 0).multiselect('refresh');
+ $('#formId'+count+' #threshold').val("");
- setEventSourceType($("#formId"+count+" #alarmCondition").val().toString(),count);
- });
- };
+ if ($('#formId'+count + ' #deleteThresh').prop('disabled')) {
+ $('#formId'+count + ' #deleteThresh').prop('disabled', false);
+ }
+ }
+ });
+
+ $('#formId'+count+' #tname').on('change',function(){
+ $('#go_properties_tab'+count).text($('#formId'+count+' #tname').val())
+ });
+ }
</script>
-</div>
-
+</div>
\ No newline at end of file