javascript集成到``z3c.form``

z3c.formjs的Python项目详细描述


这个包将提供对z3c.form库的javascript支持/增强。



使用"z3c.form*"包编写的表单的公共javascript
特性的python api。虽然
引用后端实现是针对jquery库的,但是任何其他
javascript库都可以连接到python api中。

可以连接到
任何小部件(包括按钮)上的事件。

-``jsvalidator.txt```[必须读取]


此文档演示如何实现"实时"小部件值验证。

-``jsevent.txt``[高级用户]

允许将脚本连接到任何字段上的事件。

-``jqueryrenderer.txt``[高级用户]

此文档演示完成此包的任何功能所必需的所有后端呈现程序组件。

==========================
按钮的javascript事件
==
==

在``z3c.form``包中,按钮通常呈现为表单中的"submit"
输入字段,这意味着表单将始终被
提交。另一方面,在使用javascript时,单击
按钮通常只是执行脚本。这个包的"jsaction"模块是为实现后者而设计的。


&;gt&;gt;&;gt;来自z3c.formjs import jsaction



架构;现在让我们这样做:

&;gt;&;gt;>;导入zope.interface
&;gt;&;gt;类iButtons(zope.interface.interface):
…hello=jsaction.jsbutton(title=u'hello world!')
…dblhello=jsaction.jsbutton(title=u'double hello world!')

我们现在使用一个派生的javascript按钮字段,而不是声明"z3c.form.button.button"字段。虽然最初没有差异,但它们
稍后将以不同的方式呈现。(基本上,``jsbutton``字段呈现为
按钮小部件。)



widget selector
----


与常规字段一样,按钮的操作是使用处理程序定义的,在我们的案例javascript处理程序中是
。选择器用于确定dom
元素或为其注册处理程序的元素。小部件选择器使用小部件提供选择器API:

&;gt;&;gt;&;gt;来自Z3C.form.testing import testrequest
&;gt;&;gt;request=testrequest()

&;gt;&;gt;来自Z3C.form.browser import text
&;gt;&;gt;msg=text.textwidget(请求)
&;gt;&;gt;msg.id='表单消息'
&;gt;&;gt;msg.name='消息'

&;gt;&;gt;选择器=jsaction.widgetselector(msg)
&;gt;&;gt;选择器
<;widgetselector"表单消息"&;gt;

由于小部件选择器可以确定小部件的ID,因此它也是一个ID
选择器(请参见``jsevent.txt``):

&;gt;&;gt;&;gt;来自z3c.formjs import interfaces
&;gt;&;gt;interfaces.iidselector.providedby(选择器)
true
&;gt;&;gt;selector.id
"form msg"

这有一个优点,即我们可以重用id
选择器的呈现程序。




&;gt;&;gt;def showselectedwidget(event、selector、request):
…return'alert("%r");'%(selector.widget)


&;gt;&;gt;&;gt;类窗体(对象):
…zope.interface.implements(interfaces.ihavejssubscriptions)
…jssubscriptions=jsevent.jssubscriptions()

…def update(self):
…self.jssubscriptions.subscribe(
…jsevent.click,selector,showSelectedWidget)

&;gt;&;gt;form=form()
&;gt;&;gt;form.update()

;testing.setuprenders()

我们可以使用订阅呈现viewlet检查订阅
输出:

&;gt;&;gt;viewlet=jsevent.jssubscriptionviewlet(none,request,form,none)
&;gt;&;gt;viewlet.update()
&;gt;&;gt;print viewlet.render()
<;script type="text/javascript">;
$(document.ready(function(){
$("form msg").bind("click",function(){alert("&;lt;textwidget'msg'&;gt;"));
})
<;script>;

z3c.formjs包提供vi具有此viewlet
的ewlet管理器已为其注册。viewlet管理器的名称为
``z3c.formjs.interfaces.idynamicjavascript``并且可以在
任何模板中呈现,模板如下:

<;script tal:replace="structure
provider:z3c.formjs.interfaces.idynamicjavascript">;
<;/script&;gt;



带有javascript按钮的表单
--------


下一步是创建表单。幸运的是,我们不需要任何字段来呈现表单。另外,我们现在没有使用通常的
``z3c.form.button.handler()``函数,而是有一个特殊的处理程序
decorator将按钮连接到javascript事件,还有一个
附加的decorator同时创建按钮。处理程序本身的
输出是一个字符串,用作执行的
javascript脚本。

&;gt;&;gt;&;gt;from z3c.form import按钮,form

&;gt;&;gt;类窗体(form.form):
…buttons=按钮。按钮(iButtons)

…@jsaction.handler(按钮["hello"])
…def showHelloWorldMessage(self、event、selector):
…返回'alert("%s");'%selector.widget.title

…@handler(buttons['dblhello',event=jsevent.dblclick)
…def showDoubleHelloWorldMessage(self、event、selector):
…返回'alert("%s");'%selector.widget.title

…@jsaction.button和handler(u"click me")
…def handleclickme(self、event、selector):
…return'alert("您单击了click me按钮。");'




`handler()``decorator接受两个参数,即按钮(充当dom
元素选择器)和要将操作绑定到的事件。默认情况下,
事件是``jsevent.click`.

现在让我们看看如何将这些处理程序声明转换为action
和javascript订阅。首先我们需要初始化表单:

&;gt;&;gt;&;gt;来自z3c.form.testing import testrequest
&;gt;&;gt;request=testrequest()

&;gt;&;gt;demoform=form(none,request)

从z3c.form.interfaces导入iButtonAction
&;gt;&;gt;&;gt;zope.component.provideAdapter(
…jsaction.jsButtonAction,provides=IButtonAction)

dget)


使用表单、请求和
上下文/内容实例化操作管理器。按钮操作管理器实现可在
``z3c.form.button``包中使用:

&;gt;&;gt;actions=按钮。按钮操作(演示、请求、无)
&;gt;&;gt;actions.update()

可用作
操作:

&;gt;&;gt;actions.keys()
['hello','dblhello','436c69636b204d65']
&;gt;&;gt;&;gt;操作['hello']
<;jsbuttonaction'表单。buttons.hello'u'hello world!'&;gt;

由于为这些按钮注册了特殊的javascript处理程序,因此创建并更新操作也导致表单成为来自z3c.formjs导入接口的视图;gt;interfaces.ihavejssubscriptions.providedby(demoform)
true
&;gt;&;gt;demoform.jssubscriptions
<;z3c.formjs.jsevent.jssubscriptions对象位于…&;gt;

mp;gt;selector=list(demoform.jssubscriptions)[0].selector
&;gt;&;gt;&;gt;selector
<;widgetselector"表单按钮您好">;


吨您好'
&;gt;&;gt;&;gt;选择器。小部件
<;jsbuttonaction'窗体。按钮。您好'u'hello world!'&;gt;

st我们需要一些标准的"z3c.form"注册:

&;gt;&;gt;&;gt;来自z3c.form import字段,button
&;gt;&;gt;zope.component.providdeadapter(field.fieldwidgets)
&;gt;&;gt;zope.component.providdeadapter(button.buttonactions)

下一步,我们需要为按钮操作注册模板:

&;gt;&;gt;&;gt;来自zope.pagetemplate.interfaces从z3c导入ipagetemplate
&;gt;&;gt;&;gt;来自z3c.form.interfaces从z3c导入widget
&;gt;&;gt;导入ibuttonwidget,input_mode
&;gt;&;gt;&;gt;来自z3c.form.testing import getpath

&;gt;&;gt;&;gt;zope.component.provideadapter(
…widget.widgettemplatefactory(getpath('button_input.pt'),'text/html'),
…(无,无,无,无,iButtonWidget),
…ipagetemplate,name=input_mode)

(使用python api有点乏味,但使用zcml要简单得多。)


*连接zope.pagetemplate.engine import t中的"provider"tales表达式类型:

&;gt>&;gt;。rustedengine
&;gt;&;gt;&;gt;from zope.contentprovider导入故事
&;gt;&;gt;trustedengine.registerType('provider',tales.talesprovidedexpression)


*创建不需要设置安全性的viewlet管理器:

&;gt;&;gt;从zope.viewlet导入管理器
&;gt;&;gt;&;gt;类jsviewletmanager(manager.viewletmanagerbase):
…def过滤器(self,viewlets):
…return viewlets

*将viewlet管理器注册为名为"javascript"的内容提供程序:从z3c.form.interfaces导入iformlayer
&;gt;&;gt;&;gt;从zope.content provider.interfaces导入icontentprovider
&;gt;&;gt;gt;zope.component.provideadapter(
…jsviewletmanager,
…(无,iformlayer,无),
…icontentprovider,
…name='javascript')

*为此新的viewlet管理器注册js订阅者viewlet:

&;gt;&;gt;&;gt;来自zope.viewlet.interfaces导入iviewlet
&;gt;&;gt;zope.component.provideadapter(
…jsevent.jssubscriptionswiewlet,
…(无,iformlayer,接口。ihavejssubscriptions,
…jsviewletmanager),iviewlet,name='subscriptions')


;>;print demoform.render()
<;html&;gt;
<;head&;gt;
<;script type="text/javascript">;
$(document).ready(function(){
$("表单按钮您好").bind("click",
function(){alert("hello world!");});
$("表单按钮dblhello").bind("dblclick",
function(){alert("double hello world!");});
$("form-buttons-436c69636b204d65").bind("click",
function(){alert("you clicked the click me button.");
})
<;script&;gt;
<;head&;gt;
<;body&;gt;
<;div class="action"&;gt;
&;lt;input type="button"id="form buttons hello"
name="form.buttons.hello"class="button widget jsbutton field"
value="hello world!"/&;gt;
<;div>;
<;div class="action">;
<;input type="button"id="form buttons dblhello"
name="form.buttons.dblhello"class="button widget jsbutton field"
value="Double Hello World!"/&;gt;
<;div&;gt;
<;div class="action">;
<;input type="button"id="form-buttons-436c69636b204d65"
name="form.buttons.436c69636b204d65"
class="button widget jsbutton field"value="click me"/&;gt;
&;lt;div&;gt;
<;body&;gt;
<;html&;gt;


正如您所看到的,订阅被正确地放置在头中,而按钮通常呈现,除了输入类型,现在是一个
"按钮"。



---——

由于javascript中有多个事件,一个元素可以有多个
处理程序。因此,让我们定义一个新表单,它为同一个
按钮声明两个处理程序:

&;gt;&;gt;&;gt;类表单(form.form):
…buttons=按钮。按钮(iButtons)。选择('hello')

…@jsaction.handler(按钮["hello"])
…def showHelloWorldMessage(self、event、selector):
…return'alert("你好,世界!");'

…@handler(buttons['hello',event=jsevent.dblclick)
…def showDoubleHelloWorldMessage(自我,ev输入,选择器):
…return'alert("你好,世界!x 2";"

让我们现在实例化并更新表单:

&;gt;&;gt;demoform=form(none,request)
&;gt;&;gt;demoform.update()

订阅现在可用:

&;gt;&;gt;列表(demoform.jssubscriptions)
[&;lt;jssubscription
event=&;lt;jsevent"单击">;,
selector=&;lt;widgetselector"表单按钮您好">;,
handler=&;lt;jshandler<;函数showHelloWorldMessage…&;gt;>;,
<;jssubscription
event=&;jsevent;lt;jsevent"dblclick">;,
selector=&;lt;widgetselector"表单按钮您好">;,
handler=&;lt;jshandler<;function showDoubleHelloWorldMessage…>;>;>;>;]

还有
事件,另一个则覆盖了从z3c.form.interfaces import ibutton
&;gt;&;gt;&;gt;类表单(form.form):
buttons=按钮。按钮(iButtons)

…@jsaction.handler(ibutton,interfaces.ijsevent)
…def showHelloWorldMessage(self、event、selector):
…返回''''alert("事件'%s'已发生]);''%event.name

…@handler(按钮['hello',event=jsevent.click)
…def showDoubleHelloWorldMessage(self、event、selector):
…return'alert("Hello world clicked!");'

&;gt;&;gt;demoform=form(无,请求)
&;gt;&;gt;demoform.update()

(demoform.jssubscriptions,请求),interfaces.irenderer)
&;gt;&;gt;&;gt;renderer.update()
&;gt;&;gt;print renderer.render()
$(document).ready(function(){
$("…-hello").bind("dblclick",function(){alert("the…");
$("…-hello").bind("change",function(){alert("the…");};
$("…-hello").bind("load",function(){alert("the…");});
$("…-hello").bind("blur",function(){alert("the…");
$("…-hello").bind("focus",function(){alert("the…");});
$("…-hello").bind("keydown",function(){alert("the…");};
$("…-hello").bind("keyup",function(){alert("the…");});
$("…-hello").bind("mousedown",function(){alert("the…");
$("…-hello").bind("mousemove",function(){alert("the…");});
$("…-hello").bind("mouseout",function(){alert("the…");
$("…-hello").bind("mouseover",function(){alert("the…");
$("…-hello").bind("mouseup",function(){alert("the…");
$("…-hello").bind("resize",function(){alert("the…");
$("…-hello").bind("select",function(){alert("the…"))年鉴);
>$("3535;…-hello").bind(submit,function(){alert(the…);});
$("…-dblhello").bind(click,function(){alert(the…);});
$("…-dblhello").bind(dblclick,function(){alert(the…);;
>$("…-dblhello").bind(change,function(){alert(the…));}});
>$(
>>$("
>>$(""
>>(2)在;
$("…-dblhello").bind("load",function(){alert("…));});
$("…-dblhello").bind("blur",function(){alert("…));});
$("…-dblhello").bind("focus",function(){alert("…);});
$("…-dblhello").bind("keyddown",function(){alert("…));});
$("…-dblhello").bind("…)-dblhello.bind("keydown",function(),function(){function br/>$("…-dblhello").bind("keyup",function(){alert("the…");});
$("…-dblhello").bind("mousedown",function(){alert("the…");
$("…-dblhello").bind("mousemove",function(){alert("the…");
$("…-dblhello").bind("mouseout",function(){al)
$("…)…);
$("…)…-dblhello").bind("mouseover",function(){alert("…));
$("…)…-dblhello").bind("mouseup",function(){alert("…)));
$("…)…).bind("resize",function(){alert("…)););
$("…)…));
$("…)…)-dblhelloo").bind("select",function(),function(););;
>
$("…);
>$("…"…){甲lert("the…");};
$("…-dblhello").bind("submit",function(){alert("the…");});
$("…-hello").bind("click",function(){alert("hello world clicked!");});
})

此外,
一个更具体的指令比更一般的指令具有优先性。这是由于"jshandlers"类的内置适配器注册表导致的。

gt;类窗体(form.form):
…buttons=按钮。按钮(iButtons)

…@jsaction.handler(iButtons['hello',jsevent.click)
…@jsaction.handler(iButtons['hello',jsevent.dblclick)
…def showHelloWorldMessage(self、event、selector):
…return''''alert("事件'%s'已发生]);''%event.name

&;gt;&;gt;&;gt;demoform=form(无,请求)
&;gt;&;gt;demoform.update()

renderer=zope.compone呈现订阅会得到以下结果:

&;gt;&;gt;renderer=zope.component.getmultiadapter(
…(demoform.jssubscriptions,request),interfaces.irenderer)
&;gt;&;gt;&;gt;renderer.update()
&;gt;&;gt;print renderer.render()
$(document).ready(function(){
$("表单按钮你好").bind("click",function(){alert("the…");
$("表单按钮你好").bind("click",function(){alert("the…")ons hello").bind("dblclick",function(){alert("the…");
})




让我们创建一个可以用来创建表单的简单架构:

&;gt;&;gt;&;gt;导入zope.schema

&;gt;&;gt;类iperson(zope.interface.interface):
…name=zope.schema.textline(title=u'name')
…age=zope.schema.int(title=u'age')

fields=字段。字段(iperson)

…@jsaction.handler(字段['age'])
…def ageclickevent(self、event、selector):
…return'alert("点击了年龄!");'

…@jsaction.handler(字段['name',event=jsevent.change)
…def nameChangeEvent(self、event、selector):
…return'alert("名称已更改!");'

我们还需要注册所有默认的"z3c.form"注册:

&;gt;&;gt;&;gt;来自z3c.form.testing导入setupformdefaults
&;gt;&;gt;setupformdefaults()

/>&;gt;&;gt;addform=personaddform(无,请求)
&;gt;&;gt;测试.addtemplate(addform,"simple_edit.pt")
&;gt;&;gt;addform.update()
&;gt;&;gt;打印addform.render()
<;html&;gt;
<;head>;gt;
<;script type="text/javascript">;
$(document).ready(function(){
$("表单小部件名称").bind("更改",
function(){alert("名称已更改!");});
$("窗体小部件老化").bind("单击",
function(){alert("单击了年龄!");});
})
<;script>;
<;head&;gt;
<;body&;gt;
<;blankline&;gt;
<;blankline&;gt;
<;form action=".&;gt;
<;div class="row">;
<;label for="form widgets"-name">;name<;label&;gt;
<;blankline&;gt;
<;input id="form widgets name"name="form.widgets.name"
class="text widgets required textline field"
value="type="text"/&;gt;
<;blankline>;
<;/div&;gt;
<;div class="row">;
<;label for="form widgets age">;age&;lt;/label&;gt;
<;blankline&;gt;
<;input id="form widgets age"name="form.widgets.age"
class="文本widget必选int字段"value="
type="text"/&;gt;
<;blankline&;gt;
<;div&;gt;
<;div class="action">;
<;blankline&;gt;
<;input id="form buttons add"name="form.buttons.add"
class="提交小部件按钮字段"value="add"
type="submit"/&;gt;
<;blankline&;gt;
<;div&;gt;
<;form&;gt;
<;body&;gt;
<;html&;gt;

LER要共存。



附录A:javascript事件处理程序管理器
--------------------------


&;gt;&;gt;&;gt;handlers=jsaction.jshandlers()
&;gt;&;gt;handlers
<;jshandlers[]>;

如果为某个按钮注册了处理程序,则它只是作为
实例适配器运行。

&;gt;&;gt;&;gt;处理程序。<;zope.interface.adapter.adapterRegistry对象位于…&;gt;

对象本身非常简单。要添加处理程序,首先必须创建
处理程序,…

&;gt;&;gt;def dosomething(form,event,selector):
…传递handler=jsaction.jshandler(dosomething)

&;gt;&;gt;button1=jsaction.jsbutton(name='button1',title=u'button 1')

类:

&;gt;&;gt;&;gt;类特殊按钮(jsaction.jsbutton):
…传递处理程序.addhandler(
…specialbutton,jsevent.click,jsaction.jshandler('specialaction'))

&;gt;&;gt;handlers
<;jshandler s
[&;lt;jshandler<;function dosomething at…&;gt;,
<;jshandler'specialaction'&;gt;]&;gt;

特殊按钮应使用该处理程序:

&;gt;&;gt;button2=特殊按钮(name='button2',title=U'button 2')
&;gt;&;gt;button3=特殊按钮(name='button3',title=U'button 3')

&;gt;&;gt;handlers.gethandlers(button2)
((&;lt;jsevent"单击"&;gt;,&;lt;jshandler"特殊处理"&;gt;),)
&;gt;&;gt;&;gt;handlers.gethandlers(按钮3)
((&;lt;jsevent"click"&;gt;,&;lt;jshandler"specialaction"&;gt;)


但是,为按钮2注册更特定的处理程序将覆盖
常规处理程序:

&;gt;&;gt;handlers.addhandler(
…button2,jsevent.click,jsaction.jshandler('specification2'))

&;gt;&;gt;&;gt;handlers.gethandlers(button2)
((&;lt;jsevent"click"&;gt;,&;lt;jshandler'specification2'&;gt;),)
&;gt;&;gt;handlers.gethandlers(button3)
((&;lt;jsevent"click">;,<;jshandler"specialaction">;),)


处理程序.addhandler(
…jsaction.jsbutton,jsevent.jsevent,
…jsaction.jshandler('genericeventation')

因此,在请求按钮1的处理程序时,我们会得到一个非常长的列表:

&;gt;&;gt;handlers.gethandlers(button1)
((&;lt;jsevent"click"&;gt;,&;lt;jshandler"genericeventation"&;gt;),
(&;lt;jseven)t"dblclick">;、<;jshandler"genericeventation">;)、
(&;lt;jsevent"change">;、<;jshandler"genericeventation">;)、
(&;lt;jsevent"load">;、<;jshandler"genericeventation">;)、
(<;jsevent"blur">;、<;jshandler'genericeventation'>;),
(&;lt;jsevent"focus">;,&;lt;jshandler'genericeventation'>;),
(&;lt;jsevent"keydown">;,&;lt;jshandler'genericeventation'>;),
(&;lt;jsevent"keyup">;,&;lt;jshandler'genericeventatic在"&;gt;)、
(&;lt;jsevent"mousedown">;、&;lt;jshandler"genericeventation">;)、
(&;lt;jsevent"mousemove">;、&;lt;jshandler"genericeventation">;)、
(&;lt;jsevent"mouseout">;、&;lt;jshandler"genericeventation">;)、
(&;lt;jsevent"鼠标悬停">;、&;lt;jshandler"GenericEventAction">;)、
(&;lt;jsevent"鼠标悬停">;、&;lt;jshandler"GenericEventAction">;)、
(&;lt;jsevent"调整大小">;、&;lt;jshandler"GenericEventAction">;)、
(&;lt;jsevent"s选择"&;gt;、<;jshandler'genericeventaction'>;)、
(&;lt;jsevent"submit">;、<;jshandler'genericeventaction'>;))


此时,我们使用
``jsevent.event s``变量中列出的所有事件的列表。


让我们现在为"click"事件注册一个特殊处理程序:

&;gt;&;gt;handlers.addhandler(
…button1,jsevent.click,jsaction.jshandler('clickeventaction'))


;lt;jsevent"dblclick">;、<;jshandler"genericeventation">;)、
(&;lt;jsevent"change">;、<;jshandler"genericeventation">;)、
(&;lt;jsevent"load">;、&;lt;jshandler"genericeventation">;)、
(&;lt;jsevent"blur">;,<;jshandler'genericeventaction'>;),
(&;lt;jsevent"focus">;,&;lt;jshandler'genericeventaction'>;),
(&;lt;jsevent"keydown">;,&;lt;jshandler'genericeventaction'>;),
(&;lt;jsevent"keyup">;,&;lt;jshandler'genericEventAction'&;gt;),
(&;lt;jsevent"mousedown"&;gt;,&;lt;jshandler"genericeEventAction"&;gt;),<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;J (&lt;JIf you're going to "mouseup" &&gt;; &&lt; if you are going to "genericEventEventEventAction" &gt;;,<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;lt;if if if; if if; if if;;; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;JJ;&;lt;jshandler"GenericEventAction"&;gt;)


还可以添加处理程序对象:

&;gt;handlers=jsaction.jshandlers()
&;gt;handlers.addhandler(
…button1,jsevent.click,jsaction.jshandler('button1clickaction')

&;gt;&;gt;handlers2=jsaction.jshandlers()
&;gt;&;gt;handlers2.addhandler(
…我即将成为一个事件。点击,jsaction.jshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshshs((<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<但是,添加不支持其他组件:

&;gt;&;gt;处理程序+1
回溯(最近一次调用):

notimplementederror

py()
&;gt;&;gt;isinstance(copy,jsaction.jshandlers)
true
>;copy is handlers




er
-----------------------------

the``create subscriptions for widget(event)`event subscriber列出
`iafterwidgetupdeevent`并负责查找任何
javascript操作处理程序并为它们创建事件订阅。
因此,让我们设置环境:

&;gt;&;gt;&;gt;类窗体(form.form):
…buttons=按钮。按钮(iButtons)

…@jsaction.handler(按钮["hello"]
…def showHelloWorldMessage(self、event、selector):
…return'alert("你好,世界!");'

&;gt;&;gt;form=form(none,request)


当然,不仅仅是任何小部件都可以有javascript处理程序。首先,
小部件必须是一个字段小部件:

&;gt;&;gt;来自z3c.form import widget
&;gt;>;simplewidget=widget.request


&;gt;jsaction.createsubscriptions for widget(
…widget.AfterWidgetgetUpUpUpdateEvent (simpleWidget)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

它仍然需要是一个可识别表单的widget:


&a mp;gt;&a mp;gt;jsaction.createsubscriptions for widget(
…widget.AfterWidgetUpUpdateEvent (helloWidget)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<> &gt;&;gt;hellowidget.form=form
&;gt;&;gt;zope.interface.alsoprovides(hellowidget,iformaware)

d到表单:

&;gt;&;gt;&;gt;jsaction.createSubscriptionsforWidget(
…widget.afterwidgetupdeevent(hellowidget))

&;gt;&;gt;gt;接口。iHavejssubscriptions.providedby(form)
true
&;gt;&;gt;&;gt;len(list(form.jssubscriptions))
1
&;gt;&;gt;list(form.jssubscriptions)
[<;jssubscription
event=&;lt;jsevent"单击"&;gt;,selector=<;widgetselector"hello">;,
handler=<;jshandler<;function showhelloworldmessage at…>;>;>;>;]&;gt;jsaction.createSubscriptionsforWidget(
…widget.afterwidgetupdateevent(hellowidget))
&;gt;&;gt;len(list(form.jssubscriptions))
1

&;gt;&;gt;&;gt;hellowidget.form=object()

&;gt;&;gt;jsaction.createSubscriptionsForWidget(
…widget.afterwidgeGetUpdateeEvent(hellowowwidgedget)widget.afterwidgeGetUpdateeEvent(hellowowwidget))

&;gt;amp;gt;amp;gt;amp;gt;gt;interfaces.ihavejssubscriptions.providedby(form)providedby(form)providedby(form)providedby(form)








===========javascript formform验证

==================



这个通过javascript验证小部件值。特别是,``jsvalidator``模块通过
ajax实现服务器端验证。


&;gt;&;gt;&;gt;来自z3c.formjs import jsvalidator


验证api有两个组件。第一个是validator,它是一个
form mix-in类,通过一个url来实现验证功能,并且
定义了验证的通信协议;例如,它定义了验证必须访问的路径,发送和返回的数据。第二个组件是验证脚本,它负责定义在请求验证时执行的javascript代码。





e进入页面的
内容。

因此,让我们做一些必要的设置:

&;gt;&;gt;&;gt;来自z3c.form。测试导入setupformdefaults
&;gt;&;gt;setupformdefaults()

&;gt;&;gt;导入zope.component
&;gt;&;gt;来自z3c。form import error
&;gt;&;gt;zope.component.provideadapter(error.valueerrorviewsnippet)

zip=zope.schema.int(title=u"邮政编码")

&;gt;&;gt;&;gt;来自z3c.form.interfaces导入ifield
&;gt;&;gt;&;gt;来自z3c.formjs导入jsevent,jsaction

&;gt;&;gt;类地址编辑表单(jsvalidator.messagevalidator,form.addform):
…fields=字段。字段(iAdress)

…@jsaction.handler(ifield,event=jsevent.change)
…def fieldvalidator(self、event、selector):
…返回self.validationscript(self,selector.widget).render()

est=t est request()
&;gt;&;gt;edit=addresseditform(none,request)
&;gt;&;gt;edit.update()


>我们可以执行处理程序以确保从z3c.formjs导入测试中获得一些输出:

&;gt;&;gt正在测试.setuprenders()

&;gt;&;gt;&;gt;来自z3c.formjs import jsaction
&;gt;&;gt;>;打印编辑.fieldvalidator(
…无,jsaction.widgetselector(edit.widgets['zip'])
$.get('/validate',function(data){alert(data)})

validator使用ajax处理程序与服务器通信。通常,ajax
处理程序是通过"ajax"视图查找的——有关更多
详细信息,请参见"ajax.txt"。在本例中,我们只需创建一个小助手函数:

&;gt;&;gt;&;gt;from z3c.formjs import ajax

&;gt;&;gt;def ajaxplugin(view):
…返回ajax.ajaxrequesttraversplugin(view,view.request)


&;gt;&;gt;&;gt;from z3c.formjs import ajax,interfaces
&;gt;&;gt;&;gt;from zope.publisher.interfaces.browser import ibrowserrequest

&;gt;&;gt;zope.component.providesubscrip选项适配器(
…ajax.ajaxrequesttraversplugin,
…(interfaces.iformtraverser,ibrowserrequest))

我们可以从"ajax"视图遍历到"validate"方法并呈现它。让我们首先呈现一些有效的输入:

&;gt;&;gt;request=testrequest(form={'widget-name':'zip',
…'form.widgets.zip':u'29132'})
&;gt;&;gt;&;gt;edit=addresseditform(none,request)
&;gt;&;gt;&;gt;edit.update()
&;gt;&;gt;ajaxplugin(edit).publishtraverse(none,validate')(
u'

现在让我们提供一个无效的zip
代码。如您所见,我们得到了预期的错误消息:

&;gt;&;gt;request=testrequest(form={'widget-name':'zip',
…'form.widgets.zip':'notazipcode'})
&;gt;&;gt;&;gt;edit=addresseditform(none,request)
&;gt;&;gt;&;gt;edit.update()
&;gt;&;gt;ajaxplugin(edit).publishtraverse(none,validate')(
u'输入的值不是有效的整数文本。'

当然,不能只遍历表单中的任何属性:

&;gt;&;gt;&;gt;ajaxplugin(edit).publishTraverse(none,'validationscript')(
回溯(最近一次调用最后一次):

未找到:对象:&;lt;addresseditform…&;gt;,name:'validationscript'

就这样了。


因此,让我们看看这是如何工作的。


&;gt;&;gt;&;gt;来自z3c.formjs导入接口,jsevent

要实现此功能,我们需要对三个组件建模:事件、dom元素(选择器)和脚本(处理程序)。我们还需要一个管理器来跟踪所有映射。这确实有点类似于zope
3事件模型,尽管我们不需要dom元素来连接那里的事件。



----


所以首先我们需要创建一个订阅管理器来收集
订阅:

&;gt;&;gt;&;gt;manager=jsevent.jssubscriptions()

当事件发生时,我们希望显示一条简单的"hello
world"消息。

可在所有大写字母中使用,例如:

&;gt;&;gt;&;gt;jsevent。单击
<;jsevent"click"&;gt;

&;gt;&;gt;&;gt;选择器
<;idSelector"消息"&;gt;

return u'alert("你好,世界!")

我们终于有了所有部分来订阅事件:

&;gt;&;gt;&;gt;manager.subscribe(jsevent.click,selector,showhelloworldalert)
<;jssubscription event=&;lt;jsevent"click">;,
selector=<;idselector"messag"e"&;gt;,
handler=&;lt;function showhelloworldalert at…&;gt;

,现在我们可以看到订阅:

&;gt;&;gt;list(manager)
[&;lt;jssubscription event=&;lt;jsevent"click"&;gt;,
选择器=&;lt;idSelector"Message">;,
handler=&;lt;function showhelloworldalert at…>;>;]

=&;lt;jsevent"click"&;gt;,
selector=&;lt;idselector"message">;,
handler=&;lt;function showhelloworld alert at…>;>;]

那么现在,如何将其呈现为javascript代码呢?由于这个包将定义与渲染严格分离,渲染器将负责生成输出。





我们已经在"testing"支持模块中准备了用于测试目的的渲染器。
第一个是用于id选择器的,与所有视图组件一样,来自z3c.formjs import testing的渲染器支持更新/渲染模式。我们现在可以呈现选择器:

&;gt;&;gt;&;gt;from zope.publisher.browser import testrequest
&;gt;&;gt;request=testrequest()

&;gt;&;gt;renderer=zope.component.getmultiadapter(
…(选择器,请求),interfaces.irenderer)
假设我们可以按如下方式绑定
订阅:`$(&;lt;selector&;gt;).bind("&;lt;event&;gt;",&;lt;script&;gt;)``

&;gt;&;gt;zope.component.provideadapter(testing.subscriptionrenderer)

呈现订阅,然后返回以下结果:

&;gt;&;gt;&;gt;renderer=zope.component.getMultiAdapter(
…(列表(管理器)[0],请求),interfaces.irenderer
&;gt;&;gt;&;gt;renderer.update()
&;gt;&;gt;print renderer.render()
$("消息").bind("click",function(){alert("hello world!")});

,现在进入大结局。我们为订阅管理器创建呈现程序。

&;gt;&;gt;&;gt;zope.component.provideadapter(testing.manager render)

现在让我们呈现整个管理器。

&;gt;&;gt;renderer=zope.component.getmultiadapter(
…(管理器,请求),interfaces.irenderer)
&;gt;&;gt;renderer.update()
&;gt;&;gt;print renderer.render()
$(文档).ready(function(){
$("消息").bind("click",function(){alert("hello world!")});
})



因此,存在一个名为"subscribe"的decorator,它可以将组件方法转换为订阅处理程序。让我们看看:

&;gt;&;gt;&;gt;类myview(对象):

…@jsevent.subscribe(jsevent.idselector('myid'),jsevent.dblclick)
…def alertuser(事件、选择器、请求):
…返回u"警报('`%s'在dom元素'%s`'上发生事件);"%(
…event.name,selector.id)

订阅现在在视图的订阅管理器中可用:

&;gt;&;gt;&;gt;列表(myview.jssubscriptions)
[&;lt;jssubscription event=&;lt;jsevent"dblclick"&;gt;,
选择器=&;lt;idselector"myid"&;gt;,
handler=<;function alertuser at…&;gt;&;gt;]


>我们现在呈现订阅:

&;gt;&;gt;renderer=zope.component.getmultiadapter(
…(list(myview.jssubscriptions)[0],request),interfaces.irenderer)
还可以链接cribe decorators,以便同一个处理程序可以用于多个选择器和事件:


&;gt>amp;gt;类myview(object):

…@jsevent.subscribe(jsevent.idselector('myid'),jsevent.click)
…@jsevent.subscribe(jsevent.idselector('myid'),jsevent.dblclick)
…def alertuser(事件、选择器、请求):
…返回u"警报('`%s'在dom元素'%s`'上发生事件);"%(
…event.name,selector.id)

在此示例中,我们为ID为"myid"的dom元素的click和double click事件注册此处理程序。

&;gt;&;gt;&;gt;list(myview.jssubscriptions)
[&;lt;jssubscription event=&;lt;jsevent"dblclick"&;gt;,
选择器=&;lt;idselector"myid">;,
处理程序=&;lt;函数警报用户位于…&;gt;,
<;jssubscription event=&;lt;jsevent"click">;,
选择器=&;lt;idselector"myid">;,
handler=<;function alertuser at…>;>;]相反,我们可以为js viewlet管理器注册一个viewlet,如果找到了管理器,它将呈现订阅。zope.interface.implements(interfaces.ihavejssubscriptions)
…jssubscriptions=manager

object(),request,view(),object())
&;gt;&;gt;viewlet.update()
&;gt;&;gt;print viewlet.render()
<;script type="text/javascript"&;gt;
$(document).ready(function(){
$("message").bind("click",function(){alert("hello world!")});
})
<;script>;




selector
----

元素选择器。
相应的redener负责解释选择器。

id选择器
~~~~~~~~~~~~~~~

id选择器按id选择dom元素,如上所示。它只需使用id初始化


&;gt;&;gt;idselect=jsevent.idselector('myid')
&;gt;&;gt;idselect
<;idselector"myid">;


id还可用作属性:

&;gt;&;gt;idselect.id
"myid"

(idselect,request),interfaces.irenderer)
&;gt;&;gt;renderer.update()
&;gt;&;gt;renderer.render()
u'\myid'


css选择器
~~~~~~~~~~~

css选择器使用任意css选择器表达式选择dom元素。此选择器使用表达式初始化:

&;gt;&;gt;cssselect=jsevent.css selector('div.myclass')
&;gt;&;gt;cssselect
<;cssselector"div.myclass">;

css选择器表达式也可用作属性:

&;gt;&;gt;cssselect.expr
"div.myclass"


现在让我们看一个如何呈现css选择器的示例:

&;gt;&;gt;zope.component.provideadapter(testing.css selector renderer)

&;gt;&;gt;renderer=zope.component.get多适配器(
…(cssselect,request),interfaces.irenderer)
&;gt;&;gt;&;gt;renderer.update()
&;gt;&;gt;renderer.render()
u'div.myclass'


因为大多数js库默认支持css选择器,所以renderer只需将表达式转换为unicode即可。


可用事件
----

此包映射所有可用的javascript事件。以下是完整的
列表:

&;gt;&;gt;jsevent.单击
<;jsevent"单击"&;gt;
&;gt;&;gt;jsevent.dblclick
<;jsevent"dblclick"&;gt;
&;gt;&;gt;jsevent.change
<;jsevent"更改">;&br/>&;gt;>;jsevent.load
<;jsevent"load"&;gt;
>;jsevent.blur
<;jsevent"blur">;
>;jsevent.focus
<;jsevent"focus">;
>;>;jsevent.keydown
<;jsevent"focus">;
>;>;jsevent.;jsevent"keydown">;
>;>;>;jsevent.keydup
<;jsevent"keydup">;
>;>;jsevent.mousedown
<;jsevent"mousedown">;
>;>;jsevent.mousemove
<;jsevent"mousemove">;
&;gt;&;gt;jsevent.mouseout
<;jsevent"mouseout">;
&;gt;>;jsevent.mouseover
<;jsevent"mouseover">;
>;>;jsevent.mouseup
<;jsevent"mouseup">;
>;jsevent。resize
<;jsevent"resize">;jsevent.select
<;jsevent"select">;
>;>;jsevent.submit
<;jsevent"submit">;


/>
&;gt;&;gt;&;gt;导入zope.component
&;gt;&;gt;zope.component.provideUtility(jsevent.click,name='click')

&;lt;jsevent"click">;



==
更改
=




0.5.0版(2009-07-23)
----


-功能:更新到最新的软件包版本。

-错误:避免``jsvalidator.messagevalidator``中的``forbiddenattribute``.




0.4.1版(2008-12-16)
=--


-restructure:使用zope.viewlet中的weightOrderedViewletManager,而不是z3c.viewlet中的
,这将删除额外的egg要求。


0.4.0版(2008-08-26)
已向所有
使用"z3c.formjs"所需的viewlets注册。现在您只需执行以下操作:

<;script tal:replace="structure
provider:z3c.formjs.interfaces.idynamicjavascript">;
<;script&;gt;


-功能:当ajax处理程序返回复杂的数据结构(字典、列表和元组)时,数据在交付前自动转换为json
格式。

-重新构造:使包在最新的z3c.form 1.9.0版本上运行。

-错误:多次更新的小部件正在生成重复的javascript事件订阅。现在这是固定的。



0.3.0版(2007-10-03)
----


-功能:为调用js函数制作javascript呈现程序。

-功能:实现工具,使服务器端事件传播到客户端。

-功能:现在是"jsevent"。subscribe``和``jsaction.handler`` decorators
可以链接在一起,允许对相同的方法多次调用它们。

-feature:实现在窗体上切换小部件模式的能力。



0.2.0版(2007-07-18)

-特性:通过一个简单的
装饰器注册公共ajax服务器调用。这些调用通过
原始视图上的特殊"ajax"视图提供。

-功能:允许通过
演示组件中的装饰器注册js订阅。

-功能:添加新的css选择器。

-功能:实现ajax驱动的wid获取值验证。

-重新构造:彻底检查整个api以使其最易于使用,实现也最简单。

-错误:包现在已100%测试。

-功能:以表单形式实现ajax请求处理程序。

0.1.0版(2007-06-29)
——(也许我们可以使用
现有的库?)

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何在设置AtomicBoolean之前检查另一个条件?   通过java将文件从windows计算机复制到另一台windows计算机   java如何在使用Cobertura时忽略与记录器相关的If条件?   java无法在Eclipse中导出Android应用程序   带GSON的java parse JSON返回null   java Extract/filter Splunk查询和条件逻辑   java ProgressBar带有一个倒计时器Android   java我应该为每个DAO编写通用方法的集成测试吗?   java从命令行访问执行JAR的文本文件   任务应用程序的java Gradle生成失败:processReleaseResources   预测函数的java DeepLearning4j NN不收敛   java如果发现特殊字符,如何删除字符串中的字符?   在Java中,从精确位置将字符串拆分为两个   将Java ByteArrayOutputStream压缩到不同的容器中   带有同心指示方块的java太空船模拟器制导计算机   java如何使用Jericho解析两条注释?   PersistenceUnit中的java多个类   连接到java中的elasticsearch?   当嵌入HTML页面时,删除java小程序中的外部白色边框   用于webstart的java CXF ClassCastException(SEIStub/ClientProxy)