You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Barry Books <tr...@gmail.com> on 2011/07/24 21:18:31 UTC

ClientID and jQuery selectors

I'm working on a site using the new jQuery module and I've run into a
bit of a problem trying to select elements by id when using ajax
because I end up with something like this.

<div id="slider_1315d440ac6" type="any" class="ui-slider
ui-slider-horizontal ui-widget ui-widget-content ui-corner-all"><a
href="#" class="ui-slider-handle ui-state-default ui-corner-all"
style="left: 50%; "></a></div>

for <div t:id="slider" t:mixin="slider"/>

Including a clientId helps by adding name="slider" but that does not
really solve the problem because name does not have to be unique. So I
decided to create a selector binding so I could say something like
this and have everything work.

<t:label for="size" />
	<t:any element="div" t:type="any" t:id="slider"
t:mixins="jquery/ui/slider,slidechange"
		slidechange.event="${event}"
		slidechange.zone="${zone}"
		slidechange.callback="function (event,ui,url) {url.addContext(
${selector:size}.val() )}"
		slider.options="{min:1, max: 5, value: ${selector:size}[ 0
].selectedIndex + 1,
			slide: function( event, ui, url ) {
				${selector:size}[ 0 ].selectedIndex = ui.value - 1;
			}
		}" >
	</t:any>
	<t:select t:id="size"
		model="literal:GreetingPanel,Small,Medium,Large,Jumbo"
		t:mixins="change,jquery/selector"
		change.callback="function(event,ui,url) {
			${selector:slider}.slider( 'value',
${selector:size}[0].selectedIndex + 1);
		} "/>

At first it seemed easy enough but then I ran into the label problem.
In the example above the t:any element needs the size client id before
its rendered, that's a problem and I don't think the label solution
@HeartbeatDeferred can work here. In order to solve that I created the
selector mixin. The two work together like this.

Relevant selector binding code just uses the client id if there is one
otherwise outputs a global variable reference.

public Object get() {	
		Component c = componentResources.getEmbeddedComponent(tid);
		String id = null;
		if ( ClientElement.class.isAssignableFrom(c.getClass())) {
			ClientElement ce = (ClientElement) c;
			id = ce.getClientId();
		}
		
		if ( id != null ) {
			return String.format("jQuery('#%s')",id);
		}
		return String.format("jQuery(selector%s)",tid);
	}

Relevant selector mixin code adds a global variable with the real client id

void afterRender() {
		javaScriptSupport.addScript(InitializationPriority.EARLY,"selector%s
= '#%s'", resources.getId(),clientElement.getClientId());
	}

That all works but it seems a bit complicated, error prone and uses
global javascript variables. Can anyone think of a better way to do
this, is this just difficult or can @HeartbeatDeferred solve this?

Thanks
Barry

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org