Hi John,
Thanks so much for taking the time to explain, it was a big help! I
finally got it working. I'm pretty excited to have a good rich text
editor to use with Ubiquity XForms! Now if I can just get my
submissions to work I will have a pretty cool little xrx cms using
eXist and Ubiquity.
Here is the final working code for an XForms textarea with the
CKEditor:
xquery version "1.0";
(: Textarea Element Edit Template :)
declare namespace xhtml = "
http://www.w3.org/1999/xhtml";
declare namespace atom = "
http://www.w3.org/2005/Atom";
declare namespace xforms = "
http://www.w3.org/2002/xforms";
declare namespace xf = "
http://www.w3.org/2002/xforms";
declare namespace ev = "
http://www.w3.org/2001/xml-events";
declare namespace cms = "
http://www.mysite.org/cms";
(:
$level contains the outline level in the form of 1.1, 1.2, 1.1.1,
1.1.2 etc.
and is used as a unique identifier for the textarea element in the
javascript below. This identifier
will differentiate this textarea and it's associated javascript from
any other textarea elements on the page.
As an alternative random() or some other function could be used to
create a unique identifier
:)
let $translatedLevel := translate($level, '.', '')
return
<div>
<xf:textarea ref="{$ref}" incremental="true" id="{local-name
($data)}-{$translatedLevel}" class="editor">
<xf:label>{$level}. {content:getLabel(name($data),'',
$contentElementSchema)}</xf:label>
</xf:textarea>
<!--(: This output is here only to demonstrate that the xforms
instance element is being properly updated with the data from the
editor :)-->
<xf:output ref="{$ref}">
<xf:label>Instance Data</xf:label>
</xf:output>
<!--(:
This script inserts a wrapper div and an editor div inside of the
xf:textarea,
replaces the editor div with a CKEditor instance, updates the
CKEditor instance with
data from the xforms instance element and then waits for some
activity in the editor.
Upon specified actions in the editor, a function is called to
update the xforms instance
element wit hthe content of the editor and rebuild the xforms
model.
NOTE: getElementsByTagName is used at first to get data from the
xforms instance element
because when the script is first run during page load, the
getInstanceDocument method
isn't yet available because the Ubiquity xforms script is still
building the model.
When the update function is called, getInstanceDocument is
available and can be used to access
and update the instance element. Also note that element name used
in the evalXPah expression
has to be in lower case for some reason even though the actual
element name is in UpperCamel case.
:)-->
<script type="text/javascript">
var xfTextarea = document.getElementById( '{local-name($data)}-
{$translatedLevel}' );
var editorWrapper = document.createElement('div');
var editorWrapperStyle = editorWrapper.style.clear = 'both';
var editorDiv = document.createElement('div');
var editorDivID = editorDiv.setAttribute( 'id', '{local-name
($data)}-{$translatedLevel}-editor' );
editorWrapper.appendChild(editorDiv);
xfTextarea.appendChild(editorWrapper);
var editor = CKEDITOR.replace( '{local-name($data)}-
{$translatedLevel}-editor' );
var instance = document.getElementById
("contentObjectEntryEditInstance");
var content = instance.getElementsByTagName("atom:content")[0];
var element = content.getElementsByTagName( '{name($data)}' )
[0];
if(element.childNodes[0]){{editor.setData( element.childNodes
[0].nodeValue )}};
editor.on("instanceReady", function()
{{
this.document.on("keyup", update{concat(local-name($data),
$translatedLevel)});
this.document.on("paste", update{concat(local-name($data),
$translatedLevel)});
this.document.on("mousein", update{concat(local-name($data),
$translatedLevel)});
this.document.on("mouseout", update{concat(local-name($data),
$translatedLevel)});
}});
function update{concat(local-name($data), $translatedLevel)}()
{{
CKEDITOR.tools.setTimeout( function()
{{
var editorData = CKEDITOR.instances['{local-name($data)}-
{$translatedLevel}-editor'].getData();
var model = document.getElementById("mainModel");
var instance = model.getInstanceDocument
("contentObjectEntryEditInstance");
var element = instance.XFormsInstance.evalXPath("//{lower-
case(name($data))}").value[0];
if(element.childNodes[0]){{element.childNodes[0].nodeValue
= editorData;}}
else {{var elementTextNode = document.createTextNode
(editorData); element.appendChild(elementTextNode);}};
model.flagRebuild();
model.deferredUpdate();
}}, 0);
}}
</script>
</div>