Logo Oracle Deutschland   Application Express Community
Der Rich Text Editor in Application Express: Tipps und Tricks
Erscheinungsmonat APEX-Version Datenbankversion Cloud oder on Premise
Dezember 2017 ab 5.1 ab 11.2 beides

Das APEX Element Rich Text Editor erlaubt es, im Gegensatz zu einem normalen Textbereich, formatierten Text zu bearbeiten. Der Text wird dann als HTML-Code an Application Express gesendet und typischerweise auch als solcher in Tabellen abgelegt.

Der Rich Text Editor in Application Express

Der Rich Text Editor in Application Express

Das technische Fundament des Rich Text Editors ist die Javascript Bibliothek CKEditor. Zwar sind die im Page Designer angebotenen Konfigurationsmöglichkeiten recht überschaubar ...

Rich Text Editor im Page Designer

Rich Text Editor im Page Designer

... doch bietet der CKEditor eine umfangreiche API zur Konfiguration an - und diese lässt sich ab Application Express 5.1 sehr leicht nutzen.

Rich Text Editor individuell anpassen

Navigierem Sie dazu, im Page Designer, zu Ihrem Rich Text Editor Element und dort zum Abschnitt Advanced. Das Attribute Initialization Javascript Code ist der Einstieg in die Konfigurationsmöglichkeiten des CKEditor. Typischerweise wird dort eine Funktion wie folgt hinterlegt.

function ( configObject ) {
    configObject.{attribute-name-1} = {attribute-value-1};
    configObject.{attribute-name-2} = {attribute-value-2};
    :
    return configObject;
}

Application Express ruft diese Funktion kurz vor der Initialisierung des Editors auf und übergibt das Standard-Konfigurations-Objekt. Dieses können Sie nun in Ihrem Javascript-Code verändern und an Application Express zurückgeben. Der CKEditor wird dann mit der von Ihnen veränderten Konfiguration initialisiert. Einen Überblick über die Möglichkeiten finden Sie in der API-Dokumentation des CKEditor.

Machen Sie ein paar erste Tests: Die folgende Javascript-Funktion setzt die Grundfarbe für den Editor auf eine Art Grün, und die Möglichkeit, die Größe des Editors zu verändern wird abgeschaltet. Danach starten Sie die Seite, um sich das Ergebnis anzusehen.

function ( configObject ) {
    configObject.uiColor        = "#AADC6E";
    configObject.resize_enabled = false;

    return configObject;
}
Rich Text Editor mit eigener Konfiguration

Rich Text Editor mit eigener Konfiguration

CKEditor bietet sehr viele Varianten an, wie das HTML generiert werden soll. So führt die Return-Taste standardmäßig dazu, dass mit einem <p> Tag ein neuer Absatz produziert wird.

Standardmäßig führt ein Zeilenumbruch ... ... zu einem neuen Absatz.

Standardmäßig führt ein Zeilenumbruch zu einem neuen Absatz.

Das kann geändert werden - es soll ein einfacher Zeilenumbruch mit dem Tag <br> erzeugt werden.

function ( configObject ) {
    configObject.enterMode      = 2;
    configObject.uiColor        = "#AADC6E";
    configObject.resize_enabled = false;

    return configObject;
}
Nun führt ein Zeilenumbruch ... ... zu einem einfachen Zeilenumbruch.

Nun führt ein Zeilenumbruch ... zu einem einfachen Zeilenumbruch.

Wem die von Application Express angebotenen Varianten der Toolbar nicht gefallen, kann sich eine eigene zusammenstellen.

function ( configObject ) {
    configObject.enterMode      = 2;
    configObject.uiColor        = "#AADC6E";
    configObject.resize_enabled = false;
    configObject.toolbar        = [
            ['Link','Unlink','Anchor'],
            ['Image','Table','HorizontalRule','Smiley','SpecialChar'],
            '/',
            ['Bold','Italic','Underline','Strike','-','Subscript','Superscript','-', 'RemoveFormat'],
            ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote']
        ];

    return configObject;
}
Rich Text Editor mit eigens zusammengestellter Toolbar

Rich Text Editor mit eigens zusammengestellter Toolbar

Die API-Dokumentation des CKEditor bietet noch viele weitere Einstellungsmöglichkeiten an. Am besten ist es sicherlich, sich dafür einmal etwas Zeit zu nehmen - als Ergebnis bekommt man einen Rich Text Editor nach Maß - in der APEX-Anwendung.

Bilder-Upload für den Rich Text Editor

Mitunter sollen Bilder in den Rich Text aufgenommen werden. Dafür bietet der Editor auch eine Funktion an. Nimmt man die Toolbar Full - oder nimmt man 'Image' in eine eigene Toolbar-Konfiguration auf, so bekommt die Toolbar eine Option, mit der Bilder in den Text eingebettet werden können.

Bilder in den Text einbetten

Bilder in den Text einbetten

Allerdings erwartet dieser Dialog das Eingeben einer URL - das ist erst mal nachvollziehbar, denn der CKEditor generiert HTML; in einem HTML-Dokument werden Bilder mit einem <img> Tag eingebunden, dessen "href"-Attribut die URL zum Bild enthält. Für den Endanwender ist das aber oft unbefriedigend. Man möchte das Bild eigentlich hochladen; und die URL soll automatisch eingetragen werden.

Vorab eine wichtige Voraussetzung: Teil dieser Funktionalität wird ein REST Service sein, es braucht also ORDS (Oracle REST Data Services) als APEX-Webserver. Mit dem mod_plsql oder dem PL/SQL Embedded Gateway wird dieser Teil des Tipps nicht funktionieren.

Für eine solche Image Upload Funktionalität muss etwas getan werden; Application Express kann das nicht aus dem Stand bereitstellen. Die erste und wichtigste Frage ist, wo die Bilder gespeichert werden sollen - in einer APEX-Anwendung dürfte das eine Tabelle sein. Als erstes erzeugen wir also eine Tabelle zur Ablage der Bilder.

create table tab_editor_images(
    id            number primary key,
    filename      varchar2(255),
    image_comment varchar2(4000),
    mimetype      varchar2(255),
    image         blob,
    uploaded_at   date,
    uploaded_by   varchar2(255) );

create sequence seq_editor_images;

create or replace trigger tr_pk_editor_images
before insert on tab_editor_images
for each row
begin
    :new.id          := seq_editor_images.nextval;
    :new.uploaded_at := sysdate;
    :new.uploaded_by := coalesce( v( 'APP_USER' ), sys_context( 'userenv', 'current_user' ) );
end;
/

Dann braucht es eine Webseite zum Hochladen eines neuen oder zur Auswahl eines bestehenden Bildes. Das machen wir mit einer einzigen APEX-Seite. Erzeugen Sie also eine neue Seite. Fügen Sie dieser Seite einen Classic Report mit folgender SQL-Abfrage hinzu. Konfigurieren Sie das Aussehen der Spalten danach nach Wunsch.

select id,
       filename,
       image_comment,
       dbms_lob.getlength( image ) as image
  from tab_editor_images

Fügen Sie dann ober- oder unterhalb des Berichts eine neue Region vom Typ Static Content hinzu. Platzieren Sie darauf ein Element vom Typ File Browse (PX_IMAGE) für den Bild-Upload und eine Textarea (PX_COMMENT) für den (optionalen) Kommentar. Außerdem braucht es ein Element vom Typ Hidden für den Primärschlüssel (PX_ID). Konfigurieren Sie das File Browse Element im Bereich Settings wie folgt:

  • Storage Type: BLOB column specified in Item Source attribute
  • MIME Type Column: MIMETYPE
  • Filename Type Column: FILENAME
  • BLOB Last Updated Column: UPLOADED_AT
  • Display Download Link: No
  • File Types: image/*

Im Bereich Source stellen Sie den Type auf Database Column und geben Sie IMAGE als dieselbe an.

Konfiguration des File Upload Buttons im Page Designer

Konfiguration des File Upload Buttons im Page Designer

Fügen Sie der Seite dann einen Button hinzu. Geben Sie dem Button ein Label nach Wunsch, achten Sie aber darauf, dass der (technische) Button Name auf CREATE gesetzt wird. Die Button Action bleibt bei Submit Page.

Bevor Sie die Seite starten, navigieren Sie noch zu den Seiteneinstellungen und dort zum Page Template . Nehmen Sie eines ohne Navigationsmenü - am besten "Minimal (No Navigation)". Danach sollte Ihre Seite wie folgt aussehen.

Das Layout der Image-Upload-Seite ist fertig

Das Layout der Image-Upload-Seite ist fertig

Noch können Sie aber nichts hochladen - es fehlt noch ein Seitenprozess, der On Page Submit ausgeführt werden soll. Das erledigen Sie wieder mit dem Page Designer. Nehmen Sie einen vom Typ Automatic Row Processing (DML).

  • Table Name: TAB_EDITOR_IMAGES
  • Primary Key Column: ID
  • Primary Key Item: P2_ID
  • Supported Operations: Insert

Starten Sie Ihre Seite dann und laden Sie ein Bild hoch. Danach sollte das Ergebnis wie folgt aussehen.

Der Bild-Upload funktioniert bereits

Der Bild-Upload funktioniert bereits

Als nächstes braucht es eine Download-Funktion für das Bild. Und hier müssen wir etwas aufpassen: Die Bilder werden in HTML-Text eingebettet werden - dieser HTML-Text wird im Rich Text Editor erstellt und dann in einer Tabelle abgelegt. APEX-Session IDs oder APEX-Elemente sollten in diesen Image URLs also eher nicht enthalten sein. Am besten wären typische Webserver-URLs, die einfach nur einen Pfad zum Bild beinhalten.

Dies kann sehr gut mit einem REST Service umgesetzt werden. Navigieren Sie zum SQL Workshop und dort zum Bereich RESTful Services.

REST Services im SQL Workshop

REST Services im SQL Workshop

Klicke Sie auf den Button Create, um einen neuen REST Service zu erstellen. Im Bereich RESTful Service Module machen Sie folgende Angaben.

  • Name: Image Download Service
  • URI Prefix: image/ (achten Sie auf den trailing slash)

Im Bereich Resource Template tragen Sie download/{id} als URI Template ein. Im Bereich Resource Handler wählen Sie schließlich GET als Method und Media Resource als Type aus. Hinterlegen Sie dann die folgende SQL-Abfrage.

select mimetype, image
  from tab_editor_images
 where id = :id

Speichern Sie die Angaben dann mit einem Klick auf den Button Create Module. Danach klicken Sie im Baum links nochmals auf den soeben erzeugen Eintrag für GET und stellen das Attribut Requires Secure Access auf No, wenn Ihr Application Express kein HTTPS verwendet.

Danach können Sie den REST Service testen. Die URL folgt typischerweise dem folgenden Schema:

https://{apex-server}/ords/{workspace-name}/utilities/getImage/{image-id}

Wenn Sie eine gültige ID verwenden, bekommen Sie das bereits hochgeladene Bild zurück. Wenn ein Bild mit der in der URL angegebenen ID nicht existiert, gibt es einen HTTP-404 ("Not found").

Damit sind die Vorbereitungen abgeschlossen. Als nächstes werden die Komponenten mit dem CKEditor integriert. Navigieren Sie zur Seite mit dem Rich Text Editor und dort zum Attribut Javascript Initialization Code. Setzen Sie dann das Attribut filebrowserBrowseUrl so, dass es auf die APEX-Seite zur Auswahl oder zum Upload eines Bildes zeigt.

function ( configObject ) {
    configObject.filebrowserBrowseUrl = 
        "f?p=" + $v( "pFlowId" ) + ":2:" + $v( "pInstance" ) + "::" + $v( "pdebug" );
    configObject.filebrowserWindowWidth = 640;
}

Starten Sie die Seite dann nochmals, und klicken Sie im Rich Text Editor in der Toolbar auf das Icon für ein Bild. Der Dialog enthält nun einen zusätzlichen Button Browse Server. Klickt man darauf, so öffnet sich unsere APEX-Seite, in der wir nun Bilder hochladen können.

 "Browse Server" im Image Dialog des CKEditor verzweigt auf eine APEX-Seite

"Browse Server" im Image Dialog des CKEditor verzweigt auf eine APEX-Seite

Es fehlt noch die Möglichkeit, ein Bild auszuwählen und diese Auswahl zum CKEditor zurückzugeben. Die API Dokumentation des CKEditor beschreibt, wie das geht: Navigieren Sie nochmals zur APEX-Seite für den Bild-Upload und hinterlegen Sie den folgenden Javascript Code in den Seitenattributen und Function and Global Variable Declaration. Passen Sie die URL zum vorher erzeugen REST Service an Ihre Umgebung an.

function returnFileUrl( pId ) {
    var funcNum = getUrlParam( 'CKEditorFuncNum' ),
        // Achtung: hier anpassen!
        fileUrl = "{workspace-name}/utilities/getImage/" + pId;

    function getUrlParam( paramName ) {
        var reParam = new RegExp( '(?:[\?&]|&)' + paramName + '=([^&]+)', 'i' );
        var match = window.location.search.match( reParam );

        return ( match && match.length > 1 ) ? match[1] : null;
    }

    
    window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl );
    window.close();
}

Zum Abschluss navigieren Sie zum Bericht, der die vorhandenen Bilder anzeigt, und dort zur Spalte FILENAME. Machen Sie die Spalte zu einem Link und hinterlegen Sie folgendes Link Target vom Typ URL.

javascript:returnFileUrl(#ID#)

Und damit ist es fertig. Öffnen Sie nun in Ihrem Rich Text Editor den Image Dialog, klicken Sie Browse Server; laden Sie eine Datei hoch und klicken Sie den Dateinamen der Datei im APEX-Bericht an. Sie werden zum Image-Dialog zurückgeleitet und die URL zum Bild wird bereits eingetragen. Sie können dann noch die Bildgröße anpassen und auf OK klicken. Danach wird das hochgeladene Bild in Ihrem Editor-Text erscheinen.

Rich Text Editor mit Image-Upload Funktion Rich Text Editor mit Image-Upload Funktion
Rich Text Editor mit Image-Upload Funktion Rich Text Editor mit Image-Upload Funktion

Rich Text Editor mit Image-Upload Funktion

Responsive Rich Text Editor

Zum Abschluss dieses Artikels gibt es noch einen Tipp, wie man den Rich Text Editor dazu bringt, sich automatisch an die Größe des Browser-Fensters bzw. der Region, in der er sich befindet, anzupassen. Standardmäßig legt man die Größe des Rich Text Editors in Spalten und Zeilen fest, ganz ähnlich zu einem Textbereich. Unten rechts befindet sich dann ein Handle, mit dem der Endbenutzer die Größe manuell anpassen kann.

Der Endbenutzer kann den Rich Text Editor vergrößern und verkleinern

Der Endbenutzer kann den Rich Text Editor vergrößern und verkleinern"

In einem sehr kleinen Browserfenster kann es jedoch sein, dass man an den Handle gar nicht mehr herankommt - der Editor ist eben nicht "responsive" ...

Der Rich Text Editor ist aus dem Stand nicht responsive

Der Rich Text Editor ist aus dem Stand nicht responsive

Mit etwas Javascript kann man sich hier aber leicht helfen; allerdings funktioniert dieser Tipp nur mit dem Universal Theme. Wiederum geht es zu den Einstellungen des Rich Text Editor und dort zum Javascript Initialization Code. Dort fügen Sie die folgenden Einstellungen hinzu (tragen Sie anstelle von "{PX_item-name}" den Item-Namen des Rich Text Editors ein).

function ( configObject ) {
    :

    configObject.width      = $( "#{PX_item-name}" ).closest(".t-Form-inputContainer").width() - 5;
    configObject.height     = 300;  // Specify your desired item height, in pixels
    configObject.resize_dir = 'vertical'

    : 
}

Wenn Sie die Seite nun neu starten, dann passt sich der Rich Text Editor beim Laden der Seite bereits an die Regionsbreite an. Beim Vergrößern oder Verkleinern des Browser-Fensters geschieht noch nichts. Da es nun keinen Sinn mehr macht, die horizontale Breite manuell anzupassen, funktioniert der "Handle" unten rechts nun nur noch vertikal.

Erzeugen Sie dann eine neue Dynamic Action, diese soll auf den Event Resize reagieren. Wählen Sie Execute Javascript Code als Action aus und hinterlegen Sie folgenden Code (achten Sie wieder darauf, den Namen des Rich Text Editor Elements anzupassen).

CKEDITOR.instances.{PX_item-name}.resize( $("#{PX_item-name}" ).closest( ".t-Form-inputContainer" ).width() - 5, 300 );

Starten Sie die Seite nun nochmals. Nun sollte sich der Rich Text Editor beim Vergrößern oder Verkleinern des Browserfensters anpassen.

Der Rich Text Editor ist "responsive" - 1
Der Rich Text Editor ist "responsive" - 2

Der Rich Text Editor ist "responsive"

Der CKEditor, auf dem der Application Express Rich Text Editor basiert, kann nach Belieben angepasst werden; es ist eine große Fülle an Einstellungsmöglichkeiten vorhanden. Kombiniert man dies geschickt mit APEX-Anwendungsseiten, Dynamic Actions oder REST Services, so sind den Möglichkeiten keine Grenzen gesetzt.

Zurück zur Community-Seite