From 6c4309a1e821e450cd46a680e341b97ead1292f3 Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 12:46:31 +0700 Subject: [PATCH 01/50] - support kaminari Signed-off-by: Sakchai Siripanyawuth --- app/views/layouts/application.datatables.jsonify | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/application.datatables.jsonify b/app/views/layouts/application.datatables.jsonify index 39cfc71..8e301f9 100644 --- a/app/views/layouts/application.datatables.jsonify +++ b/app/views/layouts/application.datatables.jsonify @@ -5,13 +5,13 @@ instance_variables.each do |vn| v = instance_variable_get(vn) next if v.class.name.nil? if v.class.name.start_with?("MetaSearch::Searches") and v.respond_to?('size') - current_page_entries = v.size + current_page_entries = v.total_count end if v.class.name.start_with?("ActiveRecord::Relation") and v.respond_to?('size') - current_page_entries = v.size + current_page_entries = v.total_count end if v.class.name.start_with?("Array") and v.respond_to?('size') and (current_page_entries == 0) - current_page_entries = v.size + current_page_entries = v.total_count end if v.class.name.start_with?("Mongoid::Criteria") @@ -21,7 +21,7 @@ instance_variables.each do |vn| if v.respond_to?('total_entries') total_entries = v.total_entries - current_page_entries = v.size + current_page_entries = v.total_count break end end From 909f1c38b37297b0093f5f9eada89026ab545b4c Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 12:47:36 +0700 Subject: [PATCH 02/50] - added kaminari dependency Signed-off-by: Sakchai Siripanyawuth --- simple_datatables.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/simple_datatables.gemspec b/simple_datatables.gemspec index c3c997b..d4329b4 100644 --- a/simple_datatables.gemspec +++ b/simple_datatables.gemspec @@ -20,5 +20,6 @@ Gem::Specification.new do |s| s.add_dependency "rails", "~> 3.1.0" s.add_dependency "meta_search", '~> 1.1.0' s.add_dependency "jsonify-rails" + s.add_dependency "kaminari" end From 2cbe05b1ac409f37ff8049724532e526d338f730 Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 12:49:50 +0700 Subject: [PATCH 03/50] kaminari support Signed-off-by: Sakchai Siripanyawuth --- app/views/layouts/application.datatables.jsonify | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/application.datatables.jsonify b/app/views/layouts/application.datatables.jsonify index 8e301f9..9b9cfe8 100644 --- a/app/views/layouts/application.datatables.jsonify +++ b/app/views/layouts/application.datatables.jsonify @@ -4,13 +4,13 @@ current_page_entries = 0 instance_variables.each do |vn| v = instance_variable_get(vn) next if v.class.name.nil? - if v.class.name.start_with?("MetaSearch::Searches") and v.respond_to?('size') + if v.class.name.start_with?("MetaSearch::Searches") and v.respond_to?('total_count') current_page_entries = v.total_count end - if v.class.name.start_with?("ActiveRecord::Relation") and v.respond_to?('size') + if v.class.name.start_with?("ActiveRecord::Relation") and v.respond_to?('total_count') current_page_entries = v.total_count end - if v.class.name.start_with?("Array") and v.respond_to?('size') and (current_page_entries == 0) + if v.class.name.start_with?("Array") and v.respond_to?('total_count') and (current_page_entries == 0) current_page_entries = v.total_count end From f744d3a937afb7218d4486c641521bf5f7b8be5b Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 12:55:02 +0700 Subject: [PATCH 04/50] fix total_entries Signed-off-by: Sakchai Siripanyawuth --- app/views/layouts/application.datatables.jsonify | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/application.datatables.jsonify b/app/views/layouts/application.datatables.jsonify index 9b9cfe8..00c3e57 100644 --- a/app/views/layouts/application.datatables.jsonify +++ b/app/views/layouts/application.datatables.jsonify @@ -19,8 +19,8 @@ instance_variables.each do |vn| break; end - if v.respond_to?('total_entries') - total_entries = v.total_entries + if v.respond_to?('size') + total_entries = v.size current_page_entries = v.total_count break end From 75954c9c4513c36282666bf77a60559b3d5839f9 Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 12:58:56 +0700 Subject: [PATCH 05/50] fix for kaminari Signed-off-by: Sakchai Siripanyawuth --- .../layouts/application.datatables.jsonify | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/views/layouts/application.datatables.jsonify b/app/views/layouts/application.datatables.jsonify index 00c3e57..cc3d27b 100644 --- a/app/views/layouts/application.datatables.jsonify +++ b/app/views/layouts/application.datatables.jsonify @@ -4,14 +4,14 @@ current_page_entries = 0 instance_variables.each do |vn| v = instance_variable_get(vn) next if v.class.name.nil? - if v.class.name.start_with?("MetaSearch::Searches") and v.respond_to?('total_count') - current_page_entries = v.total_count + if v.class.name.start_with?("MetaSearch::Searches") and v.respond_to?('size') + current_page_entries = v.size end - if v.class.name.start_with?("ActiveRecord::Relation") and v.respond_to?('total_count') - current_page_entries = v.total_count + if v.class.name.start_with?("ActiveRecord::Relation") and v.respond_to?('size') + current_page_entries = v.size end - if v.class.name.start_with?("Array") and v.respond_to?('total_count') and (current_page_entries == 0) - current_page_entries = v.total_count + if v.class.name.start_with?("Array") and v.respond_to?('size') and (current_page_entries == 0) + current_page_entries = v.size end if v.class.name.start_with?("Mongoid::Criteria") @@ -19,9 +19,9 @@ instance_variables.each do |vn| break; end - if v.respond_to?('size') - total_entries = v.size - current_page_entries = v.total_count + if v.respond_to?('total_count') + total_entries = v.total_count + current_page_entries = v.size break end end From 8a55db5cb6e651e811850d09c8da02148cc0bb59 Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 13:02:42 +0700 Subject: [PATCH 06/50] fix coffee script bug Signed-off-by: Sakchai Siripanyawuth --- vendor/assets/javascripts/simple_datatables.js.coffee | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vendor/assets/javascripts/simple_datatables.js.coffee b/vendor/assets/javascripts/simple_datatables.js.coffee index e72da83..fd023f6 100644 --- a/vendor/assets/javascripts/simple_datatables.js.coffee +++ b/vendor/assets/javascripts/simple_datatables.js.coffee @@ -75,5 +75,4 @@ root.simpleDatatables = ( sSource, aoData, fnCallback ) -> "_sw" data.push({name: "search["+searchcolumns.join("_or_")+op+"]", value: sSearch}); - $.ajax( { "dataType": 'json', "type": "GET", "url": sSource, "data": data, "success": fnCallback } ); - \ No newline at end of file + $.ajax( { "dataType": 'json', "type": "GET", "url": sSource, "data": data, "success": fnCallback } ); \ No newline at end of file From 61e35e6f6cc5bc7f86d2c7e86b098f6144bd8c0b Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 13:08:21 +0700 Subject: [PATCH 07/50] fix typo Signed-off-by: Sakchai Siripanyawuth --- vendor/assets/javascripts/simple_datatables.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/assets/javascripts/simple_datatables.js.coffee b/vendor/assets/javascripts/simple_datatables.js.coffee index fd023f6..4e5f1c0 100644 --- a/vendor/assets/javascripts/simple_datatables.js.coffee +++ b/vendor/assets/javascripts/simple_datatables.js.coffee @@ -66,7 +66,7 @@ root.simpleDatatables = ( sSource, aoData, fnCallback ) -> $.each(columns, (index, val) -> data.push({name: "columns["+index+"]", value: val}); ); - + if sSearch op = if bRegex From a6556b6d77c87b5a3b8b8ecb648b1a7fafa24cfd Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 13:21:25 +0700 Subject: [PATCH 08/50] -fix indentation Signed-off-by: Sakchai Siripanyawuth --- vendor/assets/javascripts/simple_datatables.js.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/assets/javascripts/simple_datatables.js.coffee b/vendor/assets/javascripts/simple_datatables.js.coffee index 4e5f1c0..3302efc 100644 --- a/vendor/assets/javascripts/simple_datatables.js.coffee +++ b/vendor/assets/javascripts/simple_datatables.js.coffee @@ -69,10 +69,10 @@ root.simpleDatatables = ( sSource, aoData, fnCallback ) -> if sSearch op = - if bRegex - "_contains" - else - "_sw" + if bRegex + "_contains" + else + "_sw" data.push({name: "search["+searchcolumns.join("_or_")+op+"]", value: sSearch}); $.ajax( { "dataType": 'json', "type": "GET", "url": sSource, "data": data, "success": fnCallback } ); \ No newline at end of file From 776c3ac740292367a38ca62504fd1f41862159d1 Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 13:26:22 +0700 Subject: [PATCH 09/50] - update read me Signed-off-by: Sakchai Siripanyawuth --- README.rdoc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.rdoc b/README.rdoc index cb37720..8782703 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,4 +1,6 @@ -= Simple Datatables += Simple Datatables for Kaminari + +This fork works with kaminari gem! Connects two awesome plugins - Datatables for Jquery and Meta Search together for Rails 3.1 @@ -24,12 +26,12 @@ There are two ways to map awesome Datatables plugin request fields for Rails. This gem provides interface for the second way. To use it you should do the following easy three steps: -Create simple meta_search and will_paginate (optionally) controller action as usual and add ".datatables" format +Create simple meta_search and kaminari (optionally) controller action as usual and add ".datatables" format respond_to :html, :datatables def search - @products = Product.search(params[:search]).paginate(:page => params[:page], :per_page=>params[:per_page]) + @products = Product.search(params[:search]).page(params[:page]).per(params[:per_page]) respond_with @products end @@ -55,7 +57,7 @@ Gem includes datatables library and fnSetFilteringDelay plugin so you haven't in == Pagination -Simple_datatables is compatible with will_paginate. Datatables will provide you "page" and "per_page" request params. +Simple_datatables is compatible with Kaminari. Datatables will provide you "page" and "per_page" request params. If you do not use pagination do not forget to save search result to some variable with meta_search relation method: From eaa55ba49ae2b430a87e014c560858c31bd7b05c Mon Sep 17 00:00:00 2001 From: Sakchai Siripanyawuth Date: Tue, 15 Nov 2011 13:38:45 +0700 Subject: [PATCH 10/50] update to data tables 1.8.2 Signed-off-by: Sakchai Siripanyawuth --- .../assets/javascripts/jquery.dataTables.js | 7440 +++++++++++++++++ .../javascripts/jquery.dataTables.min.js | 153 - .../javascripts/simple_datatables.js.coffee | 2 +- 3 files changed, 7441 insertions(+), 154 deletions(-) create mode 100644 vendor/assets/javascripts/jquery.dataTables.js delete mode 100644 vendor/assets/javascripts/jquery.dataTables.min.js diff --git a/vendor/assets/javascripts/jquery.dataTables.js b/vendor/assets/javascripts/jquery.dataTables.js new file mode 100644 index 0000000..a295d17 --- /dev/null +++ b/vendor/assets/javascripts/jquery.dataTables.js @@ -0,0 +1,7440 @@ +/* + * File: jquery.dataTables.js + * Version: 1.8.2 + * Description: Paginate, search and sort HTML tables + * Author: Allan Jardine (www.sprymedia.co.uk) + * Created: 28/3/2008 + * Language: Javascript + * License: GPL v2 or BSD 3 point style + * Project: Mtaala + * Contact: allan.jardine@sprymedia.co.uk + * + * Copyright 2008-2011 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, as supplied with this software. + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/* + * When considering jsLint, we need to allow eval() as it it is used for reading cookies + */ +/*jslint evil: true, undef: true, browser: true */ +/*globals $, jQuery,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageProcess,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnArrayCmp,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn*/ + +(function($, window, document) { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Section - DataTables variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /* + * Variable: dataTableSettings + * Purpose: Store the settings for each dataTables instance + * Scope: jQuery.fn + */ + $.fn.dataTableSettings = []; + var _aoSettings = $.fn.dataTableSettings; /* Short reference for fast internal lookup */ + + /* + * Variable: dataTableExt + * Purpose: Container for customisable parts of DataTables + * Scope: jQuery.fn + */ + $.fn.dataTableExt = {}; + var _oExt = $.fn.dataTableExt; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Section - DataTables extensible objects + * + * The _oExt object is used to provide an area where user defined plugins can be + * added to DataTables. The following properties of the object are used: + * oApi - Plug-in API functions + * aTypes - Auto-detection of types + * oSort - Sorting functions used by DataTables (based on the type) + * oPagination - Pagination functions for different input styles + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /* + * Variable: sVersion + * Purpose: Version string for plug-ins to check compatibility + * Scope: jQuery.fn.dataTableExt + * Notes: Allowed format is a.b.c.d.e where: + * a:int, b:int, c:int, d:string(dev|beta), e:int. d and e are optional + */ + _oExt.sVersion = "1.8.2"; + + /* + * Variable: sErrMode + * Purpose: How should DataTables report an error. Can take the value 'alert' or 'throw' + * Scope: jQuery.fn.dataTableExt + */ + _oExt.sErrMode = "alert"; + + /* + * Variable: iApiIndex + * Purpose: Index for what 'this' index API functions should use + * Scope: jQuery.fn.dataTableExt + */ + _oExt.iApiIndex = 0; + + /* + * Variable: oApi + * Purpose: Container for plugin API functions + * Scope: jQuery.fn.dataTableExt + */ + _oExt.oApi = { }; + + /* + * Variable: aFiltering + * Purpose: Container for plugin filtering functions + * Scope: jQuery.fn.dataTableExt + */ + _oExt.afnFiltering = [ ]; + + /* + * Variable: aoFeatures + * Purpose: Container for plugin function functions + * Scope: jQuery.fn.dataTableExt + * Notes: Array of objects with the following parameters: + * fnInit: Function for initialisation of Feature. Takes oSettings and returns node + * cFeature: Character that will be matched in sDom - case sensitive + * sFeature: Feature name - just for completeness :-) + */ + _oExt.aoFeatures = [ ]; + + /* + * Variable: ofnSearch + * Purpose: Container for custom filtering functions + * Scope: jQuery.fn.dataTableExt + * Notes: This is an object (the name should match the type) for custom filtering function, + * which can be used for live DOM checking or formatted text filtering + */ + _oExt.ofnSearch = { }; + + /* + * Variable: afnSortData + * Purpose: Container for custom sorting data source functions + * Scope: jQuery.fn.dataTableExt + * Notes: Array (associative) of functions which is run prior to a column of this + * 'SortDataType' being sorted upon. + * Function input parameters: + * object:oSettings- DataTables settings object + * int:iColumn - Target column number + * Return value: Array of data which exactly matched the full data set size for the column to + * be sorted upon + */ + _oExt.afnSortData = [ ]; + + /* + * Variable: oStdClasses + * Purpose: Storage for the various classes that DataTables uses + * Scope: jQuery.fn.dataTableExt + */ + _oExt.oStdClasses = { + /* Two buttons buttons */ + "sPagePrevEnabled": "paginate_enabled_previous", + "sPagePrevDisabled": "paginate_disabled_previous", + "sPageNextEnabled": "paginate_enabled_next", + "sPageNextDisabled": "paginate_disabled_next", + "sPageJUINext": "", + "sPageJUIPrev": "", + + /* Full numbers paging buttons */ + "sPageButton": "paginate_button", + "sPageButtonActive": "paginate_active", + "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled", + "sPageFirst": "first", + "sPagePrevious": "previous", + "sPageNext": "next", + "sPageLast": "last", + + /* Striping classes */ + "sStripeOdd": "odd", + "sStripeEven": "even", + + /* Empty row */ + "sRowEmpty": "dataTables_empty", + + /* Features */ + "sWrapper": "dataTables_wrapper", + "sFilter": "dataTables_filter", + "sInfo": "dataTables_info", + "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ + "sLength": "dataTables_length", + "sProcessing": "dataTables_processing", + + /* Sorting */ + "sSortAsc": "sorting_asc", + "sSortDesc": "sorting_desc", + "sSortable": "sorting", /* Sortable in both directions */ + "sSortableAsc": "sorting_asc_disabled", + "sSortableDesc": "sorting_desc_disabled", + "sSortableNone": "sorting_disabled", + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ + "sSortJUIAsc": "", + "sSortJUIDesc": "", + "sSortJUI": "", + "sSortJUIAscAllowed": "", + "sSortJUIDescAllowed": "", + "sSortJUIWrapper": "", + "sSortIcon": "", + + /* Scrolling */ + "sScrollWrapper": "dataTables_scroll", + "sScrollHead": "dataTables_scrollHead", + "sScrollHeadInner": "dataTables_scrollHeadInner", + "sScrollBody": "dataTables_scrollBody", + "sScrollFoot": "dataTables_scrollFoot", + "sScrollFootInner": "dataTables_scrollFootInner", + + /* Misc */ + "sFooterTH": "" + }; + + /* + * Variable: oJUIClasses + * Purpose: Storage for the various classes that DataTables uses - jQuery UI suitable + * Scope: jQuery.fn.dataTableExt + */ + _oExt.oJUIClasses = { + /* Two buttons buttons */ + "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left", + "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled", + "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right", + "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled", + "sPageJUINext": "ui-icon ui-icon-circle-arrow-e", + "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w", + + /* Full numbers paging buttons */ + "sPageButton": "fg-button ui-button ui-state-default", + "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageFirst": "first ui-corner-tl ui-corner-bl", + "sPagePrevious": "previous", + "sPageNext": "next", + "sPageLast": "last ui-corner-tr ui-corner-br", + + /* Striping classes */ + "sStripeOdd": "odd", + "sStripeEven": "even", + + /* Empty row */ + "sRowEmpty": "dataTables_empty", + + /* Features */ + "sWrapper": "dataTables_wrapper", + "sFilter": "dataTables_filter", + "sInfo": "dataTables_info", + "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ + "ui-buttonset-multi paging_", /* Note that the type is postfixed */ + "sLength": "dataTables_length", + "sProcessing": "dataTables_processing", + + /* Sorting */ + "sSortAsc": "ui-state-default", + "sSortDesc": "ui-state-default", + "sSortable": "ui-state-default", + "sSortableAsc": "ui-state-default", + "sSortableDesc": "ui-state-default", + "sSortableNone": "ui-state-default", + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ + "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n", + "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s", + "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s", + "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n", + "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s", + "sSortJUIWrapper": "DataTables_sort_wrapper", + "sSortIcon": "DataTables_sort_icon", + + /* Scrolling */ + "sScrollWrapper": "dataTables_scroll", + "sScrollHead": "dataTables_scrollHead ui-state-default", + "sScrollHeadInner": "dataTables_scrollHeadInner", + "sScrollBody": "dataTables_scrollBody", + "sScrollFoot": "dataTables_scrollFoot ui-state-default", + "sScrollFootInner": "dataTables_scrollFootInner", + + /* Misc */ + "sFooterTH": "ui-state-default" + }; + + /* + * Variable: oPagination + * Purpose: Container for the various type of pagination that dataTables supports + * Scope: jQuery.fn.dataTableExt + */ + _oExt.oPagination = { + /* + * Variable: two_button + * Purpose: Standard two button (forward/back) pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "two_button": { + /* + * Function: oPagination.two_button.fnInit + * Purpose: Initialise dom elements required for pagination with forward/back buttons only + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var nPrevious, nNext, nPreviousInner, nNextInner; + + /* Store the next and previous elements in the oSettings object as they can be very + * usful for automation - particularly testing + */ + if ( !oSettings.bJUI ) + { + nPrevious = document.createElement( 'div' ); + nNext = document.createElement( 'div' ); + } + else + { + nPrevious = document.createElement( 'a' ); + nNext = document.createElement( 'a' ); + + nNextInner = document.createElement('span'); + nNextInner.className = oSettings.oClasses.sPageJUINext; + nNext.appendChild( nNextInner ); + + nPreviousInner = document.createElement('span'); + nPreviousInner.className = oSettings.oClasses.sPageJUIPrev; + nPrevious.appendChild( nPreviousInner ); + } + + nPrevious.className = oSettings.oClasses.sPagePrevDisabled; + nNext.className = oSettings.oClasses.sPageNextDisabled; + + nPrevious.title = oSettings.oLanguage.oPaginate.sPrevious; + nNext.title = oSettings.oLanguage.oPaginate.sNext; + + nPaging.appendChild( nPrevious ); + nPaging.appendChild( nNext ); + + $(nPrevious).bind( 'click.DT', function() { + if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) ) + { + /* Only draw when the page has actually changed */ + fnCallbackDraw( oSettings ); + } + } ); + + $(nNext).bind( 'click.DT', function() { + if ( oSettings.oApi._fnPageChange( oSettings, "next" ) ) + { + fnCallbackDraw( oSettings ); + } + } ); + + /* Take the brutal approach to cancelling text selection */ + $(nPrevious).bind( 'selectstart.DT', function () { return false; } ); + $(nNext).bind( 'selectstart.DT', function () { return false; } ); + + /* ID the first elements only */ + if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.p == "undefined" ) + { + nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' ); + nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' ); + nNext.setAttribute( 'id', oSettings.sTableId+'_next' ); + } + }, + + /* + * Function: oPagination.two_button.fnUpdate + * Purpose: Update the two button pagination at the end of the draw + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + /* Loop over each instance of the pager */ + var an = oSettings.aanFeatures.p; + for ( var i=0, iLen=an.length ; i= (iPages - iPageCountHalf)) + { + iStartButton = iPages - iPageCount + 1; + iEndButton = iPages; + } + else + { + iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1; + iEndButton = iStartButton + iPageCount - 1; + } + } + } + + /* Build the dynamic list */ + for ( i=iStartButton ; i<=iEndButton ; i++ ) + { + if ( iCurrentPage != i ) + { + sList += ''+i+''; + } + else + { + sList += ''+i+''; + } + } + + /* Loop over each instance of the pager */ + var an = oSettings.aanFeatures.p; + var anButtons, anStatic, nPaginateList; + var fnClick = function(e) { + /* Use the information in the element to jump to the required page */ + var iTarget = (this.innerHTML * 1) - 1; + oSettings._iDisplayStart = iTarget * oSettings._iDisplayLength; + fnCallbackDraw( oSettings ); + e.preventDefault(); + }; + var fnFalse = function () { return false; }; + + for ( i=0, iLen=an.length ; i y) ? 1 : 0)); + }, + + "string-desc": function ( a, b ) + { + if ( typeof a != 'string' ) { a = ''; } + if ( typeof b != 'string' ) { b = ''; } + var x = a.toLowerCase(); + var y = b.toLowerCase(); + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * html sorting (ignore html tags) + */ + "html-asc": function ( a, b ) + { + var x = a.replace( /<.*?>/g, "" ).toLowerCase(); + var y = b.replace( /<.*?>/g, "" ).toLowerCase(); + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "html-desc": function ( a, b ) + { + var x = a.replace( /<.*?>/g, "" ).toLowerCase(); + var y = b.replace( /<.*?>/g, "" ).toLowerCase(); + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * date sorting + */ + "date-asc": function ( a, b ) + { + var x = Date.parse( a ); + var y = Date.parse( b ); + + if ( isNaN(x) || x==="" ) + { + x = Date.parse( "01/01/1970 00:00:00" ); + } + if ( isNaN(y) || y==="" ) + { + y = Date.parse( "01/01/1970 00:00:00" ); + } + + return x - y; + }, + + "date-desc": function ( a, b ) + { + var x = Date.parse( a ); + var y = Date.parse( b ); + + if ( isNaN(x) || x==="" ) + { + x = Date.parse( "01/01/1970 00:00:00" ); + } + if ( isNaN(y) || y==="" ) + { + y = Date.parse( "01/01/1970 00:00:00" ); + } + + return y - x; + }, + + + /* + * numerical sorting + */ + "numeric-asc": function ( a, b ) + { + var x = (a=="-" || a==="") ? 0 : a*1; + var y = (b=="-" || b==="") ? 0 : b*1; + return x - y; + }, + + "numeric-desc": function ( a, b ) + { + var x = (a=="-" || a==="") ? 0 : a*1; + var y = (b=="-" || b==="") ? 0 : b*1; + return y - x; + } + }; + + + /* + * Variable: aTypes + * Purpose: Container for the various type of type detection that dataTables supports + * Scope: jQuery.fn.dataTableExt + * Notes: The functions in this array are expected to parse a string to see if it is a data + * type that it recognises. If so then the function should return the name of the type (a + * corresponding sort function should be defined!), if the type is not recognised then the + * function should return null such that the parser and move on to check the next type. + * Note that ordering is important in this array - the functions are processed linearly, + * starting at index 0. + * Note that the input for these functions is always a string! It cannot be any other data + * type + */ + _oExt.aTypes = [ + /* + * Function: - + * Purpose: Check to see if a string is numeric + * Returns: string:'numeric' or null + * Inputs: mixed:sText - string to check + */ + function ( sData ) + { + /* Allow zero length strings as a number */ + if ( typeof sData == 'number' ) + { + return 'numeric'; + } + else if ( typeof sData != 'string' ) + { + return null; + } + + var sValidFirstChars = "0123456789-"; + var sValidChars = "0123456789."; + var Char; + var bDecimal = false; + + /* Check for a valid first char (no period and allow negatives) */ + Char = sData.charAt(0); + if (sValidFirstChars.indexOf(Char) == -1) + { + return null; + } + + /* Check all the other characters are valid */ + for ( var i=1 ; i') != -1 ) + { + return 'html'; + } + return null; + } + ]; + + /* + * Function: fnVersionCheck + * Purpose: Check a version string against this version of DataTables. Useful for plug-ins + * Returns: bool:true -this version of DataTables is greater or equal to the required version + * false -this version of DataTales is not suitable + * Inputs: string:sVersion - the version to check against. May be in the following formats: + * "a", "a.b" or "a.b.c" + * Notes: This function will only check the first three parts of a version string. It is + * assumed that beta and dev versions will meet the requirements. This might change in future + */ + _oExt.fnVersionCheck = function( sVersion ) + { + /* This is cheap, but very effective */ + var fnZPad = function (Zpad, count) + { + while(Zpad.length < count) { + Zpad += '0'; + } + return Zpad; + }; + var aThis = _oExt.sVersion.split('.'); + var aThat = sVersion.split('.'); + var sThis = '', sThat = ''; + + for ( var i=0, iLen=aThat.length ; i= parseInt(sThat, 10); + }; + + /* + * Variable: _oExternConfig + * Purpose: Store information for DataTables to access globally about other instances + * Scope: jQuery.fn.dataTableExt + */ + _oExt._oExternConfig = { + /* int:iNextUnique - next unique number for an instance */ + "iNextUnique": 0 + }; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Section - DataTables prototype + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /* + * Function: dataTable + * Purpose: DataTables information + * Returns: - + * Inputs: object:oInit - initialisation options for the table + */ + $.fn.dataTable = function( oInit ) + { + /* + * Function: classSettings + * Purpose: Settings container function for all 'class' properties which are required + * by dataTables + * Returns: - + * Inputs: - + */ + function classSettings () + { + this.fnRecordsTotal = function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsTotal, 10); + } else { + return this.aiDisplayMaster.length; + } + }; + + this.fnRecordsDisplay = function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsDisplay, 10); + } else { + return this.aiDisplay.length; + } + }; + + this.fnDisplayEnd = function () + { + if ( this.oFeatures.bServerSide ) { + if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) { + return this._iDisplayStart+this.aiDisplay.length; + } else { + return Math.min( this._iDisplayStart+this._iDisplayLength, + this._iRecordsDisplay ); + } + } else { + return this._iDisplayEnd; + } + }; + + /* + * Variable: oInstance + * Purpose: The DataTables object for this table + * Scope: jQuery.dataTable.classSettings + */ + this.oInstance = null; + + /* + * Variable: sInstance + * Purpose: Unique idendifier for each instance of the DataTables object + * Scope: jQuery.dataTable.classSettings + */ + this.sInstance = null; + + /* + * Variable: oFeatures + * Purpose: Indicate the enablement of key dataTable features + * Scope: jQuery.dataTable.classSettings + */ + this.oFeatures = { + "bPaginate": true, + "bLengthChange": true, + "bFilter": true, + "bSort": true, + "bInfo": true, + "bAutoWidth": true, + "bProcessing": false, + "bSortClasses": true, + "bStateSave": false, + "bServerSide": false, + "bDeferRender": false + }; + + /* + * Variable: oScroll + * Purpose: Container for scrolling options + * Scope: jQuery.dataTable.classSettings + */ + this.oScroll = { + "sX": "", + "sXInner": "", + "sY": "", + "bCollapse": false, + "bInfinite": false, + "iLoadGap": 100, + "iBarWidth": 0, + "bAutoCss": true + }; + + /* + * Variable: aanFeatures + * Purpose: Array referencing the nodes which are used for the features + * Scope: jQuery.dataTable.classSettings + * Notes: The parameters of this object match what is allowed by sDom - i.e. + * 'l' - Length changing + * 'f' - Filtering input + * 't' - The table! + * 'i' - Information + * 'p' - Pagination + * 'r' - pRocessing + */ + this.aanFeatures = []; + + /* + * Variable: oLanguage + * Purpose: Store the language strings used by dataTables + * Scope: jQuery.dataTable.classSettings + * Notes: The words in the format _VAR_ are variables which are dynamically replaced + * by javascript + */ + this.oLanguage = { + "sProcessing": "Processing...", + "sLengthMenu": "Show _MENU_ entries", + "sZeroRecords": "No matching records found", + "sEmptyTable": "No data available in table", + "sLoadingRecords": "Loading...", + "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", + "sInfoEmpty": "Showing 0 to 0 of 0 entries", + "sInfoFiltered": "(filtered from _MAX_ total entries)", + "sInfoPostFix": "", + "sInfoThousands": ",", + "sSearch": "Search:", + "sUrl": "", + "oPaginate": { + "sFirst": "First", + "sPrevious": "Previous", + "sNext": "Next", + "sLast": "Last" + }, + "fnInfoCallback": null + }; + + /* + * Variable: aoData + * Purpose: Store data information + * Scope: jQuery.dataTable.classSettings + * Notes: This is an array of objects with the following parameters: + * int: _iId - internal id for tracking + * array: _aData - internal data - used for sorting / filtering etc + * node: nTr - display node + * array node: _anHidden - hidden TD nodes + * string: _sRowStripe + */ + this.aoData = []; + + /* + * Variable: aiDisplay + * Purpose: Array of indexes which are in the current display (after filtering etc) + * Scope: jQuery.dataTable.classSettings + */ + this.aiDisplay = []; + + /* + * Variable: aiDisplayMaster + * Purpose: Array of indexes for display - no filtering + * Scope: jQuery.dataTable.classSettings + */ + this.aiDisplayMaster = []; + + /* + * Variable: aoColumns + * Purpose: Store information about each column that is in use + * Scope: jQuery.dataTable.classSettings + */ + this.aoColumns = []; + + /* + * Variable: aoHeader + * Purpose: Store information about the table's header + * Scope: jQuery.dataTable.classSettings + */ + this.aoHeader = []; + + /* + * Variable: aoFooter + * Purpose: Store information about the table's footer + * Scope: jQuery.dataTable.classSettings + */ + this.aoFooter = []; + + /* + * Variable: iNextId + * Purpose: Store the next unique id to be used for a new row + * Scope: jQuery.dataTable.classSettings + */ + this.iNextId = 0; + + /* + * Variable: asDataSearch + * Purpose: Search data array for regular expression searching + * Scope: jQuery.dataTable.classSettings + */ + this.asDataSearch = []; + + /* + * Variable: oPreviousSearch + * Purpose: Store the previous search incase we want to force a re-search + * or compare the old search to a new one + * Scope: jQuery.dataTable.classSettings + */ + this.oPreviousSearch = { + "sSearch": "", + "bRegex": false, + "bSmart": true + }; + + /* + * Variable: aoPreSearchCols + * Purpose: Store the previous search for each column + * Scope: jQuery.dataTable.classSettings + */ + this.aoPreSearchCols = []; + + /* + * Variable: aaSorting + * Purpose: Sorting information + * Scope: jQuery.dataTable.classSettings + * Notes: Index 0 - column number + * Index 1 - current sorting direction + * Index 2 - index of asSorting for this column + */ + this.aaSorting = [ [0, 'asc', 0] ]; + + /* + * Variable: aaSortingFixed + * Purpose: Sorting information that is always applied + * Scope: jQuery.dataTable.classSettings + */ + this.aaSortingFixed = null; + + /* + * Variable: asStripeClasses + * Purpose: Classes to use for the striping of a table + * Scope: jQuery.dataTable.classSettings + */ + this.asStripeClasses = []; + + /* + * Variable: asDestroyStripes + * Purpose: If restoring a table - we should restore its striping classes as well + * Scope: jQuery.dataTable.classSettings + */ + this.asDestroyStripes = []; + + /* + * Variable: sDestroyWidth + * Purpose: If restoring a table - we should restore its width + * Scope: jQuery.dataTable.classSettings + */ + this.sDestroyWidth = 0; + + /* + * Variable: fnRowCallback + * Purpose: Call this function every time a row is inserted (draw) + * Scope: jQuery.dataTable.classSettings + */ + this.fnRowCallback = null; + + /* + * Variable: fnHeaderCallback + * Purpose: Callback function for the header on each draw + * Scope: jQuery.dataTable.classSettings + */ + this.fnHeaderCallback = null; + + /* + * Variable: fnFooterCallback + * Purpose: Callback function for the footer on each draw + * Scope: jQuery.dataTable.classSettings + */ + this.fnFooterCallback = null; + + /* + * Variable: aoDrawCallback + * Purpose: Array of callback functions for draw callback functions + * Scope: jQuery.dataTable.classSettings + * Notes: Each array element is an object with the following parameters: + * function:fn - function to call + * string:sName - name callback (feature). useful for arranging array + */ + this.aoDrawCallback = []; + + /* + * Variable: fnPreDrawCallback + * Purpose: Callback function for just before the table is redrawn. A return of false + * will be used to cancel the draw. + * Scope: jQuery.dataTable.classSettings + */ + this.fnPreDrawCallback = null; + + /* + * Variable: fnInitComplete + * Purpose: Callback function for when the table has been initialised + * Scope: jQuery.dataTable.classSettings + */ + this.fnInitComplete = null; + + /* + * Variable: sTableId + * Purpose: Cache the table ID for quick access + * Scope: jQuery.dataTable.classSettings + */ + this.sTableId = ""; + + /* + * Variable: nTable + * Purpose: Cache the table node for quick access + * Scope: jQuery.dataTable.classSettings + */ + this.nTable = null; + + /* + * Variable: nTHead + * Purpose: Permanent ref to the thead element + * Scope: jQuery.dataTable.classSettings + */ + this.nTHead = null; + + /* + * Variable: nTFoot + * Purpose: Permanent ref to the tfoot element - if it exists + * Scope: jQuery.dataTable.classSettings + */ + this.nTFoot = null; + + /* + * Variable: nTBody + * Purpose: Permanent ref to the tbody element + * Scope: jQuery.dataTable.classSettings + */ + this.nTBody = null; + + /* + * Variable: nTableWrapper + * Purpose: Cache the wrapper node (contains all DataTables controlled elements) + * Scope: jQuery.dataTable.classSettings + */ + this.nTableWrapper = null; + + /* + * Variable: bDeferLoading + * Purpose: Indicate if when using server-side processing the loading of data + * should be deferred until the second draw + * Scope: jQuery.dataTable.classSettings + */ + this.bDeferLoading = false; + + /* + * Variable: bInitialised + * Purpose: Indicate if all required information has been read in + * Scope: jQuery.dataTable.classSettings + */ + this.bInitialised = false; + + /* + * Variable: aoOpenRows + * Purpose: Information about open rows + * Scope: jQuery.dataTable.classSettings + * Notes: Has the parameters 'nTr' and 'nParent' + */ + this.aoOpenRows = []; + + /* + * Variable: sDom + * Purpose: Dictate the positioning that the created elements will take + * Scope: jQuery.dataTable.classSettings + * Notes: + * The following options are allowed: + * 'l' - Length changing + * 'f' - Filtering input + * 't' - The table! + * 'i' - Information + * 'p' - Pagination + * 'r' - pRocessing + * The following constants are allowed: + * 'H' - jQueryUI theme "header" classes + * 'F' - jQueryUI theme "footer" classes + * The following syntax is expected: + * '<' and '>' - div elements + * '<"class" and '>' - div with a class + * Examples: + * '<"wrapper"flipt>', 'ip>' + */ + this.sDom = 'lfrtip'; + + /* + * Variable: sPaginationType + * Purpose: Note which type of sorting should be used + * Scope: jQuery.dataTable.classSettings + */ + this.sPaginationType = "two_button"; + + /* + * Variable: iCookieDuration + * Purpose: The cookie duration (for bStateSave) in seconds - default 2 hours + * Scope: jQuery.dataTable.classSettings + */ + this.iCookieDuration = 60 * 60 * 2; + + /* + * Variable: sCookiePrefix + * Purpose: The cookie name prefix + * Scope: jQuery.dataTable.classSettings + */ + this.sCookiePrefix = "SpryMedia_DataTables_"; + + /* + * Variable: fnCookieCallback + * Purpose: Callback function for cookie creation + * Scope: jQuery.dataTable.classSettings + */ + this.fnCookieCallback = null; + + /* + * Variable: aoStateSave + * Purpose: Array of callback functions for state saving + * Scope: jQuery.dataTable.classSettings + * Notes: Each array element is an object with the following parameters: + * function:fn - function to call. Takes two parameters, oSettings and the JSON string to + * save that has been thus far created. Returns a JSON string to be inserted into a + * json object (i.e. '"param": [ 0, 1, 2]') + * string:sName - name of callback + */ + this.aoStateSave = []; + + /* + * Variable: aoStateLoad + * Purpose: Array of callback functions for state loading + * Scope: jQuery.dataTable.classSettings + * Notes: Each array element is an object with the following parameters: + * function:fn - function to call. Takes two parameters, oSettings and the object stored. + * May return false to cancel state loading. + * string:sName - name of callback + */ + this.aoStateLoad = []; + + /* + * Variable: oLoadedState + * Purpose: State that was loaded from the cookie. Useful for back reference + * Scope: jQuery.dataTable.classSettings + */ + this.oLoadedState = null; + + /* + * Variable: sAjaxSource + * Purpose: Source url for AJAX data for the table + * Scope: jQuery.dataTable.classSettings + */ + this.sAjaxSource = null; + + /* + * Variable: sAjaxDataProp + * Purpose: Property from a given object from which to read the table data from. This can + * be an empty string (when not server-side processing), in which case it is + * assumed an an array is given directly. + * Scope: jQuery.dataTable.classSettings + */ + this.sAjaxDataProp = 'aaData'; + + /* + * Variable: bAjaxDataGet + * Purpose: Note if draw should be blocked while getting data + * Scope: jQuery.dataTable.classSettings + */ + this.bAjaxDataGet = true; + + /* + * Variable: jqXHR + * Purpose: The last jQuery XHR object that was used for server-side data gathering. + * This can be used for working with the XHR information in one of the callbacks + * Scope: jQuery.dataTable.classSettings + */ + this.jqXHR = null; + + /* + * Variable: fnServerData + * Purpose: Function to get the server-side data - can be overruled by the developer + * Scope: jQuery.dataTable.classSettings + */ + this.fnServerData = function ( url, data, callback, settings ) { + settings.jqXHR = $.ajax( { + "url": url, + "data": data, + "success": function (json) { + $(settings.oInstance).trigger('xhr', settings); + callback( json ); + }, + "dataType": "json", + "cache": false, + "error": function (xhr, error, thrown) { + if ( error == "parsererror" ) { + alert( "DataTables warning: JSON data from server could not be parsed. "+ + "This is caused by a JSON formatting error." ); + } + } + } ); + }; + + /* + * Variable: aoServerParams + * Purpose: Functions which are called prior to sending an Ajax request so extra parameters + * can easily be sent to the server + * Scope: jQuery.dataTable.classSettings + * Notes: Each array element is an object with the following parameters: + * function:fn - function to call + * string:sName - name callback - useful for knowing where it came from (plugin etc) + */ + this.aoServerParams = []; + + /* + * Variable: fnFormatNumber + * Purpose: Format numbers for display + * Scope: jQuery.dataTable.classSettings + */ + this.fnFormatNumber = function ( iIn ) + { + if ( iIn < 1000 ) + { + /* A small optimisation for what is likely to be the vast majority of use cases */ + return iIn; + } + else + { + var s=(iIn+""), a=s.split(""), out="", iLen=s.length; + + for ( var i=0 ; i