[
https://issues.apache.org/jira/browse/WICKET-6055?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15071074#comment-15071074
]
ASF GitHub Bot commented on WICKET-6055:
----------------------------------------
Github user dashorst commented on a diff in the pull request:
https://github.com/apache/wicket/pull/151#discussion_r48417286
--- Diff:
wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/AjaxLazyLoadPanel.java
---
@@ -139,56 +182,176 @@ protected void handleCallbackScript(final
IHeaderResponse response,
@Override
protected void onBeforeRender()
{
- if (state == 0)
+ if (state == LoadingState.WAITING_FOR_LAZY_COMPONENT)
{
add(getLoadingComponent(LAZY_LOAD_COMPONENT_ID));
- setState((byte)1);
+ setState(LoadingState.REPLACING_LAZY_COMPONENT);
}
super.onBeforeRender();
}
+ @Override
+ public void onEvent(IEvent<?> event)
+ {
+ super.onEvent(event);
+
+ if (state == LoadingState.REPLACING_LAZY_COMPONENT)
+ {
+ if (isReadyForReplacement())
+ {
+ // create the lazy load component
+ Component component =
getLazyLoadComponent(LAZY_LOAD_COMPONENT_ID);
+
+ // replace the spinner with the new component
+ AjaxLazyLoadPanel.this.replace(component);
+
+ // mark replacement as done
+ setState(LoadingState.REPLACEMENT_COMPLETED);
+
+ // remove ourselves from the timer
+ getLazyLoadTimer().removeLazyLoadPanel(this);
+
+ AjaxRequestTarget target =
getRequestCycle().find(AjaxRequestTarget.class);
+
+ // notify our subclasses of the updated
component
+ onComponentLoaded(component, target);
+
+ // repaint our selves if there's an AJAX
request in play, otherwise let the page
+ // redraw itself
+ if (target != null)
+ {
+ target.add(AjaxLazyLoadPanel.this);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onRemove()
+ {
+ super.onRemove();
+
+ // mark replacement as done
+ setState(LoadingState.REPLACEMENT_COMPLETED);
+
+ // remove ourselves from the timer
+ AjaxLazyLoadTimer timer = getLazyLoadTimer();
+ if (timer != null)
+ {
+ timer.removeLazyLoadPanel(this);
+ }
+ }
+
/**
+ * Sets the new LoadingState for this panel.
*
- * @param state
+ * @param newState
*/
- private void setState(final byte state)
+ private void setState(final LoadingState newState)
{
- this.state = state;
+ this.state = newState;
getPage().dirty();
}
/**
+ * Gets the central lazy load timer from the page if one is registered
*
- * @param markupId
- * The components markupid.
- * @return The component that must be lazy created. You may call
setRenderBodyOnly(true) on this
- * component if you need the body only.
+ * @return the central lazy load timer or {@code null}
*/
- public abstract Component getLazyLoadComponent(String markupId);
+ private AjaxLazyLoadTimer getLazyLoadTimer()
+ {
+ return getPage().getMetaData(AJAX_LAZY_LOAD_TIMER);
+ }
/**
- * Called when the placeholder component is replaced with the lazy
loaded one.
- *
- * @param component
- * The lazy loaded component
- * @param target
- * The Ajax request handler
+ * Sets the central lazy load timer on the page
+ *
+ * @param timer
+ * the timer to set
*/
- protected void onComponentLoaded(Component component, AjaxRequestTarget
target)
+ private void setLazyLoadTimer(AjaxLazyLoadTimer timer)
{
+ getPage().setMetaData(AJAX_LAZY_LOAD_TIMER, timer);
}
/**
- * @param markupId
- * The components markupid.
- * @return The component to show while the real component is being
created.
+ * @deprecated No longer called as the AjaxLazyLoadPanel uses a central
AJAX timer, and it
+ * doesn't make sense to modify the single timer from
multiple panels
*/
- public Component getLoadingComponent(final String markupId)
+ @SuppressWarnings("javadoc")
+ @Deprecated
+ protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
- IRequestHandler handler = new ResourceReferenceRequestHandler(
- AbstractDefaultAjaxBehavior.INDICATOR);
- return new Label(markupId, "<img alt=\"Loading...\" src=\"" +
- RequestCycle.get().urlFor(handler) +
"\"/>").setEscapeModelStrings(false);
}
+ /**
+ * Allows subclasses to change the callback script if needed.
+ *
+ * @param response
+ * the current response that writes to the header
+ * @param callbackScript
+ * the JavaScript to write in the header
+ * @param component
+ * the component which produced the callback script
+ */
+ protected void handleCallbackScript(final IHeaderResponse response,
+ final CharSequence callbackScript, final Component component)
+ {
+ response.render(OnDomReadyHeaderItem.forScript(callbackScript));
+ }
+
+ /**
+ * The AJAX timer for updating the AjaxLazyLoadPanel. Is designed to be
a page-local singleton
+ * keeping track of multiple LazyLoadPanels using reference counting.
+ */
+ private static class AjaxLazyLoadTimer extends AbstractAjaxTimerBehavior
+ {
+ private static final long serialVersionUID = 1L;
+
+ private final List<AjaxLazyLoadPanel> lazyLoadPanels = new
ArrayList<>();
+
+ public AjaxLazyLoadTimer()
+ {
+ super(Duration.ONE_SECOND);
--- End diff --
Can't. The timer is a single instance for all ALLP's on a page. The reason
for using just one timer is that when you have more, you get a barrage of
events fired at your server and you don't want that (I've seen the horror). A
single timer is the best compromise for this. I've thought about increasing the
timer the longer the wait takes, but decided against it because as a user you
want direct feedback. A timer of a second is a rather nice compromise between
request pressure on the server and wait time for the user.
> AjaxLazyLoadPanel should provide non-blocking lazy load
> -------------------------------------------------------
>
> Key: WICKET-6055
> URL: https://issues.apache.org/jira/browse/WICKET-6055
> Project: Wicket
> Issue Type: Improvement
> Components: wicket-extensions
> Affects Versions: 7.1.0
> Reporter: Martijn Dashorst
> Assignee: Martijn Dashorst
>
> When having multiple AjaxLazyLoadPanels on your page, they all block their
> Wicket request thread until the content is ready to load. This can be
> problematic when you try to wait for some background job to finish and want
> to poll for that job to be ready, and only then update the contents.
> The improvement would be to add a method that gives the developer the option
> to not update just yet (isReadyForReplacement) and when it returns true,
> start the replacement. By default this would return true, implementing the
> current behavior of the AjaxLazyLoadPanel.
> Furthermore to improve the responsiveness of the ALLP it should add a single
> timer to the page that can be used by multiple ALLPs to update themselves.
> The timer would poll each second and the ALLPs would use Wicket's event bus
> to update themselves. With some reference counting, the timer can remove
> itself from the page when all ALLPs have updated themselves.
> This enables refreshing the page as well when outside an AJAX context, or
> having a user be impatient and pressing F5.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)