Canvas & HTML 5 Sample Junk

by Jon Davis 27. September 2012 15:48

Poking around with HTML 5 canvas again, refreshing my knowledge of the basics. Here's where I'm dumping links to my own tinkerings for my own reference. I'll update this with more list items later as I come up with them.

  1. Don't have a seizure. http://jsfiddle.net/8RYtu/22/
    HTML5 canvas arc, line, audio, custom web font rendered in canvas, non-fixed (dynamic) render loop with fps meter, window-scale, being obnoxious
  2. Pass-through pointer events http://jsfiddle.net/MtGT8/1/
    Demonstrates how the canvas element, which would normally intercept mouse events, does not do so here, and instead allows the mouse event to propagate to the elements behind it. Huge potential but does not work in Internet Explorer.
  3. Geolocation sample. http://jsfiddle.net/nmu3x/4/ 
    Nothing to do with canvas here. Get over it.
  4. ECMAScript 5 Javascript property getter/setter. http://jsfiddle.net/9QpnW/8/
    Like C#, Javascript now supports assigning functions to property getters/setters. See how I store a value privately (in a closure) and do bad by returning a modified value.

Automatically Declaring Namespaces in Javascript (namespaces.js)

by Jon Davis 25. September 2012 18:24

Namespaces in Javascript are a pattern many untrained or undisciplined developers may fail to do, but they are an essential strategy in retaining maintainability and avoiding collisions in Javascript source.

Part of the problem with namespaces is that if you have a complex client-side solution with several Javascript objects scattered across several files but they all pertain to the same overall solution, you may end up with very long, nested namespaces like this:

var ad = AcmeCorporation.Foo.Bar.WidgetFactory.createWidget('advertisement');

I personally am not opposed to long namespaces, so long as they can be shortened with aliases when their length gets in the way.

var wf = AcmeCorporation.Foo.Bar.WidgetFactory;
var ad = wf.createWidget('advertisement');

The problem I have run into, however, is that when I have multiple .js files in my project and I am not 100% sure of their load order, I may run into errors. For example:

// acme.WidgetFactory.js
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget: function(e) {
return new otherProvider.Widget(e);
}
};

This may throw an error immediately because even though I’m declaring the WidgetFactory namespace, I am not certain that these namespaces have been defined:

  • AcmeCorporation
  • AcmeCorporation.Foo
  • AcmeCorporation.Foo.Bar

So again if any of those are missing, the code in my acme.WidgetFactory.js file will fail.

So then I clutter it with code that looks like this:

// acme.WidgetFactory.js
if (!window['AcmeCorporation']) window['AcmeCorporation'] = {};
if (!AcmeCorporation.Foo) AcmeCorporation.Foo = {};
if (!AcmeCorporation.Foo.Bar) AcmeCorporation.Foo.Bar = {};
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget: function(e) {
return new otherProvider.Widget(e);
}
};

This is frankly not very clean. It adds a lot of overhead to my productivity just to get started writing code.

So today, to compliment my using.js solution (which dynamically loads scripts), I have cobbled together a very simple script that dynamically defines a namespace in a single line of code:

// acme.WidgetFactory.js
namespace('AcmeCorporation.Foo.Bar');
AcmeCorporation.Foo.Bar.WidgetFactory = {
createWidget : function(e) {
return new otherProvider.Widget(e);
}
};
/* or, alternatively ..
namespace('AcmeCorporation.Foo.Bar.WidgetFactory');
AcmeCorporation.Foo.Bar.WidgetFactory.createWidget = function(e) {
return new otherProvider.Widget(e);
};
*/

As you can see, a function called “namespace” splits the dot-notation and creates the nested objects on the global namespace to allow for the nested namespace to resolve correctly.

Note that this will not overwrite or clobber an existing namespace, it will only ensure that the namespace exists.

a = {};
a.b = {};
a.b.c = 'dog';
namespace('a.b.c');
alert(a.b.c); // alerts with "dog"

Where you will still need to be careful is if you are not sure of load order then your namespace names all the way up the dot-notation tree should be namespaces alone and never be defined objects, or else assigning the defined objects manually may clobber nested namespaces and nested objects.

namespace('a.b.c');
a.b.c.d = 'dog';
a.b.c.e = 'bird';
// in another script ..
a.b = { 
c : {
d : 'cat'
}
};
// in consuming script / page
alert(a.b.c); // alerts [object]
alert(a.b.c.d); // alerts 'cat'
alert(a.b.c.e); // alerts 'undefined'

Here’s the download if you want it as a script file [EDIT: the linked resource has since been modified and has grown significantly], and here is its [original] content:

function namespace(ns) {
var g = function(){return this}();
ns = ns.split('.');
for(var i=0, n=ns.length; i<n; ++i) {
var x = ns[i];
if (x in g === false) g[x]={}; 
g = g[x];
}
} 

The above is actually written by commenter "steve" (sjakubowsi -AT- hotmail -dot-com). Here is the original solution that I had come up with:

namespace = function(n) {
var s = n.split('.');
var exp = 'var ___v=undefined;try {___v=x} catch(e) {} if (___v===undefined)x={}';
var e = exp.replace(/x/g, s[0]);
eval(e);
for (var i=1; i<s.length; i++) {
var ns = '';
for (var p=0; p<=i; p++) {
if (ns.length > 0) ns += '.';
ns += s[p];
}
e = exp.replace(/x/g, ns);
eval(e);
}
}

Currently rated 4.0 by 2 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Javascript | Pet Projects

Why jQuery Plugins Use String-Referenced Function Invocations

by Jon Davis 25. September 2012 10:52

Some time ago (years ago) I cobbled together a jQuery plug-in or two that at the time I was pretty proud of, but in retrospect I’m pretty embarrassed. One of these plugins was jqDialogForms. The embarrassment was not due to its styling—the point of it was that it could be skinnable, I just didn’t have time to create sample skins—nor was the embarrassment due to the functional conflict with jQuery UI’s dialog component, because I had a specific vision in mind which included modeless parent/child ownership, opening by simple DOM reference or by string, and automatic form serialization to JSON. Were I to do all this again I would probably just extend jQuery UI with syntactical sugar, and move form serialization to another plugin, but all that is a tangent from the purpose of this blog post. My embarassment with jqDialogForms is with the patterns and conventions I chose in contradiction to jQuery’s unique patterns.

Since then I have abandoned (or perhaps neglected) jQuery plugins development, but I still formed casual and sometimes uneducated opinions along the way. One of the patterns that had irked me was jQuery UI’s pattern of how its components’ functions are invoked:

$('#mydiv').accordion( 'disable' );
$('#myauto').autocomplete( 'search' , [value] );
$('#prog').progressbar( 'value' , [value] );

Notice that the actual functions being invoked are identified with a string parameter into another function. I didn’t like this, and I still think it’s ugly. This came across to me as “the jQuery UI” way, and I believed that this contradicted “the jQuery way”, so for years I have been baffled as to how jQuery could have adopted jQuery UI as part of its official suite.

Then recently I came across this, and was baffled even more:

http://docs.jquery.com/Plugins/Authoring

Under no circumstance should a single plugin ever claim more than one namespace in the jQuery.fn object.

(function( $ ){

  $.fn.tooltip = function( options ) { 
    // THIS
  };
  $.fn.tooltipShow = function( ) {
    // IS
  };
  $.fn.tooltipHide = function( ) { 
    // BAD
  };
  $.fn.tooltipUpdate = function( content ) { 
    // !!!  
  };

})( jQuery );

This is a discouraged because it clutters up the $.fn namespace. To remedy this, you should collect all of your plugin’s methods in an object literal and call them by passing the string name of the method to the plugin.

(function( $ ){

  var methods = {
    init : function( options ) { 
      // THIS 
    },
    show : function( ) {
      // IS
    },
    hide : function( ) { 
      // GOOD
    },
    update : function( content ) { 
      // !!! 
    }
  };

  $.fn.tooltip = function( method ) {
    
    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    
  
  };

})( jQuery );

// calls the init method
$('div').tooltip(); 

// calls the init method
$('div').tooltip({
  foo : 'bar'
});

// calls the hide method
$('div').tooltip('hide'); 
// calls the update method
$('div').tooltip('update', 'This is the new tooltip content!'); 

This type of plugin architecture allows you to encapsulate all of your methods in the plugin's parent closure, and call them by first passing the string name of the method, and then passing any additional parameters you might need for that method. This type of method encapsulation and architecture is a standard in the jQuery plugin community and it used by countless plugins, including the plugins and widgets in jQueryUI.

What baffled me was not their initial reasoning pertaining to namespaces. I completely understand the need to keep plugins’ namespaces in their own bucket. What baffled me was how this was considered a solution. Why not simply use this?

$('#mythingamajig').mySpecialNamespace.mySpecialFeature.doSomething( [options] );

To see about proving that I could make both myself and the “official” jQuery team happy, I cobbled this test together ..

(function($) {
    
    $.fn.myNamespace = function() {
        var fn = 'default';
        
        var args = $.makeArray(arguments);
        if (args.length > 0 && typeof(args[0]) == 'string' && !(!($.fn.myNamespace[args[0]]))) {
            fn = args[0];
            args = $(args).slice(1);
        }
        $.fn.myNamespace[fn].apply(this, args);
    };
    $.fn.myNamespace.default = function() {
        var s = '\n';
        var i=0;
        $(arguments).each(function() {            
            s += 'arg' + (++i).toString() + '=' + this + '\n';
        });
        alert('Default' + s);
        
    };
    $.fn.myNamespace.alternate = function() {
        var s = '\n';
        var i=0;
        $(arguments).each(function() {            
            s += 'arg' + (++i).toString() + '=' + this + '\n';
        });
        alert('Alternate' + s);
        
    };

    $().myNamespace('asdf', 'xyz');
    $().myNamespace.default('asdf', 'xyz');
    $().myNamespace('default', 'asdf', 'xyz');
    $().myNamespace.alternate('asdf', 'xyz');
    $().myNamespace('alternate', 'asdf', 'xyz');
    
})(jQuery);

Notice the last few lines in there ..

    $().myNamespace('asdf', 'xyz');
    $().myNamespace.default('asdf', 'xyz');
    $().myNamespace('default', 'asdf', 'xyz');
    $().myNamespace.alternate('asdf', 'xyz');
    $().myNamespace('alternate', 'asdf', 'xyz');

When this worked as I hoped I originally set about making this blog post be a “plugin generator plugin” that would make plug-in creation really simple and also enable the above calling convention. But when I got to the some passing tests, adding a few more tests I realized I had failed to notice a critical detail: the this context, and chainability.

In JavaScript, navigating a namespace as with $.fn.myNamespace.something.somethingelse doesn’t execute any code within the dot-notation. Without the execution of functional code, there can be no context for the this context, which should be the jQuery-wrapped selection, and as such there can be no context for the return chainable object. (I realize that it is possible to execute code with modern JavaScript getters and setters but all modern browsers don’t support getters and setters and all commonly used browsers certainly don’t.) This was something that I as a C# developer found easy to forget and overlook, because in C# we take the passing around of context in property getters for granted.

Surprisingly, this technical reasoning for the string-based function identifier for jQuery plug-in function invocations was not mentioned on the jQuery Plugins documentation site, nor was it mentioned in the Pluralsight video-based training I recently perused. It seemed like what Pluralsight’s trainer was saying was, “You can use $().mynamespace.function1()” but that’s obscure! Use a string parameter instead!” And I’m like, “No, it is not obscure! Calling a function by string is obscure because you can’t easily identify it as a function reference distinct from a parameter value!”

The only way to retain the this context while removing the string-based function reference is to invoke it along the way.

$().myNamespace().myFunction('myOption1', true, false);

Notice the parenthesis after .myNamespace. And that is a wholly different convention that few in jQuery-land are used to. But I do think that it is far more readable than ..

$().myNamespace('myFunction', 'myOption1', true, false);

I still like the former, it is more readable, and I remain unsure as to why the latter is the accepted convention over the former, but my guess is that a confused user might try to chain back to jQuery right after .myNamespace() rather than after executing a nested function. And that, I suppose, demonstrates how the former pattern is contrary to jQuery’s chainability design of every().invocation().just().returns().jQuery.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Javascript

My ‘Aha!’ Moment With Javascript

by Jon Davis 14. May 2009 01:25

9/27/2012 Note: This is an old 2009 blog entry, and it was recently promoted on DZone with no intention of making it a Big Link. I've since learned quite a bit more about Javascript fundamentals, correcting a few misgivings presented here, and you should, too. 

-- 

For most people this goes back to Javascript 101 but it’s worth blogging, in my opinion. A lot of people truly have no idea how much power is available on the client side of web apps, and they actually think that Javascript is dying.

The true power of Javascript was not made known to me until I had my aha! moment. It was about two or three years ago, and I think I could sum up (profusely, with freeze-dried concentration) what triggered my realization when these two essential facts became clear:

Discovery #1:

 

var myFunc = function() { };
var myObj = new myFunc();

 

.. is to Javascript what this is to C# ..

public class MyClass 
{
public MyClass() { } 
}
MyClass myObj = new MyClass();

 

 

That is to say, Javascript functions are functions (of course) but also “classes” (object prototypes) and constructors all rolled into one. So, for example, to accomplish this in C# ..

class MyClass {
void DoSomething() {
MessageBox.Show("something");
}
}
... 
MyClass myObj = new MyClass();
myObj.DoSomething();

.. you could do this in Javascript ..

function myFunc() { }
myFunc.prototype.doSomething = function() {
alert('something');
};
...
var myObj = new myFunc();
myObj.doSomething();

 

Or, you could assign the doSomething member function “at runtime” (dynamically appending the member to the object after the object has already been instantiated).

var myFunc = new function() {
this.doSomething = function() {
alert('something');
};
};
var myObj = new myFunc();
myObj.doSomething();
// or even
myObj.doSomethingElse = function() { alert('something else'); };
myObj.doSomethingElse();

Note that ‘this’ is used to reference the object instance that the function instance is. Incidentally, you can ensure “this” works when calling other objects’ functions by using function_name.call(object, params);.

That said, these things point out the dynamic nature of Javascript object members – you can append properties and functions to an object at runtime by using syntax like [object].doSomething = function() { }. It also shows that members on an object are akin to a string-keyed hashtable.

And that hashtable-like behavior brings about the second part of my “aha!” moment.

Discovery #2:

All user-defined objects, including functions, are ultimately string-keyed hashtables. That is not a limiting behavior but an extra feature because they are still real objects.

But JSON (Javascript object notation) objects are extraordinarily handy as alternatives to functions because of the expressive way you can declare them.

var myNewObject = {
member_A : "abc",
member_B : 123
};

.. is akin to C#’s ..

Dictionary<string, object> myNewObject = new Dictionary<string, object>();
myNewObject["member_A"] = "abc";
myNewObject["member_B"] = 123;

And it’s even more powerful when you consider that the members can be functions.

myNewObject = {
doSomething: function() {
alert('something');
}
};
myNewObject.doSomething(); // invoke
// or,
myNewObject = { };
myNewObject.doSomething = function() {
alert('something');
};
myNewObject.doSomething(); // invoke

.. can be implemented in C# 3.0 like so ..

delegate void SimpleMethod();
public static void RunSnippet()
{
var myNewObject = new Dictionary<string, object>();
myNewObject["doSomething"] = (SimpleMethod)(() =>
MessageBox.Show("something")
);
// .. 
((SimpleMethod)myNewObject["doSomething"])(); // invoke
}

In fact, take a look at this old blog post I saw at Ajaxian.com: http://colinramsay.co.uk/diary/2008/04/02/javascript-generation-a-change-of-heart/

In return, comparing the two languages reveals the power of C# 3.0, as well. C# 4.0’s dynamic objects will be trying even harder to “be powerful like Javascript already was”.

*evil grin*

AJAX Deferred Loader for ASP.NET

by Jon Davis 11. April 2009 14:19

Here’s a simple ASP.NET control that takes a URL parameter, renders a placeholder on the page, and uses Javascript to “lazy-load” the view content for that placeholder area. It basically does what my sprinkle.js did a long while back, but it takes advantage of ASP.NET controls and jQuery simplicity with its load() function.

It also has self-refreshing. This is good for updating a section of a page with progress information, without refreshing the entire page.

To use it,

  1. Compile the source code (below) to your Web Application project’s assembly, or create an assembly and reference the assembly in your project. You should put this control in its own namespace or in a “.Controls” namespace because of #2 below.
  2. Add a header to any page that would use it to explicitly import all controls under the namespace for which you’re using this control.
    <%@ Register Assembly="MvcApplication1" Namespace="MvcApplication1.Controls" TagPrefix="demo" %>
  3. Be sure jQuery is referenced on the page, ideally in the <head> tag. If you’re using Web Forms and <head runat=”server”>, the process of getting it in there is a little complicated but that’s a different topic. I’m using ASP.NET MVC and I just put it in the Master page. Ultimately, jQuery needs to be loaded before anything else loads, that’s your objective, so you figure it out.
    <html><!-- ... -->
    <head>
      <!-- ... -->
      <script language="javascript" type="text/javascript" src="../../Scripts/jquery-1.3.2.min-vsdoc.js"></script>
      <script language="javascript" type="text/javascript" src="<%=ResolveUrl("~/Scripts/jquery-1.3.2.min.js") %>"></script>
      <!-- ... -->
    </head>
    <body><!-- ... -->
    </body>
    </html>
  4. Now you can reference inline. Note the “RefreshInterval” setting, which is an integer that indicates, in seconds, how often to refresh the region. In this sample, it updates every two seconds. Note also that the HTML that comes back from the referenced URL can include script markup that cancels the interval, such as if a process has completed.
     
    <demo:AjaxDeferredView runat="server" ViewUrl="~/Deferred" RefreshInterval="2">
        <asp:Panel runat="server">Please wait ...</asp:Panel>
    </demo:AjaxDeferredView>
  5. This is what gets outputted with the above tag. Note the “undefined, undefined” are there because the PostData and the Callback optional properties are not set on the control tag.
    <div id="ctl00_MainContent_ctl00">
        <div>
    		Please wait ...
        </div>
    </div>
    <script language="javascript" type="text/javascript"><!--
    $(document).ready(function() {
    	window['ctl00_MainContent_ctl00_interval'] = setInterval(function() {
    		$('#ctl00_MainContent_ctl00').load('http://localhost:5577/Deferred', undefined, undefined);
    	}, 2000);
    	$('#ctl00_MainContent_ctl00').load('http://localhost:5577/Deferred');
    });
    --></script>
  6. And finally, what the end user will actually see is a momentary, split-second, or too-fast-to-see placeholder being swapped out for the content at the loaded URL.
  7. Here’s an example of how to clear that interval in the sample ~/Deferred view that comes back, such as if a process has completed, or in this case after the 5th hit (from any visitor). This sample might be the actual page that is invoked from the AJAX call.  Note the ClearParentInterval control, and that the logic that changes its ClearInterval property precedes its position on the page.
    <%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
    <%@ Register Assembly="MvcApplication1" Namespace="MvcApplication1.Controls" TagPrefix="demo" %>
    <% Response.Cache.SetCacheability(HttpCacheability.NoCache); %>
    Welcome to my deferred content. 
    <%
        
        //live counter
        var i = (int)(Context.Application["defercnt"] ?? 0);
        i++;
        Context.Application["defercnt"] = i;
        %><%=i %>
        
    <% if (i >= 5) // shutdown interval after 5 views
     {
         ClearIntervalControl.ClearInterval = true;
     } %>
     <demo:ClearParentInterval runat="server" ID="ClearIntervalControl" />
    

    This outputs the following when ClearInterval is set to true. The point of the example is in the ID’ing of the <span> tag and in the <script> tag’s contents. It basically walks up the DOM tree by one parent to get the placeholder’s ID in the DOM, then tacks on “_interval” and assumes that to be the name of the interval (which it is).
    <div>Welcome to my deferred content. 5</div>
        
    <span id="ClearIntervalControl">
    </span>
    <script type="text/javascript" language="javascript">
    	var ClearIntervalControl_ClearIntervalParentRef = $('#ClearIntervalControl').parent().attr('id') + '_interval';
    	if (window[ClearIntervalControl_ClearIntervalParentRef]) {
    		clearInterval(window[ClearIntervalControl_ClearIntervalParentRef]);
    	}
    </script>
    

Here’s the control source:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;

namespace MvcApplication1.Controls
{
    public class AjaxDeferredView : System.Web.UI.Control
    {
        protected override void OnInit(EventArgs e)
        {
            if (string.IsNullOrEmpty(ContainerTag))
                ContainerTag = "div";
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteLine();
            writer.WriteBeginTag(ContainerTag);
            writer.WriteAttribute("id", ClientID);
            writer.Write(">");
            base.Render(writer);
            writer.WriteEndTag(ContainerTag);
            writer.WriteLine();
            writer.WriteLine("<script language=\"javascript\" type=\"text/javascript\"><!--");
            writer.WriteLine("$(document).ready(function() {");
            if (RefreshInterval > 0)
            {
                writer.WriteLine("\twindow['" + this.ClientID + "_interval']"
                    + " = setInterval(function() {");
                writer.WriteLine("\t\t$('#" + this.ClientID + "').load('"
                    + ResolveFullUrl(this.ViewUrl) + "', " 
                    + GetDataArg() + ", " + GetCallbackArg() + ");");
                writer.WriteLine("\t}, " + RefreshInterval * 1000 + ");");
            }
            writer.WriteLine("\t$('#" + this.ClientID + "').load('"
                + ResolveFullUrl(this.ViewUrl) + "');");
            writer.WriteLine("});");
            writer.WriteLine("--></script>");
        }

        [PersistenceMode(PersistenceMode.Attribute)]
        public object PostData { get; set; }

        [PersistenceMode(PersistenceMode.Attribute)]
        public string Callback { get; set; }

        [PersistenceMode(PersistenceMode.Attribute)]
        public string ViewUrl { get; set; }

        [PersistenceMode(PersistenceMode.Attribute)]
        public string ContainerTag { get; set; }

        [PersistenceMode(PersistenceMode.Attribute)]
        public int RefreshInterval { get; set; }

        private string GetDataArg()
        {
            if (PostData == null) return "undefined";
            // todo: convert complex class to JSON
            return PostData.ToString();
        }

        private string GetCallbackArg()
        {
            if (string.IsNullOrEmpty(Callback)) return "undefined";
            return Callback;
        }

        private string ResolveFullUrl(string url)
        {
            var ret = new Uri(Request.Url, Page.ResolveUrl(url));
            return ret.ToString();
        }

        private HttpResponse Response
        {
            get { return HttpContext.Current.Response; }
        }

        private HttpRequest Request
        {
            get { return HttpContext.Current.Request; }
        }
    }

    public class ClearParentInterval : Control
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (string.IsNullOrEmpty(ContainerTag))
                ContainerTag = "span";
        }
        protected override void Render(HtmlTextWriter writer)
        {
            writer.WriteBeginTag(ContainerTag);
            writer.WriteAttribute("id", this.ClientID);
            writer.WriteLine(">");
            base.Render(writer);
            writer.WriteEndTag(ContainerTag);
            writer.WriteLine();
            if (ClearInterval.HasValue && ClearInterval.Value)
            {
                writer.WriteLine("<script type=\"text/javascript\" language=\"javascript\">");
                writer.WriteLine("\tvar " + ClientID + "_ClearIntervalParentRef = $('#" + this.ClientID +
                                 "').parent().attr('id') + '_interval';");
                writer.WriteLine("\tif (window[" + ClientID + "_ClearIntervalParentRef]) {");
                writer.WriteLine("\t\tclearInterval(window[" + ClientID + "_ClearIntervalParentRef]);");
                writer.WriteLine("\t}");
                writer.WriteLine("</script>");
            }
        }
        [PersistenceMode(PersistenceMode.Attribute)]
        public string ContainerTag { get; set; }

        public bool? ClearInterval { get; set; }
    }
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Web Development

jqDialogForms: v1.1 Released And New Samples Posted

by Jon Davis 27. January 2009 23:30

I've updated jqDialogForms to v1.1. Watch this space: http://www.jondavis.net/codeprojects/jqDialogForms/

It is no longer a placeholder URL that points back to my blog post, it's an actual page dedicated to the library, with some basic samples already in place. I still need to add more samples and documentation such as the default options, all of which I plan on doing this weekend, but at least there's finally something there. 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Web Development

New Javascript Library: jqDialogForms

by Jon Davis 5. January 2009 02:52

(Note: If you link to this blog entry, please use the URL: http://www.jondavis.net/codeprojects/jqDialogForms/ which only temporarily links back to here.)

I'm releasing a v1.0 v1.1 beta build of jqDialogForms, a DHTML-based dialog windows library based on jQuery and jqDnR. This is something I started to build during my free time at my last job (it was never used there) and then continued development and completed it on my own (at home). Since I'm no longer at the job where it would have been useful had it been completed there, I do not have a lot of real-world samples to demonstrate here, but I'm releasing it now in hopes that it can continue to evolve.

There are other libraries out there that produce dialog windows that are completely modal. Modal dialogs are important, but I quickly ran into problems when, for example ...

  • A dialog window spawns a child dialog window
  • I want to see behind the child's parent's window (move the window)
  • I want to open multiple dialog windows at once
  • I'm using any modern browser, including IE 7 in quirks mode
  • Dialog windows are very large, and users are browsing with small monitors or browser windows
  • The user has scrolled down beyond the fold and absolute positioning is used

jqDialogForms has a placeholder for modal dialogs but it's not implemented. The focus instead was on parent disabled+modeless+serializeable windows, meaning the ability to have a child window have a parent window, which forces the child window to retain a top-most z-index over the parent window, while the parent window's form fields are disabled, but you can still access the parent window and even drag it around. None of the windows in this scenario need to be modal; they just retain z-index. You can click on each open window and it acquires "activation", which moves its z-index to the top and then moves all of its child windows above it, and there is also an "active/inactive" titlebar color. It's a Windows 9x multiple app windowing behavior, within the browser. The window is also serializeable, meaning that it is a self-contained <form> with fields that serialize using either jQuery serialize() or using a JSON serialization. It is important to note that I made a point to be ASP.NET Web Forms compatible. jQuery's serialize() function doesn't work well with ASP.NET Web Forms unless the <form>'s are dynamically generated and appended to the body as this library does.

Because it is for dialogs, it assumes Apply and Cancel behavior and the presence of buttons. (OK is Apply+Close. Cancel is Close without Apply.) So there are assignable event handlers for before-show, showApply click, and hide. The default layout implements OK/Cancel and a close box on the top right.

There is a simple test document included with this release that I used to develop the the script, but it is an awful presentation for demoing purposes. The test document and the script itself are complete enough, though, for a knowledgeable Javascript developer to read and understand how it works without documentation. But next on my to-do list is to produce some documentation and samples, but except for modal mode the script itself it pretty much feature-complete, if not quite 100% tested, as a v1.0 beta release.

Features:

  • Modeless+parent disabling+serializeable dialog form windows
  • Reference a DOM element or a string of HTML as the message or form fields to be displayed
  • Automatically switch from fixed positioning to absolute positioning when in quirks mode IE7, and position to the current vertical scroll position
  • jqDnR enabled: Resizeable, Windows 9x style
  • jqDnR enabled: Drag around the screen via the title bar
  • Activateable; show multiple windows, and activate/focus each window as it is clicked on (Windows 9x application windows activation behavior)
  • Lacking CSS conformance of a dialog window container, a prefab one is used that includes a title bar, a close box, and OK/Cancel buttons.
  • OK button invokes Apply event handler and then, if not invalidated, closes the window.
  • Dirty state detection; on editable forms, OK/Apply buttons are disabled unless a field is changed
  • Exposes form serialize functions that outputs name/value HTML/querystring encoding (in the style of jQuery serialize()), or JSON serialization.
  • "Smart" top positioning for oversized dialogs
  • CSS-driven layout

Among the several known issues:

  • Multiple windows do not retain their activation order.
  • No fully modal dialog or truly modeless (non-disabling) support
  • No demo No extensive demos
  • No documentation

A few months back I released a Javascript library called jqAlert. I will probably rewrite jqAlert to use jqDialogForms.

It's NOT perfect, there are a few missing parts and pieces, but as far as I know it's a stable beta and can probably be used in production environments (I think). If you have any comments or suggestions, please use the Comments herein on this blog or e-mail me.

 

Download: 

http://www.jondavis.net/codeprojects/jqDialogForms/ 

 

kick it on DotNetKicks.com

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Web Development

How to ruin a perfectly good browsing session...

by Jon Davis 17. December 2008 23:36

Ever had this happen to you while you were trying to debug? You're trying to debug your Javascript code, and then you accidentally set yourself up with an infinite alert loop, and ....

, but be prepared to hit Ctrl-Alt-Del, choose Task Manager, and kill your browser.

*sigh* The browser vendors really need to find another way to make these alerts show up, such that you can cancel script.

 

Update: Oooh, nice, Chrome gave us a good one ..
chrome_stop_alert

Sadly, checking it also causes this blog page to not refresh, the whole browser becomes unstable. Click on the <-- (Back) button to make it behave normal again.

image

Opera plays nice too.

Internet Explorer, Firefox, and Safari all FAIL.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

jQuery Failed Me?

by Jon Davis 10. December 2008 19:52

I had a painful and uncomfortable epiphany today, one that should not go unnoticed. In building up a form consisting of about 30 fields, I processed all of the "submitted values restoration databinding"--that is, re-populating the fields' values after submitting the form because the form failed validation--in script, using jQuery, like so:

(Yes, this is VBScript in ASP Classic:)

	<% For Each field In MyDictionary %>
	$("#<%=field%>").val("<%=Request(field)%>");<%
	Next %>
	

This was a really simple notion, to data-bind all my fields with just three lines of code. And it worked. It worked great. Except for one problem.

With thirty fields, plus code to add highlighting and such, it took jQuery, in IE7 (yes that monstrous piece of doo-doo, Internet Explorer) the browser kept locking up for five seconds every time the page was refreshed (that is, every time the form was posted locally with invalid field values), while it waited for jQuery to find each of these fields and populate their values. Now, I'm sure I could go back and do some optimizations; for example, I could have done the loop in reverse and limited my jQuery selector to a single search, something like:

	var fieldMap = {};
	<% For Each field In MyDictionary %>
	fieldMap["<%=field%>"]="<%=Request(field)%>";<%
	Next %>
	$("input").each(function() {
$(this).val(fieldMap[$(this).attr("name")]); });

But besides the fact that my code just grew, there was another problem with the jQuery approach. Some people turn script off altogether. Ultimately I had to do what I tried so hard not to do, which was this junky markup:

	<input type="checkbox" <%If Request("foobar") = "ABC" Then %>
	checked="checked"<% End If %> name="foobar" value="ABC" />
	<input type="text" value="<%=Request("acme")%>" name="acme" /> 
	

Now all of a sudden I had messy, difficult-to-maintain code. Any time you put implementation detail on the detail, such as here having field instance named data binding, you have messy code; I prefer to go abstract as much as possible.

But I didn't see any way around this.

Generally, people don't run into this problem. They typically settle for something like Web Forms, which imposes View State and ultimately suffers from similar performance issues in different ways.

I was lucky. I was doing my ASP Classic coding in Visual Studio 2008, which I might add would be a GREAT ASP Classic IDE, except for one not-so-small problem: VS crashes every time you quit the ASP Classic debugger. :(  Anyway, Visual Studio gave me the RegEx Find-and-Replce tool, which I spent no time thinking about; as soon as I realized I had to manually inject my binding code into the HTML markup, I started doing things like this:

        Find: name\=:q
Replace With: name\=\1 value\=\"\<\%\=Request(\1)\%\>\"

I did have a lot of bad runs for the several changes I had to make (thank Microsoft for Undo->Replace All), still in the end I saved a few minutes.

The end result was instantaneous refresh. Zero delay.

But after all that, I got up and went for a nature break (too much information?) and started asking myself, wait, what just happened? Till now I've started to sing the praises of jQuery about how wonderful it is and how it is our panacea to all the world's problems and ultimately hunger and disease in Zimbabwe and elsewhere in the world will end after we all adopt jQuery.

Now I'm coming to find that DOM traversing, in general, is not something that should be done on the client for such core operations as data-binding. This had me thinking again about Aptana Jaxer. Jaxer gives you jQuery (actually, browser-compatible Javascript in general) on the server by offering a Mozilla-based browser DOM on the server and spitting out to the client the resulting DOM markup in its modified state. But would this be any more performant?

It would be more performant than IE7 at least. Mozilla's JavaScript runtime is a lot faster than IE's Javascript runtime. But it's still client-side performance before the client ever receives anything. If nothing else, it would at least be perceived performance improvement because you don't see a web page build up all around you and then you have to wait for five seconds while the browser freezes.

Even so, Jaxer is not available in the workplace, nor should I ever expect it in my case.

I ended the day realizing that my curiosity of the notion of migrating all templating and forms and view logic off the server and onto the client might not be as desirable as I thought it would be. This could be a problem, too, for ASP.NET AJAX 4.0, which intends to migrate data binding to the client (something I celebrated when I found out about it).

ASP.NET AJAX 4.0: Microsoft did it! They married the DOM and client-driven data!

by Jon Davis 3. November 2008 01:03

For over a year I've been going through a discovery process, with one pet project after another, of how it might be possible to glue Javascript objects and DOM objects together and keep them synchronized with a server in two-way data binding. And, to do it in a way that was elegant, readable, terse, trivial, and blatantly obvious and sensible. I usually failed to see this as my actual objective--I sought to find solutions to more specific problems whereby this would be the ultimate ideal.

A long while back, I came up with a script library I called Sprinkle. I created a domain name for it, I mentioned it to Ajaxian.com, and they featured an article on it. Somehow, Sprinkle disappeared and was forgotten (an oversight on my part) and sprinklejs.com no longer points anywhere.

But what Sprinkle did was quite simple. It allowed you to put src="..." on any DOM element, within reason, particularly <div>'s for HTML injection and <input>'s for default values populated from URL GETs. Then I sought to make it XHTML-compliant by using the DTD extensions spec whereby I was allowed to add my own attributes (like 'src=..') to existing declared elements (like <div>). Problem was, the browsers generated junk characters at the top of the page when I did that, so I had to use script to strip off the junk characters. The whole thing became a mess, for one simple lightweight proof of concept, and I hadn't even begun to tinker with advanced HTML and 2-way binding.

At one point a co-worker and I created a client-side MVC framework where we ended up creating DOM object assignments to "client controls" that would effectively be able to manipulate their associated DOM objects as though they were properties (which indeed they were). Nothing special in itself but it was another example of where we were marrying HTML and script. Ultimately my co-worker did most of the implementation work on that. I helped do a lot of architectural design of it, but he pointed out a lot of issues we had to work through such as dealing with composite ASP.NET server controls that defined our own client control--ClientID issues, for example, in a tree of control containers, one control nested after another.

And in my previous post I brought the whole matter up again and pondered even simple one-way data binding from scratch all over again. In the end I figured (and noted) phooey, just use client-side templates, jQuery, and JSON web services. You still, however, and up with a lot of manual work in some ways.

Anyway, the Web Forms dependency in ASP.NET AJAX made ASP.NET AJAX a complete turn-off to me all this time. I think my previous post pretty well documents why Web Forms is worth hating, most notably the evil <head runat="server"> and <form runat="server"> tags and how they completely mess everything up in a client-oriented web app.

While I reserve room for skepticism, ASP.NET 4.0 makes some promises in favor of lightweight view templates to such an extent that I'm raising my eyebrows and thinking it's worth blogging about. I'm not sure where I was back in July or so when it was announced but the new 4.0 platform promises a whole new approach to building web apps for the client. With the new ASP.NET 4.0 client templates [2], XHTML is cleanly extended using XML namespaces, and databinding and HTML templating is performed using DOM API abstractions (and jQuery) rather than server-side templating logic. What this will mean in the practical sense is yet to be proven but right now I'm thinking, holy cow. The panacea I just spoke of in my previous post has finally arrived, I think.

But let's not get ahead of ourselves. Fortunately, the proposed new ways of doing things the ASP.NET AJAX way are preview downloadable and the downloads already fetchable. We should play with this thing and provide feedback.

More info, and proof that I was a little late to the party, is at: http://weblogs.asp.net/bleroy/archive/2008/07/30/using-client-templates-part-1.aspx

.. and officially here: http://quickstarts.asp.net/previews/ajax/templates/usingajaxtemplate.aspx

kick it on DotNetKicks.com

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Web Development


 

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Jon Davis (aka "stimpy77") has been a programmer, developer, and consultant for web and Windows software solutions professionally since 1997, with experience ranging from OS and hardware support to DHTML programming to IIS/ASP web apps to Java network programming to Visual Basic applications to C# desktop apps.
 
Software in all forms is also his sole hobby, whether playing PC games or tinkering with programming them. "I was playing Defender on the Commodore 64," he reminisces, "when I decided at the age of 12 or so that I want to be a computer programmer when I grow up."

Jon was previously employed as a senior .NET developer at a very well-known Internet services company whom you're more likely than not to have directly done business with. However, this blog and all of jondavis.net have no affiliation with, and are not representative of, his former employer in any way.

Contact Me 


Tag cloud

Calendar

<<  October 2018  >>
MoTuWeThFrSaSu
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar