Jquery UI: Add a Shadow Line Around a Dialog Box

I really like the style of Facebook (or LinkedIn) Javascript popup dialogs – a thin semi-transparent shadow line around the dialog. It looks nice and from the usability point of view it has a purpose, as it is attracts user’s attention to the important component on the screen.

There are many examples of custom Javascript dialogs on the Internet that explain how to achieve this. While many solutions are really good, I wanted to make use of the dialog provided by jQuery UI library by default.

I have came up with a solution that works, but I don’t think it is the most elegant way to do it (CSS is not my strong side). The solution is quite simple, and pretty straight forward (I think :) ). The following are the final results as tested in FF3, IE8, Opera 10 and Chrome 10, please note the shadow line around the dialog:

Firefox - jQuery dialog box with semi-transparent shadow around it

Firefox 3.6.16

Internet Explorer - jQuery dialog box with semi-transparent shadow around it

Internet Explorer 8.0.76

opera-10.63

opera-10.63

chrome-10.0.648

First I defined a CSS class that’s going to have properties for the background shadow (the bg_dialog_modeless_mask.png is an 8×8 gray square image)

.dialog-mask {
 -moz-border-radius:5px 5px 5px 5px;
 -webkit-border-radius: 5px;
 border-radius: 5px;
 background:url("../images/bg_dialog_modeless_mask.png") repeat scroll left top transparent;
}

Somewhere on my HTML page, I defined a DIV that’s going to be the dialog holder:

<div id="popup-holder"></div>

I added jQuery dialog init statement in my global JS file:

$(document).ready(function(){

 $( '#popup-holder' ).dialog({
       autoOpen: false,
       height: 350,
       width: 530,
       modal: true,
       resizable: true,
       draggable: false,
       buttons: {
         Cancel: function() {
            $( this ).dialog( "close" );
            $( '#dialog-wrapper' ).remove();
         }
      },
      close: function() {
            $( '#dialog-wrapper' ).remove();
      },
      open: function() {
            wrapJqueryDialog($( this ));
      },
      resize: function() {
            wrapJqueryDialog($( this ));
      }
   });
});

The #dialog-wrapper is the ID of the DIV that holds the semi-transparent shadow which wraps the dialog. The wrapJqueryDialog function creates the shadow when dialog is opened, and handles the shadow resize when dialog is resized (it is also possible to add an event to drag the shadow when dialog has draggable option set to true).

Now the important part, the wrapJqueryDialog function:

function wrapJqueryDialog(dialogWidgetObj)  {
	//The width and height of the shadow line wrapping the dialog
        var shadowWidth = 20;

        //Lets remove the shadow holder to start clean
	$( '#dialog-wrapper' ).remove();

        //Gets the current dialog widget
	var widget = dialogWidgetObj.dialog( "widget" );

        //Create the shadow holder DIV that has the background shadow CSS class
	var dialogwrapper = $('<div id="dialog-wrapper" class="dialog-mask" />');

	//For IE, the holder must be appended to the body first before any manipulation.
	$('body').append(dialogwrapper);

        //Lets copy default inline styles from the dialog widget to the shadow holder
	dialogwrapper.attr("style", widget.attr("style"));

        //Lets position the shadow holder before and above the dialog widget
	dialogwrapper.css("top", parseInt(dialogwrapper.css("top")) - shadowWidth);
	dialogwrapper.css("left", parseInt(dialogwrapper.css("left")) - shadowWidth);

        dialogwrapper.css("position", "absolute");

	//Make sure that the dialog widget is infront of surrounding shadow box and overlay (if there is one set)
	widget.css("z-index", (parseInt(widget.css("z-index")) + 1));

	//Add to the shadow width default padding value from the class '.ui-dialog' and
	//default border width from the class '.ui-widget-content' (1px times two)
	var finalShadowWidth = shadowWidth + parseInt(widget.css("padding-top")) + 2;

	var widgetHeight = parseInt(widget.css("height"));
        //Lets extend the shadow holder height
	dialogwrapper.css("height", widgetHeight + (finalShadowWidth * 2));

	var widgetWidth = parseInt(widget.css("width"));
	//Lets extend the shadow holder width
        dialogwrapper.css("width", widgetWidth + (finalShadowWidth * 2));
}

That’s all when it comes to code (don’t forget to add to your HTML/JS code a dialog trigger, it can be a link or a button). I am really interested to hear your comments about it and suggestions. If you can suggest a better way of implementation – please do so, I am really keen to know :)

How To Select a Child Element Using jQuery

Let’s assume you have an HTML string containing a parent element with a number of children and their sub children elements. If you’d like to extract HTML of one of the children (by class name or id), you can use this jQuery line:

var html = $(htmlString).find('div.target').html();

It can be useful when you get an AJAX response from the server, and only a particular section needs to extracted.

Enriching Rich Internet Applications with Rule-Based Reasoning

I came across a Firefox Add-On today by Matthias Tylkowski, that lets user to modify the browser view of his/her preferred web pages. For example, user can modify the appearance of cnn.com to suit his/her needs.

The add-on or the web rules is a JSON-based rule language, where each rule is a JSON object. In addition, Javascript is used for method calls. The web rules use Drools-like condition language:

{
    &quot;id&quot;:&quot;rule101&quot;,  &quot;appliesTo&quot;: [
              &quot;http://www.cnn.com&quot;],
               &quot;condition&quot;:  &quot;$X:Element( class == 'note', $Y:firstChild ) &amp;&amp;
                              ($Y.nodeName == 'ul')&quot;,
               &quot;actions&quot;:[  &quot;changeBackground($Y, 'blue')&quot;   ]
}

For all elements of class note having as first child an ul, change the first child background color to blue.

I think its a quite cool add-on.

Resources:
JSON RuleS

Redefining Web Applications with AJAX, Servlets and JSON

In this article I would like to show how JSON (JavaScript Object Notation) and Java servlet can be used together in a little AJAX (Asynchronous JavaScript and XML) application.

To give brief description to those who are not closely familiar with JSON -

JSON is a lightweight syntax for representing data, which makes working with it much more pleasant than with XML and makes AJAX applications faster. Also, when working with JSON, there is no need for an XML parsing.

In the following example, I am going to create a callback servlet that fetches and parses an RSS feed. Then the parsed feed data is passed to the client side in a form of JSON. The data then formatted and presented to the user. The client uses AJAX call to query the servlet.

For this application, I used three third-party libraries:

  1. JSON library provided by JSON.org and extended by JSON-RPC-Java which allows to create and easily parse JSON data through Java code. This library can run in a Servlet container such as Tomcat, JBoss and other J2EE Application servers.
  2. Project ROME
    ROME is an set of open source Java tools for parsing, generating and publishing RSS and Atom feeds.
  3. JDOM XML parser
    JDOM is a Java-based “document object model” for XML files. JDOM serves the same purpose as DOM, but is easier to use

The libraries are included in the source code which accompanies this article. This application example is also included as a WAR archive, ready to be deployed on Tomcat.

The following is my servlet implementation. The servlet fetches and parses feed data. The JSON library mentioned previously allows me easily to create and populate JSON object.

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.fetcher.FeedFetcher;
import com.sun.syndication.fetcher.FetcherException;
import com.sun.syndication.fetcher.impl.FeedFetcherCache;
import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
import com.sun.syndication.io.FeedException;

/**
* @author Alexander Zagniotov (http://javabeans.asia)
*/
public class JsonServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String BLOG_URL = &quot;http://javabeans.asia/rss.xml&quot;;
	private static final String CONTENT_TYPE = &quot;application/json&quot;;
	private FeedFetcherCache feedInfoCache = null;
	private FeedFetcher feedFetcher = null;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		feedInfoCache = HashMapFeedInfoCache.getInstance();
		feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		SyndFeed feed = this.feedFethcer(BLOG_URL);
		if (feed != null) {
			String json = this.feedToJSON(feed);
			response.setContentType(CONTENT_TYPE);
			response.setHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;);
			response.getWriter().write(json);
		}
	}

	private SyndFeed feedFethcer(String url) {
		SyndFeed feed = null;
		try {
			feed = feedFetcher.retrieveFeed(new URL(BLOG_URL));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (FeedException e) {
			e.printStackTrace();
		} catch (FetcherException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return feed;
	}

	private String feedToJSON(SyndFeed feed) {

		JSONObject jsonObj = new JSONObject();
		JSONArray jsonEntryTitles = new JSONArray();
		jsonObj.put(&quot;blogtitle&quot;, feed.getTitle());
		jsonObj.put(&quot;blogdescription&quot;, feed.getDescription());
		jsonObj.put(&quot;bloglanguage&quot;, feed.getLanguage());
		jsonObj.put(&quot;bloglink&quot;, feed.getLink());
		jsonObj.put(&quot;author&quot;, feed.getCopyright());

		List&lt;?&gt; feedEntries = feed.getEntries();

		for (Object c : feedEntries) {
			SyndEntry syndicateEntry = (SyndEntry) c;
			jsonEntryTitles.put(syndicateEntry.getTitle());
		}

		jsonObj.put(&quot;blogentrytitles&quot;, jsonEntryTitles);
		return jsonObj.toString();
	}
}

As you can see it is very easy to construct JSON objects and arrays on the server side and pass them to the client. For the purpose of this example I am getting my data from RSS feed, but the data can also be coming from DB etc.

The following is my client implementation. The client queries the servlet using AJAX call. When an AJAX call returns a response from the servlet in a form of JSON object, the object data is formatted and information about the RSS feed is presented to the client:

&lt;html&gt;
    &lt;head&gt;
    &lt;title&gt;Java Beans dot Asia&lt;/title&gt;

    &lt;script language=&quot;JavaScript&quot; type=&quot;text/javascript&quot;&gt;

        var httpRequest = null;

    function getDescriptionAsJSON() {
        var description = document.getElementById('description');
        description.innerHTML = &quot;Loading, please wait ...&quot;;

        var url = &quot;http://localhost:8080/json/json&quot;;
        if(window.XMLHttpRequest){
            httpRequest = new XMLHttpRequest();
        } else if(window.ActiveXObject){
            httpRequest = new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);
        }

        httpRequest.open(&quot;GET&quot;, url, true);
        httpRequest.onreadystatechange = handler;
        httpRequest.send(null);
    }

    function handler() {
        if (httpRequest.readyState == 4) {
            if (httpRequest.status == 200) {
                processJSON(httpRequest.responseText);
            }
        }
    }

    function processJSON(jsonObjectString) {

        var description = document.getElementById('description');

        //Since JSON is a subset of JavaScript, I am using
        //JavaScript's own compiler to parse JSON in one line!

        var jsonObject = eval('(' + jsonObjectString + ')')
        var text = &quot;&quot;;

        text += &quot;Author: &quot; + jsonObject.author + &quot;&lt; br /&gt;&quot;;
        text += &quot;Blog Name: &quot; + jsonObject.blogtitle + &quot;&lt; br /&gt;&quot;;
        text += &quot;Blog URL: &quot; +    jsonObject.bloglink + &quot;&lt; br /&gt;&quot;;
        text += &quot;Blog Description: &quot; +    jsonObject.blogdescription + &quot;&lt; br /&gt;&quot;;
        text += &quot;Blog Language: &quot; + jsonObject.bloglanguage + &quot;&lt; br /&gt;&quot;;

        description.innerHTML = text;
        var entries = &quot;Last &quot; + jsonObject.blogentrytitles.length + &quot; blog entries are:nn&quot;;

        for (var index = 0; index &lt; jsonObject.blogentrytitles.length; index ++) {
            entries += (index + 1) + &quot;: &quot; + jsonObject.blogentrytitles[index] + &quot;n&quot;;
        }
        alert(entries);
    }

    &lt;/script&gt;

    &lt;/head&gt;
    &lt;body&gt;
        &lt;img src=&quot;images/javabeansmugshot_120x120.jpg&quot; border=&quot;1&quot; /&gt;&lt; br /&gt;&lt; br /&gt;
        &lt;div id=&quot;description&quot;&gt;&lt;/div&gt;&lt; br /&gt;&lt; br /&gt;
        &lt;a href=&quot;javascript:void(0)&quot; onclick=&quot;return getDescriptionAsJSON();&quot;&gt;Click to get description!&lt;/a&gt;
    &lt;/body&gt;
&lt;/html&gt;

As you could see, JSON data can be easily parsed on the client side with the help of Java script eval() function. To remind – JSON is a subset of Java script, therefore eval() will produce a valid object.

Keep in mind, that there is a need for extra care when using eval. The problem is that eval will compile and execute Java script code that coming back from the response. This could cause a security risk if the response data is coming from an untrusted source.

That’s it. I hope this example was clear and helpful :)

source json servlets ajax

Please note that this example was tested by me and its working fine. The source code as mentioned previously is included as Eclipse project. You can simply create a new Java project from the existing Ant build.xml file.

Comments/flames are appreciated :)

Cheers

How to Prevent iFrame Breakaway

Few days ago I was searching for a solution to the problem I’ve encountered – I needed to prevent a third party page to break out of iframe inside a web page of my web application. For people who are not closely familiar with JavaScript, the following JS snippet will make it more clear how page can break out of iframe:

if (top.location.href != self.location.href)  {
    top.location.href = self.location.href;
}

If the current page is not the parent window – become the parent window.

I needed to implement something on my end, that would block or prevent the above script or similar to it from executing. I’ve spent several hours browsing the Net, talking to people on IRC and simply playing trial and error.

After some time, I understood that I wont be able to find a solution to my problem, simply because there is none unfortunately. But, having said that, I have some findings to share:

  1. There is iframe security attribute which only works on IE. Setting this attribute to security=”restricted”, will prevent iframe to break out. Its always “nice” to see that MS have few tricks up their sleeve :). Also, on one of the forums, someone mentioned that the same attribute will work under Opera as well as under IE. I personally haven’t tested it my self under Opera, I can just say that it works for IE and not FF.
  2. To make use of window.onbeforeunload event and prompt user with a dialog that requires user’s input if he agrees to navigate away from the current page. If user disagrees (clicks “cancel”), he will remain on the current page. So here in a sense iframe breakaway was canceled. By the way, there is no way to suppress the dialog prompt and make event from clicking “cancel” default.
  3. To grab the content of third party page using PHP Curl lib and to create your own placeholder page for that content. Then the placeholder page can be put inside iframe. The page or the grabbed content will not attempt to breakout, but any request submitted to the placeholder page (hyper link or button click on the grabbed content) will cause page to unload.

Also, while researching, I came across this post that talks about preventing iframe breakaway and click jacking with the help of 204 header response code.

After all that, my conclusion is:
If the page inside iframe is not yours, in other words it is a page hosted under another domain, its not possible actually to stop a page from unloading. Having something like that, would allow malicious sites to “trap” a user indefinitely.

I would love to hear any other suggestions regarding iframe breakout you may have dear readers.

Cheers

Detecting an Internet Connection With Javascript

The other day I was developing small client-server application where I needed to check using Javascript on the client’s side whether active Internet connection exists, before submitting request to the server.

Javascript does not allow you to do ping, and even so many websites protect against ping requests (ICMP echo), so I had to come up with some alternatives.

One of the nice solutions that I have found is to create an Image object and to specify as image source, URL to an image located on a remote server. Then to test, if the newly created Image object has height or width greater than zero.

If it is greater, what it means is that there is active Internet connection, since it was possible to create Image object using image or icon located on a remote server.

The downside here is that path to the image or image filename may change in the future on the target remote server, and as a result of that your Javascript function will stop working.

While thinking what image should I link to, I decided to use Google’s favicon. I tend to think that the favicon is not something that is going to change very often. I also considered to use Goggle logo, but favicon is much smaller in size.
(Another thing worth remembering is to allow some time to retrieve the remote image, which is another reason why I went for the favicon).

The solution is:

function testConnection() {
   var googleFavIcon = new Image();
   googleFavIcon.src =
               "http://www.google.com/favicon.ico";

   if(googleFavIcon.height>0)  {
       //do something
    }
    else {
      //warn user
    }
}

Just keep in mind, that the remote image is cached once you got it. If you decide to test connection again, you have to make sure that you are not using the cached image, but trying to retrieve it again from the remote server. To prevent caching, you can add some random parameter to the URL:


http://www.google.com/favicon.ico?param=[random-value]