Skip to topic | Skip to bottom
Home
You are here: TWiki > Apex Web > DevelopmentCategory > FCKeditorIntegrationExample r4 - 11 Oct 2006 - 09:09 - MaximDemenko


Start of topic | Skip to actions

FCKeditor integration

The basic integration of FCKeditor is shown in this OTN Thread This example will only show, how to integrate into ApEx the FileBrowser and ImageUploader functionality of FCKeditor. The API to this plugins is shown in detail in the FCKeditor WiKi . Here some general considerations: To save and browse uploaded images FCKeditor assumes to have access to the filesystem of http server. As ApEx is the database driven application, i'll use instead the filesystem within the database, which is served by Oracle XML DB. On this way the images ( or other static files ) can be easily accessed by means of database and the backup of these files should not be the concern. It means, however, http access to these files will be provided through XML DB http listener, which is not always enabled. In case of ApEx delivered with the Oracle XE, it is however default configuration, so i'll describe the steps required to get it working with XE edition and at the end of article add some ideas, how can this setup be adjusted for regular ApEx ( i.e. with standalone mod_plsql).

The FCKeditor package itself should be copied per webdav/ftp into XMLDB filesystem as well. Before doing this , some files should be edited however, so archive should be extracted locally. Original lines are commented following by changed lines.

./FCKeditor/fckconfig.js

FCKConfig.LinkBrowser = true ;
//FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=connectors/' +
//            _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=/apex/connector';
FCKConfig.LinkBrowserWindowWidth  = FCKConfig.ScreenWidth * 0.7 ;   // 70%
FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ;  // 70%

FCKConfig.ImageBrowser = true ;
//FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/' +
//           _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?p_Type=Image&Connector=/apex/connector';
FCKConfig.ImageBrowserWindowWidth  = FCKConfig.ScreenWidth * 0.7 ;  // 70% ;
FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ;

FCKConfig.FlashBrowser = true ;
//FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/' +
//            _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?p_Type=Flash&Connector=/apex/connector';
FCKConfig.FlashBrowserWindowWidth  = FCKConfig.ScreenWidth * 0.7 ;  //70% ;
FCKConfig.FlashBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; //70% ;

./FCKeditor/editor/filemanager/browser/default/frmupload.html - here should be changed javascript ...

function SetCurrentFolder( resourceType, folderPath )
{
   var sUrl = oConnector.ConnectorUrl + 'Command=FileUpload' ;
   sUrl += '&Type=' + resourceType ;
   sUrl += '&CurrentFolder=' + escape( folderPath ) ;
   document.getElementById('frmUpload').action = sUrl ;
        // Following 3 lines are new
   document.getElementById('Command').value = 'FileUpload' ;
   document.getElementById('p_Type').value = 'resourceType' ;
   document.getElementById('CurrentFolder').value = escape( folderPath ) ;
}
./FCKeditor/editor/filemanager/browser/default/frmupload.html - ... and html
   <td width="100%"><input id="NewFile" name="NewFile" style="WIDTH: 100%" type="file"></td>
   <td nowrap="nowrap">&nbsp;<input id="btnUpload" type="submit" value="Upload"></td>
   <!-- Following three lines are new -->
   <td><input id="Command" name="Command" type="hidden" value=""></td>
   <td><input id="p_Type" name="p_Type" type="hidden" value=""></td>
   <td><input id="CurrentFolder" name="CurrentFolder" type="hidden" value=""></td>
./FCKeditor/editor/filemanager/browser/default/browser.html
oConnector.SendCommand = function( command, params, callBackFunction )
{
   var sUrl = this.ConnectorUrl + 'Command=' + command ;
   // The following line was original, but, unforutnately, "Type" can't be a parameter name, while a reserved word
   //sUrl += '&Type=' + this.ResourceType ;
   // The following line replaces the original
   sUrl += '&p_Type=' + this.ResourceType ;
   sUrl += '&CurrentFolder=' + escape( this.CurrentFolder ) ;

   if ( params ) sUrl += '&' + params ;

   var oXML = new FCKXml() ;

   if ( callBackFunction )
      oXML.LoadUrl( sUrl, callBackFunction ) ;   // Asynchronous load.
   else
      return oXML.LoadUrl( sUrl ) ;
}

After these changes the whole FCKeditor folder should be copied to your Oracle XE (as mentioned before, preferrably over webdav ), for example into http://localhost:8080/i/FCKeditor Finally, the connector itself - a pl sql stored procedure

CREATE OR REPLACE PROCEDURE Connector
(
  Command VARCHAR2 DEFAULT NULL,
  p_Type VARCHAR2 DEFAULT 'File',
  Currentfolder VARCHAR2 DEFAULT NULL,
  Serverpath VARCHAR2 DEFAULT '/public',
  Newfoldername VARCHAR2 DEFAULT NULL,
  Newfile VARCHAR2 DEFAULT NULL
) IS
  l_Currentfolder VARCHAR2(1000) := Serverpath || Currentfolder;
  l_Response_Xml  Xmltype;
  l_Child_Xml     Xmltype;
  l_Result        BOOLEAN;
  l_Blob_Content  BLOB;
  l_File_Name     VARCHAR2(100);
  l_Dot           PLS_INTEGER;
  l_Basename      VARCHAR2(100);
  l_Extension     VARCHAR2(100);
  l_Counter       PLS_INTEGER := 1;
  l_Message       VARCHAR2(200);

BEGIN
  IF Command != 'FileUpload' THEN
    SELECT Xmlelement("Connector",
                      Xmlattributes(Command AS "command",
                                    'File' AS "resourceType"))
    INTO l_Response_Xml
    FROM Dual;
  
    SELECT Xmlelement("CurrentFolder",
                      Xmlattributes(Currentfolder AS "path",
                                    l_Currentfolder AS "url"))
    INTO l_Child_Xml
    FROM Dual;
    SELECT Appendchildxml(l_Response_Xml, 'Connector', l_Child_Xml)
    INTO l_Response_Xml
    FROM Dual;
  
    IF Command = 'GetFolders' THEN
      SELECT Xmlelement("Folders",
                        Xmlagg(Xmlelement("Folder",
                                          Xmlattributes(Path(1) AS "name"))))
      INTO l_Child_Xml
      FROM Resource_View
      WHERE Under_Path(Res, 1, l_Currentfolder, 1) = 1
            AND Existsnode(Res, '/Resource[@Container="true"]') = 1;
    
    ELSIF Command = 'GetFoldersAndFiles' THEN
      SELECT Xmlelement("Folders",
                        Xmlagg(Xmlelement("Folder",
                                          Xmlattributes(Path(1) AS "name"))))
      INTO l_Child_Xml
      FROM Resource_View
      WHERE Under_Path(Res, 1, l_Currentfolder, 1) = 1
            AND Existsnode(Res, '/Resource[@Container="true"]') = 1;
    
      SELECT Appendchildxml(l_Response_Xml, 'Connector', l_Child_Xml)
      INTO l_Response_Xml
      FROM Dual;
      -- The size calculation for XML DB Resources can be looked up in this thread on OTN
      -- http://forums.oracle.com/forums/thread.jspa?threadID=417316&tstart=0
      SELECT Xmlelement("Files",
                        Xmlagg(Xmlelement("File",
                                          Xmlattributes(File_Name AS "name",
                                                        File_Size AS "size"))))
      INTO l_Child_Xml
      FROM (SELECT Path(1) File_Name,
                   round(Dbms_Lob.Getlength(extractValue(r.res,'/Resource/XMLLob')) / 1024 ) File_Size
            FROM Resource_View r
            WHERE Under_Path(Res, 1, l_Currentfolder, 1) = 1
                  AND Existsnode(Res, '/Resource[@Container="false"]') = 1);
    ELSIF Command = 'CreateFolder' THEN
      IF Dbms_Xdb.Existsresource(l_Currentfolder || Newfoldername) THEN
        l_Message := '101';
      ELSE
        l_Result  := Dbms_Xdb.Createfolder(l_Currentfolder || Newfoldername);
        l_Message := '0';
      END IF;
    
      SELECT Xmlelement("Error", Xmlattributes(l_Message AS "number"))
      INTO l_Child_Xml
      FROM Dual;
    
    END IF;
    SELECT Appendchildxml(l_Response_Xml, 'Connector', l_Child_Xml)
    INTO l_Response_Xml
    FROM Dual;
    SELECT Xmlroot(l_Response_Xml, Version '1.0', Standalone Yes)
    INTO l_Response_Xml
    FROM Dual;
  
    Owa_Util.Mime_Header('text/xml', TRUE, 'ISO-8859-1');
    Htp.p(l_Response_Xml.Getstringval());
  ELSIF Command = 'FileUpload' THEN
    SELECT Filename, Blob_Content
    INTO l_File_Name, l_Blob_Content
    FROM Htmldb_Application_Files
    WHERE NAME = Newfile;
  
    IF Dbms_Xdb.Existsresource(l_Currentfolder || l_File_Name) THEN
      l_Dot      := Instr(l_File_Name, '.', -1);
      l_Basename := Substr(l_File_Name, 1, l_Dot - 1);
      IF l_Dot > 0 THEN
        l_Extension := Substr(l_File_Name, l_Dot + 1);
      END IF;
      WHILE TRUE LOOP
        l_File_Name := l_Basename || '(' || l_Counter || ').' ||
                       l_Extension;
        IF NOT Dbms_Xdb.Existsresource(l_Currentfolder || l_File_Name) THEN
          l_Result  := Dbms_Xdb.Createresource(l_Currentfolder ||
                                               l_File_Name,
                                               l_Blob_Content);
          l_Message := '201,"' || l_File_Name || '"';
          EXIT;
        ELSE
          l_Counter := l_Counter + 1;
        END IF;
      END LOOP;
    ELSE
      l_Result  := Dbms_Xdb.Createresource(l_Currentfolder || l_File_Name,
                                           l_Blob_Content);
      l_Message := '0';
    END IF;
    -- optionally
    -- DELETE FROM Htmldb_Application_Files
    -- WHERE NAME = Newfile;
  
    Htp.p('<script type="text/javascript">');
    Htp.p('window.parent.frames[''frmUpload''].OnUploadCompleted(' ||
          l_Message || ') ;');
    Htp.p('</script>');
  END IF;
END;

After procedure is created ( can be your application schema, for example HR ), a public synonym should be created and grant to execute should be made.

create public synonym connector for connector;
grant execute on connector to anonymous;
In the Oracle XE ApEx version there is a little bit more restriction for execution of stored procedures, so to allow it to be executed FLOWS_020100.WWV_FLOW_EPG_INCLUDE_MOD_LOCAL should be modified accordingly.

To make this setup working with regular Application Express installation:

  • the url in the fckconfig.js should look like /pls/htmldb/connector instead of /apex/connector
  • the XML DB listener should be enabled
BEGIN
DBMS_XDB.SETHTTPPORT(7778);
END;
/
  • ./FCKeditor/editor/filemanager/browser/default/frmresourceslist.html should be modified
function OpenFile( fileUrl )
{
   // URL to inserted image refer to another web server, so should be given as absolute path
   // window.top.opener.SetUrl( fileUrl ) ;
   window.top.opener.SetUrl('http://myhost:7778' + fileUrl ) ;
   window.top.close() ;
   window.top.opener.focus() ;
}
  • optionally, XML DB acl's can be modified, to allow access to resources without providing password
If XML DB for some reasons should not be used, then it is possible to store uploaded images in the custom document table and emulate the filesystem with additional selfreferencing path table , so, file hierarchy can be simply faked with a connect by query - however i personally still prefer XML DB solution - it provides a really great functionality, is included in the database, so why don't use it ? Security aspects are not covered by this example, so it might be a good idea, to modify this setup to cover your requirements. There is also another rich editor - TinyMCE , it hasn't however own free filemanager plugin. But some people have adopted the FCKeditor's plugin for this editor - tinyfck . So, with minor modifications the setup above can be also used here.

-- MaximDemenko - 12 Aug 2006

Comments

Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r4 < r3 < r2 < r1 | More topic actions
This site is powered by the TWiki collaboration platformCopyright © 1999-2014 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback