ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç /** * This file contains JS functionality required by mforms and is included automatically * when required. */ // Namespace for the form bits and bobs M.form = M.form || {}; if (typeof M.form.dependencyManager === 'undefined') { var dependencyManager = function() { dependencyManager.superclass.constructor.apply(this, arguments); }; Y.extend(dependencyManager, Y.Base, { _locks: null, _hides: null, _dirty: null, _nameCollections: null, _fileinputs: null, _staticElements: null, _editors: null, _editorNameSuffix: '[text]', initializer: function() { // Setup initial values for complex properties. this._locks = {}; this._hides = {}; this._dirty = {}; // Setup event handlers. Y.Object.each(this.get('dependencies'), function(value, i) { var elements = this.elementsByName(i); elements.each(function(node) { var nodeName = node.get('nodeName').toUpperCase(); if (nodeName == 'INPUT') { if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) { node.on('click', this.updateEventDependencies, this); } else { node.on('blur', this.updateEventDependencies, this); } node.on('change', this.updateEventDependencies, this); } else if (nodeName == 'SELECT') { node.on('change', this.updateEventDependencies, this); } else { node.on('click', this.updateEventDependencies, this); node.on('blur', this.updateEventDependencies, this); node.on('change', this.updateEventDependencies, this); } }, this); }, this); // Handle the reset button. this.get('form').get('elements').each(function(input) { if (input.getAttribute('type') == 'reset') { input.on('click', function() { this.get('form').reset(); this.updateAllDependencies(); }, this); } }, this); this.updateAllDependencies(); }, /** * Initializes the mapping from element name to YUI NodeList */ initElementsByName: function() { var names = {}; // Form elements with a given name. var allnames = {}; // Form elements AND outer elements for groups with a given name. // Collect element names. Y.Object.each(this.get('dependencies'), function(conditions, i) { names[i] = new Y.NodeList(); allnames[i] = new Y.NodeList(); for (var condition in conditions) { for (var value in conditions[condition]) { for (var hide in conditions[condition][value]) { for (var ei in conditions[condition][value][hide]) { names[conditions[condition][value][hide][ei]] = new Y.NodeList(); allnames[conditions[condition][value][hide][ei]] = new Y.NodeList(); } } } } }); // Locate elements for each name. this.get('form').get('elements').each(function(node) { var name = node.getAttribute('name'); if (({}).hasOwnProperty.call(names, name)) { names[name].push(node); allnames[name].push(node); } else if (this.isEditor(name)) { // If this is an editor, we need to remove the suffix. name = name.replace(this._editorNameSuffix, ''); if (({}).hasOwnProperty.call(names, name)) { names[name].push(node); allnames[name].push(node); } } }, this); // Locate any groups with the given name. this.get('form').all('.fitem').each(function(node) { var name = node.getData('groupname'); if (name && ({}).hasOwnProperty.call(allnames, name)) { allnames[name].push(node); } }); // Locate any static elements for each name. this.get('form').all('.form-control-static').each(function(node) { var name = node.getData('name'); if (({}).hasOwnProperty.call(allnames, name)) { names[name].push(node); allnames[name].push(node); } }); this._nameCollections = {names: names, allnames: allnames}; }, /** * Gets all elements in the form by their name and returns * a YUI NodeList * * @param {String} name The form element name. * @param {Boolean} includeGroups (optional - default false) Should the outer element for groups be included? * @return {Y.NodeList} */ elementsByName: function(name, includeGroups) { if (includeGroups === undefined) { includeGroups = false; } var collection = (includeGroups ? 'allnames' : 'names'); if (!this._nameCollections) { this.initElementsByName(); } if (!({}).hasOwnProperty.call(this._nameCollections[collection], name)) { return new Y.NodeList(); } return this._nameCollections[collection][name]; }, /** * Checks the dependencies the form has an makes any changes to the * form that are required. * * Changes are made by functions title _dependency{Dependencytype} * and more can easily be introduced by defining further functions. * * @param {EventFacade | null} e The event, if any. * @param {String} dependon The form element name to check dependencies against. * @return {Boolean} */ checkDependencies: function(e, dependon) { var dependencies = this.get('dependencies'), tohide = {}, tolock = {}, condition, value, isHide, lock, hide, checkfunction, result, elements; if (!({}).hasOwnProperty.call(dependencies, dependon)) { return true; } elements = this.elementsByName(dependon); for (condition in dependencies[dependon]) { for (value in dependencies[dependon][condition]) { for (isHide in dependencies[dependon][condition][value]) { checkfunction = '_dependency' + condition[0].toUpperCase() + condition.slice(1); if (Y.Lang.isFunction(this[checkfunction])) { result = this[checkfunction].apply(this, [elements, value, (isHide === "1"), e]); } else { result = this._dependencyDefault(elements, value, (isHide === "1"), e); } lock = result.lock || false; hide = result.hide || false; for (var ei in dependencies[dependon][condition][value][isHide]) { var eltolock = dependencies[dependon][condition][value][isHide][ei]; if (({}).hasOwnProperty.call(tohide, eltolock)) { tohide[eltolock] = tohide[eltolock] || hide; } else { tohide[eltolock] = hide; } if (({}).hasOwnProperty.call(tolock, eltolock)) { tolock[eltolock] = tolock[eltolock] || lock; } else { tolock[eltolock] = lock; } } } } } for (var el in tolock) { var needsupdate = false; if (!({}).hasOwnProperty.call(this._locks, el)) { this._locks[el] = {}; } if (({}).hasOwnProperty.call(tolock, el) && tolock[el]) { if (!({}).hasOwnProperty.call(this._locks[el], dependon) || this._locks[el][dependon]) { this._locks[el][dependon] = true; needsupdate = true; } } else if (({}).hasOwnProperty.call(this._locks[el], dependon) && this._locks[el][dependon]) { delete this._locks[el][dependon]; needsupdate = true; } if (!({}).hasOwnProperty.call(this._hides, el)) { this._hides[el] = {}; } if (({}).hasOwnProperty.call(tohide, el) && tohide[el]) { if (!({}).hasOwnProperty.call(this._hides[el], dependon) || this._hides[el][dependon]) { this._hides[el][dependon] = true; needsupdate = true; } } else if (({}).hasOwnProperty.call(this._hides[el], dependon) && this._hides[el][dependon]) { delete this._hides[el][dependon]; needsupdate = true; } if (needsupdate) { this._dirty[el] = true; } } return true; }, /** * Update all dependencies in form */ updateAllDependencies: function() { Y.Object.each(this.get('dependencies'), function(value, name) { this.checkDependencies(null, name); }, this); this.updateForm(); }, /** * Update dependencies associated with event * * @param {Event} e The event. */ updateEventDependencies: function(e) { var el = e.target.getAttribute('name'); this.checkDependencies(e, el); this.updateForm(); }, /** * Flush pending changes to the form */ updateForm: function() { var el; for (el in this._dirty) { if (({}).hasOwnProperty.call(this._locks, el)) { this._disableElement(el, !Y.Object.isEmpty(this._locks[el])); } if (({}).hasOwnProperty.call(this._hides, el)) { this._hideElement(el, !Y.Object.isEmpty(this._hides[el])); } } this._dirty = {}; }, /** * Disables or enables all form elements with the given name * * @param {String} name The form element name. * @param {Boolean} disabled True to disable, false to enable. */ _disableElement: function(name, disabled) { const els = this.elementsByName(name), filepicker = this.isFilePicker(name), editors = this.get('form').all('.fitem [data-fieldtype="editor"] textarea[name="' + name + '[text]"]'), staticElement = this.isStaticElement(name); els.each(function(node) { const fitem = node.ancestor('.fitem'); if (disabled) { node.setAttribute('disabled', 'disabled'); } else { node.removeAttribute('disabled'); } // Enable/Disable static elements if exist. if (staticElement) { const disabledNonTextElements = 'INPUT,SELECT,TEXTAREA,BUTTON,A'; if (disabled) { // Mute the text inside the current static element. fitem.addClass('text-muted'); // Disabled non-text elements in the static if exist. fitem.all(disabledNonTextElements).each(function(disabledElement) { if (disabledElement.get('tagName').toUpperCase() === "A") { disabledElement.addClass('disabled'); } else { disabledElement.setAttribute('disabled', 'disabled'); } }); } else { // Unmute the text inside the current static element. fitem.removeClass('text-muted'); // Enabled non-text elements in the static if exist. fitem.all(disabledNonTextElements).each(function(disabledElement) { if (disabledElement.get('tagName').toUpperCase() === "A") { disabledElement.removeClass('disabled'); } else { disabledElement.removeAttribute('disabled', 'disabled'); } }); } } // Extra code to disable filepicker or filemanager form elements if (filepicker) { if (fitem) { if (disabled) { fitem.addClass('disabled'); } else { fitem.removeClass('disabled'); } } } }); editors.each(function(editor) { if (disabled) { editor.setAttribute('readonly', 'readonly'); } else { editor.removeAttribute('readonly', 'readonly'); } editor.getDOMNode().dispatchEvent(new Event('form:editorUpdated')); }); }, /** * Hides or shows all form elements with the given name. * * @param {String} name The form element name. * @param {Boolean} hidden True to hide, false to show. */ _hideElement: function(name, hidden) { var els = this.elementsByName(name, true); els.each(function(node) { var e = node.ancestor('.fitem', true); var label = null, id = null; if (e) { // Cope with differences between clean and boost themes. if (e.hasClass('fitem_fgroup')) { // Items within groups are not wrapped in div.fitem in theme_clean, so // we need to hide the input, not the div.fitem. e = node; } if (hidden) { e.setAttribute('hidden', 'hidden'); } else { e.removeAttribute('hidden'); } e.setStyles({ display: (hidden) ? 'none' : '' }); // Hide/unhide the label as well. id = node.get('id'); if (id) { label = Y.all('label[for="' + id + '"]'); if (label) { if (hidden) { label.setAttribute('hidden', 'hidden'); } else { label.removeAttribute('hidden'); } label.setStyles({ display: (hidden) ? 'none' : '' }); } } } }); }, /** * Is the form element inside a filepicker or filemanager? * * @param {String} el The form element name. * @return {Boolean} */ isFilePicker: function(el) { if (!this._fileinputs) { var fileinputs = {}; var selector = '.fitem [data-fieldtype="filepicker"] input,.fitem [data-fieldtype="filemanager"] input'; // Include a selector where the filemanager input is nested in a group. selector += ',.fitem [data-fieldtype="group"] input[id*="filemanager"]'; var els = this.get('form').all(selector); els.each(function(node) { fileinputs[node.getAttribute('name')] = true; }); this._fileinputs = fileinputs; } if (({}).hasOwnProperty.call(this._fileinputs, el)) { return this._fileinputs[el] || false; } return false; }, /** * Checks if a form element with the given name is static. * * @param {string} el - The name of the form element to check. * @returns {boolean} - Returns true if the form element is static, otherwise false. */ isStaticElement: function(el) { if (!this._staticElements) { const staticElements = {}; const els = this.get('form').all('.fitem [data-fieldtype="static"] .form-control-static'); els.each(function(node) { if (node.getData('name') === el) { staticElements[node.getData('name')] = true; } }); this._staticElements = staticElements; } if (({}).hasOwnProperty.call(this._staticElements, el)) { return this._staticElements[el] || false; } return false; }, _dependencyNotchecked: function(elements, value, isHide) { var lock = false; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'hidden' && !this.siblings('input[type=checkbox][name="' + this.get('name') + '"]').isEmpty()) { // This is the hidden input that is part of an advcheckbox. return; } if (this.getAttribute('type').toLowerCase() == 'radio' && this.get('value') != value) { return; } lock = lock || !Y.Node.getDOMNode(this).checked; }); return { lock: lock, hide: isHide ? lock : false }; }, _dependencyChecked: function(elements, value, isHide) { var lock = false; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'hidden' && !this.siblings('input[type=checkbox][name="' + this.get('name') + '"]').isEmpty()) { // This is the hidden input that is part of an advcheckbox. return; } if (this.getAttribute('type').toLowerCase() == 'radio' && this.get('value') != value) { return; } lock = lock || Y.Node.getDOMNode(this).checked; }); return { lock: lock, hide: isHide ? lock : false }; }, _dependencyNoitemselected: function(elements, value, isHide) { var lock = false; elements.each(function() { lock = lock || this.get('selectedIndex') == -1; }); return { lock: lock, hide: isHide ? lock : false }; }, _dependencyEq: function(elements, value, isHide) { var lock = false; var hiddenVal = false; var options, v, selected, values; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'radio' && !Y.Node.getDOMNode(this).checked) { return; } else if (this.getAttribute('type').toLowerCase() == 'hidden' && !this.siblings('input[type=checkbox][name="' + this.get('name') + '"]').isEmpty()) { // This is the hidden input that is part of an advcheckbox. hiddenVal = (this.get('value') == value); return; } else if (this.getAttribute('type').toLowerCase() == 'checkbox' && !Y.Node.getDOMNode(this).checked) { lock = lock || hiddenVal; return; } if (this.getAttribute('class').toLowerCase() == 'filepickerhidden') { // Check for filepicker status. const elementId = this.getAttribute('id'); if (elementId && M.form_filepicker.instances[elementId].fileadded) { lock = false; } else { lock = true; } } else if (this.get('nodeName').toUpperCase() === 'SELECT' && this.get('multiple') === true) { // Multiple selects can have one or more value assigned. A pipe (|) is used as a value separator // when multiple values have to be selected at the same time. values = value.split('|'); selected = []; options = this.get('options'); options.each(function() { if (this.get('selected')) { selected[selected.length] = this.get('value'); } }); if (values.length === 1 && values[0] === '') { // Values array contains a single empty entry -> value was empty. lock = selected.length === 0; return; } if (selected.length !== values.length) { lock = false; return; } lock = true; for (const i in selected) { v = selected[i]; if (values.indexOf(v) === -1) { lock = false; return; } } } else { lock = lock || this.get('value') == value; } }); return { lock: lock, hide: isHide ? lock : false }; }, /** * Lock the given field if the field value is in the given set of values. * * @param {Array} elements * @param {String} values Single value or pipe (|) separated values when multiple * @returns {{lock: boolean, hide: boolean}} * @private */ _dependencyIn: function(elements, values, isHide) { // A pipe (|) is used as a value separator // when multiple values have to be passed on at the same time. values = values.split('|'); var lock = false; var hiddenVal = false; var options, v, selected, value; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'radio' && !Y.Node.getDOMNode(this).checked) { return; } else if (this.getAttribute('type').toLowerCase() == 'hidden' && !this.siblings('input[type=checkbox][name="' + this.get('name') + '"]').isEmpty()) { // This is the hidden input that is part of an advcheckbox. hiddenVal = (values.indexOf(this.get('value')) > -1); return; } else if (this.getAttribute('type').toLowerCase() == 'checkbox' && !Y.Node.getDOMNode(this).checked) { lock = lock || hiddenVal; return; } if (this.getAttribute('class').toLowerCase() == 'filepickerhidden') { // Check for filepicker status. const elementId = this.getAttribute('id'); if (elementId && M.form_filepicker.instances[elementId].fileadded) { lock = false; } else { lock = true; } } else if (this.get('nodeName').toUpperCase() === 'SELECT' && this.get('multiple') === true) { // Multiple selects can have one or more value assigned. selected = []; options = this.get('options'); options.each(function() { if (this.get('selected')) { selected[selected.length] = this.get('value'); } }); // Needed to support subset resolution for empty selects, where 'no selection' is represented by ''. if (selected.length == 0) { selected.push(''); } // Lock/hide if the selected values are a subset of the values. let isSubset = selected.every(element => values.includes(element)); lock = isSubset; return; } else { value = this.get('value'); lock = lock || (values.indexOf(value) > -1); } }); return { lock: lock, hide: isHide ? lock : false }; }, _dependencyHide: function(elements, value) { return { lock: false, hide: true }; }, _dependencyDefault: function(elements, value, isHide) { var lock = false, hiddenVal = false, values ; elements.each(function() { var selected; if (this.getAttribute('type').toLowerCase() == 'radio' && !Y.Node.getDOMNode(this).checked) { return; } else if (this.getAttribute('type').toLowerCase() == 'hidden' && !this.siblings('input[type=checkbox][name="' + this.get('name') + '"]').isEmpty()) { // This is the hidden input that is part of an advcheckbox. hiddenVal = (this.get('value') != value); return; } else if (this.getAttribute('type').toLowerCase() == 'checkbox' && !Y.Node.getDOMNode(this).checked) { lock = lock || hiddenVal; return; } // Check for filepicker status. if (this.getAttribute('class').toLowerCase() == 'filepickerhidden') { const elementId = this.getAttribute('id'); if (elementId && M.form_filepicker.instances[elementId].fileadded) { lock = true; } else { lock = false; } } else if (this.get('nodeName').toUpperCase() === 'SELECT' && this.get('multiple') === true) { // Multiple selects can have one or more value assigned. A pipe (|) is used as a value separator // when multiple values have to be selected at the same time. values = value.split('|'); selected = []; this.get('options').each(function() { if (this.get('selected')) { selected[selected.length] = this.get('value'); } }); if (values.length === 1 && values[0] === '') { // Values array contains a single empty entry -> value was empty. lock = selected.length !== 0; return; } if (selected.length !== values.length) { lock = true; return; } lock = false; for (const i in selected) { if (values.indexOf(selected[i]) === -1) { lock = true; return; } } } else { lock = lock || this.get('value') != value; } }); return { lock: lock, hide: isHide ? lock : false }; }, /** * Is the form element an editor? * * @param {String} el The form element name. * @return {Boolean} */ isEditor: function(el) { if (!this._editors) { let editors = {}; const selector = '.fitem [data-fieldtype="editor"] textarea'; const els = this.get('form').all(selector); els.each(function(node) { editors[node.getAttribute('name')] = true; }); this._editors = editors; } return this._editors[el] || false; }, }, { NAME: 'mform-dependency-manager', ATTRS: { form: { setter: function(value) { return Y.one('#' + value); }, value: null }, dependencies: { value: {} } } }); M.form.dependencyManager = dependencyManager; } /** * Stores a list of the dependencyManager for each form on the page. */ M.form.dependencyManagers = {}; /** * Initialises a manager for a forms dependencies. * This should happen once per form. * * @param {YUI} Y YUI3 instance * @param {String} formid ID of the form * @param {Array} dependencies array * @return {M.form.dependencyManager} */ M.form.initFormDependencies = function(Y, formid, dependencies) { // If the dependencies isn't an array or object we don't want to // know about it if (!Y.Lang.isArray(dependencies) && !Y.Lang.isObject(dependencies)) { return false; } /** * Fixes an issue with YUI's processing method of form.elements property * in Internet Explorer. * http://yuilibrary.com/projects/yui3/ticket/2528030 */ Y.Node.ATTRS.elements = { getter: function() { return Y.all(new Y.Array(this._node.elements, 0, true)); } }; M.form.dependencyManagers[formid] = new M.form.dependencyManager({form: formid, dependencies: dependencies}); return M.form.dependencyManagers[formid]; }; /** * Update the state of a form. You need to call this after, for example, changing * the state of some of the form input elements in your own code, in order that * things like the disableIf state of elements can be updated. * * @param {String} formid ID of the form */ M.form.updateFormState = function(formid) { if (formid in M.form.dependencyManagers) { M.form.dependencyManagers[formid].updateAllDependencies(); } };