The jNotify plugin was just updated, with a new "click to dismiss" feature, which lets a user click on a notification to dismiss the notification!
One common pattern I've seen in usability, is that users don't always have great control over their mouse. It's easy to accidentally overshoot a target area with you mouse, which is really frustrating with things like nested dropdown menus, where accidentally mousing away from a target area may end up collapsing/closing the open menu.
Giva's recently released the MouseIntent jQuery Plug-in which aims to give developers a way to control this behavior. It works by monitoring an invisible border around the element to see what the user appears to be doing. If a user quickly moves back into the original element, then then no mouseaway event is ever fired. The plugin has a number of settings that allow you to control the behavior—such as monitoring whether or not the user is still moving the mouse in the invisible border area.
I've used the plugin in one of our dropdown menus that has nested menus and it's really helped to improve our user's experience.
Giva has released released a new plugin (Maskerade jQuery Plug-in) which can convert a normal text field into a power date mask input field. The plugin supports a large array of date masks (even quarters) and even supports copy/paste. Here's a list of some of it's key features:
We have actually been using this plugin in production for a long time with great success.
I just pushed out an update to the Linkselect jQuery Plugin.
I just pushed out an update to the mcDropdown jQuery Plugin.
This morning I was reading Adding your own callbacks to existing JavaScript functions by Dave Ward—which covers how to overwrite an existing function so you can add some additional functionality (in this case, adding callbacks.) While the article is informative, a couple of improvements can dramatically improve his suggestion.
If you don't want to take the time to read Dave's article, in a nutshell he describes how we can overwrite a JavaScript function by storing a reference to the original function in a variable. So, we can take the following function:
function sayHello(name){ alert("Hello, " + name + "!"); }
And we can now overwrite that function by storing a reference to the original function in a variable:
var sayHelloOld = sayHello; function sayHello(){ var name = prompt("Enter your name"); sayHelloOld.apply(this, [name]); }
Now there's a couple of problems with the above code.
We can solve both those problems by using a closure around our code:
// define a closure and pass in a reference to the global window object (function (w){ var sayHelloOld = w.sayHello; w.sayHello = function (){ var name = prompt("Enter your name"); sayHelloOld.apply(this, [name]); } })(window || {});
(NOTE: You can see a working copy on JSFiddle.)
The other topic Dave discusses is how to add callback hooks to run before and after a the original function code runs. His suggestion is built around using the global name space to declare some function names. Since the example is based around jQuery, I'd suggest a much better method would be to add in custom events to your function. This gives you a way to bind callbacks to run, but your neither cluttering the global namespace nor running into issues if the callbacks aren't needed.
Here's what Dave's original solution looks like:
var oldTmpl = jQuery.fn.tmpl; // Note: the parameters don't need to be named the same as in the // original. This could just as well be function(a, b, c). jQuery.fn.tmpl = function() { if (typeof onBeforeTmpl === 'function') onBeforeTmpl.apply(this, arguments); // Make a call to the old tmpl() function, maintaining the value // of "this" and its expected function arguments. var tmplResult = oldTmpl.apply(this, arguments); if (typeof onAfterTmpl === 'function') onAfterTmpl.apply(this, arguments); // Returning the result of tmpl() back so that it's actually // useful, but also to preserve jQuery's chaining. return tmplResult; };
Using the two previously mentioned techniques combined, here's how I'd change that code:
(function ($){ var oldTmpl = $.fn.tmpl; // Note: the parameters don't need to be named the same as in the // original. This could just as well be function(a, b, c). $.fn.tmpl = function(){ // trigger the before callback // to attach a callback, we just bind() this custom event to our jQuery object this.trigger("onBeforeTmpl", arguments); // Make a call to the old tmpl() function, maintaining the value // of "this" and its expected function arguments. var tmplResult = oldTmpl.apply(this, arguments); // trigger the after callback // to attach a callback, we just bind() this custom event to our jQuery object this.trigger("onAfterTmpl", arguments); // Returning the result of tmpl() back so that it's actually // useful, but also to preserve jQuery's chaining. return tmplResult; }; })(jQuery || {});
This gives use a few benefits over Dave's original solution:
To use our code, we can do:
$("#id") .bind("onBeforeTmpl", function (){ alert("before!"); }) .bind("onAfterTmpl", function (){ alert("after!"); }) .tmpl(data, options, parentItem);
NOTE:If your prefer to run the same callbacks for all $.tmpl() calls, you could attach the custom events globally.
Any comments on how to make this solution even better?
Today a new version of the jQuery Linkselect Plug-in was released. The new version under went a ton of changes from the previous version and includes a much better CSS skinning mechanism (see the Linkselect Example.)
The coolest new feature is probably the "placeholder" support, which allows you to specify an <option /> element in your <select /> box to use as a label/placeholder. The "placeholder" <option /> tag uses the <option /> tag as the title of the dropdown menu that's always visible, but still selectable. Here's an example:
Here's a list of all the changes:
I've been updating some code that was built using jQuery Templates, but since jQuery Templates has been discontinued, I've decided to migrate my code to use JsRender.
The syntax is close enough for the most part that translating existing templates is straightforward enough. For the most part it's updating to the new mustache-like bracket syntax and changing variables from ${var} to {{=var}}. However, there was one thing that was tripping me up—simple conditional statements.
JsRender uses the mustache like "codeless" syntax for conditions:
{{#if varName}}output{{/if}}
This fine if varName is a truthy statement, but what if you need to check if varName is equal to a specific value? Having gone through all the JsRender sample code, it appeared the only way to accomplish any kind of comparison conditional statement was to use custom code. This syntax ends up being very ugly and verbose. Here's an example of writing an attribute dynamically based on the value of a variable named varName :
<div class="base{{* if($view.data.varName == 'None'){ result += ' none'; } }}">{{=varName}}</div>
This seems overly complicated for such a simple comparison. I figured there had to be a better way.
After digging through the code, I found there's some undocumented features of the if tag. You can actually use the following syntax to do the same thing:
<div class="base{{#if varName eq='None')}} none{{/if}}">{{=varName}}</div>
While this syntax ends up being pretty close to jQuery Templates, it uses the "hash" functionality of JsRender's custom tags. The odd looking part is that you need the equal sign between the conditional operator and the value. Other operators include:
I actually would prefer to see "lte" and "gte" used for the "or equal" functions, so I've added that to a ticket.
So, while the syntax isn't ideal, it's certainly better than using using the code syntax. Since the project is still in development, it possible the syntax will change.
[UPDATED: Wednesday, August 24, 2011 at 3:19:27 PM]
I was looking through the source code of Underscore.js this morning and notice it's implementation of _.throttle() contains two issues that bother me with most JavaScript-based throttle implementations I've seen:
Let's take a look at an example I posted on JSFiddle: http://jsfiddle.net/MNGpr/
Mouse your mouse from the top left of the "Results" frame to the bottom right. If you do this quickly (under the 1 second delay,) you'll notice that when the function executes it's based upon coordinates in the upper left of the screen—not where your cursor left off.
What I've been doing is using the following throttle() function in my code:
// limit a function to only firing once every XX ms var throttle = function (fn, delay, trail){ delay || (delay = 100); var last = 0, timeout, args, context, offset = (trail === false) ? 0 : delay; return function (){ // we subtract the delay to prevent double executions var now = +new Date, elapsed = (now - last - offset); args=arguments, context=this; function exec(){ // remove any existing delayed execution timeout && (timeout = clearTimeout(timeout)); fn.apply(context, args); last = now; } // execute the function now if( elapsed > delay ) exec(); // add delayed execution (this could execute a few ms later than the delay) else if( !timeout && trail !== false ) timeout = setTimeout(exec, delay); }; };
What this version does that differentiates it from the Underscore.js version is it:
To see the difference in behavior, check out the JSFiddle example using my version of throttle().
I'm working on migrating our application to use the latest version of jQuery. In the process of migrating, I've been working on fixing compatibility issues with several of the plug-ins I've worked on to make sure they work with the latest version of jQuery. So, here's a list of updated plug-ins and their release notes:
A recent post on CF-Talk asked whether ColdFusion could use AJAX to do a database lookup. This is actually extremely easy to do in ColdFusion 8+, because it natively supports returning data in the JSON format.
To show how easy this is to do, I decided to throw together a little demo. This took me about 10 minutes to write—most of which was writing the markup. However, the bulk of the work is going to be handled automatically by ColdFusion, which will handle converting your data to JSON and by the jQuery Field Plug-in (which I wrote) which will handle populating your form from the data it receives from ColdFusion.
To show just how easy this all is, here's the jQuery code required to make an AJAX call to a CFC:
$.ajax({ // the location of the CFC to run url: "example.cfc" // send a GET HTTP operation , type: "get" // tell jQuery we're getting JSON back , dataType: "json" // send the data to the CFC , data: { // the method in the CFC to run method: "getUserById" /* send other arguments to CFC */ // send the ID entered by the user , userId: $("#userId").val() } // this gets the data returned on success , success: function (data){ // this uses the "jquery.field.min.js" library to easily populate your form with the data from the server $("#frmMain").formHash(data); } // this runs if an error , error: function (xhr, textStatus, errorThrown){ // show error alert(errorThrown); } });
Our CFC looks like this:
<cfcomponent output="false"> <cffunction name="getUserById" access="remote" returnType="struct" returnFormat="json" output="false"> <cfargument name="userId" type="numeric" required="false" /> <cfset var user = structNew() /> <!---// The only tricky part here is to use the bracketed notation to match the case in your HTML, JS is case sensentive. If you use the dot notation (user.name) then the keys will be returned in uppercase. //---> <cfset user["name"] = "User " & arguments.userId /> <cfset user["email"] = "user_" & arguments.userId & "@example.com" /> <cfif (arguments.userId mod 2) eq 0> <cfset user["gender"] = "f" /> <cfelse> <cfset user["gender"] = "m" /> </cfif> <cfreturn user /> </cffunction> </cfcomponent>
I've posted a working example so that you can see how this code looks. For the "User ID" just enter any number. If an error occurs, the error callback will handle displaying the error to the screen. I've also posted the source code as a zip file you can download.
NOTE:If you're still on ColdFusion MX & 7, there's a little more work because non-string data automatically gets converted to WDDX. While there are JS libraries for converting WDDX to native JS objects, they can be hard to find now that the OpenWDDX site has been shut down. You can find tools at RIAForge though that can convert your data into a JS string--which jQuery will automatically evaluate when it's received.
UPDATE:I've added some sample code to the download to show how you can use a proxy template in you're using ColdFusion 7 to get the same results. Just look at the example_cf7.cfm. The only difference is we call the example_cf7_proxy.cfm template instead of calling the example.cfc directly. The proxy template uses CFJSON to convert the results to JSON.
[UPDATED: Friday, March 04, 2011 at 9:59:11 AM]
The code base I work in every day includes a few external development tools that are included in our source code. We include the tools in the source code, because it's the easiest way to ensure that every developer has access to the tool and can run them quickly.
However, one disadvantage to include external development tools into your Eclipse projects is they can slow down searching your enclosing projects because they include files you generally don't really want to search. If you have a library such as "MXUnit" in your source, that adds hundreds of files that would be added to the search which you don't want.
One way you can avoid searching specific folders is to set up a "Workspace" and stick to searching workspaces. This works great, but requires that you maintain your workspace and keep it up to date. Our code base has thousands of files and hundreds of folders over several different projects, so I just find maintaining the workspace a little more tedious than I'd like.
I much prefer using the "Enclosing projects" option in Eclipse, because it searches the files in your active project. I find these is much easier than changing the workspace when I'm looking at files in a different project. So I did a little research this morning to see if there was an option to exclude folders/files from showing up in the search by default.
Turns out Eclipse has a feature called Derived resources:
Many resources get created in the course of translating, compiling, copying, or otherwise processing files that the user creates and edits. Derived resources are resources that are not original data, and can be recreated from their source files. It is common for derived files to be excluded from certain kinds of processing.
When you mark a folder or file as derived, it's excluded searches. The caveat is Eclipse assumes derived resources are probably compiled resources, so if you try to edit a derived file you will be warned that the file is derived. However, since these are external tools that I'm not needing to regularly update, this behavior is fine—and actually a nice reminder.
To set a folder as derived:
This has done the job nicely. I've been able to exclude several hundred files from showing up in my searches that I really don't care about!
NOTE: Generally derived resources are typically not files you'd keep in a repository, because they can easily be rebuilt from source code. While I had no problems setting a folder already in my SVN to derived, it's possible some source control plug-ins might treat a derived resource as being "ignored".
One thing that's essential for any web application to be successful, is to implement a method for providing users with feedback based on their input. People want feedback based on their actions in real time. Users want to know that their actions had the intended consequence and if not, why it failed.
In the golden age of web applications, most applications solved this problem by returning a completely new page to the user any time they took an action on your website. If a user filled out a form on your website, the form's data would be sent to the server and the server would then generate a completely new page that either told the user that their action was successful or would show them the errors that occurred.
As web applications began to advance, more applications began to rely on JavaScript to provide more instantaneous feedback to users. If a user would leave a required field empty, developers would use a JavaScript alert() functions to notify users that they left the field incomplete. Over time, more and more applications have come to rely on JavaScript to provide users with a better user experience. The problem is that while the browsers have made many great strides over the years, we're still left with these very rudimentary UI controls for providing native feedback with users.
The alert(), prompt() and confirm() functions basically haven't changed at all since they were introduced. They offer essentially no control over the presentation and they're completely obtrusive to the user's experience. They all halt execution and force user action before any more processing occurs. While there are certain times this behavior is desired, there are many times when it's less than ideal.
For example, let's say you have you have a page that allows users to update bulk records in real time. On each row there is an "Update" button that allows a user to save updates back to the server. You obviously want to provide users with feedback after each update operation has completed. A quick solution is to use the alert() function when the update is successful.
The problems with this method are:
What we need is a better notification system that's just as easy to use, but allows us greater control over how the messages are display. This is where the jNotify Plug-in comes in. At just about 3KB, it's a very light-weight solution that gives us lots of flexibility over how we display notifications to the user. It allows us:
I put together a short little video that illustrates some of the typical UI problems that the use of the alert() function introduces and show how jNotify can be used to solve those problems.
Implementing jNotify on your site is extremely easy. Just include the jquery.jnotify.js and jquery.notify.css files on your page, then substitute your use of alert() with $.jnotify().
So, instead of:
alert("An e-mail notification has been sent!");
You'd use:
$.jnotify("An e-mail notification has been sent!");
We've been using this plug-in in our own applications for over a year and we've had great success with it—especially when used with conjunction of providing feedback to users when AJAX operations complete.
You can see a live example on the jNotify jQuery Plug-in page.
I was doing some UI work this morning and ran into a bit of a problem. We have some HTML input elements that need to be disabled so the user can not interact with them. The problem is, we wanted to display a message to the user if they tried to interact with the element. While some browsers respond to a mousedown event, Firefox and Opera ignore all mouse-related events on a disabled form field. Since they seem to completely ignore mouse interaction, that means not even event delegation works.
After thinking about various ways to work around the behavior, I thought the most elegant solution might be to add an overlay over the disabled element which I'd use as the hotspot for mouse interaction. The overlay lays on top of the element and intercepts all mouse interaction.
Let's look at some sample HTML:
<label for="normal"> <input type="checkbox" disabled="disabled" /> Disabled Option </label>
With a little jQuery magic, we can find the disabled element, get the parent <label /> element and then place a <div /> element over where the label element resides. The code looks like this:
// on DOM ready $(document).ready(function (){ // attach a click behavior to all checkboxes $(":checkbox").click(function (){ alert("Clicked!"); }); // find the disabled elements var $disabled = $("#overlay-example input:disabled"); // loop through each of the disable elements and create an overlay $disabled.each(function (){ // get the disabled element var $self = $(this) // get it's parent label element , $parent = $self.closest("label") // create an overlay , $overlay = $("<div />"); // style the overlay $overlay.css({ // position the overlay in the same real estate as the original parent element position: "absolute" , top: $parent.position().top , left: $parent.position().left , width: $parent.outerWidth() , height: $parent.outerHeight() , zIndex: 10000 // IE needs a color in order for the layer to respond to mouse events , backgroundColor: "#fff" // set the opacity to 0, so the element is transparent , opacity: 0 }) // attach the click behavior .click(function (){ // trigger the original event handler return $self.trigger("click"); }); // add the overlay to the page $parent.append($overlay); }); });
You can see a live example here.
I'm working on some "star rating" code and I really wanted to round numbers of to the nearest fraction. While the math is really basic, my math skills are rusty and this took me longer to solve than I care to admit. So I thought I'd just blog the solution for anyone else that might find it useful:
round( value/fraction ) * fraction
Like I said, it's very basic math but is very handy when you want to round to something other than to the closest integer.