Version 0.6.1.
Licensed under the MIT-License.
This page describes a technique which uses the keyboard keys to navigate through table rows.
Implemented by Stephan Soller <stephan.soller@helionweb.de> and
extended by Roberto Rambaldi.
Idea by Florian Seefried <florian.seefried@helionweb.de>.
The main idea of Florian Seefried was to make tables more userfriendly by giving them the possibilty to use the arrow keys to navigate thought table rows and using return to “enter” an record. Together with the backspace key this makes fast navigation possible. This behaviour is known from some desktop applications but is not seen very often on web applications. This little script should make it easier for programmers to integrate this behaviour into thier applications.
If you have any questions, want to report a bug or just want to talk about the script you can write a comment at the bottom of the page.
Just take a look at the example page. You can also download the example as a zipped archive.
Include jquery.js (jQuery v1.1.1) and jquery.table_navigation.js into your page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<script src="jquery.js" type="text/javascript"></script>
<script src="jquery.table_navigation.js" type="text/javascript"></script>
Call the jQuery.tableNavigation() function to initialize the table navigation.
<script type="text/javascript">
jQuery.tableNavigation();
</script>
You can specify some options to change the behaviour or source code interaction of the script. See
the options section for a detailed description. Calling jQuery.tableNavigation()
multiple times will update the options used by the table navigation.
Add the CSS class navigateable to the table element which you want to be navigateable
using the keyboard. Also add the CSS class activation to the a element of each row
whichs href attribute should be used if the user presses the return key or double clicks on the
row. This marks the link as the activation link for the corresponding row.
<table class="navigateable">
<thead>
<tr>
<th>Cell 01</th>
<th>Cell 02</th>
<th>Cell 03</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 01-01</td>
<td><a href="target01.html" class="activation">Link 01</a></td>
</tr>
<tr>
<td>Data 02-01</td>
<td><a href="target02.html" class="activation">Link 02</a></td>
</tr>
</tbody>
</table>
It's important to use the thead and tbody tags to seperate the table header from
the body. By default only the rows (tr elements) in the tbody element are selectable
and rows in the table header are not. You can change this by modifying the row_selector option (detailed
information below).
Create a CSS style for tr.selected which formats the currently selected table row.
<style type="text/css">
tr.selected {background-color: red; color: white;}
</style>
That's all. Much fun. If you find this little script useful, discovered bugs or have ideas to improve it, just leave a comment or drop me a mail.
You can specify some options when calling the jQuery.tableNavigation function to initialize the
table navigation. To update the used options just call jQuery.tableNavigation again with the new
options. The function takes these options as a hash:
jQuery.tableNavigation({
table_selector: 'table.navigateable',
row_selector: 'table.navigateable tbody tr',
selected_class: 'selected',
activation_selector: 'a.activation',
bind_key_events_to_links: true,
focus_links_on_select: true,
select_event: 'click',
activate_event: 'dblclick',
activation_element_activate_event: 'click',
scroll_overlap: 20,
cookie_name: 'last_selected_row_index',
focus_tables: true,
focused_table_class: 'focused',
jump_between_tables: true,
disabled: false,
on_activate: null,
on_select: null
});
table_selectorfocused_table_class option. Defaults to table.navigateable.
row_selectortable.navigateable tbody tr which will effect all table rows
(tr elements) inside a tables tbody element.
This way header tr elements inside of a thead
element will not be affected. You can use your own selector here but it have to
effect tr elements. Something like
div.overview tbody tr.viewable_records will
limit the effected table rows a little bit more.
selected_classselected.
activation_selectora.activation.
bind_key_events_to_linkstrue) or to the document object (false).
If the events are bound to the document object forms on the same page will not work
properly but the script won't need the focus to work. Default value is true,
to get pre v0.5.4 behaviour set it to false.
focus_links_on_selectbind_key_events_to_links
option is set to false. Defaults to true
but if you want pre v0.5.4 behaviour set it to false.
select_eventclick) but you can use all event names supported by
jQuery, see jQueries event docs.
activate_eventdblclick.
activation_element_activate_eventfalse or null
to not bind any event to the activation element. Defaults to click.
scroll_overlap20 pixels.
This also compensates some browser incompatibilities and a value blow 20
isn't recommended.
cookie_namenull the script will not use any cookies at all. Then
however if you return to a table you may find the wrong row selected. This is caused by
different browser caching behavior and usually the script can work around the problem using
cookies. The default cookie name is last_selected_row_index.
disabledfalse (event handlers are enabled).
See the demonstration page for an example.
focus_tablestrue or false) to toggle the highlighting of the current
table. If set to true the table of the currently selected row will be marked with the
class specified in the focused_table_class option. Set to false if you
just have one table on a page and/or want to increase the performance of the script. Defaults to
true.
focused_table_classfocused.
focused_table_classfocused.
jump_between_tablestrue or false) which allows you to controll if the script can jump
between multiple tables on one page. If set to true and the last row of a
table is reached the next row selected will be the first row of the next table. Note that this can confuse users
because the keyborad focus and the view port also jumps to the first row of the next table. Defaults to
true.
on_selectnull
and no user specified code is run. See user specified event handlers
for detailed information and examples.
on_activatenull and no user specified code is run. See
user specified event handlers for detailed information and examples.
They can be used to inject your own code on certain events like when a row gets selected or activated. A quick example will tell more than 100 words so here's one:
jQuery.tableNavigation({
on_activate: function(row){
var link_destination = jQuery("a", row).attr("href");
var user_wants_to_go = confirm('This link will bring you to "' + link_destination + '".\nDo you really want to go?');
return user_wants_to_go;
}
});
As you can see in the example the event handler is a function assigned to the on_activate
option. This function takes the DOM object of the row affected by the event as a parameter and is called every time a row is activated.
What you want to do with the row is up to you. In the example we grab the value of the first links href attribute and
ask the user if he wants to go to this location. We then return the users decision. But what is this return user_wants_to_go;
about?
If an event handler returns true (or anything other than false) the plugin will continue as usual
after calling our event handler. In case of the on_activate event it will redirect the browser to the location of the
activation link. However this default action is not always wanted eg. if the user clicks "abort" in our example. In this case an event
handler can return false to suppress the default action and the user will not be redirected to the new location.
Alternatively to specifying a function you can assign a simple string to the on_activate option:
jQuery.tableNavigation({
on_activate: "onclick"
});
or
jQuery.tableNavigation({
on_activate: "alert('we love the evil eval()');"
});
If the string you assigned to the on_activate option starts with "on" it is
interpreted as an attribute name. When a row gets activated the plugin will look for an attribute of the activation link named like this
and eval its content. Any other string will be evaled directly.
These approaches are usually hard to debug and not really good coding practice. In almost any cases you will be better of by using a function like in the first example.
Everything show here for the on_activate option also applies to the
on_select option. The default action of the on_select event is to mark the next row with the
class specified in the selected_class option and to scroll the page to make the new row visible
if necessary. Again if your handler returns anything but true these default actions will be skipped.
keypress event if an arrow key is pressed. However the keydown, and keyup events are working. The script now uses the keydown event if it detects IE.
file://...) Firefox 2.0 doesn't remember the last activated row correctly. It doesn't store or read the cookie used to save the index of the last activated row.getPos function of the Interface Elements utility functions or is caused by bad browser support as the results vary on different browsers.Want to help? Know a solution to a bug? Leave a comment or send me a mail.
This script intercepts several keyboard and mouse events and uses them to manipulate the currently selected row of a table.
First of by default the script will only affect tables of the CSS class navigateable. Within such a table the script considers
only rows (tr elements) with a tbody element as selectable. This is necessary to avoide that the table
header row can be selected (tr elements within the thead element). The selected row will be marked
with the CSS class selected. So if you want to define special styles for the selected row you should simply use the CSS
selector tr.selected.
Several events can be used to manipulate the selected table row:
tr element that follows the
currently selected tr element.
tr element just before the
currently selected tr element.
When selecting a row the CSS class "selected" is added to this rows tr tag.
This class gets removed from the previously selected row. Additionaly the activation link of the new row will be
focused and the screen will scroll to the position of the row leaving a certain amount of pixels to the border of the
viewport (default 20 pixels). This ensures that the selected row is visible. If there is no next row to select the
arrow keys will cause the page to scroll just as usual.
Activating a row will also select this row. More important this will read the URL of the first link
(a tag) in the row of the class activation. Before following this URL the index of
the currently activated row and the URL of the current page will be stored to a cookie.
So, the user got to the next page... what now? Usually if you entered a record you aren't intrested in you'll use the backspace key to get back to the table and select the next interesting one. It's intuitive to think that the record you just activated is also still selected if you come back to select the next one... Well, this heavily depends on the kind of caching the browser performs. Because every browser has it's own way of caching pages this doesn't work very well and you'll get everything but not the table with the row selected you activated before.
To bypass this limitation the script saved the index of the last activated row and the URL of this page in a cookie.
If the user now returns to the table the script reads the cookie and selects the row stored there which is the row the
user activated just before leaving. This will only be done if the URL stored in the cookie matches the current URL.
In case the user goes on to another page using this script the URLs don't match and the script will select the first
row, not some strange row index from another table. You can disable this workaround by setting the
cookie_name option to null.
This little script is build upon jQuery by John Resig and contributors.
It also includes the getPos and getScroll functions of the utility functions of Stefan Petres Interface Elements for jQuery.
Cookies are handled by the cookie handling functions form Quirks Mode written by Scott Andrew and edited by Peter-Paul Koch.
Roberto Rambaldi also added some nice things to it (namely the 0.4.0 release).
Much tanks to these guys, without them such a quickly (prototype done in about 4 to 6 hours) and clearly developed
script wouldn't have been possible.
Special thanks to Roberto Rambaldi for contributing the 0.4.0 release.
Also special thanks to Antonio Biondo whos few, simple but genius changes led to the 0.5.4 release.
focused.focused.activation_link_class option (default value activation) is replaced by the
more common activation_selector option (default value a.activation).
href attribute
(speak: links). This was necessary to not break the behaviour of checkboxes if used as activation elements.
disabled option to temporarily disable all event handlers of the script (requested by Jeff).jQuery.tableNavigation() call is done inside an
if / then statement the tagName property is suddenly undefined. Fixed by
using the nodeName property instead of the tagName property. Thanks to Brian Garibaldi for
helping me out with this.
jQuery.tableNavigation()
function will rebind all event handlers if necessary. This can be used to restore the table navigation behavior if another script modified
the elements of the table. You can take a look at a test page to explore this
behavior. Again thanks to HT for his help.
jQuery.tableNavigation() function was called multiple times. This broke the table navigation
behavior in a somehow funny way. However if you call jQuery.tableNavigation() multiple times now it'll just update
the settings used by the table navigation. Thanks to HT for reporting the bug.
on_select and
on_activate events. This feature is inspired by the on_activate
option contributed by Roberto Rambaldi.
getPos and getScroll functions of the utility functions
of Stefan Petres Interface Elements for jQuery directly into the script. Now
iutil.js is no longer required.
keypress event again to fix some unwanted scrolling with Opera. If IE is detected the
keydown event is used.
return_link_name option to the less confusing name activation_link_name.cookie_name option to null.on_activate option which specifies what should happen if a row gets activated. You can even use this option to write your own row activation handler.jquery.key_navigation.js to match the plugin name scheme.jQuery.tableNavigation namespace.scrollToIfNeccessary function which makes sure an highlighted row is visible on the viewport. This one needs Stefan Petres Interface utility library.Copyright (c) 2006 Stephan Soller <stephan.soller@helionweb.de>, Florian Seefried <florian.seefried@helionweb.de>.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Hi there,
I am using this tool with a gridview and AJAX.ASP.NET. It seems that after every partial refresh (ajax postback), the table no longer remains navigateable with keys. If, however, I include jQuery.tableNavigation() in a page load event (client side), it works with one problem: Pressing the keys makes it jump two rows. If I do another postback, it jumps 4 rows, 6 rows, 8 rows and so on.
I have been trying hard to figure out why and I think its because I call jQuery.tableNavigation() everytime a postback happens. The other side of the coin is that if I don’t then the table navigation features disappear after the postback.
Any thoughts are appreciated.
Thanks HT
Strange effect. I have no idea what ASP.NET exactly does when making an AJAX request. For me it looks like it reassigns several event handlers and therefore killing the jQuery event queue. This at least would explain why the table navigation behavior vanishes but I’m afraid I can’t do something to solve this specific problem. However, hang on. :)
The second problem you described (calling jQuery.tableNavigation() multiple times) is or was a general one and is fixed now (v0.5.1). Somehow funny, if you call jQuery.tableNavigation() a second time every event handler was defined again and also added to the jQuery event queue. Now there were two event handlers sitting in the queue which do exactly the same. If someone presses the arrow down key the script selected the next row and jQuery called the next event handler in the queue… which again selected the next row. Each time jQuery.tableNavigation() was called a new iteration was added to the event queue.
Again, this is now fixed in the brand-new v0.5.1 release. jQuery.tableNavigation() will now just update the settings of the table navigation behavior when called more than once.
Thanks for your comment and detailed bug description HT. :)
Hi Stephan,
Thanks for the fix! Works like a charm.
I have noticed one more odd behavior. When I do a postback, my table comes back (re-rendered) and all the keys work fine but mouse events get dropped. The selection and activation events don’t get fired.
I have been looking through the code and everything seems to be tied together just right but I am unsure why the table stops responding to mouse click events. If you have an idea of what might be happening, I’d love to hear.
I’ll investigate further on my side and will be sure to leave you a note if I find out anything.
Cheers HT
I’ll look into this and try to reproduce the behavior. The keypress event is bound to the document object whereas all other events are bound to all or some selectable rows. Maybe the more specific events will conflict with a postback.
Time to take a closer look into the jQuery event handling…
Thanks for your comment.
After a little bit of sleep it all made sense. Like described ahead the keyboard events are bound to the document object. A postback will not change this object and the event handler of the keyboard events will not be touched. The mouse events however are bound to each specific element (each table row). If a new row is added by another script (the postback) this new row will have no table navigation event handler bound to it. Clicks and double clicks won’t work.
I’ve restructured the script a little bit (v0.5.2) and each call to the jQuery.tableNavigation() function will now bind the event handlers to new rows if necessary. You can try this behavior out at a little test page I’ve created during the bug hunt.
I’ll have to do some cleanup work on the next major release but I hope this helps you for now.
Thanks again HT for making this script better and better. :)
Hi Stephan,
I discovered the issue as you have described as well. For the time being I was tying the events on my own each time a row was recreated and so it worked. But thanks so much for an updated script. It will help keep things cleaner for my project.
You’ve done a wonderful job with the script! Thanks so much.
Having a similar issue to what I think the other poster was saying. On my page load I do a $.load(...) for the tbody of the table. The HTML it appends is identical to that I before had hand written into the table to test. However the content I can see in my table but the table’s features are gone. Tried doing the jQuery.tableNavigation() in the loading both before and after when I do the $.load() but to no avail. Not sure if there is any workaround to this? I love the plugin though. Thanks.
Sorry for my late reply. I’ve been quite busy the last two days (work…) so I wasn’t able to check the comments on a daily base. It’s really time for a newsfeed about this.
However I’ve tried a bit around. The $.load() doesn’t seem to work at all. I think this is a side effect of using the more save and faster $.ready() function to do initial work. The plugin uses $(document).ready() to bind it’s event handlers so this may kill any $(document).load() event handler and replaces it with jQuerie code necessary to run the $.ready() function.
I suggest you try to use the $.ready() method on the tbody element. As far as I know it’s the reccomended method. If this is for some reason not possible I’ll try to get the $.load() event working. However it looks like a general jQuery problem to me.
I finally was able to get it going however once the page loads it requires the user to click a button which calls jQuery.tableNavigation() again. Unfortunately this is needed every time new data is loaded into the table, though I rarely load it more than once or twice, so same issue as the user before. I was able to use the mouse move event to fake that is does it automatically.
Anyway love the plugin! Would be neat to see it work on multiple tables but I understand processing the keyboard events would be tricky. Cheers.
Strange, are you sure you used the $(document).ready() event? Like said before $.load() didn’t worked at all in my tests.
Making the plugin work with multiple tables will be a nice excercise. I’ll try it in the next few days.
Hi, I am having an issue with the speed of your script when dealing with several hundred rows in a table (500+ rows).
The script works great, but each key down/up takes about 700ms-1000ms to respond and highlight the next row.
I have been searching for some answers to this problem for a while now, I thought it was a problem with my own keyboard navigation handler I wrote which experiences the same problem. Anyone come across this or are you aware of the issue with a large table?
Thanks for your help!
Hi Cory, the script does not cache the table rows it works on. It uses jQuery to find all rows of the table every time you press a key or click on a row. Doing a bit of profiling on a 1000 row table using FireBug shows that about 93% of the execution time goes to jQuery.
The reason for this, well, slow approach is flexibility. I hoped this would allow dynamic addition of rows by other scripts (eg. some AJAX stuff). But since this didn’t really works (jQuery.tableNavigation() have to be called after adding rows) I can rework the script using some caching.
However I won’t have the time for this in the next 4 or 5 days so the next release is still some time off. It will also contain some changes to not break forms which are on the same page as the script (reported by Antonio Biondo).
Great work! Your test page works a lot better. Will be testing it out today.
I absolutely love your code. Ingenious! This is exactly what I have been needing. With all the form work I do, I needed a way to keep people off of the mouse and this is the solution! I can’t thank you enough!!!
A lot of purists are all about CSS for everything and I tried to be that way too. In fact, I actually succeeded in making most everything CSS based, but at what a great cost! I now find myself going back to tables for many purposes because, well, they just work and there is no fuss! This code falls right in line with the direction I am going.
BTW, I had to do a few mods to your code to make it work for my purposes. Just to let you know, I had to make single click function activateRow instead of selectRow(), also, I wanted to execute the onclick event of radio buttons in the row instead of hyperlinks, so I modified some code there too. Finally, i made the mouseover events on the rows serve to Select the row too so that either mouse or keys could be used with the same effect. All in all, GREAT WORK I LOVE IT!
BTW, have you tested with jquery 1.1.3. I am having some issues with pressing Enter to activate the row, but that might be my own mods causing the problem. I’ll let you know.
- JEREMY
Thanks Jeremy.
I just looked into the jQuery 1.1.3 issue and fixed it. The difference is tiny: change line 240 from
jQuery(row).find('a.' + jQuery.extendedNavigation.settings.activation_link_class).focus();
to
jQuery(row).find('a.' + jQuery.extendedNavigation.settings.activation_link_class)[0].focus();
The difference is just the [0] before the focus() call. This calls the focus() method on the real DOM object instead of the jQuery collection. jQueries focus() method just fires the jQuery events bound to focus but not the native focus event.
I packed this tiny bug fix into a new 0.5.5 release. Much fun with it.
.parents(): functions the same as .ancestors() As of jQuery 1.1, .ancestors() is no longer supported. Please use .parents()
BTW, I also forgot to mention that i had to modify the script to simply execute the onclick event of the activated element in the row without redirecting (in other words, I commented out lines 288 to 292). With the onclick events, I make ajax calls.
take care, -jeremy
Thanks again. I’ve fixed this bug. However before the next release I ask you, if there is something else, that should be fixed. :)
Firebug (Firefox extension) didn’t found this error. I’m a bit curious, with which tools did you found this bug?
BTW, you can use the on_activate option to specify your custom on activate behaviour. If you use a function for this and this function returns false the default behaviour will be skipped.
jQuery.tableNavigation({
on_activate: function(row){
var destination_element_code = jQuery("input", row).attr("onclick");
eval(destination_element_code);
return false;
}
});Hello Stephan,
I would like to disable table navigation when I show a popup and enable it when the popup is closed, how can I do that ?
Thanks Jeff
I tried this to desactivate row activation: jQuery.tableNavigation({ on_activate: function(row){ return false; } }); It would be nice to be able to disactivate table navigation and row activation with a function.
Thanks
Jeff
Ok, version 0.5.6 is out. This fixes the “ancestors” bug reported by Jeremy Dill and adds a disabled option.
The disabled option can be used to temporarily disable all event handlers of the script as requested by Jeff. I’ve created a test page to demonstrate this.
Hello
Is it possible to use the script to navigate through a table and then pressing return slecting(or toggle) a checkbox on that line?
(I will only use the script for private use but uses my works website/e-mail)
Yes, it is. :)
However it was a bit painful so I updated the script an made it easier not to use links as activation elements. The new version 0.5.7 changes a view things under the hood:
activation_link_class option (default value activation) is replaced by the more common activation_selector option (default value a.activation).href attribute (speak: links). This was necessary to not break the behaviour of checkboxes.Ok, back to topic. I’ve created a demonstration page which uses checkboxes the way you described. Just take a look, code and documentation is also there.
Hope this helps you.
Stephan… you 5.7 fix was going to be my next request! :)
This code has all kinds of potential. I have to say thank you once again!
BTW, I do have 1 tiny question, and perhaps it turns into a request.
I want the mouseover of the row to act just like moving the keypad up and down…so people can use either and have the same experience. To accomplish that, I have just done this.
<tr onmouseover=” $(‘tr.selected’).removeClass(‘selected’);className=’selected’”>
But, this isn’t a complete solution and I am wondering if there is any way that I can simply call the selectRow function on mouseover. I couldn’t figure out how to access it in DOM. For example <tr onmouseover=”selectRow(this)”>
Better yet might be a built in method to turn this functionality on and off in the settings.
Finally, I think it might be nice to have a setting called doubleclick_to_activate or something like that. If true, then the behavior is as it is now…if false, then a single mouse click should activate the row. This goes along with the above request. The idea is that Mouse Rollover – then Click is same as Key Up/Down – then Enter.
- Thanks,
Jeremy
Ah.. my example code was stripped.
Lets try without the tag open/close
tr onmouseover=” $(‘tr.selected’).removeClass(‘selected’);className=’selected’”
and I wish I could just do this
tr onmouseover=”selectRow(this)”
-thanks ..jeremy
Sorry…not trying to dominate your comment board or anything. But I have one more thought. It would also be really nice if there was a way to jump from table to table in a multi-table page..so when I reach the end of one table, it jumps to the first row of the next..and vice versa….just an idea. jeremy
Thank you for your ideas, Jeremy.
I’ve already tried some stuff but I have to sleep over this. To make the events more flexible it could be a way to add options to change the event the handlers are bound to (e.g. “click”, “dblclick”, ect.).
However the handlings of multiple tables is a bit more difficult. Just jumping to the next table would destroy the natural tab order. Maybe another possibility would be to better highlight the that the tables could recive the focus. Maybe by a different border for focused and unfocused tables.
What do you think about this?
ps.: The comments use Textile for formatting. Code will work like this:
<pre><code>your code</code></pre>Finally, version 0.6.0 is out. This version does some nice things but honestly I’m to tired to write it here again, so I’ll just quote the change log:
focused.Please take a look at the updated options section, the new features and options are described there in more detail. I’ve also created a test page demonstrating the configurable events by creating the “hover” behavior requested by Jeremy Dill.
The code base of the plugin however has reached a dead point. I really want to do a complete rewrite of the plugin to clean up the code base, make it easier to use, more powerful and in general more jQueryish. Unfortunately currently I don’t have the time to do this because there are other (more important) projects on my ToDo list. So I don’t know when I find the time to do this rewrite.
But don’t fear, I’ll still take the time to maintain this plugin. Just don’t expect the code base to become cleaner until this rewrite. Much fun with the new release. :)
Nailed it! Way to go. Thanks a million.
Stephan,
I am now utilizing your new version and it works great. But I am wondering if there is any way (with this release or future) to support having more than one type of nav table on the page. In other words, having 2 tables on the page with 2 different settings. For example, the first table is
jQuery.tableNavigation({row_selector: 'table.navigateable tbody tr', selected_class:'selected', on_activate:function(row){alert('test one'} });";
and the second one has different classes and activation, so it needs the following settings
jQuery.tableNavigation({row_selector: 'table.navigateable2 tbody tr', selected_class:'selected2', on_activate:function(row){alert('test two')} });
I believe that presently, executing the tableNavigation for the second time will override whatever the last config was, breaking the first initilized table.
Sorry for being so needy (and greedy)! I can’t wait to show you what I am doing with your tool once I am done.
Thanks, - Jeremy
Hm, nice idea. Well, the current code base won’t be able to support this because it’s strongly fixed on one namespace (or closure, however it’s called in JavaScript).
When rewriting the plugin I’ll change the underlying architecture to make it more jQuerisch. This will also allow to bind different “navigation modes” to different elements. Somehow like this:
jQuery('table.navigateable').tableNavigation({/* some options*/});
This should bind all stuff to the jQuery element collection and it shouldn’t be a problem to bind other stuff to another element collection. However this is just a though and I don’t know how the implementation will look like.
That sounds good. Its all working great for me at this point! I managed to find a temporary work around allowing me to have 2 tables with different settings at the same time. It’s kind of crazy, but I essentially store and restore the settings when going to and exiting from the 2nd table. Hard to explain, but my function looks like this.
// TEMP STORAGE OF TABLE NAV SETTINGS...USED SO THAT WE CAN DO POPUPS WITH DIFFERENT TABLE NAVES...AND STILL REVERT TO ORIG SETTINGS ONCLOSE.
var bank= new Array();
function settingsBank(transaction){
if (transaction==0&&jQuery.extendedNavigation.settings!=null) {//make a deposit (store settings)
bank['selected_class']=jQuery.extendedNavigation.settings.selected_class;
bank['on_activate']=jQuery.extendedNavigation.settings.on_activate;
bank['on_select']=jQuery.extendedNavigation.settings.on_select;
bank['row_selector']=jQuery.extendedNavigation.settings.row_selector;
bank['jump_between_tables']=jQuery.extendedNavigation.settings.jump_between_tables;
}
if (transaction==1&&jQuery.extendedNavigation.settings!=null){ //make a withdrawal (revert settings)
for ( keyVar in bank ) {
jQuery.extendedNavigation.settings[keyVar]=bank[keyVar];
}
}
}
Woha, completely overlooked your post (probably while switching to another feed reader). Sorry for this.
Nice idea, swapping the settings object should do the job for most cases. The selector options (table_selector, row_selector, activation_selector) won’t work that way but anyway this is a nice trick.
Maybe it would be simpler to swap the complete jQuery.extendedNavigation.settings object instead the single options. Might make things easier.
ps.: Didn’t know the for (a in b) syntax until now. Thanks for this little trick. I really should by a good JavaScript book by now…
I saw the example to use checkboxes as activation targets which is interesting. But what I want is what Gmail does. Gmail lets you follow the link after pressing the Enter button just like this script. Italso uses the keyboard shortcut ‘x’ to toggle a checkbox in the selected row. Any tips? Perhaps this should just be a separate script.
Also, i can confirm that safari does not work. the selected row does not move.
I use table navigation in my link like this … href=”javascript:getSplitValue(‘myvalue’);” class=”activation”..... the table in WindowModal Dialog, why it can’t work, but when my link not javascript action justi link to other file it’s work, can u tell me what’s wrong
@fred: Look for the line 236:
break;
case 13: // return
activateRow(getSelectedRow().get(0));
And add a case statement with the keycode of ‘x’ before the case 13; line. This will also execute the activateRow function when ‘x’ is pressed.
@fredu:
The default on_activation handler prevents the default event from happening (executing the stuff in the href attribute). You should try to move the JavaScript code getSplitValue(‘myvalue’) to the on_activation handler. It should work then.
“Maybe it would be simpler to swap the complete jQuery.extendedNavigation.settings object instead the single options. Might make things easier.”
I actually tried that first, but I felt like this was doing a better job of targeting only my specific settings. I think both ways are ok, I don’t know which is more efficient. Hopefully, it is just a work-around for now.
I learn new things a lot too. I have an enormous JS bible…pretty nice actually.
Cheers.
Jeremy
I too hope it will be a workaround for not to long. We’ll see when school starts here. Maybe I’ll have more time for the projects, maybe less. I don’t know yet but I strongly hope for more.
I’m still thinking about buying Simply JavaScript from SitePoint…
A suggestion for more complex tables in which not every row has or can have an “activation” element. In table_navigation.js, function selectRow(), adding the following will prevent an error in any browser when a non-active row is clicked on:
if (jQuery.extendedNavigation.settings.focus_links_on_select) {
// New part
if(jQuery(row).find(jQuery.extendedNavigation.settings.activation_selector)[0] != null) {
// End New jQuery(row).find(jQuery.extendedNavigation.settings.activation_selector)[0].focus();
} // Extra bracket for If
}
Solved some problems I was having while experimenting.
Also, if there is a way to hijack the l/r arrow keys in all cells to emulate tab and shift+tab, or in a table where there are anchors in all cells allow them all to retain the keystroke events of the “activation” element, then you’d instantly have a fully navigable table. I have not tried yet, but will.
I have not implemented this code live yet, but have been interested in it very much. Thanks for your work.
Thanks for your bug report and it’s solution Bill. I’ve included it into the code base and made a 0.6.1 bug fix release. :)
keep up the your great work. thank you.
Thaks for the solution.It helps me a lot.Thank you again…
It just look to be what I need, thank you for this plugin.
Your plugin looks to propose row navigation. Is there an option to enable cell navigation (we can move to the left and right cell to, additionally to the up and down cell) ?
Thanks.
Unfortunately the plugin currently does not support cell navigation. The rewrite might support that in future but I don’t think I’ll find the time for this in the next half year. Sorry. :|
Great plugin,
Any suggestions on how to implement a hover effect (e.g. change of background-color) on table rows, – that will also work in IE6?
There already is a demonstration page for this behaviour. It also details the necessary option changes.
I hope this helps you.
Hi,
I am a new comer into this site and also for web development. I am facing a problem in table navigation in .net. Currently we are working on mark entry system project where the rows are made of cells. When we try to enter the marks into those cells it is enabling only tab keys. How should i work with > < and up and dows arrows to enter the marks.
—I want to refresh the page only when the submit button is pressed and for enter the cursor should move to the next cell. How can we do this using .net.
-- when we press enter the page gets refreshed.
Thanks in advance.
devi
Hello, and thanks for this plugin. It provides exactly the function I was looking for. However, I tested it with Safari 3+ and it does not work for some reason, safari is usually very good with jquery and javascript.
And also, I get very poor performance both in IE 6 and 7, as far as scrolling by arrow keys. The speed is good up to about 100 rows or so, but then it starts lagging. At 500 rows I get half a second for switching rows, and testing with 1000 rows I have about a whole second for switching. This using both your test file on your own site, and the test file included in the zip, altering the row numbers. Firefox works fine, but IE also creates popups warning about slow running script whenever the row number gets over 500+
I would settle for the 99ms response per row for 500 rows, any idea on how to go about enhancing the time? I only want to use the initial row and link scroll-by-key-hilight-and execute-on-enter, no hovers and form element support…
Any help on optimizing or stripping functions to gain performance is most welcome
/Torgil – kabelkultur.se
Thanks Torgil,
Unfortunately this script is very old and therefore might be outdated or using old and slow jQuery functions. Safari is also a problem for me because I don’t have a Mac somewhere near me so I can’t test this stuff properly for Safari. :|
As for optimization… well, the script uses a cached list of the table row objects to avoid letting jQuery parse the DOM tree on every key press. Unfortunately I found no easy way to get the next row so it uses some strange jQuery stuff to look it up right now. Maybe you can optimize this a bit by directly doing the DOM stuff yourself.
I haven’t worked with JavaScript for several month now so I’m afraid I can’t be much of a help for you… especially if it comes to IE specific stuff. :|
Thanks for your reply Stephan. I’ll digg around with it a bit myself, the function is perfect for a very large project I’m working on, and I’d rather get this plugin working than bring in stuff like ActiveWidgets or similar to do it.
As far as Safari goes, the version 3 beta for windows is perfect for testing web apps in, works exactly like the mac version except for the stufff that are still system dependant, like various form elements. Try it out, it helps you if you do stuff that meeds to be mac-compatible in the future.
Thanks again.
/Torgil
Hi Stephan Just an small Query i have do i have performance issue if i use this for a table of structure 12 columns and 200 rows. By see the example above for version 0.5.4 i found that my internet explorer brust out saying memorry issue will i face the same problem here….When this application i am build is in production and will be used by 1000users at atime.
Please let me know as this is Urgent and need to develop many pages soon
Sorry for the performance problems. The script hasn’t been updated for a long time and therefore I don’t know if it works well with more current versions of jQuery or IE.
You can try to make the script use a new version of jQuery but I haven’t programmed with JavaScript for about a year so I’m definitely not up to date.
I have three tables with class “navigateable” and I am hiding all those three tables by default by using style property and enabling them when user clicks on a button. But when I try to open this page in IE 7, I am getting an alert as “Can’t move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus”. But it is working fine in FF. This error is because of the tables visibility. Is there any way to overcome this?
Hm, this might be caused by the row selection. If a row gets selected the script tries to focus it and this likely causes the error in IE.
Some workaroung I can thing of might be the focus_links_on_select option. Set it to false as long as the tables are hidden and if you show them set it to true again. This might prevent this error.
Is there any option to move focus to the first item when user presses ‘down arrow’ when focus is on the last item?
Is there any way to disable cookies functionality in Table navigation. i.e., when I come back to form once again, then I the previosly selected row is highlighted by default. How can I disable this?
Sorry for my late reply Arun. Looks like my feed reader stopped refreshing some feeds after I updated several days ago.
Regarding the “arrow down” behavior I did not implemented this to not confuse the user to much by a sudden page jump and to not break the arrow key scrolling. However I think it can be implemented by using a custom on_select event handler. These are described in detail in the documentation up ahead and within the source code of the script.
Regarding the cookies: You can disable the usage of cookies by setting the cookie_name option to null. This will prevent the script from using them.
oray , Arun ga for optimization… well, the script uses a cached list of the table row objects to avoid letting jQuery parse the DOM tree on every key press. Unfortunately I found no easy way to get the next row so it uses some strange jQuery stuff to look it up right now. Maybe you can optimize this a bit by directly doing the DOM stuff yourself
Thanks for this idea. I might do that in the future but right now I don’t have the time to update or to improve this script. Haven’t really programmed JavaScript for about a year now…
Another, easier to implement, possibility might be to add a reference to the next and previous table row directly to each row. A kind of linked list so to speak. Should increase performance quite a bit and since no big list of DOM objects is needed should also decrease memory usage. I might try that but right now I really don’t have much time left. :|
@okkadu Please give respect to the other person.
@Stepham Soller I would like to implement table key navigation for two different tables, one of them uses click as select_event and the other one uses mouseover as select_event. This is causing some problems.
After initializing key navigation for these tables(table_selector is different), the latest one is working( Rows in first table are also being activated when cursor is placed over a row).
As far as I can remember the script uses an option hash that is used by all tables. Because of this all tables should behave the same way.
To change this you can try to attach the option hash to the table element of each navigatable table. With this in place the script can read it’s configuration from there instead from the global option hash.
Stephen, I am using the cookie_name option to null. It is working in my system perfectly and I am able to disable cookies. But when I place the same code on a new machine, it is not working even though the cookie_name option is set to null. What would be the problem?
Can you please specify more details? What is the wanted behavior and in what way it doesn’t work on the new machine? Are you changing the host of the code (read: the domain name of the cookie changed) or are you just viewing the page from a different machine?
I am viewing the page from a different machine. I want to disable the functionality of using cookies for storing selected row index.
Hi, Please go to: http://tutorialsforu.com/Sample.html and click on the last record in table, table is out of view. What would be the problem?
Hm, I just tested it on my computer and all works as expected. Maybe we have a little misunderstanding here: If the cookie_name option is set to null the script does not create a cookie and therefore has no possibility to highlight the last selected row when you return to the table. So if you disable cookies you relay on browser caching to select the right row and this is very different between browsers.
Stephen, what I am doing is: I have set the cookie_name option to null. I tested it on my machine and verified(using FireCookie) that no cookie is created and the navigation is working fine. Then the same code moved to a Linux server and when ever I use the key navigation, a cookie with name “last_selected_row_index”. I don’t know why this cookie is being created even though I set the cookie_name option to null.
One more thing is, the cookie is being created when user clicks on a row, not when user uses keys to navigate.
Now that is strange. Since it all runs on the client, what browser is running on the client machine? Are you sure that the cookie was deleted before running the tests on the client? Can you make sure that this option is set to null on every page that uses table navigation?
Yes, before browsing the page, the cookie has been removed. I have to make sure that other pages that are also using cookie_name option and it is set to false.
I have a navigable table which is having 100 rows and I have placed this table inside a DIV whose overflow property is set to scroll. So, vertical scroll bar is displayed. If I use keys and navigate to the rows at the bottom of the table, then the page is also being scrolled and the table is out of view. Then I scrolled to the top of the page, and clicked on the last row, this time also page is scrolled even though I have not used keys to navigate. What would be the problem?
Hi, I have an serious problem here.. Can you please help me on this. I have done with this code.But now when i add rows dynamically to my table through javascript the table navigation fails.Please help me how can i have enable of rows that are added dynamically. Also i ahve mentioed into td with an ahref elemnt with class=”activation”. Please help it is bit urgent
Hi Stephen, nice plugin!
I’ve noticed that you use global settings for all the tables. In my case I have two tables in the same page, but I want to specify different options for each table. It could be nice to be able to do $(’#table1’).tableNavigation() and $(’#table2’).tableNavigation(). Any plans to include this?
Thanks in advance.
Hi Stephen.
Thank you very mach for your plugin. But I see that some options could be improved. Your plugin supports the homogeneous table, when all rows have same type. But in my case in the table I have “anchor” rows, and also “select” rows (This is by MRD, it is not virtual example :-). To all rows could be assigned class “activation”. Problem with different behaviour by selection may be solved easyly by handling “on_select” event. But “activation_selector” allows to define only one type of row activation element. I saw that changing this selector to collection of selectors is possible. In my case value will be actSelectors.add(‘select.activation’); actSelectors.add(‘a.activation’);
Thanks in advance.
Hi Stephen.
Additional note. From time to time we need to do some action when a table row gets unselected status. For example, a row has image and the icon must be changed when the row is selected and restored when the row is unselected. For this purpose we could add the ‘on_unselect’ option and call a user specified function for this option from ‘function selectRow(row)’.
var prevSelRow = getSelectedRow().get(0);
if (row != prevSelRow) executeEventHandler(prevSelRow,jQuery.extendedNavigation.settings.on_unselect);
Pay attention that ‘on_unselect’ function calling have to be predecessor of ‘on_select’ function calling.
Thank you for your attention.
Hi, I really love the script but I’m having one problem that hopefully you can help with, or at least clarify so that I can set about fixing it myself.
This is in Firefox 3.04.
I have a table with 3 columns, the first column holds the selector, the second column holds some hidden data that I read in if someone actually selects the row, and the third column holds various unstructured data. In the third column you should be able to select text (with the mouse) but whenever I do the rendered table does a little jump and my selected text is no longer selected. This bug is not seen if I select text all the way to the end of the line or over several lines, but if I select text in which there is still more text on the line it is a problem.
Hi,
I’m having a problem I thought that with a call to the the table navigation function like this:
jQuery.tableNavigation({ row_selector: “table.navigateable tbody tr.activatingrow”, } );
and an html structure like this:|
class=”activation” onclick=”activation();return false;”>a | 1 | 2 |
| 3 | 4 | 5 |
| <a href=”#”
class=”activation” onclick=”activation();return false;”>a | 6 | 7 |
That the table would be navigable, that is to say it when I pressed the down arrow it would move to the next tr class = activatingrow, rather than to just sit there.
Is there any explanation why this is not happening. How can I have a navigating table where it navigates between every other row?
It should be noted that this was the way I found to solve the earlier problem I had, to actually allow selection of text within the row I have to have it in the non-selected row.
I need this type of solution but it seems to be slow when applied to a large table with over 200 columns. Any suggestions?
not working with up and down key with Google Chrome browser any idea????
Hi!!! Need a little help here. How can i get the id of row that is highlighted, or an event to throw my id to my javascript function…