cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Christofer Dutz" <christofer.d...@c-ware.de>
Subject AW: AW: Client-side validation in CForms
Date Mon, 14 Jul 2008 13:45:17 GMT
Hi Jeremy,

Doesn't dojo already add support for this? I have a custom xslt transforming
integer-widgets to NumberTextBox dates to DateTextBox and so on. One thing I
was working on was to support server side validation errors. The only
solution I could come up for here, was to add a client side regexp that is
always false, but I thought "yuck!" every time I saw the code so I removed
it again ... I'll send you my xslt (even if it depends on some Java-Script I
wrote). It's really basic and only supports the usecases I used in my
application. But maybe it helps. Now please don't complain about the really
basic xslt ... I didn’t want to get lost in XSLT issues and wanted to
concentrate on the Dojo Support ... One thing I have to mention ... I user
TinyMCE as HTMLArea Widget.

I think generating the validation-output needed for client side-validation
shouldn't be a big problem, since it’s the same for almost all widgets the
class having to be patched should be the simple Widget base-classes. I would
volunteer implementing it, but only if it is really wanted. 

Chris



<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
exclude-result-prefixes="fi">
  <xsl:template match="page">
    <page>
      <!--xsl:if test="//fi:field[(fi:datatype/@type='string') and
(fi:styling/@type='htmlarea')]">
        <xsl:text disable-output-escaping="yes">
          <![CDATA[<script language="javascript" type="text/javascript"
src="/resources/forms/tiny_mce/tiny_mce_src.js"></script>]]>
        </xsl:text>
      </xsl:if-->
      <script type="text/javascript"> dojo.require("dijit.form.TextBox");
<xsl:if
 
test="//fi:field/fi:datatype[@type='date']">dojo.require("dijit.form.DateTex
tBox"); </xsl:if>
        <xsl:if test="//fi:field[(fi:datatype/@type='integer') or
(fi:datatype/@type='float')]"
          >dojo.require("dijit.form.NumberTextBox"); </xsl:if>
        <xsl:if test="//fi:field[(fi:datatype/@type='string') and
fi:selection-list]"
          >dojo.require("dijit.form.FilteringSelect"); </xsl:if>
        <xsl:if
test="//fi:booleanfield">dojo.require("dijit.form.CheckBox"); </xsl:if>
          dojo.parser.parse(dojo.byId('<xsl:value-of select="@name"/>'));
</script>
      <xsl:apply-templates select="* | text()"/>
    </page>
  </xsl:template>
  <!--
    
    Form Fields handling
    
  -->
  <xsl:template match="fi:form-template[@type = 'cweb']" priority="5">
    <form id="{@name}" class="soria" onsubmit="return false;">
      <xsl:copy-of select="@*"/>
      <input type="hidden" name="forms_submit_id"/>
      <xsl:apply-templates/>
    </form>
    <xsl:if test="//fi:validation-message">
      <table>
        <xsl:for-each select="//fi:validation-message">
          <tr>
            <td>
              <xsl:value-of select="../@id"/>: <xsl:value-of select="."/>
            </td>
          </tr>
        </xsl:for-each>
      </table>
    </xsl:if>
  </xsl:template>
  <xsl:template match="fi:form-template" priority="0">
    <form class="soria">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </form>
    <xsl:if test="//fi:validation-message">
      <table>
        <xsl:for-each select="//fi:validation-message">
          <tr>
            <td>
              <xsl:value-of select="../@id"/>: <xsl:value-of select="."/>
            </td>
          </tr>
        </xsl:for-each>
      </table>
    </xsl:if>
  </xsl:template>

  <xsl:template match="fi:continuation-id">
    <input type="hidden" name="continuation-id" value="{.}"/>
  </xsl:template>
  <!--
    
    
 
////////////////////////////////////////////////////////////////////////////
////////
    //
    //   Widget definitions
    //
 
////////////////////////////////////////////////////////////////////////////
/////////
  
  
  -->
  <xsl:template match="fi:field[fi:styling/@type='hidden']" priority="6">
    <input type="hidden" name="{@id}">
      <xsl:attribute name="value">
        <xsl:value-of select="fi:value"/>
      </xsl:attribute>
    </input>
  </xsl:template>
  <!-- 
    
    date widget 
  
  -->
  <xsl:template match="fi:field[fi:datatype/@type='date']" priority="0">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="text" name="{@id}" dojoType="dijit.form.DateTextBox">
          <xsl:attribute name="value">
            <xsl:value-of select="fi:value"/>
          </xsl:attribute>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    integer widget 
  
  -->
  <xsl:template match="fi:field[fi:datatype/@type='integer']" priority="0">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="text" name="{@id}" dojoType="dijit.form.NumberTextBox">
          <xsl:attribute name="value">
            <xsl:value-of select="fi:value"/>
          </xsl:attribute>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
          <!--xsl:if test="">
        <xsl:attribute name="promptMessage">Enter a value between -20000 and
+20000</xsl:attribute>
      </xsl:if-->
          <!--constraints="{min:-20000,max:20000,places:0}"
      invalidMessage= "Invalid elevation."-->
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    float widget 
  
  -->
  <xsl:template match="fi:field[fi:datatype/@type='float']" priority="0">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="text" name="{@id}" dojoType="dijit.form.NumberTextBox">
          <xsl:attribute name="value">
            <xsl:value-of select="fi:value"/>
          </xsl:attribute>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
          <!--xsl:if test="">
            <xsl:attribute name="promptMessage">Enter a value between -20000
and +20000</xsl:attribute>
            </xsl:if-->
          <!--constraints="{min:-20000,max:20000,places:0}"
            invalidMessage= "Invalid elevation."-->
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    string with selection-list widget 
  
  -->
  <xsl:template match="fi:field[(fi:datatype/@type='string') and
fi:selection-list]" priority="5">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:for-each select="fi:selection-list/fi:item">
          <xsl:if test="../../fi:value = @value">
            <xsl:choose>
              <xsl:when test="fi:label">
                <xsl:value-of select="fi:label"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="@value"/>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:if>
        </xsl:for-each>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <select name="{@id}" dojoType="dijit.form.FilteringSelect"
autocomplete="false">
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
          <xsl:for-each select="fi:selection-list/fi:item">
            <option>
              <xsl:attribute name="value">
                <xsl:value-of select="@value"/>
              </xsl:attribute>
              <xsl:if test="../../fi:value = @value">
                <xsl:attribute name="selected">selected</xsl:attribute>
              </xsl:if>
              <xsl:choose>
                <xsl:when test="fi:label">
                  <xsl:value-of select="fi:label"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="@value"/>
                </xsl:otherwise>
              </xsl:choose>
            </option>
          </xsl:for-each>
        </select>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    string with html-area widget 
  
  -->
  <xsl:template match="fi:field[(fi:datatype/@type='string') and
(fi:styling/@type='htmlarea')]"
    priority="5">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <div>
          <textarea title="{fi:hint}" name="{@id}">
            <xsl:if test="@required = 'true'">
              <xsl:attribute name="required">true</xsl:attribute>
            </xsl:if>
            <xsl:if test="@listening = 'true'">
              <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
            </xsl:if>
            <xsl:copy-of select="@style | fi:styling/@style"/>
            <xsl:value-of select="fi:value"/>&amp;nbsp;
          </textarea>
        </div>
        <script language="javascript" type="text/javascript">
          <![CDATA[
	tinyMCE.init({
		mode : "textareas",
		theme : "advanced",
		plugins :
"safari,style,layer,table,save,advhr,advimage,advlink,inlinepopups,insertdat
etime,preview,media,searchreplace,contextmenu,paste,directionality,fullscree
n,noneditable,visualchars,nonbreaking,template,pagebreak",
		theme_advanced_buttons1_add_before :
"save,newdocument,separator",
		theme_advanced_buttons1_add : "fontselect,fontsizeselect",
		theme_advanced_buttons2_add :
"separator,forecolor,backcolor",
		theme_advanced_buttons2_add_before:
"cut,copy,paste,pastetext,pasteword,separator,search,replace,separator",
		theme_advanced_buttons3_add_before :
"tablecontrols,separator",
		theme_advanced_buttons3_add :
"emotions,iespell,media,advhr,separator,print,separator,ltr,rtl,separator,fu
llscreen",
		theme_advanced_buttons4 :
"visualchars,nonbreaking,template,blockquote,pagebreak,|,insertfile,insertim
age",
		theme_advanced_toolbar_location : "top",
		theme_advanced_toolbar_align : "left",
		theme_advanced_statusbar_location : "bottom",
		external_link_list_url : "html-area/example_link_list.js",
		external_image_list_url : "html-area/example_image_list.js",
		flash_external_list_url : "html-area/example_flash_list.js",
		template_external_list_url :
"html-area/example_template_list.js",
		theme_advanced_resize_horizontal : false,
		theme_advanced_resizing : true,
		apply_source_formatting : true,
		spellchecker_languages :
"+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Po
lish=pl,Portuguese=pt,Spanish=es,Swedish=sv"
	});
          ]]>
        </script>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="@*|*" mode="htmlarea-copy">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" mode="htmlarea-copy"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="text()" mode="htmlarea-copy">
    <xsl:copy-of select="translate(., '&#13;', '')"/>
  </xsl:template>
  <!-- 
    
    password string widget 
    
  -->
  <xsl:template match="fi:field[(fi:datatype/@type='string') and
(fi:styling/@type='password')]"
    priority="5">
    <xsl:choose>
      <xsl:when test="@state = 'output'"> XXXXXXXXXXXX </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="password" name="{@id}" dojoType="dijit.form.TextBox"
trim="true">
          <xsl:attribute name="value">
            <xsl:value-of select="fi:value"/>
          </xsl:attribute>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
          <!--xsl:attribute name="regExp">[\w]+</xsl:attribute>
            <xsl:attribute name="invalidMessage">Invalid Non-Space
Text.</xsl:attribute-->
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    normal string widget 
  
  -->
  <xsl:template match="fi:field[fi:datatype/@type='string']">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="text" name="{@id}" dojoType="dijit.form.TextBox"
trim="true">
          <xsl:attribute name="value">
            <xsl:value-of select="fi:value"/>
          </xsl:attribute>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onchange">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
          <xsl:copy-of select="fi:styling/@style"/>
          <!--xsl:attribute name="regExp">[\w]+</xsl:attribute>
      <xsl:attribute name="invalidMessage">Invalid Non-Space
Text.</xsl:attribute-->
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <!-- 
    
    booleanfield widget 
  
  -->
  <xsl:template match="fi:booleanfield">
    <xsl:choose>
      <xsl:when test="@state = 'output'">
        <xsl:value-of select="fi:value"/>
      </xsl:when>
      <xsl:when test="@state = 'active'">
        <input type="checkbox" name="{@id}" dojoType="dijit.form.CheckBox"
value="true">
          <xsl:if test="fi:value = 'true'">
            <xsl:attribute name="checked">checked</xsl:attribute>
          </xsl:if>
          <xsl:if test="@required = 'true'">
            <xsl:attribute name="required">true</xsl:attribute>
          </xsl:if>
          <xsl:if test="@listening = 'true'">
            <xsl:attribute
name="onclick">forms_submitForm(this)</xsl:attribute>
          </xsl:if>
        </input>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <xsl:template match="fi:action">
    <input id="{@id}" type="submit" name="{@id}" title="{fi:hint}">
      <xsl:attribute name="value">
        <xsl:value-of select="fi:label/node()"/>
      </xsl:attribute>
      <xsl:if test="ancestor::fi:form-template[@type='cweb']">
        <xsl:attribute name="onclick">forms_submitForm(this, '<xsl:value-of
select="@id"/>'); return false;</xsl:attribute>
      </xsl:if>
      <!--xsl:apply-templates select="." mode="styling"/-->
    </input>
  </xsl:template>
  <xsl:template match="fi:action[fi:styling/@type = 'link']" priority="1">
    <a id="{@id}" title="{fi:hint}" href="#"
      onclick="forms_submitForm(this, '{@id}'); return false;">
      <!--xsl:apply-templates select="." mode="styling"/-->
      <xsl:copy-of select="fi:label/node()"/>
    </a>
  </xsl:template>
  <xsl:template match="fi:repeater-size">
    <input type="hidden" name="{@id}.size" value="{@size}"/>
  </xsl:template>
  <!--
  
  Defaults
  
  -->
  <xsl:template match="@*|node()" priority="-1" mode="forms-header">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()" priority="-1">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="fi:label"/>
</xsl:stylesheet>





-----Ursprüngliche Nachricht-----
Von: Jeremy Quinn [mailto:jeremy@apache.org] 
Gesendet: Montag, 14. Juli 2008 12:41
An: dev@cocoon.apache.org
Betreff: Re: AW: Client-side validation in CForms

Hi Christofer

On 13 Jul 2008, at 13:13, Christofer Dutz wrote:

> When I was working on my first attempts to do exactly what you are  
> trying to
> do (CForms using dojo 1.1 and client side validation), I ran into  
> exactly
> the same problem as you did. I too think it would be easily possible  
> to
> implement client and server-side validation using dojo. Even if it  
> would not
> be possible to implement all.
>
> Unfortunately the fi-output is hard-coded into the widget class
> implementation and no validation information is sent. Making client- 
> side
> validation work, it would make it necessary to patch every single  
> Widget
> class to output this validation-data, but should be easy to  
> accomplish.
>
> I stopped my work on this, since I had doubt's anyone would be  
> interested in
> a feature like this and the thought of having to maintain patches  
> for so
> many classes let me drop that idea.

I had a look as well and did not fancy ploughing in to the code to add  
this right now, as I have so much else to do before I can release the  
client-side stuff (hence asking for volunteers .... )

What I am working on in the meantime is using the (existing)  
<fi:datatype base="string|integer|long|double|float|decimal"/> tags to  
perform basic datatype validation on the client. My hope is that  
adding support for this now, will make it easier to add fuller  
validation client-side in the future.

BTW. Christofer, I attempted to contact you earlier about the private  
work you said you had been doing on Dojo 1.1, to see if I could roll  
it into my work. If you are interested in contributing, please contact  
me off-list.


Many thanks

regards Jeremy



>
> -----Ursprüngliche Nachricht-----
> Von: Jeremy Quinn [mailto:jeremy@apache.org]
> Gesendet: Mittwoch, 9. Juli 2008 17:17
> An: dev@cocoon.apache.org
> Betreff: Client-side validation in CForms
>
> Hi All
>
> As you may know, I am working heavily on the revamp of Dojo on the
> client-side of CForms.
>
> In Dojo it is possible to perform quite a lot of validation on form
> fields. There is a partial match between the validation capabilities
> of CForms and those of Dojo. Several people have thought in the past
> that it would be good to have the same validation occur on both the
> server and the client.
>
> OTTOMH, the kind of validators we could probably make work in both
> places would be :
> 	email, length, mod10, range and regexp (plus maybe javascript, if we
>
> can sort out any context differences)
>
> ATM however, no validation information is output by the form
> generation process. Datatypes are there (which I can initially use)
> but no validation.
>
> So my question is, would someone volunteer to either add the
> definition's validation tags to the output or help work out the
> cleanest approach to adding it?
>
> Many thanks
>
>
> regards Jeremy
>
>




Mime
View raw message