Conception et traitement de scripts côté client
Des scripts clients bien conçus peuvent réduire le temps nécessaire aux utilisateurs pour remplir un formulaire.
Un traitement côté client correct dépend du chargement initial du formulaire. La mise à jour des enregistrements avant le chargement du formulaire peut entraîner des résultats inattendus qui contournent le traitement côté client.
- Désactivez l’édition de liste pour la table.
- Créez des règles métier ou des contrôles d’accès appropriés pour la modification des listes.
- Créer des politiques de données.
- Créez un script client onCellEdit distinct.
Restreindre l’édition de listes
Si vous créez des politiques d’interface utilisateur ou des scripts clients pour les champs d’un formulaire, vous devez utiliser une autre méthode pour vous assurer que les données de ces champs sont contrôlées de la même manière dans une liste.
- Désactivez l’édition de liste pour la table.
- Créez des règles métier ou des contrôles d’accès appropriés pour la modification des listes.
- Créer des politiques de données.
- Créez un script client onCellEdit distinct.
Réduire les recherches de serveur
Utilisez les données client autant que possible pour éliminer le besoin de recherches fastidieuses sur le serveur.
Le scripting client utilise soit les données disponibles sur le client, soit les données récupérées sur le serveur. Les principales façons d’obtenir des informations à partir du serveur sont la recherche GlideAjax g_scratchpad et asynchrone.
La principale différence entre ces méthodes est que g_scratchpad est envoyée une fois lorsqu’un formulaire est chargé (les informations sont transmises du serveur au client), tandis que GlideAjax est déclenché dynamiquement lorsque le client demande des informations au serveur.
Récupérer les données du serveur à l’aide de g_scratchpad
L’objet g_scratchpad transmet des informations du serveur au client, par exemple lorsque le client a besoin d’informations non disponibles sur le formulaire.Par exemple, si vous avez un script client qui doit accéder au champ u_retrieve et que ce champ n’est pas sur le formulaire, les données ne sont pas disponibles pour le script client. Une solution classique à ce problème consiste à placer le champ sur le formulaire, puis à toujours le masquer avec un script client ou une politique d’interface utilisateur. Bien que cette solution soit plus rapide à configurer, son exécution est plus lente.
Si vous savez quelles informations le client doit obtenir du serveur avant le chargement du formulaire, une règle métier d’affichage peut créer g_scratchpad propriétés pour conserver ces informations. Theg_scratchpad est envoyée au client lorsque le formulaire est demandé, ce qui le rend disponible pour toutes les méthodes de scripting côté client. Il s’agit d’un moyen très efficace d’envoyer des informations du serveur au client. Toutefois, vous ne pouvez charger des données de cette façon que lorsque le formulaire est chargé. La règle métier ne peut pas être déclenchée dynamiquement. Dans ce cas, utilisez un appel GlideAjax asynchrone.
- Valeur de la propriété système css.base.color
- Indique si l’enregistrement actuel comporte ou non des pièces jointes
- Le nom du gestionnaire de l’appelant
g_scratchpad.css = gs.getProperty('css.base.color');
g_scratchpad.hasAttachments = current.hasAttachments();
g_scratchpad.managerName = current.caller_id.manager.getDisplayValue();// Check if the form has attachments
if (g_scratchpad.hasAttachments)
// do something interesting here
else
alert('You need to attach a form signed by ' + g_scratchpad.managerName);Récupérer les données du serveur à l’aide de GlideAjax asynchrone
GlideAjax asynchrone vous permet de demander dynamiquement des informations au serveur.
//Alert if the assignment groups name matches the support group
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading)
return;
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getCiSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.addParam('sysparm_ag', g_form.getValue('assignment_group'));
ga.getXML(doAlert); // Always try to use asynchronous (getXML) calls rather than synchronous (getXMLWait)
}
// Callback function to process the response returned from the server
function doAlert(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
alert(answer);
}var ciCheck = Class.create();
ciCheck.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getCiSupportGroup: function() {
var retVal = ''; // Return value
var ciID = this.getParameter('sysparm_ci');
var agID = this.getParameter('sysparm_ag');
var ciRec = new GlideRecord('cmdb_ci');
// If we can read the record, check if the sys_ids match
if (ciRec.get(ciID)) {
if (ciRec.getValue('support_group') == agID)
retVal = 'CI support group and assignment group match';
else
retVal = 'CI support group and assignment group do not match';
// Can't read the CI, then they don't match
} else {
retVal = 'CI support group and assignment group do not match';
}
return retVal;
}
});Utiliser le paramètre displayValue setValue() pour les champs de référence
Lors de l’utilisation de setValue() sur un champ de référence, incluez le paramètre displayValue pour éviter des appels de serveur supplémentaires.
Lorsque vous utilisez setValue() sur un champ de référence, assurez-vous d’inclure la valeur d’affichage du champ de référence comme 3ème paramètre. Si vous définissez la valeur sans displayValue, l’instance effectue un appel synchrone pour récupérer la valeur d’affichage de l’enregistrement que vous avez spécifié. Cet aller-retour supplémentaire vers le serveur peut avoir un impact sur les performances.
var id = '5137153cc611227c000bbd1bd8cd2005';
g_form.setValue('assigned_to', id); // Client needs to go back to the server to
// fetch the name that goes with this IDvar id = '5137153cc611227c000bbd1bd8cd2005';
var name = 'Fred Luddy';
g_form.setValue('assigned_to', id, name); // No server call requiredUtiliser une politique d’interface utilisateur au lieu d’un script client
Dans la mesure du possible, envisagez d’utiliser une politique d’interface utilisateur au lieu d’un script client.
- Les politiques d’interface utilisateur disposent d’un champ Ordre pour permettre un contrôle total sur l’ordre dans lequel les opérations côté client ont lieu.
- Les politiques d’interface utilisateur n’exigent pas de scripting pour rendre un champ obligatoire, en lecture seule ou visible.
Valider l’entrée à l’aide de scripts clients
Une excellente utilisation des scripts clients consiste à valider l’entrée de l’utilisateur.
Cette validation améliore l’expérience utilisateur, car l’utilisateur découvre s’il existe des problèmes de données avant de soumettre les informations.
if (g_form.getValue('impact') == '3' && g_form.getValue('priority') == '1')
g_form.showFieldMsg('impact', getMessage('Low impact now allowed with High priority'), 'error');
Définir l’ordre des scripts clients
Contrôlez l’ordre d’exécution de vos scripts clients à l’aide du champ Ordre. Pour éviter que deux ou plusieurs scripts clients s’exécutent simultanément et n’entrent en conflit, vous pouvez ajouter un ordre d’exécution des scripts.
Avant de commencer
Pourquoi et quand exécuter cette tâche
Procédure
Éviter la manipulation des DOM
Évitez autant que possible la manipulation du DOM (Document Object Model). Cela peut entraîner un problème de maintenabilité lorsque les navigateurs sont mis à jour.
Au lieu de cela, utilisez l’API GlideForm ou envisagez une approche différente pour la solution. En général, lorsque vous utilisez des méthodes de manipulation DOM, vous devez référencer un élément dans le DOM par ID ou à l’aide d’un sélecteur CSS. Lorsque vous faites référence à des éléments DOM prêts à l’emploi, il existe un risque que l’ID d’élément ou l’emplacement dans le DOM puisse changer, entraînant l’arrêt du fonctionnement du code et/ou générant des erreurs. Faites preuve de prévoyance, de prudence et comprenez parfaitement le risque que vous encourez. Examinez ces objets et réduisez autant que possible l’utilisation des méthodes de manipulation des DOM.
Éviter les scripts clients globaux
Un script client global est tout script client dans lequel la table sélectionnée est globale. Les scripts clients globaux n’ont aucune restriction de table, par conséquent, ils se chargeront sur chaque page du système, introduisant ainsi un délai de chargement du navigateur.
Il n’y a aucun avantage à charger ce type de scripts sur chaque page.
Comme alternative, et pour une approche plus modulaire et évolutive, envisagez de déplacer les scripts clients vers une table de base (telle que Tâche[task] ou Élément de configuration[cmdb_ci]) qui peut être dérivée pour toutes les tables enfants/extensibles. Le système évite ainsi de charger les scripts sur chaque formulaire de l’interface utilisateur, tels que les pages d’accueil ou Service Catalog où ils sont rarement (voire jamais) nécessaires.
Enfermer le code dans les fonctions
Encerclez le code dans un script client à l’intérieur d’une fonction.
Les scripts clients sans fonction entraînent des problèmes avec la portée variable. Lorsque le code n’est pas entouré d’une fonction, les variables et autres objets sont disponibles et partagés avec tous les autres scripts côté client. Si vous utilisez les mêmes noms de variables, il est possible qu’ils entrent en collision. Cela peut entraîner des conséquences inattendues difficiles à résoudre.
var state = "6";
function onSubmit() {
if(g_form.getValue('incident_state') == state) {
alert("This incident is Resolved");
}
}function onSubmit() {
var state = "6";
if(g_form.getValue('incident_state') == state) {
alert("This incident is Resolved");
}
}Cette solution est beaucoup plus sûre car la portée de l’état variable est limitée à la fonction onSubmit(). Par conséquent, la variable state n’entre pas en conflit avec les variables state dans d’autres scripts côté client.
Exécuter uniquement les scripts nécessaires
Pour éviter d’exécuter inutilement des scripts chronophages, assurez-vous que les scripts clients n’effectuent que les tâches nécessaires.
Les exemples suivants illustrent les améliorations apportées à l’exemple de code initial. Chaque exemple montre une amélioration particulière du script afin d’améliorer les performances et d’éviter les appels inutiles.
N’oubliez pas que les scripts clients n’ont pas de champ Condition . Cela signifie que les scripts onLoad() et onChange() s’exécutent dans leur intégralité à chaque fois que le formulaire approprié est chargé. Cet exemple est un script client onChange() inefficace qui doit s’exécuter lorsque le champ Élément de configuration change.
//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading) {
var ciSupportGroup = g_form.getReference('cmdb_ci').support_group;
if (ciSupportGroup != '' && g_form.getValue('assignment_group) != '')
g_form.setValue('assignment_group', ciRec.support_group.sys_id);
}
Cet exemple améliore le premier en remplaçant la recherche getReference() ou GlideRecord par un appel GlideAjax asynchrone.
//Set Assignment Group to support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}
L’indicateur isLoading est le moyen le plus simple d’empêcher le code inutile de prendre du temps de navigation dans les scripts onChange. Le isLoading marqueur doit être utilisé au début de tout script dont l’exécution n’est pas nécessaire lorsque le formulaire est en cours de chargement. Il n’est pas nécessaire d’exécuter ce script lors d’un chargement de formulaire, car la logique s’est déjà exécutée lors de la dernière modification du champ. L’ajout de la isLoading vérification au script empêche qu’il effectue une recherche de cmdb_ci à chaque chargement de formulaire.
Le isTemplate marqueur indique qu’un modèle est en cours de chargement.
//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading) {}; // run during loading
// rest of script here
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
if (newValue != oldValue) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
if (newValue != oldValue) {
if (g_form.getValue('assignment_group') == '') {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}