Stackoverflow in xbl control that encapsulates another

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Stackoverflow in xbl control that encapsulates another

bwallis42
I'm developing a control that works much like the character counter control. It is a variant on a spell checker where i can just annotate an input, textarea or tinymce editor.

I have a problem with the control. I think I'm pretty much doing the same thing as the character counter control but I get a stackoverflow error (see below) when I open the form builder.  The error seems to be related to the xpath in the <xsl:element>.

I've copied what character counter does like so

                <xsl:element name="{name(/*)}">
                    <xsl:attribute name="id"          select="'field'"/>
                    <xsl:attribute name="ref"         select="'$binding'"/>
                    <xsl:attribute name="incremental" select="'true'"/>
                    <xsl:attribute name="appearance"  select="tokenize(/*/@appearance, '\s+')[. != 'spell-checker']"/>
                </xsl:element>

If I change the xpath from 'name(/*)' to hardcode the element name (say 'xf:input') then the control works correctly, spell checking and all.

My component source is:

<!--
  Copyright (C) 2010 Orbeon, Inc.

  This program is free software; you can redistribute it and/or modify it under the terms of the
  GNU Lesser General Public License as published by the Free Software Foundation; either version
  2.1 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU Lesser General Public License for more details.

  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
  -->
<xbl:xbl xmlns:xh="http://www.w3.org/1999/xhtml"
         xmlns:xf="http://www.w3.org/2002/xforms"
         xmlns:xs="http://www.w3.org/2001/XMLSchema"
         xmlns:ev="http://www.w3.org/2001/xml-events"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
         xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
         xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
         xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
         xmlns:saxon="http://saxon.sf.net/"
         xmlns:xbl="http://www.w3.org/ns/xbl"
         xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         xmlns:oxf="http://www.orbeon.com/oxf/processors"
         xmlns:exf="http://www.exforms.org/exf/1-0" 
         xmlns:im="http://www.infomedix.com.au/cpf/forms">
     
    <xbl:script src="/xbl/im/spell-checker/JavaScriptSpellCheck/include.js" />
    
    <xbl:script src="/xbl/im/spell-checker/spell-checker.js"/>

    <xbl:binding id="im-spell-checker" 
        element="
            im|spell-checker,
            xf|input[appearance ~= spell-checker],
            xf|textarea[appearance ~= spell-checker],
            fr|tinymce[appearance ~= spell-checker]"
        xxbl:mode="binding lhha"
        xxbl:label-for="field"
        xxbl:container="span">
        
        <metadata xmlns="http://orbeon.org/oxf/xml/form-builder">
            <display-name lang="en">Spell Checker</display-name>
            <toolbox show="false"/>
            <icon lang="en">
                <small-icon>/xbl/im/spell-checker/JavaScriptSpellCheck/themes/buttons/spellicon.gif</small-icon>
            </icon>
            <templates>
                <view>
                    <xf:input id="" ref="" appearance="spell-checker" xmlns="">
                        <xf:label ref=""/>
                        <xf:hint ref=""/>
                        <xf:help ref=""/>
                        <xf:alert ref=""/>
                    </xf:input>
                </view>
            </templates>
            
        </metadata>
       
        <xbl:resources>
            <xbl:style src="/xbl/im/spell-checker/spell-checker.css"/>
        </xbl:resources>
        
        <xbl:template xxbl:transform="oxf:xslt">
            <xh:span xsl:version="2.0" >
                <xf:var
                    name="binding"
                    value="xxf:binding('im-spell-checker')"/>

                <xf:var
                    name="current"
                    value="string-length(string($binding))"/>
                    
                <xsl:element name="{name(/*)}">
                    <xsl:attribute name="id"          select="'field'"/>
                    <xsl:attribute name="ref"         select="'$binding'"/>
                    <xsl:attribute name="incremental" select="'true'"/>
                    <xsl:attribute name="appearance"  select="tokenize(/*/@appearance, '\s+')[. != 'spell-checker']"/>
                </xsl:element>
                
                <!-- Trigger that starts spell checking -->
                <xf:trigger class="im-spell-checker-start" ref="xxf:binding('im-spell-checker')">
                    <xf:label>Spell check</xf:label>
                    <xf:action event="xforms-enabled">
                        <xf:action type="javascript">
                            <xf:param name="componentId" value="field"/>
                            <xf:body>
                                console.log('component is initialising');
                                ORBEON.xforms.XBL.instanceForControl(this).DisableBrowserSpellCheck(componentId);
                            </xf:body>
                        </xf:action>
                    </xf:action>
                    
                    <!-- Open spell check dialog -->
                    <xf:action event="DOMActivate">
                        <xf:action type="javascript">
                            <xf:param name="componentId" value="field"/>
                            <xf:body>
                                console.log('component is '+componentId);
                                ORBEON.xforms.XBL.instanceForControl(this).SpellCheckInWindow(componentId);
                            </xf:body>
                        </xf:action>
                    </xf:action>
                </xf:trigger>
            </xh:span>
        </xbl:template>
    </xbl:binding>

</xbl:xbl>

The stack trace I get when trying to open the builder is:

12:02:49,619 [ajp-localhost%2F127.0.0.1-8009-15] ERROR org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/orbeon].[orbeon-main-servlet] - Servlet.service() for servlet orbeon-main-servlet threw exception: java.lang.StackOverflowError
	at org.orbeon.dom.io.SAXContentHandler.startElement(SAXContentHandler.scala:86) [:2016.3.201612230117]
	at org.orbeon.oxf.xml.dom4j.LocationSAXContentHandler.startElement(LocationSAXContentHandler.scala:38) [:2016.3.201612230117]
	at org.orbeon.oxf.xml.SimpleForwardingXMLReceiver.startElement(SimpleForwardingXMLReceiver.java:83) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.transformer.xslt.XSLTTransformer$1$3.startElement(XSLTTransformer.java:376) [:2016.3.201612230117]
	at org.orbeon.saxon.event.ContentHandlerProxy.startContent(ContentHandlerProxy.java:362) [:]
	at org.orbeon.saxon.event.NamespaceReducer.startContent(NamespaceReducer.java:197) [:]
	at org.orbeon.saxon.event.ComplexContentOutputter.startContent(ComplexContentOutputter.java:552) [:]
	at org.orbeon.saxon.event.ComplexContentOutputter.startElement(ComplexContentOutputter.java:174) [:]
	at org.orbeon.saxon.instruct.ElementCreator.processLeavingTail(ElementCreator.java:289) [:]
	at org.orbeon.saxon.instruct.Block.processLeavingTail(Block.java:556) [:]
	at org.orbeon.saxon.instruct.Instruction.process(Instruction.java:93) [:]
	at org.orbeon.saxon.instruct.ElementCreator.processLeavingTail(ElementCreator.java:296) [:]
	at org.orbeon.saxon.instruct.Template.applyLeavingTail(Template.java:203) [:]
	at org.orbeon.saxon.instruct.ApplyTemplates.applyTemplates(ApplyTemplates.java:345) [:]
	at org.orbeon.saxon.Controller.transformDocument(Controller.java:1807) [:]
	at org.orbeon.saxon.TransformerHandlerImpl.endDocument(TransformerHandlerImpl.java:144) [:]
	at org.orbeon.oxf.xml.ForwardingXMLReceiver.endDocument(ForwardingXMLReceiver.java:83) [:2016.3.201612230117]
	at org.orbeon.saxon.event.ContentHandlerProxy.close(ContentHandlerProxy.java:274) [:]
	at org.orbeon.saxon.event.ProxyReceiver.close(ProxyReceiver.java:90) [:]
	at org.orbeon.saxon.event.ComplexContentOutputter.close(ComplexContentOutputter.java:507) [:]
	at org.orbeon.saxon.event.ReceivingContentHandler.endDocument(ReceivingContentHandler.java:219) [:]
	at org.orbeon.dom.io.SAXWriter.endDocument(SAXWriter.scala:153) [:2016.3.201612230117]
	at org.orbeon.dom.io.SAXWriter.writeDocument(SAXWriter.scala:68) [:2016.3.201612230117]
	at org.orbeon.dom.io.SAXWriter.parse(SAXWriter.scala:127) [:2016.3.201612230117]
	at org.orbeon.saxon.event.Sender.sendSAXSource(Sender.java:404) [:]
	at org.orbeon.saxon.event.Sender.send(Sender.java:193) [:]
	at org.orbeon.oxf.xml.IdentityTransformerWithFixup.transform(IdentityTransformerWithFixup.scala:31) [:2016.3.201612230117]
	at org.orbeon.oxf.xml.TransformerWrapper.transform(TransformerUtils.java:714) [:2016.3.201612230117]
	at org.orbeon.oxf.xml.TransformerUtils.sourceToSAX(TransformerUtils.java:530) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.generator.DOMGenerator$1.readImpl(DOMGenerator.java:202) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl$TopLevelOutputFilter.read(ProcessorOutputImpl.java:256) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl.read(ProcessorOutputImpl.java:392) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsSAX(ProcessorImpl.java:262) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor$InternalTopOutput$1.run(PipelineProcessor.java:535) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor.executeParents(PipelineProcessor.java:696) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor.access$400(PipelineProcessor.java:60) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor$InternalTopOutput.readImpl(PipelineProcessor.java:531) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl$TopLevelOutputFilter.read(ProcessorOutputImpl.java:256) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl.read(ProcessorOutputImpl.java:392) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsSAX(ProcessorImpl.java:262) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsSAX(ProcessorImpl.java:266) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.transformer.xslt.XSLTTransformer$1.runTransformer(XSLTTransformer.java:470) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.transformer.xslt.XSLTTransformer$1.readImpl(XSLTTransformer.java:188) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl$TopLevelOutputFilter.read(ProcessorOutputImpl.java:256) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl.read(ProcessorOutputImpl.java:392) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsSAX(ProcessorImpl.java:262) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor$1$1.run(PipelineProcessor.java:93) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor.executeChildren(PipelineProcessor.java:679) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor.access$000(PipelineProcessor.java:60) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.pipeline.PipelineProcessor$1.readImpl(PipelineProcessor.java:91) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl$TopLevelOutputFilter.read(ProcessorOutputImpl.java:256) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.impl.ProcessorOutputImpl.read(ProcessorOutputImpl.java:392) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsSAX(ProcessorImpl.java:262) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readInputAsDOM4J(ProcessorImpl.java:279) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl$2.read(ProcessorImpl.java:309) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl$2.read(ProcessorImpl.java:307) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readCacheInputAsObject(ProcessorImpl.java:363) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.ProcessorImpl.readCacheInputAsDOM4J(ProcessorImpl.java:307) [:2016.3.201612230117]
	at org.orbeon.oxf.processor.DOMSerializer.runGetDocument(DOMSerializer.scala:49) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.Transform$$anonfun$transformBoundElement$1.apply(Transform.scala:87) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.Transform$$anonfun$transformBoundElement$1.apply(Transform.scala:85) [:2016.3.201612230117]
	at org.orbeon.oxf.pipeline.InitUtils$.withPipelineContext(InitUtils.scala:53) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.Transform$.transformBoundElement(Transform.scala:85) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.AbstractBinding$$anonfun$newTransform$1.apply(AbstractBinding.scala:133) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.AbstractBinding$$anonfun$newTransform$1.apply(AbstractBinding.scala:130) [:2016.3.201612230117]
	at scala.Option.map(Option.scala:146) [:]
	at org.orbeon.oxf.xforms.xbl.AbstractBinding.newTransform(AbstractBinding.scala:130) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$org$orbeon$oxf$xforms$xbl$XBLBindings$$generateRawShadowTree$1$$anonfun$apply$5.apply(XBLBindings.scala:319) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$org$orbeon$oxf$xforms$xbl$XBLBindings$$generateRawShadowTree$1$$anonfun$apply$5.apply(XBLBindings.scala:310) [:2016.3.201612230117]
	at org.orbeon.oxf.util.Logging$class.withDebug(Logging.scala:50) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings.withDebug(XBLBindings.scala:42) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$org$orbeon$oxf$xforms$xbl$XBLBindings$$generateRawShadowTree$1.apply(XBLBindings.scala:310) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$org$orbeon$oxf$xforms$xbl$XBLBindings$$generateRawShadowTree$1.apply(XBLBindings.scala:309) [:2016.3.201612230117]
	at scala.Option.map(Option.scala:146) [:]
	at org.orbeon.oxf.xforms.xbl.XBLBindings.org$orbeon$oxf$xforms$xbl$XBLBindings$$generateRawShadowTree(XBLBindings.scala:308) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$processElementIfNeeded$1.apply(XBLBindings.scala:95) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.xbl.XBLBindings$$anonfun$processElementIfNeeded$1.apply(XBLBindings.scala:94) [:2016.3.201612230117]
	at scala.Option.flatMap(Option.scala:171) [:]
	at org.orbeon.oxf.xforms.xbl.XBLBindings.processElementIfNeeded(XBLBindings.scala:94) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.PartAnalysisImpl.build(PartAnalysisImpl.scala:129) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.PartAnalysisImpl$$anonfun$analyze$1$$anonfun$1.apply(PartAnalysisImpl.scala:201) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.PartAnalysisImpl$$anonfun$analyze$1$$anonfun$1.apply(PartAnalysisImpl.scala:201) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2.apply(ChildrenBuilderTrait.scala:70) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2.apply(ChildrenBuilderTrait.scala:69) [:2016.3.201612230117]
	at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:683) [:]
	at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) [:]
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) [:]
	at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:682) [:]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$class.buildChildren$1(ChildrenBuilderTrait.scala:69) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$class.build(ChildrenBuilderTrait.scala:87) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ControlAnalysisFactory$$anonfun$10$$anon$7.build(ControlAnalysisFactory.scala:241) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2$$anonfun$apply$1.applyOrElse(ChildrenBuilderTrait.scala:73) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2$$anonfun$apply$1.applyOrElse(ChildrenBuilderTrait.scala:70) [:2016.3.201612230117]
	at scala.PartialFunction$Lifted.apply(PartialFunction.scala:223) [:]
	at scala.PartialFunction$Lifted.apply(PartialFunction.scala:219) [:]
	at scala.Option.collect(Option.scala:282) [:]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2.apply(ChildrenBuilderTrait.scala:70) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2.apply(ChildrenBuilderTrait.scala:69) [:2016.3.201612230117]
	at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:683) [:]
	at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59) [:]
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48) [:]
	at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:682) [:]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$class.buildChildren$1(ChildrenBuilderTrait.scala:69) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$class.build(ChildrenBuilderTrait.scala:87) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.controls.ComponentControl.build(ComponentControl.scala:7) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2$$anonfun$apply$1.applyOrElse(ChildrenBuilderTrait.scala:73) [:2016.3.201612230117]
	at org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2$$anonfun$apply$1.applyOrElse(ChildrenBuilderTrait.scala:70) [:2016.3.201612230117]
	at scala.PartialFunction$Lifted.apply(PartialFunction.scala:223) [:]
	at scala.PartialFunction$Lifted.apply(PartialFunction.scala:219) [:]
	at scala.Option.collect(Option.scala:282) [:]

and then repeats from org.orbeon.oxf.xforms.analysis.ChildrenBuilderTrait$$anonfun$2.apply(ChildrenBuilderTrait.scala:70) 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
Hi Brian,

Off the top of my head, I can see a potential problem here if you’re using the component as `<im:spell-checker>`, instead of say `<xf:input appearance=“spell-checker”>`, as this code will produce a `<im:spell-checker>` in the output, that will in turn be processed by the XBL engine, and so on. Are you having the problem if using `<xf:input appearance=“spell-checker”>`?

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Thanks for the clue Alex, I found that I had a reference to the old control from within another control in our list of xbl controls. I took that out and now no stack overflow error.

I have added my control to the property oxf.fb.toolbox.group.other.uri.*.* along with my other custom controls and I get a new radio button for the input and textarea controls that lets me select spell-checker appearance. This does add spell-checker to the appearance attribute on the text control but the control is doing nothing. No button appears below the text element. None of the javascript functions are called.

I've attached the current source of the control. Will the trigger and the events contained within work at this position in the code?


<xbl:xbl
    xmlns:xh="http://www.w3.org/1999/xhtml"
    xmlns:xf="http://www.w3.org/2002/xforms"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ev="http://www.w3.org/2001/xml-events"
    xmlns:xi="http://www.w3.org/2001/XInclude"
    xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
    xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
    xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
    xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:xbl="http://www.w3.org/ns/xbl"
    xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:oxf="http://www.orbeon.com/oxf/processors"
    xmlns:exf="http://www.exforms.org/exf/1-0"
    xmlns:im="http://www.infomedix.com.au/cpf/forms">

    <xbl:script src="/xbl/im/spell-checker/JavaScriptSpellCheck/include.js" />
    <xbl:script src="/xbl/im/spell-checker/spell-checker.js" />

    <xbl:binding
        id="im-spell-checker"
        element="
            im|spell-checker,
            xf|input[appearance ~= spell-checker],
            xf|textarea[appearance ~= spell-checker],
            fr|tinymce[appearance ~= spell-checker]"
        xxbl:mode="binding lhha"
        xxbl:label-for="field"
        xxbl:container="span">

        <metadata xmlns="http://orbeon.org/oxf/xml/form-builder">
            <display-name lang="en">Spell Checker</display-name>
            <toolbox show="false" />
            <icon lang="en">
                <small-icon>/xbl/im/spell-checker/JavaScriptSpellCheck/themes/buttons/spellicon.gif</small-icon>
            </icon>
            <templates>
                <view>
                    <xf:input
                        id=""
                        ref=""
                        appearance="spell-checker"
                        xmlns="">
                        <xf:label ref="" />
                        <xf:hint ref="" />
                        <xf:help ref="" />
                        <xf:alert ref="" />
                    </xf:input>
                </view>
            </templates>
        </metadata>

        <xbl:resources>
            <xbl:style src="/xbl/im/spell-checker/spell-checker.css" />
        </xbl:resources>

        <xbl:template xxbl:transform="oxf:xslt">
            <xh:span xsl:version="2.0">
                <xf:var
                    name="binding"
                    value="xxf:binding('im-spell-checker')" />

                <xsl:element name="{name(/*)}">
                    <xsl:attribute
                        name="id"
                        select="'field-control'" />
                    <xsl:attribute
                        name="ref"
                        select="'$binding'" />
                    <xsl:attribute
                        name="incremental"
                        select="'true'" />
                    <xsl:attribute
                        name="appearance"
                        select="tokenize(/*/@appearance, '\s+')[. != 'spell-checker']" />
                </xsl:element>
                
                <!-- Trigger that starts spell checking -->
                <xf:trigger
                    class="im-spell-checker-start"
                    ref="$binding">
                    <xf:label>Spell check</xf:label>
                    
                    <xf:action event="xforms-enabled">
                        <xf:action type="javascript">
                            <xf:param
                                name="componentId"
                                value="'field'" />
                            <xf:body>
                                console.log('component is initialising');
                                ORBEON.xforms.XBL.instanceForControl(this).DisableBrowserSpellCheck(componentId);
                            </xf:body>
                        </xf:action>
                    </xf:action>
                    <!-- Open spell check dialog -->
                    <xf:action event="DOMActivate">
                        <xf:action type="javascript">
                            <xf:param
                                name="componentId"
                                value="'field'" />
                            <xf:body>
                                console.log('component is '+componentId);
                                ORBEON.xforms.XBL.instanceForControl(this).SpellCheckInWindow(componentId);
                            </xf:body>
                        </xf:action>
                    </xf:action>
                </xf:trigger>
            </xh:span>
        </xbl:template>
    </xbl:binding>
</xbl:xbl>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
I'm also curious why the appearance settings are radio buttons, sometimes you might want more than one such as resize and character counter. I can do this from the source editor and it works fine but not from the dialog.

thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
In reply to this post by bwallis42
Hi Brian,

Great, I'm glad removing the reference to `<im:spell-checker>` solve the stack overflow issue.

Regarding the issue with the button not showing below the text, is this only happening in Form Builder, or is it also happen after you publish the form and got to /new? If the input shows, I don't see why the trigger wouldn't show, since they are both bound to `$binding`.

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Happening in both. The control just does nothing. No button is present. Strange that it worked before when
It was included by the other control as long as i didn't use the xpath expression.

It is being seen by orbeon since I have the radio button in the configuration dialogue.

To include this control l just need to include it in the property with my other controls? Is that correct?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
Brian, are you saying that it is as if the XForms engine didn't see you had an XBL control to handle that appearance? I.e. as if you had `appearance="gaga"` instead of `spell-checker`? If that is the case, is the XBL file even read? To see what is going on, you might also want to uncomment the <category> for `org.orbeon.xbl` in your log4j.xml.

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Alessandro Vernet wrote
Brian, are you saying that it is as if the XForms engine didn't see you had an XBL control to handle that appearance? I.e. as if you had `appearance="gaga"` instead of `spell-checker`? If that is the case, is the XBL file even read? To see what is going on, you might also want to uncomment the <category> for `org.orbeon.xbl` in your log4j.xml.
The builder is reading the control file and is using it. If I make the file invalid xml then I get an error when it tries to read it. If I change the templates view in the metadata from xf:input to a xh:textarea and have the control in the toolbox, when I insert it I get either the xf:input or xh:textarea inserted into my form.

So I think the builder is fine with it at design time, it is certainly reading the file and using the template.

So I expect that the appearance="spell-checker" is just not causing the control to be used to add it's behaviour to the annotated input/textarea. It looks like the xsl transformation is not happening on the annotated control and the original is just left there as is.

The logging hasn't really helped me find what is going on yet.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Is there a way I can see the xsl processing and results of processing the xbl control?

I've spent some more time experimenting with this including making a copy of the control with a new name to eliminate any possibility of the old control name being used elsewhere in our code confusing things. It sill looks like the xsl processing of the control just isn't happening.

thanks
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
I just want to check that the only place I need to mention my new control is in the property oxf.fb.toolbox.group.other.uri.cpf.* along with my other controls?

i.e. I have this set in my local properties file

    <property as="xs:string" name="oxf.fb.toolbox.group.other.uri.cpf.*">
        oxf:/xbl/im/dynamic-list/dynamic-list.xbl
        oxf:/xbl/im/codeset-select1/codeset-select1.xbl
        oxf:/xbl/im/codeset-index-select1/codeset-index-select1.xbl
        oxf:/xbl/im/codeset-category-select1/codeset-category-select1.xbl
        oxf:/xbl/im/edit-history/edit-history.xbl
        oxf:/xbl/im/print-letter-trigger/print-letter-trigger.xbl
        oxf:/xbl/im/document-state/document-state.xbl
        oxf:/xbl/im/growth-chart/growth-chart.xbl
        oxf:/xbl/im/progress-note/progress-note.xbl
        oxf:/xbl/im/spell-checker/spell-checker.xbl
        
    </property>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
Hi Brian,

Yes, you can see the output of the XSLT processing. Add `analysis` and `analysis-xbl-tree` to your `oxf.xforms.logging.debug` property. Also see:

https://doc.orbeon.com/configuration/advanced/xforms-logging.html.

For the properties, in addition to a reference for the Form Builder toolbox, you also need to have a config mapping `im` to the namespace you're using, so the XBL code can know it needs to look for files corresponding to that namespace in oxf:/xbl/im. Also see:

https://doc.orbeon.com/configuration/properties/xforms.html#automatic-inclusion-of-xbl-bindings

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Hi Alex,

Alessandro Vernet wrote
Yes, you can see the output of the XSLT processing. Add `analysis` and `analysis-xbl-tree` to your `oxf.xforms.logging.debug` property. Also see:

https://doc.orbeon.com/configuration/advanced/xforms-logging.html.
I've enabled that but still not a lot of help (to my eyes) in the reams of logging produced. The analysis-xbl-tree didn't seem to produce much else different from analysis.
For the properties, in addition to a reference for the Form Builder toolbox, you also need to have a config mapping `im` to the namespace you're using, so the XBL code can know it needs to look for files corresponding to that namespace in oxf:/xbl/im. Also see:

https://doc.orbeon.com/configuration/properties/xforms.html#automatic-inclusion-of-xbl-bindings
I have that already. I already have half a dozen other controls working from the toolbox. This is my first as an 'appearance' on other controls.

I made a copy of the character counter control into my local toolbox and changed the name and the namespace. It appears in the configuration dialog but also doesn't appear on the control so there must be something wrong in my environment but I cannot see what.

My relevant configuration properties are:-
<!-- Configuration for Additional Components in the builder -->
    <property as="xs:string" name="oxf.xforms.xbl.mapping.im" value="http://www.infomedix.com.au/cpf/forms" />
    <property as="xs:string" name="oxf.fb.toolbox.group.other.uri.*.*">
        oxf:/xbl/im/dynamic-list/dynamic-list.xbl
        oxf:/xbl/im/codeset-select1/codeset-select1.xbl
        oxf:/xbl/im/codeset-index-select1/codeset-index-select1.xbl
        oxf:/xbl/im/codeset-category-select1/codeset-category-select1.xbl
        oxf:/xbl/im/edit-history/edit-history.xbl
        oxf:/xbl/im/print-letter-trigger/print-letter-trigger.xbl
        oxf:/xbl/im/document-state/document-state.xbl
        oxf:/xbl/im/growth-chart/growth-chart.xbl
        oxf:/xbl/im/progress-note/progress-note.xbl
        oxf:/xbl/im/my-character-counter/my-character-counter.xbl
        oxf:/xbl/im/spell-checker/spell-checker.xbl
    </property>

As I said, all are working except the last two in the list.

Not sure what to try next. I think I'll have to study the log output some more.

thanks,
brian...

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Got in to a brute force search of the orbeon source code for clues. I found the property oxf.xforms.xbl.library which looked interesting.

I've copied this from properties-xforms.xml to my local properties file and add two lines for my two text appearance based controls

    <property as="xs:string"  name="oxf.xforms.xbl.library">
        fr:tinymce
        fr:dropdown-select1
        fr:dropdown-date
        fr:fields-date
        fr:box-select
        fr:character-counter
        fr:bootstrap-select1
        fr:boolean-input
        fr:yesno-input
        fr:open-select1
        im:spell-checker
        im:my-character-counter
    </property>

Now it is all working as expected!

So, what have I missed? I don't think I should be reproducing this property in my local properties but I do seem to need to be able to add something to it... Re-reading https://doc.orbeon.com/xforms/xbl/library.html suggests that this is the only way to add attribute based bound components.

So, what is the correct way to do this for a customer written attribute bound control?

thanks
brian...

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
Hi Brian,

Yes, I forgot to mention `oxf.xforms.xbl.library`. Sorry about that!
And per your last comment, I created the following RFE:

https://github.com/orbeon/orbeon-forms/issues/3184

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

bwallis42
Thanks for the help with that Alex. All working now.

I've ended up with a control that also uses an xslt transformation. That was difficult to debug and get right, particularly since I needed to pass the ID attribute from the component that I'm wrapping through to some javascript code. It takes a while to get your mind around the layers of transformations!

brian...
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Stackoverflow in xbl control that encapsulates another

Alessandro  Vernet
Administrator
Excellent, Brian, I'm glad you managed to make that component work. And indeed, dealing with an XSLT transformation, and XForms on top of that, isn't always easy to comprehend. You're dealing with here with one of the hardest part of the product! :)

Alex
--
Follow Orbeon on Twitter: @orbeon
Follow me on Twitter: @avernet
Loading...