Calling a method on NPAPI plugin object respawns the plugin - javascript

I have a NPAPI plugin embedded in a HTML page. When I call a method on it from browser's developer console, everything is ok - methods call lands on the right plugin instance and is properly executed. Anyway, when I call the same method from JS callback, like a button click, for instance, plugin is destroyed and the recreated again, while NPP.pdata is set to null.
Can it be somehow related to JS multithreading model and how can it be solved?

I figured it out. The issue was not related to NPAPI, or JS multithreading at all.
I was calling a method on NPAPI plugin object in a HTML form.
<form>
<input id="whatever-button" type="submit" value="Whatever"></input>
</form>
<script type="text/javascript">
$('#whatever-button').click(function(e) {
var plugin = document.getElementById('plugin');
plugin.whatever();
});
</script>
What I have not considered is the page reload - which is the default action after a click on a button. Page reload then triggered plugin object recreation, and it was fast enough, so I have not noticed it. The problem is solved by simply adding e.preventDefault(); to the callback function. This is how the working code looks like.
<embed id="plugin" type="application/my-npapi-plugin" width="640" height="480">
<form>
<input id="whatever-button" type="submit" value="Whatever"></input>
</form>
<script type="text/javascript">
$('#whatever-button').click(function(e) {
e.preventDefault();
var plugin = document.getElementById('plugin');
plugin.whatever();
});
</script>
UPD: Actually, setting input type to button, instead of submit is easier way to solve the issue. It also does not require e.preventDefault();.

Related

Difference between button onclick and a href

I'm trying to integrate SendOwl shopping cart into my application (details of the application are at the end).
To demo the problem I created a simple snippet using pure HTML / Javascript. In the head section of the HTML, I have this:
<script type="text/javascript">
function SendOwl(url) {
window.location.href=url;
}
</script>
<script type="text/javascript" src="https://transactions.sendowl.com/assets/sendowl.js" ></script>
In the body I have this:
Example 1: Opens the checkout form in its own window (Undesired behavior):
<input type="button" onclick="SendOwl('https://transactions.sendowl.com/products/8/5C080C0F/purchase');" value="On Click" />
Screenshot 1: Notice the URL changed and it's not an overlay (compared to 2).
Example 2: Opens the checkout form in a modal window as an overlay (Desired behavior):
<a href='https://transactions.sendowl.com/products/8/5C080C0F/purchase'>a href</a>
Screenshot 2: The URL stays the same, but the form opens in an overlay.
You can also see a live demo on the SendOwl's demo page.
My application is based on GWT (SmartGWT to be precise). In my application, I call button onclick handler to invoke a Javascript that invokes the Buy Now link using JSNI call (shown below). But the Buy Now link always opens in a full window as in example 1 above.
public static native void onBuyNowClick(String url) /*-{
$wnd.SendOwl(url);
}-*/;
I have tried $wnd.open(url) but that has the same behavior.
How do I get the first example to behave like the second but still using button onclick?
UPDATE:
The magic is in the sendowl.js script. If I remove that script, then both examples work the same way. If I could figure out how that script works, it might give some clues to make Example 1 work the same way as Example 2.
Thanks.
I have resolved the issue myself by probing into the sendowl.js . That's the script which is doing all the magic.
This is my modified script that makes Example 1 work exactly like Example 2:
<script>
function SendOwl(url) {
sendOwl.addLoadingImage();
sendOwl.loadIframe ('https://transactions.sendowl.com/products/8/5C080C0F/purchase');
}
</script>
<script src="https://transactions.sendowl.com/assets/sendowl.js"></script>
Thanks to all who replied and tried to help.
All you need is:
<script type="text/javascript" src="https://transactions.sendowl.com/assets/sendowl.js" ></script>
<input type="button" value="Purchase" />
https://help.sendowl.com/help/article/link/button-codes-to-sell-your-product
Works fine for me.
In GWT you can use a PopupPanel to display the overlay. Personally I never tried embedding a page inside a popup but you can try adding a Frame object inside the popup panel, something like this:
PopupPanel popup = new PopupPanel();
Frame frame = new Frame("http://www.yourlink.com/");
popup.setWidget(frame);
popup.setGlassEnabled(true);
popup.center();
As for the URL please check the documentation and this thread

Back button needs to redirect to last visited page

In web site I have to add "Back" button or Link URL which will redirects to me previously visited page.
Currently I have added below code, but it doesn't always work.
<i>Back</i>
I observed that it is not working in Google chrome.
<script>
function sample(){
window.location.href = window.history.back(1);
}
</script>
<input type="button" value="trying" onclick="sample()"/>
I have tested here it is working test ... :)
Event this work as same
<i>Back</i>
Try this :
<input action="action" type="button" value="Back" onclick="history.go(-1);" />
The following was an incorrect assumption by me
The value passed to onclick should be a function to call when the link is clicked. You are passing window.history.back() which is the value returned by the back function.
Try the following.
<i>Back</i>
Turns out I assumed, incorrectly, that the value of onClick should be a function to call on click. As Brian North and putvande pointed out in the comments it should be the javascript code to run when the event is triggered.
Suggestion
However one should generally avoid binding events in the way you are doing as it couples presentation, HTML, too tightly with the javascript. Instead one should bind the click listener from an external javascript file using for example addEventListener or jQuery.on.
jQuery example
HTML
Back
Javascript
$(function() {
$("#history-back").on("click", window.history.back);
});

Attaching a callback to html generated by JSF - Primefaces

I've got a Primefaces command button that I need to add a callback to in jQuery on document.ready. Basically what I've been trying to do is get a reference to the existing function and then call it in a new function that I wrote:
var existingFunction = jQuery("[id~='submit']").live("click");
jQuery("[id~='submit']").live("click", function(){
existingFunction();
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
It seems simple enough to me but for some reason this will not work. When I load the page and click the submit button it doesn't even reach the alert.
I've checked the error console and found that it's throwing the following errors:
((f.event.special[s.origType] || {}).handle || s.handler).apply is not a function
There is existing jQuery functions on the page that I did not write but I'd like to make sure this error is not related to the way I'm approaching this.
I'm using tomcat 6 with an older version of JQuery (1.3 or 1.4 ).
Thanks and let me know if you guys need any more info.
Edit
I've put up an example of what I'm trying to do on JS Fiddle: http://jsfiddle.net/anSXH/2/
Here is some further clarification:
I've built the button as a project in JSF 2.0 (MyFaces) using the latest Primefaces component library. I've then taken that button and embedded it into an existing web page. The button submits the form and then calls a JavaScript function to show the result on the page after an ajax request is complete. This all works when I embed the button onto the page but I now need to update something on the client side after the button calls the function. That's why I'm looking at adding a callback to the existing onclick function.
As a side note, because I'm using Primefaces I can attach a JavaScript function to run after the ajax request is complete. My plan B is to try and access this function and somehow override it.
Edit part 2
Here is the generated control from primefaces:
<button
id="topsaveform:submittop"
name="topsaveform:submittop"
class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
onclick="PrimeFaces.ab({source:'topsaveform:submittop',process:'topsaveform OEIMeasurementsTable',update:'errorMessages submittedPopup',onstart:function(cfg){jQuery('#loadingBar').show('fast');;},oncomplete:function(xhr,status,args){postSubmit();;}});return false;"
type="submit">
<span class="ui-button-text">Save</span>
</button>
Did you try making the original function die (ref)?
jQuery("[id~='submit']").die("click");
jQuery("[id~='submit']").live("click", function(){
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
The problem was that I was trying to do this with a primefaces button. When I switched to a standard JSF button I was able to affix the function to it no problem.

Prevent this page from creating additional dialogs

Firefox4 has a new feature → 【Prevent this page from creating additional dialogs】
But it was also a trouble with me when I hope an alert dialog opened more than once.
Now, A new problem has appeared ...like below ↓
1) I call the alert dialog more than once , and check the
【Prevent this page from creating additional dialogs】
2) I click a download button , My web application is down....
(my button' event is below.... and because it hasn't into the action , so I'm just write the client source....)
My Button Event
getDownloadFile:function(){
$('xform').submit();
}
My Page Code
<div style="display:none;">
<form id="xform" action="down.do" method="post" target="xfra">
</form>
</div>
<iframe id="xfra" name="xfra" src="/?scid=dummy.htm" style="width:0px;height:0px;visibility:hidden;"></iframe>
Hope anybody can help me ...thanks...
I am guessing the $ on your code means you are using jQuery (you should mention it in the tags if this is the case).
If you are not using jQuery, then I don't know much of the other frameworks' selectors. However, if it is jQuery, your selector is not correct, it should be:
$('#xform').submit();
not
$('xform').submit();
Since you are using PrototypeJS, the above is incorrect.
Here's a simple fix:
function myAlertMsg() {
alert("Whatever message you want");
location.reload(); /*This prevents the browsers pop-up disabler*/
}

Server-Side callback function to solve JS-CF execution order dependency?

I would like to call a form as pop-up window (a form with some input fields and a submit button) and then read the user selected results from the session. The problem is that the mixing of JS code (pop-up window) with CF (server-side) code, as is expected, causes the process to output the session variable before the process updates it. For better understanding, hereunder is the scenario together with some relevant code snippets:
Scenario:
1. User calls ShowForm(..)
2. ShowForm(..) displays a pop-up window and waits for the user
to submit his selection
3. The result gets stored in the session
4. The function returns the user-submitted result
form.cfc
<cffunction name="ShowForm" access="public" output="true" returntype="string">
<script>
window.showModalDialog('formpage.cfm',null,"dialogHeight=400px,dialogLeft=150px");
</script>
<cfreturn session.form_result> <!--- #toFix: The return of form_result is happening before the actual form_result is set. --->
</cffunction>
formpage.cfm
<cfajaxproxy cfc="components.sess_mgr" jsclassname="JSMaskProxy">
<script>
function submitSelection(formObj)
{
for (i=0; i<intSelValue.length; i++)
result.push(intSelValue[i]);
var instCfProxy = new JSMaskProxy();
instCfProxy.setToSession(result); // updates session.form_result
//window.returnValue=result;
window.close();
}
</script>
<form name="frmDtls">
<td align="center"><input type="button" id="selectButton" name="selectButton" onClick="submitSelection(details);">
</form>
What's your take on this? How to solve this problem?
ColdFusion.navigate(..) function can have a callback function and an error handler but the thing is that the callback function can only be a client-side function. If the function could be a CF function or maybe a server-side page I think that would solve this dependency problem.
Something on the side, ideally I would love to read the value from window.showModalDialog rather than reading it from the session, but this is just a sketch and the main point here is how to overcome this JS-CF intermingling problem.
Rather than using window.showModalDialog use something like cfwindow, jQuery dialog or an extjs window. All of these have some form of callback or event listener. cfwindow has a onHide function, jQuery dialog has a close option to which a function can be assigned, ext.window has onHide, as well as event listeners.
All of these will allow you to open a new "window" and run some function when the window is hidden or closed. Those functions should all have access to anything from the window as well as being able to access the main window.
Ray Camden has a cfwindow example : http://www.coldfusionjedi.com/index.cfm/2008/9/26/Ask-a-Jedi-Another-CFWINDOW-Example
jQuery dialog has an example of what you're after : http://jqueryui.com/demos/dialog/#modal-form
Sencha's Ext.Window examples show passing values to the main window when a dialog is closed : http://dev.sencha.com/deploy/dev/examples/message-box/msg-box.html
Plenty of options there. I hope they help.
Problem solved!
The solution adopted is based on Stephen Moretti idea which is that of replacing window.showModalDialog with cfwindow call. This alone does not solve the problem. However, I worked when replacing the script tag with cfscript, and then inside the cfscript I simply do a server-side redirection to the page with cfwindow tag.

Categories