Без опису
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /**
  2. * DataTables Basic
  3. */
  4. 'use strict';
  5. let fv, offCanvasEl;
  6. document.addEventListener('DOMContentLoaded', function (e) {
  7. (function () {
  8. const formAddNewRecord = document.getElementById('form-add-new-record');
  9. setTimeout(() => {
  10. const newRecord = document.querySelector('.create-new'),
  11. offCanvasElement = document.querySelector('#add-new-record');
  12. // To open offCanvas, to add new record
  13. if (newRecord) {
  14. newRecord.addEventListener('click', function () {
  15. offCanvasEl = new bootstrap.Offcanvas(offCanvasElement);
  16. // Empty fields on offCanvas open
  17. (offCanvasElement.querySelector('.dt-full-name').value = ''),
  18. (offCanvasElement.querySelector('.dt-post').value = ''),
  19. (offCanvasElement.querySelector('.dt-email').value = ''),
  20. (offCanvasElement.querySelector('.dt-date').value = ''),
  21. (offCanvasElement.querySelector('.dt-salary').value = '');
  22. // Open offCanvas with form
  23. offCanvasEl.show();
  24. });
  25. }
  26. }, 200);
  27. // Form validation for Add new record
  28. fv = FormValidation.formValidation(formAddNewRecord, {
  29. fields: {
  30. basicFullname: {
  31. validators: {
  32. notEmpty: {
  33. message: 'The name is required'
  34. }
  35. }
  36. },
  37. basicPost: {
  38. validators: {
  39. notEmpty: {
  40. message: 'Post field is required'
  41. }
  42. }
  43. },
  44. basicEmail: {
  45. validators: {
  46. notEmpty: {
  47. message: 'The Email is required'
  48. },
  49. emailAddress: {
  50. message: 'The value is not a valid email address'
  51. }
  52. }
  53. },
  54. basicDate: {
  55. validators: {
  56. notEmpty: {
  57. message: 'Joining Date is required'
  58. },
  59. date: {
  60. format: 'MM/DD/YYYY',
  61. message: 'The value is not a valid date'
  62. }
  63. }
  64. },
  65. basicSalary: {
  66. validators: {
  67. notEmpty: {
  68. message: 'Basic Salary is required'
  69. }
  70. }
  71. }
  72. },
  73. plugins: {
  74. trigger: new FormValidation.plugins.Trigger(),
  75. bootstrap5: new FormValidation.plugins.Bootstrap5({
  76. // Use this for enabling/changing valid/invalid class
  77. // eleInvalidClass: '',
  78. eleValidClass: '',
  79. rowSelector: '.form-control-validation'
  80. }),
  81. submitButton: new FormValidation.plugins.SubmitButton(),
  82. // defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
  83. autoFocus: new FormValidation.plugins.AutoFocus()
  84. },
  85. init: instance => {
  86. instance.on('plugins.message.placed', function (e) {
  87. if (e.element.parentElement.classList.contains('input-group')) {
  88. e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
  89. }
  90. });
  91. }
  92. });
  93. // FlatPickr Initialization & Validation
  94. const flatpickrDate = document.querySelector('[name="basicDate"]');
  95. if (flatpickrDate) {
  96. flatpickrDate.flatpickr({
  97. enableTime: false,
  98. monthSelectorType: 'static',
  99. static: true,
  100. // See https://flatpickr.js.org/formatting/
  101. dateFormat: 'm/d/Y',
  102. // After selecting a date, we need to revalidate the field
  103. onChange: function () {
  104. fv.revalidateField('basicDate');
  105. }
  106. });
  107. }
  108. })();
  109. // init function
  110. const dt_basic_table = document.querySelector('.datatables-basic');
  111. let dt_basic;
  112. if (dt_basic_table) {
  113. let tableTitle = document.createElement('h5');
  114. tableTitle.classList.add('card-title', 'mb-0', 'text-md-start', 'text-center');
  115. tableTitle.innerHTML = 'DataTable with Buttons';
  116. dt_basic = new DataTable(dt_basic_table, {
  117. ajax: assetsPath + 'json/table-datatable.json',
  118. columns: [
  119. { data: 'id' },
  120. { data: 'id', orderable: false, render: DataTable.render.select() },
  121. { data: 'id' },
  122. { data: 'full_name' },
  123. { data: 'email' },
  124. { data: 'start_date' },
  125. { data: 'salary' },
  126. { data: 'status' },
  127. { data: 'id' }
  128. ],
  129. columnDefs: [
  130. {
  131. // For Responsive
  132. className: 'control',
  133. orderable: false,
  134. searchable: false,
  135. responsivePriority: 2,
  136. targets: 0,
  137. render: function (data, type, full, meta) {
  138. return '';
  139. }
  140. },
  141. {
  142. // For Checkboxes
  143. targets: 1,
  144. orderable: false,
  145. searchable: false,
  146. responsivePriority: 3,
  147. checkboxes: true,
  148. render: function () {
  149. return '<input type="checkbox" class="dt-checkboxes form-check-input">';
  150. },
  151. checkboxes: {
  152. selectAllRender: '<input type="checkbox" class="form-check-input">'
  153. }
  154. },
  155. {
  156. targets: 2,
  157. searchable: false,
  158. visible: false
  159. },
  160. {
  161. // Avatar image/badge, Name and post
  162. targets: 3,
  163. responsivePriority: 4,
  164. render: function (data, type, full, meta) {
  165. const userImg = full['avatar'];
  166. const name = full['full_name'];
  167. const post = full['post'];
  168. let output;
  169. if (userImg) {
  170. // For Avatar image
  171. output = `<img src="${assetsPath}img/avatars/${userImg}" alt="Avatar" class="rounded-circle">`;
  172. } else {
  173. // For Avatar badge
  174. const stateNum = Math.floor(Math.random() * 6);
  175. const states = ['success', 'danger', 'warning', 'info', 'dark', 'primary', 'secondary'];
  176. const state = states[stateNum];
  177. let initials = name.match(/\b\w/g) || [];
  178. initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
  179. output = `<span class="avatar-initial rounded-circle bg-label-${state}">${initials}</span>`;
  180. }
  181. // Creates full output for row
  182. const rowOutput = `
  183. <div class="d-flex justify-content-start align-items-center user-name">
  184. <div class="avatar-wrapper">
  185. <div class="avatar me-2">
  186. ${output}
  187. </div>
  188. </div>
  189. <div class="d-flex flex-column">
  190. <span class="emp_name text-truncate text-heading">${name}</span>
  191. <small class="emp_post text-truncate">${post}</small>
  192. </div>
  193. </div>
  194. `;
  195. return rowOutput;
  196. }
  197. },
  198. {
  199. responsivePriority: 1,
  200. targets: 4
  201. },
  202. {
  203. // Label
  204. targets: -2,
  205. render: function (data, type, full, meta) {
  206. const statusNumber = full.status;
  207. const statuses = {
  208. 1: { title: 'Current', class: 'bg-label-primary' },
  209. 2: { title: 'Professional', class: 'bg-label-success' },
  210. 3: { title: 'Rejected', class: 'bg-label-danger' },
  211. 4: { title: 'Resigned', class: 'bg-label-warning' },
  212. 5: { title: 'Applied', class: 'bg-label-info' }
  213. };
  214. if (typeof statuses[statusNumber] === 'undefined') {
  215. return data;
  216. }
  217. return `
  218. <span class="badge ${statuses[statusNumber].class}">
  219. ${statuses[statusNumber].title}
  220. </span>
  221. `;
  222. }
  223. },
  224. {
  225. // Actions
  226. targets: -1,
  227. title: 'Actions',
  228. orderable: false,
  229. searchable: false,
  230. className: 'd-flex align-items-center',
  231. render: function (data, type, full, meta) {
  232. return (
  233. '<div class="d-inline-block">' +
  234. '<a href="javascript:;" class="btn btn-icon dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="icon-base bx bx-dots-vertical-rounded"></i></a>' +
  235. '<ul class="dropdown-menu dropdown-menu-end m-0">' +
  236. '<li><a href="javascript:;" class="dropdown-item">Details</a></li>' +
  237. '<li><a href="javascript:;" class="dropdown-item">Archive</a></li>' +
  238. '<div class="dropdown-divider"></div>' +
  239. '<li><a href="javascript:;" class="dropdown-item text-danger delete-record">Delete</a></li>' +
  240. '</ul>' +
  241. '</div>' +
  242. '<a href="javascript:;" class="btn btn-icon item-edit"><i class="icon-base bx bx-edit icon-sm"></i></a>'
  243. );
  244. }
  245. }
  246. ],
  247. select: {
  248. style: 'multi',
  249. selector: 'td:nth-child(2)'
  250. },
  251. order: [[2, 'desc']],
  252. layout: {
  253. top2Start: {
  254. rowClass: 'row card-header flex-column flex-md-row pb-0',
  255. features: [tableTitle]
  256. },
  257. top2End: {
  258. features: [
  259. {
  260. buttons: [
  261. {
  262. extend: 'collection',
  263. className: 'btn btn-label-primary dropdown-toggle me-4',
  264. text: '<span class="d-flex align-items-center gap-2"><i class="icon-base bx bx-export me-sm-1"></i> <span class="d-none d-sm-inline-block">Export</span></span>',
  265. buttons: [
  266. {
  267. extend: 'print',
  268. text: `<span class="d-flex align-items-center"><i class="icon-base bx bx-printer me-1"></i>Print</span>`,
  269. className: 'dropdown-item',
  270. exportOptions: {
  271. columns: [3, 4, 5, 6, 7],
  272. format: {
  273. body: function (inner, coldex, rowdex) {
  274. if (inner.length <= 0) return inner;
  275. // Check if inner is HTML content
  276. if (inner.indexOf('<') > -1) {
  277. const parser = new DOMParser();
  278. const doc = parser.parseFromString(inner, 'text/html');
  279. // Get all text content
  280. let text = '';
  281. // Handle specific elements
  282. const userNameElements = doc.querySelectorAll('.user-name');
  283. if (userNameElements.length > 0) {
  284. userNameElements.forEach(el => {
  285. // Get text from nested structure
  286. const nameText =
  287. el.querySelector('.fw-medium')?.textContent ||
  288. el.querySelector('.d-block')?.textContent ||
  289. el.textContent;
  290. text += nameText.trim() + ' ';
  291. });
  292. } else {
  293. // Get regular text content
  294. text = doc.body.textContent || doc.body.innerText;
  295. }
  296. return text.trim();
  297. }
  298. return inner;
  299. }
  300. }
  301. },
  302. customize: function (win) {
  303. win.document.body.style.color = config.colors.headingColor;
  304. win.document.body.style.borderColor = config.colors.borderColor;
  305. win.document.body.style.backgroundColor = config.colors.bodyBg;
  306. const table = win.document.body.querySelector('table');
  307. table.classList.add('compact');
  308. table.style.color = 'inherit';
  309. table.style.borderColor = 'inherit';
  310. table.style.backgroundColor = 'inherit';
  311. }
  312. },
  313. {
  314. extend: 'csv',
  315. text: `<span class="d-flex align-items-center"><i class="icon-base bx bx-file me-1"></i>Csv</span>`,
  316. className: 'dropdown-item',
  317. exportOptions: {
  318. columns: [3, 4, 5, 6, 7],
  319. format: {
  320. body: function (inner, coldex, rowdex) {
  321. if (inner.length <= 0) return inner;
  322. // Parse HTML content
  323. const parser = new DOMParser();
  324. const doc = parser.parseFromString(inner, 'text/html');
  325. let text = '';
  326. // Handle user-name elements specifically
  327. const userNameElements = doc.querySelectorAll('.user-name');
  328. if (userNameElements.length > 0) {
  329. userNameElements.forEach(el => {
  330. // Get text from nested structure - try different selectors
  331. const nameText =
  332. el.querySelector('.fw-medium')?.textContent ||
  333. el.querySelector('.d-block')?.textContent ||
  334. el.textContent;
  335. text += nameText.trim() + ' ';
  336. });
  337. } else {
  338. // Handle other elements (status, role, etc)
  339. text = doc.body.textContent || doc.body.innerText;
  340. }
  341. return text.trim();
  342. }
  343. }
  344. }
  345. },
  346. {
  347. extend: 'excel',
  348. text: `<span class="d-flex align-items-center"><i class="icon-base bx bxs-file-export me-1"></i>Excel</span>`,
  349. className: 'dropdown-item',
  350. exportOptions: {
  351. columns: [3, 4, 5, 6, 7],
  352. format: {
  353. body: function (inner, coldex, rowdex) {
  354. if (inner.length <= 0) return inner;
  355. // Parse HTML content
  356. const parser = new DOMParser();
  357. const doc = parser.parseFromString(inner, 'text/html');
  358. let text = '';
  359. // Handle user-name elements specifically
  360. const userNameElements = doc.querySelectorAll('.user-name');
  361. if (userNameElements.length > 0) {
  362. userNameElements.forEach(el => {
  363. // Get text from nested structure - try different selectors
  364. const nameText =
  365. el.querySelector('.fw-medium')?.textContent ||
  366. el.querySelector('.d-block')?.textContent ||
  367. el.textContent;
  368. text += nameText.trim() + ' ';
  369. });
  370. } else {
  371. // Handle other elements (status, role, etc)
  372. text = doc.body.textContent || doc.body.innerText;
  373. }
  374. return text.trim();
  375. }
  376. }
  377. }
  378. },
  379. {
  380. extend: 'pdf',
  381. text: `<span class="d-flex align-items-center"><i class="icon-base bx bxs-file-pdf me-1"></i>Pdf</span>`,
  382. className: 'dropdown-item',
  383. exportOptions: {
  384. columns: [3, 4, 5, 6, 7],
  385. format: {
  386. body: function (inner, coldex, rowdex) {
  387. if (inner.length <= 0) return inner;
  388. // Parse HTML content
  389. const parser = new DOMParser();
  390. const doc = parser.parseFromString(inner, 'text/html');
  391. let text = '';
  392. // Handle user-name elements specifically
  393. const userNameElements = doc.querySelectorAll('.user-name');
  394. if (userNameElements.length > 0) {
  395. userNameElements.forEach(el => {
  396. // Get text from nested structure - try different selectors
  397. const nameText =
  398. el.querySelector('.fw-medium')?.textContent ||
  399. el.querySelector('.d-block')?.textContent ||
  400. el.textContent;
  401. text += nameText.trim() + ' ';
  402. });
  403. } else {
  404. // Handle other elements (status, role, etc)
  405. text = doc.body.textContent || doc.body.innerText;
  406. }
  407. return text.trim();
  408. }
  409. }
  410. }
  411. },
  412. {
  413. extend: 'copy',
  414. text: `<i class="icon-base bx bx-copy me-1"></i>Copy`,
  415. className: 'dropdown-item',
  416. exportOptions: {
  417. columns: [3, 4, 5, 6, 7],
  418. format: {
  419. body: function (inner, coldex, rowdex) {
  420. if (inner.length <= 0) return inner;
  421. // Parse HTML content
  422. const parser = new DOMParser();
  423. const doc = parser.parseFromString(inner, 'text/html');
  424. let text = '';
  425. // Handle user-name elements specifically
  426. const userNameElements = doc.querySelectorAll('.user-name');
  427. if (userNameElements.length > 0) {
  428. userNameElements.forEach(el => {
  429. // Get text from nested structure - try different selectors
  430. const nameText =
  431. el.querySelector('.fw-medium')?.textContent ||
  432. el.querySelector('.d-block')?.textContent ||
  433. el.textContent;
  434. text += nameText.trim() + ' ';
  435. });
  436. } else {
  437. // Handle other elements (status, role, etc)
  438. text = doc.body.textContent || doc.body.innerText;
  439. }
  440. return text.trim();
  441. }
  442. }
  443. }
  444. }
  445. ]
  446. },
  447. {
  448. text: '<span class="d-flex align-items-center gap-2"><i class="icon-base bx bx-plus icon-sm"></i> <span class="d-none d-sm-inline-block">Add New Record</span></span>',
  449. className: 'create-new btn btn-primary'
  450. }
  451. ]
  452. }
  453. ]
  454. },
  455. topStart: {
  456. rowClass: 'row m-3 my-0 justify-content-between',
  457. features: [
  458. {
  459. pageLength: {
  460. menu: [10, 25, 50, 100],
  461. text: 'Show_MENU_entries'
  462. }
  463. }
  464. ]
  465. },
  466. topEnd: {
  467. search: {
  468. placeholder: ''
  469. }
  470. },
  471. bottomStart: {
  472. rowClass: 'row mx-3 justify-content-between',
  473. features: ['info']
  474. },
  475. bottomEnd: 'paging'
  476. },
  477. language: {
  478. paginate: {
  479. next: '<i class="icon-base bx bx-chevron-right scaleX-n1-rtl icon-18px"></i>',
  480. previous: '<i class="icon-base bx bx-chevron-left scaleX-n1-rtl icon-18px"></i>',
  481. first: '<i class="icon-base bx bx-chevrons-left scaleX-n1-rtl icon-18px"></i>',
  482. last: '<i class="icon-base bx bx-chevrons-right scaleX-n1-rtl icon-18px"></i>'
  483. }
  484. },
  485. responsive: {
  486. details: {
  487. display: DataTable.Responsive.display.modal({
  488. header: function (row) {
  489. const data = row.data();
  490. return 'Details of ' + data['full_name'];
  491. }
  492. }),
  493. type: 'column',
  494. renderer: function (api, rowIdx, columns) {
  495. const data = columns
  496. .map(function (col) {
  497. return col.title !== '' // Do not show row in modal popup if title is blank (for check box)
  498. ? `<tr data-dt-row="${col.rowIndex}" data-dt-column="${col.columnIndex}">
  499. <td>${col.title}:</td>
  500. <td>${col.data}</td>
  501. </tr>`
  502. : '';
  503. })
  504. .join('');
  505. if (data) {
  506. const div = document.createElement('div');
  507. div.classList.add('table-responsive');
  508. const table = document.createElement('table');
  509. div.appendChild(table);
  510. table.classList.add('table');
  511. table.classList.add('datatables-basic');
  512. const tbody = document.createElement('tbody');
  513. tbody.innerHTML = data;
  514. table.appendChild(tbody);
  515. return div;
  516. }
  517. return false;
  518. }
  519. }
  520. }
  521. });
  522. // Add New record
  523. // ? Remove/Update this code as per your requirements
  524. var count = 101;
  525. // On form submit, if form is valid
  526. fv.on('core.form.valid', function () {
  527. let new_name = document.querySelector('.add-new-record .dt-full-name').value,
  528. new_post = document.querySelector('.add-new-record .dt-post').value,
  529. new_email = document.querySelector('.add-new-record .dt-email').value,
  530. new_date = document.querySelector('.add-new-record .dt-date').value,
  531. new_salary = document.querySelector('.add-new-record .dt-salary').value;
  532. if (new_name != '') {
  533. dt_basic.row
  534. .add({
  535. id: count,
  536. full_name: new_name,
  537. post: new_post,
  538. email: new_email,
  539. start_date: new_date,
  540. salary: '$' + new_salary,
  541. status: 5
  542. })
  543. .draw();
  544. count++;
  545. // Hide offcanvas using javascript method
  546. offCanvasEl.hide();
  547. }
  548. });
  549. //? The 'delete-record' class is necessary for the functionality of the following code.
  550. document.addEventListener('click', function (e) {
  551. if (e.target.classList.contains('delete-record')) {
  552. dt_basic.row(e.target.closest('tr')).remove().draw();
  553. const modalEl = document.querySelector('.dtr-bs-modal');
  554. if (modalEl && modalEl.classList.contains('show')) {
  555. const modal = bootstrap.Modal.getInstance(modalEl);
  556. modal?.hide();
  557. }
  558. }
  559. });
  560. }
  561. // Complex Header DataTable
  562. const dt_complex_header_table = document.querySelector('.dt-complex-header');
  563. let dt_complex;
  564. if (dt_complex_header_table) {
  565. dt_complex = new DataTable(dt_complex_header_table, {
  566. ajax: assetsPath + 'json/table-datatable.json',
  567. columns: [
  568. { data: 'full_name' },
  569. { data: 'email' },
  570. { data: 'city' },
  571. { data: 'post' },
  572. { data: 'salary' },
  573. { data: 'status' },
  574. { data: '' }
  575. ],
  576. columnDefs: [
  577. {
  578. // Label
  579. targets: -2,
  580. render: function (data, type, full, meta) {
  581. const statusNumber = full.status;
  582. const statuses = {
  583. 1: { title: 'Current', class: 'bg-label-primary' },
  584. 2: { title: 'Professional', class: 'bg-label-success' },
  585. 3: { title: 'Rejected', class: 'bg-label-danger' },
  586. 4: { title: 'Resigned', class: 'bg-label-warning' },
  587. 5: { title: 'Applied', class: 'bg-label-info' }
  588. };
  589. if (typeof statuses[statusNumber] === 'undefined') {
  590. return data;
  591. }
  592. return `
  593. <span class="badge ${statuses[statusNumber].class}">
  594. ${statuses[statusNumber].title}
  595. </span>
  596. `;
  597. }
  598. },
  599. {
  600. // Actions
  601. targets: -1,
  602. title: 'Actions',
  603. orderable: false,
  604. searchable: false,
  605. render: function (data, type, full, meta) {
  606. return (
  607. '<div class="d-inline-block">' +
  608. '<a href="javascript:;" class="btn btn-icon dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="icon-base bx bx-dots-vertical-rounded"></i></a>' +
  609. '<ul class="dropdown-menu dropdown-menu-end m-0">' +
  610. '<li><a href="javascript:;" class="dropdown-item">Details</a></li>' +
  611. '<li><a href="javascript:;" class="dropdown-item">Archive</a></li>' +
  612. '<div class="dropdown-divider"></div>' +
  613. '<li><a href="javascript:;" class="dropdown-item text-danger delete-record">Delete</a></li>' +
  614. '</ul>' +
  615. '</div>' +
  616. '<a href="javascript:;" class="btn btn-icon item-edit"><i class="icon-base bx bx-edit icon-sm"></i></a>'
  617. );
  618. }
  619. }
  620. ],
  621. order: [[2, 'desc']],
  622. layout: {
  623. topStart: {
  624. rowClass: 'row mx-3 my-0 justify-content-between',
  625. features: [
  626. {
  627. pageLength: {
  628. menu: [7, 10, 25, 50, 100],
  629. text: 'Show_MENU_entries'
  630. }
  631. }
  632. ]
  633. },
  634. topEnd: {
  635. search: {
  636. placeholder: ''
  637. }
  638. },
  639. bottomStart: {
  640. rowClass: 'row mx-3 justify-content-between',
  641. features: ['info']
  642. },
  643. bottomEnd: 'paging'
  644. },
  645. displayLength: 7,
  646. language: {
  647. paginate: {
  648. next: '<i class="icon-base bx bx-chevron-right scaleX-n1-rtl icon-18px"></i>',
  649. previous: '<i class="icon-base bx bx-chevron-left scaleX-n1-rtl icon-18px"></i>',
  650. first: '<i class="icon-base bx bx-chevrons-left scaleX-n1-rtl icon-18px"></i>',
  651. last: '<i class="icon-base bx bx-chevrons-right scaleX-n1-rtl icon-18px"></i>'
  652. }
  653. }
  654. });
  655. //? The 'delete-record' class is necessary for the functionality of the following code.
  656. document.addEventListener('click', function (e) {
  657. if (e.target.classList.contains('delete-record')) {
  658. dt_complex.row(e.target.closest('tr')).remove().draw();
  659. const modalEl = document.querySelector('.dtr-bs-modal');
  660. if (modalEl && modalEl.classList.contains('show')) {
  661. const modal = bootstrap.Modal.getInstance(modalEl);
  662. modal?.hide();
  663. }
  664. }
  665. });
  666. }
  667. // Row Grouping DataTable
  668. const dt_row_grouping_table = document.querySelector('.dt-row-grouping');
  669. let dt_row_grouping,
  670. groupColumn = 2;
  671. if (dt_row_grouping_table) {
  672. dt_row_grouping = new DataTable(dt_row_grouping_table, {
  673. ajax: assetsPath + 'json/table-datatable.json',
  674. columns: [
  675. { data: 'id' },
  676. { data: 'full_name' },
  677. { data: 'post' },
  678. { data: 'email' },
  679. { data: 'city' },
  680. { data: 'start_date' },
  681. { data: 'salary' },
  682. { data: 'status' },
  683. { data: '' }
  684. ],
  685. columnDefs: [
  686. {
  687. // For Responsive
  688. className: 'control',
  689. orderable: false,
  690. targets: 0,
  691. searchable: false,
  692. render: function (data, type, full, meta) {
  693. return '';
  694. }
  695. },
  696. { visible: false, targets: groupColumn },
  697. {
  698. // Label
  699. targets: -2,
  700. render: function (data, type, full, meta) {
  701. const statusNumber = full.status;
  702. const statuses = {
  703. 1: { title: 'Current', class: 'bg-label-primary' },
  704. 2: { title: 'Professional', class: 'bg-label-success' },
  705. 3: { title: 'Rejected', class: 'bg-label-danger' },
  706. 4: { title: 'Resigned', class: 'bg-label-warning' },
  707. 5: { title: 'Applied', class: 'bg-label-info' }
  708. };
  709. if (typeof statuses[statusNumber] === 'undefined') {
  710. return data;
  711. }
  712. return `
  713. <span class="badge ${statuses[statusNumber].class}">
  714. ${statuses[statusNumber].title}
  715. </span>
  716. `;
  717. }
  718. },
  719. {
  720. // Actions
  721. targets: -1,
  722. title: 'Actions',
  723. orderable: false,
  724. searchable: false,
  725. className: 'd-flex align-items-center',
  726. render: function (data, type, full, meta) {
  727. return (
  728. '<div class="d-inline-block">' +
  729. '<a href="javascript:;" class="btn btn-icon dropdown-toggle hide-arrow me-1" data-bs-toggle="dropdown"><i class="bx bx-dots-vertical-rounded icon-base"></i></a>' +
  730. '<div class="dropdown-menu dropdown-menu-end m-0">' +
  731. '<a href="javascript:;" class="dropdown-item">Details</a>' +
  732. '<a href="javascript:;" class="dropdown-item">Archive</a>' +
  733. '<div class="dropdown-divider"></div>' +
  734. '<a href="javascript:;" class="dropdown-item text-danger delete-record">Delete</a>' +
  735. '</div>' +
  736. '</div>' +
  737. '<a href="javascript:;" class="btn btn-icon item-edit"><i class="icon-base bx bx-edit icon-sm"></i></a>'
  738. );
  739. }
  740. }
  741. ],
  742. layout: {
  743. topStart: {
  744. rowClass: 'row mx-3 my-0 justify-content-between',
  745. features: [
  746. {
  747. pageLength: {
  748. menu: [7, 10, 25, 50, 100],
  749. text: 'Show_MENU_entries'
  750. }
  751. }
  752. ]
  753. },
  754. topEnd: {
  755. search: {
  756. placeholder: ''
  757. }
  758. },
  759. bottomStart: {
  760. rowClass: 'row mx-3 justify-content-between',
  761. features: ['info']
  762. },
  763. bottomEnd: 'paging'
  764. },
  765. order: [[groupColumn, 'asc']],
  766. displayLength: 7,
  767. language: {
  768. paginate: {
  769. next: '<i class="icon-base bx bx-chevron-right scaleX-n1-rtl icon-18px"></i>',
  770. previous: '<i class="icon-base bx bx-chevron-left scaleX-n1-rtl icon-18px"></i>',
  771. first: '<i class="icon-base bx bx-chevrons-left scaleX-n1-rtl icon-18px"></i>',
  772. last: '<i class="icon-base bx bx-chevrons-right scaleX-n1-rtl icon-18px"></i>'
  773. }
  774. },
  775. drawCallback: function (settings) {
  776. const api = this.api();
  777. const rows = api.rows({ page: 'current' }).nodes();
  778. let last = null;
  779. api
  780. .column(groupColumn, { page: 'current' })
  781. .data()
  782. .each(function (group, i) {
  783. if (last !== group) {
  784. const newRow = document.createElement('tr');
  785. newRow.classList.add('group');
  786. const newCell = document.createElement('td');
  787. newCell.setAttribute('colspan', '8');
  788. newCell.textContent = group;
  789. newRow.appendChild(newCell);
  790. rows[i].parentNode.insertBefore(newRow, rows[i]);
  791. last = group;
  792. }
  793. });
  794. },
  795. responsive: {
  796. details: {
  797. display: DataTable.Responsive.display.modal({
  798. header: function (row) {
  799. var data = row.data();
  800. return 'Details of ' + data['full_name'];
  801. }
  802. }),
  803. type: 'column',
  804. renderer: function (api, rowIdx, columns) {
  805. const data = columns
  806. .map(function (col) {
  807. return col.title !== '' // Do not show row in modal popup if title is blank (for check box)
  808. ? `<tr data-dt-row="${col.rowIndex}" data-dt-column="${col.columnIndex}">
  809. <td>${col.title}:</td>
  810. <td>${col.data}</td>
  811. </tr>`
  812. : '';
  813. })
  814. .join('');
  815. if (data) {
  816. const div = document.createElement('div');
  817. div.classList.add('table-responsive');
  818. const table = document.createElement('table');
  819. div.appendChild(table);
  820. table.classList.add('table');
  821. const tbody = document.createElement('tbody');
  822. tbody.innerHTML = data;
  823. table.appendChild(tbody);
  824. return div;
  825. }
  826. return false;
  827. }
  828. }
  829. }
  830. });
  831. //? The 'delete-record' class is necessary for the functionality of the following code.
  832. document.addEventListener('click', function (e) {
  833. if (e.target.classList.contains('delete-record')) {
  834. dt_row_grouping.row(e.target.closest('tr')).remove().draw();
  835. const modalEl = document.querySelector('.dtr-bs-modal');
  836. if (modalEl && modalEl.classList.contains('show')) {
  837. const modal = bootstrap.Modal.getInstance(modalEl);
  838. modal?.hide();
  839. }
  840. }
  841. });
  842. }
  843. // Multilingual DataTable
  844. const dt_multilingual_table = document.querySelector('.dt-multilingual');
  845. let dt_multilingual,
  846. lang = 'DE';
  847. if (dt_multilingual_table) {
  848. dt_multilingual = new DataTable(dt_multilingual_table, {
  849. ajax: assetsPath + 'json/table-datatable.json',
  850. columns: [
  851. { data: 'id' },
  852. { data: 'full_name' },
  853. { data: 'post' },
  854. { data: 'email' },
  855. { data: 'start_date' },
  856. { data: 'salary' },
  857. { data: 'status' },
  858. { data: '' }
  859. ],
  860. columnDefs: [
  861. {
  862. // For Responsive
  863. className: 'control',
  864. orderable: false,
  865. targets: 0,
  866. searchable: false,
  867. render: function (data, type, full, meta) {
  868. return '';
  869. }
  870. },
  871. {
  872. // Label
  873. targets: -2,
  874. render: function (data, type, full, meta) {
  875. const statusNumber = full.status;
  876. const statuses = {
  877. 1: { title: 'Current', class: 'bg-label-primary' },
  878. 2: { title: 'Professional', class: 'bg-label-success' },
  879. 3: { title: 'Rejected', class: 'bg-label-danger' },
  880. 4: { title: 'Resigned', class: 'bg-label-warning' },
  881. 5: { title: 'Applied', class: 'bg-label-info' }
  882. };
  883. if (typeof statuses[statusNumber] === 'undefined') {
  884. return data;
  885. }
  886. return `
  887. <span class="badge ${statuses[statusNumber].class}">
  888. ${statuses[statusNumber].title}
  889. </span>
  890. `;
  891. }
  892. },
  893. {
  894. // Actions
  895. targets: -1,
  896. title: 'Actions',
  897. orderable: false,
  898. className: '',
  899. searchable: false,
  900. render: function (data, type, full, meta) {
  901. return (
  902. '<div class="d-flex align-items-center">' +
  903. '<div class="d-inline-block">' +
  904. '<a href="javascript:;" class="btn btn-icon dropdown-toggle hide-arrow me-1" data-bs-toggle="dropdown"><i class="icon-base bx bx-dots-vertical-rounded icon-sm"></i></a>' +
  905. '<div class="dropdown-menu dropdown-menu-end m-0">' +
  906. '<a href="javascript:;" class="dropdown-item">Details</a>' +
  907. '<a href="javascript:;" class="dropdown-item">Archive</a>' +
  908. '<div class="dropdown-divider"></div>' +
  909. '<a href="javascript:;" class="dropdown-item text-danger delete-record">Delete</a>' +
  910. '</div>' +
  911. '</div>' +
  912. '<a href="javascript:;" class="btn btn-icon item-edit"><i class="icon-base bx bx-edit icon-sm"></i></a>' +
  913. '</div>'
  914. );
  915. }
  916. }
  917. ],
  918. language: {
  919. url: 'https://cdn.datatables.net/plug-ins/1.11.5/i18n/de-' + lang + '.json',
  920. paginate: {
  921. next: '<i class="icon-base bx bx-chevron-right scaleX-n1-rtl icon-sm"></i>',
  922. previous: '<i class="icon-base bx bx-chevron-left scaleX-n1-rtl icon-sm"></i>'
  923. }
  924. },
  925. order: [[2, 'desc']],
  926. displayLength: 7,
  927. layout: {
  928. topStart: {
  929. rowClass: 'row m-3 justify-content-between',
  930. features: [
  931. {
  932. pageLength: {
  933. menu: [7, 10, 25, 50, 100]
  934. }
  935. }
  936. ]
  937. },
  938. topEnd: {
  939. search: {
  940. placeholder: 'Geben Sie hier die Suche ein'
  941. }
  942. },
  943. bottomStart: {
  944. rowClass: 'row mx-3 justify-content-between',
  945. features: ['info']
  946. },
  947. bottomEnd: 'paging'
  948. },
  949. responsive: {
  950. details: {
  951. display: DataTable.Responsive.display.modal({
  952. header: function (row) {
  953. var data = row.data();
  954. return 'Details of ' + data['full_name'];
  955. }
  956. }),
  957. type: 'column',
  958. renderer: function (api, rowIdx, columns) {
  959. const data = columns
  960. .map(function (col) {
  961. return col.title !== '' // Do not show row in modal popup if title is blank (for check box)
  962. ? `<tr data-dt-row="${col.rowIndex}" data-dt-column="${col.columnIndex}">
  963. <td>${col.title}:</td>
  964. <td>${col.data}</td>
  965. </tr>`
  966. : '';
  967. })
  968. .join('');
  969. if (data) {
  970. const div = document.createElement('div');
  971. div.classList.add('table-responsive');
  972. const table = document.createElement('table');
  973. div.appendChild(table);
  974. table.classList.add('table');
  975. const tbody = document.createElement('tbody');
  976. tbody.innerHTML = data;
  977. table.appendChild(tbody);
  978. return div;
  979. }
  980. return false;
  981. }
  982. }
  983. }
  984. });
  985. //? The 'delete-record' class is necessary for the functionality of the following code.
  986. document.addEventListener('click', function (e) {
  987. if (e.target.classList.contains('delete-record')) {
  988. dt_multilingual.row(e.target.closest('tr')).remove().draw();
  989. const modalEl = document.querySelector('.dtr-bs-modal');
  990. if (modalEl && modalEl.classList.contains('show')) {
  991. const modal = bootstrap.Modal.getInstance(modalEl);
  992. modal?.hide();
  993. }
  994. }
  995. });
  996. }
  997. // Filter form control to default size
  998. // ? setTimeout used for multilingual table initialization
  999. setTimeout(() => {
  1000. const elementsToModify = [
  1001. { selector: '.dt-buttons .btn', classToRemove: 'btn-secondary' },
  1002. { selector: '.dt-search .form-control', classToRemove: 'form-control-sm', classToAdd: 'ms-4' },
  1003. { selector: '.dt-length .form-select', classToRemove: 'form-select-sm' },
  1004. { selector: '.dt-layout-table', classToRemove: 'row mt-2' },
  1005. { selector: '.dt-layout-end', classToAdd: 'mt-0' },
  1006. { selector: '.dt-layout-end .dt-search', classToAdd: 'mt-0 mt-md-6' },
  1007. { selector: '.dt-layout-start', classToAdd: 'mt-0' },
  1008. { selector: '.dt-layout-end .dt-buttons', classToAdd: 'mb-0' },
  1009. { selector: '.dt-layout-full', classToRemove: 'col-md col-12', classToAdd: 'table-responsive' }
  1010. ];
  1011. // Delete record
  1012. elementsToModify.forEach(({ selector, classToRemove, classToAdd }) => {
  1013. document.querySelectorAll(selector).forEach(element => {
  1014. if (classToRemove) {
  1015. classToRemove.split(' ').forEach(className => element.classList.remove(className));
  1016. }
  1017. if (classToAdd) {
  1018. classToAdd.split(' ').forEach(className => element.classList.add(className));
  1019. }
  1020. });
  1021. });
  1022. }, 100);
  1023. });