[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 (function () { 2 'use strict'; 3 4 /** 5 * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> 6 * @license GNU General Public License version 2 or later; see LICENSE.txt 7 */ 8 9 /** 10 * JField 'showon' class 11 */ 12 var Showon = /*#__PURE__*/function () { 13 /** 14 * Constructor 15 * 16 * @param {HTMLElement} cont Container element 17 */ 18 function Showon(cont) { 19 var _this = this; 20 21 var self = this; 22 this.container = cont || document; 23 this.fields = {// origin-field-name: { 24 // origin: ['collection of all the trigger nodes'], 25 // targets: ['collection of nodes to be controlled control'] 26 // } 27 }; 28 this.showonFields = [].slice.call(this.container.querySelectorAll('[data-showon]')); // Populate the fields data 29 30 if (this.showonFields.length) { 31 // @todo refactor this, dry 32 this.showonFields.forEach(function (field) { 33 // Set up only once 34 if (field.hasAttribute('data-showon-initialised')) { 35 return; 36 } 37 38 field.setAttribute('data-showon-initialised', ''); 39 var jsondata = field.getAttribute('data-showon') || ''; 40 var showonData = JSON.parse(jsondata); 41 var localFields; 42 43 if (showonData.length) { 44 localFields = [].slice.call(self.container.querySelectorAll("[name=\"" + showonData[0].field + "\"], [name=\"" + showonData[0].field + "[]\"]")); 45 46 if (!_this.fields[showonData[0].field]) { 47 _this.fields[showonData[0].field] = { 48 origin: [], 49 targets: [] 50 }; 51 } // Add trigger elements 52 53 54 localFields.forEach(function (cField) { 55 if (_this.fields[showonData[0].field].origin.indexOf(cField) === -1) { 56 _this.fields[showonData[0].field].origin.push(cField); 57 } 58 }); // Add target elements 59 60 _this.fields[showonData[0].field].targets.push(field); // Data showon can have multiple values 61 62 63 if (showonData.length > 1) { 64 showonData.forEach(function (value, index) { 65 if (index === 0) { 66 return; 67 } 68 69 localFields = [].slice.call(self.container.querySelectorAll("[name=\"" + value.field + "\"], [name=\"" + value.field + "[]\"]")); 70 71 if (!_this.fields[showonData[0].field]) { 72 _this.fields[showonData[0].field] = { 73 origin: [], 74 targets: [] 75 }; 76 } // Add trigger elements 77 78 79 localFields.forEach(function (cField) { 80 if (_this.fields[showonData[0].field].origin.indexOf(cField) === -1) { 81 _this.fields[showonData[0].field].origin.push(cField); 82 } 83 }); // Add target elements 84 85 if (_this.fields[showonData[0].field].targets.indexOf(field) === -1) { 86 _this.fields[showonData[0].field].targets.push(field); 87 } 88 }); 89 } 90 } 91 }); // Do some binding 92 93 this.linkedOptions = this.linkedOptions.bind(this); // Attach events to referenced element, to check condition on change and keyup 94 95 Object.keys(this.fields).forEach(function (key) { 96 if (_this.fields[key].origin.length) { 97 _this.fields[key].origin.forEach(function (elem) { 98 // Initialize the showon behaviour for the given HTMLElement 99 self.linkedOptions(key); // Setup listeners 100 101 elem.addEventListener('change', function () { 102 self.linkedOptions(key); 103 }); 104 elem.addEventListener('keyup', function () { 105 self.linkedOptions(key); 106 }); 107 elem.addEventListener('click', function () { 108 self.linkedOptions(key); 109 }); 110 }); 111 } 112 }); 113 } 114 } 115 /** 116 * 117 * @param key 118 */ 119 120 121 var _proto = Showon.prototype; 122 123 _proto.linkedOptions = function linkedOptions(key) { 124 var _this2 = this; 125 126 // Loop through the elements that need to be either shown or hidden 127 this.fields[key].targets.forEach(function (field) { 128 var elementShowonDatas = JSON.parse(field.getAttribute('data-showon')) || []; 129 var showfield = true; 130 var itemval; // Check if target conditions are satisfied 131 132 elementShowonDatas.forEach(function (elementShowonData, index) { 133 var condition = elementShowonData || {}; 134 condition.valid = 0; // Test in each of the elements in the field array if condition is valid 135 136 _this2.fields[key].origin.forEach(function (originField) { 137 if (originField.name.replace('[]', '') !== elementShowonData.field) { 138 return; 139 } 140 141 var originId = originField.id; // If checkbox or radio box the value is read from properties 142 143 if (originField.getAttribute('type') && ['checkbox', 'radio'].includes(originField.getAttribute('type').toLowerCase())) { 144 if (!originField.checked) { 145 // Unchecked fields will return a blank and so always match 146 // a != condition so we skip them 147 return; 148 } 149 150 itemval = document.getElementById(originId).value; 151 } else if (originField.nodeName === 'SELECT' && originField.hasAttribute('multiple')) { 152 itemval = Array.from(originField.querySelectorAll('option:checked')).map(function (el) { 153 return el.value; 154 }); 155 } else { 156 // Select lists, text-area etc. Note that multiple-select list returns 157 // an Array here s0 we can always treat 'itemval' as an array 158 itemval = document.getElementById(originId).value; // A multi-select <select> $field will return null when no elements are 159 // selected so we need to define itemval accordingly 160 161 if (itemval === null && originField.tagName.toLowerCase() === 'select') { 162 itemval = []; 163 } 164 } // Convert to array to allow multiple values in the field (e.g. type=list multiple) 165 // and normalize as string 166 167 168 if (!(typeof itemval === 'object')) { 169 itemval = JSON.parse("[\"" + itemval + "\"]"); 170 } // Test if any of the values of the field exists in showon conditions 171 172 173 itemval.forEach(function (val) { 174 // ":" Equal to one or more of the values condition 175 if (condition.sign === '=' && condition.values.indexOf(val) !== -1) { 176 condition.valid = 1; 177 } // "!:" Not equal to one or more of the values condition 178 179 180 if (condition.sign === '!=' && condition.values.indexOf(val) === -1) { 181 condition.valid = 1; 182 } 183 }); 184 }); // Verify conditions 185 // First condition (no operator): current condition must be valid 186 187 188 if (condition.op === '') { 189 if (condition.valid === 0) { 190 showfield = false; 191 } 192 } else { 193 // Other conditions (if exists) 194 // AND operator: both the previous and current conditions must be valid 195 if (condition.op === 'AND' && condition.valid + elementShowonDatas[index - 1].valid < 2) { 196 showfield = false; 197 condition.valid = 0; 198 } // OR operator: one of the previous and current conditions must be valid 199 200 201 if (condition.op === 'OR' && condition.valid + elementShowonDatas[index - 1].valid > 0) { 202 showfield = true; 203 condition.valid = 1; 204 } 205 } 206 }); // If conditions are satisfied show the target field(s), else hide 207 208 if (field.tagName !== 'option') { 209 if (showfield) { 210 field.classList.remove('hidden'); 211 field.dispatchEvent(new CustomEvent('joomla:showon-show', { 212 bubbles: true 213 })); 214 } else { 215 field.classList.add('hidden'); 216 field.dispatchEvent(new CustomEvent('joomla:showon-hide', { 217 bubbles: true 218 })); 219 } 220 } else { 221 // @todo: If chosen or choices.js is active we should update them 222 field.disabled = !showfield; 223 } 224 }); 225 }; 226 227 return Showon; 228 }(); 229 230 if (!window.Joomla) { 231 throw new Error('Joomla API is not properly initialized'); 232 } // Provide a public API 233 234 235 if (!Joomla.Showon) { 236 Joomla.Showon = { 237 initialise: function initialise(container) { 238 return new Showon(container); 239 } 240 }; 241 } 242 /** 243 * Initialize 'showon' feature at an initial page load 244 */ 245 246 247 Joomla.Showon.initialise(document); 248 /** 249 * Search for matching parents 250 * 251 * @param {HTMLElement} $child 252 * @param {String} selector 253 * @returns {HTMLElement[]} 254 */ 255 256 var getMatchedParents = function getMatchedParents($child, selector) { 257 var $parent = $child; 258 var $matchingParent; 259 var parents = []; 260 261 while ($parent) { 262 $matchingParent = $parent.matches && $parent.matches(selector) ? $parent : null; 263 264 if ($matchingParent) { 265 parents.unshift($matchingParent); 266 } 267 268 $parent = $parent.parentNode; 269 } 270 271 return parents; 272 }; 273 /** 274 * Initialize 'showon' feature when part of the page was updated 275 */ 276 277 278 document.addEventListener('joomla:updated', function (_ref) { 279 var target = _ref.target; 280 281 // Check is it subform, then wee need to fix some "showon" config 282 if (target.classList.contains('subform-repeatable-group')) { 283 var elements = [].slice.call(target.querySelectorAll('[data-showon]')); 284 285 if (elements.length) { 286 var search = []; 287 var replace = []; // Collect all parent groups of changed group 288 289 getMatchedParents(target, '.subform-repeatable-group').forEach(function ($parent) { 290 search.push(new RegExp("\\[" + $parent.dataset.baseName + "X\\]", 'g')); 291 replace.push("[" + $parent.dataset.group + "]"); 292 }); // Fix showon field names in a current group 293 294 elements.forEach(function (element) { 295 var showon = element.dataset.showon; 296 search.forEach(function (pattern, i) { 297 showon = showon.replace(pattern, replace[i]); 298 }); 299 element.dataset.showon = showon; 300 }); 301 } 302 } 303 304 Joomla.Showon.initialise(target); 305 }); 306 307 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |