google.load issue - java

Hi I am messing around with google ajax api at the momemt and following the examples from the documentation I have two script tags in my html file:
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">google.load('search', '1');</script>
All works fine, but it will not work when I am using jquery and trying to call the google.load('search', '1'); in an external javascript file after $(document).ready(function()
I get the following error: null is null or not an object.
I am obviously missing something fundamental as I am just learning javascript but I was under the impression that it is best to use javascript unobtrusively. The second script tag that actually contains some js code isnt unobtrusive. Can anyone lend any help with this please?

From what you have explained it seems your page is setup something like this:
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('jquery');
$(document).ready(function(){
... do stuff ...
});
</script>
<script src="/my/external.js" type="text/javascript"></script>
However, this will not work as you expect since the document.ready event will not fire until the DOM is completely loaded. JavaScript files, however, are executed as they are loaded. So the actual execution looks like this:
Load Google JSAPI
Load jQuery
Load External.js
Call Document Ready
Depending on what the rest of your code looks like, you might want to either put all your initialization code in a separate file, or move your search load back into the main document.
ABOUT UNOBTRUSIVE CODE:
David, unobtrusive JavaScript has to do with how it affects the page, not with whether or not it is in-page or external.
It is more about not making your site so dependent on JavaScript that it does not function with it disabled
For instance, this is obtrusive:
Click Me
Because it will only work with JavaScript enabled. Additionally the code is inline which is bad because it does not separate functionality from structure (HTML).
However, taking a similar piece of code:
Click Me
and using this javascript/jquery snippet:
$(document).ready(function(){
$("#do-something").click(function(e){
doSomethingNicer();
e.preventDefault(); // Keep the browser from following the href
});
});
Is becomes unobtrusive because the page still works (loads /do/something by default), but it works in a nicer way when JavaScript is enabled (executes the javascript instead of loading that url). This is also called Progressive Enhancement.

Related

script inside scriptlet - bad practice how to avoid

i am working on a legacy project where i have seen below piece of code.
I know it is a bad practice to use script inside scriptlet.
Regarding this , i have few confusion in mind.
what i believe is scriptlet is executed before page loads, so if below if condition is true then ShowBookReference() function call is a part of an Html page, but my question is when page is rendered should this function call happens or not ?
<% if (refLinkTerm != null) { %>
<script Language="javascript">
ShowBookReference('<%=sub2ndNavMenu%>', '<%=refLinkTerm%>', <%=String.valueOf(searchType)%>, <%=String.valueOf(codeType)%>)
</script>
<%}%>
How to avoid this kind of practice ?
Please share your thoughts.
Use an MVC framework such as Spring MVC. In these frameworks, you fill in a Java object (or map of objects) with the values for the page to display, and then the page just fills in placeholders with those values.
In terms of JSP, Its usual to use scriptlets to assign value to JS.
But as you've mentioned that it runs before the page load, so it's good to run the function on window.onload.
<script type="text/javascript">
window.onload = function() {
ShowBookReference('<%=sub2ndNavMenu%>', '<%=refLinkTerm%>', <%=String.valueOf(searchType)%>, <%=String.valueOf(codeType)%>)
}
</script>
In case you're referring some DOM elements inside ShowBookReference function, it may not be available so run it on page load.
Else you can use UI frameworks like JSF which provides you tags to bind java values to UI easily.

Inject to GWT authorize.net Verified Merchant Seal

I have gwt app with payment feature. I would like to insert into UIBinder following code (provided by authorize.net for verified merchants. I added my site to Verified Merchant Seal Domains List on authorize.net server):
<div class="AuthorizeNetSeal">
<script type="text/javascript" language="javascript">var ANS_customer_id="MY_ID";</script>
<script type="text/javascript" language="javascript" src="//verify.authorize.net/anetseal/seal.js"></script>
MerchantServices
</div>
I tried following:
UIBinder:
<g:HTMLPanel>
<div class="AuthorizeNetSeal">
Merchant Services
</div>
</g:HTMLPanel>
and in constructor of the control after initWidget(...)
ScriptInjector.fromString("var ANS_customer_id = 'MY_ID';").inject();
ScriptInjector.fromUrl("//verify.authorize.net/anetseal/seal.js").inject();
Tried scheduleDeferred. Tried setCallback() for ScriptInjector.fromUrl. Success method is called.
But seal doesn't appear.
please help
Thanks
Add script elements to the head section of your host page. If scripts are small and/or you do not use code splitting, there is little to no advantage in using a ScriptInjector.
Verify with your browser console that the script loads correctly from a URL you provided.
You need to inject them in the correct window:
ScriptInjector.fromString("var ANS_customer_id = 'MY_ID';").setWindow(ScriptInjector.TOP_WINDOW).inject();
But the seal.js uses document.write so it cannot be injected that way anyway, it must be present in the HTML document when loaded by the browser.
You could put this snippet in your HTML host page in a hidden <div> that you later relocate (Document.get().getElementById(…) and other appendChild DOM methods) where you want it within your app.
…and you should ask Authorize.net to provide an async version of their script so that if their servers are slow they don't slow down the loading of your app.
Thanks for your answers. I created separate HTML page with html code above and inserted it to iframe.

Inject Javascript in GWT

When I inject javascript this way:
ScriptInjector.fromString("var WRInitTime=(new Date()).getTime();").inject();
ScriptInjector.fromString(Resources.instance.clicktaleScript().getText()).inject();
I can see that the script injected was in a IFRAME. What is the GWT approach in injecting Javascript code? Considering that the pages are "Ajax" or Dynamic. The goal is to make Clicktale script be able to record browser events just like how it works for normal HTML pages, making this work with Dynamic website with Ajax data is quite hard.
The actual JS Script are:
<!-- ClickTale Top part -->
<script type="text/javascript">
var WRInitTime=(new Date()).getTime();
</script>
<!-- ClickTale end of Top part -->
and
<script type='text/javascript'>
// The ClickTale Balkan Tracking Code may be programmatically customized using hooks:
//
// function ClickTalePreRecordingHook() { /* place your customized code here */ }
//
// For details about ClickTale hooks, please consult the wiki page http://wiki.clicktale.com/Article/Customizing_code_version_2
document.write(unescape("%3Cscript%20src='"+
(document.location.protocol=='https:'?
"https://clicktalecdn.sslcs.cdngc.net/www02/ptc/1239e635-ed5c-4c26-81a7-5eedf55952f0.js":
"http://cdn.clicktale.net/www02/ptc/1239e635-ed5c-4c26-81a7-5eedf55952f0.js")+"'%20type='text/javascript'%3E%3C/script%3E"));
</script>
<!-- ClickTale end of Bottom part -->
I am not 100% sure, what your problem is, but if you want to access the same frame as the GWT Application you will need to set the correct Window object:
ScriptInjector s= ScriptInjector.fromString("var WRInitTime=(new Date()).getTime();");
s.setWindow(ScriptInjector.TOP_WINDOW);
s.inject();
http://www.gwtproject.org/javadoc/latest/com/google/gwt/core/client/ScriptInjector.FromString.html

GWT: How to make sure a javascript is run after the GWT page is constructed

I have a javascript file main.js. The main.js contains something like this:
$(document).ready(function() {
Cufon.replace('#myform p.head', { fontFamily: 'HelveticaNeueLT Std Thin' });
......
});
I suppose what this does is to run this method after the whole page is loaded and apply the change to the css elements.
But what I found out is that this only works when the script is loaded before all the HTML elements, e.g.:
<body>
HTML......
<script type="text/javascript" src="js/main.js"></script>
</body>
However, if this script is put on top of all the HTML, it stops working:
<body>
<script type="text/javascript" src="js/main.js"></script>
HTML......
</body>
This happens on both static HTML and the GWT page. Because my GWT always put the generated HTML stuff at the end of all the body contents, the script is always before the HTML, hence is does not work. For example, my HTML for GWT module is like this:
<body>
<script type="text/javascript" src="js/main.js"></script>
</body>
And after compiled, the generated HTML from my UIBinding gives HTML page like:
<body>
<script type="text/javascript" src="js/main.js"></script>
Generated HTML....
</body>
My questions are:
Is there anyway in GWT where I can specify the generated HTML goes
between some statements in the tag.
Is there any other ways instead of $(document).ready I can guarantee
it is called as the last thing happened in a page load?
Many thanks
While I find it strange that the script doesn't work as intended when moved up in a static page ($(document).ready(…) is supposed to wait for the </html> to be reached –aka DOMContentLoaded– before running the function passed to it), it's not the reason it doesn't work with your GWT application (in other words, your diagnostic is wrong).
GWT's onModuleLoad also runs at DOMContentLoaded (or later, but never earlier) so you probably have a race condition between your app's onModuleLoad and jQuery's $(document).ready(…). You could try putting the <script> for your GWT app before the main.js, but because onModuleLoad might run after DOMContentLoader anyway, there's no guarantee it'll work (even less in a crossbrowser way).
I think you'd better remove the main.js or replace the $(document).ready(…) with a simple function, and call Cufon (and/or whatever else you were doing in $(document).ready(…)) from within your GWT app, at the moment appropriate for your needs (i.e. after you attached the #myform p.head element/widget to the document).
The easiest way to do that is to put the script in a JSNI method and then call that method where appropriate. Just make sure you use $wnd.Cufon instead of Cufon (and similarly for all other globals), and replace all occurrences of document with $doc and window with $wnd.
public static void cufon() /*-{
$wnd.Cufon.replace('#myform p.head', { fontFamily: 'HelveticaNeueLT Std Thin' });
}-*/;

GWT - easiest way to do a simple loading screen until file is loaded

When clicking a button, my GWT application returns a PDF file embedded in an HTML page which looks something like:
<html><head></head>
<body marginwidth="0" marginheight="0" bgcolor="rgb(38,38,38)">
<embed width="100%" height="100%" name="plugin"
src="http://myserver/?cmd=getMyPdf" type="application/pdf">
</body>
</html>
Problem is it can take a while for the server to create this PDF file, so what I want is a waiting screen with a loading animation which can have the PDF file download in the background, and then when the file is done, display the page as described above.
One obvious way would be to display a loading page, send an asynchronous command to the server and then once the onSucceed method is called, call the page as normal. Downside is I'd have to add some server-side logic for making the PDF creation work in the background...
Is there any way to do this client-side with the GWT API?
Did you see this stackoverflow question Detect when browser receives file download? Basically the answer given is that you set a cookie in the return response and wait on the client side for this cookie to be set. This can be done easily with GWT as it has a Scheduler (for the repeated timer check) and easy access to Cookies. You still need to make some server changes, but you don't have to create a background process.
I don't have the full answer, but the following code works for me in Safari, and maybe you can modify it, to make it work with other browsers, too (?):
<html><head>
<script type="text/javascript">
function showPdf() {
document.getElementById("loading").style.visibility = "hidden";
document.getElementById("pdf").style.visibility = "visible";
}
</script>
</head>
<body marginwidth="0" marginheight="0" bgcolor="rgb(38,38,38)">
<div id="loading"
style="position: absolute; background-color: white;">Loading...</div>
<iframe id="pdf" width="100%" height="100%" name="plugin"
src="http://myserver/?cmd=getMyPdf" onload="javascript:showPdf();"
style="visibility: hidden;"></iframe>
</body>
</html>
This is pure JavaScript - but could certainly be done with GWT, too. Note, that I'm using an iframe instead of embed, because embed doesn't really support the onload method (and embed is not a standard HTML element, as far as I remember).
The reason, why this may not be the full answer, is that Chrome fires the onload event as soon as the PDF starts downloading (but after the PDF generation on the server side has finished). I'm not sure, if this is what you want?

Categories