jquery-tablesorter 1.12.7 → 1.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ /*! Duration parser
2
+ */
3
+ /*jshint jquery:true, unused:false */
4
+ ;(function($){
5
+ "use strict";
6
+
7
+ // If any number > 9999, then set table.config.durationLength = 5
8
+ // The below regex matches this duration example: 1y 23d 12h 44m 9s
9
+ $.tablesorter.addParser({
10
+ id: "duration",
11
+ is: function() {
12
+ return false;
13
+ },
14
+ format: function(s, table) {
15
+ var i, time,
16
+ c = table.config,
17
+ t = '',
18
+ duration = '',
19
+ len = c.durationLength || 4,
20
+ str = new Array(len + 1).join('0'),
21
+ labels = (c.durationLabels || '(?:years|year|y),(?:days|day|d),(?:hours|hour|h),(?:minutes|minute|min|m),(?:seconds|second|sec|s)').split(/\s*,\s*/),
22
+ llen = labels.length;
23
+ // build regex
24
+ if (!c.durationRegex) {
25
+ for (i = 0; i < llen; i++) {
26
+ t += '(?:(\\d+)\\s*' + labels[i] + '\\s*)?';
27
+ }
28
+ c.durationRegex = new RegExp(t, 'i');
29
+ }
30
+ // remove commas from value
31
+ time = ( c.usNumberFormat ? s.replace(/,/g, '') : s.replace( /(\d)(?:\.|\s*)(\d)/g, '$1$2') ).match(c.durationRegex);
32
+ for (i = 1; i < llen + 1; i++) {
33
+ duration += ( str + ( time[i] || 0 ) ).slice(-len);
34
+ }
35
+ return duration;
36
+ },
37
+ type: "text"
38
+ });
39
+
40
+ })(jQuery);
@@ -1,14 +1,16 @@
1
- /*! Title parser
1
+ /*! Title parser - updated 9/15/2014 (v2.17.8)
2
2
  * This parser will remove "The", "A" and "An" from the beginning of a book
3
3
  * or movie title, so it sorts by the second word or number
4
4
  * Demo: http://jsfiddle.net/Mottie/abkNM/5/
5
5
  */
6
- /*global jQuery: false */
6
+ /*jshint browser: true, jquery:true, unused:false */
7
7
  ;(function($){
8
8
  "use strict";
9
9
 
10
+ var ts = $.tablesorter;
11
+
10
12
  // basic list from http://en.wikipedia.org/wiki/Article_%28grammar%29
11
- $.tablesorter.ignoreArticles = {
13
+ ts.ignoreArticles = {
12
14
  "en" : "the, a, an",
13
15
  "de" : "der, die, das, des, dem, den, ein, eine, einer, eines, einem, einen",
14
16
  "nl" : "de, het, de, een",
@@ -24,22 +26,34 @@
24
26
  // and then set the language id 'xx' in the headers option
25
27
  // ignoreArticles : 'xx'
26
28
 
27
- $.tablesorter.addParser({
29
+ ts.addParser({
28
30
  id: 'ignoreArticles',
29
31
  is: function() {
30
32
  return false;
31
33
  },
32
34
  format: function(s, table, cell, cellIndex) {
33
- var c = table.config, art, lang;
35
+ var art, ignore, lang,
36
+ c = table.config,
37
+ str = s || '';
34
38
  if ( !(c.headers && c.headers[cellIndex] && c.headers[cellIndex].ignoreArticlesRegex) ) {
35
- // initialize - save regex in c.headers[cellIndex].ignoreArticles
39
+ // initialize - save regex in c.headers[cellIndex].ignoreArticlesRegex
36
40
  if (!c.headers) { c.headers = {}; }
37
41
  if (!c.headers[cellIndex]) { c.headers[cellIndex] = {}; }
38
- lang = $.tablesorter.getData(c.$headers.eq(cellIndex), c.headers[cellIndex], 'ignoreArticles');
39
- art = ($.tablesorter.ignoreArticles[lang] || "the, a, an" ) + "";
42
+ lang = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticles' );
43
+ art = (ts.ignoreArticles[lang] || "the, a, an" ) + "";
40
44
  c.headers[cellIndex].ignoreArticlesRegex = new RegExp('^(' + $.trim( art.split(/\s*\,\s*/).join('\\s|') + "\\s" ).replace("_\\s","") + ')', 'i');
45
+ // exception regex stored in c.headers[cellIndex].ignoreArticlesRegex2
46
+ ignore = ts.getData( c.$headers.eq(cellIndex), ts.getColumnData( table, c.headers, cellIndex ), 'ignoreArticlesExcept' );
47
+ c.headers[cellIndex].ignoreArticlesRegex2 = ignore !== '' ? new RegExp('^(' + ignore.replace(/\s/g, "\\s") + ')', 'i') : '';
48
+ }
49
+ art = c.headers[cellIndex].ignoreArticlesRegex;
50
+ if (art.test(str)) {
51
+ ignore = c.headers[cellIndex].ignoreArticlesRegex2;
52
+ if ( !(ignore && ignore.test(str)) ) {
53
+ return str.replace(art, '');
54
+ }
41
55
  }
42
- return (s || '').replace(c.headers[cellIndex].ignoreArticlesRegex, '');
56
+ return str;
43
57
  },
44
58
  type: 'text'
45
59
  });
@@ -1,5 +1,5 @@
1
1
  /*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
2
- * Updated 8/1/2014 (v2.17.6)
2
+ * Updated 9/15/2014 (v2.17.8)
3
3
  * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
4
4
  */
5
5
  /*jshint browser: true, jquery:true, unused:false */
@@ -101,16 +101,20 @@
101
101
  // this flag prevents the updateCell event from being spammed
102
102
  // it happens when you modify input text and hit enter
103
103
  var focused = false,
104
- restoreValue = function(){
104
+ restoreValue = function(isTbody){
105
105
  // focused = false; // uncomment this line to prevent auto-accepting changes
106
106
  // make sure we restore original values
107
- $(':focus').blur();
107
+ // isTbody is needed to prevent the select from closing in IE
108
+ // see https://connect.microsoft.com/IE/feedbackdetail/view/962618/
109
+ if (isTbody) {
110
+ $(':focus').blur();
111
+ }
108
112
  return;
109
113
  };
110
114
  // bind to .tablesorter (default class name)
111
115
  $(this).children('tbody')
112
- .on('mouseleave', function(){
113
- restoreValue();
116
+ .on('mouseleave', function(e){
117
+ restoreValue(e.target.tagName === 'TBODY');
114
118
  })
115
119
  .on('focus', 'select, input, textarea', function(){
116
120
  focused = true;
@@ -1,4 +1,4 @@
1
- /*! tablesorter Editable Content widget - updated 8/1/2014 (core v2.17.6)
1
+ /*! tablesorter Editable Content widget - updated 9/15/2014 (core v2.17.8)
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
@@ -14,14 +14,42 @@
14
14
  editable_enterToAccept : true,
15
15
  editable_autoAccept : true,
16
16
  editable_autoResort : false,
17
- editable_validate : null, // function(text, originalText){ return text; }
17
+ editable_wrapContent : '<div>', // wrap the cell content... makes this widget work in IE, and with autocomplete
18
+ editable_trimContent : true, // trim content inside of contenteditable (remove tabs & carriage returns)
19
+ editable_validate : null, // function(text, originalText){ return text; }
20
+ editable_focused : null, // function(text, columnIndex, $element) {}
21
+ editable_blur : null, // function(text, columnIndex, $element) { }
22
+ editable_selectAll : false, // true/false or function(text, columnIndex, $element) { return true; }
18
23
  editable_noEdit : 'no-edit',
19
24
  editable_editComplete : 'editComplete'
20
25
  },
21
26
  init: function(table, thisWidget, c, wo){
22
27
  if ( !wo.editable_columns.length ) { return; }
23
28
  var indx, tmp, $t,
24
- cols = [];
29
+ cols = [],
30
+ editComplete = function($cell, refocus){
31
+ $cell
32
+ .removeClass('tseditable-last-edited-cell')
33
+ .trigger( wo.editable_editComplete, [c] );
34
+ // restore focus last cell after updating
35
+ if (refocus) {
36
+ setTimeout(function(){
37
+ $cell.focus();
38
+ }, 50);
39
+ }
40
+ },
41
+ selectAll = function(cell){
42
+ setTimeout(function(){
43
+ // select all text in contenteditable
44
+ // see http://stackoverflow.com/a/6150060/145346
45
+ var range = document.createRange();
46
+ range.selectNodeContents(cell);
47
+ var sel = window.getSelection();
48
+ sel.removeAllRanges();
49
+ sel.addRange(range);
50
+ }, 100);
51
+ };
52
+
25
53
  if ( $.type(wo.editable_columns) === "string" && wo.editable_columns.indexOf('-') >= 0 ) {
26
54
  // editable_columns can contain a range string (i.e. "2-4" )
27
55
  tmp = wo.editable_columns.split('-');
@@ -38,25 +66,51 @@
38
66
  }
39
67
  });
40
68
  }
69
+ tmp = $('<div>').wrapInner(wo.editable_wrapContent).children().length || $.isFunction(wo.editable_wrapContent);
41
70
  // IE does not allow making TR/TH/TD cells directly editable (issue #404)
42
71
  // so add a div or span inside ( it's faster than using wrapInner() )
43
72
  c.$tbodies.find( cols.join(',') ).not( '.' + wo.editable_noEdit ).each(function(){
44
73
  // test for children, if they exist, then make the children editable
45
74
  $t = $(this);
46
- ( $t.children().length ? $t.children() : $t ).prop( 'contenteditable', true );
75
+
76
+ if (tmp && $t.children().length === 0) {
77
+ $t.wrapInner( wo.editable_wrapContent );
78
+ }
79
+ if ($t.children().length) {
80
+ // make all children content editable
81
+ $t.children().not('.' + wo.editable_noEdit).each(function(){
82
+ var $this = $(this);
83
+ if (wo.editable_trimContent) {
84
+ $this.text(function(i, txt){
85
+ return $.trim(txt);
86
+ });
87
+ }
88
+ $this.prop( 'contenteditable', true );
89
+ });
90
+ } else {
91
+ if (wo.editable_trimContent) {
92
+ $t.text(function(i, txt){
93
+ return $.trim(txt);
94
+ });
95
+ }
96
+ $t.prop( 'contenteditable', true );
97
+ }
47
98
  });
48
99
  c.$tbodies
49
100
  .on('mouseleave.tseditable', function(){
50
101
  if ( c.$table.data('contentFocused') ) {
51
102
  // change to "true" instead of element to allow focusout to process
52
103
  c.$table.data( 'contentFocused', true );
53
- $(':focus').trigger('blur');
104
+ $(':focus').trigger('focusout');
54
105
  }
55
106
  })
56
107
  .on('focus.tseditable', '[contenteditable]', function(e){
108
+ clearTimeout( $(this).data('timer') );
57
109
  c.$table.data( 'contentFocused', e.target );
58
110
  var $this = $(this),
59
- v = $this.html();
111
+ selAll = wo.editable_selectAll,
112
+ column = $this.closest('td').index(),
113
+ txt = $.trim( $this.text() );
60
114
  if (wo.editable_enterToAccept) {
61
115
  // prevent enter from adding into the content
62
116
  $this.on('keydown.tseditable', function(e){
@@ -65,46 +119,79 @@
65
119
  }
66
120
  });
67
121
  }
68
- $this.data({ before : v, original: v });
122
+ $this.data({ before : txt, original: txt });
123
+
124
+ if (typeof wo.editable_focused === 'function') {
125
+ wo.editable_focused( txt, column, $this );
126
+ }
127
+
128
+ if (selAll) {
129
+ if (typeof selAll === 'function') {
130
+ if ( selAll( txt, column, $this ) ) {
131
+ selectAll($this[0]);
132
+ }
133
+ } else {
134
+ selectAll($this[0]);
135
+ }
136
+ }
69
137
  })
70
138
  .on('blur focusout keydown '.split(' ').join('.tseditable '), '[contenteditable]', function(e){
71
139
  if ( !c.$table.data('contentFocused') ) { return; }
72
- var t,
140
+ var t, validate,
73
141
  valid = false,
74
- $this = $(e.target);
142
+ $this = $(e.target),
143
+ txt = $.trim( $this.text() ),
144
+ column = $this.closest('td').index();
75
145
  if ( e.which === 27 ) {
76
146
  // user cancelled
77
- $this.html( $this.data('original') ).trigger('blur.tseditable');
147
+ $this.html( $.trim( $this.data('original') ) ).trigger('blur.tseditable');
78
148
  c.$table.data( 'contentFocused', false );
79
149
  return false;
80
150
  }
151
+ // accept on enter (if set), alt-enter (always) or if autoAccept is set and element is blurred or unfocused
81
152
  t = e.which === 13 && ( wo.editable_enterToAccept || e.altKey ) || wo.editable_autoAccept && e.type !== 'keydown';
82
153
  // change if new or user hits enter (if option set)
83
- if ( t && $this.data('before') !== $this.html() ) {
84
- valid = $.isFunction(wo.editable_validate) ? wo.editable_validate( $this.html(), $this.data('original') ) : $this.html();
154
+ if ( t && $this.data('before') !== txt ) {
155
+
156
+ validate = wo.editable_validate;
157
+ valid = txt;
158
+
159
+ if (typeof(validate) === "function") {
160
+ valid = validate( txt, $this.data('original'), column, $this );
161
+ } else if (typeof (validate = $.tablesorter.getColumnData( table, validate, column )) === 'function') {
162
+ valid = validate( txt, $this.data('original'), column, $this );
163
+ }
164
+
85
165
  if ( t && valid !== false ) {
166
+ c.$table.find('.tseditable-last-edited-cell').removeClass('tseditable-last-edited-cell');
86
167
  $this
87
- .html( valid )
168
+ .addClass('tseditable-last-edited-cell')
169
+ .html( $.trim( valid ) )
88
170
  .data('before', valid)
171
+ .data('original', valid)
89
172
  .trigger('change');
90
- c.$table.trigger('updateCell', [ $this.closest('td'), wo.editable_autoResort, function(table){
91
- $this.trigger( wo.editable_editComplete, [c] );
92
- $this.data( 'original', $this.html() );
93
- if ( wo.editable_autoResort && c.sortList.length ) {
94
- c.$table.trigger('applyWidgets');
173
+ c.$table.trigger('updateCell', [ $this.closest('td'), false, function(){
174
+ if (wo.editable_autoResort) {
175
+ setTimeout(function(){
176
+ c.$table.trigger("sorton", [ c.sortList, function(){
177
+ editComplete(c.$table.find('.tseditable-last-edited-cell'), true);
178
+ }, true ]);
179
+ }, 10);
180
+ } else {
181
+ editComplete(c.$table.find('.tseditable-last-edited-cell'));
95
182
  }
96
- // restore focus last cell after updating
97
- setTimeout(function(){
98
- var t = c.$table.data('contentFocused');
99
- if ( t instanceof HTMLElement ) { t.focus(); }
100
- }, 50);
101
183
  } ]);
102
184
  return false;
103
185
  }
104
- }
105
- if ( !valid && e.type !== 'keydown' ) {
186
+ } else if ( !valid && e.type !== 'keydown' ) {
187
+ clearTimeout( $this.data('timer') );
188
+ $this.data('timer', setTimeout(function(){
189
+ if ($.isFunction(wo.editable_blur)) {
190
+ wo.editable_blur( $.trim( $this.text() ), column, $this );
191
+ }
192
+ }, 100));
106
193
  // restore original content on blur
107
- $this.html( $this.data('original') );
194
+ $this.html( $.trim( $this.data('original') ) );
108
195
  }
109
196
  });
110
197
  }
@@ -1,4 +1,4 @@
1
- /* Pager widget for TableSorter 8/1/2014 (v2.17.6) */
1
+ /* Pager widget for TableSorter 9/15/2014 (v2.17.8) */
2
2
  /*jshint browser:true, jquery:true, unused:false */
3
3
  ;(function($){
4
4
  "use strict";
@@ -215,7 +215,7 @@ tsp = ts.pager = {
215
215
  s = wo.pager_selectors;
216
216
 
217
217
  c.$table
218
- .unbind('filterStart filterEnd sortEnd disable enable destroy update updateRows updateAll addRows pageSize '.split(' ').join('.pager '))
218
+ .unbind('filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize '.split(' ').join('.pager '))
219
219
  .bind('filterStart.pager', function(e, filters) {
220
220
  p.currentFilters = filters;
221
221
  // don't change page is filters are the same (pager updating, etc)
@@ -232,7 +232,9 @@ tsp = ts.pager = {
232
232
  }
233
233
  // update page display first, so we update p.filteredPages
234
234
  tsp.updatePageDisplay(table, c, false);
235
- tsp.moveToPage(table, p, false);
235
+ // tsp.moveToPage(table, p, false); <-- called when applyWidgets is triggered
236
+ c.pager.last.page = -1;
237
+ c.$table.trigger('applyWidgets');
236
238
  tsp.fixHeight(table, c);
237
239
  }
238
240
  })
@@ -248,12 +250,18 @@ tsp = ts.pager = {
248
250
  e.stopPropagation();
249
251
  tsp.destroyPager(table, c);
250
252
  })
251
- .on('update updateRows updateAll addRows '.split(' ').join('.pager '), function(e){
253
+ .on('updateComplete.pager', function(e, table, triggered){
252
254
  e.stopPropagation();
255
+ // table can be unintentionally undefined in tablesorter v2.17.7 and earlier
256
+ if (!table || triggered) { return; }
253
257
  tsp.fixHeight(table, c);
254
- var $rows = c.$tbodies.eq(0).children('tr');
258
+ var $rows = c.$tbodies.eq(0).children('tr').not(c.selectorRemove);
255
259
  p.totalRows = $rows.length - ( c.widgetOptions.pager_countChildRows ? 0 : $rows.filter('.' + c.cssChildRow).length );
256
260
  p.totalPages = Math.ceil( p.totalRows / p.size );
261
+ if ($rows.length && c.rowsCopy && c.rowsCopy.length === 0) {
262
+ // make a copy of all table rows once the cache has been built
263
+ tsp.updateCache(table);
264
+ }
257
265
  tsp.updatePageDisplay(table, c);
258
266
  tsp.hideRows(table, c);
259
267
  // make sure widgets are applied - fixes #450
@@ -400,7 +408,8 @@ tsp = ts.pager = {
400
408
  for ( i = 1; i <= pg; i++ ) {
401
409
  t += '<option>' + i + '</option>';
402
410
  }
403
- p.$goto.html(t).val( p.page + 1 );
411
+ p.$goto[0].innerHTML = t;
412
+ p.$goto[0].value = p.page + 1;
404
413
  }
405
414
  // rebind startRow/page inputs
406
415
  $out.find('.ts-startRow, .ts-page').unbind('change').bind('change', function(){
@@ -740,9 +749,8 @@ tsp = ts.pager = {
740
749
 
741
750
  wo.pager_startPage = p.page;
742
751
  wo.pager_size = p.size;
743
- c.$table.trigger('applyWidgets');
744
752
  if (table.isUpdating) {
745
- c.$table.trigger('updateComplete');
753
+ c.$table.trigger('updateComplete', [ table, true ]);
746
754
  }
747
755
 
748
756
  },
@@ -764,6 +772,7 @@ tsp = ts.pager = {
764
772
  .removeAttr('aria-describedby')
765
773
  .find('tr.pagerSavedHeightSpacer').remove();
766
774
  tsp.renderTable(table, c.rowsCopy);
775
+ c.$table.trigger('applyWidgets');
767
776
  if (c.debug) {
768
777
  ts.log('pager disabled');
769
778
  }
@@ -834,9 +843,11 @@ tsp = ts.pager = {
834
843
  }
835
844
  $.data(table, 'pagerLastPage', p.page);
836
845
  if (p.initialized && pageMoved !== false) {
837
- c.$table.trigger('pageMoved', c);
846
+ c.$table
847
+ .trigger('pageMoved', c)
848
+ .trigger('applyWidgets');
838
849
  if (!p.ajax && table.isUpdating) {
839
- c.$table.trigger('updateComplete');
850
+ c.$table.trigger('updateComplete', [ table, true ]);
840
851
  }
841
852
  }
842
853
  },
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-tablesorter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.7
4
+ version: 1.12.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jun Lin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-10 00:00:00.000000000 Z
12
+ date: 2014-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -31,7 +31,8 @@ dependencies:
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '5'
34
- description: Simple integration of jquery-tablesorter into the asset pipeline.
34
+ description: Simple integration of jquery-tablesorter (Mottie's fork) into the Rails
35
+ asset pipeline.
35
36
  email:
36
37
  - github@black-milk.de
37
38
  executables: []
@@ -90,6 +91,7 @@ files:
90
91
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js
91
92
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js
92
93
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js
94
+ - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-duration.js
93
95
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js
94
96
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js
95
97
  - vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js
@@ -139,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
141
  requirements:
140
142
  - - ">="
141
143
  - !ruby/object:Gem::Version
142
- version: '0'
144
+ version: 1.9.3
143
145
  required_rubygems_version: !ruby/object:Gem::Requirement
144
146
  requirements:
145
147
  - - ">="
@@ -150,5 +152,6 @@ rubyforge_project:
150
152
  rubygems_version: 2.2.2
151
153
  signing_key:
152
154
  specification_version: 4
153
- summary: Simple integration of jquery-tablesorter into the asset pipeline.
155
+ summary: Simple integration of jquery-tablesorter (Mottie's fork) into the Rails asset
156
+ pipeline.
154
157
  test_files: []