/* * Copyright 2009 Richard Nichols. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * under the License. */ package com.visural.wicket.component.submitters; import com.visural.wicket.component.submitters.impl.SmallAjaxIndicatorRef; import com.visural.wicket.security.IPrivilege; import com.visural.wicket.security.ISecureEnableInstance; import com.visural.wicket.security.ISecureRenderInstance; import java.util.Collection; import org.apache.wicket.Component; import org.apache.wicket.ResourceReference; import org.apache.wicket.ajax.IAjaxCallDecorator; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.behavior.HeaderContributor; import org.apache.wicket.markup.html.IHeaderContributor; import org.apache.wicket.markup.html.IHeaderResponse; /** * An AJAX `Link` which replaces the given elements with an indicator image, while the update occurs. *Requires JQuery* * * @version $Id: IndicateRefreshAjaxLink.java 232 2010-11-22 09:51:32Z tibes80@gmail.com $ * @author Richard Nichols */ public abstract class IndicateRefreshAjaxLink extends AjaxLink implements ISecureEnableInstance, ISecureRenderInstance { private static final long serialVersionUID = 1L; // TODO: modularise this with AjaxSubmitLink public static final int AJAX_SUBMIT_DELAY_WINDOW = 300; public IndicateRefreshAjaxLink(String id) { super(id); add(new HeaderContributor(new IHeaderContributor() { public void renderHead(IHeaderResponse arg0) { arg0.renderOnDomReadyJavascript("jQuery('<img />').attr('src', '" + urlFor(getRefreshIndicatorImageReference()) + "');"); } })); } /** * Override and return false to suppress static Javascript and CSS contributions. * (May be desired if you are concatenating / compressing resources as part of build process) * @return */ public boolean autoAddToHeader() { return true; } /** * @return the collection of web markup containers to be replaced with an AJAX * indicator. Note that you must setOutputMarkupId(true) on each of * these elements. */ protected abstract Collection<? extends Component> getIndicateRefreshContainers(); /** * You may override this method to modify the delay threshold before the * indicator is displayed. * * @return the milliseconds to wait before displaying the AJAX indicator. */ protected int getIndicatorDisplayThresholdMillis() { return AJAX_SUBMIT_DELAY_WINDOW; } /** * You may override the html that is inserted into the page to something * other than a simple AJAX indicator image. * * This method also would allow you to implement different indicators for * different page components should you need to. * * @return the html to be replaced for the given container component. */ protected String getIndicatorHTML(Component container) { return "<img src=\""+urlFor(getRefreshIndicatorImageReference())+"\"/>"; } /** * Override to modify the AJAX indicator image used. * * @return resource reference to AJAX indicator image. */ protected ResourceReference getRefreshIndicatorImageReference() { return new SmallAjaxIndicatorRef(); } private String getAjaxImageReplaceScript() { Collection<? extends Component> containers = getIndicateRefreshContainers(); StringBuffer result = new StringBuffer(); if (containers != null) { // TODO: refactor JS - fix namespacing across all components result.append("VISURAL"+this.getMarkupId()+"Complete = false; window.setTimeout(function() { if (!VISURAL"+this.getMarkupId()+"Complete) { "); for (Component container : containers) { result.append("jQuery('#"+container.getMarkupId()+"').hide();"); result.append("jQuery('#"+container.getMarkupId()+"').after('<span class=\"visuralajaxind_"+this.getId()+"\">"+getIndicatorHTML(container)+"</span>');"); } result.append("} }, "+getIndicatorDisplayThresholdMillis()+");"); } return result.toString(); } private String getAjaxImageUnreplaceScript() { Collection<? extends Component> containers = getIndicateRefreshContainers(); StringBuffer result = new StringBuffer(); if (containers != null) { // TODO: refactor JS - fix namespacing across all components result.append("VISURAL"+IndicateRefreshAjaxLink.this.getMarkupId()+"Complete = true;"); for (Component container : containers) { result.append("jQuery('#"+container.getMarkupId()+"').show();"); result.append("jQuery('.visuralajaxind_"+this.getId()+"').remove();"); } } return result.toString(); } @Override protected IAjaxCallDecorator getAjaxCallDecorator() { return new IAjaxCallDecorator() { public CharSequence decorateScript(CharSequence script) { return getAjaxImageReplaceScript()+script; } public CharSequence decorateOnSuccessScript(CharSequence script) { return getAjaxImageUnreplaceScript(); } public CharSequence decorateOnFailureScript(CharSequence script) { return getAjaxImageUnreplaceScript(); } }; } public IPrivilege getRenderPrivilege() { return IPrivilege.NULL; } public IPrivilege getEnablePrivilege() { return IPrivilege.NULL; } }