Wir beschäftigen uns mit WebKit in 1C, zum Beispiel der Integration von TinyMCE in eine verwaltete Form in UT 11.4

Viele wissen bereits, dass in der Veröffentlichung der Plattform 8.3.14.1565 der Internet Explorer durch das Web-Kit ersetzt wurde. Dies ist eigentlich ein großer Schritt nach vorne, aber ich bin mir sicher, dass noch nicht klar ist, was was ist. Es gab die Erfahrung, Web-Kit in 1C zu verwenden, JS von 1C aufzurufen und 1C von JS aufzurufen. Versuchen wir gemeinsam zu verstehen, wie sich das eine vom anderen unterscheidet, und gleichzeitig etwas Nützliches zu tun. Ja, und sicherlich müssen viele ihre ähnlichen Fertigkeiten nach dem Update auf eine neue Plattform umschreiben, also hoffe ich, dass meine Erfahrung nützlich sein wird.

Alles begann damit, dass die Aufgabe lautete: „Wir möchten in UT eine formatierte Beschreibung für das Produkt eingeben, damit es später in den Onlineshop gelangt.“ Die Standardbeschreibung für das Produkt kommt in einer durchgezogenen Linie ohne Silbentrennung an und sieht nicht sehr gut aus. Sofort gab es den Wunsch, ein formatiertes Dokument zu verwenden, es gibt einen einfachen Editor, und Sie können es in HTML hochladen. Aber sobald ich den Webentwicklern den HTML-Code zeigte, der durch das formatierte Dokument generiert wurde, winkten sie sofort mit den Händen und sagten, dass dies nicht funktionieren würde. Die Site verfügt bereits über eigene Stile zum Anzeigen der erforderlichen Blockelemente, und das Verhalten dieser Art von Text kann unvorhersehbar werden.

Die Get HTML-Funktion eines formatierten Dokuments gibt eine vollständig formatierte HTML-Seite mit der gesamten Struktur der Tags und den unangenehmsten Inline-Stilen zurück. Es sieht so aus.

<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> 

Und wenn das Abrufen des Inhalts des Body-Tags eine einfache Aufgabe ist, wollte ich die Stilattribute nicht aus den Tags analysieren und ausschneiden.

TinyMCE bringt ein schönes Layout zurück. Erlauben Sie sich Inline-Stile nur bei Farbe, was schon viel besser ist.

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

Es wurde beschlossen, TinyMCE, einen Texteditor von Drittanbietern, zu integrieren. Darüber hinaus ist die Erfahrung bei der Integration in die 1C-Community bereits recht groß.

Vielleicht war es damals ein Fehler, und Sie mussten nur den von einem formatierten Dokument erzeugten Text analysieren, aber wir haben das, was wir haben.

1. Merkmale der Lösung


Da 1C das Hochladen lokaler Dateien aus dem Dateisystem auf die Seite im HTML-Feld nicht zulässt, benötigen Sie auf jeden Fall einen Webserver oder zumindest die Adresse dieser Datei im temporären Speicher. Stellen Sie die Tiny js-Bibliothek neben 1C und laden Sie sie in die Header des HTML-Dokuments Sie können nicht - Sie müssen auch eine Datei mit einem HTML-Layout erstellen, das intern ein vorgefertigtes Editorfenster bildet und bereits mit dem HTML-Dokument verbunden ist.

Im Allgemeinen können Sie eine Bibliothek laden, wenn Sie im Repository eine Adresse dafür erhalten, wenn sie in einer Datei kompiliert wurde. Tiny enthält neben der Hauptbibliothek auch Plug-in-JS-Dateien, einen Stil-Manager und Stile, die selbst Dateien knacken , Symbole usw., und wie Sie es verstehen, erschwert dies die Aufgabe erheblich. Zu einer Zeit gab es sogar die Idee, all dieses Zeug in eine Datei zu kompilieren und die Probleme nicht zu kennen, aber es dauerte lange, bis man die Werkzeuge verstanden hatte. Dann wurde TinyMCE Builder auf der offiziellen Website gefunden, die alle js in einer Datei zusammenfasst. Es wäre ein kleiner Sieg, wenn es dasselbe mit css machen würde, aber nein, css lag immer noch neben mehreren Ordnern.

TinyMCE erstellt einen Iframe für das Bearbeitungsfenster, das selbst ein in die Seite eingebettetes HTML-Dokument ist. Ereignisse, die in diesem Iframe 1C auftreten, können daher nicht nachverfolgt werden.

Die Konfiguration von UT 11.4 zum Zeitpunkt der Entwicklung hatte einen Kompatibilitätsmodus von 8.3.12, so dass nun der IE als integrierter Browser verwendet wurde. Ein weiteres Update erforderte jedoch einen Übergang zu neuen Versionen, die das Web-Kit bereits verwenden.

2. Erste Schritte


Die Hauptunterschiede beim Arbeiten mit dem Web-Kit:

Das Hauptobjekt der HTML-Felder hat jetzt eine andere Struktur. Um mit dem Inhalt der Seite arbeiten zu können, müssen Sie die Eigenschaft defaultView verwenden

 .HTML.Document.DefaultView 

Zuvor wurde hierfür die Eigenschaft parentWindow verwendet

 .HTML.Document.parentWindow 

Das Verbot der Verwendung von eval, das früher allgemein zum Aufrufen von JS-Code verwendet wurde. So etwas in der Art

Elements.FieldHTML.Document.parentWindow.eval ("alert ('Aufrufcode von 1C')")
Sie können jedoch direkt von 1C aus auf die Methoden zugreifen.

Elements.Description HTML.Document.DefaultView.NameMethodJS ();
Und ich habe schnell Wrapping-Funktionen für alle Tiny-Methoden erstellt, die ich benötige.

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

Welche weiter aus 1C so angesprochen

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

Obwohl man mit direkten Aufrufen des Editor-Objekts auskommen könnte, zum Beispiel

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

Die Verarbeitung aus der Publikation wurde sofort heruntergeladen (ein separater Hinweis an den Autor), der mir viele interessante Dinge zeigte. Es funktionierte mehr oder weniger im IE, aber das Kopieren und Einfügen funktionierte nicht im Webkit. Zuerst verursachte es einen Fehler. Später wurde jedoch klar, dass aufgrund des Iframes das HTML-Feld beim Klicken nicht aktiviert wurde, da der Klick tatsächlich im angehängten Dokument auftrat HTML, dessen Ereignisse irgendwo auf dem Weg zu 1C hängen blieben. Wenn Sie also an einer Stelle des Formulars Strg + C drücken und versuchen, es in das Feld des Editors einzufügen, wird der Text in das Feld eingefügt, aus dem er kopiert wurde, da das HTML-Feld des Dokuments nicht aktiviert ist. Das gleiche passiert im umgekehrten Fall, die Tastaturkürzel zum Kopieren und Einfügen funktionieren nicht.

Bild

Zuerst kam die Idee auf, dass es sich um einen winzigen Pfosten handelt, der direkte Paste aus dem Puffer blockiert, wie CKEditor, der ein separates Fenster zum Einfügen aus dem Puffer bietet. Aber um zu überprüfen, ob es ganz einfach war, habe ich ein leeres Dokument mit einem Eingabefeld erstellt und versucht, es zu kopieren und einzufügen

Bild

Wie Sie sehen, funktioniert alles. Das Problem liegt also irgendwo in Tiny oder in der Interaktion mit 1C.

3. Entscheidung


Um das Problem mit der Interaktion von Browser und 1C zu lösen, wurde der übliche Trick angewendet. Ich erstellte eine unsichtbare Schaltfläche auf der HTML-Seite und plante, in JS darauf zu klicken, wenn die erforderlichen Ereignisse auf der Seite eintraten, die 1C im HTML-Press-Ereignis abfangen würde. Aber bei welcher Veranstaltung soll eine Programmpresse durchgeführt werden?

Das Layout sieht ungefähr so ​​aus:

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

Und eine Funktion zum Auslösen eines Schaltflächen-Klick-Ereignisses

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

Bisher war es möglich, ein Objekt der Form 1C als Objekt in das HTML-Feld zu übertragen, und aufgrund der Tatsache, dass der IE über COM mit 1C verbunden war, wurde das Formular selbst in ein Objekt umgewandelt, das der IE verstand, und es war möglich, Exportfunktionen der Form 1C direkt aus JS-Code aufzurufen . Jetzt ist es unmöglich.

Wir haben die Tiny API-Dokumentation untersucht und ein Konstrukt zum Abfangen von Ereignishandlern und eine geeignete Kombination von Ereignissen gefunden, die das HTML-Feld des Dokuments aktivieren sollen

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

Sie müssen diesen Code an der Stelle ablegen, an der Tiny bereits initialisiert wurde. Ich habe dies im Onload- Handler des Fensterobjekts gemacht . Aber Sie können es schöner machen und den Code beim Initialisieren von Tiny in den Parameter einfügen:

 init_instance_callback 

Jetzt sollte alles in Ordnung sein. Und das Formular sollte funktionieren, wie es sollte ...

Es wurde viel besser, das HTML-Feld begann wirklich aktiviert zu werden, aber nicht immer, aus irgendeinem Grund verursachten einige Klicks nicht, dass der Fokus auf das Feld verschoben wurde:

Bild

Dieser Datensatz zeigt, dass, wenn Sie auf die Zeile klicken, in der der Cursor blinkt, der Fokus des Felds wie gewünscht funktioniert. Wenn Sie jedoch unten klicken, wird das Feld nicht aktiviert.

Es war ein ärgerliches Artefakt, und Versuche zu verstehen, was geschah, gaben keine Lösung. Ich habe Warnungen an den Handler ausgegeben, und es wurden Warnungen angezeigt, aber 1C hat nicht auf das Ereignis reagiert

Bild

Plötzlich kam mir die Idee: Was passiert, wenn 1C es nicht schafft, das Ereignis im Feld zu verarbeiten? Was passiert, wenn Sie die Ausführung des JS-Skripts etwas verlangsamen und sehen, was passiert? Die Pausenfunktion in JS wurde schnell implementiert, indem Versprechen und asynchrone Wartezeiten verwendet wurden. Wie Sie in JS sehen können, existiert es auch standardmäßig nicht und es gibt nichts, Leute leben).

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

Hier stelle ich die Verzögerung auf eine Millisekunde ein, bevor ich auf den Button klicke. Und voila, es hat funktioniert. 1C fing an, das Klicken eines Knopfes rechtzeitig zu verarbeiten.

Bild

4. Wir beenden den Austausch


Da zum Speichern der neuen Beschreibung im HTML-Format dem Verzeichnis ein neues Attribut hinzugefügt wurde, müssen wir beim Entladen den Wert des typischen Felds ersetzen. Fügen Sie dazu im Modul ExchangeSiteRemoveable der Erweiterung die Funktion GetTexts of RequestsCatalog hinzu und schreiben Sie dort:

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

Das ist alles. Wir starten den Austausch und alles funktioniert, es bleiben nur noch Änderungen an der Site, falls erforderlich, damit die Produktbeschreibung als Layout und nicht als String wahrgenommen wird.

Zusammenfassung


In diesem Beispiel habe ich die Interaktion von JS WebKit und 1C ausprobiert, den Rechen gesammelt und eine Lösung gefunden.

Um dieses Problem zu lösen, war es vielleicht einfacher, den HTML-Text aus einem formatierten Dokument zu analysieren und zu löschen, aber es wäre nicht so interessant und könnte Probleme mit einigen komplexen Formatierungsoptionen verursachen.

Danke fürs Lesen.

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


All Articles