xref: /plugin/sortablejs/script.js (revision daef2155c7c3cb93214b73412d71680c1ba34500)
1/*
2	SortTable
3  version 2.1
4  7th April 2007
5  Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
6
7  19 Feb 2008
8  Fixed some jslint errors to support DokuWiki (http://www.splitbrain.org) js compression
9
10  function reinitsort()
11  sorttable.reinit
12  added by Otto Vainio to allow sort tables updated with javascript.
13  Otto Vainio (otto@valjakko.net)
14
15  27.11.2008
16  Changed line 77 document.getElementsByTagName('table') to div.getElementsByTagName('table')
17  To allow multiple sortable tables in same page
18  (Thanks to Hans Sampiemon)
19
20  14.1.2009
21  Added option for default sorting.
22  Use dokuwiki event registration.
23
24  27.1.2009
25  Cleaned some jlint errors to make this workable, when css+js compress is set in dokuwiki
26
27  10.5.2011
28 * version 2.5 Fixed problems with secionediting, footnotes and edittable
29
30  18.7.2013
31 * version 2.6 Added support for jQuery and dokuwiki Weatherwax ->
32
33  28.5.2014
34  * version 2.7 Fixed problem with first row not getting sorted
35
36  30.5.2014
37  * version 2.8 Fixed problem with first row not getting sorted in default sort. Added option "sumrow" to prevent sum line sort.
38
39
40  Instructions:
41  Used from dokuwiki
42  Click on the headers to sort
43
44  Thanks to many, many people for contributions and suggestions.
45  Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
46  This basically means: do what you want with it.
47*/
48
49var stIsIE = /*@cc_on!@*/false;
50var tableid = 0;
51
52sorttable = {
53  reinit: function() {
54    arguments.callee.done = true;
55    // kill the timer
56    //if (_timer) {clearInterval(_timer);}
57
58    if (!document.createElement || !document.getElementsByTagName) {return;}
59
60//    sorttable.DATE_RE = /^(\d\d?)[\/\.\-](\d\d?)[\/\.\-]((\d\d)?\d\d)$/;
61    sorttable.DATE_RE = /^(\d\d?)[\/\.\-](\d\d?)[\/\.\-]((\d\d)?\d\d)( (\d\d?)[:\.]?(\d\d?))?$/;
62
63
64    forEach(document.getElementsByTagName('table'), function(table) {
65      if (table.className.search(/\bsortable\b/) != -1) {
66        sorttable.makeSortable(table);
67      }
68    });
69    forEach(document.getElementsByTagName('div'), function(div) {
70      if (div.className.search(/\bsortable\b/) != -1) {
71        sorttable.makeSortablediv(div);
72      }
73    });
74  },
75
76  init: function() {
77    // quit if this function has already been called
78    if (arguments.callee.done) {return;}
79    // flag this function so we don't do the same thing twice
80    arguments.callee.done = true;
81    // kill the timer
82    //if (_timer) {clearInterval(_timer);}
83
84    if (!document.createElement || !document.getElementsByTagName) {return;}
85
86//    sorttable.DATE_RE = /^(\d\d?)[\/\.\-](\d\d?)[\/\.\-]((\d\d)?\d\d)$/;
87    sorttable.DATE_RE = /^(\d\d?)[\/\.\-](\d\d?)[\/\.\-]((\d\d)?\d\d)( (\d\d?):?(\d\d?))?$/;
88
89    forEach(document.getElementsByTagName('table'), function(table) {
90      if (table.className.search(/\bsortable\b/) != -1) {
91        sorttable.makeSortable(table);
92      }
93    });
94    forEach(document.getElementsByTagName('div'), function(div) {
95      if (div.className.search(/\bsortable\b/) != -1) {
96        sorttable.makeSortablediv(div);
97      }
98    });
99
100  },
101  makeSortablediv: function(div) {
102        if (div.getElementsByTagName('table').length === 0) {
103        } else {
104          forEach(div.getElementsByTagName('table'), function(table) {
105            colid=div.className;
106            overs = new Array();
107            var patt1=/\bcol_\d_[a-z]+/gi;
108            var overs = new Array();
109            if (colid.search(patt1) != -1) {
110              var overrides = new Array();
111              overrides = colid.match(patt1);
112              var xo="";
113              for (xo in overrides)
114              {
115                if (xo == "")
116                {
117                } else {
118                  try
119                  {
120                    var tmp = overrides[xo].split("_");
121                    var ind = tmp[1];
122                    var val = tmp[2];
123                    overs[ind]=val;
124
125                  }
126                  catch (e)
127                  {
128                  }
129                }
130              }
131              colid = colid.replace(patt1,'');
132            }
133            var patt2=/\bsortbottom/gi;
134            var bottoms = 0;
135            if (colid.search(patt2) != -1) {
136				bottoms=1;
137			}
138            sorttable.makeSortable(table,overs,bottoms);
139            if (colid.search(/\bsort/) != -1) {
140              colid = colid.replace('sortable','');
141              colid = colid.replace(' sort','');
142              if (!colid != '')
143              {
144                colid = colid.trim();
145              }
146              revs=false;
147              if (colid.search(/\br/) != -1) {
148                revs=true;
149                colid = colid.replace('r','');
150              }
151              sorttable.defaultSort(table,colid,revs);
152            }
153          });
154        }
155  },
156  defaultSort: function(table, colid, revs) {
157//    theadrow = table.tHead.rows[0].cells;
158    theadrow = table.rows[0].cells;
159    colid--;
160    colname ="col"+colid;
161     // remove sorttable_sorted classes
162     var thiscell=false;
163     forEach(theadrow, function(cell) {
164       colclass=cell.className;
165       classname = colclass.split(" ");
166       if (classname[0]==colname)
167//       if (cell.className==colname)
168       {
169         thiscell=cell;
170       }
171//       if (cell.nodeType == 1) { // an element
172//         cell.className = cell.className.replace('sorttable_sorted_reverse','');
173//         cell.className = cell.className.replace('sorttable_sorted','');
174//       }
175     });
176     if (thiscell===false) {return;}
177     sortfwdind = document.getElementById('sorttable_sortfwdind');
178     if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
179     sortrevind = document.getElementById('sorttable_sortrevind');
180     if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
181
182     thiscell.className += ' sorttable_sorted';
183     sortfwdind = document.createElement('span');
184     sortfwdind.id = "sorttable_sortfwdind";
185     sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
186     thiscell.appendChild(sortfwdind);
187
188     // build an array to sort. This is a Schwartzian transform thing,
189     // i.e., we "decorate" each row with the actual sort key,
190     // sort based on the sort keys, and then put the rows back in order
191     // which is a lot faster because you only do getInnerText once per row
192     row_array = [];
193     col = thiscell.sorttable_columnindex;
194     rows = thiscell.sorttable_tbody.rows;
195     for (var j=0; j<rows.length; j++) {
196       row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
197     }
198     /* If you want a stable sort, uncomment the following line */
199     //sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
200     /* and comment out this one */
201     row_array.sort(thiscell.sorttable_sortfunction);
202
203     tb = thiscell.sorttable_tbody;
204     for (var jj=0; jj<row_array.length; jj++) {
205       tb.appendChild(row_array[jj][1]);
206     }
207
208     delete row_array;
209     // If reverse sort wanted, then doit
210     if (revs) {
211      // reverse the table, which is quicker
212       sorttable.reverse(thiscell.sorttable_tbody);
213       thiscell.className = thiscell.className.replace('sorttable_sorted',
214                                                       'sorttable_sorted_reverse');
215       thiscell.removeChild(document.getElementById('sorttable_sortfwdind'));
216       sortrevind = document.createElement('span');
217       sortrevind.id = "sorttable_sortrevind";
218       sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
219       thiscell.appendChild(sortrevind);
220     }
221
222
223
224  },
225
226  makeSortable: function(table,overrides, bottoms) {
227//    tableid++;
228/*
229    if (table.getElementsByTagName('thead').length === 0) {
230      // table doesn't have a tHead. Since it should have, create one and
231      // put the first table row in it.
232      the = document.createElement('thead');
233      the.appendChild(table.rows[0]);
234      table.insertBefore(the,table.firstChild);
235    }
236*/
237    // Safari doesn't support table.tHead, sigh
238/*
239    if (table.tHead === null) {table.tHead = table.getElementsByTagName('thead')[0];}
240
241    if (table.tHead.rows.length != 1) {return;} // can't cope with two header rows
242  */
243//    table.tHead.className += ' tableid'+tableid;
244
245    // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
246    // "total" rows, for example). This is B&R, since what you're supposed
247    // to do is put them in a tfoot. So, if there are sortbottom rows,
248    // for backwards compatibility, move them to tfoot (creating it if needed).
249
250    sortbottomrows = [];
251	if (bottoms>0) {
252		frombottom=0;
253		for (var i=table.rows.length; i>0; i--) {
254//		  if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
255          if (bottoms==frombottom) {
256			sortbottomrows[sortbottomrows.length] = table.rows[i];
257		  }
258		  frombottom++;
259		}
260		if (sortbottomrows) {
261		  if (table.tFoot === null) {
262			// table doesn't have a tfoot. Create one.
263			tfo = document.createElement('tfoot');
264			table.appendChild(tfo);
265		  }
266		  for (var ii=0; ii<sortbottomrows.length; ii++) {
267			tfo.appendChild(sortbottomrows[ii]);
268		  }
269		  delete sortbottomrows;
270		}
271    }
272    // work through each column and calculate its type
273//    headrow = table.tHead.rows[0].cells;
274    headrow = table.rows[0].cells;
275//    for (var i=0; i<headrow.length; i++) {
276    for (i=0; i<headrow.length; i++) {
277      // manually override the type with a sorttable_type attribute
278      var colOptions="";
279      if (overrides[i+1])
280      {
281        colOptions=overrides[i+1];
282      }
283      if (!colOptions.match(/\bnosort\b/)) { // skip this col
284        mtch = colOptions.match(/\b[a-z0-9]+\b/);
285        if (mtch) { override = mtch[0]; }
286        if (mtch && typeof sorttable["sort_"+override] == 'function') {
287          headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
288        } else {
289          headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
290        }
291/*
292      if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
293        mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
294        if (mtch) { override = mtch[1]; }
295        if (mtch && typeof sorttable["sort_"+override] == 'function') {
296          headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
297        } else {
298          headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
299        }
300*/
301        // make it clickable to sort
302        headrow[i].sorttable_columnindex = i;
303        headrow[i].sorttable_tbody = table.tBodies[0];
304//        dean_addEvent(headrow[i],"click", function(e) {
305//        addEvent(headrow[i],"click", function(e) {
306        jQuery(headrow[i]).click(function(){
307
308          theadrow = this.parentNode;
309
310          if (this.className.search(/\bsorttable_sorted\b/) != -1) {
311            // if we're already sorted by this column, just
312            // reverse the table, which is quicker
313            sorttable.reverse(this.sorttable_tbody);
314            this.className = this.className.replace('sorttable_sorted',
315                                                    'sorttable_sorted_reverse');
316            sortfwdind = document.getElementById('sorttable_sortfwdind');
317            if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
318//            this.removeChild(document.getElementById('sorttable_sortfwdind'));
319            sortrevind = document.getElementById('sorttable_sortrevind');
320            if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
321            sortrevind = document.createElement('span');
322            sortrevind.id = "sorttable_sortrevind";
323            sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
324            this.appendChild(sortrevind);
325            return;
326          }
327          if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
328            // if we're already sorted by this column in reverse, just
329            // re-reverse the table, which is quicker
330            sorttable.reverse(this.sorttable_tbody);
331            this.className = this.className.replace('sorttable_sorted_reverse',
332                                                    'sorttable_sorted');
333            sortrevind = document.getElementById('sorttable_sortrevind');
334            if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
335//            this.removeChild(document.getElementById('sorttable_sortrevind'));
336            sortfwdind = document.getElementById('sorttable_sortfwdind');
337            if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
338            sortfwdind = document.createElement('span');
339            sortfwdind.id = "sorttable_sortfwdind";
340            sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
341            this.appendChild(sortfwdind);
342            return;
343          }
344
345          // remove sorttable_sorted classes
346//          theadrow = this.parentNode;
347          forEach(theadrow.childNodes, function(cell) {
348            if (cell.nodeType == 1) { // an element
349              cell.className = cell.className.replace('sorttable_sorted_reverse','');
350              cell.className = cell.className.replace('sorttable_sorted','');
351            }
352          });
353          sortfwdind = document.getElementById('sorttable_sortfwdind');
354          if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
355          sortrevind = document.getElementById('sorttable_sortrevind');
356          if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
357
358          this.className += ' sorttable_sorted';
359          sortfwdind = document.createElement('span');
360          sortfwdind.id = "sorttable_sortfwdind";
361          sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
362          this.appendChild(sortfwdind);
363
364          // build an array to sort. This is a Schwartzian transform thing,
365          // i.e., we "decorate" each row with the actual sort key,
366          // sort based on the sort keys, and then put the rows back in order
367          // which is a lot faster because you only do getInnerText once per row
368          row_array = [];
369          col = this.sorttable_columnindex;
370          rows = this.sorttable_tbody.rows;
371          for (var j=0; j<rows.length; j++) {
372            row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
373          }
374          /* If you want a stable sort, uncomment the following line */
375          //sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
376          /* and comment out this one */
377          row_array.sort(this.sorttable_sortfunction);
378
379          tb = this.sorttable_tbody;
380          for (var j3=0; j3<row_array.length; j3++) {
381            tb.appendChild(row_array[j3][1]);
382          }
383
384          delete row_array;
385        });
386      }
387    }
388  },
389
390  guessType: function(table, column) {
391    // guess the type of a column based on its first non-blank row
392  var NONE=0;
393	var TEXT=0;
394	var NUM=0;
395	var DDMM=0;
396	var MMDD=0;
397    sortfn = sorttable.sort_alpha;
398    for (var i=0; i<table.tBodies[0].rows.length; i++) {
399      text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
400      set=0;
401      if (text !== '') {
402        if (text.match(/^-?[£$¤]?[\d,.]+[%€]?$/)) {
403          set=1;
404          NUM=1;
405        }
406        // check for a date: dd/mm/yyyy or dd/mm/yy
407        // can have / or . or - as separator
408        // can be mm/dd as well
409        possdate = text.match(sorttable.DATE_RE);
410        if (possdate) {
411          // looks like a date
412          first = parseInt(possdate[1]);
413          second = parseInt(possdate[2]);
414          if (first > 12) {
415            // definitely dd/mm
416//            return sorttable.sort_ddmm;
417            set=1;
418            DDMM=1;
419          } else if (second > 12) {
420            set=1;
421            MMDD=1;
422//            return sorttable.sort_mmdd;
423          } else {
424            // looks like a date, but we can't tell which, so assume
425            // that it's dd/mm (English imperialism!) and keep looking
426            set=1;
427            DDMM=1;
428//            sortfn = sorttable.sort_ddmm;
429          }
430        }
431        // if nothing known then assume text
432        if (set==0) {
433          TEXT=1;
434        }
435        set=0;
436
437      }
438    }
439    if (TEXT>0 || NUM+DDMM+MMDD>1) return sorttable.sort_alpha;
440    if (NUM>0) return sorttable.sort_numeric;
441    if (DDMM>0) return sorttable.sort_ddmm;
442    if (MMDD>0) return sorttable.sort_mmdd;
443  },
444
445  getInnerText: function(node) {
446    // gets the text we want to use for sorting for a cell.
447    // strips leading and trailing whitespace.
448    // this is *not* a generic getInnerText function; it's special to sorttable.
449    // for example, you can override the cell text with a customkey attribute.
450    // it also gets .value for <input> fields.
451
452    hasInputs = (typeof node.getElementsByTagName == 'function') &&
453                 node.getElementsByTagName('input').length;
454
455    if (node.getAttribute("sorttable_customkey") !== null) {
456      return node.getAttribute("sorttable_customkey");
457    }
458    else if (typeof node.textContent != 'undefined' && !hasInputs) {
459      return node.textContent.replace(/^\s+|\s+$/g, '');
460    }
461    else if (typeof node.innerText != 'undefined' && !hasInputs) {
462      return node.innerText.replace(/^\s+|\s+$/g, '');
463    }
464    else if (typeof node.text != 'undefined' && !hasInputs) {
465      return node.text.replace(/^\s+|\s+$/g, '');
466    }
467    else {
468      switch (node.nodeType) {
469        case 3:
470          if (node.nodeName.toLowerCase() == 'input') {
471            return node.value.replace(/^\s+|\s+$/g, '');
472          }
473        case 4:
474          return node.nodeValue.replace(/^\s+|\s+$/g, '');
475          break;
476        case 1:
477        case 11:
478          var innerText = '';
479          for (var i = 0; i < node.childNodes.length; i++) {
480            innerText += sorttable.getInnerText(node.childNodes[i]);
481          }
482          return innerText.replace(/^\s+|\s+$/g, '');
483          break;
484        default:
485          return '';
486      }
487    }
488  },
489
490  reverse: function(tbody) {
491    // reverse the rows in a tbody
492    newrows = [];
493    for (var i=0; i<tbody.rows.length; i++) {
494      newrows[newrows.length] = tbody.rows[i];
495    }
496    for (var i=newrows.length-1; i>=0; i--) {
497       tbody.appendChild(newrows[i]);
498    }
499    delete newrows;
500  },
501
502  /* sort functions
503     each sort function takes two parameters, a and b
504     you are comparing a[0] and b[0] */
505  sort_numeric: function(a,b) {
506    aa = parseFloat(a[0].replace(/[^0-9.\-]/g,''));
507    if (isNaN(aa)) {aa = 0;}
508    bb = parseFloat(b[0].replace(/[^0-9.\-]/g,''));
509    if (isNaN(bb)) {bb = 0;}
510    return aa-bb;
511  },
512  sort_alpha: function(a,b) {
513    if (a[0]==b[0]) {return 0;}
514    if (a[0]<b[0]) {return -1;}
515    return 1;
516  },
517  sort_ddmm: function(a,b) {
518    mtch = a[0].match(sorttable.DATE_RE);
519    y = mtch[3]; m = mtch[2]; d = mtch[1];
520    t = mtch[5]+'';
521    if (t.length < 1 ) {t = '';}
522    if (m.length == 1) {m = '0'+m;}
523    if (d.length == 1) {d = '0'+d;}
524    dt1 = y+m+d+t;
525    mtch = b[0].match(sorttable.DATE_RE);
526    y = mtch[3]; m = mtch[2]; d = mtch[1];
527    t = mtch[5]+'';
528    if (t.length < 1 ) {t = '';}
529    if (m.length == 1) {m = '0'+m;}
530    if (d.length == 1) {d = '0'+d;}
531    dt2 = y+m+d+t;
532    if (dt1==dt2) {return 0;}
533    if (dt1<dt2) {return -1;}
534    return 1;
535  },
536  sort_mmdd: function(a,b) {
537    mtch = a[0].match(sorttable.DATE_RE);
538    y = mtch[3]; d = mtch[2]; m = mtch[1];
539    t = mtch[5]+'';
540    if (m.length == 1) {m = '0'+m;}
541    if (d.length == 1) {d = '0'+d;}
542    dt1 = y+m+d+t;
543    mtch = b[0].match(sorttable.DATE_RE);
544    y = mtch[3]; d = mtch[2]; m = mtch[1];
545    t = mtch[5]+'';
546    if (t.length < 1 ) {t = '';}
547    if (m.length == 1) {m = '0'+m;}
548    if (d.length == 1) {d = '0'+d;}
549    dt2 = y+m+d+t;
550    if (dt1==dt2) {return 0;}
551    if (dt1<dt2) {return -1;}
552    return 1;
553  },
554
555  shaker_sort: function(list, comp_func) {
556    // A stable sort function to allow multi-level sorting of data
557    // see: http://en.wikipedia.org/wiki/Cocktail_sort
558    // thanks to Joseph Nahmias
559    var b = 0;
560    var t = list.length - 1;
561    var swap = true;
562
563    while(swap) {
564        swap = false;
565        for(var i = b; i < t; ++i) {
566            if ( comp_func(list[i], list[i+1]) > 0 ) {
567                var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
568                swap = true;
569            }
570        } // for
571        t--;
572
573        if (!swap) {break;}
574
575        for(var i = t; i > b; --i) {
576            if ( comp_func(list[i], list[i-1]) < 0 ) {
577                var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
578                swap = true;
579            }
580        } // for
581        b++;
582
583    } // while(swap)
584  }
585
586
587};
588/* ******************************************************************
589   Supporting functions: bundled here to avoid depending on a library
590   ****************************************************************** */
591
592
593
594// Dean Edwards/Matthias Miller/John Resig
595
596
597// Dean's forEach: http://dean.edwards.name/base/forEach.js
598/*
599  forEach, version 1.0
600  Copyright 2006, Dean Edwards
601  License: http://www.opensource.org/licenses/mit-license.php
602*/
603
604// array-like enumeration
605if (!Array.forEach) { // mozilla already supports this
606  Array.forEach = function(array, block, context) {
607    for (var i = 0; i < array.length; i++) {
608      block.call(context, array[i], i, array);
609    }
610  };
611}
612
613// generic enumeration
614Function.prototype.forEach = function(object, block, context) {
615  for (var key in object) {
616    if (typeof this.prototype[key] == "undefined") {
617      block.call(context, object[key], key, object);
618    }
619  }
620};
621
622// character enumeration
623String.forEach = function(string, block, context) {
624  Array.forEach(string.split(""), function(chr, index) {
625    block.call(context, chr, index, string);
626  });
627};
628
629// globally resolve forEach enumeration
630var forEach = function(object, block, context) {
631  if (object) {
632    var resolve = Object; // default
633    if (object instanceof Function) {
634      // functions have a "length" property
635      resolve = Function;
636    } else if (object.forEach instanceof Function) {
637      // the object implements a custom forEach method so use that
638      object.forEach(block, context);
639      return;
640    } else if (typeof object == "string") {
641      // the object is a string
642      resolve = String;
643    } else if (typeof object.length == "number") {
644      // the object is array-like
645      resolve = Array;
646    }
647    resolve.forEach(object, block, context);
648  }
649};
650
651
652if ('undefined' != typeof(window.addEvent)) {
653    window.addEvent(window, 'load', sorttable.init);
654} else {
655    jQuery(function() {
656      sorttable.init();
657    });
658}
659
660//sorttable.init;
661
662function reinitsort() {
663  sorttable.reinit();
664}
665