<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>wicket praxis</title>
	<atom:link href="http://www.wicket-praxis.de/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.wicket-praxis.de/blog</link>
	<description>erfahrungen mit wicket aus dem projektalltag</description>
	<lastBuildDate>Fri, 26 Aug 2011 11:14:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Wicket Ajax &#8211; IAjaxRegionMarkupIdProvider</title>
		<link>http://www.wicket-praxis.de/blog/2011/05/18/wicket-ajax-iajaxregionmarkupidprovider/</link>
		<comments>http://www.wicket-praxis.de/blog/2011/05/18/wicket-ajax-iajaxregionmarkupidprovider/#comments</comments>
		<pubDate>Wed, 18 May 2011 07:00:01 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=316</guid>
		<description><![CDATA[Fast unbemerkt versammeln sich in den Wicket-Updates neben einer Reihe von Bugfixes kleine Anpassungen, die das Entwickeln mit Wicket einfacher machen können. Da man nicht bei jedem Update nachsieht, was sich verändert hat, weil die Erfahrung gezeigt hat, dass man bei Wicket eigentlich immer auf die aktuelle Version wechseln kann, läuft man Gefahr, dass man [...]]]></description>
			<content:encoded><![CDATA[<p>Fast unbemerkt versammeln sich in den Wicket-Updates neben einer Reihe von Bugfixes kleine Anpassungen, die das Entwickeln mit Wicket einfacher machen können. Da man nicht bei jedem Update nachsieht, was sich verändert hat, weil die Erfahrung gezeigt hat, dass man bei Wicket eigentlich immer auf die aktuelle Version wechseln kann, läuft man Gefahr, dass man wichtige Anpassungen verpasst. Deshalb stelle ich heute eine Erweiterung von Wicket vor, die in meinen Augen ein erhebliches Potential bietet: das Interface <strong>IAjaxRegionMarkupIdProvider</strong>.</p>
<p>Über dieses Interface ist es möglich, Wicket mitzuteilen, welches Seitenelement in einem Ajax-Response eigentlich ersetzt werden soll. So ist es möglich, z.B. in einem Behavior vor und nach der Komponente Html-Markup einzufügen, dass bei Aktualisierung der Komponente ebenfalls ersetzt wird. Was sich kompliziert anhört ist in der Anwendung recht einfach. Wir implementieren ein Interface, dass einen roten Rahmen um eine Komponente ziehen soll, die per Ajax aktualisiert wird.<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_316"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.behavior;</li><li></li><li>import org.apache.wicket.Component;</li><li>import org.apache.wicket.ajax.IAjaxRegionMarkupIdProvider;</li><li>import org.apache.wicket.behavior.AbstractBehavior;</li><li></li><li></li><li>public class AjaxRegionBehavior extends AbstractBehavior implements IAjaxRegionMarkupIdProvider {</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void beforeRender(Component component) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;component.getResponse().write(&quot;&lt;div style=\&quot;border:1px solid red;\&quot; id=\&quot;&quot;+getAjaxRegionMarkupId(component)+&quot;\&quot;&gt;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.beforeRender(component);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void onRendered(Component component) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.onRendered(component);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;component.getResponse().write(&quot;&lt;/div&gt;&quot;);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public String getAjaxRegionMarkupId(Component component) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return component.getMarkupId()+&quot;_border&quot;;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 316); </script></p>
<p>Das Behavior funktioniert wie folgt: In beforeRender() und in onRendered() wird um die Komponente herum ein div-Tag mit passender Style-Anweisung geschrieben. Hierbei muss in beforeRender() die id des Tags auf den Wert gesetzt werden, den Wicket dann auch über die Interface-Methode getAjaxRegionMarkupId() bekommt. Das führt dazu, dass Wicket die Ersetzung per Ajax automatisch auf den durch das Behavior definierten Rahmen, eben die ID, die per getAjaxRegionMarkupId() definiert wurde, ausweitet.</p>
<p>Die Anwendung ist recht einfach:<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_2_316"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.behavior;</li><li></li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.ajax.markup.html.AjaxLink;</li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.markup.html.basic.Label;</li><li>import org.apache.wicket.model.Model;</li><li></li><li></li><li>public class AjaxRegionPage extends WebPage {</li><li></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;private Model&lt;Integer&gt; _counter;</li><li></li><li>&nbsp;&nbsp;public AjaxRegionPage() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_counter = Model.of(0);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;final Label label=new Label(&quot;label&quot;,_counter);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;label.setOutputMarkupId(true);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;label.add(new AjaxRegionBehavior());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(label);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new AjaxLink&lt;Integer&gt;(&quot;link&quot;,_counter) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick(AjaxRequestTarget target) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setModelObject(1+getModelObject());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(label);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 316); </script></p>
<p>Wie man im Code-Beispiel sehen kann, wird das Behavior zur Komponente hinzugefügt. Würde man das Interface nicht implementieren, würden bei jeder Aktualisierung immer neue rote Rahmen um die Komponente entstehen.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_3_316"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;AjaxRegion Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;span wicket:id=&quot;label&quot;&gt;&lt;/span&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;a wicket:id=&quot;link&quot;&gt;Count&lt;/a&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 316); </script></p>
<p>Bisher war es nötig, diese Anforderung immer auf Komponenten abzubilden, die dann korrekt ersetzt werden mussten. Damit ist es jetzt sehr viel einfacher möglich, Eine Komponente zu dekorieren und diese Dekoration auch per Ajax korrekt zu ersetzten. Auch wenn der erste Gedanke einer Anwendung sich vermutlich um Formularfelder mit fehlerhaften Eingaben dreht, gibt es unzählige Möglichkeiten, wo diese Funktionalität die Entwicklung nachhaltig vereinfachen wird.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>No Related Post</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2011/05/18/wicket-ajax-iajaxregionmarkupidprovider/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket &#8211; Komponentenübersicht (1.4.17)</title>
		<link>http://www.wicket-praxis.de/blog/2011/05/15/wicket-komponentenubersicht-1-4-17/</link>
		<comments>http://www.wicket-praxis.de/blog/2011/05/15/wicket-komponentenubersicht-1-4-17/#comments</comments>
		<pubDate>Sun, 15 May 2011 08:48:50 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Technologie]]></category>
		<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=298</guid>
		<description><![CDATA[Seit Wicket 1.4.1 haben sich bei den Komponenten und Interfaces ein paar Anpassungen ergeben, so dass ich die Komponentenübersichten aktualisiert habe. Folgende Diagramme beziehen sich auf die Version 1.4.17. Andere BeiträgeNo Related Post]]></description>
			<content:encoded><![CDATA[<p>Seit Wicket 1.4.1 haben sich bei den Komponenten und Interfaces ein paar Anpassungen ergeben, so dass ich die Komponentenübersichten aktualisiert habe. Folgende Diagramme beziehen sich auf die Version 1.4.17.</p>
<div id="attachment_161" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-comp.gv_.jpg"><img class="size-medium wp-image-161" title="wicket-comp.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-comp.gv_-450x367.jpg" alt="Wicket Kompontenten - Basis" width="450" height="367" /></a>
<p class="wp-caption-text">Wicket Kompontenten &#8211; Basis</p>
</div>
<div id="attachment_162" class="wp-caption aligncenter" style="width: 420px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-comp-ext.gv_.jpg"><img class="size-medium wp-image-162" title="wicket-comp-ext.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-comp-ext.gv_-410x450.jpg" alt="Wicket Komponenten inklusive Extensions" width="410" height="450" /></a>
<p class="wp-caption-text">Wicket Komponenten inklusive Extensions</p>
</div>
<div id="attachment_164" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-model.gv_.jpg"><img class="size-medium wp-image-164" title="wicket-model.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-model.gv_-450x382.jpg" alt="Wicket Modelle" width="450" height="382" /></a>
<p class="wp-caption-text">Wicket Modelle</p>
</div>
<div id="attachment_160" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-behavior.gv_.jpg"><img class="size-medium wp-image-160" title="wicket-behavior.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-behavior.gv_-450x95.jpg" alt="Wicket Behavior" width="450" height="95" /></a>
<p class="wp-caption-text">Wicket Behavior</p>
</div>
<div id="attachment_163" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-listener.gv_.jpg"><img class="size-medium wp-image-163" title="wicket-listener.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-listener.gv_-450x205.jpg" alt="Wicket Listener" width="450" height="205" /></a>
<p class="wp-caption-text">Wicket Listener</p>
</div>
<div id="attachment_165" class="wp-caption aligncenter" style="width: 460px"><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-requestTarget.gv_.jpg"><img class="size-medium wp-image-165" title="wicket-requestTarget.gv" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2011/05/wicket-requestTarget.gv_-450x180.jpg" alt="Wicket RequestTarget" width="450" height="180" /></a>
<p class="wp-caption-text">Wicket RequestTarget</p>
</div>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>No Related Post</li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2011/05/15/wicket-komponentenubersicht-1-4-17/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket &#8211; Back Button zuverlässig erkennen</title>
		<link>http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/</link>
		<comments>http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 06:22:31 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[back]]></category>
		<category><![CDATA[back button]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[button]]></category>
		<category><![CDATA[detect]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=290</guid>
		<description><![CDATA[Die Entwicklung moderner Webanwendungen orientiert sich zunehmend am Interaktionsmodel wie es Desktopanwendungen bieten. Wicket unterstütz dabei erheblich, in dem z.B. der Einsatz von Ajax keine große Hürde mehr darstellt. Eine Interaktionsmöglichkeit ist Desktopanwendungen doch bisher eher fremd: der Back Button im Browser. Der Nutzer erwartet, dass er auf einen vorherigen Zustand zurück navigieren kann. Je [...]]]></description>
			<content:encoded><![CDATA[<p>Die Entwicklung moderner Webanwendungen orientiert sich zunehmend am Interaktionsmodel wie es Desktopanwendungen bieten. Wicket unterstütz dabei erheblich, in dem z.B. der Einsatz von Ajax keine große Hürde mehr darstellt. Eine Interaktionsmöglichkeit ist Desktopanwendungen doch bisher eher fremd: der Back Button im Browser. Der Nutzer erwartet, dass er auf einen vorherigen Zustand zurück navigieren kann. Je komplexer die Webanwendung, desto aufwendiger war es mit anderen Frameworks, die Nutzererwartung auch in ein sinnvolles Anwendungsverhalten zu übertragen. Wicket bietet mit versionierten Seiten bereits eine gute Unterstützung, die einem Entwickler ermöglicht, die kleine &#8220;Zeitreise&#8221;, die der Nutzer vornimmt, auf Anwendungsseite entsprechend abbilden zu können.</p>
<p>Trotzdem möchte man unter Umständen wissen, dass der Nutzer den Back Button betätigt hat, weil es vielleicht auch einen Rückschluss darauf zulässt, dass der Nutzer in der Anwendung nicht die richtige Interaktionsmöglichkeit gefunden hat (z.B. in einem Bestellvorgang doch nochmal die Anschrift ändern zu wollen).</p>
<p>Folgendes Beispiel ist eine Möglichkeit, zu erkennen, ob der Nutzer mit dem Browser vor und zurück navigiert hat. Dabei gibt es zwei Dinge zu beachten. Der erste Seitenaufruf darf nicht in einer Url enden, die den Konstruktor der Seite aufruft. Denn dann sieht das aus Anwendungssicht so aus, als ob der Nutzer erneut auf die Seite navigiert ist. Zum zweiten muss man den Browser dazu zwingen, die Seite in jedem Fall neu vom Server abzurufen.</p>
<p>Daher brauchen wir zu erst eine Sprungseite:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_290"><ol><li>package de.wicketpraxis.web.blog.pages.questions.backbutton;</li><li></li><li>import org.apache.wicket.markup.html.WebPage;</li><li></li><li>public class BackButtonStartPage extends WebPage {</li><li></li><li>&nbsp;&nbsp;public BackButtonStartPage() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setResponsePage(new BackButtonPage());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setRedirect(true);</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 290); </script></p>
<p>Die Sprungseite ruft die eigentliche Seite auf. Außerdem ist der Aufruf von setRedirect() notwendig, damit nicht nur die neue Seite dargestellt wird, sondern sich auch die Url entsprechend ändert.</p>
<p>Die Seite mit der Erkennung der Button-Nutzung sieht dann wie folgt aus:<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_2_290"><ol><li>package de.wicketpraxis.web.blog.pages.questions.backbutton;</li><li></li><li>import java.util.Date;</li><li></li><li>import org.apache.wicket.MetaDataKey;</li><li>import org.apache.wicket.Session;</li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.markup.html.link.Link;</li><li>import org.apache.wicket.markup.html.panel.FeedbackPanel;</li><li>import org.apache.wicket.protocol.http.WebResponse;</li><li></li><li>public class BackButtonPage extends WebPage {</li><li></li><li>&nbsp;&nbsp;static final TimeStampKey KEY = new TimeStampKey();</li><li>&nbsp;&nbsp;private long _pageInitTimeStamp;</li><li></li><li>&nbsp;&nbsp;public BackButtonPage() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;//setVersioned(true);</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;_pageInitTimeStamp = new Date().getTime();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setPageTimeStamp(_pageInitTimeStamp);</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new FeedbackPanel(&quot;feedback&quot;));</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new Link&lt;Void&gt;(&quot;link&quot;) {</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setResponsePage(new BackButtonPage());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;private static void setPageTimeStamp(long timeStamp) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Session.get().setMetaData(KEY, timeStamp);</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void onBeforeRender() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.onBeforeRender();</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;Long lastPageRendered = Session.get().getMetaData(KEY);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setPageTimeStamp(_pageInitTimeStamp);</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (lastPageRendered &gt; _pageInitTimeStamp) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info(&quot;BackButton pressed&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (lastPageRendered &lt; _pageInitTimeStamp) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info(&quot;ForwardButton pressed&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void configureResponse() {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.configureResponse();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;WebResponse response = getWebRequestCycle().getWebResponse();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.setHeader(&quot;Cache-Control&quot;, &quot;no-cache, max-age=0,must-revalidate, no-store&quot;);</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;static class TimeStampKey extends MetaDataKey&lt;Long&gt; {</li><li></li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 290); </script></p>
<p>Das Markup der Seite:</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_3_290"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;BackButton Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div wicket:id=&quot;feedback&quot;&gt;&lt;/div&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;a wicket:id=&quot;link&quot;&gt;Link&lt;/a&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 290); </script></p>
<p>Das Prinzip funktioniert wie folgt: Die Seite bekommt einen Zeitstempel über den Zeitpunkt der Erstellung. Dieser Zeitpunkt wird außerdem als Metainformation in die Session gesetzt (Hinweis: um diese Funktion bei mehr als einer Seite benutzen zu können, ist natürlich etwas mehr Aufwand nötig). Das bedeutet, dass jede Version der Seite einen eigenen Zeitstempel hat. In onBeforeRender() kann man nun prüfen, ob diese Seite auch die aktuelle Seite ist, oder ob der Nutzer auf einen neuere oder ältere Version zurückgegriffen hat. Der Link dient dazu, immer neue Version der Seite zu erzeugen.</p>
<p>Damit der Browser die Seite aber in jedem Fall neu lädt, muss man entsprechende Header in den Http-Response einfügen. Eine Möglichkeit besteht darin, die configureResponse()-Methode entsprechend zu überschreiben.</p>
<p>Wenn man nun auf der Seite den Link klickt und dann mit dem Back Button oder dem Forward Button navigiert, erscheinen die entsprechenden Hinweise auf der Seite.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>24. Oktober 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/10/24/wicket-mainstream-github-mongodb/" title="Wicket &#8211; Mainstream, Github, MongoDB">Wicket &#8211; Mainstream, Github, MongoDB</a></li><li>15. Juli 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/07/15/wicket-flexibilitat-mit-factories/" title="Wicket &#8211; Flexibilität mit Factories">Wicket &#8211; Flexibilität mit Factories</a></li><li>14. April 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/04/14/wicket-eclipse-plugin-qwickie/" title="Wicket Eclipse Plugin &#8211;  qwickie">Wicket Eclipse Plugin &#8211;  qwickie</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket &#8211; Mainstream, Github, MongoDB</title>
		<link>http://www.wicket-praxis.de/blog/2010/10/24/wicket-mainstream-github-mongodb/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/10/24/wicket-mainstream-github-mongodb/#comments</comments>
		<pubDate>Sun, 24 Oct 2010 09:45:57 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[mongodb]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=275</guid>
		<description><![CDATA[In den letzten Wochen und Monaten habe ich recht wenig neues über Wicket gelesen. Man könnte meinen, dass es ruhig geworden ist um Wicket. Doch wenn man sich z.B. die Mailinglisten ansieht, spricht das eine deutlich andere Sprache. Jobangebote fragen zunehmend ab, ob Wicket-KnowHow vorhanden ist. Man sieht mehr und mehr Anwendungen, die mit Wicket [...]]]></description>
			<content:encoded><![CDATA[<p>In den letzten Wochen und Monaten habe ich recht wenig neues über Wicket gelesen. Man könnte meinen, dass es ruhig geworden ist um Wicket. Doch wenn man sich z.B. die Mailinglisten ansieht, spricht das eine deutlich andere Sprache. Jobangebote fragen zunehmend ab, ob Wicket-KnowHow vorhanden ist. Man sieht mehr und mehr Anwendungen, die mit Wicket realisiert wurden. Wicket ist im Mainstream angekommen.</p>
<p>Vielleicht ist das auch nur eine sehr persönliche Sichtweise, aber ich glaube, das auch Git im Mainstream angekommen ist. Git wurde bereits in bestimmten Bereichen auf einer breiten Basis eingesetzt. Aber der bedeutende Unterschied liegt darin, dass man sich bei neuen Projekten eigentlich immer die Frage stellt: Subversion oder besser gleich Git?</p>
<p>Ich habe alle meine Projekte von Subversion auf Git umgestellt und dabei gemerkt, das Subversion und Git nicht wirklich aufeinander abbildbar sind, aber die Vorteile die Git mitbringt sich selbst dann auszahlen, wenn man Git noch wie Subversion benutzt. Man findet ab jetzt die Quelltexte für das Buch bei Github unter <a href="http://github.com/michaelmosmann/wicket-praxis.git" rel="nofollow">http://github.com/michaelmosmann/wicket-praxis.git</a>.</p>
<p>Da ich in meinen aktuellen Projekten mich mit der Frage beschäftigt habe, ob nicht eine Dokumentendatenbank wie MongoDB die bessere Alternative ist, sei an dieser Stelle auch noch auf einen Objektmapper verwiesen, denn in ich diesem Zusammenhang entwickelt habe: <a href="http://github.com/michaelmosmann/mongoom.flapdoodle.de">http://github.com/michaelmosmann/mongoom.flapdoodle.de</a></p>
<p>In Zukunft an dieser Stelle wieder mehr und dann vielleicht rund um Wicket in Zusammenarbeit mit Dokumentendatenbanken.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>29. April 2011 -- <a href="http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/" title="Wicket &#8211; Back Button zuverlässig erkennen">Wicket &#8211; Back Button zuverlässig erkennen</a></li><li>15. Juli 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/07/15/wicket-flexibilitat-mit-factories/" title="Wicket &#8211; Flexibilität mit Factories">Wicket &#8211; Flexibilität mit Factories</a></li><li>14. April 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/04/14/wicket-eclipse-plugin-qwickie/" title="Wicket Eclipse Plugin &#8211;  qwickie">Wicket Eclipse Plugin &#8211;  qwickie</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/10/24/wicket-mainstream-github-mongodb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket &#8211; Flexibilität mit Factories</title>
		<link>http://www.wicket-praxis.de/blog/2010/07/15/wicket-flexibilitat-mit-factories/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/07/15/wicket-flexibilitat-mit-factories/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 07:13:46 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Refactoring]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[component]]></category>
		<category><![CDATA[factory]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=270</guid>
		<description><![CDATA[Komplexe Komponenten entstehen in Wicket durch das zusammenfügen von einfacheren Komponenten. Dabei werden die verwendeten Komponenten direkt adressiert. Nach außen ist nicht sichtbar, wie sich eine Komponente zusammensetzt. Um von dieser Komponente eine leicht abgewandelte Form zu erstellen, kann man auf z.B. Vererbung zurückgreifen, Komponenten ausblenden, das Markup überschreiben. Je mehr Variationen nötig sind, desto [...]]]></description>
			<content:encoded><![CDATA[<p>Komplexe Komponenten entstehen in Wicket durch das zusammenfügen von einfacheren Komponenten. Dabei werden die verwendeten Komponenten direkt adressiert. Nach außen ist nicht sichtbar, wie sich eine Komponente zusammensetzt. Um von dieser Komponente eine leicht abgewandelte Form zu erstellen, kann man auf z.B. Vererbung zurückgreifen, Komponenten ausblenden, das Markup überschreiben. Je mehr Variationen nötig sind, desto komplizierter wird der Aufbau. Der Aufwand steigt erheblich an.</p>
<p>Einen Ausweg aus dieser Situation könnte die Verwendung von Factories liefern. Dazu benötigen wir ein sehr einfach gehaltenes Interface:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.Component;</li><li></li><li>public interface IComponentFactory&lt;T extends Component&gt;</li><li>{</li><li>&nbsp;&nbsp;T newComponent(String id);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 270); </script></p>
<p>Eine einfach Implementierung, die immer ein Label mit einem bestimmten Text liefert, können wir wie folgt implementieren:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_2_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.markup.html.basic.Label;</li><li>import org.apache.wicket.model.IModel;</li><li></li><li>public class LabelFactory implements IComponentFactory&lt;Label&gt;</li><li>{</li><li>&nbsp;&nbsp;IModel&lt;?&gt; _model;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public LabelFactory(IModel&lt;?&gt; model)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_model = model;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public Label newComponent(String id)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new Label(id,_model);</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 270); </script></p>
<p>Wir übergeben hierbei ein Model, das durch das Label angezeigt wird. Soll ein anderer Text angezeigt werden, muss man dafür eine neue Factory erstellen. Bis jetzt ist noch kein Vorteil dieser Lösung absehbar. Deshalb steigern wir etwas die Komplexität. Wir erstellen eine Factory, die einen Rahmen um eine Komponente ziehen kann. Dabei wird für die Darstellung das style-Attribut erweitert.<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_3_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.AttributeModifier;</li><li>import org.apache.wicket.Component;</li><li>import org.apache.wicket.behavior.AttributeAppender;</li><li>import org.apache.wicket.markup.html.WebMarkupContainer;</li><li>import org.apache.wicket.markup.html.panel.Panel;</li><li>import org.apache.wicket.model.IModel;</li><li></li><li>public class BorderPanelFactory implements IComponentFactory&lt;Panel&gt;</li><li>{</li><li>&nbsp;&nbsp;private final IComponentFactory&lt;? extends Component&gt; _content;</li><li>&nbsp;&nbsp;private final IModel&lt;String&gt; _style;</li><li></li><li>&nbsp;&nbsp;public BorderPanelFactory(IComponentFactory&lt;? extends Component&gt; content, IModel&lt;String&gt; style)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_content = content;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_style = style;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public Panel newComponent(String id)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new BorderPanel(id, _content, _style);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;static class BorderPanel extends Panel</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public BorderPanel(String id,IComponentFactory&lt;? extends Component&gt; content,IModel&lt;String&gt; style)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(id);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WebMarkupContainer border=new WebMarkupContainer(&quot;border&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;border.add(content.newComponent(&quot;content&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;border.add(new AttributeAppender(&quot;style&quot;, true, style,&quot;;&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add(border);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 270); </script><br />
Wir übergeben daher eine Factory, die Komponenten erzeugt und ein Model, dass die Styleattribute beinhaltet. In dem Panel, was innerhalb der Factory erzeugt wird, wir dann eine Komponente eingebunden (&#8220;content&#8221;), die aus der übergebenen Factory kommt. Wir benötigen noch eine passende Markup-Datei (BorderPanelFactory$BorderPanel.html):<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_4_270"><ol><li>&lt;wicket:panel&gt;</li><li>&nbsp;&nbsp;&lt;div wicket:id=&quot;border&quot; style=&quot;padding: 8px&quot;&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;wicket:container wicket:id=&quot;content&quot;&gt;&lt;/wicket:container&gt;</li><li>&nbsp;&nbsp;&lt;/div&gt;</li><li>&lt;/wicket:panel&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(4, 270); </script></p>
<p>Um zu demonstrieren, welche Flexibilität man mit diesen wenigen Klassen bereits erreicht hat, verwenden wir beide Factories in einem Beispiel:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_5_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.model.Model;</li><li></li><li>public class ComponentFactoryPage extends WebPage</li><li>{</li><li>&nbsp;&nbsp;public ComponentFactoryPage()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; redBorderStyle = Model.of(&quot;border:1px solid red; background-color: #fff0f0;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; greenBorderStyle = Model.of(&quot;border:1px solid green; background-color: #f0fff0;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; blueBorderStyle = Model.of(&quot;border:1px solid blue; background-color: #f0f0ff;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;LabelFactory haveFunLabelFactory = new LabelFactory(Model.of(&quot;Have Fun&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory redBorderHasFunFactory = new BorderPanelFactory(haveFunLabelFactory,redBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory greenBorderWrapsRedFactory = new BorderPanelFactory(redBorderHasFunFactory,greenBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory blueBorderWrapsAllFactory = new BorderPanelFactory(greenBorderWrapsRedFactory,blueBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(blueBorderWrapsAllFactory.newComponent(&quot;element&quot;));</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(5, 270); </script></p>
<p>Wir erstellen 3 Modelle mit unterschiedlichen Werten für das style-Attribut. Um etwas Text anzuzeigen benutzen wir die LabelFactory. Danach werden drei BorderPanelFactory-Instanzen erzeugt, die eine andere Factory &#8220;umwickelt&#8221;. Zum Schluss wird ein Element erzeugt und in der Seite benutzt. Das Markup ist entsprechend einfach:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_6_270"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;ComponentFactory Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;wicket:container wicket:id=&quot;element&quot;&gt;&lt;/wicket:container&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(6, 270); </script></p>
<p>Das Ergebnis sieht dann wie folgt aus:<br />
<a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/07/wicket-component-factory.jpg"><img src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/07/wicket-component-factory-450x72.jpg" alt="" title="Wicket Component Factory Beispiel" width="450" height="72" class="aligncenter size-medium wp-image-271" /></a></p>
<p>Um zu zeigen, wie schnell die Möglichkeiten wachsen, die man mit diesem Ansatz abdecken kann, erstellen wir eine weitere Factory. In diesem Fall möchten wir zwei Elemente nebeneinander dargestellen:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_7_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.Component;</li><li>import org.apache.wicket.markup.html.panel.Panel;</li><li></li><li>public class TwoInARowFactory implements IComponentFactory&lt;Component&gt;</li><li>{</li><li>&nbsp;&nbsp;private final IComponentFactory&lt;? extends Component&gt; _left;</li><li>&nbsp;&nbsp;private final IComponentFactory&lt;? extends Component&gt; _right;</li><li></li><li>&nbsp;&nbsp;public TwoInARowFactory(IComponentFactory&lt;? extends Component&gt; left, IComponentFactory&lt;? extends Component&gt; right)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_left = left;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_right = right;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public Component newComponent(String id)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new ContainerPanel(id, _left, _right);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;static class ContainerPanel extends Panel</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public ContainerPanel(String id,IComponentFactory&lt;? extends Component&gt; left, IComponentFactory&lt;? extends Component&gt; right)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(id);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add(left.newComponent(&quot;left&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add(right.newComponent(&quot;right&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(7, 270); </script><br />
Es werden daher zwei Factories übergeben, die dann für die Erzeugung des linken und des rechten Elements zuständig sind. Das Markup benutzt der Einfachheit halber Html-Tabellen für die Anordnung:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_8_270"><ol><li>&lt;wicket:panel&gt;</li><li>&nbsp;&nbsp;&lt;table&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;wicket:container wicket:id=&quot;left&quot;&gt;&lt;/wicket:container&gt;&lt;/td&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;wicket:container wicket:id=&quot;right&quot;&gt;&lt;/wicket:container&gt;&lt;/td&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;</li><li>&nbsp;&nbsp;&lt;/table&gt;</li><li>&lt;/wicket:panel&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(8, 270); </script></p>
<p>Unsere Seitenklasse ergänzen wir entsprechend:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_9_270"><ol><li>package de.wicketpraxis.web.blog.pages.questions.factories;</li><li></li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.model.Model;</li><li></li><li>public class ComponentFactoryPage extends WebPage</li><li>{</li><li>&nbsp;&nbsp;public ComponentFactoryPage()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; redBorderStyle = Model.of(&quot;border:1px solid red; background-color: #fff0f0;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; greenBorderStyle = Model.of(&quot;border:1px solid green; background-color: #f0fff0;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Model&lt;String&gt; blueBorderStyle = Model.of(&quot;border:1px solid blue; background-color: #f0f0ff;&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;LabelFactory haveFunLabelFactory = new LabelFactory(Model.of(&quot;Have Fun&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory redBorderHasFunFactory = new BorderPanelFactory(haveFunLabelFactory,redBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory greenBorderWrapsRedFactory = new BorderPanelFactory(redBorderHasFunFactory,greenBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;BorderPanelFactory blueBorderWrapsAllFactory = new BorderPanelFactory(greenBorderWrapsRedFactory,blueBorderStyle);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(blueBorderWrapsAllFactory.newComponent(&quot;element&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;TwoInARowFactory twoInARowFactory = new TwoInARowFactory(redBorderHasFunFactory, greenBorderWrapsRedFactory);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(twoInARowFactory.newComponent(&quot;two&quot;));</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(9, 270); </script></p>
<p>Das Markup muss ebenfalls angepasst werden:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_10_270"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;ComponentFactory Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;wicket:container wicket:id=&quot;element&quot;&gt;&lt;/wicket:container&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;wicket:container wicket:id=&quot;two&quot;&gt;&lt;/wicket:container&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(10, 270); </script></p>
<p>Das Ergebnis kann sich sehen lassen:<br />
<a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/07/wicket-component-factory-split.jpg"><img src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/07/wicket-component-factory-split-450x128.jpg" alt="" title="Wicket Component Factory Split" width="450" height="128" class="aligncenter size-medium wp-image-272" /></a></p>
<p>Wie man an diesem Beispiel sehr gut erkennen kann, liegt in diesem Ansatz sehr viel Potential, gerade wenn die Anforderungen an die Flexibilität sehr hoch sind. In Projekten, die eine hohe Flexibilität erforderten hat sich dieses System bereits erfolgreich bewährt. Dabei kommt eine Kombinationen aus dem &#8220;klassischen&#8221; und dem Factory-Ansatz zum Einsatz, wodurch sich die meisten Anforderungen wesentlich besser abdecken lassen.</p>
<p>Gibt es noch ganz andere Lösungsstrategien?</p>
<div id="vgwpixel"><img src="http://vg05.met.vgwort.de/na/dbf3aa1d112c4807bddeabbd9ede6f31" width="1" height="1" alt=""></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>5. Januar 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/01/05/wicket-lose-koppelung-von-komponenten/" title="Wicket &#8211; lose Koppelung von Komponenten">Wicket &#8211; lose Koppelung von Komponenten</a></li><li>16. Oktober 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/10/16/wicket-component-overview/" title="Wicket Komponentenübersicht">Wicket Komponentenübersicht</a></li><li>29. April 2011 -- <a href="http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/" title="Wicket &#8211; Back Button zuverlässig erkennen">Wicket &#8211; Back Button zuverlässig erkennen</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/07/15/wicket-flexibilitat-mit-factories/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Wicket Eclipse Plugin &#8211;  qwickie</title>
		<link>http://www.wicket-praxis.de/blog/2010/04/14/wicket-eclipse-plugin-qwickie/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/04/14/wicket-eclipse-plugin-qwickie/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 06:28:47 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=267</guid>
		<description><![CDATA[Zufällig bin ich auf ein Wicket-Eclipse-Plugin gestoßen, dass im täglichen Umgang mit Wicket-basierten Projekten zu einer nicht unwesentlichen Arbeitserleichterung führt. In Anbetracht des frühen Entwicklungsstadiums (Version 0.1) ist das bereits eine reife Leistung. Was macht das Plugin? Mit dem Plugin ist es möglich, durch den Klick auf die Wicket-ID einer Komponente zwischen Java-Klasse und zugehörigen [...]]]></description>
			<content:encoded><![CDATA[<p>Zufällig bin ich auf ein <a href="http://code.google.com/p/qwickie/" target="_blank">Wicket-Eclipse-Plugin</a> gestoßen, dass im täglichen Umgang mit Wicket-basierten Projekten zu einer nicht unwesentlichen Arbeitserleichterung führt. In Anbetracht des frühen Entwicklungsstadiums (Version 0.1) ist das bereits eine reife Leistung.</p>
<p><strong>Was macht das Plugin?</strong></p>
<p>Mit dem Plugin ist es möglich, durch den Klick auf die Wicket-ID einer Komponente zwischen Java-Klasse und zugehörigen Markup wechseln zu können. Dabei springt der Cursor gleich an die richtige Stelle. Kurz: Das ist genau das, was ich am häufigsten benötige.</p>
<p>Bei der Installation sollte man zwei Dinge beachten: 1. Das Plugin befindet sich wirklich noch in einem sehr frühen Stadium, so dass Fehler auftreten. Man muss also abwägen, ob der Vorteil die Nachteile aufwiegt. 2. Die Hinweise zur Installation und zur Handhabung auf der Seite sollte man beachten.</p>
<p>Diese Plugin sollte man im Auge behalten. Sofern es meine Zeit erlaubt, werde ich versuchen, an diesem Plugin mitzuentwickeln. </p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>13. Januar 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/01/13/wicket-und-eclipse/" title="Wicket und Eclipse">Wicket und Eclipse</a></li><li>29. April 2011 -- <a href="http://www.wicket-praxis.de/blog/2011/04/29/wicket-back-button-detect/" title="Wicket &#8211; Back Button zuverlässig erkennen">Wicket &#8211; Back Button zuverlässig erkennen</a></li><li>24. Oktober 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/10/24/wicket-mainstream-github-mongodb/" title="Wicket &#8211; Mainstream, Github, MongoDB">Wicket &#8211; Mainstream, Github, MongoDB</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/04/14/wicket-eclipse-plugin-qwickie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket &#8211; AbstractEvent Update</title>
		<link>http://www.wicket-praxis.de/blog/2010/04/09/wicket-abstractevent-update/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/04/09/wicket-abstractevent-update/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 07:20:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Wicket]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[event]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=265</guid>
		<description><![CDATA[Wie ich bereits beschrieben habe, kann man mit Wicket relativ leicht eine lose Koppelung von Komponenten über einen Event-Mechanismus erreichen. Dabei wurden bisher nur Komponenten berücksichtigt. Manchmal ist es aber sinnvoll, die Behandlung dieser Events an einer zentralen Stelle durchzuführen. Daher habe ich die Basisklasse leicht erweitert. Dabei ist der Visitior in eine eigene Klasse [...]]]></description>
			<content:encoded><![CDATA[<p>Wie ich bereits beschrieben habe, kann man mit Wicket relativ leicht eine <a href="http://www.wicket-praxis.de/blog/2010/01/05/wicket-lose-koppelung-von-komponenten/">lose Koppelung von Komponenten</a> über einen Event-Mechanismus erreichen. Dabei wurden bisher nur Komponenten berücksichtigt. Manchmal ist es aber sinnvoll, die Behandlung dieser Events an einer zentralen Stelle durchzuführen. Daher habe ich die Basisklasse leicht erweitert. Dabei ist der Visitior in eine eigene Klasse gewandert. Außerdem ist es wesentlich geschickter, auch bei nicht Ajax-Requests mit Events zu arbeiten. Die Modifikation des EventListener-Interface trägt dem Rechnung.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_265"><ol><li>package de.wicketpraxis.web.blog.pages.questions.events;</li><li></li><li>public interface EventListenerInterface</li><li>{</li><li>&nbsp;&nbsp;public void notifyEvent(AbstractEvent event);</li><li>}</li><li></li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 265); </script></p>
<p>Die Methode lautet nun <strong>notifyEvent</strong> statt <strong>notifyAjaxEvent</strong>.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_2_265"><ol><li>package de.wicketpraxis.web.blog.pages.questions.events;</li><li></li><li>import org.apache.wicket.Component;</li><li>import org.apache.wicket.Component.IVisitor;</li><li></li><li>public class NotifyVisitor implements IVisitor&lt;Component&gt; </li><li>{</li><li>&nbsp;&nbsp;private final AbstractEvent _event;</li><li>&nbsp;&nbsp; </li><li>&nbsp;&nbsp;public NotifyVisitor(final AbstractEvent event)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_event = event;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp; </li><li>&nbsp;&nbsp;public Object component(final Component component)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (component instanceof EventListenerInterface) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((EventListenerInterface) component).notifyEvent(_event);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return IVisitor.CONTINUE_TRAVERSAL;</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 265); </script></p>
<p>Der Event sucht jetzt nicht nur in allen Komponenten nach dem EventListenerInterface, sondern auch in der Application, der Session und der Page.<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_3_265"><ol><li>package de.wicketpraxis.web.blog.pages.questions.events;</li><li></li><li>import org.apache.wicket.Application;</li><li>import org.apache.wicket.Component;</li><li>import org.apache.wicket.Page;</li><li>import org.apache.wicket.Session;</li><li>import org.apache.wicket.Component.IVisitor;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li></li><li>public class AbstractEvent</li><li>{</li><li>&nbsp;&nbsp;private final Component _source;</li><li>&nbsp;&nbsp;protected final AjaxRequestTarget _target;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public AbstractEvent(final Component source, AjaxRequestTarget target)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_source = source;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_target = target;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public AbstractEvent(final Component source)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;this(source,null);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public Component getSource()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return _source;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;/**</li><li>&nbsp;&nbsp; * notify Application, Session, Page and Components</li><li>&nbsp;&nbsp; */</li><li>&nbsp;&nbsp;public final void fire()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Page page=getSource().getPage();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Application application=page.getApplication();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (application instanceof EventListenerInterface)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((EventListenerInterface) application).notifyEvent(this);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Session session=page.getSession();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (session instanceof EventListenerInterface)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((EventListenerInterface) session).notifyEvent(this);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (page instanceof EventListenerInterface)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((EventListenerInterface) page).notifyEvent(this);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;page.visitChildren(EventListenerInterface.class, getVisitor());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;onAfterFire();</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;protected&nbsp;&nbsp;void onAfterFire()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;protected IVisitor&lt;Component&gt; getVisitor()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new NotifyVisitor(this);</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;public AjaxRequestTarget getTarget()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return _target;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public boolean isAjax()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return _target!=null;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;public final void update(Component component)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (_target!=null)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_target.addComponent(component);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li></li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 265); </script></p>
<p>Hinzugekommen ist außerdem die Funktion onAfterFire() die aufgerufen wird, sobald alle möglichen Listener benachrichtig wurden. An dieser Stelle könnte man dann Prüfungen einbauen, ob z.B. der Event überhaupt ein Ziel erreicht hat.</p>
<p>Ich glaube, dass diese Lösung zu offensichtlich war, so dass man sie leicht übersehen konnte.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>7. März 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/03/07/wicket-heatmap-ajax-mit-parametern/" title="Wicket Heatmap &#8211; Ajax mit Parametern">Wicket Heatmap &#8211; Ajax mit Parametern</a></li><li>3. März 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/03/03/wicket-extensions-anpassungen-am-modalwindow/" title="Wicket Extensions &#8211; Anpassungen am ModalWindow">Wicket Extensions &#8211; Anpassungen am ModalWindow</a></li><li>23. Dezember 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/12/23/wicket-ajax-tipp-ajaxrequesttarget-nachtraglich-ermitteln/" title="Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln">Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/04/09/wicket-abstractevent-update/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wicket Heatmap &#8211; Ajax mit Parametern</title>
		<link>http://www.wicket-praxis.de/blog/2010/03/07/wicket-heatmap-ajax-mit-parametern/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/03/07/wicket-heatmap-ajax-mit-parametern/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 15:22:07 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Wicket]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[clickmap]]></category>
		<category><![CDATA[parameter]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=257</guid>
		<description><![CDATA[Wer wissen möchte, wohin die Nutzer in der eigenen Anwendung so klicken (z.B. auf Dinge, von denen man selbst nicht annehmen würde, das Nutzer darauf klicken), der muss jeden Mausklick des Nutzers aufzeichnen. Aus diesen Daten kann man dann ermitteln, wohin die Nutzer ihren Mauszeiger so wandern lassen. Dafür gibt es bereits Opensourcelösungen, die meist [...]]]></description>
			<content:encoded><![CDATA[<p>Wer wissen möchte, wohin die Nutzer in der eigenen Anwendung so klicken (z.B. auf Dinge, von denen man selbst nicht annehmen würde, das Nutzer darauf klicken), der muss jeden Mausklick des Nutzers aufzeichnen. Aus diesen Daten kann man dann ermitteln, wohin die Nutzer ihren Mauszeiger so wandern lassen. Dafür gibt es bereits Opensourcelösungen, die meist auf PHP basieren. Unter dem Suchbergriff <a href="http://de.wikipedia.org/wiki/Heatmap" rel="nofollow" target="_blank">Heatmap</a> wird man auch bei Google fündig. Da sich alles in diesem Blog um Java und dann noch um Wicket dreht, lag es natürlich nahe, zu prüfen, ob und wie man diese Anforderung mit Wicket realisieren kann. Dieser Beitrag wäre viel kürzer, wenn man die Frage nach dem &#8220;ob&#8221; mit nein beantworten müsste. Kommen wir also zum &#8220;wie?&#8221;.</p>
<p>Für die Umsetzung habe ich mir anfänglich einiges aus dem Beispielen aus folgendem <a href="http://blog.corunet.com/the-definitive-heatmap/">Blogbeitrag</a> entlehnt. Im Laufe der Zeit ist zwar davon nicht mehr viel zu sehen, das Grundprinzip ist aber das Gleiche geblieben.</p>
<p>Folgende Fragestellung stand am Anfang dieses Versuchs: Wie kann man mit Wicket Werte in einem AjaxRequest übergeben (z.B. die Mausposition). Die erste Idee bestand darin, ein unsichtbares Formular zu erstellen, in das man die Werte per Javascript einfügt und dieses Formular per Ajax abschickt. Das hat auch funktioniert, war aber irgendwie auch ein wenig zu aufwendig. Nach einer Reihe missglückter Versuche, den richtigen Ansatz zu finden, stellte ich diese Frage in der Wicket-Mailingliste und bekam den entscheidenen Tipp von Ernesto Reinaldo Barreiro. Es gab einen <a href="http://londonwicket.googlecode.com/files/LondonWicket-Paint.pdf" target="_blank">Vortrag</a> der <a href="http://code.google.com/p/londonwicket/" target="_blank">London Wicket User Group</a>, der dieses Problem löste. Mit dieser Vorarbeit begann ich das Thema umzusetzen. Dabei hat sich die eigene Implementierung vom Original entfernt. Hier nun Schritt für Schritt der vollständige Code:</p>
<p><strong>AbstractParameterizedDefaultAjaxBehavior</strong></p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import java.util.HashMap;</li><li>import java.util.Map;</li><li></li><li>import org.apache.wicket.Request;</li><li>import org.apache.wicket.RequestCycle;</li><li>import org.apache.wicket.ResourceReference;</li><li>import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.markup.html.IHeaderResponse;</li><li>import org.apache.wicket.util.time.Duration;</li><li></li><li>public abstract class AbstractParameterizedDefaultAjaxBehavior extends AbstractDefaultAjaxBehavior</li><li>{</li><li>&nbsp;&nbsp;static int sec=0;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;private Duration _throttleDelay;</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void renderHead(IHeaderResponse response)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.renderHead(response);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(new ResourceReference(AbstractParameterizedDefaultAjaxBehavior.class,&quot;AbstractParameterizedDefaultAjaxBehavior.js&quot;));</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void respond(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Request request = RequestCycle.get().getRequest();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String,Object&gt; map=new HashMap&lt;String, Object&gt;();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Parameter&lt;?&gt;[] parameter = getParameter();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;for (Parameter&lt;?&gt; p : parameter)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String svalue = request.getParameter(p.getName());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (svalue!=null)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object value=getComponent().getConverter(p.getType()).convertToObject(svalue, getComponent().getLocale());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(p.getName(), value);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;respond(target, new ParameterMap(map));</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public CharSequence getCallbackUrl(boolean onlyTargetActivePage)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder sb=new StringBuilder();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;sb.append(super.getCallbackUrl(onlyTargetActivePage));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Parameter&lt;?&gt;[] parameter = getParameter();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;for (Parameter&lt;?&gt; p : parameter)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(&quot;&amp;&quot;).append(p.getName()).append(&quot;='+&quot;).append(p.getJavascript()).append(&quot;+'&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return sb.toString();</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected final CharSequence getCallbackScript()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (_throttleDelay!=null)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return throttleScript(super.getCallbackScript(),&quot;thw&quot;+(sec++),_throttleDelay);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return super.getCallbackScript();</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected static class Parameter&lt;T&gt;</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;String _name;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;String _javascript;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;T&gt; _type;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected Parameter(String name,Class&lt;T&gt; type,String javascript)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_name=name;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_type=type;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_javascript=javascript;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected String getName()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _name;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected String getJavascript()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _javascript;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected Class&lt;T&gt; getType()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _type;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected static &lt;T&gt; Parameter&lt;T&gt; of(String name,Class&lt;T&gt; type,String javascript)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new Parameter&lt;T&gt;(name, type, javascript);</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected static class ParameterMap</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String, Object&gt; _map;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected ParameterMap(Map&lt;String, Object&gt; map)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_map=map;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public &lt;T&gt; T getValue(Parameter&lt;T&gt; parameter)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return (T) _map.get(parameter.getName());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public final AbstractParameterizedDefaultAjaxBehavior setThrottleDelay(Duration throttleDelay)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_throttleDelay=throttleDelay;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return this;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected abstract void respond(AjaxRequestTarget target,ParameterMap parameterMap);</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected abstract Parameter&lt;?&gt;[] getParameter();</li><li></li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 257); </script></p>
<p>Die drei wichtigsten Bestandteile dieser Klasse sind folgende: Die Klasse Parameter definiert den Namen, den Typ, und das Javascript, das für das Ermitteln des Wertes im Browser aufgerufen muss. Die Methode respond(AjaxRequestTarget) liest die Werte aus dem Request aus, konvertiert diese in den gewünschen Typ und ruf damit eine zu überschreibende Methode auf. Die Methode getCallbackUrl() liefert das Javascript-Fragment für die Url, die dann per Ajax aufgerufen wird.</p>
<p>Um die Position des Mauszeigers ermitteln zu können, muss man sich mit einer eigenen Funktion für so einen Event registrieren. Damit mehr als eine Funktion auf so einen Event reagieren kann, sollte man die Funktion, die davor registriert war, ebenfalls aufrufen. Um für diese Problematik, die vermutlich in allen abgeleiteten Klassen vorhanden ist, besser lösen zu können, binden wir automatisch eine hilfreiche Javascript-Klasse ein.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Javascript"><div class="devcodeoverflow"><div id="devfmt_ajax_2_257"><ol><li>Callback = {</li><li>&nbsp;&nbsp;create: function(oldCallback,newCallback)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return function(a,b,c,d,e,f)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (oldCallback) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oldCallback(a,b,c,d,e,f);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newCallback(a,b,c,d,e,f);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;},</li><li>};</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 257); </script></p>
<p>Der Code sieht etwas merkwürdig aus. Das liegt an folgenden Gründen: zum einen stehe ich mit Javascript immer noch auf Kriegsfuß (mit Wicket kann man den Javascript-Teil sehr schön verstecken) und habe daher keine geeignete Lösung gefunden, mit der es mir möglich war, alle Argumente des Funktionsaufrufs an die zwei Funktionen weiterzureichen. Da es aber Javascript egal ist, mit wie vielen Parametern man eine Funktion aufruft, werden auf diese Weise bis zu 6 Übergabeparameter weitergereicht. Für Hinweise an dieser Stelle bin ich extrem dankbar.</p>
<p><strong>WicketWindowJavascript</strong></p>
<p>Für vieles bringt Wicket bereits fertige Implementierungen mit. Allerdings verstecken sich diese manchmal an unauffälligen Stellen. Für das Ermitteln des sichtbaren Bereichs fand ich die nötigen Javascript-Funktionen bei der ModelWindow-Klasse. Da ich nicht das vollständige ModalWindow-Javascript einbinden wollte, habe ich diese allgemeinen Funktionen in eine eigene Resource verpackt.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_3_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import org.apache.wicket.ResourceReference;</li><li></li><li>public class WicketWindowJavascript</li><li>{</li><li>&nbsp;&nbsp;private WicketWindowJavascript()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public static final ResourceReference RESOURCE=new ResourceReference(WicketWindowJavascript.class,&quot;WicketWindowJavascript.js&quot;);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 257); </script></p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Javascript"><div class="devcodeoverflow"><div id="devfmt_ajax_4_257"><ol><li>// aus der Datei modal.js zur Klasse ModalWindow</li><li></li><li>if (typeof(Wicket.Window) == &quot;undefined&quot;) {</li><li>&nbsp;&nbsp;Wicket.Window = { };</li><li>}</li><li></li><li>/**</li><li> * Returns the height of visible area.</li><li> */</li><li>Wicket.Window.getViewportHeight = function() {</li><li>&nbsp;&nbsp;if (window.innerHeight != window.undefined) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return window.innerHeight;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;if (document.compatMode == 'CSS1Compat') </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return document.documentElement.clientHeight;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;if (document.body) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return document.body.clientHeight;</li><li>&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;return window.undefined; </li><li>}</li><li></li><li>/**</li><li> * Returns the width of visible area.</li><li> */</li><li>Wicket.Window.getViewportWidth =&nbsp;&nbsp;function() {</li><li>&nbsp;&nbsp;if (window.innerWidth != window.undefined) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return window.innerWidth;</li><li>&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;if (document.compatMode == 'CSS1Compat') </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return document.documentElement.clientWidth; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;if (document.body) </li><li>&nbsp;&nbsp;&nbsp;&nbsp;return document.body.clientWidth;</li><li>&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;return window.undefined;</li><li>}</li><li></li><li>/**</li><li> * Returns the horizontal scroll offset</li><li> */</li><li>Wicket.Window.getScrollX = function() {</li><li>&nbsp;&nbsp;var iebody = (document.compatMode &amp;&amp; document.compatMode != &quot;BackCompat&quot;) ? document.documentElement : document.body&nbsp;&nbsp;</li><li>&nbsp;&nbsp;return document.all? iebody.scrollLeft : pageXOffset</li><li>}</li><li></li><li>/**</li><li> * Returns the vertical scroll offset</li><li> */</li><li>Wicket.Window.getScrollY = function() {</li><li>&nbsp;&nbsp;var iebody = (document.compatMode &amp;&amp; document.compatMode != &quot;BackCompat&quot;) ? document.documentElement : document.body&nbsp;&nbsp;</li><li>&nbsp;&nbsp;return document.all? iebody.scrollTop : pageYOffset</li><li>}</li><li></li><li></li><li>/**</li><li> * Returns element offset</li><li> */</li><li>Wicket.Window.getXYOffset = function(obj)</li><li>{</li><li>&nbsp;&nbsp;var curleft = 0;</li><li>&nbsp;&nbsp;var curtop = 0;</li><li>&nbsp;&nbsp;if (obj.offsetParent)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;while (obj.offsetParent)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curleft += obj.offsetLeft;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curtop += obj.offsetTop;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;obj = obj.offsetParent;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;else</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (obj.x)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curleft += obj.x;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (obj.y)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curtop += obj.y;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;if (Wicket.Browser.isIE())</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;bodyElement=document.getElementsByTagName('body')[0];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;// In IE there's a default margin in the page body. If margin's not defined,</li><li>&nbsp;&nbsp;&nbsp;&nbsp;// use defaults</li><li>&nbsp;&nbsp;&nbsp;&nbsp;var marginLeftExplorer&nbsp;&nbsp;= parseInt(bodyElement.style.marginLeft);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;var marginTopExplorer&nbsp;&nbsp; = parseInt(bodyElement.style.marginTop);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;/* assume default 10px/15px margin in explorer */</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (isNaN(marginLeftExplorer)) {marginLeftExplorer=10;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (isNaN(marginTopExplorer)) {marginTopExplorer=15;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;curleft=curleft+marginLeftExplorer;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;curtop=curtop+marginTopExplorer;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;return [curleft,curtop];</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(4, 257); </script></p>
<p>Hinzugefügt habe ich nur die Methode Wicket.Window.getXYOffset(), um den Offset für ein bestimmtes oder das erste Kindelement der Seite ermitteln zu können. Eine Klasse, die diese Methoden benötigt, muss die Resource entsprechend einbinden.</p>
<p><strong>WindowResizeBehavior</strong></p>
<p>Um die Heatmap in der richtigen Größe zeichnen zu können, benötigen wir Informationen über die Dimensionen des sichtbaren Bereichs. Für window.onresize wird ein neuer Callback registriert. Die Werte können über die ensprechend Wicket.Window-Funktionen ermittelt werden. Daher wird nicht nur der Callback registiert, sondern die Funktion nach dem Laden der Seite direkt aufgerufen. Auf diese Weise bekommen wir die Informationen über den sichtbaren Bereich nicht erst, wenn der Nutzer die Fenstergröße verändert.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_5_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import org.apache.wicket.ResourceReference;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.markup.html.IHeaderResponse;</li><li>import org.apache.wicket.util.time.Duration;</li><li></li><li>public abstract class WindowResizeBehavior extends AbstractParameterizedDefaultAjaxBehavior</li><li>{</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; WIDTH=of(&quot;width&quot;, Integer.class, &quot;Wicket.Window.getViewportWidth()&quot;);</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; HEIGHT=of(&quot;height&quot;, Integer.class, &quot;Wicket.Window.getViewportHeight()&quot;);</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void renderHead(IHeaderResponse response)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.renderHead(response);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(WicketWindowJavascript.RESOURCE);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderOnDomReadyJavascript(getJavascript());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderOnDomReadyJavascript(getCallbackScript().toString());</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected final String getJavascript()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return &quot;window.onresize = Callback.create(window.onresize,function () {&quot;+getCallbackScript()+&quot;});&quot;;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected final Parameter&lt;?&gt;[] getParameter()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new Parameter&lt;?&gt;[]{ WIDTH,HEIGHT};</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void respond(AjaxRequestTarget target, ParameterMap parameterMap)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;onResize(target, parameterMap.getValue(WIDTH), parameterMap.getValue(HEIGHT));&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected abstract void onResize(AjaxRequestTarget target, int width, int height);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(5, 257); </script></p>
<p><strong>ElementOffsetBehavior</strong></p>
<p>Die Bestimmung der richtigen Mauskoordinaten gestaltet sich insofern schwierig, als das nicht jede Webseite bei jeder Fenstergröße gleich aussieht. Damit die Koordinaten bei der Auswertung verwendbar bleiben, berechnen wir die Position in Relation zu einem Element, dass den Rahmen der Seite darstellen sollte (z.B. das erste div-Tag innerhalb des body-Tags, dass auf eine feste Breite gesetzt wurde und im sichtbaren Bereich zentriert dargestellt wird).</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_6_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import org.apache.wicket.ResourceReference;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.markup.html.IHeaderResponse;</li><li></li><li>import de.wicketpraxis.web.blog.pages.questions.ajax.parameter.AbstractParameterizedDefaultAjaxBehavior.Parameter;</li><li></li><li>public abstract class ElementOffsetBehavior extends AbstractParameterizedDefaultAjaxBehavior</li><li>{</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; X_OFFSET=of(&quot;xOffset&quot;, Integer.class, &quot;xOffset&quot;);</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; Y_OFFSET=of(&quot;yOffset&quot;, Integer.class, &quot;yOffset&quot;);</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;private String _contentId;</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void renderHead(IHeaderResponse response)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.renderHead(response);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(WicketWindowJavascript.RESOURCE);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(new ResourceReference(ElementOffsetBehavior.class,&quot;ElementOffsetBehavior.js&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderOnDomReadyJavascript(getJavascript());</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public ElementOffsetBehavior()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public ElementOffsetBehavior(String contentId)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_contentId=contentId;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected final String getJavascript()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (_contentId!=null) return &quot;ElementOffsetBehavoir.init(function (xOffset,yOffset) {&quot;+getCallbackScript()+&quot;},'&quot;+_contentId+&quot;');&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return &quot;ElementOffsetBehavoir.init(function (xOffset,yOffset) {&quot;+getCallbackScript()+&quot;});&quot;;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected final Parameter&lt;?&gt;[] getParameter()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new Parameter&lt;?&gt;[]{ X_OFFSET,Y_OFFSET};</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void respond(AjaxRequestTarget target, ParameterMap parameterMap)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;onOffset(target, parameterMap.getValue(X_OFFSET), parameterMap.getValue(Y_OFFSET));&nbsp;&nbsp; </li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected abstract void onOffset(AjaxRequestTarget target, int xOffset, int yOffset);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(6, 257); </script></p>
<p>Im Gegensatz zum letzten Behavior sind wir in diesem Fall auf etwas mehr Javascript angewiesen.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Javascript"><div class="devcodeoverflow"><div id="devfmt_ajax_7_257"><ol><li>ElementOffsetBehavoir =</li><li>{</li><li>&nbsp;&nbsp;init : function(callback, contentId)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;function Listener(callback, contentId)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.xOffset = 0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.yOffset = 0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement = null;</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// function(xOffset,yOffset)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.onOffsetChanged = callback;</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.updateOffsets = function()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var offsets = Wicket.Window.getXYOffset(this.firstElement);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.xOffset = offsets[0];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.yOffset = offsets[1];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.onOffsetChanged(this.xOffset, this.yOffset);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var bodyElement = document.getElementsByTagName('body')[0];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement = bodyElement.childNodes[1];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (contentId != null)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement = document.getElementById(contentId);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;var listener = new Listener(callback, contentId);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;listener.updateOffsets();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;window.onresize = Callback.create(window.onresize, function()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.updateOffsets();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(7, 257); </script></p>
<p>Der Listener wird über die init-Methode initialisiert und wird ebenfalls aufgerufen, wenn die Fenstergröße verändert wurde. Außerdem wird die updateOffsets()-Methode bereits bei der Initialisierung aufgerufen. Somit ist auch in diesem Fall der Offset eines Elements bekannt.</p>
<p><strong>PageMouseClickBehavior</strong></p>
<p>Das letzte Behavior ist gleichzeitig das aufwendigste. In diesem Fall muss nicht nur die Position des Klicks ermittelt werden, sondern gleichzeitig in Relation zu einem Element gebracht werden. Auf diese Weise kommen die Koordinaten schon passend an und können z.B. auch negative Werte annehmen.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_8_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import org.apache.wicket.Request;</li><li>import org.apache.wicket.ResourceReference;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.markup.html.IHeaderResponse;</li><li></li><li>public abstract class PageMouseClickBehavior extends AbstractParameterizedDefaultAjaxBehavior</li><li>{</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; MOUSE_X=of(&quot;x&quot;, Integer.class, &quot;x&quot;);</li><li>&nbsp;&nbsp;static final Parameter&lt;Integer&gt; MOUSE_Y=of(&quot;y&quot;, Integer.class, &quot;y&quot;);</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;String _contentId;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public PageMouseClickBehavior()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public PageMouseClickBehavior(String contentId)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;_contentId=contentId;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;public void renderHead(IHeaderResponse response)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super.renderHead(response);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(WicketWindowJavascript.RESOURCE);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderJavascriptReference(new ResourceReference(PageMouseClickBehavior.class,&quot;PageMouseClickBehavior.js&quot;));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;response.renderOnDomReadyJavascript(getJavascript());</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected String getJavascript()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;if (_contentId!=null) return &quot;PageMouseClickBehavoir.init(function (x,y,xOffset,yOffset) {&quot;+getCallbackScript()+&quot;},'&quot;+_contentId+&quot;');&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return &quot;PageMouseClickBehavoir.init(function (x,y,xOffset,yOffset) {&quot;+getCallbackScript()+&quot;});&quot;;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected Parameter&lt;?&gt;[] getParameter()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return new Parameter&lt;?&gt;[] { MOUSE_X, MOUSE_Y };</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;protected void respond(AjaxRequestTarget target, ParameterMap map)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;onClick(target, map.getValue(MOUSE_X), map.getValue(MOUSE_Y));&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;protected abstract void onClick(AjaxRequestTarget target, int x, int y);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(8, 257); </script></p>
<p>Das dazugehörige Javascript kümmert sich um die Verarbeitung:</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Javascript"><div class="devcodeoverflow"><div id="devfmt_ajax_9_257"><ol><li>PageMouseClickBehavoir = </li><li>{</li><li>&nbsp;&nbsp;init: function(callback,contentId)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;function Listener(callback,contentId)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.xOffset=0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.yOffset=0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement=null;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// function(x,y)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.onMouseEvent=callback;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.mouseEvent= function(e)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempX=0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempY=0;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Wicket.Browser.isIE() || Wicket.Browser.isGecko())</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempX = e.clientX + Wicket.Window.getScrollX();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempY = e.clientY + Wicket.Window.getScrollY();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempX = e.pageX</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempY = e.pageY</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempX-=this.xOffset;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempY-=this.yOffset;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.onMouseEvent(tempX,tempY);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.updateOffsets=function()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var offsets=Wicket.Window.getXYOffset(this.firstElement);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.xOffset=offsets[0];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.yOffset=offsets[1];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var bodyElement=document.getElementsByTagName('body')[0];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement=bodyElement.childNodes[1];</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (contentId!=null)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.firstElement=document.getElementById(contentId);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.updateOffsets();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;var listener=new Listener(callback,contentId);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;document.onmousedown=Callback.create(document.onmousedown,function(e)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.mouseEvent(e)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;&nbsp;&nbsp;window.onresize=Callback.create(window.onresize,function()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.updateOffsets();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;},</li><li>}</li><li></li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(9, 257); </script></p>
<p>Sobald der Nutzer klickt (auch wenn es eigentlich nichts klickbares gibt), wird eine Request an die Anwendung gesendet. Diese Behavior können wir nun in die Anwendung einbauen, um die Mausklicks der Nutzer aufzuzeichnen.</p>
<p><strong>Die Anwendung</strong></p>
<p>In unserer Beispielanwendung werfen wir alles in einen Topf. Wir zeichnen alle Mausklicks auf und aktualisieren dann die Heatmap.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_10_257"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.parameter;</li><li></li><li>import java.awt.AlphaComposite;</li><li>import java.awt.BasicStroke;</li><li>import java.awt.Color;</li><li>import java.awt.Composite;</li><li>import java.awt.Graphics2D;</li><li>import java.awt.RenderingHints;</li><li>import java.io.Serializable;</li><li>import java.util.ArrayList;</li><li>import java.util.List;</li><li></li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.markup.html.WebMarkupContainer;</li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.markup.html.image.Image;</li><li>import org.apache.wicket.markup.html.image.NonCachingImage;</li><li>import org.apache.wicket.markup.html.image.resource.DynamicImageResource;</li><li>import org.apache.wicket.markup.html.image.resource.RenderedDynamicImageResource;</li><li>import org.apache.wicket.markup.html.panel.FeedbackPanel;</li><li>import org.apache.wicket.protocol.http.WebResponse;</li><li>import org.apache.wicket.util.time.Duration;</li><li></li><li>public class HeatMapPage extends WebPage</li><li>{</li><li>&nbsp;&nbsp;List&lt;Pos&gt; _points=new ArrayList&lt;Pos&gt;();</li><li>&nbsp;&nbsp;int _xOffset=0;</li><li>&nbsp;&nbsp;int _yOffset=0;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public HeatMapPage()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;final FeedbackPanel feedbackPanel = new FeedbackPanel(&quot;feedback&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;feedbackPanel.setOutputMarkupId(true);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(feedbackPanel);</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;final WebMarkupContainer box=new WebMarkupContainer(&quot;box&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;final ClickMap imageResource = new ClickMap(100, 100);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;final Image image = new NonCachingImage(&quot;map&quot;,imageResource);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;box.setOutputMarkupId(true);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;box.add(image);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(box);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new ElementOffsetBehavior(&quot;#content&quot;)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected void onOffset(AjaxRequestTarget target, int xOffset, int yOffset)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info(&quot;Offset: &quot;+xOffset+&quot;,&quot;+yOffset);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_xOffset=xOffset;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_yOffset=yOffset;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageResource.invalidate();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(feedbackPanel);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(box);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}.setThrottleDelay(Duration.milliseconds(250)));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new PageMouseClickBehavior(&quot;#content&quot;)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected void onClick(AjaxRequestTarget target, int x, int y)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info(&quot;Clicked: &quot;+x+&quot;,&quot;+y);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_points.add(new Pos(x,y));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageResource.invalidate();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(box);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(feedbackPanel);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}.setThrottleDelay(Duration.milliseconds(50)));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new WindowResizeBehavior()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected void onResize(AjaxRequestTarget target, int width, int height)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;info(&quot;Size changed: &quot;+width+&quot;,&quot;+height);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageResource.setWidth(width);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageResource.setHeight(height);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageResource.invalidate();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(feedbackPanel);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target.addComponent(box);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}.setThrottleDelay(Duration.milliseconds(250)));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;class ClickMap extends RenderedDynamicImageResource</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public ClickMap(int width, int height)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(width, height,&quot;jpg&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setCacheable(false);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;protected boolean render(Graphics2D graphics)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.setBackground(new Color(255,255,255));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.setColor(new Color(0,0,0,50));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.clearRect(0, 0, getWidth(), getHeight());</li><li> </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (Pos p : _points)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;graphics.fillArc(_xOffset+p.getX()-5, _yOffset+p.getY()-5, 9, 9, 0, 360);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;static class Pos implements Serializable</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;int _x;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;int _y;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public Pos(int x, int y)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_x = x;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_y = y;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public int getX()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _x;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;public int getY()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _y;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(10, 257); </script></p>
<p>Im Markup müssen wir dann nur das Image hinter der Seite platzieren und schon stimmen Mausklick und Heatmap überein.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_11_257"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;Heatmap Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div id=&quot;#content&quot; style=&quot;width:800px; margin:auto; border:1px solid #888;&quot;&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div wicket:id=&quot;feedback&quot;&gt;&lt;/div&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div wicket:id=&quot;box&quot; style=&quot;z-index: -1; position: absolute; top: 0px;left: 0px;&quot;&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;img wicket:id=&quot;map&quot;&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(11, 257); </script></p>
<p>In diesem Beispiel haben ich den Rahmen auf eine Breite von 800 Pixeln gesetzt und zentriert. Trotzdem werden die Mausklicks immer korrekt angezeigt.</p>
<p><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/wicket-heatmap-ajax.jpg"><img class="aligncenter size-medium wp-image-262" title="wicket-heatmap-ajax" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/wicket-heatmap-ajax-450x156.jpg" alt="wicket-heatmap-ajax" width="450" height="156" /></a></p>
<p>Wie man sehen kann, ist die Interaktion von Wicket mit Ereignissen, die durch Javascript ausgelöst werden, ohne weiteres möglich. Dabei können diese Komponenten ohne weiteres in beliebigen Anwendungen benutzt werden, ohne das sich ein anderer Entwickler mit den Implementierungsdetails beschäftigen muss. Allerdings hätte ich mir gewünscht, dass die Parameterisierung von Ajax-Aufrufen bereits in den Kern von Wicket integriert wäre.</p>
<p>Viel Spass mit dem ausprobieren:)</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>9. April 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/04/09/wicket-abstractevent-update/" title="Wicket &#8211; AbstractEvent Update">Wicket &#8211; AbstractEvent Update</a></li><li>3. März 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/03/03/wicket-extensions-anpassungen-am-modalwindow/" title="Wicket Extensions &#8211; Anpassungen am ModalWindow">Wicket Extensions &#8211; Anpassungen am ModalWindow</a></li><li>23. Dezember 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/12/23/wicket-ajax-tipp-ajaxrequesttarget-nachtraglich-ermitteln/" title="Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln">Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/03/07/wicket-heatmap-ajax-mit-parametern/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wicket Extensions &#8211; Anpassungen am ModalWindow</title>
		<link>http://www.wicket-praxis.de/blog/2010/03/03/wicket-extensions-anpassungen-am-modalwindow/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/03/03/wicket-extensions-anpassungen-am-modalwindow/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 07:42:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Technologie]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[modalwindow]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=249</guid>
		<description><![CDATA[Wicket liefert im Bereich Extensions Komponenten mit, die zwar nicht direkt zum Kern von Wicket gehören, die aber fast so häufig wie die Standardwicketkomponenten zum Zuge kommen. Im folgenden Beitrag zeige ich, wie man die ModalWindow-Komponente benutzen kann und wie man die Darstellung an eigene Wünsche anpasst. Als erstes benötigen wir eine Komponente, die durch [...]]]></description>
			<content:encoded><![CDATA[<p>Wicket liefert im Bereich Extensions Komponenten mit, die zwar nicht direkt zum Kern von Wicket gehören, die aber fast so häufig wie die Standardwicketkomponenten zum Zuge kommen. Im folgenden Beitrag zeige ich, wie man die ModalWindow-Komponente benutzen kann und wie man die Darstellung an eigene Wünsche anpasst. Als erstes benötigen wir eine Komponente, die durch das ModalWindow angezeigt werden soll.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_1_249"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.modal;</li><li></li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.ajax.markup.html.AjaxLink;</li><li>import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;</li><li>import org.apache.wicket.markup.html.panel.Panel;</li><li></li><li>public abstract class AbstractModalClosePanel extends Panel</li><li>{</li><li>&nbsp;&nbsp;public AbstractModalClosePanel(ModalWindow modalWindow)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super(modalWindow.getContentId());</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new AjaxLink&lt;Void&gt;(&quot;link&quot;)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AbstractModalClosePanel.this.onClick(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public abstract void onClick(AjaxRequestTarget target);</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(1, 249); </script></p>
<p>Die ModalWindow-Komponente kann nur eine andere Komponente anzeigen. Daher ist die Komponenten-ID fest definiert. Daher macht es Sinn, statt einer eigenen ID einfach das ModalWindow, in dem die Komponente angezeigt werden soll als Parameter zu übergeben. Damit diese Komponente auch eine Funktion bereitstellt, fügen wir einen Link hinzu. Wichtig: Wenn man Formulare benutzen möchte, muss man diese bei Anzeige durch ein ModalWindow per Ajax absenden.</p>
<p>Das Markup der Komponente ist wenig überraschend:<br />
<!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_2_249"><ol><li>&lt;wicket:panel&gt;</li><li>&nbsp;&nbsp;&lt;div&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Nothing to hide:)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;a wicket:id=&quot;link&quot;&gt;Link&lt;/a&gt;</li><li>&nbsp;&nbsp;&lt;/div&gt;</li><li>&lt;/wicket:panel&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(2, 249); </script></p>
<p>Die ModalWindow-Komponente unterscheidet sich von anderen Komponenten in einem wesentlichen Punkt. Die Darstellung wird nicht durch ein Markup realisiert, dass man überschreiben könnte. Der Rahmen für das Fenster wird per Javascript erzeugt. Um das Aussehen der Komponente anzupassen müssen wir also etwas tiefer in die Trickkiste greifen.</p>
<p>In diesem Beispiel nehmen wir Veränderungen an verschiedenen Stellen vor. Fangen wir mit den Grafiken für den Rahmen an. Der Einfachheit halber verändere ich nur die Farbwirkung aber nicht die Dimensionen, so dass ich die vorhandenen Grafiken (die man sich aus dem wicket-extension.jar extrahieren kann) nur leicht verändere:</p>
<p><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-1-alpha.png"><img class="alignnone size-full wp-image-251" title="frame-custom-1-alpha" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-1-alpha.png" alt="frame-custom-1-alpha" width="100" height="100" /></a><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-1-ie.png"><img class="alignnone size-full wp-image-252" title="frame-custom-1-ie" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-1-ie.png" alt="frame-custom-1-ie" width="100" height="100" /></a><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-2-alpha.png"><img class="alignnone size-full wp-image-253" title="frame-custom-2-alpha" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-2-alpha.png" alt="frame-custom-2-alpha" width="20" height="100" /></a><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-2-ie.png"><img class="alignnone size-full wp-image-254" title="frame-custom-2-ie" src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/frame-custom-2-ie.png" alt="frame-custom-2-ie" width="20" height="100" /></a></p>
<p>Es gibt zwei Grafiken, wobei es für jede noch eine Version für den InternetExplorer gibt, die auf transparente Schatten verzichtet (der InternetExplorer hat da Schwierigkeiten, ähm.. nicht nur da). Wie man sieht befinden sich die Grafikinformationen für die Ränder, Ecken und Buttons in einer Grafik. Das Stylesheet sorgt dafür, dass an der richtigen Stelle die richtige Grafik eingeblendet wird. Daher müssen wir eine eigene Stylesheet-Datei einbinden, die unsere Anpassungen wiederspiegelt. Auch an dieser Stelle ist es sinnvoll, sich den Inhalt der ModalWindow-eigenen Stylesheet-Datei anzuschauen.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="CSS"><div class="devcodeoverflow"><div id="devfmt_ajax_3_249"><ol><li>div.wicket-modal div.w_content_3</li><li>{</li><li>&nbsp;&nbsp;border:0px;</li><li>}</li><li></li><li>div.wicket-modal div.w_caption</li><li>{</li><li>&nbsp;&nbsp;background-color: inherit;</li><li>}</li><li></li><li>div.wicket-modal a.w_close {&nbsp;&nbsp;</li><li>&nbsp;&nbsp;top: 3px;</li><li>}</li><li></li><li>div.wicket-modal div.custom div.w_left,</li><li>div.wicket-modal div.custom div.w_right {</li><li>&nbsp;&nbsp;background-image: url('frame-custom-2-alpha.png'); </li><li>&nbsp;&nbsp;_background-image: url('frame-custom-2-ie.png');</li><li>}</li><li></li><li></li><li>div.wicket-modal div.custom div.w_top,</li><li>div.wicket-modal div.custom div.w_bottom,</li><li>div.wicket-modal div.custom div.w_topLeft,</li><li>div.wicket-modal div.custom div.w_topRight,</li><li>div.wicket-modal div.custom div.w_bottomRight,</li><li>div.wicket-modal div.custom div.w_bottomLeft,</li><li>div.wicket-modal div.custom a.w_close {</li><li>&nbsp;&nbsp;background-image: url('frame-custom-1-alpha.png'); </li><li>&nbsp;&nbsp;_background-image: url('frame-custom-1-ie.png');</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(3, 249); </script></p>
<p>Wie ich bereits weiter oben erwähnt habe, wird das Html für den Rahmen nicht wie üblich sondern per Javascript erzeugt. Da wir auch an dieser Stelle Anpassungen vornehmen wollen, müssen wir die entsprechende Funktion überschreiben:</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Javascript"><div class="devcodeoverflow"><div id="devfmt_ajax_4_249"><ol><li>Wicket.Window.getMarkup = function(idWindow, idClassElement, idCaption, idContent, idTop, idTopLeft, idTopRight, idLeft, idRight, idBottomLeft, idBottomRight, idBottom, idCaptionText, isFrame) {</li><li>&nbsp;&nbsp;var s =</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;wicket-modal\&quot; id=\&quot;&quot;+idWindow+&quot;\&quot; style=\&quot;top: 10px; left: 10px; width: 100px;\&quot;&gt;&lt;form style='background-color:transparent;padding:0px;margin:0px;border-width:0px;position:static'&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div id=\&quot;&quot;+idClassElement+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_caption\&quot;&nbsp;&nbsp;id=\&quot;&quot;+idCaption+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;a class=\&quot;w_close\&quot; href=\&quot;#\&quot;&gt;&lt;/a&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;span id=\&quot;&quot;+idCaptionText+&quot;\&quot; class=\&quot;w_captionText\&quot;&gt;&lt;/span&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_top_1\&quot;&gt;&quot;+</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_topLeft\&quot; id=\&quot;&quot;+idTopLeft+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_topRight\&quot; id=\&quot;&quot;+idTopRight+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_top\&quot; id='&quot;+idTop+&quot;'&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_left\&quot; id='&quot;+idLeft+&quot;'&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_right_1\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_right\&quot; id='&quot;+idRight+&quot;'&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_content_1\&quot; onmousedown=\&quot;if (Wicket.Browser.isSafari()) { event.ignore = true; }&nbsp;&nbsp;else { Wicket.stopEvent(event); } \&quot;&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_content_2\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_content_3\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_content\&quot;&gt;&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (isFrame) {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (Wicket.Browser.isIELessThan7() || !Wicket.Browser.isIE()) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s+= &quot;&lt;iframe src='\/\/:' frameborder=\&quot;0\&quot; id='&quot;+idContent+&quot;' allowtransparency=\&quot;false\&quot; style=\&quot;height: 200px\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/iframe&gt;&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s+= &quot;&lt;iframe src='about:blank' frameborder=\&quot;0\&quot; id='&quot;+idContent+&quot;' allowtransparency=\&quot;false\&quot; style=\&quot;height: 200px\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/iframe&gt;&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s+=</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div id='&quot;+idContent+&quot;'&gt;&lt;/div&gt;&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s+=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li></li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_bottom_1\&quot; id=\&quot;&quot;+idBottom+&quot;\&quot;&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_bottomRight\&quot;&nbsp;&nbsp;id=\&quot;&quot;+idBottomRight+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_bottomLeft\&quot; id=\&quot;&quot;+idBottomLeft+&quot;\&quot;&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;div class=\&quot;w_bottom\&quot; id=\&quot;&quot;+idBottom+&quot;\&quot;&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li></li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li><li></li><li></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/div&gt;&quot;+</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&quot;&lt;/form&gt;&lt;/div&gt;&quot;;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return s;</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(4, 249); </script></p>
<p>Da die Javascript-Datei der ModalWindow-Komponente automatisch eingebunden wird (da von dieser Klasse abgeleitet wird), muss ich nur diese eine Funktion überschreiben. Ich habe mich in diesem Beispiel darauf beschränkt, den Bereich für die Überschrift und den CloseButton oberhalb des Rahmens darstellen zu lassen (Das div mit der Klasse &#8220;w_caption&#8221;).</p>
<p>In unsere Komponentenklasse betreten wir nun wieder vertrautes Terrain. Wir leiten von ModalWindow ab und passen ein paar grundsätzliche Dinge an:</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_5_249"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.modal;</li><li></li><li>import org.apache.wicket.ResourceReference;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;</li><li>import org.apache.wicket.markup.html.CSSPackageResource;</li><li>import org.apache.wicket.markup.html.JavascriptPackageResource;</li><li>import org.apache.wicket.markup.html.resources.CompressedResourceReference;</li><li>import org.apache.wicket.markup.html.resources.JavascriptResourceReference;</li><li></li><li>public class CustomModalWindow extends ModalWindow</li><li>{</li><li>&nbsp;&nbsp;private static ResourceReference CSS = new CompressedResourceReference(CustomModalWindow.class, &quot;styles/custom-modal.css&quot;);</li><li>&nbsp;&nbsp;private static ResourceReference JAVASCRIPT = new JavascriptResourceReference(CustomModalWindow.class,&nbsp;&nbsp;&quot;styles/custom-modal.js&quot;);</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;public CustomModalWindow(String id)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;super(id);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setCssClassName(&quot;custom&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(JavascriptPackageResource.getHeaderContribution(JAVASCRIPT));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(CSSPackageResource.getHeaderContribution(CSS));</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setCloseButtonCallback(new CloseButtonCallback()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public boolean onCloseButtonClicked(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return onCloseClicked(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setWindowClosedCallback(new WindowClosedCallback()</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClose(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CustomModalWindow.this.onClose(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;protected void onClose(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;}</li><li></li><li>&nbsp;&nbsp;protected boolean onCloseClicked(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;return true;</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(5, 249); </script></p>
<p>Wir setzen die Css-Klasse für den Rahmen, fügen unsere CSS- und Javascript-Anpassungen hinzu (da unsere Referenzen nach den ModalWindow-Referenzen eingebunden werden, überschreiben wir sowohl die CSS-Definitionen als auch die Javascript-Funktionen). Außerdem fügen wir zwei Callbacks hinzu, die auf einen Klick auf das Schließen-Symbol reagieren. Für diese Komponenten benötigen wir keine eigene Markup-Datei.</p>
<p>Jetzt möchten wir diese Komponente endlich verwenden. Dazu legen wir eine Seitenklasse an:</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="Java(TM) 2 Platform Standard Edition 5.0"><div class="devcodeoverflow"><div id="devfmt_ajax_6_249"><ol><li>package de.wicketpraxis.web.blog.pages.questions.ajax.modal;</li><li></li><li>import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;</li><li>import org.apache.wicket.ajax.AjaxRequestTarget;</li><li>import org.apache.wicket.ajax.markup.html.AjaxLink;</li><li>import org.apache.wicket.markup.html.WebPage;</li><li>import org.apache.wicket.util.time.Duration;</li><li></li><li>public class ModalWindowPage extends WebPage</li><li>{</li><li>&nbsp;&nbsp;public ModalWindowPage()</li><li>&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;final CustomModalWindow modalWindow = new CustomModalWindow(&quot;modal&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.setTitle(&quot;Popup&quot;);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.setInitialWidth(400);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.setInitialHeight(400);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.setResizable(true);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.setContent(new AbstractModalClosePanel(modalWindow)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.close(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(modalWindow);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new AjaxLink&lt;Void&gt;(&quot;open&quot;)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onClick(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.show(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;add(new AbstractAjaxTimerBehavior(Duration.seconds(2))</li><li>&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected void onTimer(AjaxRequestTarget target)</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modalWindow.show(target);</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop();</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</li><li>&nbsp;&nbsp;&nbsp;&nbsp;});</li><li>&nbsp;&nbsp;}</li><li>}</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(6, 249); </script></p>
<p>Wir erstellen eine Instanz unsere ModalWindow-Komponente und fügen ein Panel als Content-Element hinzu. Dabei wird beim Klick auf den Link innerhalb der Komponente das Fenster geschlossen. Da das ModalWindow per Ajax geöffnet und geschlossen werden muss, benötigen wir zum Öffnen einen AjaxLink. Wenn man dem Nutzer das Fenster bereits beim Aufruf der Seite einmalig anzeigen möchte, kann man sich damit behelfen, das man eine Instanz AbstractAjaxTimerBehavior-Klasse erstellt und die Zeit entsprechend klein wählt (weniger als die zwei Sekunden aus diesem Beispiel). In der onTimer()-Methode führt der Aufruf von stop() dazu, dass die Methode nach der abgelaufenen Zeit nicht noch einmal aufgerufen wird.</p>
<p><!--DEVFMTCODE--><pre class="devcodeblock" title="HTML"><div class="devcodeoverflow"><div id="devfmt_ajax_7_249"><ol><li>&lt;html&gt;</li><li>&nbsp;&nbsp;&lt;head&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;ModalWindow Page&lt;/title&gt;</li><li>&nbsp;&nbsp;&lt;/head&gt;</li><li>&nbsp;&nbsp;&lt;body&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;div wicket:id=&quot;modal&quot;&gt;&lt;/div&gt;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;a wicket:id=&quot;open&quot;&gt;Open&lt;/a&gt;</li><li>&nbsp;&nbsp;&lt;/body&gt;</li><li>&lt;/html&gt;</li></ol></div></div></pre><!--END_DEVFMTCODE--><script> devfmt_addAjaxBuffer(7, 249); </script></p>
<p>Und so sieht das Ergebnis aus:</p>
<p><a href="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/wicket-custom-modalwindow.jpg"><img src="http://www.wicket-praxis.de/blog/wp-content/uploads/2010/03/wicket-custom-modalwindow-382x450.jpg" alt="wicket-custom-modalwindow" title="wicket-custom-modalwindow" width="382" height="450" class="aligncenter size-medium wp-image-255" /></a></p>
<p>Der Aufwand für eine eigene Komponente ist zwar wesentlich höher als in anderen Fällen, aber der Aufwand lohnt schon deshalb, weil dann das Aussehen der ModalWindow-Kompoente zur restlichen Anwendung passt.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>9. April 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/04/09/wicket-abstractevent-update/" title="Wicket &#8211; AbstractEvent Update">Wicket &#8211; AbstractEvent Update</a></li><li>7. März 2010 -- <a href="http://www.wicket-praxis.de/blog/2010/03/07/wicket-heatmap-ajax-mit-parametern/" title="Wicket Heatmap &#8211; Ajax mit Parametern">Wicket Heatmap &#8211; Ajax mit Parametern</a></li><li>23. Dezember 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/12/23/wicket-ajax-tipp-ajaxrequesttarget-nachtraglich-ermitteln/" title="Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln">Wicket Ajax Tipp &#8211; AjaxRequestTarget nachträglich ermitteln</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/03/03/wicket-extensions-anpassungen-am-modalwindow/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Buchkritik bei it-republik.de</title>
		<link>http://www.wicket-praxis.de/blog/2010/02/11/buchkritik-praxisbuch-wicket/</link>
		<comments>http://www.wicket-praxis.de/blog/2010/02/11/buchkritik-praxisbuch-wicket/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 08:46:12 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[buch]]></category>
		<category><![CDATA[rezension]]></category>

		<guid isPermaLink="false">http://www.wicket-praxis.de/blog/?p=247</guid>
		<description><![CDATA[Danke für die gute Rezension. Andere Beiträge19. Oktober 2009 -- Wicketbuch aus dem dpunkt Verlag9. September 2009 -- Wicket im JavaMagazin27. Mai 2009 -- Wicket Praxis als Buch]]></description>
			<content:encoded><![CDATA[<p>Danke für die gute <a href="http://it-republik.de/jaxenter/buchtipps/Praxisbuch-Wicket-0810.html">Rezension</a>.</p>
<div id="vgwpixel"></div><h3  class="related_post_title">Andere Beiträge</h3><ul class="related_post"><li>19. Oktober 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/10/19/wicket-dpunkt-verlag/" title="Wicketbuch aus dem dpunkt Verlag">Wicketbuch aus dem dpunkt Verlag</a></li><li>9. September 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/09/09/wicket-im-javamagazin/" title="Wicket im JavaMagazin">Wicket im JavaMagazin</a></li><li>27. Mai 2009 -- <a href="http://www.wicket-praxis.de/blog/2009/05/27/wicket-praxis-als-buch/" title="Wicket Praxis als Buch">Wicket Praxis als Buch</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.wicket-praxis.de/blog/2010/02/11/buchkritik-praxisbuch-wicket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 80/184 queries in 0.198 seconds using disk: basic
Object Caching 1463/1608 objects using disk: basic

Served from: www.wicket-praxis.de @ 2012-05-19 07:58:54 -->
