jQuery Moblie, Phonegap alerts

I don't particularly like the look and feel of the standard alert message but you can't argue about the ease of use.

Fortunately it is easy to change the look and feel. I do this by overwriting the native alert method. You can do the same thing in web apps but IE whines about it being a security violation. At least in Phonegap apps running on iOS there is no problem. I have not tested it on Android.

The javascript is very simple. I put this in after jQuery has loaded the page.

view plain print about
1alert=function(ex){
2    $("#alertMessage").html(ex);
3    $("#alertbutton").click();
4}
5$("#alertid").on("click","#alertclose",function(){
6    $('.ui-dialog').dialog('close');
7});

Notice that I am redefining the native alert method.

I have the following in the html page.

view plain print about
1<div data-role="page" id="alertid">
2    <div data-role="header">
3        <h1>Attention required</h1>
4    </div><!-- /header -->
5    <div data-role="content" data-theme="e">
6        <p id="alertMessage"></p>
7        <a href="#" data-role="button" data-theme="b" data-inline="true" id="alertclose">Ok</a>
8        <a href="#alertid" data-rel="dialog" id="alertbutton" style="display:none"></a>
9    </div><!--END OF jqMobile Content Div-->
10</div>

The hidden button just gives me a simple way to open the dialog. Notice that I trigger a click on it when the alert method is called.

That is all there is to it. The remainder of your code just calls alert as appropriate.

A couple of screen shots to illustrate. When the user clicks on the tweet icon the code verifies that Twitter is set up on the device. If not we raise an alert.

Refresh jQuery Mobile Listview Themes at Runtime

jQuery mobile's ListViews are very nice but the framework provides no methods for changing the theme (either of the entire list or an individual element) at run time.

Quite often I need to change the appearance of an element based on state. For example I use a listview on the left hand side of the page and change the content on the right hand side when the user clicks on a category. I, of course, want the selected category to be a different color than the rest of the list.

One would think you could just change the "data-theme" attribute of the element you click on and refresh the list view. This doesn't work because the element you click on doesn't even have a data-theme attribute (even though you specified it in the original markup).

This is because the framework places a lot of wrappers around the element(an href) but doesn't attach the data-theme attribute to it.

In order to change the theme there are a few steps:

  1. Determine the current theme
  2. Remove classes associated with the theme on the ancestors of the element
  3. Add classes on those elements corresponding to the new theme
  4. Change the data-theme attribute on the appropriate ancestor
  5. Refresh the listview

I have written a simple function to accomplish this:

view plain print about
1var changeListViewElementTheme = function(selector, theme){
2    try {
3        $(selector).each(function(){
4            try {
5                var btn = $(this);
6                var ggpar = btn.parent().parent().parent();
7                var gggpar = ggpar.parent();
8                var th = ggpar.attr("data-theme");
9                var nth = theme;
10                ggpar.removeClass("ui-btn-up-" + th).addClass("ui-btn-up-" + nth);
11                ggpar.removeClass("ui-btn-down-" + th).addClass("ui-btn-down-" + nth);
12                ggpar.attr("data-theme", nth);
13                gggpar.listview("refresh");
14            }catch(exignore){
15                //silent catch because this will fail for non initialized lists
16                //but thats ok
17            }
18        });
19    }
20    catch (ex) {
21        alert(ex);
22    }
23}

Notice that the classes you need to change are ui-btn-up-x and ui-btn-down-x, where x is the theme (a,b,c,d,e). These classes and the theme exist on the great grandparent of the href element. The listview is the great great grandparent.

You can play with the concept here

That annoying serializeJSON function

One annoying aspect of using a weakly typed language like ColdFusion is that sometimes you really need the type. If you ever have fields which are numeric strings (e.g. phone numbers, ssn, or your database uses varchar for ids which consist only of digits) you have probably had issues if you serialize the data using serializeJSON and send it to the client. SSN's likely will be expressed in scientific notation and leading zeros will be lost in your id's and international phone numbers.

You can always work around this by prepending a "~" to the variable and then stripping it off in javascript but that is kludgy at best.

I have written a parser which preserves appropriate variables as strings when serialized. Since this only works if you can identify the appropriate fields the parser only preserves numerical strings that are part of a struct. If that is too limiting you can always modify the parser to treat all simple values as strings but that means some javascript conversions are necessary on the client to converts strings back to numbers.

The concept is to pass a mapping struct to the parser telling it which elements to preserve as strings. If you pass an empty mapping struct you get the normal CF serialization.

Creating a JSON string for a struct or array is straightforward. The parser I have built id not designed to process multi-dimensional arrays. You just start at the root and recursively call a conversion function until you have processed the entire input.

[More]

A Tricky Problem With a Simple Solution

I have a app where the "words" are actually divs and I would like them to flow as if they were words. That is pretty easy to do, just make the word container float left. The problem comes when the page reflows because the user changes the text size or resizes the browser. The browser reflows perfectly except that sometimes the "spacer div" then becomes the first element on a new line which looks bad.

The question was how to eliminate that? After a bit of head scratching I found a very simple solution.

view plain print about
1var fixLeadingSpaces =function(){
2    $(".wordspace").show();
3    $(".wordspace").each(function(){
4        var t=$(this).offset().top;
5        var pt=$(this).parent().prev().offset().top;
6        if(pt < t){
7            $(this).hide();
8        }
9    });
10}

All the spacer divs have a class "wordspace". I just iterate over that class and determine its position compared to the previous word. If the top of the spacer is greater than that of the previous word then it must be on a new line so I just hide it. I already eliminate adjacent spaces so the previous word is always either a real word or punctuation. I have to use the parent container because the wordspace element is wrapped by another container.

Ya gotta love jQuery

Generation of ApplicationCache Manifest Files

In order to make an application available offline one has to create a manifest file telling the browser which files it can cache and which files require connectivity. Unfortunately, as far as I know, the browser cannot use wildcards for this so we need to list files explicitly.

I, for one, certainly have no interest in hardcoding that list and trying to keep it up to date.

The manifest file format:

CACHE MANIFEST
#Thu Mar 15 16:13:49 MDT 2012
#Total Files: 54
#Explicitly cached files
css/icryptogramplay.css
css/images/ui-icons_ffffff_256x240.png
js/cachelogging.js
...
NETWORK:
#files which require connectivity
setting_debug.cfm
cfcProxy.cfc
Application.cfc
...
OFFLINE:
    
....

# are comments which are ignored by the browser

Because I am too lazy to maintain a hardcoded file I have written a bash script to generate it for me. The idea is to get a list of files in the web root, get a list of required files, eliminate the required files from the first list and generate the file.

Here is the script

[More]

A jQuery plugin for Zooming.


I have worked on a jQuery plugin to allow a user to pan over a low res image and zoom in on the same position in a hi res image. The code is entirely client-side and depends on both low and high res images being available. There is no resampling of the image.The plugin may be applied to multiple images on a page. Before delving into the code let's take a look at an example. (The video seems to hang at a couple of points. Toggling the pause button will allow the video to continue.)

Let's look at the code in the rendering page.

[More]

Progressive filtering using jQuery


Here is a simple plugin to filter a result set using jQuery

You "attach" the plugin to a text field and then as you type in that field only the matching records are shown

[More]

ColdFusion Directory Watcher Gateway

On a daily basis I have my websites backed up and send the tarball via ftp to my local machine. I was interested in automatically copying those files to an external hard drive. I found a simple way to do this using an instance of ColdFusion Directory Watcher Gateway. One could write a component that scans the directory and looks for differences between that and the archive directory on the external drive and copy any changed or added files and run that as a scheduled task. It is far easier to use a gateway instance rather than reinvent the wheel.

[More]

Generating Components From Tables and Queries

Quite often I find it useful to have a ColdFusion object which reflects the data in the row of a query or database table.

I have a written a generator to accomplish this. Please note that this is CF 9 specific. But wait, you say, CF 9 has ORM built in why not just use that. There are two limitations of Hibernate as implemented in CF 9 which rule it out for my use. 1)It is limited to a single datasource and 2) it will not work on an arbitrary query.

We have an application for which different clients have different datasources. The database schema is the same for each client but the database instance, and hence datasource is different.

Also, we often move data returned by a query around the application and to the client side to be used by jQuery. It is much easier to use an object for this than using queries directly.

[More]

Overriding OS alerts and confirms using jQuery

I have recently been tasked with unifying the look and feel of a large application. The application makes use of the jQuery dialog for notifications as ajax operations process but there are a large number of places where the application uses OS alerts and confirms.

You cannot just replace these calls with a dialog because displaying the dialog does not stop downstream processing like alerts and confirms do. In the alert case this is usually not important unless you have code like:

alert("Sending you to google");
location.href="http://www.google.com";

In the above case you will go toodling off to google before the replacement for the alert has been dismissed. Fortunately in our application this use case doesn't occur so replacing the alert with a dialog works fine.

[More]

Previous Entries / More Entries