1/** 2* Inptu visibility control plugin 3* @param {DOM} element - The DOM object which will be hidden or shown 4* @param {DOMs} controllers - The controller DOM objects which will control the visibility of the element 5* @param {bool} visible - The visibility state of the element 6*/ 7 8class VisibilityControl { 9 element = null; 10 controllers = null; 11 visible = false; 12 13 //========== Constructor ========== 14 constructor(element) { 15 var self = this; 16 17 // Assign element to class instance 18 self.element = element; 19 20 // Assign class instance to target element 21 self.element.data('visibility', self); 22 23 // Get controllers DOM objects 24 self.controllers = self.getControllers(); 25 26 // Loop through controllers and add event listeners to update visibility on change or input 27 self.controllers.forEach(function(controller) { 28 controller.on('input change', function() { 29 self.updateVisibility(); 30 }); 31 }); 32 33 // Set the cms-validation attribute to x-cms-validation (to avoid validating while hidden) and remove cms-validation attribute 34 self.element.find('[cms-validation]').each(function() { 35 $(this).attr('x-cms-validation', $(this).attr('cms-validation')).removeAttr('cms-validation'); 36 }); 37 38 // Update visibility once initialized 39 self.updateVisibility(); 40 } 41 42 //========== Update input visibility ========== 43 updateVisibility() { 44 var self = this; 45 46 if (self.element.hasAttribute('visibility-pattern')) { 47 return this.updateVisibilityUsingPattern(); 48 } 49 50 // Get visibility/invisibility values 51 let elementAttributes = optionsObjectFromDOM(self.element); 52 let showValues = elementAttributes.visibilityValue; 53 let hideValues = elementAttributes.invisibilityValue; 54 let visibilityCondition = elementAttributes.visibilityCondition; 55 56 // If visbility/invisibility values are not an array, convert to array 57 if (typeof showValues !== 'object') showValues = [showValues]; 58 if (typeof hideValues !== 'object') hideValues = [hideValues]; 59 60 // Array holding a bool of the checks result for each controller 61 let controllersChecks = []; 62 63 // Loop through controllers and check if any of them match the visibility values 64 self.controllers.forEach(function(controller, index) { 65 // If visibility condition is set, evaluate and check if it's true 66 if (typeof visibilityCondition !== 'undefined') { 67 controllersChecks.push(eval(visibilityCondition)); 68 69 // Otherwise, check if the controller value matches any of the visibility/invisibility values 70 } else { 71 let controllerValue = getInputValue(controller); 72 let visibilityValues = showValues[index] != null ? parseCSV(showValues[index]) : []; 73 let invisibilityValues = hideValues[index] != null ? parseCSV(hideValues[index]) : []; 74 75 // If controller value is an array (checkboxes or multiple select), check if any of the values match the visibility values 76 if (typeof controllerValue == 'object') { 77 if (visibilityValues.length) controllersChecks.push(controllerValue.some(r => visibilityValues.includes(r))); 78 if (invisibilityValues.length) controllersChecks.push(controllerValue.some(r => !invisibilityValues.includes(r))); 79 80 // Otherwise, check if the controller value matches any of the visibility values 81 } else { 82 if (visibilityValues.length) controllersChecks.push(visibilityValues.includes(controllerValue)); 83 if (invisibilityValues.length) controllersChecks.push(!invisibilityValues.includes(controllerValue)); 84 } 85 } 86 }); 87 88 let show = !controllersChecks.includes(false); 89 if (show) { 90 self.showElement(); 91 } else { 92 self.hideElement(); 93 } 94 } 95 96 //========== Update input visibility using pattern ========== 97 updateVisibilityUsingPattern() { 98 const self = this; 99 100 let pattern = self.element.attr('visibility-pattern'); 101 let parts = pattern.split(/\[(.*?)\]/).filter(part => part); 102 103 let show = parts.some((part) => { 104 let partsByController = part.split(','); 105 106 return self.controllers.every((controller, index) => { 107 let controllerValue = getInputValue(controller); 108 let allowedValues = partsByController[index].split('|'); 109 110 // Early return if wildcard is allowed 111 if (allowedValues.includes('*')) { 112 return true; 113 } 114 115 if (typeof controllerValue == 'object') { 116 return controllerValue.some(r => allowedValues.includes(r)); 117 } 118 119 return allowedValues.includes(controllerValue); 120 }); 121 }); 122 123 if (show) { 124 self.showElement(); 125 } else { 126 self.hideElement(); 127 } 128 } 129 130 //========== Get controllers DOM objects ========== 131 getControllers() { 132 var self = this; 133 let control = self.element.attr('visibility-control'); 134 let controllers = parseCSV(control); 135 let controllersDOMs = []; 136
137 controllers.forEach(function(controller) { 138 // First check for (visibility-controller) attribute 139 if ($(`[visibility-controller="${controller}"]`).length) { 140 controllersDOMs.push($(`[visibility-controller="${controller}"]`)); 141 142 // Then check for jquery object 143 } else if ($(controller).length) { 144 controllersDOMs.push($(controller)); 145 146 // Then check for (id) attribute 147 } else if ($(`[id="${controller}"]`).length) { 148 controllersDOMs.push($(`[id="${controller}"]`)); 149 150 // Then check for (name) attribute 151 } else if ($(`[name="${controller}"]`).length) { 152 controllersDOMs.push($(`[name="${controller}"]`)); 153 154 // Then check for (name) attribute with brackets 155 } else if ($(`[name="${controller}[]"]`).length) { 156 controllersDOMs.push($(`[name="${controller}[]"]`)); 157 } 158 }); 159 160 return controllersDOMs; 161 } 162 163 //========== Show element ========== 164 showElement() { 165 var self = this; 166 167 self.element.show(); 168 self.visible = true; 169 self.updateElementAttributes(); 170 } 171 172 //========== Hide element ========== 173 hideElement() { 174 var self = this; 175 176 self.element.hide(); 177 self.visible = false; 178 self.updateElementAttributes(); 179 } 180 181 //========== Update element attributes ========== 182 updateElementAttributes() { 183 var self = this; 184 185 // Re-assign is-hidden attribute accordingly 186 self.element.attr('is-hidden', !self.visible); 187 self.element.find('input, select, textarea').each(function() { 188 $(this).attr('is-hidden', !self.visible); 189 }); 190 191 // Re-assign cms-validation attribute accordingly 192 if (self.visible) { 193 self.element.find('[x-cms-validation]').each(function() { 194 $(this).attr('cms-validation', $(this).attr('x-cms-validation')); 195 }); 196 } else { 197 self.element.find('[x-cms-validation]').removeAttr('cms-validation'); 198 } 199 200 // Adjust row span if inside data-table (Currently only works when the title and cell are last in row) 201 if (self.element.prop('tagName')=='TD') { 202 let row = self.element.parents('tr'); 203 let visibleCells = row.find('td:not([is-hidden=true])').length; 204 let targetCell = row.find('td:not(.title):not([is-hidden])'); 205 let colspan = (visibleCells <= 2 ? 3 : 1); 206 targetCell.attr('colspan', colspan).css('width', 'auto'); 207 } 208 } 209}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.