Tapestry Prototype在区域更新时按ID选择元素

时间:2013-11-25 09:40:21

标签: java javascript prototypejs tapestry zone

我的网页上有一个包含select元素的区域。

我正在通过JavaScript在该元素上添加onChange侦听器(感谢http://jsfiddle.net/AnbmU/6/

void afterRender() {
    javaScriptSupport.addScript(
        "$('groupSelecter').observe('change', function() {" + 
        "    var width = $(this).getWidth();" + 
        "    var selectBox = $('groupSelecter');" + 
        "    var chosen = selectBox.selectedIndex >= 0 ? selectBox.options[selectBox.selectedIndex].innerHTML : undefined;" + 
        "    $(this).next('.ninja-input')" + 
        "         .toggleClassName('hidden', chosen != 'Create New Group...')" + 
        "         .select();" + 
        "});",
        ""
    );
}

当我触发区域刷新时出现问题,我的选择将id更改为以下内容:groupSelecter_846e54edd0b5

有没有办法让select的元素id保持不变,或者能够更改javascript并在每个区域更新中选择id?

编辑: 我以前没有意识到的另一个问题。

隐藏的输入字段会切换所选元素的每次更改,而不管其内容如何。例如,如果我最初选择GROUP_1GROUP_2GROUP_3Create New Group...以及GROUP_1,并更改为GROUP_2,则输入框出现。当我将其更改为Create New Group...时,输入会再次隐藏。同样,当我更改为GROUP_3时,会出现输入字段。请注意,在JSfiddle中,这很好用。但由于某种原因,它在我的Tapestry项目中不起作用。

EDIT2: 好的,我尝试了一些更多的摆弄:

Tapestry使用id=groupSelecter_d769af562f89生成了select元素。 它还生成了插入此JavaScript(在HTML的底部):

$$('.groupSelecter').invoke('observe', 'change', function() {
    var width = $(this).getWidth();
    var chosen = $(this).selectedIndex >= 0 ? $(this).options[$(this).selectedIndex].innerHTML : undefined;
    $(this).next('.ninja-input')
        .toggleClassName('ninja-hidden', chosen != 'Create New Group...');
});

我想到了Firefox中的元素,导航到标签,找到生成的代码并将其删除。之后,我打开了firefox JS控制台并粘贴了我刚剪切的相同的代码。而且,瞧,它有用,出于某种原因。 (选课,即)。

3 个答案:

答案 0 :(得分:1)

我不知道Tapestry,但如果它不改变类属性,你可以附加到类

而不是

$('groupSelecter').observe('change', function() {

添加一个名为'groupSelector'的类

$$('.groupSelector').first().observe('change',function() {

或者如果您有多个元素

$$('.groupSelector').invoke('observe','change',function(){

答案 1 :(得分:1)

您需要确保每次选择渲染时都触发javascript。您目前只在页面渲染(而不是ajax更新)上触发它。

您可以在mixin中执行此操作,也可以在页面呈现和ajax更新期间添加脚本。如果您使用类属性或数据属性(如此线程中的其他答案所示),您可以在两个事件中通过JavaScriptSupport添加脚本,因为在select组件呈现之前已知该值。

如果要在ajax操作中使用clientId,这有点棘手,因为您只能在选择组件呈现后添加脚本。在此之前,不会定义clientId。如果你想这样做,我建议你从你的ajax动作中返回RenderCommand。请注意,Block可以是TypeCoerced到RenderCommand

例如:

@InjectComponent
private Zone zone;

@InjectComponent
private Select groupSelector;

@Inject
private TypeCoercer typeCoercer;

RenderCommand onActionFromSomeComponent() {
    return new RenderCommand() {
        public void render(MarkupWriter writer, RenderQueue queue) {
            RenderCommand zoneBody = typeCoercer.coerce(zone.getBody(), RenderCommand.class);
            zoneBody.render(writer, queue);
            javaScriptSupport.addScript(
                "$('%s').observe('change', function() {" + 
                   // more stuff
                 "});",
                 groupSelector.getClientId()
            );
        }
    };
}

void afterRender() {
    javaScriptSupport.addScript(
        "$('%s').observe('change', function() {" + 
            // more stuff
        "});",
        groupSelector.getClientId()
    );
}

答案 2 :(得分:0)

我很惊讶Geek Num 88添加课程并按该课程选择的想法不起作用。您还可以添加data- *属性并按此选择。

否则,您可以观察动态clientId。

@InjectComponent
private Select groupSelector;

void afterRender() {
    javaScriptSupport.addScript(
        "$('%s').observe('change', function() {" + 
            // more stuff
        "});",
    groupSelector.getClientId());
}

顺便说一句。解决此问题的挂毯方法是将脚本移动到js文件并使用T5.extendInitializers(...),JavaScriptSupport.addInitializerCall(...)和@Import。演示here