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.

Jangle Java: Synchronization

This tutorial is a continutation of the ‘Jangle Java: Upload & Load‘ tutorial. Make sure to follow the steps of this tutorial first before doing this one.

This tutorial shows the synchronization capabilities of the appjangle Java client. In particular, the well known producer-consumer scenario is applied on the simple pizza parlor data defined in the upload & load tutorial.

You can find the source code of the completed tutorial on github: V_JangleJavaShort_Synchronize.java.

Step 1: Define the Producer

The producer in this simple scenario adds nodes with the value "Pizza!" to the ./servings node defined for the pizza parlor.

For this, define a new Java class Producer as shown below. Please replace the pizza parlor node path with the path to the pizza parlor data created in the upload & load tutoria and replace the access secret as well.

static class Producer implements Runnable {

	final CoreDsl dsl = OneJre.init();
	final OneClient client = dsl.createClient();

	@Override
	public void run() {
		try {
			Thread.sleep(600);
		} catch (final InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("Making pizza ...");
		dsl.load(
				"[your node]/servings")
				.withSecret("[your secret]").in(client)
				.and(new WhenLoaded() {

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

						dsl.append(new String("Pizza!"))
								.to(sr.loadedNode()).in(client);

						dsl.commit(client).and(WhenCommitted.DO_NOTHING);

						System.out.println("... pizza made!");
						run();

					}

				});

	}

}

Calling the run() method of this class will start a recursive loop in which nodes with the value “Pizza!” will be appended to pizzaParlor/servings. The resulting changes to the local client data will be uploaded to the server via the commit operation.

Step 2: Defining the Consumer

The consumer in this scenario will ‘monitor’ the pizza parlor’s servings node for any changes. If a change occurs, the consumer will replace all “Pizza!” values with outcries of yummy!

Define a new class Consumer as follows (again replace address and access secret!):

class Consumer implements Runnable {

	private volatile int eaten = 0;

	@Override
	public void run() {
		final CoreDsl dsl = OneJre.init();
		final OneClient client = dsl.createClient();

		dsl.monitor(
				dsl.reference("[your node]/servings"))
				.inInterval(Interval.FAST).withSecret("[your secret]")
				.in(client).and(new WhenNodeChanged() {

					@Override
					public void thenDo(final WithNodeChangedContext context) {

						checkForPizza(dsl, client, context);

					}

				});
	}

This class so far will install a monitor on the ./servings node and call a checkForPizza method every time a change has been made to the servings node.

The checkForPizza method can be defined as follows:

private void checkForPizza(final CoreDsl dsl, final OneClient client,
		final WithNodeChangedContext context) {
	dsl.selectFrom(context.changedNode()).theChildren()
			.ofType(String.class).in(client)
			.and(new WhenChildrenSelected<OneTypedReference<String>>() {

				@Override
				public void thenDo(
						final WithChildrenSelectedResult<OneTypedReference<String>> csr) {

					for (final OneTypedReference<String> pizza : csr
							.children()) {

						if (!dsl.dereference(pizza).in(client)
								.equals("Pizza!")) {
							continue;
						}

						dsl.replace(pizza)
								.with("Yummy (" + eaten + ")!")
								.in(client);
						eaten++;
						System.out.println("Ate " + eaten
								+ " Pizza(s)!");
					}

					dsl.commit(client).and(WhenCommitted.DO_NOTHING);

					if (eaten > 10) {
						System.out.println("Had enough pizza.");
						context.monitor().stop(WhenShutdown.DO_NOTHING);
						System.exit(0);
					}
				}
			});
}

This method does the following:

  1. All child nodes, which have the class String.class are selected from the pizzaParlor/servings node through calling the method selectFrom(...).
  2. All children of the class String are checked whether their value equals “Pizza!”.
  3. If so, the respective value is replaces with the value “Yummy (x)!”.
  4. Lastly, all changes made to the servings node are committed to the appjangle cloud.

Producer and consumer can be assembled in an application such as given here. Running this application should result in an output such as the following:

Making pizza ...
Ate 1 Pizza(s)!
... pizza made!
Making pizza ...
... pizza made!
Making pizza ...
... pizza made!
Ate 2 Pizza(s)!
Ate 3 Pizza(s)!
Making pizza ...
... pizza made!
Making pizza ...
Ate 4 Pizza(s)!
... pizza made!
Making pizza ...

While such a producer/consumer example is easily accomplished using threads and shared resources, the producer and consumer in the given example need not be part of one application. Indeed, producer and consumer can run on seperate Java-compatible devices as long as these are connected to the Internet.

The work of producer and consumer can further be traced through the various REST interfaces as seen for instance on the following page:

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

What’s more?

To learn more about the capabilities of appjangle and onedb, you can check:

onedb 0.0.6 powers appjangle

The last few weeks a great number of improvements and changes have been made to the onedb database. Chiefly, with the development of the JavaScript API, onedb has been integrated into the new appjangle platform.

This platform is designed to enable not only to store data from applications from various platforms but also to aid you in developing and deploying these applications. Please note that the appjangle platform is currently in PREVIEW and various features are in the process of being completed.

Currently, all already documented features of onedb are available on appjangle. However, it is not possible anymore to obtain an API key from the onedb website. Instead, signing up for appjangle will get you an API key you can use to develop Java applications.

There is a new, short tutorial helping to get started developing Java apps with appjangle/onedb. Check out:

Jangle Java: Upload & Load Tutorial

Jangle Java: Synchronization Tutorial

New Features

Here a short list of the additional capabilities of the onedb engine in version 0.0.6:

Seed operation

The seed operation has been added as further element operation to the client API. The seed operation allows creating a root node on the appjangle platform. This root node is meant as a space for a small amount of data, required if it is not possible to connect to a registered user’s database. It’s great for creating a space to try out the various features, too.

Currently, it is encouraged to limit nodes appended to a seed node to about 50 nodes. All nodes appended to a seed are by default protected by a private write secret but they do allow public read.

If more data is to be uploaded or the data should also be private read protected, the createRealm operation can be used.

A usage example for the seed operation can be found in the following Java App:

RapidDataUploadFromAnywhere.java

Binary Nodes

It is now possible to upload nodes with binary content such as images to the appjangle platform.

You can create a new node with binary content as follows:

byte[] myData = ...
OneBytes node = one.common.nodes.newByteData(myData, "image/png");
One.append(node).to(parent).atAddress("./mypic").in(c);

You can then access this picture through the REST server, for instance:

http://u1.linnk.it/xxzv0z/imgTst/odblogo.value.png

Note that you will need to add “.value.png” to the nodes address to assure it is rendered as binary data. Other currently supported formats for binary data are:

  • .value.jpg
  • .value.jpeg
  • .value.ico
  • .value.gif

Markdown Serialization

Text nodes, which contain content in the Markdown format, can now be rendered into HTML automatically. Just add the marker One.reference("https://u1.linnk.it/6wbnoq/Types/isMarkdown") to your plain text node.

A sample Java app is available on github:

ServerSideMarkdownRendering.java

Template Rendering

A simple syntax allows now to embed text nodes within other text nodes. This is a feature heavily utilized for the appjangle JavaScript source files.

See the sample Java app on github, which illustrates the template feature:

EmbeddingTextNodes.java

Using a slight variation of the syntax, it is also possible to embed HTML rendered from a Markdown template into a HTML page. The syntax for this is:

<!-- embedMarkdown("[path to node]") -->

User Registration/Login

The onedb client engine now allows to interface with the user login and registration of the appjangle platform. For this, the two operations registerUser(..) and loginUser(..) have been added to the core API.

These operations do not only allow to register and login a user for the appjangle platform but also build login/registration capabilities for your own apps. These operations require to specify a applicationNodeUri. This can be an address to any node on the appjangle platform. The specified node can then function as a global unique identifier for your application and associated registered users.

Have a look at the appjangle login module and the appjangle signin module (you will need to check the page’s source) for examples of usage of this API. The Java API works very similar to the JavaScript version and examples for this will be added shortly.

Bug Fixes

A number of bugs in the onedb core engine have been fixed. Chiefly:

  • References to nodes stored on other server instances would sometimes not be resolved correctly. To fix this issues, all references are always assumed to be resolvable. In consequence, it is not permitted anymore to add a reference object to a network, if there is no resolvable node defined for this reference.
  • Fixed a bug in the authorization system. If a child node would have a matching security token with insufficient authorization but the parent node would have a security token with sufficient authorization, the token in the parent node would not be recognized.
  • A number of stability improvements have been made to the routines rendering HTML nodes.