load data and navigate using the same action - zk

I'm newbie with zk6 framework. I created a view model class where i'm trying to navigate from one zul and load some data in another one:
public class SearchVM {
#Command
#NotifyChange({ "searchBean","slides" })
public void doSearch() {
//load data (slides) from data base
//navigate to another zul where i display my data
}
}
The data is displayed if i stay in the same zul but i get nothing if i navigate to another one.
i tried to use Executions.sendRedirect("/result.zul") with no sucess.

Don't do a browser redirect. Show the results using AJAX.
So in the following a single zul file has two zones, once is hidden by default. When you click the button it hides the first zone and shows the second.
<zk>
<zscript>
boolean showFirstZone = true;
</zscript>
<window visible="${showFirstZone}" id="firstZoneWindow">
This is first zone.
<include src="/WEB-INF/search/search-input.zul"/>
<button label="Switch To Results" onClick="secondZoneWindow.visible=true;firstZoneWindow.visible=false;" />
</window>
<window visible="${!showFirstZone}" id="secondZoneWindow" >
This is second zone.
<include src="/WEB-INF/search/search-result.zul"/>
</window>
</zk>
Notice that I put the included zul files under /WEB-INF so that they are not accessible from the browser which is a good idea. That way only the entry pages which define the desktops of the system are in the main folder of the site (e.g. one for customers, one for staff, one for admins) each of which can reuse the including fragments hidden under /WEB-INF.
The Theory:
With php/jsp you have the browser request new pages and you draw them so that they see related dated via the session. ZK is a desktop oriented framework where you tend to build "single page applications" which means applications updated by AJAX. Doing a browser redirect is not doing an AJAX update. Your forcing a refetch of all the JS and CSS and re-evaluation of the zul file which is a lot less efficient than doing a dynamic update over AJAX.
If you read http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/UI%20Composing/Component-based%20UI it indicates that when you open a new URL you are creating a new desktop. ZK actually puts in a body onunload javascript handler onto the html page it renders telling the browser to send a final AJAX event to destroy the existing desktop when the user navigates to a new url. So your actually destroying your ViewModel when you have your user navigate away from your first zul page. That's why you don't see any data at the new url the browser goes to; it is an entirely new desktop which would get an entirely new ViewModel which has nothing to do with the one the user went away from.

Related

How to access input field in TinyMCE 5 URL dialog

I'm porting a TinyMCE 3 installation to version 5. I set up a toolbar button that opens a dialog that contains a custom page and is therefore loaded using the new windowManager.openUrl method. I have some footer buttons, too, and, of course, an onAction( dialogApi, details ) handler that is invoked when a button is clicked. details.name contains the name of the button that was clicked so I can react on every click individually.
It seems, when a regular dialog is used, I configure every input field in my plugin.js file and retrieve its value through the getData method of first param that in passed into my onAction handler. This method does not exist in my dialogApi for the URL dialog.
My iframe/dialog contains a dropdown and I want to insert the selected value into the editor instance when a dialog footer button is clicked. I understand I can use postMessage to send information from the iframe to the plugin but that's not what I want.
How can I access input fields in the dialog, when a button is clicked and my dialog was opened through openUrl? How do I access the document in the dialog's iframe? this seems to be the JavaScript object I passed into openUrl. document is the page where the editor is embedded.
I've made a demo that shows two different ways of getting the data from user inputs in an iframe dialog:
https://codesandbox.io/embed/tinymce-dialog-openurl-demo-fpfew
This blog post is also an excellent resource for working with iframe dialogs in TinyMCE:
https://www.martyfriedel.com/blog/tinymce-5-url-dialog-component-and-window-messaging
The first method in my demo uses a button in the HTML of the iframe itself. That button collects user data and uses postMessage to send that data back to the TinyMCE editor.
As you can see, the process is a little more complex using the footer buttons as opposed to the "in iframe" button. Essentially, the footer button sends a message to the iframe in the dialog asking the iframe to collect and insert user data into TinyMCE.
When using an iframe, you have to respect the browser security policy, so most times you can't interact with an iframe directly (the exception being if the iframe uses the same domain). Here's some more information about iframe security policy:
https://security.stackexchange.com/questions/67889/why-do-browsers-enforce-the-same-origin-security-policy-on-iframes
This also means that TinyMCE has no way of knowing what's inside the iframe like it does with a TinyMCE dialog, so the data needs to be fetched "manually". With that in mind, if it's a cross origin request (different domain) there's no way to access the iframe content without using postMessage.
The getData method mentioned works with TinyMCE dialogs because everything in the dialog is a TinyMCE component. TinyMCE components have a custom concept of values/states that getData can access to return data.
When you use a URL dialog, the dialog no longer uses TinyMCE components so it isn't able to collect the data for getData, hence it the method doesn't exist. That's why you have to manually get the data needed from whatever elements are in the URL dialog, and send them back to TinyMCE using postMessage.

Java Wicket - Prevent Form From Creating New Tab When Exception Occurs

I am creating reports using Jasper right now and almost everything goes well. We set it in a way that if the user will preview a report, the report(pdf) will be shown on a new Tab. The problem is if an error occurs, a new Tab would still be opened instead of just showing the Feedback Panel on the original page.
How can the form be setup in such a way that the feedback panel will be shown on the original page instead of the newly opened Tab?
Form<?> form = new Form<Void>("form");
form.add(new AttributeAppender("target", Model.of("_blank")));
SubmitLink view= new SubmitLink("view") {
#Override
public void onSubmit() {
//code inside a try-catch to generate the report using Jasper}
};
CptiDownloadButton download = new CptiDownloadButton("download", new AbstractReadOnlyModel<File>(){
//CptiDownloadButton extends SubmitLink button and is a modification of Mr Ivaynberg's DownloadLink
};
<form wicket:id="form">
<input type="button" wicket:message="value:search"/>
<input type="button" wicket:message="value:download"/>
</form>
Thanks in advance to anyone who'll answer. ^^
If you do any form submission to a form with target="_blank", the browser will automatically open a new tab to render the response from the form submission. It is the intended behavior, and trying to prevent it is breaking the standard target="_blank" behavior. I guess what I'm saying is you should really think whether breaking this standard behavior is something you want to do.
If it is, here's how I would go about it. Warning: ain't gonna be clean.
Use Ajax (AjaxButton or AjaxFormSubmitBehavior) to submit the form. Since it is done via ajax, the browser will not invoke default form submission behavior, hence not opening a new tab.
Ajax then invokes the form processing. On error, re-render the feedback panel and return. On success append JavaScript to invoke the default form submission on the respective link when the request returns. This will perform standard form submission behavior, hence performing the target="_blank". It will once more validate the form, but then it will proceed to perform the originally intended behavior.
The way you invoke the default form submission on the link you desire can be done in a few different ways and is entirely up to you. As a quick and dirty way you can hide the buttons that you have right now (visually) and perform javascript to click the button. Or you can use a hidden form field to identify which button has been clicked if you don't want ugly hidden clicking behavior.
You'll have to do a form (Ajax)-submit without target, and then initiate the actual download after checking possible errors.
See https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow for an example with Ajax and an attachment content disposition.

How to find if web page got appended using chrome extension

I am new to chrome extension and I am trying to find whether page content got appended.
For E.g. in Facebook, we can see the content will appended automatically when the user scroll down the page.
I have the following code in background.js
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
alert("page is appending....");
});
The above code is expected to fire when the page got updated. But, I am seeing that it is getting called only for few times. Not always.
Or Am I making any mistake here ?
My requirement is, whenever the web page appended in facebook, I have to do get the page content and obtain few string from the same.
Thanks in advance.
Your onUpdated event is in the chrome.tabs namespace on purpose, it listens the updates of tab's general attributes like: the tab pinned, the favicon changed, the URL changed, see the documentation (also check the update() method). So this way is not workable. Instead listen the DOM tree change with DOMSubtreeModified event or MutationObserver.

Can't add external script into gwt widget

I am trying to add google gadget into FlowPanel(or HTMLPanel), but after a host page is loaded it navigates away from my page and shows gadget in a new page, if i click browser's back button it loads host page and again navigates away to new page to show the gadget.
Here is the code:
String code="here_goes_scrip_tag_for_gadget";
flowPanel.add(new HTML(SafeHtmlUtils.fromTrustedString(code)));
What am i doing wrong, please help.
UPDATE
The above code to load script was wrong, i've modified it as following:
FlowPanel gadgetContainer = new FlowPanel();
Element script = Document.get().createScriptElement();
script.setAttribute("type", "text/javascript");
script.setAttribute("src", "http://www.gmodules.com/ig/ifr?url=http://digg.com/goog/ig.xml&up_user=&up_thumbnail=1&up_filter=0&up_num=5&up_type=popular&up_refresh=0&up_tab=0&up_offset=0&up_pagination=0&up_business=true&up_entertainment=true&up_gaming=true&up_lifestyle=true&up_offbeat=true&up_politics=true&up_science=true&up_sports=true&up_technology=true&up_world_news=true&synd=open&w=320&h=200&title=Digg&border=%23ffffff%7C3px%2C1px+solid+%23999999&output=js");
gadgetContainer.getElement().appendChild(script);
But it still doesn't work.
For solving this problem in general, check out the com.google.gwt.core.client.ScriptInjector class - it has two methods that allow you to inject scripts into the page in a cross browser way. The way you are attempting to inject the script content won't work cross browser.
Looking specifically at your gadget case, I'm guessing that the script you are loading has code in it to prevent it from being loaded into another page. Have you tried to use a plain html page that references that script tag? If the same thing happens, see if you can see where in the script file the page reassigns window.location.

gwt multi-page application

I have a multipage application which needs to manually switched from one page to another. could it be done in GWT since it is targeted towards single page application. I am learning from the Google code and online forums but could not find any application which had multi-pages not linked by a common entry-point. Any ideas?
GWT has support for "pages" within application via URL fragment identifier (FI), i.e. http://www.yourhost.vom/main#pagename, where "pagename" is a fragment identifier representing a "page" within your app.
This "pages" (note that browser never really reloads the page, so GWT app stays the same), have full history support and are bookmarkable.
NOTE: throughout GWT docs fragment identifier is sometimes referred to as place token or history token.
Enable history support by adding an iframe to your host page:
<iframe src="javascript:''"
id="__gwt_historyFrame"
style="width:0;height:0;border:0">
</iframe>
Register a ValueChangeHandler to be notified when FI (page) changes: History.addValueChangeHandler(..). Within this handler you put a logic that displays the new page.
Go to a particular page by calling History.newItem("newpage") (without #)
You can even pass "parameters" to page, by dividing fragment identifier into sub parts: for example "#edit/user4". Just parse this FI, invoke code that shows edit page and pass "user4" to it. You can use any character to divide FI into a "page" part and "parameter" part (I use "/" here). To see this in real life: open a message in gmail and look at URL.
While you can use GWT to switch pages, the resulting code will be slow and suboptimal, with the pages taking longer to load.