1(function (vendor, $, window) { 2 var appName = 'Tables', 3 elemCss = { 4 display: 'none', 5 position: 'absolute', 6 boxSizing: 'border-box', 7 border: '2px solid #ddd', 8 resize: 'none', 9 overflow: 'hidden', 10 padding: '0', 11 margin: '0', 12 textIndent: '10px', 13 }, 14 dtsCellChangeReqTimeout = {}, 15 dtsCellEditLock = {}, 16 allowedFileTypes = typeof dtb_allowedFileTypes !== 'undefined' ? dtb_allowedFileTypes : ['png', 'jpeg', 'jpg', 'pdf']; 17 18 if (!(appName in vendor)) { 19 vendor[appName] = {}; 20 } 21 vendor[appName].setFrontendFields = function ($table) { 22 var $tableWrap = $table.parents('.supsystic-tables-wrap:first'), 23 editable = $tableWrap.find('.editable'), 24 editfiles = $tableWrap.find('.editfile'), 25 selectable = $tableWrap.find('.selectable'), 26 date = $tableWrap.find('.datefield'); 27 28 if ($table.data('id')) { 29 var currTableId = $table.data('id'); 30 dtsCellEditLock[currTableId] = 0; 31 dtsCellChangeReqTimeout[currTableId] = false; 32 $tableWrap.find('.dtsFrontendExport a').on('click', function (event) { 33 // prevent clicking on "link" 34 if (dtsCellEditLock[currTableId]) { 35 event.preventDefault(); 36 } 37 }); 38 } 39 this.createEditableFields($table, editable); 40 this.createEditableFileFields($table, editfiles); 41 this.createSelectableFields($table, selectable); 42 this.createDateFields($table, date); 43 }; 44 45 vendor[appName].updateAfterRedraw = function (table) { 46 var id = table.data('id'), 47 viewId = table.data('view-id'), 48 $currentTableWrapper = $('#supsystic-table-' + viewId), 49 $currentTable = $currentTableWrapper.find('#supsystic-table-' + id), 50 $currentEditableFields = $currentTableWrapper.find('.editable'), 51 $currentEditableFileFields = $currentTableWrapper.find('.editfile'), 52 $currentSelectableFields = $currentTableWrapper.find('.selectable'), 53 $currentDateFields = $currentTableWrapper.find('.datefield'); 54 55 this.createEditableFields($currentTable, $currentEditableFields); 56 this.createEditableFileFields($currentTable, $currentEditableFileFields); 57 this.createSelectableFields($currentTable, $currentSelectableFields); 58 this.createDateFields($currentTable, $currentDateFields); 59 this.setTooltipCell($currentTable); 60 this.setCollapsibleRow($currentTable); 61 this.setImgLightbox($currentTable); 62 if (g_stbServerSideProcessing) { 63 this.setCollapsibleCell($currentTable); 64 } 65 }; 66 67 vendor[appName].createEditableFields = function ($table, $fields) { 68 var self = this; 69 70 if (this._useFrontendFields($table) && $fields.length) { 71 var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 72 $elem = $tableWrapper.find('.inputArea'); 73 74 if (!$elem.length) { 75 $elem = $('<textarea class="inputArea" />'); 76 $elem.css( 77 $.extend({}, elemCss, { 78 textIndent: '0', 79 padding: '5px', 80 overflowY: 'auto', 81 }) 82 );
83 $elem.appendTo($tableWrapper); 84 $elem = $tableWrapper.find('.inputArea'); 85 } 86 $fields.off('click.sup').on('click.sup', function (event) { 87 event.preventDefault(); 88 self._setEditedValueToCell($(this), $elem, $table); 89 }); 90 } 91 }; 92 93 vendor[appName].setClickableDeleteBtn = function ($td, $elem, $table) { 94 var self = this, 95 cell = JSON.stringify({ c: $td.data('x'), r: $td.data('y') }), 96 cellType = this._getCellType($td); 97 98 $(document) 99 .off('click') 100 .on('click vclick tap', '.delete-upload-file', function () { 101 var deleteFileBtn = $(this); 102 self 103 .request( 104 { 105 module: 'tables', 106 action: 'deleteEditableFieldsFile', 107 nonce: DTGS_NONCE_FRONTEND, 108 }, 109 { 110 id: $table.data('id'), 111 cell: cell, 112 file_src: typeof deleteFileBtn.siblings('[data-path]') !== 'undefined' ? deleteFileBtn.siblings('[data-path]').attr('data-path') : '', 113 } 114 ) 115 .done(function (response) { 116 if (response.success) { 117 $td.attr('data-original-value', ''); 118 $td.attr('data-order', ''); 119 $td.attr('data-editfile', ''); 120 $td.html(''); 121 if ($table.attr('data-fixed-cols') === 'on') { 122 var cloneTd = $table.find('[data-x="' + $td.data('x') + '"][data-y="' + $td.data('y') + '"]'); 123 if (typeof cloneTd !== 'undefined') { 124 cloneTd.attr('data-original-value', ''); 125 cloneTd.attr('data-order', ''); 126 cloneTd.attr('data-editfile', ''); 127 cloneTd.html(''); 128 } 129 } 130 setTimeout(function () { 131 self._updateTableCell(cellType, $elem, $td, $table); 132 }, 1000); 133 } else { 134 alert(response.message.message); 135 } 136 }); 137 138 return false; 139 }); 140 }; 141 142 vendor[appName].createEditableFileFields = function ($table, $fields) { 143 var self = this; 144 145 if (this._useFrontendFields($table) && $fields.length) { 146 var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 147 $elem = $tableWrapper.find('.inputFile'); 148 149 $fields.find('.delete-upload-file').show(); 150 151 if (!$elem.length) { 152 $elem = $('<input type="file" class="inputFile" />'); 153 $elem.css( 154 $.extend({}, elemCss, { 155 textIndent: '0', 156 padding: '5px', 157 overflowY: 'auto', 158 }) 159 );
160 $elem.appendTo($tableWrapper); 161 $elem = $tableWrapper.find('.inputFile'); 162 } 163 $fields.off('click.sup').on('click.sup', function (event) { 164 event.preventDefault(); 165 if (!$(this).find('a').length && !$(this).find('img').length) { 166 self._setEditedValueToCell($(this), $elem, $table); 167 } else { 168 self.setClickableDeleteBtn($(this), $elem, $table); 169 } 170 }); 171 } 172 }; 173 174 vendor[appName].createSelectableFields = function ($table, $fields) { 175 var self = this; 176 177 if (this._useFrontendFields($table) && $fields.length) { 178 var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 179 $elem = $tableWrapper.find('.selectArea'), 180 $isDb = $table.closest('.supsystic-tables-wrap').find('.stbDBEditData'); 181 182 if (!$elem.length) { 183 $elem = $('<select class="selectArea" />'); 184 $elem.css(elemCss); 185 $elem.appendTo($tableWrapper); 186 $elem = $tableWrapper.find('.selectArea'); 187 } 188 $fields.off('click.sup').on('click.sup', function (event) { 189 event.preventDefault(); 190 if ($isDb.length === 0 || ($isDb.length && $(this).hasClass('editable'))) { 191 self._setEditedValueToCell($(this), $elem, $table); 192 } 193 }); 194 } 195 }; 196 197 vendor[appName].createDateFields = function ($table, $fields) { 198 var self = this; 199 200 if (this._useFrontendFields($table) && $fields.length) { 201 var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 202 $elem = $tableWrapper.find('.datetimeArea'); 203 204 if (typeof $.datepicker == 'object') { 205 if (!$elem.length) { 206 $.datepicker.parseDate = function (format, value) { 207 return moment(value, format).toDate(); 208 }; 209 $.datepicker.formatDate = function (format, value) { 210 return moment(value).format(format); 211 }; 212 213 $elem = $('<input type="text" class="datetimeArea" />'); 214 $elem.css(elemCss);
215 $elem.appendTo($tableWrapper); 216 $elem = $tableWrapper.find('.datetimeArea'); 217 $elem.datepicker({ 218 beforeShow: function (input, inst) { 219 $('#ui-datepicker-div').addClass('stbDatePicker'); //add custom class to datepicker 220 }, 221 }); 222 } 223 $fields.off('click.sup').on('click.sup', function (event) { 224 event.preventDefault(); 225 self._setEditedValueToCell($(this), $elem, $table); 226 }); 227 } 228 } 229 }; 230 231 vendor[appName].setImgLightbox = function ($table) { 232 if ($table.attr('data-lightbox-img') && $table.attr('data-lightbox-img') == 'on') { 233 setTimeout(function () { 234 $table 235 .parents('.supsystic-tables-wrap:first') 236 .find('th img, td img') 237 .each(function () { 238 if (!$(this).parent().is('a')) { 239 var url = $(this).data('full') || $(this).attr('src'); 240 $(this).attr('href', url).attr('data-featherlight', 'image'); 241 } 242 }); 243 }, 1000); 244 } 245 }; 246 247 vendor[appName].setTooltipCell = function ($table) { 248 $table.find('.tooltipCell').each(function () { 249 var cell = $(this), 250 // content = cell.html(), 251 content = cell.attr('data-original-value'), 252 icon = $('<i class="fa fa-info-circle"></i>'); 253 254 cell.html(icon); 255 icon.tooltipster({ 256 content: content, 257 contentAsHTML: true, 258 interactive: true, 259 position: 'top-left', 260 updateAnimation: true, 261 animation: 'swing', 262 }); 263 }); 264 }; 265 266 vendor[appName]._useFrontendFields = function ($table) { 267 var useFrontendFields = false, 268 tableId = $table.data('id'); 269 270 if ((window.useEdit && typeof window.useEdit != 'undefined' && typeof window.useEdit[tableId] != 'undefined') || (SDT_DATA.isAdmin && SDT_DATA.isPro)) { 271 useFrontendFields = true; 272 } 273 return useFrontendFields; 274 }; 275 276 vendor[appName]._setElemPosition = function ($elem, $td) { 277 var params = [ 278 { selector: '.dataTables_scrollHead', scroll: true }, 279 { selector: '.dataTables_scrollBody', scroll: true }, 280 { selector: '.dataTables_scrollFoot', scroll: true }, 281 { selector: '.DTFC_LeftHeadWrapper' }, 282 { selector: '.DTFC_LeftBodyWrapper' }, 283 { selector: '.DTFC_LeftFootWrapper' }, 284 { selector: '.DTFC_RightHeadWrapper' }, 285 { selector: '.DTFC_RightBodyWrapper' }, 286 { selector: '.DTFC_RightFootWrapper' }, 287 { selector: 'td.child' }, 288 { selector: '.dataTables_wrapper' }, 289 ], 290 scrollTop, 291 scrollLeft, 292 position; 293 294 for (var i = 0; i < params.length; i++) { 295 var parent = $td.parents(params[i].selector + ':first'); 296 297 if (parent.length) { 298 parent.append($elem); 299 scrollTop = params[i].scroll ? parent.scrollTop() : 0; 300 scrollLeft = params[i].scroll ? parent.scrollLeft() : 0; 301 position = $td.position(); 302 $elem.css({ 303 // top: position.top + scrollTop, 304 // left: position.left + scrollLeft 305 top: position.top, 306 left: position.left, 307 }); 308 break; 309 } 310 } 311 }; 312 313 vendor[appName]._getCellType = function ($td) { 314 var types = ['editable', 'selectable', 'datefield', 'editfile'], 315 cellType = 'editable'; 316 317 for (var i = 0; i < types.length; i++) { 318 if ($td.hasClass(types[i])) { 319 cellType = types[i]; 320 } 321 } 322 return cellType; 323 }; 324 325 vendor[appName]._setEditedValueToCell = function ($td, $elem, $table) { 326 var self = this, 327 cellType = this._getCellType($td), 328 value = $td.data('formula') ? $td.data('formula') : $td.data('original-value'), 329 source = $td.data('source') && $td.data('source').length ? $td.data('source') : [], 330 formula = $td.data('formula'), 331 useComaAsDelimiter = $table.data('use-comma-as-delimiter'), 332 triggerEvent = (typeof $.browser != 'undefined' && $.browser.msie) || !!navigator.userAgent.match(/Trident\/7\./) ? 'focusout' : 'blur'; 333 334 this._setElemPosition($elem, $td); 335 // Set element CSS styles 336 $elem.css({ 337 width: $td.innerWidth() + 1, // To cover cell right border 338 height: $td.innerHeight() + 1, // To cover cell bottom border 339 minHeight: $td.innerHeight() + 1, 340 fontSize: $td.css('font-size'), 341 lineHeight: $td.css('line-height'), 342 });
343 // To remove unneeded zeros from end of percent values, e.g. 15.230000000001 344 if (!formula && $td.data('cell-format-type') == 'percent') { 345 value = this._preparePercentValue(value, $td.data('cell-format')); 346 } 347 switch (cellType) { 348 case 'editable': 349 // Show stored <br> line breaks as real newlines while editing in the textarea 350 value = (value || '').toString().replace(/<br\s*\/?>/gi, '\n'); 351 if (useComaAsDelimiter && value.match(/^-{0,1}\d+\.{0,1}\d*$/)) { 352 value = value.replace('.', ','); 353 } 354 break; 355 case 'selectable': 356 $elem.html(''); 357 for (var i = 0; i < source.length; i++) { 358 var selected = source[i] == value ? 'selected="selected"' : ''; 359 $elem.append('<option ' + selected + '>' + source[i] + '</option>'); 360 } 361 break; 362 case 'datefield': 363 var isDate = $td.data('cell-format-type') == 'date' && typeof $td.data('cell-format') != 'undefined', 364 format = isDate ? $td.data('cell-format') : $table.data('date-format'), 365 defDate = isDate && value ? value : moment().format(format); 366 367 value = isDate && value ? value : defDate; 368 $elem.datepicker('option', 'dateFormat', format); 369 $elem.datepicker('option', 'defaultDate', defDate); 370 break; 371 case 'editfile': 372 $elem.click(); 373 break; 374 default: 375 break; 376 } 377 if (cellType != 'selectable' && cellType != 'editfile') { 378 $elem.off('keypress').on('keypress', function (event) { 379 if ((event.keyCode || event.which) == 13) { 380 if (cellType == 'editable' && event.ctrlKey) { 381 // Ctrl+Enter inserts a line break in the cell, same as the backend cell editor 382 return true; 383 } 384 // Enter button 385 event.preventDefault(); 386 var $this = $(this); 387 $this.trigger(triggerEvent); 388 if (cellType == 'datefield') { 389 $this.datepicker('hide'); 390 } 391 return true; 392 } 393 }); 394 $elem.val(value); 395 } 396 $elem.off('keydown').on('keydown', function (event) { 397 if (cellType == 'editable' && (event.keyCode || event.which) == 13 && event.ctrlKey) { 398 // Ctrl+Enter inserts a line break, same as the backend cell editor. 399 // Browsers do not insert "\n" into a textarea by themselves for Ctrl+Enter 400 // (and Chromium does not even fire "keypress" for it), so do it manually. 401 event.preventDefault(); 402 var el = this, 403 start = el.selectionStart, 404 end = el.selectionEnd, 405 val = el.value; 406 407 el.value = val.slice(0, start) + '\n' + val.slice(end); 408 el.selectionStart = el.selectionEnd = start + 1; 409 return; 410 } 411 if ((event.keyCode || event.which) == 9) { 412 // Tab button 413 event.preventDefault(); 414 var $this = $(this), 415 $fields = $table.find('.editable, .selectable, .datefield, .editfile'), 416 nextIndex = self._getNextVisibleIndex($fields, $fields.index($td) + 1); 417 418 $this.trigger(triggerEvent); 419 if (cellType == 'datefield') { 420 $this.datepicker('hide'); 421 } 422 if (nextIndex > 0) { 423 $fields.eq(nextIndex).trigger('click'); 424 } 425 } 426 }); 427 if (cellType == 'datefield') { 428 $elem.datepicker('option', 'onClose', function () { 429 $('#ui-datepicker-div').removeClass('stbDatePicker'); 430 self._updateTableCell(cellType, $elem, $td, $table); 431 }); 432 } else if (cellType == 'editfile') { 433 $elem.off('change').on('change', function (e) { 434 var file = typeof e.target.files[0] !== 'undefined' ? e.target.files[0] : { type: 'supsystic', name: '' }, 435 url = window.ajaxurl ? window.ajaxurl : ajax_obj.ajaxurl, 436 message = '', 437 file_ext = file.name.slice((Math.max(0, file.name.lastIndexOf('.')) || Infinity) + 1).toLowerCase(); 438 439 $td.attr('data-editfile', ''); 440 if (file.type === 'supsystic') { 441 $td.attr('data-editfile', ''); 442 $elem.hide(); 443 } else if (toeInArray(file_ext, allowedFileTypes) >= 0) { 444 var fileData = new FormData(); 445 fileData.append('action', 'supsystic-tables'); 446 fileData.append('route[module]', 'tables'); 447 fileData.append('route[action]', 'saveEditableFieldsFile'); 448 fileData.append('route[nonce]', DTGS_NONCE_FRONTEND); 449 fileData.append('id', $table.data('id')); 450 fileData.append('cellFile', file); 451 fileData.append( 452 'cell', 453 JSON.stringify({ 454 c: $td.data('x'), 455 r: $td.data('y'), 456 }) 457 ); 458 459 jQuery 460 .ajax({
461 url: url, 462 data: fileData, 463 cache: false, 464 contentType: false, 465 processData: false, 466 dataType: 'json', 467 beforeSend: function () { 468 jQuery('*').css({ cursor: 'wait' }); 469 }, 470 method: 'POST', 471 type: 'POST', 472 success: function (response) { 473 $elem.hide(); 474 if (response.success) { 475 $td.html(response.message); 476 $td.attr('data-original-value', response.message); 477 $td.attr('data-order', response.message); 478 $td.attr('data-editfile', response.message); 479 setTimeout(function () { 480 self._updateTableCell(cellType, $elem, $td, $table); 481 }, 500); 482 $elem.val(''); 483 } else { 484 $td.attr('data-editfile', ''); 485 alert(response.message.message); 486 } 487 }, 488 }) 489 .done(function () { 490 jQuery('*').css({ cursor: '' }); 491 }); 492 } else { 493 $td.attr('data-editfile', ''); 494 $elem.hide(); 495 // todo: create some notification? 496 alert(file_ext + ' is not allowed file type!'); 497 } 498 }); 499 } else { 500 $elem.off(triggerEvent).on(triggerEvent, function () { 501 self._updateTableCell(cellType, $elem, $td, $table); 502 }); 503 } 504 $elem.show().focus().select(); 505 }; 506 507 vendor[appName]._updateTableCell = function (cellType, $elem, $td, $table) { 508 var self = this, 509 newValue = typeof $elem !== 'undefined' ? $.trim($elem.val()) : '', 510 originalValue = typeof $td.data('original-value') != 'undefined', 511 oldValue = originalValue ? $td.data('original-value') : '', 512 formula = typeof $td.data('formula') != 'undefined', 513 editfile = typeof $td.attr('data-editfile') != 'undefined', 514 tableId = $table.data('id'), 515 history = $table.data('from-history'), 516 period = $table.data('history-period'), 517 dataTableInstance = this.getTableInstanceById(tableId), 518 _ruleJS = this.getRuleJSInstance($table), 519 cells = []; 520 521 if (editfile) { 522 newValue = encodeURI($td.attr('data-editfile')); 523 } 524 525 if (cellType == 'editable') { 526 // Turn line breaks typed via Ctrl+Enter into real <br> tags for display and storage 527 newValue = newValue.replace(/\r\n|\r|\n/g, '<br>'); 528 } 529 530 if ($table.data('use-comma-as-delimiter') && newValue.toString().match(/^-{0,1}\d+\,{0,1}\d*$/)) { 531 newValue = newValue.toString().replace(',', '.'); 532 } 533 534 // Set formula value 535 if (formula) { 536 $td.data('formula', newValue); 537 $td.attr('data-formula', newValue); 538 } 539 // Set original value for cells without formulas 540 if (originalValue && !formula) { 541 if (cellType == 'editable' && $td.data('cell-format-type') == 'percent') { 542 newValue = this._preparePercentValue(newValue, $td.data('cell-format'), true); 543 } 544 // We need to update edited cell here for correct work of _ruleJS.init(); 545 $td.data('original-value', newValue); 546 $td.attr('data-original-value', newValue); 547 $td.data('order', newValue); 548 $td.attr('data-order', newValue); 549 } 550 $elem.hide(); 551 if (editfile) { 552 $td.html(decodeURI(newValue)); 553 } else { 554 $td.html(newValue); 555 } 556 if ($table.data('mark-last-edited-cell')) { 557 $table.parents('.supsystic-tables-wrap').find('th, td').removeClass('justEdited'); 558 $td.addClass('justEdited'); 559 setTimeout(function () { 560 $td.removeClass('justEdited'); 561 }, 1500); 562 } 563 564 // Parse formulas 565 _ruleJS.init(); 566 567 // Set data for edited cell 568 var dbEditData = $table.closest('.supsystic-tables-wrap').find('.stbDBEditData'), 569 dbTable = '', 570 uniqFields = '', 571 isDB = dbEditData.length; 572 573 if (isDB) { 574 if (originalValue && oldValue == newValue) { 575 return; 576 } 577 if ($table.data('save-editable-fields') && $td.hasClass('editable')) { 578 var error = dbEditData.data('error'), 579 dbTable = dbEditData.data('table'); 580 if (error && error.length > 0) { 581 alert(error); 582 } else if (!dbTable || dbTable.length == 0) { 583 alert('Table not found.'); 584 } else { 585 var dbFields = dbEditData.data('fields'), 586 uniqFields = dbEditData.data('unique-fields'), 587 uniqData = dbEditData.data('unique-data'), 588 fieldNum = $td.data('x'), 589 rowNum = g_stbServerSideProcessing ? $td.data('db-index') : $td.data('y'); 590 if (fieldNum in dbFields && rowNum in uniqData) { 591 cells.push({ 592 c: fieldNum, 593 f: dbFields[fieldNum], 594 r: rowNum, 595 u: uniqData[rowNum], 596 v: formula ? '=' + $td.data('formula') : newValue, 597 ov: formula ? $.trim($td.html()) : newValue, 598 }); 599 } 600 } 601 } 602 } else { 603 cells.push({ 604 c: $td.data('x'), 605 r: $td.data('y'), 606 v: formula ? '=' + $td.data('formula') : newValue, 607 ov: formula ? $.trim($td.html()) : newValue, 608 }); 609 } 610 611 // Set original value for edited cell with formula 612 // We need to set unformat value which we get after ruleJS init 613 if (originalValue && formula) { 614 var newOriginalValue = $.trim($td.html()); 615 616 $td.data('original-value', newOriginalValue); 617 $td.attr('data-original-value', newOriginalValue); 618 $td.data('order', newOriginalValue); 619 $td.attr('data-order', newOriginalValue); 620 } 621 622 // Update other table cells before setting format to table 623 $table.find('th, td').each(function (index, elem) { 624 var $elem = $(elem); 625 626 // Break if current cell is current edited cell 627 if ($elem.data('x') == $td.data('x') && $elem.data('y') == $td.data('y')) return; 628 629 var $elemValue = $.trim($elem.html()), 630 $elemOrValue = $elem.data('original-value') || '', 631 $elemFormula = $elem.data('formula') || ''; 632
633 if (!isDB && $elemFormula && $elemOrValue != $elemValue) { 634 $elem.data('original-value', $elemValue); 635 $elem.attr('data-original-value', $elemValue); 636 $elem.data('order', $elemValue); 637 $elem.attr('data-order', $elemValue); 638 cells.push({ 639 c: $elem.data('x'), 640 r: $elem.data('y'), 641 v: $elemFormula ? '=' + $elemFormula : $elemValue, 642 ov: $elemValue, 643 }); 644 } 645 }); 646 // Parse formulas again to correct calculation of formulas, which is dependent to the follow placed cells 647 // TODO: find the way to check how many times we need to recalc formulas to get final result 648 _ruleJS.init(); 649 650 // Set formats 651 this.formatDataAtTable($table); 652 653 //save formated values (need for export) 654 $.each(cells, function (index, elem) { 655 var cell = $table.find('[data-x="' + elem['c'] + '"][data-y="' + elem['r'] + '"]'); 656 if (cell.length == 1) { 657 elem['fv'] = cell.data('editfile') ? encodeURI(cell.data('editfile')) : cell.html(); 658 } 659 }); 660 661 // Update table sorting 662 if (dataTableInstance && !g_stbServerSideProcessing) { 663 $table.find('th, td').each(function () { 664 dataTableInstance.api().cell($(this)).invalidate(); 665 }); 666 if (typeof dataTableInstance.fnAdjustColumnSizing == 'function') { 667 dataTableInstance.fnAdjustColumnSizing(false); 668 } 669 } 670 671 // Set conditional formatting 672 this.setConditionalFormatting($table, true); 673 674 if ($table.data('save-editable-fields') && cells.length > 0) { 675 if (dtsCellChangeReqTimeout[tableId]) { 676 clearTimeout(dtsCellChangeReqTimeout[tableId]); 677 } 678 dtsCellChangeReqTimeout[tableId] = setTimeout(function () { 679 dtsCellEditLock[tableId]++; 680 self 681 .request( 682 { 683 module: 'tables', 684 action: 'saveEditableFields', 685 nonce: DTGS_NONCE_FRONTEND, 686 }, 687 { 688 id: tableId, 689 isSSP: g_stbServerSideProcessing ? 1 : 0, 690 isDB: isDB ? 1 : 0, 691 dbTable: dbTable, 692 uniqFields: JSON.stringify(uniqFields), 693 cells: JSON.stringify(cells), 694 history: history, 695 period: period ? period : null, 696 } 697 ) 698 .always(function (responce) { 699 if (isDB && responce) { 700 if (responce.success) { 701 var needSave = false, 702 uniqNum; 703 704 for (var i = 0; i < cells.length; i++) { 705 uniqNum = $.inArray(cells[i].f, uniqFields); 706 if (uniqNum >= 0) { 707 uniqData[cells[i].r][uniqNum] = cells[i].v; 708 needSave = true; 709 } 710 } 711 if (needSave) { 712 dbEditData.data('unique-data', uniqData); 713 } 714 } else { 715 alert(responce); 716 } 717 } 718 dtsCellEditLock[tableId]--; 719 dtsCellChangeReqTimeout[tableId] = false; 720 }); 721 }, 400); 722 } 723 724 if (editfile) { 725 $td.find('.delete-upload-file').show(); 726 } 727 728 //Refresh diagrams 729 if (typeof g_stbGoogleCharts != 'undefined' && g_stbGoogleCharts.length > 0) { 730 for (var i = 0; i < g_stbGoogleCharts.length; i++) { 731 if (g_stbGoogleCharts[i].chartData.table_id == tableId) { 732 var rangeFrom = g_stbGoogleCharts[i].chartData.selection.from, 733 rangeTo = g_stbGoogleCharts[i].chartData.selection.to, 734 buffer; 735 if (rangeFrom.row > rangeTo.row) { 736 buffer = rangeFrom.row; 737 rangeFrom.row = rangeTo.row; 738 rangeTo.row = buffer; 739 } 740 if (rangeFrom.col > rangeTo.col) { 741 buffer = rangeFrom.col; 742 rangeFrom.col = rangeTo.col; 743 rangeTo.col = buffer; 744 } 745 var firstCol = g_stbGoogleCharts[i].chartData.rangeData[0].length > rangeTo.col - rangeFrom.col + 1 ? 1 : 0; 746 for (var c = 0; c < cells.length; c++) { 747 var cell = cells[c]; 748 if (cell.r >= rangeFrom.row + 1 && cell.r <= rangeTo.row + 1 && cell.c >= rangeFrom.col && cell.c <= rangeTo.col) { 749 var params = g_stbGoogleCharts[i].chartData.params, 750 row = params.switchRowsColumns ? cell.c - rangeFrom.col : cell.r - rangeFrom.row - (params.useFirstRow ? 1 : 0), // - 1, 751 col = params.switchRowsColumns ? cell.r - rangeFrom.row - (params.useFirstRow ? 1 : 0) : cell.c - rangeFrom.col + firstCol, //(params.useFirstColumn ? 0 :1),
752 cellValue = cell.v.length > 0 && cell.v.substring(0, 1) == '=' ? cell.ov : cell.v, 753 newVar = typeof g_stbGoogleCharts[i].chartData.rangeData[row][col] == 'string' ? cellValue : Number(cellValue) + 0; 754 755 g_stbGoogleCharts[i].chartData.rangeData[row][col] = g_stbGoogleCharts[i].chartData.rangeData[row][col] === '' && row == 0 ? '' : newVar; 756 drawCharts(g_stbGoogleCharts[i], i); 757 } 758 } 759 } 760 } 761 } 762 763 // refresh fixed columns 764 if (typeof $table.data('fixed-cols') !== 'undefined') { 765 var dataTableInstance = typeof $table.api == 'function' ? $table : self.getTableInstanceById($table.data('id')); 766 dataTableInstance.api().fixedColumns().update(); 767 } 768 }; 769 770 vendor[appName]._preparePercentValue = function (value, format, reverse) { 771 reverse = reverse ? reverse : false; 772 773 if (this.isNumber(value)) { 774 var round = format.match(/\d+/g), 775 index = round.length - 1, 776 fixed = round[index] ? round[index].length : 0; 777 778 value = reverse ? value / 100 : value * 100; 779 780 return reverse ? value : value.toFixed(fixed); 781 } 782 return value; 783 }; 784 785 vendor[appName]._getNextVisibleIndex = function ($elem, index) { 786 if (index >= $elem.length) return -1; 787 788 if (!$elem.eq(index).is(':visible')) { 789 index++; 790 index = this._getNextVisibleIndex($elem, index); 791 } 792 return index; 793 }; 794 795 vendor[appName].initConditions = function (elem) { 796 if (this.Editor && this.Editor._Conditions) { 797 this.Editor.Conditions = new this.Editor._Conditions(elem, true); 798 } 799 }; 800 801 vendor[appName].setConditionalFormatting = function ($table, reinit) { 802 // Apply conditional formatting 803 reinit = reinit ? reinit : false; 804 805 var self = this, 806 tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 807 conditionsElem = tableWrapper.find('.stbConditionsData'), 808 conditionsList = conditionsElem.data('conditions'); 809 810 if (typeof conditionsList == 'undefined' || conditionsList.length == 0) { 811 return; 812 } 813 var cells = $table.data('responsive-mode') == 2 ? tableWrapper.find('.dataTables_scrollHead th, .dataTables_scrollFoot th, .dataTables_scrollBody td') : tableWrapper.find('th, td'); 814 815 if (!this.Editor.Conditions) { 816 this.initConditions(conditionsElem); 817 } 818 cells.each(function () { 819 self.applyConditionsToCell(this, conditionsList, tableWrapper, reinit); 820 }); 821 if (!reinit) { 822 $table.bind('column-visibility.dt draw.dt', function (e) { 823 var tableWrapper = $table.parents('.supsystic-tables-wrap:first'), 824 cells = $table.data('responsive-mode') == 2 ? tableWrapper.find('.dataTables_scrollHead th, .dataTables_scrollFoot th, .dataTables_scrollBody td') : tableWrapper.find('th, td'); 825 826 cells.each(function () { 827 self.applyConditionsToCell(this, conditionsList, tableWrapper); 828 }); 829 }); 830 } 831 }; 832 833 vendor[appName].applyConditionsToCell = function (cell, conditionsList, tableWrapper, reinit) { 834 cell = cell instanceof jQuery ? cell : $(cell); 835 reinit = reinit ? reinit : false; 836 837 var conditions = this.Editor.Conditions; 838 839 if (reinit) { 840 conditions.clearElemStyles(cell); 841 this.setStylesToCell(cell); 842 } 843 conditions.setConditionToCell(cell.data('y') - 1, cell.data('x'), cell.data('original-value'), cell, conditionsList, tableWrapper); 844 }; 845 846 vendor[appName].setCollapsibleCell = function ($table) { 847 var self = this, 848 features = $table.data('features'); 849 850 if ($table.has('.collapsibleCell').length && !$table.find('[class*="collapsibleRow_"]').length && toeInArray('paging', features) == -1) { 851 var collapsibleIndex = Math.floor(Math.random() * 99999), 852 collapsibleClass = 'collapsibleRow_' + collapsibleIndex, 853 collapsibleGroupMain = true, 854 hasFixedCols = $table.attr('data-fixed-cols') === 'on' || false, 855 foundTr = hasFixedCols ? $(document).find('tr') : $table.find('tr'); 856 857 foundTr.each(function () { 858 var row = $(this); 859 860 if (row.find('.collapsibleCell').length) { 861 row.addClass(collapsibleClass); 862 if (collapsibleGroupMain) { 863 var curCollapsibleClass = collapsibleClass; 864 row.addClass('collapsibleRowMain'); 865 $(document).on('click', '.' + curCollapsibleClass + '.collapsibleRowMain', function () { 866 var curRow = $(this); 867 868 $(document) 869 .find('.' + curCollapsibleClass + '.collapsibleRowMain') 870 .toggleClass('collapsibleRowOpen'); 871 $(document) 872 .find('.' + curCollapsibleClass + ':not(.collapsibleRowMain)') 873 .toggleClass('collapsibleRowHide'); 874 875 if (curRow.hasClass('collapsibleRowOpen')) { 876 curRow.trigger('collapsible.sup'); 877 } 878 }); 879 collapsibleGroupMain = false; 880 } else { 881 row.addClass('collapsibleRowHide'); 882 } 883 884 /* if merge cells by rows and it is collapsed we need hide next rows also */ 885 var trTds = row.find('td'); 886 trTds.each(function () { 887 var td = $(this); 888 if (parseInt(td.data('rowspan')) > 1) { 889 for (var i = 1, n = parseInt(td.data('rowspan')); i < n; i++) { 890 $table.find('td[data-x="' + parseInt(td.data('x')) + '"][data-y="' + (parseInt(td.data('y')) + i) + '"]').addClass('collapsibleCell'); 891 } 892 } 893 }); 894 } else { 895 collapsibleIndex++; 896 collapsibleClass = 'collapsibleRow_' + collapsibleIndex; 897 collapsibleGroupMain = true; 898 } 899 }); 900 $table.on('search.dt', function (e) { 901 if (g_stbServerSideProcessing) { 902 g_stbServerSideProcessingIsActive = true; 903 } 904 var table = $(this), 905 tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id'); 906 self.applyTableEventClb(self.searchEventPro, 50, tableSelector); 907 }); 908 } 909 }; 910 911 vendor[appName].setCollapsibleRow = function ($table) { 912 var self = this, 913 features = $table.data('features'); 914 915 if ($table.has('.collapsibleRow').length && !$table.find('[class*="collapsibleGroup_"]').length && toeInArray('paging', features) == -1) { 916 var collapsibleIndex = Math.floor(Math.random() * 99999), 917 collapsibleClass = 'collapsibleGroup_' + collapsibleIndex, 918 hasFixedCols = $table.attr('data-fixed-cols') === 'on' || false, 919 foundTr = hasFixedCols ? $(document).find('tr') : $table.find('tr'), 920 currentGroupClass = null, 921 groupState = null; 922 923 foundTr.each(function () { 924 var row = $(this), 925 isCollapsibleHeader = row.find('.collapsibleRow').length, 926 isClosedByDefault = row.find('.collapsibleRowClosed').length; 927 928 if (isCollapsibleHeader) { 929 row.addClass(collapsibleClass).addClass('collapsibleRowMain'); 930 if (!isClosedByDefault) { 931 row.addClass('collapsibleRowOpen'); 932 } 933 934 (function (curCollapsibleClass) { 935 $(document).on('click', '.' + curCollapsibleClass + '.collapsibleRowMain', function () { 936 var curRow = $(this); 937 938 $(document) 939 .find('.' + curCollapsibleClass + '.collapsibleRowMain') 940 .toggleClass('collapsibleRowOpen'); 941 $(document) 942 .find('.' + curCollapsibleClass + ':not(.collapsibleRowMain)') 943 .toggleClass('collapsibleRowHide'); 944 945 if (curRow.hasClass('collapsibleRowOpen')) { 946 curRow.trigger('collapsible.sup'); 947 } 948 }); 949 })(collapsibleClass); 950 951 currentGroupClass = collapsibleClass; 952 groupState = isClosedByDefault ? 'closed' : 'open'; 953 collapsibleIndex++; 954 collapsibleClass = 'collapsibleGroup_' + collapsibleIndex; 955 } else if (groupState !== null && currentGroupClass !== null) { 956 row.addClass(currentGroupClass); 957 if (groupState === 'closed') { 958 row.addClass('collapsibleRowHide'); 959 } 960 } 961 }); 962 963 $table.on('search.dt', function (e) { 964 if (g_stbServerSideProcessing) { 965 g_stbServerSideProcessingIsActive = true; 966 } 967 var table = $(this), 968 tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id'); 969 self.applyTableEventClb(self.searchEventPro, 50, tableSelector); 970 }); 971 } 972 }; 973 974 vendor[appName].searchEventPro = function (tableSelector) { 975 var table = $(tableSelector), 976 searchInput = table.parents('.supsystic-tables-wrap').find('.dataTables_filter input[type="search"]'); 977 978 if (searchInput.length) { 979 if (searchInput.val()) { 980 table.find('.collapsibleRowMain').addClass('collapsibleRowOpen'); 981 table.find('.collapsibleRowHide').addClass('collapsibleSearchMode'); 982 } else { 983 table.find('.collapsibleRowMain').removeClass('collapsibleRowOpen'); 984 table.find('.collapsibleRowHide').removeClass('collapsibleSearchMode'); 985 } 986 } 987 }; 988 989 vendor[appName].drawDiagramsInTable = function (tableSelector) { 990 var table = $(tableSelector), 991 tableWrapper = table.parents('.supsystic-tables-wrap:first'), 992 $diagramsInTable = tableWrapper.find('.supsystic-table-diagram'); 993 994 // search.dt event triggers during first load of table, so drawCharts function may be not existed yet 995 if ($diagramsInTable.length && typeof drawCharts == 'function') { 996 drawCharts($diagramsInTable); 997 } 998 }; 999 1000 vendor[appName].globalPageSearchClb = function (e) { 1001 // Tab, ArrowUp, ArrowLeft, ArrowRight, ArrowDown buttons 1002 if (toeInArray(e.keyCode || e.which, [9, 37, 38, 39, 40]) != -1) return false; 1003 1004 var input = $(this), 1005 value = $.fn.dataTable.util.escapeRegex(input.val()),
1006 tables = vendor[appName].getAllTableInstances(); 1007 1008 if (tables.length) { 1009 for (var i = 0; i < tables.length; i++) { 1010 tables[i].api().search(value, false, false).draw(); 1011 } 1012 } 1013 }; 1014 1015 vendor[appName]._beforeInitializeTable = function ($table) { 1016 this.setCollapsibleRow($table); 1017 // Add collapsible rows 1018 this.setCollapsibleCell($table); 1019 }; 1020 1021 vendor[appName]._beforeShowTable = function ($table) { 1022 var self = this; 1023 1024 // Create tooltip cells 1025 this.setTooltipCell($table); 1026 this.setCollapsibleRow($table); 1027 if (g_stbServerSideProcessing) { 1028 // Add collapsible rows 1029 this.setCollapsibleCell($table); 1030 } 1031 1032 //for empty first collapsible row 1033 $table.find('.collapsibleRowMain').each(function () { 1034 var row = $(this); 1035 if (row.height() < 28) { 1036 row.css('height', parseInt(row.find(':first-child').css('line-height')) + 16 + 'px'); 1037 } 1038 }); 1039 1040 $table.on('column-visibility.dt page.dt search.dt collapsible.sup', function (e) { 1041 // Fix of displaying diagrams in the tables with next features: pagination, Automatic Column Hiding response mode, sorting. 1042 // Fix of displaying diagrams in the tables search results. 1043 if (e.namespace == 'dt' && toeInArray(e.type, ['page', 'search']) && g_stbServerSideProcessing) { 1044 g_stbServerSideProcessingIsActive = true; 1045 } 1046 var table = $(this), 1047 tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id'); 1048 self.applyTableEventClb(self.drawDiagramsInTable, 50, tableSelector); 1049 }); 1050 if (g_stbServerSideProcessing) { 1051 var tableSelector = '#supsystic-table-' + $table.data('view-id') + ' #supsystic-table-' + $table.data('id'); 1052 self.applyTableEventClb(self.drawDiagramsInTable, 50, tableSelector); 1053 } 1054 1055 // Set conditional formatting 1056 this.setConditionalFormatting($table); 1057 }; 1058 1059 vendor[appName].initTablesOnPage = function (id) { 1060 this._initTablesOnPagePro(id); 1061 this._initTablesOnPage(id); 1062 }; 1063 1064 vendor[appName]._initTablesOnPagePro = function (id) { 1065 var oneTable = typeof id != 'undefined', 1066 supsysticTables = $(oneTable ? '#supsystic-table-' + id + ':not(.dataTable)' : '.supsystic-table'), 1067 globalPageSearchInput = $('.supsystic-tables-global-page-search'); 1068 1069 // Set callbacks to table 1070 supsysticTables.each(function () { 1071 var $curTable = $(this), 1072 features = $curTable.data('features'); 1073 1074 $curTable.on('beforeInitializeTable', function () { 1075 if (globalPageSearchInput.length) { 1076 vendor[appName].setExtraConfig('searching', true); 1077 } 1078 vendor[appName]._beforeInitializeTable($curTable); 1079 }); 1080 $curTable.on('beforeShowTable', function () { 1081 vendor[appName]._beforeShowTable($curTable); 1082 if (toeInArray('searching', features) == -1) { 1083 $('#supsystic-table-' + $curTable.data('id') + '_filter').remove(); 1084 } 1085 }); 1086 }); 1087 if (oneTable) return; 1088 1089 // Global Table Search 1090 if (globalPageSearchInput.length) { 1091 var focusOutEvent = (typeof $.browser != 'undefined' && $.browser.msie) || !!navigator.userAgent.match(/Trident\/7\./) ? 'focusout' : 'blur'; 1092 globalPageSearchInput.on(focusOutEvent, function (e) { 1093 vendor[appName].globalPageSearchClb.call(this, e); 1094 }); 1095 globalPageSearchInput.on('keydown', function (e) { 1096 var self = this; 1097 setTimeout(function () { 1098 vendor[appName].globalPageSearchClb.call(self, e); 1099 }, 10); 1100 }); 1101 } 1102 }; 1103})((window.supsystic = window.supsystic || {}), window.jQuery, window);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.