Java Webアプリケーション+jQuery DataTables 1.9.4のbStateSave=trueでCookieに状態保存できない
はまったのでメモ。
事象
Tomcatで動作するJava Webアプリケーション上でjQuery DataTablesを使用しています。
DataTablesでは前回表示した状態を保持する機能がある(以下参照)のですが、Java Webアプリケーションの中で使うと状態保持できず、常に初期状態の表示になってしまいます。
DataTables example
原因
jQuery DataTablesが生成するCookieのキーの一部に「;jsessionid=xxx」が入ってしまうため、保存に失敗する。
参考
When using DataTables in a J2EE application with the state cookie a bug occurs when jsessionid is appended to the URL. Since the cookie name uses the path it ends up including the jsessionid along with it. The bigger issue with this is that jsessionid is by markcuk · Pull Request #59 · DataTables/DataTables · GitHub
ただし、コミット内容を見ると状態の保存の場合のみで状態の読込部分に対応できていない…。
対処
jquery_datatables.jsの以下の部分を修正すると正常動作する。
1. _fnCreateCookie
変更前
/* * Shocking but true - it would appear IE has major issues with having the path not having * a trailing slash on it. We need the cookie to be available based on the path, so we * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the * patch to use at least some of the path */ var aParts = window.location.pathname.split('/'); var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase(); var sFullCookie, oData; if ( fnCallback !== null )
変更後
/* * Shocking but true - it would appear IE has major issues with having the path not having * a trailing slash on it. We need the cookie to be available based on the path, so we * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the * patch to use at least some of the path */ var aParts = window.location.pathname.split('/'); var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase(); var sFullCookie, oData; /* * Need to remove anything after a semicolon so that the cookie doesn't contain one. * This occurs when jsessionid is appended to the url for example. */ sNameFile = sNameFile.split(';', 1)[0]; if ( fnCallback !== null )
2._fnReadCookie
変更前
var aParts = window.location.pathname.split('/'), sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=', sCookieContents = document.cookie.split(';');
変更後
var aParts = window.location.pathname.split('/'), sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase().split(';', 1)[0] + '=', sCookieContents = document.cookie.split(';');