This widget is used in the Record Producer -> Custom -> Widget.
Note:
2 variables are needed in my case, so the code is a bit complex
I've used this plugin; check it out before implementing it!
(Note: I've used the old version)
https://www.jqueryscript.net/demo/Drop-Down-Combo-Tree/
HTML:
<div class="form-group" ng-show="data.showTreeWidget"> <div class="input-wrapper" style="width: 100%;"> <span class="field-decorations"> <span class="fa fa-asterisk mandatory sp-field-label-padding" ng-class="{'mandatory-filled': positionHierarchy || existingHierarchyValue}" aria-label="Required" role="img" aria-hidden="true"></span> </span> <label for="positionHierarchy" style="margin-left: -3px;">Hierarchy (Lowest level)</label> <input type="text" class="form-control" id="positionHierarchy" placeholder="" autocomplete="off" ng-model="positionHierarchy" > <span class="clear-icon" id="clearPositionHierarchy" title="Clear field" style="display:none;">✖</span> </div></div>
<script type="text/javascript"> /*! * jQuery ComboTree Plugin * Author: Erhan FIRAT * Mail: erhanfirat@gmail.com * Licensed under the MIT license */ ;(function ( $, window, document, undefined ) { // Create the defaults once var comboTreePlugin = 'comboTree', defaults = { source: [], isMultiple: false }; // The actual plugin constructor function ComboTree( element, options ) { this.elemInput = element; this._elemInput = $(element); this.options = $.extend( {}, defaults, options) ; this._defaults = defaults; this._name = comboTreePlugin; this.init(); } ComboTree.prototype.init = function () { // Setting Doms this.comboTreeId = 'comboTree' + Math.floor(Math.random() * 999999); this._elemInput.addClass('comboTreeInputBox'); if(this._elemInput.attr('id') === undefined) this._elemInput.attr('id', this.comboTreeId + 'Input'); this.elemInputId = this._elemInput.attr('id'); this._elemInput.wrap('<div id="'+ this.comboTreeId + 'Wrapper" class="comboTreeWrapper"></div>'); this._elemInput.wrap('<div id="'+ this.comboTreeId + 'InputWrapper" class="comboTreeInputWrapper"></div>'); this._elemWrapper = $('#' + this.comboTreeId + 'Wrapper'); this._elemArrowBtn = $('<button id="' + this.comboTreeId + 'ArrowBtn" class="comboTreeArrowBtn"><span class="comboTreeArrowBtnImg">▼</span></button>'); this._elemInput.after(this._elemArrowBtn); this._elemWrapper.append('<div id="' + this.comboTreeId + 'DropDownContainer" class="comboTreeDropDownContainer"><div class="comboTreeDropDownContent"></div>'); // DORP DOWN AREA this._elemDropDownContainer = $('#' + this.comboTreeId + 'DropDownContainer'); this._elemDropDownContainer.html(this.createSourceHTML()); this._elemItems = this._elemDropDownContainer.find('li'); this._elemItemsTitle = this._elemDropDownContainer.find('span.comboTreeItemTitle'); // VARIABLES this._selectedItem = {}; this._selectedItems = []; this.bindings(); }; /* Newly created by AUTHOR Starts here */ ComboTree.prototype.clearSelection = function () { this._selectedItem = {}; this._selectedItems = []; this.refreshInputVal(); this._elemItemsTitle.find('input[type=checkbox]').prop('checked', false); }; // Add this function inside the ComboTree prototype ComboTree.prototype.selectByValue = function(value) { // Find the item with the provided value var selectedItem = this._elemItemsTitle.filter(function() { return $(this).attr('data-id') === value; }); // Check if the item is found if (selectedItem.length) { // Select the item if (this.options.isMultiple) { // For multiple selection, toggle checkbox selectedItem.find('input[type="checkbox"]').prop('checked', true); } else { // For single selection, simulate click selectedItem.click(); } } }; /* Created by AUTHOR Ends here */ // ********************************* // SOURCES CODES // ********************************* ComboTree.prototype.removeSourceHTML = function () { this._elemDropDownContainer.html(''); }; ComboTree.prototype.createSourceHTML = function () { var htmlText = this.createSourceSubItemsHTML(this.options.source); return htmlText; }; ComboTree.prototype.createSourceSubItemsHTML = function (subItems) { var subItemsHtml = '<UL>'; for (var i=0; i<subItems.length; i++){ subItemsHtml += this.createSourceItemHTML(subItems[i]); } subItemsHtml += '</UL>' return subItemsHtml; } ComboTree.prototype.createSourceItemHTML = function (sourceItem) { var itemHtml = "", isThereSubs = sourceItem.hasOwnProperty("subs"); itemHtml = '<LI class="ComboTreeItem' + (isThereSubs?'Parent':'Chlid') + '"> '; if (isThereSubs) itemHtml += '<span class="comboTreeParentPlus">−</span>'; if (this.options.isMultiple) itemHtml += '<span data-id="' + sourceItem.id + '" class="comboTreeItemTitle"><input type="checkbox">' + sourceItem.title + '</span>'; else itemHtml += '<span data-id="' + sourceItem.id + '" class="comboTreeItemTitle">' + sourceItem.title + '</span>'; if (isThereSubs) itemHtml += this.createSourceSubItemsHTML(sourceItem.subs); itemHtml += '</LI>'; return itemHtml; }; // BINDINGS // ***************************** ComboTree.prototype.bindings = function () { var _this = this; this._elemArrowBtn.on('click', function(e){ e.stopPropagation(); _this.toggleDropDown(); }); this._elemInput.on('click', function(e){ e.stopPropagation(); if (!_this._elemDropDownContainer.is(':visible')) _this.toggleDropDown(); }); this._elemItems.on('click', function(e){ e.stopPropagation(); if ($(this).hasClass('ComboTreeItemParent')){ _this.toggleSelectionTree(this); } }); this._elemItemsTitle.on('click', function(e){ e.stopPropagation(); if (_this.options.isMultiple) _this.multiItemClick(this); else _this.singleItemClick(this); }); this._elemItemsTitle.on("mousemove", function (e) { e.stopPropagation(); _this.dropDownMenuHover(this); }); // KEY BINDINGS this._elemInput.on('keyup', function(e) { //console.log(e) e.stopPropagation(); switch (e.keyCode) { case 27: //console.log('A') _this.closeDropDownMenu(); break; case 13: case 39: case 37: case 40: case 38: //console.log('B') e.preventDefault(); break; default: if (!_this.options.isMultiple) _this.filterDropDownMenu(); //console.log('C') break; } }); this._elemInput.on('keydown', function(e) { e.stopPropagation(); switch (e.keyCode) { case 9: _this.closeDropDownMenu(); break; case 40: case 38: e.preventDefault(); _this.dropDownInputKeyControl(e.keyCode - 39); break; case 37: case 39: e.preventDefault(); _this.dropDownInputKeyToggleTreeControl(e.keyCode - 38); break; case 13: if (_this.options.isMultiple) _this.multiItemClick(_this._elemHoveredItem); else _this.singleItemClick(_this._elemHoveredItem); e.preventDefault(); break; default: if (_this.options.isMultiple) e.preventDefault(); } }); // ON FOCUS OUT CLOSE DROPDOWN $(document).on('mouseup.' + _this.comboTreeId, function (e){ if (!_this._elemWrapper.is(e.target) && _this._elemWrapper.has(e.target).length === 0 && _this._elemDropDownContainer.is(':visible')) _this.closeDropDownMenu(); }); }; // EVENTS HERE // **************************** // DropDown Menu Open/Close ComboTree.prototype.toggleDropDown = function () { this._elemDropDownContainer.slideToggle(50); this._elemInput.focus(); }; ComboTree.prototype.closeDropDownMenu = function () { this._elemDropDownContainer.slideUp(50); }; // Selection Tree Open/Close ComboTree.prototype.toggleSelectionTree = function (item, direction) { var subMenu = $(item).children('ul')[0]; if (direction === undefined){ if ($(subMenu).is(':visible')) $(item).children('span.comboTreeParentPlus').html("+"); else $(item).children('span.comboTreeParentPlus').html("−"); $(subMenu).slideToggle(50); } else if (direction == 1 && !$(subMenu).is(':visible')){ $(item).children('span.comboTreeParentPlus').html("−"); $(subMenu).slideDown(50); } else if (direction == -1){ if ($(subMenu).is(':visible')){ $(item).children('span.comboTreeParentPlus').html("+"); $(subMenu).slideUp(50); } else { this.dropDownMenuHoverToParentItem(item); } } }; // SELECTION FUNCTIONS // ***************************** ComboTree.prototype.singleItemClick = function (ctItem) { this._selectedItem = { id: $(ctItem).attr("data-id"), title: $(ctItem).text() }; this.refreshInputVal(); this.closeDropDownMenu(); }; ComboTree.prototype.multiItemClick = function (ctItem) { this._selectedItem = { id: $(ctItem).attr("data-id"), title: $(ctItem).text() }; var index = this.isItemInArray(this._selectedItem, this._selectedItems); if (index){ this._selectedItems.splice(parseInt(index), 1); $(ctItem).find("input").prop('checked', false); } else { this._selectedItems.push(this._selectedItem); $(ctItem).find("input").prop('checked', true); } this.refreshInputVal(); }; ComboTree.prototype.isItemInArray = function (item, arr) { for (var i=0; i<arr.length; i++) if (item.id == arr[i].id && item.title == arr[i].title) return i + ""; return false; } ComboTree.prototype.refreshInputVal = function () { var tmpTitle = ""; if (this.options.isMultiple) { for (var i=0; i<this._selectedItems.length; i++){ tmpTitle += this._selectedItems[i].title; if (i<this._selectedItems.length-1) tmpTitle += ", "; } } else { tmpTitle = this._selectedItem.title; } this._elemInput.val(tmpTitle); } ComboTree.prototype.dropDownMenuHover = function (itemSpan, withScroll) { this._elemItems.find('span.comboTreeItemHover').removeClass('comboTreeItemHover'); $(itemSpan).addClass('comboTreeItemHover'); this._elemHoveredItem = $(itemSpan); if (withScroll) this.dropDownScrollToHoveredItem(this._elemHoveredItem); } ComboTree.prototype.dropDownScrollToHoveredItem = function (itemSpan) { var curScroll = this._elemDropDownContainer.scrollTop(); this._elemDropDownContainer.scrollTop(curScroll + $(itemSpan).parent().position().top - 80); } ComboTree.prototype.dropDownMenuHoverToParentItem = function (item) { var parentSpanItem = $($(item).parents('li.ComboTreeItemParent')[0]).children("span.comboTreeItemTitle"); if (parentSpanItem.length) this.dropDownMenuHover(parentSpanItem, true); else this.dropDownMenuHover(this._elemItemsTitle[0], true); } ComboTree.prototype.dropDownInputKeyToggleTreeControl = function (direction) { var item = this._elemHoveredItem; if ($(item).parent('li').hasClass('ComboTreeItemParent')) this.toggleSelectionTree($(item).parent('li'), direction); else if (direction == -1) this.dropDownMenuHoverToParentItem(item); } ComboTree.prototype.dropDownInputKeyControl = function (step) { if (!this._elemDropDownContainer.is(":visible")) this.toggleDropDown(); var list = this._elemItems.find("span.comboTreeItemTitle:visible"); i = this._elemHoveredItem?list.index(this._elemHoveredItem) + step:0; i = (list.length + i) % list.length; this.dropDownMenuHover(list[i], true); }, ComboTree.prototype.filterDropDownMenu = function () { var searchText = this._elemInput.val(); if (searchText != ""){ this._elemItemsTitle.hide(); this._elemItemsTitle.siblings("span.comboTreeParentPlus").hide(); list = this._elemItems.find("span:icontains('" + this._elemInput.val() + "')").each(function (i, elem) { $(this).show(); $(this).siblings("span.comboTreeParentPlus").show(); }); } else{ this._elemItemsTitle.show(); this._elemItemsTitle.siblings("span.comboTreeParentPlus").show(); } } // Retuns Array (multiple), Integer (single), or False (No choice) ComboTree.prototype.getSelectedItemsId = function () { if (this.options.isMultiple && this._selectedItems.length>0){ var tmpArr = []; for (i=0; i<this._selectedItems.length; i++) tmpArr.push(this._selectedItems[i].id); return tmpArr; } else if (!this.options.isMultiple && this._selectedItem.hasOwnProperty('id')){ return this._selectedItem.id; } return false; } // Retuns Array (multiple), Integer (single), or False (No choice) ComboTree.prototype.getSelectedItemsTitle = function () { if (this.options.isMultiple && this._selectedItems.length>0){ var tmpArr = []; for (i=0; i<this._selectedItems.length; i++) tmpArr.push(this._selectedItems[i].title); return tmpArr; } else if (!this.options.isMultiple && this._selectedItem.hasOwnProperty('id')){ return this._selectedItem.title; } return false; } ComboTree.prototype.unbind = function () { this._elemArrowBtn.off('click'); this._elemInput.off('click'); this._elemItems.off('click'); this._elemItemsTitle.off('click'); this._elemItemsTitle.off("mousemove"); this._elemInput.off('keyup'); this._elemInput.off('keydown'); this._elemInput.off('mouseup.' + this.comboTreeId); $(document).off('mouseup.' + this.comboTreeId); } ComboTree.prototype.destroy = function () { this.unbind(); this._elemWrapper.before(this._elemInput); this._elemWrapper.remove(); this._elemInput.removeData('plugin_' + comboTreePlugin); } $.fn[comboTreePlugin] = function ( options) { var ctArr = []; this.each(function () { if (!$.data(this, 'plugin_' + comboTreePlugin)) { $.data(this, 'plugin_' + comboTreePlugin, new ComboTree( this, options)); ctArr.push($(this).data()['plugin_' + comboTreePlugin]); } }); if (this.length == 1) return ctArr[0]; else return ctArr; }})( jQuery, window, document );</script>
<script type="text/javascript">$.expr[':'].icontains = function (obj, index, meta, stack) { return (obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0; };</script>
CSS:
/* Clear Icon starts here */.input-wrapper { position: relative; display: inline-block;}.clear-icon { position: absolute; right: 10px; top: 73%; transform: translateY(-50%); cursor: pointer; color: #999;}.clear-icon:hover { color: #333;}/* Clear Icon ends here */
/* Tree dropdown starts herer */.comboTreeWrapper { position: relative; text-align: left !important;}.comboTreeInputWrapper { position: relative;}.comboTreeArrowBtn { position: absolute; right: 1px; bottom: 1px; top: 1px; box-sizing: border-box; border: none; border-left: 1px solid #8790a1; border-radius: 0 3px 3px 0; background: #fff;}.comboTreeDropDownContainer { display: none; background: #fff; border: 1px solid #aaa; max-height: 250px; overflow-y: auto; position: absolute; width: 100%; z-index: 1; box-sizing: border-box;}.comboTreeDropDownContainer ul { padding: 0px; margin: 0;}.comboTreeDropDownContainer li { list-style-type: none; padding-left: 15px; cursor: pointer;}.comboTreeDropDownContainer li:hover { background-color: #ddd;}.comboTreeDropDownContainer li:hover ul { background-color: #fff;}.comboTreeDropDownContainer li span.comboTreeItemTitle.comboTreeItemHover { background-color: #418EFF; color: #fff;}span.comboTreeItemTitle { display: block; padding: 2px 4px;}.comboTreeDropDownContainer label { cursor: pointer; width: 100%; display: block;}.comboTreeDropDownContainer .comboTreeItemTitle input { position: relative; top: 2px; margin: 0px 4px 0px 0px;}.comboTreeParentPlus { position: relative; left: -12px; top: 4px; width: 4px; float: left;}.comboTreeInputBox { padding: 5px; border-radius: 3px; border: 1px solid #999; width: 100%; box-sizing: border-box; padding-right: 24px;}.comboTreeArrowBtnImg { font-size: 0.7rem; padding: 6px; color: #888888; background: #fff;}/* Tree Dropdown ends here */
ClientScript:
api.controller = function($rootScope, $scope, $filter, $timeout) { var c = this;
console.log(c.data.prePopulate); $scope.positionHierarchy = ''; $scope.existingHierarchyValue = '';
// Function to find node by id in tree structure function findNodeById(nodes, id) { for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.id == id) { return node; } if (node.subs) { var foundNode = findNodeById(node.subs, id); if (foundNode) { return foundNode; } } } return null; }
var comboTree2; jQuery(document).ready(function($) { /* Initialize tree drop-down starts here */ comboTree2 = $('#positionHierarchy').comboTree({ source: c.data.cmnDepartments, isMultiple: false, }); /* Initialize tree drop-down ends here */ // Define the flag globally $scope.isSettingValue = false; if(c.data.prePopulate){ $rootScope.$on("field.change", function(evt, parms) { console.info("parms.field.name: " + parms.field.name); if (parms.field.name == 'u_hierarchy_hidden') { // Do something starts here $scope.existingHierarchyValue = $scope.page.g_form.getValue('u_hierarchy_hidden'); if ($scope.existingHierarchyValue) { // Check if the existing value exists in the combo tree data var selectedNode = findNodeById(c.data.cmnDepartments, $scope.existingHierarchyValue); console.log(selectedNode+'-----selectedNode'); if (selectedNode) { $scope.isSettingValue = true; comboTree2.selectByValue($scope.existingHierarchyValue); $("#clearPositionHierarchy").show(); // Set the flag back to false after a short delay setTimeout(function() { $scope.isSettingValue = false; }, 100); } } // Do something starts here } }); }
/* Clear starts here */ $('#clearPositionHierarchy').click(function() { $scope.positionHierarchy = ''; $scope.page.g_form.clearValue('u_hierarchy'); $scope.page.g_form.clearValue('u_hierarchy_hidden'); comboTree2.clearSelection(); comboTree2.filterDropDownMenu(); $("#clearPositionHierarchy").hide(); $('#positionHierarchy').val('').trigger('input'); }); /* Clear ends here */
/* Set value on click starts here */ $(".comboTreeItemTitle").click(function() { // Check the flag before proceeding if ($scope.isSettingValue) return; $scope.selectedOption = $(this)[0].innerText; var selectedOptionId = $(this)[0].dataset.id; console.log(selectedOptionId+'----selectedOptionId'); $scope.positionHierarchy = selectedOptionId; $scope.page.g_form.clearValue('u_hierarchy'); $scope.page.g_form.setValue('u_hierarchy', selectedOptionId); $scope.page.g_form.clearValue('u_hierarchy_hidden'); $scope.page.g_form.setValue('u_hierarchy_hidden', selectedOptionId); $("#clearPositionHierarchy").show(); }); /* Set value on click ends here */
});};
ServcerSript:
(function() { data.page = $sp.getParameter('id'); data.prePopulate = false; data.sys_id = $sp.getParameter('sys_id'); // holds sys_id data.allowedPrePopulateCatItems = ['ac9a24541b9682903af60e1ce54bcbbd', '347cea171b868a503af60e1ce54bcb6d']; if (data.sys_id && data.page == 'sc_cat_item') { if (data.allowedPrePopulateCatItems.indexOf(data.sys_id) !== -1) { // if data.sys_id is present in the allowed array then make the flag true data.prePopulate = true; } else { data.prePopulate = false; // optionally handle the false case } } else { data.prePopulate = false; // handle the case where data.sys_id is not present } data.showTreeWidget = true; if(data.page == 'hrm_ticket_page'){ data.showTreeWidget = false; }else{ data.showTreeWidget = true; } //data.directReports = [{"subs":[{"id":"776fec6d1b11b110e37053d2604bcb5e","title":"Title1 Test"}],"id":"3bdd4b321bf11010551d55392a4bcb39","title":"Title345 Test"}]; data.cmnDepartments = []; // Helper function to recursively build the hierarchy function buildHierarchy(department, allDepartments) { var children = []; for (var i = 0; i < allDepartments.length; i++) { if (allDepartments[i].parent == department.id) { children.push(buildHierarchy(allDepartments[i], allDepartments)); } } if (children.length > 0) { department.subs = children; } else { department.subs = []; } return department; } // Fetch all departments var allDepartments = []; var grDept = new GlideRecordSecure("cmn_department"); grDept.addEncodedQuery("u_dep_type!=NULL"); grDept.query(); while (grDept.next()) { var dept = {}; dept.id = grDept.getUniqueValue(); if(grDept.getDisplayValue('u_dep_type')){ dept.title = grDept.getDisplayValue('name')+" ("+grDept.getDisplayValue('u_dep_type')+")"; }else{ dept.title = grDept.getDisplayValue('name'); } dept.parent = grDept.getValue('parent'); // For parent ID matching allDepartments.push(dept); } // Build the hierarchy starting from root departments (where parent is empty) for (var j = 0; j < allDepartments.length; j++) { if (!allDepartments[j].parent) { var rootDept = buildHierarchy(allDepartments[j], allDepartments); data.cmnDepartments.push(rootDept); } }})();
<div class="form-group" ng-show="data.showTreeWidget">
<div class="input-wrapper" style="width: 100%;">
<span class="field-decorations">
<span class="fa fa-asterisk mandatory sp-field-label-padding" ng-class="{'mandatory-filled': positionHierarchy || existingHierarchyValue}" aria-label="Required" role="img" aria-hidden="true"></span>
</span>
<label for="positionHierarchy" style="margin-left: -3px;">Hierarchy (Lowest level)</label>
<input type="text" class="form-control" id="positionHierarchy" placeholder="" autocomplete="off" ng-model="positionHierarchy" >
<span class="clear-icon" id="clearPositionHierarchy" title="Clear field" style="display:none;">✖</span>
</div>
</div>
<script type="text/javascript">
/*!
* jQuery ComboTree Plugin
* Author: Erhan FIRAT
* Mail: erhanfirat@gmail.com
* Licensed under the MIT license
*/
;(function ( $, window, document, undefined ) {
// Create the defaults once
var comboTreePlugin = 'comboTree',
defaults = {
source: [],
isMultiple: false
};
// The actual plugin constructor
function ComboTree( element, options ) {
this.elemInput = element;
this._elemInput = $(element);
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = comboTreePlugin;
this.init();
}
ComboTree.prototype.init = function () {
// Setting Doms
this.comboTreeId = 'comboTree' + Math.floor(Math.random() * 999999);
this._elemInput.addClass('comboTreeInputBox');
if(this._elemInput.attr('id') === undefined)
this._elemInput.attr('id', this.comboTreeId + 'Input');
this.elemInputId = this._elemInput.attr('id');
this._elemInput.wrap('<div id="'+ this.comboTreeId + 'Wrapper" class="comboTreeWrapper"></div>');
this._elemInput.wrap('<div id="'+ this.comboTreeId + 'InputWrapper" class="comboTreeInputWrapper"></div>');
this._elemWrapper = $('#' + this.comboTreeId + 'Wrapper');
this._elemArrowBtn = $('<button id="' + this.comboTreeId + 'ArrowBtn" class="comboTreeArrowBtn"><span class="comboTreeArrowBtnImg">▼</span></button>');
this._elemInput.after(this._elemArrowBtn);
this._elemWrapper.append('<div id="' + this.comboTreeId + 'DropDownContainer" class="comboTreeDropDownContainer"><div class="comboTreeDropDownContent"></div>');
// DORP DOWN AREA
this._elemDropDownContainer = $('#' + this.comboTreeId + 'DropDownContainer');
this._elemDropDownContainer.html(this.createSourceHTML());
this._elemItems = this._elemDropDownContainer.find('li');
this._elemItemsTitle = this._elemDropDownContainer.find('span.comboTreeItemTitle');
// VARIABLES
this._selectedItem = {};
this._selectedItems = [];
this.bindings();
};
/* Newly created by AUTHOR Starts here */
ComboTree.prototype.clearSelection = function () {
this._selectedItem = {};
this._selectedItems = [];
this.refreshInputVal();
this._elemItemsTitle.find('input[type=checkbox]').prop('checked', false);
};
// Add this function inside the ComboTree prototype
ComboTree.prototype.selectByValue = function(value) {
// Find the item with the provided value
var selectedItem = this._elemItemsTitle.filter(function() {
return $(this).attr('data-id') === value;
});
// Check if the item is found
if (selectedItem.length) {
// Select the item
if (this.options.isMultiple) {
// For multiple selection, toggle checkbox
selectedItem.find('input[type="checkbox"]').prop('checked', true);
} else {
// For single selection, simulate click
selectedItem.click();
}
}
};
/* Created by AUTHOR Ends here */
// *********************************
// SOURCES CODES
// *********************************
ComboTree.prototype.removeSourceHTML = function () {
this._elemDropDownContainer.html('');
};
ComboTree.prototype.createSourceHTML = function () {
var htmlText = this.createSourceSubItemsHTML(this.options.source);
return htmlText;
};
ComboTree.prototype.createSourceSubItemsHTML = function (subItems) {
var subItemsHtml = '<UL>';
for (var i=0; i<subItems.length; i++){
subItemsHtml += this.createSourceItemHTML(subItems[i]);
}
subItemsHtml += '</UL>'
return subItemsHtml;
}
ComboTree.prototype.createSourceItemHTML = function (sourceItem) {
var itemHtml = "",
isThereSubs = sourceItem.hasOwnProperty("subs");
itemHtml = '<LI class="ComboTreeItem' + (isThereSubs?'Parent':'Chlid') + '"> ';
if (isThereSubs)
itemHtml += '<span class="comboTreeParentPlus">−</span>';
if (this.options.isMultiple)
itemHtml += '<span data-id="' + sourceItem.id + '" class="comboTreeItemTitle"><input type="checkbox">' + sourceItem.title + '</span>';
else
itemHtml += '<span data-id="' + sourceItem.id + '" class="comboTreeItemTitle">' + sourceItem.title + '</span>';
if (isThereSubs)
itemHtml += this.createSourceSubItemsHTML(sourceItem.subs);
itemHtml += '</LI>';
return itemHtml;
};
// BINDINGS
// *****************************
ComboTree.prototype.bindings = function () {
var _this = this;
this._elemArrowBtn.on('click', function(e){
e.stopPropagation();
_this.toggleDropDown();
});
this._elemInput.on('click', function(e){
e.stopPropagation();
if (!_this._elemDropDownContainer.is(':visible'))
_this.toggleDropDown();
});
this._elemItems.on('click', function(e){
e.stopPropagation();
if ($(this).hasClass('ComboTreeItemParent')){
_this.toggleSelectionTree(this);
}
});
this._elemItemsTitle.on('click', function(e){
e.stopPropagation();
if (_this.options.isMultiple)
_this.multiItemClick(this);
else
_this.singleItemClick(this);
});
this._elemItemsTitle.on("mousemove", function (e) {
e.stopPropagation();
_this.dropDownMenuHover(this);
});
// KEY BINDINGS
this._elemInput.on('keyup', function(e) {
//console.log(e)
e.stopPropagation();
switch (e.keyCode) {
case 27:
//console.log('A')
_this.closeDropDownMenu(); break;
case 13:
case 39: case 37: case 40: case 38:
//console.log('B')
e.preventDefault();
break;
default:
if (!_this.options.isMultiple)
_this.filterDropDownMenu();
//console.log('C')
break;
}
});
this._elemInput.on('keydown', function(e) {
e.stopPropagation();
switch (e.keyCode) {
case 9:
_this.closeDropDownMenu(); break;
case 40: case 38:
e.preventDefault();
_this.dropDownInputKeyControl(e.keyCode - 39); break;
case 37: case 39:
e.preventDefault();
_this.dropDownInputKeyToggleTreeControl(e.keyCode - 38);
break;
case 13:
if (_this.options.isMultiple)
_this.multiItemClick(_this._elemHoveredItem);
else
_this.singleItemClick(_this._elemHoveredItem);
e.preventDefault();
break;
default:
if (_this.options.isMultiple)
e.preventDefault();
}
});
// ON FOCUS OUT CLOSE DROPDOWN
$(document).on('mouseup.' + _this.comboTreeId, function (e){
if (!_this._elemWrapper.is(e.target) && _this._elemWrapper.has(e.target).length === 0 && _this._elemDropDownContainer.is(':visible'))
_this.closeDropDownMenu();
});
};
// EVENTS HERE
// ****************************
// DropDown Menu Open/Close
ComboTree.prototype.toggleDropDown = function () {
this._elemDropDownContainer.slideToggle(50);
this._elemInput.focus();
};
ComboTree.prototype.closeDropDownMenu = function () {
this._elemDropDownContainer.slideUp(50);
};
// Selection Tree Open/Close
ComboTree.prototype.toggleSelectionTree = function (item, direction) {
var subMenu = $(item).children('ul')[0];
if (direction === undefined){
if ($(subMenu).is(':visible'))
$(item).children('span.comboTreeParentPlus').html("+");
else
$(item).children('span.comboTreeParentPlus').html("−");
$(subMenu).slideToggle(50);
}
else if (direction == 1 && !$(subMenu).is(':visible')){
$(item).children('span.comboTreeParentPlus').html("−");
$(subMenu).slideDown(50);
}
else if (direction == -1){
if ($(subMenu).is(':visible')){
$(item).children('span.comboTreeParentPlus').html("+");
$(subMenu).slideUp(50);
}
else {
this.dropDownMenuHoverToParentItem(item);
}
}
};
// SELECTION FUNCTIONS
// *****************************
ComboTree.prototype.singleItemClick = function (ctItem) {
this._selectedItem = {
id: $(ctItem).attr("data-id"),
title: $(ctItem).text()
};
this.refreshInputVal();
this.closeDropDownMenu();
};
ComboTree.prototype.multiItemClick = function (ctItem) {
this._selectedItem = {
id: $(ctItem).attr("data-id"),
title: $(ctItem).text()
};
var index = this.isItemInArray(this._selectedItem, this._selectedItems);
if (index){
this._selectedItems.splice(parseInt(index), 1);
$(ctItem).find("input").prop('checked', false);
}
else {
this._selectedItems.push(this._selectedItem);
$(ctItem).find("input").prop('checked', true);
}
this.refreshInputVal();
};
ComboTree.prototype.isItemInArray = function (item, arr) {
for (var i=0; i<arr.length; i++)
if (item.id == arr[i].id && item.title == arr[i].title)
return i + "";
return false;
}
ComboTree.prototype.refreshInputVal = function () {
var tmpTitle = "";
if (this.options.isMultiple) {
for (var i=0; i<this._selectedItems.length; i++){
tmpTitle += this._selectedItems[i].title;
if (i<this._selectedItems.length-1)
tmpTitle += ", ";
}
}
else {
tmpTitle = this._selectedItem.title;
}
this._elemInput.val(tmpTitle);
}
ComboTree.prototype.dropDownMenuHover = function (itemSpan, withScroll) {
this._elemItems.find('span.comboTreeItemHover').removeClass('comboTreeItemHover');
$(itemSpan).addClass('comboTreeItemHover');
this._elemHoveredItem = $(itemSpan);
if (withScroll)
this.dropDownScrollToHoveredItem(this._elemHoveredItem);
}
ComboTree.prototype.dropDownScrollToHoveredItem = function (itemSpan) {
var curScroll = this._elemDropDownContainer.scrollTop();
this._elemDropDownContainer.scrollTop(curScroll + $(itemSpan).parent().position().top - 80);
}
ComboTree.prototype.dropDownMenuHoverToParentItem = function (item) {
var parentSpanItem = $($(item).parents('li.ComboTreeItemParent')[0]).children("span.comboTreeItemTitle");
if (parentSpanItem.length)
this.dropDownMenuHover(parentSpanItem, true);
else
this.dropDownMenuHover(this._elemItemsTitle[0], true);
}
ComboTree.prototype.dropDownInputKeyToggleTreeControl = function (direction) {
var item = this._elemHoveredItem;
if ($(item).parent('li').hasClass('ComboTreeItemParent'))
this.toggleSelectionTree($(item).parent('li'), direction);
else if (direction == -1)
this.dropDownMenuHoverToParentItem(item);
}
ComboTree.prototype.dropDownInputKeyControl = function (step) {
if (!this._elemDropDownContainer.is(":visible"))
this.toggleDropDown();
var list = this._elemItems.find("span.comboTreeItemTitle:visible");
i = this._elemHoveredItem?list.index(this._elemHoveredItem) + step:0;
i = (list.length + i) % list.length;
this.dropDownMenuHover(list[i], true);
},
ComboTree.prototype.filterDropDownMenu = function () {
var searchText = this._elemInput.val();
if (searchText != ""){
this._elemItemsTitle.hide();
this._elemItemsTitle.siblings("span.comboTreeParentPlus").hide();
list = this._elemItems.find("span:icontains('" + this._elemInput.val() + "')").each(function (i, elem) {
$(this).show();
$(this).siblings("span.comboTreeParentPlus").show();
});
}
else{
this._elemItemsTitle.show();
this._elemItemsTitle.siblings("span.comboTreeParentPlus").show();
}
}
// Retuns Array (multiple), Integer (single), or False (No choice)
ComboTree.prototype.getSelectedItemsId = function () {
if (this.options.isMultiple && this._selectedItems.length>0){
var tmpArr = [];
for (i=0; i<this._selectedItems.length; i++)
tmpArr.push(this._selectedItems[i].id);
return tmpArr;
}
else if (!this.options.isMultiple && this._selectedItem.hasOwnProperty('id')){
return this._selectedItem.id;
}
return false;
}
// Retuns Array (multiple), Integer (single), or False (No choice)
ComboTree.prototype.getSelectedItemsTitle = function () {
if (this.options.isMultiple && this._selectedItems.length>0){
var tmpArr = [];
for (i=0; i<this._selectedItems.length; i++)
tmpArr.push(this._selectedItems[i].title);
return tmpArr;
}
else if (!this.options.isMultiple && this._selectedItem.hasOwnProperty('id')){
return this._selectedItem.title;
}
return false;
}
ComboTree.prototype.unbind = function () {
this._elemArrowBtn.off('click');
this._elemInput.off('click');
this._elemItems.off('click');
this._elemItemsTitle.off('click');
this._elemItemsTitle.off("mousemove");
this._elemInput.off('keyup');
this._elemInput.off('keydown');
this._elemInput.off('mouseup.' + this.comboTreeId);
$(document).off('mouseup.' + this.comboTreeId);
}
ComboTree.prototype.destroy = function () {
this.unbind();
this._elemWrapper.before(this._elemInput);
this._elemWrapper.remove();
this._elemInput.removeData('plugin_' + comboTreePlugin);
}
$.fn[comboTreePlugin] = function ( options) {
var ctArr = [];
this.each(function () {
if (!$.data(this, 'plugin_' + comboTreePlugin)) {
$.data(this, 'plugin_' + comboTreePlugin, new ComboTree( this, options));
ctArr.push($(this).data()['plugin_' + comboTreePlugin]);
}
});
if (this.length == 1)
return ctArr[0];
else
return ctArr;
}
})( jQuery, window, document );
</script>
<script type="text/javascript">
$.expr[':'].icontains = function (obj, index, meta, stack) {
return (obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;
};
</script>
/* Clear Icon starts here */
.input-wrapper {
position: relative;
display: inline-block;
}
.clear-icon {
position: absolute;
right: 10px;
top: 73%;
transform: translateY(-50%);
cursor: pointer;
color: #999;
}
.clear-icon:hover {
color: #333;
}
/* Clear Icon ends here */
/* Tree dropdown starts herer */
.comboTreeWrapper {
position: relative;
text-align: left !important;
}
.comboTreeInputWrapper {
position: relative;
}
.comboTreeArrowBtn {
position: absolute;
right: 1px;
bottom: 1px;
top: 1px;
box-sizing: border-box;
border: none;
border-left: 1px solid #8790a1;
border-radius: 0 3px 3px 0;
background: #fff;
}
.comboTreeDropDownContainer {
display: none;
background: #fff;
border: 1px solid #aaa;
max-height: 250px;
overflow-y: auto;
position: absolute;
width: 100%;
z-index: 1;
box-sizing: border-box;
}
.comboTreeDropDownContainer ul {
padding: 0px;
margin: 0;
}
.comboTreeDropDownContainer li {
list-style-type: none;
padding-left: 15px;
cursor: pointer;
}
.comboTreeDropDownContainer li:hover {
background-color: #ddd;
}
.comboTreeDropDownContainer li:hover ul {
background-color: #fff;
}
.comboTreeDropDownContainer li span.comboTreeItemTitle.comboTreeItemHover {
background-color: #418EFF;
color: #fff;
}
span.comboTreeItemTitle {
display: block;
padding: 2px 4px;
}
.comboTreeDropDownContainer label {
cursor: pointer;
width: 100%;
display: block;
}
.comboTreeDropDownContainer .comboTreeItemTitle input {
position: relative;
top: 2px;
margin: 0px 4px 0px 0px;
}
.comboTreeParentPlus {
position: relative;
left: -12px;
top: 4px;
width: 4px;
float: left;
}
.comboTreeInputBox {
padding: 5px;
border-radius: 3px;
border: 1px solid #999;
width: 100%;
box-sizing: border-box;
padding-right: 24px;
}
.comboTreeArrowBtnImg {
font-size: 0.7rem;
padding: 6px;
color: #888888;
background: #fff;
}
/* Tree Dropdown ends here */
api.controller = function($rootScope, $scope, $filter, $timeout) {
var c = this;
console.log(c.data.prePopulate);
$scope.positionHierarchy = '';
$scope.existingHierarchyValue = '';
// Function to find node by id in tree structure
function findNodeById(nodes, id) {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
if (node.id == id) {
return node;
}
if (node.subs) {
var foundNode = findNodeById(node.subs, id);
if (foundNode) {
return foundNode;
}
}
}
return null;
}
var comboTree2;
jQuery(document).ready(function($) {
/* Initialize tree drop-down starts here */
comboTree2 = $('#positionHierarchy').comboTree({
source: c.data.cmnDepartments,
isMultiple: false,
});
/* Initialize tree drop-down ends here */
// Define the flag globally
$scope.isSettingValue = false;
if(c.data.prePopulate){
$rootScope.$on("field.change", function(evt, parms) {
console.info("parms.field.name: " + parms.field.name);
if (parms.field.name == 'u_hierarchy_hidden') {
// Do something starts here
$scope.existingHierarchyValue = $scope.page.g_form.getValue('u_hierarchy_hidden');
if ($scope.existingHierarchyValue) {
// Check if the existing value exists in the combo tree data
var selectedNode = findNodeById(c.data.cmnDepartments, $scope.existingHierarchyValue);
console.log(selectedNode+'-----selectedNode');
if (selectedNode) {
$scope.isSettingValue = true;
comboTree2.selectByValue($scope.existingHierarchyValue);
$("#clearPositionHierarchy").show();
// Set the flag back to false after a short delay
setTimeout(function() {
$scope.isSettingValue = false;
}, 100);
}
}
// Do something starts here
}
});
}
/* Clear starts here */
$('#clearPositionHierarchy').click(function() {
$scope.positionHierarchy = '';
$scope.page.g_form.clearValue('u_hierarchy');
$scope.page.g_form.clearValue('u_hierarchy_hidden');
comboTree2.clearSelection();
comboTree2.filterDropDownMenu();
$("#clearPositionHierarchy").hide();
$('#positionHierarchy').val('').trigger('input');
});
/* Clear ends here */
/* Set value on click starts here */
$(".comboTreeItemTitle").click(function() {
// Check the flag before proceeding
if ($scope.isSettingValue) return;
$scope.selectedOption = $(this)[0].innerText;
var selectedOptionId = $(this)[0].dataset.id;
console.log(selectedOptionId+'----selectedOptionId');
$scope.positionHierarchy = selectedOptionId;
$scope.page.g_form.clearValue('u_hierarchy');
$scope.page.g_form.setValue('u_hierarchy', selectedOptionId);
$scope.page.g_form.clearValue('u_hierarchy_hidden');
$scope.page.g_form.setValue('u_hierarchy_hidden', selectedOptionId);
$("#clearPositionHierarchy").show();
});
/* Set value on click ends here */
});
};
(function() {
data.page = $sp.getParameter('id');
data.prePopulate = false;
data.sys_id = $sp.getParameter('sys_id'); // holds sys_id
data.allowedPrePopulateCatItems = ['ac9a24541b9682903af60e1ce54bcbbd', '347cea171b868a503af60e1ce54bcb6d'];
if (data.sys_id && data.page == 'sc_cat_item') {
if (data.allowedPrePopulateCatItems.indexOf(data.sys_id) !== -1) { // if data.sys_id is present in the allowed array then make the flag true
data.prePopulate = true;
} else {
data.prePopulate = false; // optionally handle the false case
}
} else {
data.prePopulate = false; // handle the case where data.sys_id is not present
}
data.showTreeWidget = true;
if(data.page == 'hrm_ticket_page'){
data.showTreeWidget = false;
}else{
data.showTreeWidget = true;
}
//data.directReports = [{"subs":[{"id":"776fec6d1b11b110e37053d2604bcb5e","title":"Title1 Test"}],"id":"3bdd4b321bf11010551d55392a4bcb39","title":"Title345 Test"}];
data.cmnDepartments = [];
// Helper function to recursively build the hierarchy
function buildHierarchy(department, allDepartments) {
var children = [];
for (var i = 0; i < allDepartments.length; i++) {
if (allDepartments[i].parent == department.id) {
children.push(buildHierarchy(allDepartments[i], allDepartments));
}
}
if (children.length > 0) {
department.subs = children;
} else {
department.subs = [];
}
return department;
}
// Fetch all departments
var allDepartments = [];
var grDept = new GlideRecordSecure("cmn_department");
grDept.addEncodedQuery("u_dep_type!=NULL");
grDept.query();
while (grDept.next()) {
var dept = {};
dept.id = grDept.getUniqueValue();
if(grDept.getDisplayValue('u_dep_type')){
dept.title = grDept.getDisplayValue('name')+" ("+grDept.getDisplayValue('u_dep_type')+")";
}else{
dept.title = grDept.getDisplayValue('name');
}
dept.parent = grDept.getValue('parent'); // For parent ID matching
allDepartments.push(dept);
}
// Build the hierarchy starting from root departments (where parent is empty)
for (var j = 0; j < allDepartments.length; j++) {
if (!allDepartments[j].parent) {
var rootDept = buildHierarchy(allDepartments[j], allDepartments);
data.cmnDepartments.push(rootDept);
}
}
})();
