Skip to content

Instantly share code, notes, and snippets.

@xfyre
Last active December 27, 2015 18:19
Show Gist options
  • Save xfyre/7369149 to your computer and use it in GitHub Desktop.
Save xfyre/7369149 to your computer and use it in GitHub Desktop.
Tapestry HashChange mixin
package my.package.mixins;
import org.apache.commons.lang3.StringUtils;
import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.corelib.base.AbstractComponentEventLink;
import org.apache.tapestry5.corelib.components.ActionLink;
import org.apache.tapestry5.corelib.components.EventLink;
import org.apache.tapestry5.internal.InternalComponentResources;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.InitializationPriority;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.slf4j.Logger;
@Import(library={"context:js/jquery.ba-hashchange.js","hashchange.js"})
public class HashChange {
@Parameter(defaultPrefix=BindingConstants.LITERAL)
private String zone;
@Inject
private Logger logger;
@Inject
private ComponentResources resources;
@Inject
private Request request;
@Inject
private TypeCoercer typeCoercer;
@InjectContainer
private AbstractComponentEventLink link;
@Environmental
private JavaScriptSupport jsSupport;
void afterRender ( MarkupWriter writer ) {
InternalComponentResources internalResources =
(InternalComponentResources) resources.getContainerResources ();
String path = null;
if ( link instanceof EventLink ) {
Binding eventBinding = internalResources.getBinding ( "event" );
path = eventBinding.get ().toString ();
}
if ( link instanceof ActionLink ) {
Binding contextBinding = internalResources.getBinding ( "context" );
if ( contextBinding == null )
path = link.getClientId ();
else
path = typeCoercer.coerce ( contextBinding.get (), String.class );
}
if ( path == null )
throw new IllegalArgumentException ( "cannot determine hash path" );
if ( internalResources.getBinding ( "zone" ) != null ) {
Binding zoneBinding = internalResources.getBinding ( "zone" );
if ( StringUtils.isNotBlank ( zoneBinding.get ().toString () ) ) {
JSONObject params = new JSONObject ();
params.put ( "linkId", link.getClientId () );
params.put ( "zoneId", zoneBinding.get ().toString () );
params.put ( "token", path );
params.put ( "ajax", request.isXHR () );
jsSupport.addInitializerCall ( InitializationPriority.LATE, "hashchange", params );
}
}
}
}
var hashchangeHandlers = {};
var hashchangeInstalled = false;
Tapestry.Initializer.hashchange = function(spec) {
var token = spec.token;
var linkId = spec.linkId;
var zoneId = spec.zoneId;
var el = jQuery('#'+linkId);
var zoneElement = jQuery('#'+zoneId);
var url = jQuery(el).attr('href');
Tapestry.onDOMLoaded(function() {
var setupHandlers = function() {
// unbind default click handler
el.unbind('click');
// perform hash change
el.bind('click', function(event) {
location.hash = '#'+token;
return false;
});
};
hashchangeHandlers['#'+token] = function() {
el.trigger(Tapestry.TRIGGER_ZONE_UPDATE_EVENT);
};
setupHandlers();
jQuery(document.body).unbind(Tapestry.ZONE_UPDATED_EVENT + "." + token);
jQuery(document.body).bind(Tapestry.ZONE_UPDATED_EVENT + "." + token, function(){
setupHandlers();
});
if (!hashchangeInstalled) {
jQuery(window).hashchange(function() {
if (hashchangeHandlers[location.hash] != null) {
var hashchangeHandler = hashchangeHandlers[location.hash];
hashchangeHandler();
}
});
hashchangeInstalled = true;
}
if (!spec.ajax && (location.hash == ('#'+token)))
el.trigger(Tapestry.TRIGGER_ZONE_UPDATE_EVENT);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment