199 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * @copyright   (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
 | |
|  * @license     GNU General Public License version 2 or later; see LICENSE.txt
 | |
|  */
 | |
| Joomla = window.Joomla || {};
 | |
| ((Joomla, document) => {
 | |
| 
 | |
|   Joomla.hideAssociation = (formControl, languageCode) => {
 | |
|     document.querySelectorAll('#associations .control-group').forEach(element => {
 | |
|       // Current selected language. Hide it
 | |
|       const el = element.querySelector('.control-label label');
 | |
|       if (el) {
 | |
|         const attribute = el.getAttribute('for');
 | |
|         if (attribute.replace(/_name$/, '') === `${formControl}_associations_${languageCode.replace('-', '_')}`) {
 | |
|           element.classList.add('hidden');
 | |
|         }
 | |
|       }
 | |
|     });
 | |
|   };
 | |
|   Joomla.showAssociationMessage = () => {
 | |
|     const associations = document.getElementById('associations');
 | |
|     if (associations) {
 | |
|       const html = document.createElement('joomla-alert');
 | |
|       html.innerText = Joomla.Text._('JGLOBAL_ASSOC_NOT_POSSIBLE');
 | |
|       associations.insertAdjacentElement('afterbegin', html);
 | |
|     }
 | |
|     document.querySelectorAll('#associations .control-group').forEach(element => {
 | |
|       element.classList.add('hidden');
 | |
|     });
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Inject associations into other association fields
 | |
|    *
 | |
|    * This function is called whenever the Ajax request within propagateAssociation() completes
 | |
|    * successfully.
 | |
|    * Its purpose is to inject the associations which have been returned in the Ajax response into
 | |
|    * the other association fields in the form.
 | |
|    * It does this by invoking the various callback functions of those association fields (i.e. the
 | |
|    * function which gets called whenever the administrator selects an association via the modal),
 | |
|    * and passing the appropriate associated record details.
 | |
|    *
 | |
|    * @param   result                  The response from the Ajax request.
 | |
|    *                                  Its structure is that generated by the JResponseJson class,
 | |
|    *                                  with the data field containing the associations
 | |
|    * @param   callbackFunctionPrefix  The name of the callback function which the modal window uses
 | |
|    *                                  to set the selected item as the association, but minus the
 | |
|    *                                  language tag at the end
 | |
|    *
 | |
|    * @return  boolean
 | |
|    *
 | |
|    * @since   3.9.0
 | |
|    */
 | |
|   Joomla.injectAssociations = (result, callbackFunctionPrefix) => {
 | |
|     let functionName;
 | |
|     if (result.success) {
 | |
|       if (result.data.length !== 0) {
 | |
|         Object.keys(result.data).forEach(lang => {
 | |
|           functionName = callbackFunctionPrefix + lang.replace('-', '_');
 | |
|           window[functionName](result.data[lang].id, result.data[lang].title, result.data[lang].catid, null, null, lang);
 | |
|         });
 | |
|       }
 | |
|       if (result.message) {
 | |
|         Joomla.renderMessages({
 | |
|           notice: [result.message]
 | |
|         });
 | |
|       }
 | |
|     } else {
 | |
|       Joomla.renderMessages({
 | |
|         warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED')]
 | |
|       });
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   /**
 | |
|    * Propagate associations from this field into other association fields
 | |
|    *
 | |
|    * This function is called whenever an administrator populates an association (in the association
 | |
|    * modal field) and then clicks on the Propagate button.
 | |
|    * The purpose of this function is to find what other records (if any) are associated with the
 | |
|    * one which the administrator has selected, and populate the other association fields with these
 | |
|    * records. (Otherwise, if the administrator just clicks on Save without clicking on Propagate,
 | |
|    * those other associations will be deleted). It does this by finding the id of the selected
 | |
|    * associated record (from a hidden field) and makes an Ajax call to the server to find the other
 | |
|    * associations, also passing up the language of the record currently being edited, as it should
 | |
|    * be excluded. Once it has received from the server the other associations it calls
 | |
|    * injectAssociations to inject them into the other association fields within the form.
 | |
|    *
 | |
|    * @param   fieldPrefix             The stem of the html ids for the elements comprising the
 | |
|    *                                  modal field
 | |
|    * @param   callbackFunctionPrefix  The name of the callback function which the modal window uses
 | |
|    *                                  to set the selected item as the association, but minus the
 | |
|    *                                  language tag at the end
 | |
|    *
 | |
|    * @return  boolean
 | |
|    *
 | |
|    * @since   3.9.0
 | |
|    */
 | |
|   Joomla.propagateAssociation = (fieldPrefix, callbackFunctionPrefix) => {
 | |
|     // Find the id of the record which has been set as an association
 | |
|     const assocId = document.getElementById(`${fieldPrefix}_id`).value;
 | |
| 
 | |
|     // Find the language of the record being edited
 | |
|     const languageField = document.getElementById('jform_language');
 | |
|     const currentLang = languageField.options[languageField.selectedIndex].value;
 | |
|     const data = {
 | |
|       task: 'ajax.fetchAssociations',
 | |
|       format: 'json',
 | |
|       assocId,
 | |
|       excludeLang: currentLang
 | |
|     };
 | |
|     data[Joomla.getOptions('csrf.token', '')] = 1;
 | |
|     const queryString = Object.keys(data).reduce((a, k) => {
 | |
|       a.push(`${k}=${encodeURIComponent(data[k])}`);
 | |
|       return a;
 | |
|     }, []).join('&');
 | |
|     const url = `${document.forms.adminForm.action}&${queryString}`;
 | |
|     Joomla.request({
 | |
|       // Find the action url associated with the form - we need to add the token to this
 | |
|       url,
 | |
|       method: 'GET',
 | |
|       data: JSON.stringify(data),
 | |
|       headers: {
 | |
|         'Content-Type': 'application/json'
 | |
|       },
 | |
|       onSuccess: response => {
 | |
|         Joomla.injectAssociations(JSON.parse(response), callbackFunctionPrefix);
 | |
|       },
 | |
|       onError: () => {
 | |
|         Joomla.renderMessages({
 | |
|           warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_PROPAGATE_FAILED')]
 | |
|         });
 | |
|       }
 | |
|     });
 | |
|     return false;
 | |
|   };
 | |
|   document.addEventListener('DOMContentLoaded', () => {
 | |
|     const associationsEditOptions = Joomla.getOptions('system.associations.edit');
 | |
|     const formControl = associationsEditOptions.formControl || 'jform';
 | |
|     const formControlLanguage = document.getElementById(`${formControl}_language`);
 | |
| 
 | |
|     // Hide the associations tab if needed
 | |
|     if (parseInt(associationsEditOptions.hidden, 10) === 1) {
 | |
|       Joomla.showAssociationMessage();
 | |
|     } else if (formControlLanguage) {
 | |
|       // Hide only the associations for the current language
 | |
|       Joomla.hideAssociation(formControl, formControlLanguage.value);
 | |
|     }
 | |
| 
 | |
|     // When changing the language
 | |
|     if (formControlLanguage) {
 | |
|       formControlLanguage.addEventListener('change', ({
 | |
|         target
 | |
|       }) => {
 | |
|         // Remove message if any
 | |
|         Joomla.removeMessages();
 | |
|         let existsAssociations = false;
 | |
| 
 | |
|         /** For each language, remove the associations, ie,
 | |
|          *  empty the associations fields and reset the buttons to Select/Create
 | |
|          */
 | |
|         document.querySelectorAll('#associations .control-group').forEach(element => {
 | |
|           const attribute = element.querySelector('.control-label label').getAttribute('for');
 | |
|           const languageCode = attribute.replace('_name', '').replace('jform_associations_', '');
 | |
| 
 | |
|           // Show the association fields
 | |
|           element.classList.remove('hidden');
 | |
| 
 | |
|           // Check if there was an association selected for this language
 | |
|           if (!existsAssociations && document.getElementById(`${formControl}_associations_${languageCode}_id`).value !== '') {
 | |
|             existsAssociations = true;
 | |
|           }
 | |
| 
 | |
|           // Call the modal clear button
 | |
|           let clear = document.getElementById(`${formControl}_associations_${languageCode}_clear`);
 | |
|           clear = clear || element.querySelector('[data-button-action="clear"]');
 | |
|           clear.click();
 | |
|         });
 | |
| 
 | |
|         // If associations existed, send a warning to the user
 | |
|         if (existsAssociations) {
 | |
|           Joomla.renderMessages({
 | |
|             warning: [Joomla.Text._('JGLOBAL_ASSOCIATIONS_RESET_WARNING')]
 | |
|           });
 | |
|         }
 | |
| 
 | |
|         // If the selected language is All hide the fields and add a message
 | |
|         const selectedLanguage = target.value;
 | |
|         if (selectedLanguage === '*') {
 | |
|           Joomla.showAssociationMessage();
 | |
|         } else {
 | |
|           // Else show the associations fields/buttons and hide the current selected language
 | |
|           Joomla.hideAssociation(formControl, selectedLanguage);
 | |
|         }
 | |
|       });
 | |
|     }
 | |
|   });
 | |
| })(Joomla, document);
 |