Nous traitons WebKit dans 1C, par exemple, l'intégration de TinyMCE dans un formulaire géré dans UT 11.4

Beaucoup savent déjà que dans la sortie de la plate-forme 8.3.14.1565, le navigateur Internet Explorer a été remplacé par le Web-Kit, c'est en fait un grand pas en avant, mais je suis sûr, comme moi, que ce n'est pas encore clair. Il y avait une expérience d'utilisation de web-kit dans 1C, appelant JS de 1C et appelant 1C de JS. Essayons de comprendre ensemble en quoi l'un diffère de l'autre et en même temps, faisons quelque chose d'utile. Oui, et sûrement beaucoup devront réécrire leurs métiers similaires après la mise à jour vers une nouvelle plate-forme, donc j'espère que mon expérience sera utile.

Tout a commencé avec le fait que la tâche a surgi: «Nous voulons, en UT, entrer une description formatée pour le produit afin qu'il vole plus tard vers la boutique en ligne», car la description standard du produit arrive en trait plein sans césure et n'a pas l'air très bien. Immédiatement, il y avait un désir d'utiliser un document formaté, il y a un simple éditeur, et vous pouvez le télécharger en HTML. Mais dès que j'ai montré le code HTML généré par le document formaté aux développeurs Web, ils ont immédiatement agité la main et ont dit que cela ne fonctionnerait pas. Le site a déjà ses propres styles pour afficher les éléments de bloc nécessaires et le comportement de ce type de texte peut devenir imprévisible.

La fonction Get HTML d'un document formaté renvoie une page HTML entièrement formée, avec la structure entière des balises, et ce qui est le plus désagréable, avec des styles en ligne. Cela ressemble à ceci.

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta name="format-detection" content="telephone=no" /> <style type="text/css"> body{margin:0;padding:8px;} p{line-height:1.15;margin:0;white-space:pre-wrap;} ol,ul{margin-top:0;margin-bottom:0;} img{border:none;} li>p{display:inline;} </style> </head> <body> <p><span style="text-decoration: underline;"></span></p> <p><span style="font-weight: bold;"> </span></p> <p><span style="color: #ff0000;font-weight: normal;"> </span></p> <p><br></p> </body> </html> 

Et si obtenir le contenu de la balise body est une tâche simple, je ne voulais pas analyser et découper les attributs de style des balises.

TinyMCE ramène une belle mise en page. Vous autoriser les styles en ligne uniquement dans le cas de la couleur, ce qui est déjà beaucoup mieux.

 <p></p> <p><strong></strong></p> <p><span style="color: #ff0000;"></span></p> 

Il a été décidé d'intégrer TinyMCE, un éditeur de texte tiers. De plus, l'expérience de son intégration avec la communauté 1C est déjà assez large.

C'était peut-être une erreur à ce moment-là, et il suffisait d'analyser le texte généré par un document formaté, mais nous avons ce que nous avons.

1. Caractéristiques de la solution


Étant donné que 1C ne permet pas de télécharger des fichiers locaux du système de fichiers vers la page dans le champ HTML, pour cela, vous avez certainement besoin d'un serveur Web ou au moins l'adresse de ce fichier dans un stockage temporaire, placez la bibliothèque Tiny js à côté de 1C et chargez-la dans les en-têtes du document HTML vous ne pouvez pas - vous devrez également créer un fichier avec une mise en page HTML qui forme en interne une fenêtre d'éditeur prête à l'emploi et qui est déjà connecté au document HTML.

En général, en fait, vous pouvez charger une bibliothèque si vous obtenez une adresse dans le référentiel si elle a été compilée dans un fichier, et Tiny, en plus de la bibliothèque principale, contient également des fichiers js de plug-in, un gestionnaire de style et des styles, des fichiers de crack eux-mêmes , icônes, etc., et comme vous le comprenez, cela complique grandement la tâche. À un moment donné, il y avait même une idée de compiler toutes ces choses dans un seul fichier et de ne pas connaître les problèmes, mais il a fallu beaucoup de temps pour comprendre les outils. Ensuite, TinyMCE Builder a été trouvé sur le site officiel, qui compile tous les js dans un seul fichier et ce serait une petite victoire s'il faisait de même avec css, mais non, css se trouvait toujours à côté de plusieurs dossiers.

TinyMCE crée un iframe pour la fenêtre d'édition, qui est lui-même un document HTML incorporé dans la page, donc les événements qui se produisent dans cet iframe 1C ne peuvent pas être suivis, plus à ce sujet ci-dessous.

La configuration de UT 11.4 au moment du développement avait un mode de compatibilité de 8.3.12, donc en fait maintenant il utilisait IE comme navigateur intégré, mais une nouvelle mise à jour impliquait une transition vers de nouvelles versions qui utilisent déjà le web-kit.

2. Premières étapes


Les principales différences dans l'utilisation du kit Web:

L'objet principal des champs HTML a maintenant une structure différente et pour travailler avec le contenu de la page, vous devez utiliser la propriété defaultView

 .HTML.Document.DefaultView 

précédemment utilisé la propriété parentWindow pour cette

 .HTML.Document.parentWindow 

L'interdiction d'utiliser eval, qui était utilisé universellement pour appeler le code JS. Quelque chose comme ça

Elements.FieldHTML.Document.parentWindow.eval ("alert ('Call code from 1C')")
Mais vous pouvez accéder aux méthodes directement depuis 1C.

Elements.Description HTML.Document.DefaultView.NameMethodJS ();
Et j'ai rapidement créé des fonctions d'encapsulation pour toutes les méthodes Tiny dont j'ai besoin.

 function GetText(){ return tinyMCE.activeEditor.getContent({format: "text"}); } function SetText(text){ return tinyMCE.activeEditor.setContent(text); } function GetHTML(){ return tinyMCE.activeEditor.getContent(); } 

Qui s'est en outre adressé à partir de 1C afin

 HTML = .HTML.Document.DefaultView; HTML = HTML.GetHTML();  = HTML.GetText(); 

Bien que l'on puisse se débrouiller avec des appels directs à l'objet éditeur, par exemple,

 .HTML..defaultView.tinyMCE.activeEditor.getContent() 

Le traitement de la publication a été immédiatement téléchargé (un respect distinct pour l'auteur), ce qui m'a montré beaucoup de choses intéressantes. Cela a plus ou moins fonctionné sur IE, mais le copier-coller ne fonctionnait pas sur le webkit, au début, cela a causé une stupeur, mais plus tard, il est devenu clair que c'était à cause de l'iframe que le champ HTML n'était pas activé en cliquant à l'intérieur, car le clic s'est effectivement produit dans le document joint HTML dont les événements se sont coincés quelque part sur le chemin du 1C. Par conséquent, si vous appuyez sur Ctrl + C à un endroit du formulaire et essayez de le coller dans le champ de l'éditeur, le texte sera inséré dans ce champ d'où il a été copié car le champ HTML du document n'est pas activé. La même chose se produit dans le cas contraire, les raccourcis clavier pour copier-coller ne fonctionnent pas.

image

Au début, l'idée est venue qu'il s'agissait d'un jambage Tiny, et il bloque la pâte directe du tampon, comme CKEditor, qui offre une fenêtre distincte pour le collage à partir du tampon. Mais pour vérifier que c'était assez facile, j'ai créé un document vide avec un champ de saisie et j'ai essayé de copier et coller

image

Comme vous pouvez le voir, tout fonctionne. Le problème se situe donc quelque part dans Tiny ou en interaction avec 1C.

3. Décision


Pour résoudre le problème avec l'interaction du navigateur et de 1C, l'astuce habituelle a été appliquée, j'ai créé un bouton invisible sur la page HTML, et prévu de cliquer dessus depuis JS lorsque les événements nécessaires se sont produits à l'intérieur de la page que 1C intercepterait dans l'événement HTML Press. Mais à quel événement réaliser un programme presse?

La disposition ressemble à ceci:

 <body> <textarea id="editor"></textarea> <button id="button1c" style="display: none"></button> </body> 

Et une fonction pour déclencher un événement de clic de bouton

 function clickButton() { button1c.click(); } 

Auparavant, il était possible de transférer un objet de forme 1C dans le champ HTML en tant qu'objet, et en raison du fait qu'IE connecté à 1C via COM, le formulaire lui-même était en quelque sorte converti en un objet que IE comprenait et il était possible d'appeler des fonctions d'exportation de forme 1C directement à partir du code JS . Maintenant c'est impossible.

Nous avons étudié la documentation de l'API Tiny et trouvé une construction pour intercepter les gestionnaires d'événements et une combinaison appropriée d'événements qui devraient activer le champ HTML du document

 tinymce.activeEditor.on('click', function(e){clickButton(e)}); tinymce.activeEditor.on('KeyDown', function(e){clickButton(e)}); 

Vous devez mettre ce code à l'endroit où Tiny a déjà été initialisé. Je l'ai fait dans le gestionnaire de chargement de l'objet fenêtre . Mais vous pouvez le faire plus magnifiquement et placer le code lors de l'initialisation de Tiny dans le paramètre:

 init_instance_callback 

Maintenant, tout devrait être en ordre. Et le formulaire devrait fonctionner comme il se doit ...

C'est devenu beaucoup mieux, le champ HTML a vraiment commencé à être activé, mais pas toujours, pour une raison quelconque, certains clics n'ont pas entraîné le déplacement du focus vers le champ:

image

Cet enregistrement montre que si vous cliquez sur la ligne où le curseur clignote, le focus du champ fonctionne comme il se doit, mais si vous cliquez ci-dessous, le champ ne s'active pas.

C'était un artefact ennuyeux, et les tentatives de comprendre ce qui se passait n'ont donné aucune solution. J'ai émis des alertes vers le gestionnaire et des alertes ont été affichées, mais 1C n'a pas répondu à l'événement

image

Soudain, l'idée m'est venue à l'esprit: que se passe-t-il si 1C ne parvient pas à traiter l'événement sur le terrain, et si vous ralentissez un peu l'exécution du script JS et voyez ce qui se passe. La fonction de pause dans JS a été rapidement implémentée en utilisant des promesses et une attente asynchrone. Comme vous pouvez le voir dans JS, il manque également par défaut et rien, les gens vivent).

 function sleep(ms){ return new Promise(resolve => setTimeout(resolve, ms)); } async function clickButton(e){ await sleep(1); button1c.click(); } 

Ici, je règle le retard sur une milliseconde, avant de cliquer sur le bouton. Et le tour est joué. 1C a commencé à traiter le clic d'un bouton à temps.

image

4. Nous finissons l'échange


Étant donné que pour stocker la nouvelle description au format HTML, un nouvel attribut a été ajouté au répertoire, nous devons remplacer la valeur du champ typique lors du déchargement. Pour ce faire, dans le module ExchangeSiteRemoveable, ajoutez la fonction GetTexts of RequestsCatalog à l'extension et écrivez-y:

 . = (., ".", ".HTML_HTML"); 

C’est tout. Nous entamons l'échange et tout fonctionne, il ne reste plus qu'à effectuer des modifications sur le site, si nécessaire, afin que la description du produit soit perçue comme une mise en page et non comme une chaîne.

Résumé


Dans cet exemple, j'ai essayé l'interaction de JS WebKit et 1C, collecté le râteau et trouvé une solution.

Peut-être que pour résoudre ce problème, il était plus facile d'analyser et d'effacer le texte HTML d'un document formaté, mais ce ne serait pas si intéressant et pourrait poser des problèmes avec certaines options de mise en forme complexes.

Merci d'avoir lu.

Source: https://habr.com/ru/post/fr481768/


All Articles