Posts Tagged ‘Javascript’
jLinq Update (2.2.1)
I’m off from work this week so the first thing I did was get some work done on jLinq. I’ve had a few bugs I’ve needed to sort out along with a new feature I wanted to implement. I’m also going to be working on documentation this week. Previously, I had created a Wiki and was hoping that people might add to the documentation… but instead spam bots pretty much ruined it so I’ll be starting over from scratch… oh well..
New Features
jLinq itself doesn’t really have a new feature but instead a new way to get the jLinq library. Instead of simply downloading a standard jLinq library you can use the new online jLinq Framework Generator to select only the functionality that you want to include. You can still download the basic pack but this option gives you a little more control what goes into your version of jLinq.
Changes
The most notable change for jLinq is that all of the operator commands have been included as standard functions for the framework. Before, these functions were actually methods extended onto the framework. Since these functions are required for jLinq to work I’ve moved them so that they are in every jLinq framework by default.
Bug Fixes
orderBy with joined records would return incorrect results
jLinq uses eval to figure out the values of field names since you can provide methods, array indexes or whatever. The code used to sort the values wasn’t getting the values correctly so the sorted result was always wrong.
using 0 in certain comparisons would return incorrect results
Ah, this one was fun. So check out the code below…
var values = [ 0 ];
var index = 0;
var a = !values[index];
var b = values[index] == null;
So what is a and what is b? If you said true and false then give yourself a cookie.
jLinq uses the number of arguments passed to help determine if anything is being memorized (like the field name). jLinq makes a quick pass to select all values until it finds a null value… or at least that is what I meant for it to do. Unfortunately, I wasn’t thinking when I wrote that method and didn’t check explicitly for null.
Feedback
If you find any problems with jLinq or have any suggestions, please leave a comment or contact me directly.
Double Whammy – jLinq Release And Screencast!
Now that you’re all excited time for some disappointment – it is just a minor update to fix a few bugs and to add one new feature.
But instead of just blogging about it I’ve also done a new screencast to talk about the updates and new feature in this release.
- Dynamic Queries (using OR) – Before, if you used “OR” at the start of a query then you’d get an exception. jLinq would try and tag “||” at the start of your query which would cause the whole thing to collapse. Now, jLinq correctly handles this and prevents the error. In turn, writing dynamic queries just got a whole lot easier!.
- Range Comparisons With Dates – Version 2.2.0 introduced smarter comparisons by evaluating the types of values being passed in instead of expecting only one type. However, in the change, the range comparisons like
greater,less,between, etc, would all incorrectly evaluate Dates as strings… bummer. - Bitwise Flag Comparisons – jLinq 2.2.1 introduces a new query method called
haswhich performs bitwise flag comparisons on records. It even works with regular ol’ numbers by converting them before performing the comparisons.
Anyways, go check out he new screen cast now and tell me what you think!
Bonus: CamStudio Icon

Last night while I was setting up CamStudio for this screencast I was looking at their UGLY icon they use for their program — I just couldn’t stand it being in my beautiful RocketDock – so I designed a new one for them. If you’re looking for an improved logo then you can download the PNG for the CamStudio icon.
jLinq Screencast #3 – Modifying Records During A Query
Sometimes when you get your records they aren’t exactly what you we’re needing, or sometimes some of the fields need to be formatted before they can be queried against. Fortunately, jLinq comes with that functionality built into it.
This screencast goes over several of the methods you have available to you that allow records to be formatted before they are selected.
each(delegate(record)): Performs a loop through each of the values in the array. This code can be used to modify records, create new properties or anything you need it to do.attach(alias, delegate(record)): Performs the method passed in on each of the records in the array and attaches the result to the record using the alias provided.join(records, alias, foreignKey, primaryKey): Joins two arrays together using the alias and the keys to match the values. Joins tend to be slow when using large arrays, so use caution.
If you have any recommendations or requests for the next screencast, please let me know and I’ll see what I can do.
Side note: Never improvise on a screen cast – nothing like having to redo a screen cast twice because you say something that isn’t true and then realize it while recording.
More jQuery Magic – iPhone Style Password Box
I like to think of myself as a technology-neutral developer that can look past any Microsoft-Apple rivalries and instead focus on the best tool for the job…
I like to think that — but I know that I’m a total Microsoft fanboy…
So wouldn’t you know it that my entire FAMILY has been purchasing Apple stuff lately? Each (adult) family member has an iFail iPhone (except me, of course), my brother has an iTouch, sister-in-law with MacBook – Blasphemy! From my own flesh and blood!! ACK!!
However, despite this treachery I did discover that I did like the way that Apple handled inputting passwords.
iPhone Style Password Box
It’s worth mentioning up front that this code is just an experiment — it’s not a finished product and probably shouldn’t be pasted into a live site.
If you’ve used an iPhone before then you’ve probably noticed that you can see the last character you entered when inputting your password. This character disappears after a moment or two or the next time you enter a character. Using some jQuery and a hidden password field I attempted to create something similar.

Now unfortunately, by using a div instead of an input I’ve taken away the ability to select the characters in the field. When I was working on this I had an idea that I might try using the ‘contenteditable’ property instead and then display the normal password box for browsers that don’t support it.
Why Not A Input[Type=Text]
I tried doing a similar idea with by using a regular text box and just masking the characters on the fly, but ran into a problem where pasting a password would cause the whole thing visible for a moment — which seems like too much of a risk.
Another Approach
The basic idea of the Apple style password box was to show the most recently entered character but the first example lost some of the usability of a normal password box. I figured I’d give the idea a second pass, but adjusted it to be a little more HTML friendly.

You’ll notice in this version that the characters actually float up as you enter them. Similar to before, after a few moments, or when you press a new key, they will disappear.
This version is better from a usability standpoint, but it does have a couple problems of its own. For example, if you enter a really long password then the floating box stops moving at the end — no big deal right? Well for the end of the box, no, it looks fine — but if you click back out in the middle then your floating hints may be off-centered.
Simple But Effective Interface Designs
The code above isn’t ready for publishing, but they are some interesting examples of how you can take a typical form element and use a little jQuery to make some great usability enchancements to them.
You may have read some of my earlier jQuery posts about mimicking Vista style password boxes or creating search highlighting for web pages and noticed that it doesn’t take that much code to transform the functionality of your pages.
How do you enhance your pages for your visitors? It doesn’t take much!
Simulate Threading Using Javascript
One of the cool things about .NET is how easy it is to create more than one thread for your application to run on. On a recent project I had to make many calls to different web services on our network. They were all identical, but each call took quite awhile, roughly around 2 or 3 seconds each.
Instead of doing one at a time, I created 10 separate threads and then merged the results together. Instead of taking around 20 seconds, the calls were reduced to the length of the slowest call. (Web Services also have an Asynchronous method to call a service, so that is an alternative as well).
So What Does This Have To Do With Javascript?
In Javascript, any long running process will cause a noticeable lag for a user. Buttons won’t respond, links don’t do anything, the screen may even turn white — clearly not the user experience we want to deliver.
Recently I was experimenting with joining records using jLinq. jLinq was doing fairly well with the records I was using – I had about 850 records to join against a handful (about 10) of other records. The process finished in around 250ms to 500ms. I was pretty satisfied — until I tried a different set of records…
A different set of records, around 90, crippled the browser. After about 8 seconds the browser finally released itself and we were back in business. Yikes.
Simulating A Thread
So what are the options here? Well unless someone has built threading into Javascript then we’re forced to come with a more creative solution — enter setTimeout.
If you’ve read some of my blog posts before, you know I’m a big fan of enclosures. Using Javascript we can take advantage of both enclosures and setTimeout to try and simulate threading and reduce the time a browser is locked up.
So let’s say we’re working with a really large loop, say around 500,000 records – What can we do? One idea is to break up the work into smaller, more manageable chunks.
//loops through an array in segments
var threadedLoop = function(array) {
var self = this;
//holds the threaded work
var thread = {
work: null,
wait: null,
index: 0,
total: array.length,
finished: false
};
//set the properties for the class
this.collection = array;
this.finish = function() { };
this.action = function() { throw "You must provide the action to do for each element"; };
this.interval = 1;
//set this to public so it can be changed
var chunk = parseInt(thread.total * .005);
this.chunk = (chunk == NaN || chunk == 0) ? thread.total : chunk;
//end the thread interval
thread.clear = function() {
window.clearInterval(thread.work);
window.clearTimeout(thread.wait);
thread.work = null;
thread.wait = null;
};
//checks to run the finish method
thread.end = function() {
if (thread.finished) { return; }
self.finish();
thread.finished = true;
};
//set the function that handles the work
thread.process = function() {
if (thread.index >= thread.total) { return false; }
//thread, do a chunk of the work
if (thread.work) {
var part = Math.min((thread.index + self.chunk), thread.total);
while (thread.index++ < part) {
self.action(self.collection[thread.index], thread.index, thread.total);
}
}
else {
//no thread, just finish the work
while(thread.index++ < thread.total) {
self.action(self.collection[thread.index], thread.index, thread.total);
}
}
//check for the end of the thread
if (thread.index >= thread.total) {
thread.clear();
thread.end();
}
//return the process took place
return true;
};
//set the working process
self.start = function() {
thread.finished = false;
thread.index = 0;
thread.work = window.setInterval(thread.process, self.interval);
};
//stop threading and finish the work
self.wait = function(timeout) {
//create the waiting function
var complete = function() {
thread.clear();
thread.process();
thread.end();
};
//if there is no time, just run it now
if (!timeout) {
complete();
}
else {
thread.wait = window.setTimeout(complete, timeout);
}
};
};
// Note: this class is not battle-tested, just personal testing on large arrays
This example class allows us to pass in a loop and then supply a few actions for us to use on each pass. The idea here is that if we do a section, pause for the browser to catch up, and then resume work.
How exactly do you use this? Well let’s just say we have a really large loop of strings we’re wanting to compare…
var array = [];
for (var i = 0; i < 500000; i++) {
array.push("this is some long string");
}
That’s a lot of work to check all those – Let’s move it into our new class we created…
//create our new class
var work = new threadedLoop(array);
//create the action to compare each item with
work.action = function(item, index, total) {
var check = (item == "this is some long string comparison to slow it down");
document.body.innerHTML = "Item " + index + " of " + total;
};
//another action to use when our loop is done
work.finish = function(thread) {
alert("Thread finished!");
};
//and start our 'thread'
work.start();
If you run this test in a browser, you’ll see that our page is updated as each pass of the array is completed. This way our browser remains ‘responsive’ to a degree, but continues to process our work in the background.
This code allows you to set a few additional properties as well as an additional function.
- chunk: The number of records to loop through on each interval. The default is numberOfRecords * 0.005.
- interval: The number of milliseconds to wait between passes. The default is 1. A longer value gives the browser more time to recover, but makes the loop take longer.
- wait([timeout]): Waits the number of milliseconds before canceling the thread and blocking the browser until the work finishes. If no time is provided, as in left blank, the waiting starts immediately.
Threading Possibilities?
It’s always amazing to see what enclosures can do – I’m not so sure how simple this same creation would be in Javascript without them. With a little bit of code we can create a half-way decent attempt at creating an asynchronous experience for our user, even if we have a lot of work to do.
Could your heavy client side scripts benefit from ‘threading’?
jLinq (LINQ for JSON) Screencast #2 – Creating Your Own Extension Methods
jLinq is a Javascript library that allows you to do LINQ style queries with JSON data.
Did you know that jLinq let’s you extend the base library with your own methods? Did you realize that any method you create plugs right in and works with the built in jLinq features?
This screencast goes over some of the basics to creating your first extension method for jLinq.
Creating A Query Method
A Query method is what determines what records stay and which records are removed from a jLinq query. Here is a sample of what a extension method looks like.
jLinq.extend({
name:"evenValues", //the name of this method
type:"query", //the kind of method this is
count:0, //how many parameters we expect
method:function(query) {
//determine how to evaluate the value being compared
var compare = query.when({
"string":function() {
return query.value.length;
},
"array":function() {
return query.value.length;
},
"other":function() {
return query.helper.getNumericValue(query.value);
}
});
//the actual comparison
return compare % 2 == 0;
}
});
You’ll notice we provide the name of this new method, the kind of method (in this instance, a query method), the expected number of parameters (not counting the field name) and then the actual method we use to determine if we keep the record.
If you don’t understand how this works exactly then you might want to watch the screencast at the end of this post to see how this works step by step.
Operator Naming
This screencast also explains operator naming. When you extend a query method, several additional operator prefixed name methods are added to jLinq as well. Each of these perform the correct switches when they are used. For example…
//this method is one way to do it
jLinq.from(data.users)
.less("age", 30)
.or()
.evenValues()
.select();
//this method was generated automatically - saves us a step!
jLinq.from(data.users)
.less("age", 30)
.orEvenValues()
.select();
Of course, if you name your method something like orHasSomeValue() you’re going to end up with some strangely named operator methods (for example orOrHasSomeValue()).
It’s Simple–ish
Extension methods are a little confusing at first but after you create your first one you should be on your way. This screencast will get you started in that direction.
Watch Screencast #2 – Extending A Method In jLinq
.
Testing Your Javascript
I’ve noticed that there has been a lot of talk lately about TDD, or Test Driven Development. Personally, I see it useful in certain areas and not so much in others. But, one thing that I’ve found TDD really great for is Javascript libraries, or really any dynamic language for that matter.
Dynamic languages have a chance of being altered by anything at anytime. It makes them particularly difficult to debug. Have you ever tried this before?
window.alert = document.body; window.alert.innerHTML = "Dude, what?";
Yep, believe it or not, that code actually runs — and works as advertised!
So you’re working on a large Javascript library, how can you test? There is plenty of libraries out there that you can download and use, but for fun we’re going to write our own.
What Makes A Test?
It’s a good question! Basically you take some code from your library, check the results of a method or series of methods and then return back if the test succeeded or not.
That’s an overly simplistic view of a test – but it’s sufficient for this example. Here is some code I wrote for my jLinq tests.
setTimeout(function() {
(function(tests) {
var self = this;
self.index = 0;
self.errors = [];
self.target = document.getElementById("results");
this.assert = function(ok, msg) {
if (ok) { return; }
self.errors.push(msg);
};
var test = function() {
//reset
self.errors = [];
//try the method
try {
//document.body.innerHTML += "<hr/>" + tests[self.index].name;
this.current = tests[self.index].method;
this.current();
}
catch (e) {
self.errors.push("Exception: " + e);
}
//if not okay, display the errors
var result = ["<div class='result result-"];
if (self.errors.length > 0) {
result.push("error' >");
result.push("<div class='result-title'>#" + (self.index + 1) + ": " + tests[self.index].name + "</div>");
result.push("<div class='result-errors' >" + self.errors.join("<br />") + "</div>");
}
else {
result.push("success' >");
result.push("<div class='result-title'>#" + (self.index + 1) + ": " + tests[self.index].name + "</div>");
}
result.push("</div>");
self.target.innerHTML += result.join("");
//set the next test
self.index++;
if (self.index >= tests.length) { return; }
setTimeout(test, 1);
};
//start the tests
test();
})([
//Actual Tests go here
//more explained in a moment
//.......
])}, 250);
What we have created here is a special bit of code that only I know about. I actually invented it just today which I have named a “Recursive Function”.
…oh? You mean that’s been around for awhile now already? Nevermind then…
The code basically calls the same test routine each time, but increments our test index each time. This way all of our tests are completed, but are also done with a slight pause between each to keep our browser from locking up.
Adding A Test
So how do we actually create a test. What do we need to have for this to work? Well since we’re passing in array of tests our code will look something like this
//Rest of the class
//...snip...
})([
//Tests
{name:"Function charAt correctly finds values at indexes",
method:function() {
this.assert("abcd".charAt(0) == "a", "Did not locate correct letter checking start of string");
this.assert("abcd".charAt(3) == "d", "Did not locate correct letter checking end of string");
}},
{name:"Function calculateRate correctly returns percentage based on values",
method:function() {
this.assert(calculateRate(11000) == 0.5, "Did not calculate correct rate from values greater than 10,000");
this.assert(calculateRate(5100) == 0.3, "Did not calculate correct rate from values greater than 5,000");
this.assert(calculateRate(1100) == 0.1, "Did not calculate correct rate from values greater than 1,000");
this.assert(calculateRate(100) == 0, "Did not calculate correct rate from values less than 1,000");
}},
{name:"Runs a function (this test just fails for this blog example)",
method:function() {
this.assert(someFakeFunction(), "We won't see this message");
}}
]);
The tests above are some examples of tests you could write. I’m not an expert on this stuff by any stretch of the imagination, but these tests seem solid enough to tell us if one of our functions fail.
The last example calls a function that doesn’t exist, which in my code, passes the exception along as the error message.
So Why Does This Help
Remember the code sample at the start of the post? Where I just up and changed what window.alert does? Let’s say we had our tests and then somewhere in our code we did this…
String.prototype.charAt = function() { return "a"; }
It’s perfectly legal and it completely breaks what we expect our results to be.
Now, jLinq is 1655 lines of code right now, clearly not a behemoth of a library like jQuery, but large enough that I don’t remember what I wrote everywhere, but now that I have tests it doesn’t matter as much. I’m able to write some changes to the code, run the test and be certain that the library is still in tact. In fact, I wish I would have done it sooner.
What’s Next?
Don’t consider this to be all there is to TDD, but instead a very basic explanation of the concept of TDD. I would recommend to you that if you’re working on large project, especially dynamic languages, make sure you write tests for all of your functions. They will save you in the long run.
jLinq Screencast #1 – Getting Started With jLinq
Want to get started using jLinq, but want to see it in action a little before you do? You could go try it out online or you could watch the brand new jLinq screencast!
Yep, with a lot of effort, I’ve done my first screencast and it turned out not half bad (my wife survived 45 seconds before she left – she felt it was too boring
)
jLinq Screencast #1
- The four different types of commands in jLinq — source, query, action and selection.
- How to select a new object type from the
.select()command. - Reuse a query after selecting records.
- Explained how Command Memorizing and Field Memorizing works.
- Several sample queries.
So, what would you like to see next?
jLinq 2.2.0 Released!
Ever hear of jLinq. If not, it’s no big deal. Its a personal project of mine to make a LINQ style query language for Javascript. With all these “Web 2.0″ applications floating around, the ability to sort, query and manage your records on the client side may become a necessity. Use jLinq with the JSON data you already have and you’ve got quite a combination.
If you haven’t tried it out, there is an online version available you can use to see it in action.
Below are some of the new features in jLinq 2.2.0.
Smarter Comparisons
Let’s say you ran the command below…
jLinq.from(users)
.less("firstname", 5)
.select();
Seems simple enough, first names less than 5 characters long?
Nope…
The previous version of jLinq expected certain data types depending on the command. For example, if you used less, lessEquals, greater, greaterEquals, between or betweenEquals then the expected parameter was a number as was the field you were querying against.
In the new version you’ll find code like this when checking values.
//get the the parameter value
value = query.helper.when(value, {
number:function() { return value; },
other:function() { return value.length; }
});
//determine how to check this against the value
return query.when({
string:function() {
return (query.value.length < value);
},
array:function() {
return (query.value.length < value);
},
other:function() {
return (query.value < value);
}
});
Instead of making any assumptions, jLinq now checks the types and returns the values required to make the query work. For example, if you use ‘less’ with a string value, the length property is automatically used instead of the string value itself.
jLinq also is more intelligent with different command types. For example, the .contains() used to work with string values only. Now it works with arrays or converts a value to a string then checks the result.
11 New Commands
- attach(alias, function): Executes and attaches the return value of your function onto the record using the alias name you provice.
- sum(field): Returns an object with information about the sum of the field name used.
returns{
count:the number of records counted,
result:the sum of all records selected,
records:the records used to find the sum
} - average(field): Returns an object with information about the average of the field name used.
returns{
total:the sum before the average was calculated,
count:the number of records used,
result:the average of all records selected,
records:the records used to find the average
} - max(field): The maximum value found for the field name provided.
- min(field): The minimum value found for the field name provided.
- except(collection): Compares a second set of records and only returns records that are not found in the comparison list. Returns a new jLinq object. (example)
- intersect(collection): Compares a second set of records and only returns records that are found in both lists. Returns a new jLinq object. (example)
- union(collection): Compares a second set of records and only returns records that are unique in both lists. Returns a new jLinq object. (example)
- skipWhile(delegate): Skips selecting records until the first ‘false’ result is returned from your function. After that point, all records are selected. Returns an array of results. (example)
- takeWhile(delegate): Selects records until the first ‘false’ result is returned from your function. After that point, all records are ignored. Returns an array of results. (example)
- selectMany(collection, compareFunction, selectionFunction): Compares each value of the current query against the provided collection array (example). For each successful comparison a new record is added to your results. If you use your own selection method then you need to write a function similar to
function(queryRecord, compareRecord) {. The return value will be added to the list. If no selection method is used, then the following object is returned.
returns{
source:the record in the jLinq query that is compared,
compare:the record in the collection array that is compared
}
Bug Fixes
There was an Opera bug when you tried to sort records. I’m not sure that I understand why, but basically, there really is a difference between for loops in Opera.
jLinq Testing
If you’re interested in creating your own jLinq extension methods you can now download a series of tests that you can use to determine that your command doesn’t break anything else in jLinq.
Wrapping Up
Whew! You’re still with me? You must be dedicated!
Right now I realize that there still may be some confusion on how to use jLinq. I’m currently working on some screencasts that I can share to help people get started.
If you have some requests on what you would like to see in an upcoming screencast, please send me your ideas and I’ll add them to my list.
Source Code
Download jLinq-2.2.0.js
.
More jQuery Magic – Search Highlighting
So at first glance, which browser do you think we’re using in the screenshot below? FireFox? Chrome? IE8?

It’s actually IE6 and all that search highlighting is done via jQuery!

Now most modern browsers do some sort of highlighting now when you do a “Find On Page” search so this may not be the most incredible jQuery trick you see in your life — but at the very least it’s the most impressive jQuery trick on this page.
Highlighting The Page
If you’re interested in following along, you can view the demo/source code at this page.
In order to search the page we’re going to need to a couple things…
- Check for user input.
- Use the search phrase and find matching text.
- Replace our matches with the new highlighted text.
Let’s jump in.
Checking For Input
jQuery makes it easy to work with events that we’re previously… well… a pain. The .keyup() function allows you to supply a delegate to monitor for changes to your search field. Below is the code you’ll find in the example.
//snip ...
self.input.keyup(function(e) {
if (self.search) { clearTimeout(self.search); }
//start a timer to perform the search. On browsers like
//Chrome, Javascript works fine -- other less performant
//browsers like IE6 have a hard time doing this
self.search = setTimeout(self.performSearch, 300);
});
//snip...
As you can see by the comment, we don’t do the search each time the key goes down. IE6, bless it’s heart, tries it’s best to keep up but it’s a losing battle. Instead, we use a short time out to check for when the search begins. In many ways this is a lot better anyways. It’s fairly transparent to the user and saves undue strain on the browser.
Search And Find
Once we’re ready to search, we need to check the user’s input and format it as required.
//snip...
//create a search string
var phrase = self.input.val().replace(/^\s+|\s+$/g, "");
phrase = phrase.replace(/\s+/g, "|");
//make sure there are a couple letters
if (phrase.length < 3) { return; }
//append the rest of the expression
phrase = ["\\b(", phrase, ")"].join("");
//snip...
If you’ve read some of my blog before you know that I really like Regular Expressions…. a lot… In this part we use our expressions to format our search phrase. Specifically, we’re trimming it down and replacing spaces with “or”. This makes sure that any phrase in the box is matched.
You may want to change this depending on your needs, for example, require all values to match, etc…
Find, Replace, Repeat
Once we have a valid search phrase, now it’s time to actually replace the values on the page. You’ll notice that I target specific types of elements since you don’t want to search the entire document. Unlike a built in browser search option, this function actually makes changes to the markup. If you we’re to highlight a value inside a textarea then you’re going to end up with markup instead of a yellow block.
It’s worth noting that this version only works with elements that don’t have additional markup within them. Links, bold text, spans, etc… they are going to be wiped out by this. I’m working on another version that respects child elements, but for now – be warned.
The code below shows what we’re doing to make this change.
//snip...
//find and replace with highlight tags
$("h1, h3, p").each(function(i, v) {
//replace any matches
var block = $(v);
block.html(
block.text().replace(
new RegExp(phrase, "gi"),
function(match) {
return ["<span class='highlight'>", match, "</span>"].join("");
}));
});
//snip...
In this example I’m limiting my changes to a couple header tags and paragraphs. This helps me avoid things like my search bar at the top of the page. You could also create a class named .search and use that as a target.
The code starts by removing any existing highlighting classes from the element and then follows up by replacing any matches with a highlight tag.
Practical Uses… (tell me if you think of one)
I’ll admit that this was written just to see what it would look like. Most browsers already have a search on page feature that can be used to achieve the same effect. However, there are a few places that something like this may be handy.
AJAX Search Field
Have a page that searches other pages on the site and shows them as an list below the search field? Why not search the page they are on at the same time and highlight possible results?
Client Side Highlighting
Showing lists of data? Why not highlight matching values when a user hovers over certain buttons and filter options? Give them a preview of things to come?
Highlighting? How About Formatting?
Why just highlight text? Why not use this as dynamic formatting for text? Give users a preview of a change they are getting ready to make when they roll over a button?
Think this could be useful? Who knows! But it just goes to show just how much you can do with just a little bit of jQuery!



