Using JQuery to Detect If on a Mobile Phone

JQuery and/or JavaScript have no native mechanism to determine whether a page is loaded on a mobile phone or not. However, CSS media queries offer this capability. I found the following nice trick on stackoverflow to utilize media queries to help JS/JQuery applications to determine whether they run in a mobile.

First, insert an arbitrary div somewhere in the body of your HTML document such as:

<div id=”mobileDetector”></div>

Then, add the following CSS:

@media only screen and (max-width: 480px) {
#mobileDetector { display: none; }
}

(Note: You can also use the width 767px or so to also capture tablets).

Finally, the following JQuery function can be used to determine if on a mobile or not:

(function($) {
  $.isMobile = function() { 
      return $('#mobileDetector').css('display') === 'none'; 
  }
}) (jQuery);

New Online Markdown Editor

nodejump is a small web application to create and publish web pages using the Markdown markup language.

It’s really easy to get started creating a new document (and therewith a new webpage). Just open the following link:

http://nodejump.com

The main features of this editor are the following:

  • Publish simple web pages from various devices (desktop, mobile) quickly and easily.
  • Allow to share documents for viewing and collaborative editing via simple hyperlinks.
  • Allow users to use the tool with and without registering.
  • Switch between editing and viewing in real-time.
  • Synchronize documents opened on multiple locations in real-time.

Screenshots

The editor is built to load quickly and scale for various screen resolutions.

Switching between ‘edit’ and ‘view’ mode is done in real-time both in desktop and mobile environments.

Further Resources

Source code on github

Application documentation

Beware of BootstrapCDN :(

A few days ago, I discovered the service BootstapCDN. I really like the idea to serve standard libraries such as JQuery or Twitter Bootstrap through central Content Delivery Networks. Especially since serving libraries through a standard location enables clients to not have to download these libraries at all (if the CDN server is configured for caching correctly).

However, already after a few days of using BootstrapCDN to provide the Twitter bootstrap files for a few web applications, the service was/is down for a few hours. In consequence, otherwise slightly better looking webpages are served such as in the example below:

I think the idea of services like BootstrapCDN is really great, and, the service explicitly warns that ‘This free service comes with no warranty.’ So, if it is not work as expected, that is fair enough.

However, most of the time all dependencies of a web application need to be available in order for it to function as intended. Therefore, even if the CDN just fails sometimes (my sample is really small -just a few days and one outtime), it would be better to serve the libraries from your own server. Since, when your server would be down, well, the availability of third party libraries is anyway of limited help.

Internet Explorer ‘SCRIPT1002: Syntax error’: Help!?!

Problem

A script that otherwise is interpreted by other major browsers (Chrome/ Firefox) without problems, prompts Internet Explorer to issue an error along the lines of:

SCRIPT1002: Syntax error
edit-snapshot, line 2230 character 1

Analysis

I think this error can broadly be interpreted as: there is some seriously illegal markup in your script (according to IE’s definition)

Solution

The script error will usually (unhelpfully) point to the end of the script definition, the </script> tag. Essentially, the best strategy I could come up with, to sift through your script and search for anything unusual. For instance:

  • Does your JavaScript define new ‘<script></script>’ elements by using the exact string ‘<script>’
  • Does your JavaScript markup resembling HTML/XML style comments, such as `<!–‘ or ‘–>’

Resources

JAVASCRIPT WITHIN AJAX FAILS TO LOAD IN IE – ERROR 80020101

Regular Expression to Find HTML Comments in Java

Problem

You would like to select the contents of all comments in an HTML (or XML) document using Java Regular Expressions.

For instance:

<html>

<!– FOR ME TO SELECT –>

</html>

Solution

There is a powerful regular expression, which can be found on this page.

static final String commentRegex = “(// )?\\<![ \\r\\n\\t]*(–([^\\-]|[\\r\\n]|-[^\\-])*–[ \\r\\n\\t]*)\\>”;

However, this regular expression might lead to your application to ‘hang’ if there are (bad, bad input) documents with starting comments without matching comment end, like:

<html>

<!– I AM SO EVIL

</html>

To prevent your application to hang in this case, you can search for the beginnings and ends of comments with two separate matchers:

static final String matchCommentStart = “\\<![ \\r\\n\\t]*–“;

static final String matchCommentEnd = “–[ \\r\\n\\t]*\\>”;

You can find a live example for this code in this class.

 

 

Something other than a Java object was returned from JSNI method

Google Web Toolkit allows building powerful bridges between the world of Java and JavaScript using so called JS overlay objects.

However, these overlay objects can become it bit tricky if it is not certain what the type of objects passed from JavaScript will be.

Wait? Types and JavaScript? Yes, but only the most fundamental ones of `string`, `number` and `Boolean`.

Problem

Variations of the following exceptions are reported in GWT hosted mode, if the wrong type is declared in the JS overlay object.

java.lang.IllegalArgumentException: Something other than a Java object was returned from JSNI method ‘@one.app.js.api.IntParams::getValue()’: JS value of type boolean, expected java.lang.Object

 

In the example above, a method such as the following might have been declared in the JS overlay object:

public final native Object getValue()/*-{ this.value; }-*/;

Howerver, `this.value` happened to be of the type `boolean` in JavaScript.

Solution

An easy solution is to change the declaration of the method in the JavaScript overlay type to:

public final native boolean getValue()/*-{ this.value; }-*/;

However, things are a bit more difficult, if depending on the context, `this.value` can take on values of different type than boolean (for instance `number` or java script object).

In this case, the a little bit more work is required. First, the function in the overlay type must be changed to something like:

public final native Object getValue() /*-{ 
	if ( this.value && 
	     ((typeof this.value == "number") || 
	      (typeof this.value == "boolean")) ) {
		return {
			type: "JsAtomicTypeWrapper",
			value: this.value
		};
	}

	return this.value;
}-*/;

This method replaces the value with a wrapper JS object. For retrieving the value, another JS overlay type can be introduced to extract the value such as:

ublic class JsAtomicTypeWrapper extends JavaScriptObject {

	protected JsAtomicTypeWrapper() {
	}

	public final native boolean isWrapper()/*-{ 
		if ( this.type && this.type == "JsAtomicTypeWrapper") return true;
		return false;
	}-*/;

	public final native boolean isBoolean()/*-{ 
		return typeof this.value == "boolean";
	}-*/;

	public final native boolean isDouble()/*-{ 
		return !isNaN(parseFloat(this.value));
	}-*/;

	public final native boolean isInteger()/*-{ 
		return this.value % 1 === 0;
	}-*/;

	public final Object getValue() {
		if (isBoolean()) {
			return getBooleanValue();
		}

		if (isInteger()) {
			return getIntValue();
		}

		if (isDouble()) {
			return getDoubleValue();
		}

		return getGenericValue();

	}

	public final native Object getGenericValue()/*-{ 
		return this.value; 
	}-*/;

	public final native int getIntValue()/*-{ 
		return this.value; 
	}-*/;

	public final native double getDoubleValue()/*-{ 
		return this.value; 
	}-*/;

	public final native boolean getBooleanValue()/*-{ 
		return this.value; 
	}-*/;

}

When reading the returned value of the first JS overlay type, the JsAtomicType Wrapper overlay type can be used as follows:

JsAtomicTypeWrapper wrapper;
wrapper = ((JavaScriptObject) jso.getValue()).cast();

if (wrapper.isWrapper()) {
	GWT.log("Number value: " + wrapper.getValue());
	GWT.log("Number value class: " + wrapper.getValue().getClass());
}

Jangle Java: Upload & Load Data

This tutorial illustrates in a few simple steps how to upload and download data from a Java application into the appjangle platform.

You can find the source code of the completed steps 2 & 3 on github:

T_JangleJavaShort_Upload.java

U_JangleJavaShort_Load.java

Step 1: Link Client Libraries

To upload data to appjangle from a Java application, the onedb Java Client API will be required. Download the latests version of the ‘onedb Java client’ from the onedb downloads page:

http://cms.onedb.de/downloads

Drop the client library into a Java project of your favorite IDE or assure they are added to the classpath of your Java app in another way of your choice.

Step 2: Upload Data

Define a new Java class and add a main method. Add the following code to your app:

final CoreDsl dsl = OneJre.init();

final OneClient client = dsl.createClient();

dsl.seed(client, new WhenSeeded() {

	@Override
	public void thenDo(final WithSeedResult sr) {

		final OneNode parlor = dsl.append("My Pizza Parlor")
				.to(sr.seedNode()).atAddress("./pizzaParlor")
				.in(client);

		dsl.append("Awsome Pizza!").to(parlor).in(client);

		System.out.println("Pizza Parlor Created:");
		System.out.println("at node      : " + parlor.getId());
		System.out.println("access secret: " + sr.accessToken());

		dsl.shutdown(client).and(WhenShutdown.DO_NOTHING);
	}
});

Running the application should result in an output such as the following.

Pizza Parlor Created:
at node      : https://u1.linnk.it/lnzvwp/sd1/3/h/sd/pizzaParlor
access secret: rfa______1rd

Important: Save the node and access secret for step 3.

The application above defines a number of interconnected data items on the appjangle platform:

  1. a seed root node is created by the call to the seed operation.
  2. a node with the value ‘My Pizza Parlor’ is appended to this seed node at the address ./pizzaParlor (where . denotes the seed root node)
  3. a node with the value ‘Awsome Pizza!’ is appeneded to the ‘pizza parlor’ node.

Each of these data items and their interconnections are uploaded to the appjangle platform, and, using their respective identifiers (URIs), they can be accessed from any Internet connected device using various mechansims:

  1. If the device supports Java and/or JavaScript, the data itmes can be accessed using the onedb client libraries.
  2. Per REST in various formats, for instance:

    1. XML: pizzaParlor/Awsome_Piz0.value.xml
    2. JSON: pizzaParlor/Awsome_Piz0.value.json
    3. HTML: pizzaParlor.node.html

Step 3: Load Data

While new data was defined on the appjangle platform in the previous step, in this step, the defined data is loaded and extended.

For this, define a new Java class with the following main method. Replace the node and access secret with the ones you have saved in the previous step:

final CoreDsl dsl = OneJre.init();

final OneClient client = dsl.createClient();

dsl.load("[your node]").withSecret("[your secret]")
		.in(client).and(new WhenLoaded() {

			@Override
			public void thenDo(final WithLoadResult<Object> lr) {

				final OneNode servings = dsl.append("servings")
						.to(lr.loadedNode()).atAddress("./servings")
						.in(client);

				dsl.append("Pizza!").to(servings).in(client);

				System.out.println("Servings defined.");

				dsl.shutdown(client).and(WhenShutdown.DO_NOTHING);
			}
		});

Running the app, will result in the following:

  1. The previously defined ‘pizza parlor’ node is loaded into a local client context.
  2. A node ‘servings’ is appended to the pizza parlor node at the specific address ./servings.
  3. One value “Pizza!” is added to the servings node.
  4. The local client context is closed using the shutdown operation and all changed data is uploaded to the appjangle platform.

Browsing the the pizza parlor node will now show two nodes attached to this node, the descriptive node ‘Awsome Pizza’ as well as a node containing the servings such as the following:

http://u1.linnk.it/lnzvwp/sd1/2/h/sd/pizzaParlor

Learning More

Please check the second part of this tutorial:

Jangle Java: Synchronization

You can also find more information on various aspects touched upon in this tutorial on the onedb documentation page.