aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDeterme, Sebastien (sd378r) <sd378r@intl.att.com>2017-08-08 03:10:28 -0700
committerSébastien Determe <sd378r@intl.att.com>2017-08-08 12:35:50 +0000
commita1171303f4017991cf4e41fd2202d8e165b70732 (patch)
treec8653768f94188e8a9511916a439735af851f984 /src
parent5a7bab3cf8dcc44ce306828619d09d43998174f0 (diff)
Rework the Designer UI (part1)
Rework the Designer UI (part1), mainly html pages + javascripts Change-Id: I216e9ef65da91b2be3bf39e591220e6060578192 Issue-Id: CLAMP-1 Signed-off-by: Determe, Sebastien (sd378r) <sd378r@intl.att.com>
Diffstat (limited to 'src')
-rw-r--r--src/main/resources/META-INF/resources/designer/authenticate.html37
-rw-r--r--src/main/resources/META-INF/resources/designer/index.html3
-rw-r--r--src/main/resources/META-INF/resources/designer/lib/multiselect.js3432
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/menu.html23
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html498
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/clds_create_model_off_Template.html100
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/clds_modelling.html12
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_model.html4
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_template.html4
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/global_properties.html165
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/refresh_asdc.html2
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/stringMatch_properties.html1102
-rw-r--r--src/main/resources/META-INF/resources/designer/partials/portfolios/tca_properties.html697
-rw-r--r--src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js139
14 files changed, 3484 insertions, 2734 deletions
diff --git a/src/main/resources/META-INF/resources/designer/authenticate.html b/src/main/resources/META-INF/resources/designer/authenticate.html
index 0db00c3d..8b30ef8c 100644
--- a/src/main/resources/META-INF/resources/designer/authenticate.html
+++ b/src/main/resources/META-INF/resources/designer/authenticate.html
@@ -20,8 +20,41 @@
===================================================================
ECOMP is a trademark and service mark of AT&T Intellectual Property.
-->
+<style>
+.divRow {
+ margin-left: 5px;
+ font-size: 20px;
+ font-weight: normal;
+}
+.divFormRow {
+ margin-left: 5px;
+ font-size: 13px;
+ font-weight: normal;
+}
-<div ng-init="authenticate()">
- <b>Validating Login.... Please wait....</b>
+.divRow + .divForm {
+ margin-top:10px;
+}
+</style>
+
+<head>
+ <title>CLDS</title>
+</head>
+<div ng-controller="AuthenticateCtrl">
+ <div id='head'>
+ <div ng-include="'menu_simplified.html'"></div>
+ </div>
+
+ <div id='main'>
+ <div class="divRow"><b>Welcome to Clamp. Please login first.</b></div>
+ <div class="divForm">
+ <form ng-submit="authenticate()">
+ <div class="divFormRow"><label>User Name : <input type="text" ng-model="username" name="username"/> </label></div>
+ <div class="divFormRow"><label>Password: <input type="password" ng-model="password" name="password"/> </label></div>
+ <div class="divFormRow"><input type="submit" value=" Sign In"/></div>
+ </form>
+ </div>
+ </div>
</div>
+
diff --git a/src/main/resources/META-INF/resources/designer/index.html b/src/main/resources/META-INF/resources/designer/index.html
index a63bfd6b..31b20e34 100644
--- a/src/main/resources/META-INF/resources/designer/index.html
+++ b/src/main/resources/META-INF/resources/designer/index.html
@@ -118,6 +118,7 @@
<!-- <script src="lib/angular.min.js"></script>-->
<script src="lib/angular-route.js"></script>
<script src="lib/angular-resource.min.js"></script>
+ <script src="lib/angular-md5.js"></script>
<!-- jQuery Include and Bootstrap -->
@@ -209,6 +210,8 @@
<script src="scripts/AutosaveProjectCtrl.js"></script>
<script src="scripts/userPreferencesService.js"></script>
+ <script src="scripts/ExtraUserInfoCtrl.js"></script>
+ <script src="scripts/ExtraUserInfoService.js"></script>
<script src="scripts/saveConfirmationModalPopUpCtrl.js"></script>
<script src="scripts/CldsTemplateService.js"></script>
<script src="scripts/CldsOpenTemplateCtrl.js"></script>
diff --git a/src/main/resources/META-INF/resources/designer/lib/multiselect.js b/src/main/resources/META-INF/resources/designer/lib/multiselect.js
index 9a50a18a..fac82e89 100644
--- a/src/main/resources/META-INF/resources/designer/lib/multiselect.js
+++ b/src/main/resources/META-INF/resources/designer/lib/multiselect.js
@@ -1,1716 +1,1716 @@
-/**
- * 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);
+/**
+ * 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);
diff --git a/src/main/resources/META-INF/resources/designer/partials/menu.html b/src/main/resources/META-INF/resources/designer/partials/menu.html
index dd4dae42..e4f617cc 100644
--- a/src/main/resources/META-INF/resources/designer/partials/menu.html
+++ b/src/main/resources/META-INF/resources/designer/partials/menu.html
@@ -132,7 +132,8 @@
<li ng-repeat="section in tabs[dropDownName]"
ng-if="section.name==='Create CL'"><a
id="{{section.name}}" role="presentation"
- ng-click="emptyMenuClick(section.link,section.name)">{{section.name}}</a>
+ ng-click="emptyMenuClick(section.link,section.name)"
+ ng-class="{true:'ThisLink', false:''}[!(userInfo['permissionUpdateCl'])]">{{section.name}}</a>
</li>
<li ng-repeat="section in tabs[dropDownName]"
@@ -142,24 +143,35 @@
</li>
<li ng-repeat="section in tabs[dropDownName]"
- ng-if="section.name==='Create Template'"><a
+ ng-if="section.name==='Log Out'"><a
id="{{section.name}}" role="presentation"
ng-click="emptyMenuClick(section.link,section.name)">{{section.name}}</a>
</li>
<li ng-repeat="section in tabs[dropDownName]"
+ ng-if="section.name==='Create Template'"><a
+ id="{{section.name}}" role="presentation"
+ ng-click="emptyMenuClick(section.link,section.name)"
+ ng-class="{true:'ThisLink', false:''}[!(userInfo['permissionUpdateTemplate'])]">{{section.name}}</a>
+ </li>
+
+ <li ng-repeat="section in tabs[dropDownName]"
ng-if="section.name==='Open Template'"><a
id="{{section.name}}" role="presentation"
ng-click="emptyMenuClick(section.link,section.name)">{{section.name}}</a>
</li>
<li ng-repeat="section in tabs[dropDownName]"
- ng-if="section.name != 'Create CL' && section.name != 'Create Template' && section.name != 'Open CL' && section.name != 'Open Template' && section.name != 'ONAP User Guide - Design Overview' && section.name != 'ONAP User Guide - Closed Loop Design' && section.name != 'ONAP User Guide - CLAMP'"><a
+ ng-if="section.name != 'Create CL' && section.name != 'Create Template' && section.name != 'Open CL' && section.name != 'Open Template' && section.name != 'ECOMP User Guide - Design Overview' && section.name != 'ECOMP User Guide - Closed Loop Design' && section.name != 'ECOMP User Guide - CLAMP' && section.name != 'User Info'"><a
id="{{section.name}}" role="presentation"
ng-click="emptyMenuClick(section.link,section.name)"
class="ThisLink">{{section.name}}</a>
</li>
-
+ <li ng-repeat="section in tabs[dropDownName]"
+ ng-if="section.name==='User Info'"><a
+ id="{{section.name}}" role="presentation"
+ ng-click="emptyMenuClick(section.link,section.name)">{{section.name}}</a>
+ </li>
<li ng-repeat="section in tabs[dropDownName]"
ng-if="section.name == 'ONAP User Guide - Design Overview' || section.name == 'ONAP User Guide - Closed Loop Design' || section.name == 'ONAP User Guide - CLAMP'"><a
id="{{section.name}}" role="presentation"
@@ -181,8 +193,7 @@
<li class="dropdown" style="height: inherit"><a
class="navbar-brand logo_name" active-link="active"
class="dropdown-toggle dropdownTitle" role="button"
- data-toggle="dropdown" style="height: inherit;">Hello:
- {{loginuser}} </a></li>
+ data-toggle="dropdown" style="height: inherit;">Hello:{{loginuser}} </a></li>
</ul>
</div>
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html
index 7adeb1b4..5e809ae0 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html
@@ -21,6 +21,7 @@
ECOMP is a trademark and service mark of AT&T Intellectual Property.
-->
+
<style>
#deletePolicy{
height:34px;
@@ -59,13 +60,7 @@
margin-top: 17px;
}
-.form-group {
-/* height:24px; */
-/* box-sizing:border-box; */
- margin-bottom:20px;
-}
-
-.glyphicon-search{
+.modelSearchBox{
position:absolute;
padding: 25px 12px;
}
@@ -85,14 +80,26 @@ label{
background-color:#f2bfab;
}
-#pname{
- height:28px;
- margin-left:-5px;
+.idError{
+ color:red;
+ padding:50px 0px;
+ text-align:center;
+ display:none;
}
.policyPanel{
background-color: #f5f5f5;
- padding: 10px 5px;
+ padding: 15px 5px 0 5px;
+}
+
+.form-group.clearfix{
+ display:-webkit-flex;
+ display: flex;
+ align-items: center;
+}
+
+label{
+ margin-bottom:0px;
}
#policySearch{
@@ -131,11 +138,6 @@ label{
overflow:auto;
}
-#timeout{
- height:28px;
- margin-left:10px;
-}
-
</style>
<script type="text/javascript">
@@ -170,12 +172,12 @@ label{
</div>
- <div class="container">
+ <div class="modal-body">
<div attribute-test="policywindowpropertiesb" class="modal-body row">
<div class="leftPolicyPanel">
<div class="panel panel-default">
- <i class="glyphicon glyphicon-search"></i>
+ <i class="glyphicon glyphicon-search modelSearchBox"></i>
<input type="text" id="policySearch" onkeyup="searchPolicyList()"
placeholder="Search ...">
<div id="policyTableHolder">
@@ -188,17 +190,30 @@ label{
<div style="float:right">
<button type="button" id="deletePolicy" class="btn btn-sm glyphicon glyphicon-trash" disabled></button></span>
</div>
+ <div id="repeatIdError" class="idError">Error: This Policy name is already taken.</div>
+ <div id="newIdError" class="idError">Error: Please rename your new Policy.</div>
+ <div id="spaceError" class="idError">Error: Spaces are not allowed in the ID.</div>
</div>
<div class="panel panel-default col-sm-9 policyPanel" style="display:none;">
<form id="Timeoutform" class="form-horizontal">
<div>
<div class="form-group clearfix row">
- <label style="margin-top:5px;" class="col-sm-2">Name</label>
- <input type="text" id="pname"; name="pname"; class="col-sm-4"></span>
+ <label class="col-sm-2">Name</label>
+ <div class="col-sm-3" style="padding:0px;">
+ <input type="text" id="pname" name="pname" maxlength="48" placeholder="Enter Unique Name" class="form-control">
+ </div>
- <label for="userID" class="col-sm-3" style="margin-top:5px; padding:0px;">Overall Time Limit</label>
- <input type="text" class="col-sm-2" id="timeout" name="timeout">
+ <label class="col-sm-1">ID</label>
+ <div class="col-sm-1" style="padding:0px;">
+ <input onkeydown="return false;" type="text" id="pid" name="pid" class="form-control" readonly>
+ </div>
+
+ <label for="userID" class="col-sm-3" style="padding-left:5px;padding-right:10px;">Overall Time Limit</label>
+ <div class="col-sm-2" style="padding-left:0px;">
+ <input type="text" maxlength="10" onkeypress="return isNumberKey(event)"
+ class="form-control" id="timeout" name="timeout">
+ </div>
</div>
</div>
</form>
@@ -219,7 +234,7 @@ label{
<form class="saveProps" class="form-horizontal">
<div>
<div class="form-group clearfix" >
- <label for="recipe" class="col-sm-4 control-label" >Recipe</label>
+ <label class="col-sm-4 control-label" for="recipe">Recipe</label>
<div class="col-sm-8">
<select class="form-control" name="recipe" id="recipe" enableFilter="false"></select>
</div>
@@ -228,20 +243,21 @@ label{
<label for="maxRetries" class="col-sm-4 control-label">
Max Retries</label>
<div class="col-sm-8">
- <input type="number" min="0" class="form-control" id="maxRetries"
+ <input type="text" maxlength="5" class="form-control" id="maxRetries"
+ onkeypress="return isNumberKey(event)"
name="maxRetries"> </input>
</div>
</div>
- <br />
<div class="form-group clearfix" >
<label for="retryTimeLimit" class="col-sm-4 control-label" >
Retry Time Limit</label>
<div class="col-sm-8">
- <input type="number" min="0" class="form-control" id="retryTimeLimit"
+ <input type="text" maxlength="5" class="form-control" id="retryTimeLimit"
+ onkeypress="return isNumberKey(event)"
name="retryTimeLimit"></input>
</div>
</div>
- <div hidden class="form-group clearfix">
+ <div style="display:none;" class="form-group clearfix">
<label for="_id" class="col-sm-4 control-label">
PolicyID</label>
<div class="col-sm-8">
@@ -262,7 +278,7 @@ label{
Parent Policy Conditions</label>
<div class="col-sm-8">
<select class="form-control" id="parentPolicyConditions"
- name="parentPolicyConditions" multiple size=2></select>
+ name="parentPolicyConditions" multiple></select>
</div>
</div>
</div>
@@ -283,17 +299,18 @@ label{
// css attribute display:none
$("#add_one_more").click(function(event) {
event.preventDefault();
- add_one_more();
+ var num = add_one_more();
setMultiSelect();
});
loadPropertyWindow("policy")
// by default, parentPolicyConditions is disabled
- $("#parentPolicyConditions").prop('disabled', 'disabled');
+ //$("#parentPolicyConditions").prop('disabled', 'disabled');
var parent_policy={}
var policy_ids={}
var loadingId=false;
var allPolicies={};
+ var allPolIds=[];
//Grab saved values for dropdowns
var obj = elementMap[lastElementSelected];
@@ -301,12 +318,17 @@ label{
if (!($.isEmptyObject(obj))){
allPolicies = jQuery.extend({}, obj);
for (var x in allPolicies){
- $("#policyTable").prepend("<tr id='"+x+"'><td>"+x+"</td></tr>");
+ $("#policyTable").prepend("<tr><td>"+x+"</td></tr>");
+ if (allPolicies[x][1]['value']){
+ allPolIds.push(parseInt(allPolicies[x][1]['value']));
+ }
}
}
+ $("#pname").val('');
//load recipes for a chosen policy
function disperseConfig(policyObj, id){
+ parent_policy={};
//remove old gui forms
for (var i=1; i<($(".formId").length + 1); i++){
$("#go_properties_tab"+i).parent().remove();
@@ -314,7 +336,7 @@ label{
$(".formId").remove();
if (policyObj !== undefined) {
- var el = policyObj[id][2]['policyConfigurations']
+ var el = policyObj[id][3]['policyConfigurations']
for (var i = 0; i < el.length; i++) {
loadingId=true;
var num = add_one_more();
@@ -345,17 +367,33 @@ label{
for(k in parent_policy){
$("#formId"+k+" #parentPolicy").val(parent_policy[k]);
+ if($("#formId"+k+" #parentPolicy").val() ==""){
+ $("#formId" +k+ " #parentPolicyConditions").multiselect("disable");
+ } else {
+ $("#formId" +k+ " #parentPolicyConditions").multiselect("enable");
+ }
// force the change event
$("#formId"+k+" #parentPolicy").change();
}
- if(policyObj[id][0] && policyObj[id][1]){
- $("#" + policyObj[id][0].name).val(policyObj[id][0].value);
- $("#" + policyObj[id][1].name).val(policyObj[id][1].value);
+ for (headInd in policyObj[id]){
+ if (!(policyObj[id][headInd].hasOwnProperty("policyConfigurations"))){
+ $("#" + policyObj[id][headInd].name).val(policyObj[id][headInd].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');
+ }
+
}
@@ -379,11 +417,26 @@ label{
}
$("#savePropsBtn").click(function(event) {
-
+ $(".idError").hide();
+ if ($("#policyTable .highlight td").html() !== $("#pname").val()){
+ //repeated name
+ if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ delete allPolicies[$("#policyTable .highlight td").html()];
+ }
+ }
+ if ($("#pname").val().trim() == "New_Policy"){
+ $("#newIdError").show();
+ return;
+ }
+
//Saves edits
- if ($("#policyTable .highlight").length > 0){
+ /* if ($("#policyTable .highlight").length > 0){
saveLastPolicyLocally($("#policyTable .highlight").attr("id"));
- }
+ } */
+ startNextItem();
//Removes outdated (deleted) policies by checking against left menu
var finalSaveList = {};
@@ -433,7 +486,7 @@ label{
$("#formId" + count).append(form);
$(".formId").not($("#formId" + count)).css("display", "none")
addCustListen(count)
- addTabListen(count)
+ //addTabListen(count)
// This is for when the process is not loading from map but being created
if(!loadingId){
var l=makeid()
@@ -443,21 +496,26 @@ label{
for(var i=1;i<=greatestIdNum();i++){
if($("#formId"+i).length>0){
-
- answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val()
+ answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val();
$("#formId"+i+" #parentPolicy").empty();
+
for(k in policy_ids){
- if($("#formId"+i+" #_id").val().toString()!==policy_ids[k] && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
- $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"''> "+$(k+" #recipe").val()+"</option>")
+ if(($("#formId"+i+" #_id").val()!==policy_ids[k].toString()) && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
+ $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"'>"+$(k+" #recipe").val()+"</option>")
}
}
$("#formId"+i+" #parentPolicy").prepend("<option value=''></option>")
}
}
+
+ $("#formId"+count+" #parentPolicyConditions").multiselect("disable");
+
+ //re-populate parent policy with chosen options
for(k in answers){
$(k).val(answers[k])
}
}
+
return count;
}
@@ -468,123 +526,35 @@ label{
}
$(".formId").remove();
- //Reset header
- var ms = new Date().getTime();
- var defPolName = "Policy" + ms;
- $("#pname").val(defPolName);
+ //Reset headers
+ //$("#pname").val("0");
+ $("#pname").val("New_Policy");
$("#timeout").val(defaults_props.policy.timeout);
- //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;
- //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");
- //for every recipe
- 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;
- $("#properties_tab").append(
- ('<span class="formId" id="formId'+count+'"></span>'));
- } else {
- count++;
- $("#properties_tab").append(
- '<span class="formId" id="formId1"></span>');
- }
-
- //$(form).find("#policyName").val("Recipe "+makid(2))
- //TODO change up how we auto assign policyName. There could be the case where we do this and it will have repeats
- //alert($(form).find("#_id").val())
- //policyNameChangeListener(form)
- $("#add_one_more")
- .parent()
- .before(
- ' <li class="active"><a id="go_properties_tab'+count+'">Policy</a><button id="tab_close'+count+'" type="button" class="close tab-close-popup" aria-hidden="true" style="margin-top: -30px;margin-right: 5px">&times;</button></li>');
- $("#formId" + count).append(form);
- $(".formId").not($("#formId" + count)).css("display", "none")
- addCustListen(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)
- policy_ids["#formId" + count]=l
- var answers={}
-
- for(var i=1;i<=greatestIdNum();i++){
- if($("#formId"+i).length>0){
-
- answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val()
- $("#formId"+i+" #parentPolicy").empty();
- for(k in policy_ids){
- if($("#formId"+i+" #_id").val().toString()!==policy_ids[k] && $(k+" #recipe").val()!==undefined && $(k+" #recipe").val()!==""){
- $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"''> "+$(k+" #recipe").val()+"</option>")
- }
- }
- $("#formId"+i+" #parentPolicy").prepend("<option value=''></option>")
- }
- }
- for(k in answers){
- $(k).val(answers[k])
- }
- }
-
-
-
- setMultiSelect();
- return defPolName;
+ $("#add_one_more").click();
}
//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("Policy");
-
- var answers={}
-
- for(var i=1;i<=greatestIdNum();i++){
- if($("#formId"+i).length>0){
-
- answers["#formId"+i+" #parentPolicy"]=$("#formId"+i+" #parentPolicy").val()
- $("#formId"+i+" #parentPolicy").empty();
-
- for(k in policy_ids){
- if($("#formId"+i+" #_id").val().toString()!==policy_ids[k] && $(k+" #recipe").val()!=='undefined' && $(k+" #recipe").val()!==""){
- $("#formId"+i+" #parentPolicy").append("<option value='"+policy_ids[k]+"''> "+$(k+" #recipe").val()+"</option>")
- }
- }
- $("#formId"+i+" #parentPolicy").prepend("<option value=''></option>")
- }
- }
- for(k in answers){
- $(k).val(answers[k])
- }
- })
+ function addTabListen(count){
// disable parentPolicyConditions when a parentPolicy is not selected
- $("#formId"+count+" #parentPolicy").on("change",function(){
+ //don't think this is used..
+ /* $("#formId"+count+" #parentPolicy").on("change",function(){
if($("#formId"+count+" #parentPolicy").val().toString()==""){
// deselect all options
$("#formId"+count+" #parentPolicyConditions option:selected").prop("selected", false);
// disable the select box
- $("#formId"+count+" #parentPolicyConditions").prop('disabled', 'disabled');
+ $("#formId"+count+" #parentPolicyConditions").multiselect("disable");
+
} else {
- $("#formId"+count+" #parentPolicyConditions").prop('disabled', false);
+ $("#formId"+count+" #parentPolicyConditions").multiselect("enable");
+
}
- })
+ }); */
}
-
- function addCustListen(count) {
+ function addCustListen(count) {
$('#go_properties_tab' + count).click(function(event) {
$("#nav_Tabs li").removeClass("active");
$(this).parent().addClass("active");
@@ -599,7 +569,6 @@ label{
$(this).parent().remove();
for(var i=1;i<=greatestIdNum();i++){
if( $("#formId"+i).length>0){
- //alert("fudge")
if(i!==count ){
if( $("#formId"+i+" #parentPolicy").val()===$("#formId"+count+" #_id").val().toString())
$("#formId"+i+" #parentPolicy").val("")
@@ -612,7 +581,8 @@ label{
})
}
- function greatestIdNum(){
+
+ function greatestIdNum() {
var greatest = 0;
var s = $(".formId");
for (var i = 0; i < s.length; i++) {
@@ -622,57 +592,58 @@ label{
}
return greatest;
}
-
+
//Generate random id for each policy
//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 policy_ids){
- if(text===policy_ids[k])
- hasValue=true
- }
- if (hasValue)
+ 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 policy_ids) {
+ if (text === policy_ids[k])
+ hasValue = true
+ }
+ if (hasValue)
return makeid(num);
else
return text
}
-
- var ParentPolicy=function(id,name){
- this.id=id
- this.name=name
+
+ var ParentPolicy = function(id, name) {
+ this.id = id
+ this.name = name
}
-
+
//Policy table search filter
function searchPolicyList() {
var search = document.getElementById("policySearch");
var row = document.getElementsByTagName("td");
- for (var i=0; i<row.length; i++){
- if (row[i].innerHTML.toUpperCase().indexOf(search.value.toUpperCase()) > -1){
+ 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";
}
}
}
-
- function saveLastPolicyLocally(lastPolicyId){
+
+ function saveLastPolicyLocally(lastPolicyId) {
var polForm = []
-
- var properties = $(".saveProps").not("#formSpan .saveProps")
+
+ var properties = $(".saveProps").not("#formSpan .saveProps");
var timeoutForm = $("#Timeoutform").serializeArray();
-
- for (var i=0; i<timeoutForm.length; i++){
+
+ for (var i = 0; i < timeoutForm.length; i++) {
polForm.push(timeoutForm[i]);
}
-
+
var d = {}
d["policyConfigurations"] = [];
for (var i = 0; i < properties.length; i++) {
@@ -684,66 +655,179 @@ label{
allPolicies[lastPolicyId] = polForm;
}
- $("#deletePolicy").on('click', function(){
- var deleteId = $("#policyTable .highlight").attr("id");
- delete allPolicies.deleteId;
+ function getNextId(){
+ var newPolId;
+ allPolIds.sort();
+ if ((Math.min.apply(Math, allPolIds) == 0)
+ && (allPolIds.length > 0)) {
+ loop1:
+ for (var i = 1; i < allPolIds.length; i++) {
+ if ((allPolIds[i] - allPolIds[i - 1]) != 1) {
+ newPolId = (allPolIds[i - 1] + 1);
+ break loop1;
+ };
+ };
+ if (!newPolId) {
+ newPolId = (Math.max.apply(Math, allPolIds)) + 1;
+ }
+ } else {
+ newPolId = 0;
+ }
+ allPolIds.push(newPolId);
+ $("#pid").val(newPolId);
+ }
+
+ $("#deletePolicy").on('click', function() {
+ $(".idError").hide();
+ //delete policy id
+ allPolIds.splice((allPolIds.indexOf(parseInt($("#pid").val()))),1);
+
+ //delete policy name
+ var deleteId = $("#policyTable .highlight td").html();
+ delete allPolicies[deleteId];
$("#policyTable .highlight").remove();
+ $("#pname").val('');
expandTable();
});
-
+
$('#policyTable').on('click', 'tr', function(event) {
- startNextItem();
-
+ $(".idError").hide();
+ //edited name
+ if ($("#policyTable .highlight td").html() !== $("#pname").val()){
+ //repeated name
+ if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ $("#repeatIdError").hide();
+ delete allPolicies[$("#policyTable .highlight td").html()];
+ }
+ }
+ //if (parseInt($("#pname").val()) == 0){
+ if ($("#pname").val().trim() == "New_Policy"){
+ $("#newIdError").show();
+ return;
+ }
+ if (!(readOnly||readMOnly)){
+ startNextItem();
+ } else {
+ if ($("#policyTable .highlight").length == 0){
+ collapseTable();
+ }
+ }
$(this).addClass('highlight').siblings().removeClass('highlight');
- disperseConfig(allPolicies, $(this).attr("id"));
+ disperseConfig(allPolicies, $(this).find("td").html());
});
-
+
$('#createNewPolicy').on('click', function(){
+ $(".idError").hide();
+ //edited name
+ if ($("#policyTable .highlight td").html() !== $("#pname").val()){
+ //repeated name
+ if ($.inArray($("#pname").val(), Object.keys(allPolicies)) > -1){
+ $("#repeatIdError").show();
+ return;
+ } else { //not repeated
+ $("#repeatIdError").hide();
+ delete allPolicies[$("#policyTable .highlight td").html()];
+ }
+ }
+ //if (parseInt($("#pname").val()) == 0){
+ if ($("#pname").val().trim() == "New_Policy"){
+ $("#newIdError").show();
+ return;
+ }
startNextItem();
-
- var defPolName = add_new_policy();
-
+ add_new_policy();
if (("#policyTable .highlight").length > 0){
$('#policyTable tr.highlight').removeClass('highlight');
}
- $("#policyTable").prepend("<tr class='highlight' id='" +defPolName+ "''><td>"+defPolName+"</td></tr>");
+ $("#policyTable").prepend("<tr class='highlight'><td>New_Policy</td></tr>");
+
+ getNextId();
+ });
+
+ $('#pname').on('keypress', function(e){
+ /* var newVal = $(this).val() + String.fromCharCode(e.which);
+ if ((newVal>99) || (($(this).val().length>2) && e.keyCode != 46 && e.keyCode !=8)){
+ e.preventDefault();
+ } */
+ if (e.keyCode == 32){
+ $("#spaceError").show();
+ e.preventDefault();
+ }
});
- function startNextItem(){
+ function isNumberKey(event){
+ var charCode = (event.which) ? event.which : event.keyCode
+ if (charCode > 31 && (charCode < 48 || charCode > 57)){
+ return false;
+ }
+ return true;
+ }
+
+ function startNextItem() {
//save last item before transitioning
var lastItem = $("#policyTable .highlight");
- if (lastItem.length > 0){
+ if (lastItem.length > 0) {
saveLastPolicyLocally($("#pname").val());
-
- lastItem.attr("id",$("#pname").val());
- $("#"+lastItem.attr("id")+" td").html($("#pname").val());
- } else{
+ //lastItem.attr("id", $("#pname").val());
+ lastItem.find("td").html($("#pname").val());
+ } else {
collapseTable();
}
-
+
//allow deleting
- if ($("#deletePolicy").prop("disabled")){
+ if ($("#deletePolicy").prop("disabled")) {
$("#deletePolicy").prop("disabled", false);
}
}
+ setASDCFields();
+
+ //load metrics dropdown
+ if (elementMap["global"]){
+ for (var i = 0; i < (elementMap["global"].length); i++){
+ if ((elementMap["global"][i]["name"]) == "actionSet"){
+ var asSel = elementMap["global"][i]["value"];
+ if (asSel == "vnfRecipe"){
+ if (vf_Services["policy"][asSel]){
+ $.each((vf_Services["policy"][asSel]), function(val, text) {
+ $('#recipe').append(
+ $('<option></option>').val(val).html(text)
+ );
+ });
+ }
+ break;
+ } else if (asSel == "enbRecipe"){
+ if (vf_Services["policy"][asSel]){
+ $.each((vf_Services["policy"][asSel]), function(val, text) {
+ $('#recipe').append(
+ $('<option></option>').val(val).html(text)
+ );
+ });
+ }
+ break;
+ }
+ };
+ };
+ };
+
//Show table panel only
- function expandTable(){
- $(".policyPanel").css("display","none");
+ function expandTable() {
+ $(".policyPanel").css("display", "none");
$(".leftPolicyPanel").removeClass("col-sm-3");
- $(".glyphicon-search").css("padding", "25px 12px");
- if (!($("#deletePolicy").prop("disabled"))){
+ $(".modelSearchBox").css("padding", "25px 12px");
+ if (!($("#deletePolicy").prop("disabled"))) {
$("#deletePolicy").prop("disabled", true);
}
}
-
+
//Show both menus
- function collapseTable(){
+ function collapseTable() {
$(".leftPolicyPanel").addClass("col-sm-3");
- $(".glyphicon-search").css("padding", "10px 12px");
- $(".policyPanel").css("display","unset");
+ $(".modelSearchBox").css("padding", "10px 12px");
+ $(".policyPanel").css("display", "unset");
}
-
</script>
-</div>
-
+</div> \ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_create_model_off_Template.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_create_model_off_Template.html
index 09aba135..a4e4607e 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_create_model_off_Template.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_create_model_off_Template.html
@@ -27,63 +27,61 @@
<h4>Model Creation</h4>
</div>
<div attribute-test="cldsmodelofftemplate" class="modal-body" >
- <div style="height: 30px"></div>
- <button class="btn btn-primary btn-xs" ng-click="setTypeModel('template')">Template</button>
- <button class="btn btn-primary btn-xs" ng-click=" setTypeModel('clone')">Clone</button>
- <div ng-show="error.flag">{{error.message}} </div>
- <div ng-switch on="typeModel">
- <div ng-switch-when="template">
- <form name="model" class="form-horizontal" novalidate>
- <div class="form-group">
- <label for="modelName" class="col-sm-3 control-label">Model Name</label>
- <div class="col-sm-8">
- <input type="text" class="form-control" id="modelName" name="modelName" ng-model="modelName" placeholder="Model Name" ng-change="checkExisting();" autofocus="autofocus" ng-pattern="/^\s*[\w\-]*\s*$/" required ng-trim="true">
- <div role="alert"><span ng-show="model.modelName.$error.pattern" style="color: red">Special Characters are not allowed in Model name.</span> <span ng-show="nameinUse" style="color: red"> Model Name Already In Use</span></div>
- </div>
+
+ <ul style="margin-bottom:15px;" class="nav nav-tabs">
+ <li ng-class="{active : typeModel == 'template'}" ng-click="setTypeModel('template');"><a href="#">Template</a></li>
+ <li ng-class="{active : typeModel == 'clone'}" ng-click="setTypeModel('clone');"><a href="#">Clone</a></li>
+ </ul>
+ <div ng-show="error.flag">{{error.message}} </div>
+ <div ng-show="(typeModel=='template')">
+ <form name="model" class="form-horizontal" novalidate>
+ <div class="form-group">
+ <label for="modelName" class="col-sm-3 control-label">Model Name</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" id="modelName" name="modelName" ng-model="modelName" placeholder="Model Name" ng-change="checkExisting();" autofocus="autofocus" ng-pattern="/^\s*[\w\-]*\s*$/" required ng-trim="true">
+ <div role="alert"><span ng-show="model.modelName.$error.pattern" style="color: red">Special Characters are not allowed in Model name.</span> <span ng-show="nameinUse" style="color: red"> Model Name Already In Use</span></div>
</div>
- <div class="form-group">
- <label for="modelName" class="col-sm-3 control-label">Templates</label>
- <div class="col-sm-8">
- <select class="form-control" id="templateName" name="templateName" autofocus="autofocus" required ng-trim="true">
- <option ng-repeat="x in templateNamel" value="{{x}}">{{x}}</option>
- </select>
- </div>
+ </div>
+ <div class="form-group">
+ <label for="modelName" class="col-sm-3 control-label">Templates</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="templateName" name="templateName" autofocus="autofocus" required ng-trim="true">
+ <option ng-repeat="x in templateNamel" value="{{x}}">{{x}}</option>
+ </select>
</div>
- </form>
- </div>
- <div ng-switch-when="clone">
- <form name="model" class="form-horizontal" novalidate>
- <div class="form-group">
- <label for="modelName" class="col-sm-3 control-label">Model Name</label>
- <div class="col-sm-8">
- <input type="text" class="form-control" id="modelName" name="modelName" ng-model="modelName" placeholder="Model Name" ng-change="checkExisting()" autofocus="autofocus" ng-pattern="/^\s*[\w\-]*\s*$/" required ng-trim="true">
- <div role="alert"><span ng-show="model.modelName.$error.pattern" style="color: red">Special Characters are not allowed in Model name.</span> <span ng-show="nameinUse" style="color: red"> Model Name Already In Use</span></div>
- </div>
+ </div>
+ </form>
+ </div>
+ <div ng-show="(typeModel=='clone')">
+ <form name="model" class="form-horizontal" novalidate>
+ <div class="form-group">
+ <label for="modelName" class="col-sm-3 control-label">Model Name</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" id="modelName" name="modelName" ng-model="modelName" placeholder="Model Name" ng-change="checkExisting()" autofocus="autofocus" ng-pattern="/^\s*[\w\-]*\s*$/" required ng-trim="true">
+ <div role="alert"><span ng-show="model.modelName.$error.pattern" style="color: red">Special Characters are not allowed in Model name.</span> <span ng-show="nameinUse" style="color: red"> Model Name Already In Use</span></div>
</div>
- <div class="form-group">
- <label for="modelName" class="col-sm-3 control-label">Clone</label>
- <div class="col-sm-8">
- <select class="form-control" id="modelList" name="modelList" autofocus="autofocus" required ng-trim="true">
- <option ng-repeat="x in modelNamel" value="{{x}}">{{x}}</option>
- </select>
- </div>
+ </div>
+ <div class="form-group">
+ <label for="modelName" class="col-sm-3 control-label">Clone</label>
+ <div class="col-sm-8">
+ <select class="form-control" id="modelList" name="modelList" autofocus="autofocus" required ng-trim="true">
+ <option ng-repeat="x in modelNamel" value="{{x}}">{{x}}</option>
+ </select>
</div>
- </form>
- </div>
+ </div>
+ </form>
</div>
</div>
- <div ng-switch on="typeModel">
- <div ng-switch-when="template">
- <div class="modal-footer">
- <button ng-click="createNewModelOffTemplate(model)" class="btn btn-primary" ng-disabled="spcl || nameinUse" class="btn btn-primary">Create</button>
- <button ng-click="close(true)" class="btn btn-primary">Cancel</button>
- </div>
+ <div ng-show="(typeModel=='template')">
+ <div class="modal-footer">
+ <button ng-click="createNewModelOffTemplate(model)" class="btn btn-primary" ng-disabled="spcl || nameinUse" class="btn btn-primary">Create</button>
+ <button ng-click="close(true)" class="btn btn-primary">Cancel</button>
</div>
- <div ng-switch-when="clone">
- <div class="modal-footer">
- <button ng-click="cloneModel()" class="btn btn-primary" ng-disabled="model.modelName.$error.pattern || nameinUse" class="btn btn-primary">Clone</button>
- <button ng-click="close(true)" class="btn btn-primary">Cancel</button>
- </div>
+ </div>
+ <div ng-show="(typeModel=='clone')">
+ <div class="modal-footer">
+ <button ng-click="cloneModel()" class="btn btn-primary" ng-disabled="model.modelName.$error.pattern || nameinUse" class="btn btn-primary">Clone</button>
+ <button ng-click="close(true)" class="btn btn-primary">Cancel</button>
</div>
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_modelling.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_modelling.html
index 3f7192e0..aca810c2 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_modelling.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_modelling.html
@@ -637,10 +637,14 @@ width: 14px;
<div class="panel-heading">
<div style="color: white;">
- <span class="pull-left"> <span id="modeler_name">Closed Loop Modeler</span>
-
- </span> <span class="pull-right" ng-click="showTDRView=!showTDRView"><i
- ng-class="showTDRView == true ?'fa fa-plus-circle':'fa fa-minus-circle'"></i></span>
+ <span class="pull-left">
+ <span id="modeler_name">Closed Loop Modeler</span>
+ </span>
+ <span class="pull-right" >
+ <span id="templa_name"></span>
+ &nbsp;
+ <i ng-click="showTDRView=!showTDRView" ng-class="showTDRView == true ?'fa fa-plus-circle':'fa fa-minus-circle'"></i>
+ </span>
</div>
<div class="clearfix"></div>
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_model.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_model.html
index 7af1d594..5ebacce8 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_model.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_model.html
@@ -31,7 +31,7 @@
<div style="height: 30px"></div>
<form name="model" class="form-horizontal">
- <div class="form-group">
+ <div class="form-group clearfix">
<label for="modelName" class="col-sm-3 control-label">Model Name</label>
<div class="col-sm-8">
<select class="form-control" id="modelName" name="modelName"
@@ -41,7 +41,7 @@
<div role="alert"><span ng-show="model.modelName.$error.pattern" style="color: red">Special Characters are not allowed in Model name.</span></div>
</div>
</div>
- <div class="form-group">
+ <div class="form-group clearfix">
<label for="modelName" class="col-sm-3 control-label">Read Only</label>
<div class="col-sm-8">
<input type="checkbox" class="form-control" id="readOnly" name="readOnly"></input>
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_template.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_template.html
index e824a7e0..fceb7369 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_template.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/clds_open_template.html
@@ -31,7 +31,7 @@
<div style="height: 30px"></div>
<form name="model" class="form-horizontal">
- <div class="form-group">
+ <div class="form-group clearfix">
<label for="modelName" class="col-sm-3 control-label">Model Name</label>
<div class="col-sm-8">
<select class="form-control" id="modelName" name="modelName"
@@ -50,7 +50,7 @@
</div>
<script>
- /*$.get("/restservices/clds/v1/jaxrsClds/clds/model-names",function(data) {
+ /*$.get("/restservices/clds/v1/clds/model-names",function(data) {
var mySelect = $('#modelName');
mySelect.empty();
mySelect.append("<option value=''>New Diagram</option>")
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/global_properties.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/global_properties.html
index e6f20e0f..755ad7df 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/global_properties.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/global_properties.html
@@ -21,6 +21,7 @@
ECOMP is a trademark and service mark of AT&T Intellectual Property.
-->
+
<style>
.fileUpload {
position: relative;
@@ -79,8 +80,9 @@
aria-hidden="true" style="margin-top: -3px">&times;</button>
<h4>Model Properties</h4>
</div>
+
<div class="modal-body" style="height: 280px">
- <div style="height: 10px"></div>
+ <i hidden id="ridinSpinners" class="fa fa-spinner fa-spin" style="display:none;margin-bottom:10px;width:100%;text-align:center;font-size:24px;color:black;"></i>
<form id="saveProps" >
<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>
@@ -94,23 +96,35 @@
<div class="col-sm-8">
<select class="form-control"
- name="service" id="service" >
+ name="service" id="service" onchange="propChangeAlert(this);">
<!-- <option ng-repeat="(key, value) in services" value="{{key}}">{{value}}</option> -->
</select>
</div>
</div>
- <div class="form-group">
+ <div class="form-group clearfix">
<label for="vf" class="col-sm-4 control-label">
Resource-VF</label>
<div class="col-sm-8">
- <select class="form-control" id="vf" name="vf" >
+ <select class="form-control" id="vf" name="vf" onchange="propChangeAlert(this);">
</select>
</div>
</div>
- <div class="form-group">
+
+ <div class="form-group clearfix">
+ <label for="actionSet" class="col-sm-4 control-label">
+ Action Set</label>
+
+ <div class="col-sm-8">
+ <select class="form-control" id="actionSet" name="actionSet" onchange="propChangeAlert(this);">
+ </select>
+
+ </div>
+ </div>
+
+ <div class="form-group clearfix">
<label for="location" class="col-sm-4 control-label">
Location</label>
@@ -121,15 +135,20 @@
</div>
</div>
+
+
+
</div>
</form>
- <i hidden id="ridinSpinners" class="fa fa-spinner fa-spin" style="display:none;width:100%;text-align:center;font-size:24px;color:black;"></i>
+ <div class="alert alert-warning propChangeWarn" style="display:none;">
+ <strong>Warning!</strong> Changing these properties will reset all associated GUI fields.
+ </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 id="savePropsBtn" class="btn btn-primary">Save</button>
<button ng-click="close(true)" id="close_button"
class="btn btn-primary">Cancel</button>
@@ -160,7 +179,7 @@
// $.ajax({
// async:false,
// dataType: "json",
-// url: '/restservices/clds/v1/jaxrsClds/clds/asdc/services/',
+// url: '/restservices/clds/v1/clds/asdc/services/',
// success: function(data){
// vf_Services=data;
// },
@@ -185,31 +204,52 @@
// $("#" + el[i].name).val(el[i].value);
// }
// }
-
-
-
-
- (function () {
+
+ //display message only if global was previously saved
+ serDiff = false;
+ vfDiff = false;
+ asDiff = false;
- var previous;
+ (function () {
$("#paramsWarn").hide();
/*Below service method is called for checking the service is being loaded or not*/
- loadSharedPropertyByService();
-
- $("#service").on('focus', function () {
- // Store the current value on focus and on change
- previous = this.value;
-
- }).change(function(){
- $("#ridinSpinners").css("display","")
- var bool=loadSharedPropertyByService($(this).val())
- $("#ridinSpinners").css("display","none")
- if(!bool)
- $(this).val(previous)
- });
+
+ var intialize = intializeService;
+
+ function intializeService() {
+ $("#service").off('focus').off('change');
+
+ $("#service").on('change', function(){
+ var chosen = $(this).val();
+ (function(spinner){
+ $("#ridinSpinners").show();
+ setTimeout(spinner, 1);
+ })(function(){
+ loadSharedPropertyByService(chosen, null, intialize);
+ if (elementMap["global"]){
+ if ($("#vf").val() == oldVf){
+ vfDiff = false;
+ if ((!vfDiff)&&(!asDiff)&&(!serDiff)){
+ $(".propChangeWarn").hide();
+ };
+ } else {
+ vfDiff = true;
+ $(".propChangeWarn").show();
+ }
+ }
+
+ $("#ridinSpinners").hide();
+ });
+ });
+
+ }
+
+ loadSharedPropertyByService(undefined, null, intialize);
+ intializeService();
+
$("#paramsRetry").on('click', function () {
//$("#paramsWarn").hide();
- var currentValue = $("#service").val() == null ? previous : $("#service").val();
+ var currentValue = $("#service").val();
$("#ridinSpinners").css("display","")
var bool=loadSharedPropertyByService(currentValue);
$("#ridinSpinners").css("display","none")
@@ -219,12 +259,9 @@
$("#paramsWarn").hide();
});
+
})();
-// $("#service").on("change",function(){
-// $("#ridinSpinners").css("display","")
-// loadSharedPropertyByService($(this).val())
-// $("#ridinSpinners").css("display","none")
-// })
+
function noRepeats(form){
var select={};
for(var i=0;i<form.length;i++){
@@ -243,14 +280,73 @@
}
return arr
}
+
+ $(function(){
+ if (elementMap["global"]){
+ for (var i=0; i< elementMap["global"].length; i++){
+ if (elementMap["global"][i]["name"]=="vf"){
+ oldVf = elementMap["global"][i]["value"];
+ }
+ }
+ } else {
+ oldVf = "";
+ }
+ });
+
+ function propChangeAlert(actionset){
+ //throw warnings only if options were previously chosen
+ if (elementMap["global"]){
+ loop1:
+ for (var i=0; i< elementMap["global"].length; i++){
+ if (elementMap["global"][i]["name"] == actionset.id){
+ //user did not change properties
+ if (elementMap["global"][i]["value"][0] == actionset.value){
+ if (elementMap["global"][i]["name"] == "actionSet"){
+ asDiff = false;
+ } else if (elementMap["global"][i]["name"] == "service"){
+ serDiff = false;
+ } else if (elementMap["global"][i]["name"] == "vf"){
+ vfDiff = false;
+ }
+ if ((!vfDiff)&&(!asDiff)&&(!serDiff)){
+ $(".propChangeWarn").hide();
+ };
+ //user changed properties
+ } else {
+ if (elementMap["global"][i]["name"] == "actionSet"){
+ asDiff = true;
+ } else if (elementMap["global"][i]["name"] == "service"){
+ serDiff = true;
+ } else if (elementMap["global"][i]["name"] == "vf"){
+ vfDiff = true;
+ };
+ $(".propChangeWarn").show();
+ }
+ break loop1;
+ }
+ }
+ }
+ }
$("#saveProps").on('submit', function(event) {
saveGlobalProperties(noRepeats($(this).serializeArray()))
event.preventDefault();
+ //module reset, based on property updates
+ if (elementMap["global"]){
+ $.each(Object.keys(elementMap), function(i,v){
+ if ((v.match(/^Policy/)) && asDiff){
+ elementMap[v]={};
+ }
+ if ((v.match(/^TCA/)) && (vfDiff || serDiff)){
+ elementMap[v]={};
+ }
+ });
+ };
+
$("#close_button").click();
-
})
+
$("#savePropsBtn").click(function(event) {
//alert($("#CProp_Target").val())
$("#saveProps").submit();
@@ -259,4 +355,3 @@
</script>
</div>
-
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/refresh_asdc.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/refresh_asdc.html
index 947e4191..c3621f8a 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/refresh_asdc.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/refresh_asdc.html
@@ -111,7 +111,7 @@
// $.ajax({
// async:false,
// dataType: "json",
-// url: '/services/clds-designer/v1/jaxrsClds/clds/asdc/services/',
+// url: '/restservices/clds/v1/clds/asdc/services/',
// success: function(data){
// vf_Services=data;
// },
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/stringMatch_properties.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/stringMatch_properties.html
index 4b5d22bb..75491185 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/stringMatch_properties.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/stringMatch_properties.html
@@ -18,10 +18,17 @@
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;
@@ -52,19 +59,88 @@
}
.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>
@@ -76,14 +152,12 @@ label{text-align:right;
}
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;
@@ -93,296 +167,351 @@ label{text-align:right;
</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">&times;</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 = {}
@@ -392,84 +521,69 @@ label{text-align:right;
}
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(
@@ -477,12 +591,83 @@ label{text-align:right;
$("#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");
@@ -491,95 +676,300 @@ label{text-align:right;
})
$('#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
diff --git a/src/main/resources/META-INF/resources/designer/partials/portfolios/tca_properties.html b/src/main/resources/META-INF/resources/designer/partials/portfolios/tca_properties.html
index c0bbe3b4..3219fe43 100644
--- a/src/main/resources/META-INF/resources/designer/partials/portfolios/tca_properties.html
+++ b/src/main/resources/META-INF/resources/designer/partials/portfolios/tca_properties.html
@@ -22,6 +22,17 @@
-->
<style>
+#createNewThresh{
+ height:34px;
+ width:120px; /*84*/
+ background-color:#f2bfab;
+}
+
+#deleteThresh{
+ height:34px;
+ background-color:#dddd;
+}
+
.fileUpload {
position: relative;
overflow: hidden;
@@ -52,7 +63,61 @@
}
.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>
@@ -88,205 +153,340 @@
</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;
@@ -297,96 +497,127 @@
}
}
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">&times;</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">&times;</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
diff --git a/src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js
index 9529ad4f..2fc3f755 100644
--- a/src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js
+++ b/src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js
@@ -22,7 +22,7 @@
*/
app.directive( "contextMenu", function($compile){
- console.log("contextMenu");
+
contextMenu = {};
contextMenu.restrict = "AE";
contextMenu.link = function( lScope, lElem, lAttr ){
@@ -49,15 +49,14 @@ app.directive( "contextMenu", function($compile){
});
app.directive('ngRightClick', function($parse) {
- console.log("ngRightClick");
- console.log("ngRightClick");
+
return function(scope, element, attrs) {
- console.log("returnfunction");
+
var fn = $parse(attrs.ngRightClick);
element.bind('contextmenu', function(event) {
- console.log("contextmenu");
+
scope.$apply(function() {
- console.log("apply");
+
event.preventDefault();
fn(scope, {$event:event});
});
@@ -66,16 +65,16 @@ app.directive('ngRightClick', function($parse) {
});
app.directive('inputInfoClass', function ($compile) {
- console.log("inputInfoClass");
+
return {
restrict: "C",
replace: true,
link: function(scope,element,attrs){
- console.log("link");
+
var elementHTML = '';
scope.sourceExplorer = 'AM';
angular.forEach(scope.infoType.schemaElements, function(value, key){
- console.log("schemaElement");
+
scope.schemaElement = value;
@@ -122,12 +121,12 @@ app.directive('inputInfoClass', function ($compile) {
});
app.directive('inputInfoClassMember', function ($compile, $timeout) {
- console.log("inputInfoClassMember");
+
return {
restrict: "C",
link: function(scope,element,attrs){
- console.log("link");
+
var elementHTML = '';
@@ -254,17 +253,13 @@ app.directive('inputInfoClassMember', function ($compile, $timeout) {
});
app.directive('expandable', function ($compile) {
- console.log("expandable");
+
return {
restrict: "AE",
link: function(scope,element,attrs){
- console.log("link");
+
var elementHTML = '';
element.bind("click", function(){
- console.log("bindclick");
- //console.log('directive clicked!!!');
- //console.log(scope.sourceExplorer);
- //console.log(scope.parKey);
var test1 = document.getElementById(scope.parKey);
@@ -273,8 +268,6 @@ app.directive('expandable', function ($compile) {
var htmlCount = test1.getElementsByTagName('div').length;
var schemaElementCount = scope.schemaElement.type.elements.length;
- //console.log(htmlCount);
- //console.log(schemaElementCount);
if(htmlCount<schemaElementCount){
var x = angular.element(test1).append('<div class="inputInfoClassMember" style="margin-left: 10px" ng-repeat="schemaElement in schemaElement.type.elements" ng-init="currentElementName=schemaElement.element.name;parentName=parKey; parentElement=parElement; heirarchyLevel=heirLevel+1 ;"></div>');
@@ -290,9 +283,7 @@ app.directive('expandable', function ($compile) {
if((cElements[i].getElementsByTagName('div') != null)&&(scope.schemaElement.type.elements != null)){
var htmlCount = cElements[i].getElementsByTagName('div').length;
var schemaElementCount = scope.schemaElement.type.elements.length;
- //console.log(htmlCount);
- //console.log(schemaElementCount);
- //console.log(cElements[i]);
+
if(htmlCount<schemaElementCount){
var x = '';
if(scope.sourceExplorer=='SDV'){
@@ -316,7 +307,7 @@ app.directive('expandable', function ($compile) {
app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','dialogs', '$filter','Datafactory','soapRequestService', function($scope,$rootScope, $location,dialogs,$filter,Datafactory,soapRequestService){
- console.log("ActivityModellingCtrl");
+
$scope.count=0;
$scope.depth=0;
$scope.parentElementList=[];
@@ -334,14 +325,12 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
$rootScope.initProjectExplorer = function () {
- console.log("initProjectExplorer");
+
if(map_model_repeatable_heirarchical_elements[selected_model] != null) {
$rootScope.repeatableHeirarchicalElementMap = map_model_repeatable_heirarchical_elements[selected_model];
- ////console.log("$scope.repeatableHeirarchicalElementMap :: " + $rootScope.repeatableHeirarchicalElementMap);
}
- ////console.log("$rootScope.utmModelSchemaExtension :: " + JSON.stringify(list_model_schema_extensions[selected_model]));
if(list_model_schema_extensions[selected_model] != null) {
$scope.utmModelSchemaExtension = list_model_schema_extensions[selected_model];
if($scope.utmModelSchemaExtension.radioSelection == null || $scope.utmModelSchemaExtension.radioSelection == '')
@@ -362,16 +351,12 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
console.log("requiredOnly");
for (var key in $scope.utmModelSchemaExtension.utmSchemaExtentionMap) {
- ////console.log(key);
-
if ($scope.utmModelSchemaExtension.utmSchemaExtentionMap.hasOwnProperty(key)) {
- //$scope.utmModelSchemaExtension.utmSchemaExtentionMap[key].checked = $scope.utmModelSchemaExtension.radioSelection == "Required Only" && $rootScope.requiredValues[key] != 0;
$scope.utmModelSchemaExtension.utmSchemaExtentionMap[key].checked = $rootScope.requiredValues[key] != 0;
}
}
angular.forEach($scope.utmModelSchemaExtension.utmSchemaExtentionMap, function(value, key) {
console.log("forEach");
- //console.log(key + ': ' + value);
});
};
@@ -400,17 +385,11 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
}
};
-/* $scope.generatedXML = function(xmlValue){
- $scope.generatedXMLVal=xmlValue;
- var dlg = dialogs.create('partials/portfolios/generatedXML.html','generateXMLCtrl',{},{size:'lg',keyboard: true,backdrop: true,windowClass: 'my-class'});
-
- };*/
-
//Functionality for Hierarchical Elements
$scope.addHierarchicalElement1 = function(schemaElement, parentElement, elementKey, index){
console.log("addHeirarchicalElement1");
if($rootScope.isHorR){
- //console.log("Entering addHeirarchicalElement1");
+
$scope.clonedSchemaElement={};
angular.copy(schemaElement, $scope.clonedSchemaElement);
@@ -520,15 +499,13 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
if(schemaElement.type.complexType != null){
for(var i=0;i<$scope.childElements.length;i++){
if(angular.equals($scope.childElements[i],schemaElement)){
- //console.log("Complex Element List Match :" +$scope.childElements[i]);
$scope.childElements.splice((i+1),0,$scope.clonedSchemaElement);
break;
}
}
} else if(schemaElement.element.name !=null) {
for(var j=0;j<$scope.childElements.length;j++){
- if(angular.equals($scope.childElements[j],schemaElement)){
- //console.log("Element List Match :" +$scope.childElements[j]);
+ if(angular.equals($scope.childElements[j],schemaElement)){
$scope.childElements.splice((j+1),0,$scope.clonedSchemaElement);
break;
}
@@ -591,24 +568,7 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
i++;
});
};
-
- /*$scope.renameModel = function(){
- console.log("renameModel");
-
- console.log("renameModel");
-
- var dlg = dialogs.create('partials/portfolios/rename_model.html','CreateModelCtrl',{},{size:'lg',keyboard: true,backdrop: true,windowClass: 'my-class'});
- dlg.result.then(function(name){
- console.log("dlg.result");
-
- },function(){
- console.log("...empty");
- });
-
-
- };*/
-
-
+
$scope.addRepeatableElement = function(schemaElement, parentElement, elementKey){
console.log("addRepeatableElement");
$rootScope.isHorR = false;
@@ -727,17 +687,7 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
}
}
}
-
- /*if(parentElement.complexType != null){
- var index = parentElement.elements.indexOf(schemaElement);
- parentElement.elements.splice(index, 1);
- }
- else{
- var index = parentElement.type.elements.indexOf(schemaElement);
- parentElement.type.elements.splice(index, 1);
- }*/
-
-
+
if(list_model_repeatable_heirarchical_elements[selected_model] != null)
{
for(var i=0;i<list_model_repeatable_heirarchical_elements[selected_model].repeatableHeirachicalSchemaElements.length;i++){
@@ -753,7 +703,6 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
$scope.removeRepeatableHeirarchicalMap= function(modelName,repeatableHeirachicalSchemaElement,elementKey){
console.log("removeRepeatableHeirarchicalMap");
- //console.log("child element length:"+$scope.childElements.length);
$scope.repeatableElements = repeatableHeirachicalSchemaElement.repeatableElements;
$scope.heirarchicalElements = repeatableHeirachicalSchemaElement.heirarchicalElements;
@@ -876,52 +825,4 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
}
-
- //Execute and display tst results
- /*$scope.executeTst = function(index){
- console.log("executeTst");
- Datafactory.setSelectedTestCase($rootScope.modeltestset.activityTestCases[index]);
-
- var tstInput={};
- console.log("inside generateTST() method");
- var executeTSTUrl ="/utm-service/soa_integration/executeTST";
- var tempActivityTestcase= {};
- angular.copy(Datafactory.getSelectedTestCase(),tempActivityTestcase);
-
- tstInput.activityTestCase = tempActivityTestcase;
-
- if(tstInput.activityTestCase.version != null){
- var newTestCaseName = tstInput.activityTestCase.testCaseName + "_"+ tstInput.activityTestCase.version;
- tstInput.activityTestCase.testCaseName = newTestCaseName;
-
- }
-
- tstInput.projectPreferenceInfo = Datafactory.getProjectPreferenceInfo();
- tstInput.environmentData = $rootScope.environmentData;
- tstInput.writeFileToolList=Datafactory.getWriteFileDataList();
- tstInput.fileStreamWriterList=Datafactory.getFileStreamWriterList();
- tstInput.commonPythonScriptList = Datafactory.getCommonPythonScriptList();
-
-
- soapRequestService.generateTst(tstInput, executeTSTUrl)
- .then(function(pars) {
- console.log("pars");
-
- if(pars != null || pars != undefined){
-
- Datafactory.setExecuteResultset(pars);
-
- var dlg = dialogs.create('partials/SOA/execute-request.html','executeRequestCtrl',{},{size:'lg',keyboard: true,backdrop: true,windowClass: 'my-class'});
- }
- else{
- dialogs.error("Some error occured during execution of tst file");
- }
-
-
- });
-
-
-
-
- }*/
-}]);
+}]); \ No newline at end of file