This should be totally simple but I can't get it working no matter what I try. I'm trying to use Google Analytics with GWT application. From what I understood, there are two way to do it:
First is synchronous, by inserting tracking code at the end of <head> section HTML page and then calling this method:
public static native void recordAnalyticsHit(String pageName) /*-{
pageTracker._trackPageview(pageName);
}-*/;
Second is asynchronous, by inserting tracking code just after <body> tag and then calling this method:
public static native void recordAnalyticsHit(String pageName) /*-{
_gaq.push(['_trackPageview(' + pageName + ')']);
}-*/;
When running each of those methods, however, I get this exceptions in hosted mode:
[ERROR] [myproject] Uncaught exception escaped
com.google.gwt.core.client.JavaScriptException: (ReferenceError): pageTracker is not defined
[ERROR] [myproject] Uncaught exception escaped
com.google.gwt.core.client.JavaScriptException: (ReferenceError): _gaq is not defined
When observing site in Firebug, I see that ga.js gets loaded, but that's about it.
Did anyone get Analytics working with GWT? Also, does _gaq accept page name as trackPageview parameter, since all the examples I've seen use this call:
_gaq.push(['_trackPageview()']);
(Of course, that also doesn't work for me.)
This is just a guess, but you probably need to reference the host page (the one where the Google Analytics JS code has been included) via $wnd in the JSNI, like this:
public static native void recordAnalyticsHit(String pageName) /*-{
$wnd.pageTracker._trackPageview(pageName);
}-*/;
JSNI code (and in general, GWT code) is run in a iframe to keep the namespace clean, that's why you need the $wnd reference to the main window.
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-xxxxxx-x");
pageTracker._trackPageview("/subdirectory/pagename");
</script>
See http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55485 for details.
Related
I'm looking for some sample code using the AEM JCR_SQL2 API in server-side Javascript (NOT Java), i.e. code that starts with use(function() { ... }) and is loaded via data-sly-use=${...}.
All Google results are 100% Java based examples.
What I've already tried: Google "JCR-SQL2 js example" and variations.
Expected result: sample code in Javascript.
Actual result: lots of Java code :-(
If you wanna use server-side JS (what I don't recommend), then you only have to convert the syntax of the Java examples. You interact with the Java-Objects anyway. So the API is the same for JS as for Java. In case you have a HTL component and calling the JS via the Use-API, then several objects are already defined in your JS scope.
https://helpx.adobe.com/experience-manager/htl/using/global-objects.html
Here is an JS example to search all core components with a SQL-2 query:
use(function () {
var pageName = currentPage.name;
var title = currentPage.properties.get("jcr:title");
var resourceName = granite.resource.name;
var resourceTitle = properties.get("jcr:title");
var componentList = [];
var componentIter = resolver.findResources("SELECT * FROM [cq:Component] AS c WHERE ISDESCENDANTNODE(c, '/apps/core/wcm')", "JCR-SQL2");
while (componentIter.hasNext()) {
var compoenentRes = componentIter.next();
componentList.push(compoenentRes.getPath());
}
return {
pageName: pageName,
title: title,
resourceName: resourceName,
componentList: componentList
};
});
The component HTL code to use it, would be:
<div data-sly-use.info="info.js">
<p>page name: ${info.pageName}</p>
<p>title: ${info.title}</p>
<p>resourceName: ${info.resourceName}</p>
<p>core components: </p>
<ul data-sly-list.component="${info.componentList}">
<li>${component}
</ul>
</div>
PS: You probably know, but here you find the Use-API for JS:
https://helpx.adobe.com/experience-manager/htl/using/use-api-javascript.html
I'm not aware of any Web-API for JCR_SQL2 queries. You would have to implement your own Servlet in AEM (with Java), which would accept queries from external HTTP requests. Then you could call your servlet from your JS code via Ajax, and execute the query inside AEM with Java.
Maybe the Query Builder API is interesting for you. This query-language is already available from the outside, and can be called via Ajax. For testing and developing your queries you can use the Query Debugger:
Adobe Documentation:
https://helpx.adobe.com/experience-manager/6-3/sites/developing/using/querybuilder-api.html
Query Debugger:
http://localhost:4502/libs/cq/search/content/querydebug.html
Query Debuger with Sample Query:
http://localhost:4502/libs/cq/search/content/querydebug.html?charset=UTF-8&query=type%3Dcq%3APage%0D%0Aorderby%3D%40jcr%3Acontent%2Fcq%3AlastModified%0D%0Aorderby.sort%3Ddesc
Sample Query called directly:
http://localhost:4502/bin/querybuilder.json?orderby=%40jcr%3acontent%2fcq%3alastModified&orderby.sort=desc&type=cq%3aPage
I'm trying to start SuperDevMode the following way. I modified my index.jsp page to append a configurable prefix to the .nocache.js file. Production config contains an empty prefix, while development config contains something like http://localhost:9876. Then I start the server on Tomcat and type localhost:8080. GWT starts normally, but when it tries to send an RPC request, it fails, because request goes to localhost:9876 instead of localhost:8080. How can I customize which host should RPC use to send request to?
I spent some time digging into GWT code with Eclipse and debugger, and found, that GWT RPC concatenates the result of GWT.getModuleBaseURL() with the value of #RemoteServiceRelativePath. Here is the code of the getModuleBaseURL method:
public static native String getModuleBaseURL() /*-{
// Check to see if DevModeRedirectHook has set an alternate value.
// The key should match DevModeRedirectHook.js.
var key = "__gwtDevModeHook:" + $moduleName + ":moduleBase";
var global = $wnd || self;
return global[key] || $moduleBase;
}-*/;
I also examined dev_mode_on.js and found several occurences of __gwtDevModeHook, but none of them contained moduleBase. Also dev_mode_on.js install all its hooks into sessionStorage, while getModuleBaseURL reads from $wnd (I used debugger and became convinced that $wnd = window).
So I used the following solution and it worked for me. I simply added the following into my index.jsp:
<c:if test="${not empty gwtScriptPrefix}">
<script type="text/javascript">
window["__gwtDevModeHook:MYAPP:moduleBase"] = "MYAPP/";
</script>
</c:if>
just before
<script type="text/javascript"
src="${gwtScriptPrefix}MYAPP/MYAPP.nocache.js">
</script>
where the gwtScriptPrefix attribute is calculated by System.getProperty, and the corresponding system property is set to localhost:9876/ on the Eclipse running configuration.
When a user loads my page for the first time on an iPhone (works fine on Android, IE, FF,
Opera, Chrome, Safari), the two portions of the page generated by a Prototype/Scriptaculous Ajax.Updater call are garbled - they look as if a binary file were injected into the page or the character map was scrambled. If the user then reloads the page, or uses the page's tabs to navigate around via Ajax.Updater requests, everything is then fine. It's only the very first time the page is loaded in a browser session that this occurs. Here are the relevant calls with a bit of context:
soundManager.onready(function(){
new Ajax.Updater('PlayerSet', 'http://' + location.host +
playerHTMLloc, {method: 'post', onComplete: startPlayer});
});
This is only called once per site visit (so the user has to reload in order to get it to display correctly). It calls a python script that writes html to stdout.
Here's the other:
show: function(elm) {
var id = elm.identify();
elm.addClassName(id.sub('-html', '-selected'));
var link = 'ajax/' + id.sub('-', '.');
$('centercontent').update('<div id="floaterForSpinner"></div><div
id="centerSpinner"><img src="images/ajax-loader.gif"></div>');
new Ajax.Updater('centercontent', link, {evalScripts: 'true',
method: 'post'});
}
This is part of a small class that handles tabs on the page. Again, only the first time show() is called does the error occur. After that the tabber works normally. The updater is just pulling html text files from the server.
The issue occurs with both Prototype/Scripty 1.6.1/1.8.3 and 1.7/1.9.0.
The post and receive headers are identical for the first and subsequent loads, and the acceptable charset is Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 in all cases per Firebug.
I don't have an iPhone myself, and none of the off or online iPhone simulators I've tried reproduce the problem, so testing this is going to be a nightmare. Hence, anything anyone could do to help, would be, uh, very... helpful.
UPDATE based on questions I received on the GG prototype list:
All the code above is called after the DOM is loaded:
document.observe('dom:loaded', function() {
Ajax.Responders.register({onCreate: removeListeners});
Ajax.Responders.register({onComplete: postAJAX});
new Lightbox();
initMailList();
AT = new AjaxTabber('tablist');
initInternalLinkListener();
initIE6msgClose();
$('PlayerSet').update('<div style="text-align:center">
<img src="images/ajax-loader.gif"></div>');
soundManager.onready(function(){
new Ajax.Updater('PlayerSet', 'http://' + location.host +
playerHTMLloc, {method: 'post', onComplete: startPlayer});
});
});
AjaxTabber is the tab class that contains the show() function I mentioned earlier. The document.observe function above is in the last js file in the header.
UPDATE #2:
Replacing
document.observe('dom:loaded', function() {
with
Event.observe(window, 'load', function() {
in the 3rd code block fixes the garbled loads. However, the fix raises new questions/issues:
Why do the Ajax.Updater loads need to have the entire page loaded to work correctly? A DOM load should be all that's necessary. There's no reason to need the images loaded for an ajax load to work.
My overall page performance is now substantially degraded to fix an iPhone only problem. I'd really like to go back to loading once the DOM load is complete.
Calling update() and then Ajax.Updater on the same element one after another like this might introduce timing problems that can be difficult to diagnose. I recommend doing this instead (to add a "loading" indicator to your Ajax-loading element):
new Ajax.Updater('elementID', '/path/to/server', {
parameters: {},
method: 'get',
onCreate: function(){
$('elementID').update('placeholder html here');
},
onSuccess: function(){
// any other cleanup here
}
});
The onCreate callback hook will guarantee to run and complete before the request is sent and the element is updated by A.U.
I am debugging a GWT application and I need to print some stuff to the console for testing purposes. System.out.println and GWT.log don't work. Does anyone have any ideas?
Quoting the documentation:
Adding GWT logging is really quite simple, as simple as the following code example. However — understanding how logging works, and
how to correctly configure it is important, so please do take the time
to read the rest of this document.
http://code.google.com/webtoolkit/doc/latest/DevGuideLogging.html
The simplest way to enable logging is:
# In your .gwt.xml file
<inherits name="com.google.gwt.logging.Logging"/>
# In your .java file
Logger logger = java.util.logging.Logger.getLogger("NameOfYourLogger");
logger.log(Level.SEVERE, "this message should get logged");
I needed to do this in the context of a GWT application that was deployed to an Android device/emulator via PhoneGap (and gwt-phonegap). Neither System.out.println() nor GWT logging as above (with module declaration) showed up in Android's logcat, so I resorted to a simple JSNI wrapper to console.log:
public void onModuleLoad()
{
Logger logger = Logger.getLogger("Test1.java");
logger.log(Level.INFO, "ash: starting onModuleLoad (1)"); // not in logcat
System.out.println( "ash: starting onModuleLoad (2)" ); // not in logcat
consoleLog( "ash: starting onModuleLoad (3)" ); // This shows up
...
}
native void consoleLog( String message) /*-{
console.log( "me:" + message );
}-*/;
To log to browsers console you can do it using native, in a very simple way. Very helpful in debugging.
If you add a native method like in below, you can send a string to it from where you want and it will log it in the browsers console.
public static native void console(String text)
/*-{
console.log(text);
}-*/;
For more information about using native in GWT:
http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
In GWT version 2.6.0, method GWT.log writes message to browser console, you don't need to write native methods.
Just summing up the different possibilities shown in the answer's of mreppy and Strelok in one snippet. I also added one possible workaround for IE exceptions as described here: Why does JavaScript only work after opening developer tools in IE once?
java.util.logging.Logger logger = Logger.getLogger(this.getClass().getSimpleName());
native void jsConsoleLog(String message) /*-{
try {
console.log(message);
} catch (e) {
}
}-*/;
private void log(final String message) {
// Logs to Dev mode console only
GWT.log(message);
// Logs to Dev mode and JavaScript console (requires configuration)
this.logger.log(Level.FINEST, message);
// Logs to JavaScript console only
jsConsoleLog(message);
Yet another variation using the native console...
Add this class:
package XXX.XXX.XXX.XXX;
public class Debug {
private static boolean isEnabled_ = false;
public static void enable() { isEnabled_ = true; }
public static void setEnabled( final boolean isEnabled )
{ isEnabled_ = isEnabled; }
public static void log( final String s )
{ if( isEnabled_ ) nativeConsoleLog( s ); }
private static native void nativeConsoleLog( String s )
/*-{ console.log( s ); }-*/;
}
Then, enable debugging with it at some point, like upon starting the app:
public class XXXXXX implements EntryPoint {
#Override
public void onModuleLoad() {
Debug.enable();
...
}
}
Then just use it like so:
Debug.log("Hello World!");
I had this problem as well. The GWT log works but because it's all converted to javascript, it prints to the client output, so just view your browser's console and they will be there. In Google Chrome click the triple-line Customize button in the top right, click Tools-->Developer tools and the console will pop up. Your sought-after statements will be there. Also, Ctrl+Shift+I is the shortcut that brings it up. If you want to print to the server, I believe logger handlers and such are in order?
The documentation url in the first answer already gives the different configuration option to log to different places.
This framework i wrote offers you a usefull api and allows you to choose your server-side logging implementation.
Have a look :
https://code.google.com/p/gwt-usefull-logging/
I suggest you use GWT Developer mode It adds a little overhead cause the automatic compilation and code-allocating on the code server, but it's pretty clear when some exceptions arises in client side of your application. I mean, some times chrome console (or firebug or whatever browser debugging built-in tool) doesn't say too much in those situations, trust me, finding a NullPointerException is a pain in the neck when you try to figure out what is happening by alerting your code.
For printing to the browser console I am using something like this:
EventLogger.java
public class EventLogger {
public static void logEvent(String subsys, String grp, String type) {
logEvent(GWT.getModuleName(), subsys, grp,
Duration.currentTimeMillis(), type);
}
public static native void logEvent(String module, String subsys,
String grp, double millis, String type)
/*-{
if ($wnd.__gwtStatsEvent) {
$wnd.__gwtStatsEvent({
'moduleName':module,
'subSystem':subsys,
'evtGroup':grp,
'millis':millis,
'type':type
});
}
}-*/;
}
You can put alaert.Alert(""); in your gwt code compile it and run it you will get pop up on browser when you make request or at the action where you have placed that alert
I have a GWT application and I want to run some code when the user leaves the application to force a logout and remove any data etc.
To do this I am using a CloseHandler and registering it using Window.addCloseHandler.
I have noticed that when the refresh button is clicked the onClose method is run but I have been unable to differentiate this event from a close where the user has closed the browser. If it is a refresh I do not want to do the logout etc, I only want to do this when the user closes the browser/tab or navigates away from the site.
Does anybody know how I can do this?
There is no way to differentiate the 'close' from 'refresh'. But, you can set a cookie that holds the last CloseHandler call time and check, when loading the module, if this time is old enough to clean the information before showing the page.
You can do that with the folowing utility class (BrowserCloseDetector). Here is an example using it on the onModuleLoad.
The test lines:
#Override
public void onModuleLoad() {
if (BrowserCloseDetector.get().wasClosed()) {
GWT.log("Browser was closed.");
}
else {
GWT.log("Refreshing or returning from another page.");
}
}
The utility class:
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
public class BrowserCloseDetector {
private static final String COOKIE = "detector";
private static BrowserCloseDetector instance;
private BrowserCloseDetector() {
Window.addWindowClosingHandler(new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
Cookies.setCookie(COOKIE, "");
}
});
}
public static BrowserCloseDetector get() {
return (instance == null) ? instance = new BrowserCloseDetector() : instance;
}
public boolean wasClosed() {
return Cookies.getCookie(COOKIE) == null;
}
}
Have you tried
<BODY onUnload = "scriptname">
in your gwt hosting/launching html file?
I am thinking that if you defined a map "hash" (i.e. a javascript pseudo hash) in the hosting file and then accessed the "hash" in GWT through Dictionary class, you could update values in that hash as the user progresses through the gwt app. Which means, your programming style would require you to log milestones on the user's progress onto this map.
When the user closes the browser page, the onunload script of the launching html page would be triggered. That script would access the map to figure out what needs to be updated to the server, or what other url to launch.
I am intereted too if someone got a solution (GWT/java side only).
Maybe we can do it with HistoryListerner ?
1-set a flag for your current viewing page.
2-when ClosingHandler event, launch a "timeout" on server-side (for example 10s)
3-if during this time your got a massage from HistoryListerner with the same last flag so it was just a refresh.
of disconnect if timer is over...
Is not a good solution but I think it is easy to do... If someone have a better one...