tabledrag.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. /**
  2. * DO NOT EDIT THIS FILE.
  3. * See the following change record for more information,
  4. * https://www.drupal.org/node/2815083
  5. * @preserve
  6. **/
  7. (function ($, Drupal, drupalSettings) {
  8. var showWeight = JSON.parse(localStorage.getItem('Drupal.tableDrag.showWeight'));
  9. Drupal.behaviors.tableDrag = {
  10. attach: function attach(context, settings) {
  11. function initTableDrag(table, base) {
  12. if (table.length) {
  13. Drupal.tableDrag[base] = new Drupal.tableDrag(table[0], settings.tableDrag[base]);
  14. }
  15. }
  16. for (var base in settings.tableDrag) {
  17. if (settings.tableDrag.hasOwnProperty(base)) {
  18. initTableDrag($(context).find('#' + base).once('tabledrag'), base);
  19. }
  20. }
  21. }
  22. };
  23. Drupal.tableDrag = function (table, tableSettings) {
  24. var self = this;
  25. var $table = $(table);
  26. this.$table = $(table);
  27. this.table = table;
  28. this.tableSettings = tableSettings;
  29. this.dragObject = null;
  30. this.rowObject = null;
  31. this.oldRowElement = null;
  32. this.oldY = 0;
  33. this.changed = false;
  34. this.maxDepth = 0;
  35. this.rtl = $(this.table).css('direction') === 'rtl' ? -1 : 1;
  36. this.striping = $(this.table).data('striping') === 1;
  37. this.scrollSettings = { amount: 4, interval: 50, trigger: 70 };
  38. this.scrollInterval = null;
  39. this.scrollY = 0;
  40. this.windowHeight = 0;
  41. this.indentEnabled = false;
  42. for (var group in tableSettings) {
  43. if (tableSettings.hasOwnProperty(group)) {
  44. for (var n in tableSettings[group]) {
  45. if (tableSettings[group].hasOwnProperty(n)) {
  46. if (tableSettings[group][n].relationship === 'parent') {
  47. this.indentEnabled = true;
  48. }
  49. if (tableSettings[group][n].limit > 0) {
  50. this.maxDepth = tableSettings[group][n].limit;
  51. }
  52. }
  53. }
  54. }
  55. }
  56. if (this.indentEnabled) {
  57. this.indentCount = 1;
  58. var indent = Drupal.theme('tableDragIndentation');
  59. var testRow = $('<tr/>').addClass('draggable').appendTo(table);
  60. var testCell = $('<td/>').appendTo(testRow).prepend(indent).prepend(indent);
  61. var $indentation = testCell.find('.js-indentation');
  62. this.indentAmount = $indentation.get(1).offsetLeft - $indentation.get(0).offsetLeft;
  63. testRow.remove();
  64. }
  65. $table.find('> tr.draggable, > tbody > tr.draggable').each(function () {
  66. self.makeDraggable(this);
  67. });
  68. $table.before($('<button type="button" class="link tabledrag-toggle-weight"></button>').attr('title', Drupal.t('Re-order rows by numerical weight instead of dragging.')).on('click', $.proxy(function (e) {
  69. e.preventDefault();
  70. this.toggleColumns();
  71. }, this)).wrap('<div class="tabledrag-toggle-weight-wrapper"></div>').parent());
  72. self.initColumns();
  73. $(document).on('touchmove', function (event) {
  74. return self.dragRow(event.originalEvent.touches[0], self);
  75. });
  76. $(document).on('touchend', function (event) {
  77. return self.dropRow(event.originalEvent.touches[0], self);
  78. });
  79. $(document).on('mousemove pointermove', function (event) {
  80. return self.dragRow(event, self);
  81. });
  82. $(document).on('mouseup pointerup', function (event) {
  83. return self.dropRow(event, self);
  84. });
  85. $(window).on('storage', $.proxy(function (e) {
  86. if (e.originalEvent.key === 'Drupal.tableDrag.showWeight') {
  87. showWeight = JSON.parse(e.originalEvent.newValue);
  88. this.displayColumns(showWeight);
  89. }
  90. }, this));
  91. };
  92. Drupal.tableDrag.prototype.initColumns = function () {
  93. var $table = this.$table;
  94. var hidden = void 0;
  95. var cell = void 0;
  96. var columnIndex = void 0;
  97. for (var group in this.tableSettings) {
  98. if (this.tableSettings.hasOwnProperty(group)) {
  99. for (var d in this.tableSettings[group]) {
  100. if (this.tableSettings[group].hasOwnProperty(d)) {
  101. var field = $table.find('.' + this.tableSettings[group][d].target).eq(0);
  102. if (field.length && this.tableSettings[group][d].hidden) {
  103. hidden = this.tableSettings[group][d].hidden;
  104. cell = field.closest('td');
  105. break;
  106. }
  107. }
  108. }
  109. if (hidden && cell[0]) {
  110. columnIndex = cell.parent().find('> td').index(cell.get(0)) + 1;
  111. $table.find('> thead > tr, > tbody > tr, > tr').each(this.addColspanClass(columnIndex));
  112. }
  113. }
  114. }
  115. this.displayColumns(showWeight);
  116. };
  117. Drupal.tableDrag.prototype.addColspanClass = function (columnIndex) {
  118. return function () {
  119. var $row = $(this);
  120. var index = columnIndex;
  121. var cells = $row.children();
  122. var cell = void 0;
  123. cells.each(function (n) {
  124. if (n < index && this.colSpan && this.colSpan > 1) {
  125. index -= this.colSpan - 1;
  126. }
  127. });
  128. if (index > 0) {
  129. cell = cells.filter(':nth-child(' + index + ')');
  130. if (cell[0].colSpan && cell[0].colSpan > 1) {
  131. cell.addClass('tabledrag-has-colspan');
  132. } else {
  133. cell.addClass('tabledrag-hide');
  134. }
  135. }
  136. };
  137. };
  138. Drupal.tableDrag.prototype.displayColumns = function (displayWeight) {
  139. if (displayWeight) {
  140. this.showColumns();
  141. } else {
  142. this.hideColumns();
  143. }
  144. $('table').findOnce('tabledrag').trigger('columnschange', !!displayWeight);
  145. };
  146. Drupal.tableDrag.prototype.toggleColumns = function () {
  147. showWeight = !showWeight;
  148. this.displayColumns(showWeight);
  149. if (showWeight) {
  150. localStorage.setItem('Drupal.tableDrag.showWeight', showWeight);
  151. } else {
  152. localStorage.removeItem('Drupal.tableDrag.showWeight');
  153. }
  154. };
  155. Drupal.tableDrag.prototype.hideColumns = function () {
  156. var $tables = $('table').findOnce('tabledrag');
  157. $tables.find('.tabledrag-hide').css('display', 'none');
  158. $tables.find('.tabledrag-handle').css('display', '');
  159. $tables.find('.tabledrag-has-colspan').each(function () {
  160. this.colSpan = this.colSpan - 1;
  161. });
  162. $('.tabledrag-toggle-weight').text(Drupal.t('Show row weights'));
  163. };
  164. Drupal.tableDrag.prototype.showColumns = function () {
  165. var $tables = $('table').findOnce('tabledrag');
  166. $tables.find('.tabledrag-hide').css('display', '');
  167. $tables.find('.tabledrag-handle').css('display', 'none');
  168. $tables.find('.tabledrag-has-colspan').each(function () {
  169. this.colSpan = this.colSpan + 1;
  170. });
  171. $('.tabledrag-toggle-weight').text(Drupal.t('Hide row weights'));
  172. };
  173. Drupal.tableDrag.prototype.rowSettings = function (group, row) {
  174. var field = $(row).find('.' + group);
  175. var tableSettingsGroup = this.tableSettings[group];
  176. for (var delta in tableSettingsGroup) {
  177. if (tableSettingsGroup.hasOwnProperty(delta)) {
  178. var targetClass = tableSettingsGroup[delta].target;
  179. if (field.is('.' + targetClass)) {
  180. var rowSettings = {};
  181. for (var n in tableSettingsGroup[delta]) {
  182. if (tableSettingsGroup[delta].hasOwnProperty(n)) {
  183. rowSettings[n] = tableSettingsGroup[delta][n];
  184. }
  185. }
  186. return rowSettings;
  187. }
  188. }
  189. }
  190. };
  191. Drupal.tableDrag.prototype.makeDraggable = function (item) {
  192. var self = this;
  193. var $item = $(item);
  194. $item.find('td:first-of-type').find('a').addClass('menu-item__link');
  195. var handle = $('<a href="#" class="tabledrag-handle"><div class="handle">&nbsp;</div></a>').attr('title', Drupal.t('Drag to re-order'));
  196. var $indentationLast = $item.find('td:first-of-type').find('.js-indentation').eq(-1);
  197. if ($indentationLast.length) {
  198. $indentationLast.after(handle);
  199. self.indentCount = Math.max($item.find('.js-indentation').length, self.indentCount);
  200. } else {
  201. $item.find('td').eq(0).prepend(handle);
  202. }
  203. handle.on('mousedown touchstart pointerdown', function (event) {
  204. event.preventDefault();
  205. if (event.originalEvent.type === 'touchstart') {
  206. event = event.originalEvent.touches[0];
  207. }
  208. self.dragStart(event, self, item);
  209. });
  210. handle.on('click', function (e) {
  211. e.preventDefault();
  212. });
  213. handle.on('focus', function () {
  214. self.safeBlur = true;
  215. });
  216. handle.on('blur', function (event) {
  217. if (self.rowObject && self.safeBlur) {
  218. self.dropRow(event, self);
  219. }
  220. });
  221. handle.on('keydown', function (event) {
  222. if (event.keyCode !== 9 && !self.rowObject) {
  223. self.rowObject = new self.row(item, 'keyboard', self.indentEnabled, self.maxDepth, true);
  224. }
  225. var keyChange = false;
  226. var groupHeight = void 0;
  227. switch (event.keyCode) {
  228. case 37:
  229. case 63234:
  230. keyChange = true;
  231. self.rowObject.indent(-1 * self.rtl);
  232. break;
  233. case 38:
  234. case 63232:
  235. var $previousRow = $(self.rowObject.element).prev('tr:first-of-type');
  236. var previousRow = $previousRow.get(0);
  237. while (previousRow && $previousRow.is(':hidden')) {
  238. $previousRow = $(previousRow).prev('tr:first-of-type');
  239. previousRow = $previousRow.get(0);
  240. }
  241. if (previousRow) {
  242. self.safeBlur = false;
  243. self.rowObject.direction = 'up';
  244. keyChange = true;
  245. if ($(item).is('.tabledrag-root')) {
  246. groupHeight = 0;
  247. while (previousRow && $previousRow.find('.js-indentation').length) {
  248. $previousRow = $(previousRow).prev('tr:first-of-type');
  249. previousRow = $previousRow.get(0);
  250. groupHeight += $previousRow.is(':hidden') ? 0 : previousRow.offsetHeight;
  251. }
  252. if (previousRow) {
  253. self.rowObject.swap('before', previousRow);
  254. window.scrollBy(0, -groupHeight);
  255. }
  256. } else if (self.table.tBodies[0].rows[0] !== previousRow || $previousRow.is('.draggable')) {
  257. self.rowObject.swap('before', previousRow);
  258. self.rowObject.interval = null;
  259. self.rowObject.indent(0);
  260. window.scrollBy(0, -parseInt(item.offsetHeight, 10));
  261. }
  262. handle.trigger('focus');
  263. }
  264. break;
  265. case 39:
  266. case 63235:
  267. keyChange = true;
  268. self.rowObject.indent(self.rtl);
  269. break;
  270. case 40:
  271. case 63233:
  272. var $nextRow = $(self.rowObject.group).eq(-1).next('tr:first-of-type');
  273. var nextRow = $nextRow.get(0);
  274. while (nextRow && $nextRow.is(':hidden')) {
  275. $nextRow = $(nextRow).next('tr:first-of-type');
  276. nextRow = $nextRow.get(0);
  277. }
  278. if (nextRow) {
  279. self.safeBlur = false;
  280. self.rowObject.direction = 'down';
  281. keyChange = true;
  282. if ($(item).is('.tabledrag-root')) {
  283. groupHeight = 0;
  284. var nextGroup = new self.row(nextRow, 'keyboard', self.indentEnabled, self.maxDepth, false);
  285. if (nextGroup) {
  286. $(nextGroup.group).each(function () {
  287. groupHeight += $(this).is(':hidden') ? 0 : this.offsetHeight;
  288. });
  289. var nextGroupRow = $(nextGroup.group).eq(-1).get(0);
  290. self.rowObject.swap('after', nextGroupRow);
  291. window.scrollBy(0, parseInt(groupHeight, 10));
  292. }
  293. } else {
  294. self.rowObject.swap('after', nextRow);
  295. self.rowObject.interval = null;
  296. self.rowObject.indent(0);
  297. window.scrollBy(0, parseInt(item.offsetHeight, 10));
  298. }
  299. handle.trigger('focus');
  300. }
  301. break;
  302. }
  303. if (self.rowObject && self.rowObject.changed === true) {
  304. $(item).addClass('drag');
  305. if (self.oldRowElement) {
  306. $(self.oldRowElement).removeClass('drag-previous');
  307. }
  308. self.oldRowElement = item;
  309. if (self.striping === true) {
  310. self.restripeTable();
  311. }
  312. self.onDrag();
  313. }
  314. if (keyChange) {
  315. return false;
  316. }
  317. });
  318. handle.on('keypress', function (event) {
  319. switch (event.keyCode) {
  320. case 37:
  321. case 38:
  322. case 39:
  323. case 40:
  324. return false;
  325. }
  326. });
  327. };
  328. Drupal.tableDrag.prototype.dragStart = function (event, self, item) {
  329. self.dragObject = {};
  330. self.dragObject.initOffset = self.getPointerOffset(item, event);
  331. self.dragObject.initPointerCoords = self.pointerCoords(event);
  332. if (self.indentEnabled) {
  333. self.dragObject.indentPointerPos = self.dragObject.initPointerCoords;
  334. }
  335. if (self.rowObject) {
  336. $(self.rowObject.element).find('a.tabledrag-handle').trigger('blur');
  337. }
  338. self.rowObject = new self.row(item, 'pointer', self.indentEnabled, self.maxDepth, true);
  339. self.table.topY = $(self.table).offset().top;
  340. self.table.bottomY = self.table.topY + self.table.offsetHeight;
  341. $(item).addClass('drag');
  342. $('body').addClass('drag');
  343. if (self.oldRowElement) {
  344. $(self.oldRowElement).removeClass('drag-previous');
  345. }
  346. };
  347. Drupal.tableDrag.prototype.dragRow = function (event, self) {
  348. if (self.dragObject) {
  349. self.currentPointerCoords = self.pointerCoords(event);
  350. var y = self.currentPointerCoords.y - self.dragObject.initOffset.y;
  351. var x = self.currentPointerCoords.x - self.dragObject.initOffset.x;
  352. if (y !== self.oldY) {
  353. self.rowObject.direction = y > self.oldY ? 'down' : 'up';
  354. self.oldY = y;
  355. var scrollAmount = self.checkScroll(self.currentPointerCoords.y);
  356. clearInterval(self.scrollInterval);
  357. if (scrollAmount > 0 && self.rowObject.direction === 'down' || scrollAmount < 0 && self.rowObject.direction === 'up') {
  358. self.setScroll(scrollAmount);
  359. }
  360. var currentRow = self.findDropTargetRow(x, y);
  361. if (currentRow) {
  362. if (self.rowObject.direction === 'down') {
  363. self.rowObject.swap('after', currentRow, self);
  364. } else {
  365. self.rowObject.swap('before', currentRow, self);
  366. }
  367. if (self.striping === true) {
  368. self.restripeTable();
  369. }
  370. }
  371. }
  372. if (self.indentEnabled) {
  373. var xDiff = self.currentPointerCoords.x - self.dragObject.indentPointerPos.x;
  374. var indentDiff = Math.round(xDiff / self.indentAmount);
  375. var indentChange = self.rowObject.indent(indentDiff);
  376. self.dragObject.indentPointerPos.x += self.indentAmount * indentChange * self.rtl;
  377. self.indentCount = Math.max(self.indentCount, self.rowObject.indents);
  378. }
  379. return false;
  380. }
  381. };
  382. Drupal.tableDrag.prototype.dropRow = function (event, self) {
  383. var droppedRow = void 0;
  384. var $droppedRow = void 0;
  385. if (self.rowObject !== null) {
  386. droppedRow = self.rowObject.element;
  387. $droppedRow = $(droppedRow);
  388. if (self.rowObject.changed === true) {
  389. self.updateFields(droppedRow);
  390. for (var group in self.tableSettings) {
  391. if (self.tableSettings.hasOwnProperty(group)) {
  392. var rowSettings = self.rowSettings(group, droppedRow);
  393. if (rowSettings.relationship === 'group') {
  394. for (var n in self.rowObject.children) {
  395. if (self.rowObject.children.hasOwnProperty(n)) {
  396. self.updateField(self.rowObject.children[n], group);
  397. }
  398. }
  399. }
  400. }
  401. }
  402. self.rowObject.markChanged();
  403. if (self.changed === false) {
  404. $(Drupal.theme('tableDragChangedWarning')).insertBefore(self.table).hide().fadeIn('slow');
  405. self.changed = true;
  406. }
  407. }
  408. if (self.indentEnabled) {
  409. self.rowObject.removeIndentClasses();
  410. }
  411. if (self.oldRowElement) {
  412. $(self.oldRowElement).removeClass('drag-previous');
  413. }
  414. $droppedRow.removeClass('drag').addClass('drag-previous');
  415. self.oldRowElement = droppedRow;
  416. self.onDrop();
  417. self.rowObject = null;
  418. }
  419. if (self.dragObject !== null) {
  420. self.dragObject = null;
  421. $('body').removeClass('drag');
  422. clearInterval(self.scrollInterval);
  423. }
  424. };
  425. Drupal.tableDrag.prototype.pointerCoords = function (event) {
  426. if (event.pageX || event.pageY) {
  427. return { x: event.pageX, y: event.pageY };
  428. }
  429. return {
  430. x: event.clientX + document.body.scrollLeft - document.body.clientLeft,
  431. y: event.clientY + document.body.scrollTop - document.body.clientTop
  432. };
  433. };
  434. Drupal.tableDrag.prototype.getPointerOffset = function (target, event) {
  435. var docPos = $(target).offset();
  436. var pointerPos = this.pointerCoords(event);
  437. return { x: pointerPos.x - docPos.left, y: pointerPos.y - docPos.top };
  438. };
  439. Drupal.tableDrag.prototype.findDropTargetRow = function (x, y) {
  440. var rows = $(this.table.tBodies[0].rows).not(':hidden');
  441. for (var n = 0; n < rows.length; n++) {
  442. var row = rows[n];
  443. var $row = $(row);
  444. var rowY = $row.offset().top;
  445. var rowHeight;
  446. if (row.offsetHeight === 0) {
  447. rowHeight = parseInt(row.firstChild.offsetHeight, 10) / 2;
  448. } else {
  449. rowHeight = parseInt(row.offsetHeight, 10) / 2;
  450. }
  451. if (y > rowY - rowHeight && y < rowY + rowHeight) {
  452. if (this.indentEnabled) {
  453. for (n in this.rowObject.group) {
  454. if (this.rowObject.group[n] === row) {
  455. return null;
  456. }
  457. }
  458. } else {
  459. if (row === this.rowObject.element) {
  460. return null;
  461. }
  462. }
  463. if (!this.rowObject.isValidSwap(row)) {
  464. return null;
  465. }
  466. while ($row.is(':hidden') && $row.prev('tr').is(':hidden')) {
  467. $row = $row.prev('tr:first-of-type');
  468. row = $row.get(0);
  469. }
  470. return row;
  471. }
  472. }
  473. return null;
  474. };
  475. Drupal.tableDrag.prototype.updateFields = function (changedRow) {
  476. for (var group in this.tableSettings) {
  477. if (this.tableSettings.hasOwnProperty(group)) {
  478. this.updateField(changedRow, group);
  479. }
  480. }
  481. };
  482. Drupal.tableDrag.prototype.updateField = function (changedRow, group) {
  483. var rowSettings = this.rowSettings(group, changedRow);
  484. var $changedRow = $(changedRow);
  485. var sourceRow = void 0;
  486. var $previousRow = void 0;
  487. var previousRow = void 0;
  488. var useSibling = void 0;
  489. if (rowSettings.relationship === 'self' || rowSettings.relationship === 'group') {
  490. sourceRow = changedRow;
  491. } else if (rowSettings.relationship === 'sibling') {
  492. $previousRow = $changedRow.prev('tr:first-of-type');
  493. previousRow = $previousRow.get(0);
  494. var $nextRow = $changedRow.next('tr:first-of-type');
  495. var nextRow = $nextRow.get(0);
  496. sourceRow = changedRow;
  497. if ($previousRow.is('.draggable') && $previousRow.find('.' + group).length) {
  498. if (this.indentEnabled) {
  499. if ($previousRow.find('.js-indentations').length === $changedRow.find('.js-indentations').length) {
  500. sourceRow = previousRow;
  501. }
  502. } else {
  503. sourceRow = previousRow;
  504. }
  505. } else if ($nextRow.is('.draggable') && $nextRow.find('.' + group).length) {
  506. if (this.indentEnabled) {
  507. if ($nextRow.find('.js-indentations').length === $changedRow.find('.js-indentations').length) {
  508. sourceRow = nextRow;
  509. }
  510. } else {
  511. sourceRow = nextRow;
  512. }
  513. }
  514. } else if (rowSettings.relationship === 'parent') {
  515. $previousRow = $changedRow.prev('tr');
  516. previousRow = $previousRow;
  517. while ($previousRow.length && $previousRow.find('.js-indentation').length >= this.rowObject.indents) {
  518. $previousRow = $previousRow.prev('tr');
  519. previousRow = $previousRow;
  520. }
  521. if ($previousRow.length) {
  522. sourceRow = $previousRow.get(0);
  523. } else {
  524. sourceRow = $(this.table).find('tr.draggable:first-of-type').get(0);
  525. if (sourceRow === this.rowObject.element) {
  526. sourceRow = $(this.rowObject.group[this.rowObject.group.length - 1]).next('tr.draggable').get(0);
  527. }
  528. useSibling = true;
  529. }
  530. }
  531. this.copyDragClasses(sourceRow, changedRow, group);
  532. rowSettings = this.rowSettings(group, changedRow);
  533. if (useSibling) {
  534. rowSettings.relationship = 'sibling';
  535. rowSettings.source = rowSettings.target;
  536. }
  537. var targetClass = '.' + rowSettings.target;
  538. var targetElement = $changedRow.find(targetClass).get(0);
  539. if (targetElement) {
  540. var sourceClass = '.' + rowSettings.source;
  541. var sourceElement = $(sourceClass, sourceRow).get(0);
  542. switch (rowSettings.action) {
  543. case 'depth':
  544. targetElement.value = $(sourceElement).closest('tr').find('.js-indentation').length;
  545. break;
  546. case 'match':
  547. targetElement.value = sourceElement.value;
  548. break;
  549. case 'order':
  550. var siblings = this.rowObject.findSiblings(rowSettings);
  551. if ($(targetElement).is('select')) {
  552. var values = [];
  553. $(targetElement).find('option').each(function () {
  554. values.push(this.value);
  555. });
  556. var maxVal = values[values.length - 1];
  557. $(siblings).find(targetClass).each(function () {
  558. if (values.length > 0) {
  559. this.value = values.shift();
  560. } else {
  561. this.value = maxVal;
  562. }
  563. });
  564. } else {
  565. var weight = parseInt($(siblings[0]).find(targetClass).val(), 10) || 0;
  566. $(siblings).find(targetClass).each(function () {
  567. this.value = weight;
  568. weight++;
  569. });
  570. }
  571. break;
  572. }
  573. }
  574. };
  575. Drupal.tableDrag.prototype.copyDragClasses = function (sourceRow, targetRow, group) {
  576. var sourceElement = $(sourceRow).find('.' + group);
  577. var targetElement = $(targetRow).find('.' + group);
  578. if (sourceElement.length && targetElement.length) {
  579. targetElement[0].className = sourceElement[0].className;
  580. }
  581. };
  582. Drupal.tableDrag.prototype.checkScroll = function (cursorY) {
  583. var de = document.documentElement;
  584. var b = document.body;
  585. var windowHeight = this.windowHeight = window.innerHeight || (de.clientHeight && de.clientWidth !== 0 ? de.clientHeight : b.offsetHeight);
  586. var scrollY = void 0;
  587. if (document.all) {
  588. scrollY = this.scrollY = !de.scrollTop ? b.scrollTop : de.scrollTop;
  589. } else {
  590. scrollY = this.scrollY = window.pageYOffset ? window.pageYOffset : window.scrollY;
  591. }
  592. var trigger = this.scrollSettings.trigger;
  593. var delta = 0;
  594. if (cursorY - scrollY > windowHeight - trigger) {
  595. delta = trigger / (windowHeight + scrollY - cursorY);
  596. delta = delta > 0 && delta < trigger ? delta : trigger;
  597. return delta * this.scrollSettings.amount;
  598. } else if (cursorY - scrollY < trigger) {
  599. delta = trigger / (cursorY - scrollY);
  600. delta = delta > 0 && delta < trigger ? delta : trigger;
  601. return -delta * this.scrollSettings.amount;
  602. }
  603. };
  604. Drupal.tableDrag.prototype.setScroll = function (scrollAmount) {
  605. var self = this;
  606. this.scrollInterval = setInterval(function () {
  607. self.checkScroll(self.currentPointerCoords.y);
  608. var aboveTable = self.scrollY > self.table.topY;
  609. var belowTable = self.scrollY + self.windowHeight < self.table.bottomY;
  610. if (scrollAmount > 0 && belowTable || scrollAmount < 0 && aboveTable) {
  611. window.scrollBy(0, scrollAmount);
  612. }
  613. }, this.scrollSettings.interval);
  614. };
  615. Drupal.tableDrag.prototype.restripeTable = function () {
  616. $(this.table).find('> tbody > tr.draggable, > tr.draggable').filter(':visible').filter(':odd').removeClass('odd').addClass('even').end().filter(':even').removeClass('even').addClass('odd');
  617. };
  618. Drupal.tableDrag.prototype.onDrag = function () {
  619. return null;
  620. };
  621. Drupal.tableDrag.prototype.onDrop = function () {
  622. return null;
  623. };
  624. Drupal.tableDrag.prototype.row = function (tableRow, method, indentEnabled, maxDepth, addClasses) {
  625. var $tableRow = $(tableRow);
  626. this.element = tableRow;
  627. this.method = method;
  628. this.group = [tableRow];
  629. this.groupDepth = $tableRow.find('.js-indentation').length;
  630. this.changed = false;
  631. this.table = $tableRow.closest('table')[0];
  632. this.indentEnabled = indentEnabled;
  633. this.maxDepth = maxDepth;
  634. this.direction = '';
  635. if (this.indentEnabled) {
  636. this.indents = $tableRow.find('.js-indentation').length;
  637. this.children = this.findChildren(addClasses);
  638. this.group = $.merge(this.group, this.children);
  639. for (var n = 0; n < this.group.length; n++) {
  640. this.groupDepth = Math.max($(this.group[n]).find('.js-indentation').length, this.groupDepth);
  641. }
  642. }
  643. };
  644. Drupal.tableDrag.prototype.row.prototype.findChildren = function (addClasses) {
  645. var parentIndentation = this.indents;
  646. var currentRow = $(this.element, this.table).next('tr.draggable');
  647. var rows = [];
  648. var child = 0;
  649. function rowIndentation(indentNum, el) {
  650. var self = $(el);
  651. if (child === 1 && indentNum === parentIndentation) {
  652. self.addClass('tree-child-first');
  653. }
  654. if (indentNum === parentIndentation) {
  655. self.addClass('tree-child');
  656. } else if (indentNum > parentIndentation) {
  657. self.addClass('tree-child-horizontal');
  658. }
  659. }
  660. while (currentRow.length) {
  661. if (currentRow.find('.js-indentation').length > parentIndentation) {
  662. child++;
  663. rows.push(currentRow[0]);
  664. if (addClasses) {
  665. currentRow.find('.js-indentation').each(rowIndentation);
  666. }
  667. } else {
  668. break;
  669. }
  670. currentRow = currentRow.next('tr.draggable');
  671. }
  672. if (addClasses && rows.length) {
  673. $(rows[rows.length - 1]).find('.js-indentation:nth-child(' + (parentIndentation + 1) + ')').addClass('tree-child-last');
  674. }
  675. return rows;
  676. };
  677. Drupal.tableDrag.prototype.row.prototype.isValidSwap = function (row) {
  678. var $row = $(row);
  679. if (this.indentEnabled) {
  680. var prevRow = void 0;
  681. var nextRow = void 0;
  682. if (this.direction === 'down') {
  683. prevRow = row;
  684. nextRow = $row.next('tr').get(0);
  685. } else {
  686. prevRow = $row.prev('tr').get(0);
  687. nextRow = row;
  688. }
  689. this.interval = this.validIndentInterval(prevRow, nextRow);
  690. if (this.interval.min > this.interval.max) {
  691. return false;
  692. }
  693. }
  694. if (this.table.tBodies[0].rows[0] === row && $row.is(':not(.draggable)')) {
  695. return false;
  696. }
  697. return true;
  698. };
  699. Drupal.tableDrag.prototype.row.prototype.swap = function (position, row) {
  700. this.group.forEach(function (row) {
  701. Drupal.detachBehaviors(row, drupalSettings, 'move');
  702. });
  703. $(row)[position](this.group);
  704. this.group.forEach(function (row) {
  705. Drupal.attachBehaviors(row, drupalSettings);
  706. });
  707. this.changed = true;
  708. this.onSwap(row);
  709. };
  710. Drupal.tableDrag.prototype.row.prototype.validIndentInterval = function (prevRow, nextRow) {
  711. var $prevRow = $(prevRow);
  712. var minIndent = void 0;
  713. var maxIndent = void 0;
  714. minIndent = nextRow ? $(nextRow).find('.js-indentation').length : 0;
  715. if (!prevRow || $prevRow.is(':not(.draggable)') || $(this.element).is('.tabledrag-root')) {
  716. maxIndent = 0;
  717. } else {
  718. maxIndent = $prevRow.find('.js-indentation').length + ($prevRow.is('.tabledrag-leaf') ? 0 : 1);
  719. if (this.maxDepth) {
  720. maxIndent = Math.min(maxIndent, this.maxDepth - (this.groupDepth - this.indents));
  721. }
  722. }
  723. return { min: minIndent, max: maxIndent };
  724. };
  725. Drupal.tableDrag.prototype.row.prototype.indent = function (indentDiff) {
  726. var $group = $(this.group);
  727. if (!this.interval) {
  728. var prevRow = $(this.element).prev('tr').get(0);
  729. var nextRow = $group.eq(-1).next('tr').get(0);
  730. this.interval = this.validIndentInterval(prevRow, nextRow);
  731. }
  732. var indent = this.indents + indentDiff;
  733. indent = Math.max(indent, this.interval.min);
  734. indent = Math.min(indent, this.interval.max);
  735. indentDiff = indent - this.indents;
  736. for (var n = 1; n <= Math.abs(indentDiff); n++) {
  737. if (indentDiff < 0) {
  738. $group.find('.js-indentation:first-of-type').remove();
  739. this.indents--;
  740. } else {
  741. $group.find('td:first-of-type').prepend(Drupal.theme('tableDragIndentation'));
  742. this.indents++;
  743. }
  744. }
  745. if (indentDiff) {
  746. this.changed = true;
  747. this.groupDepth += indentDiff;
  748. this.onIndent();
  749. }
  750. return indentDiff;
  751. };
  752. Drupal.tableDrag.prototype.row.prototype.findSiblings = function (rowSettings) {
  753. var siblings = [];
  754. var directions = ['prev', 'next'];
  755. var rowIndentation = this.indents;
  756. var checkRowIndentation = void 0;
  757. for (var d = 0; d < directions.length; d++) {
  758. var checkRow = $(this.element)[directions[d]]();
  759. while (checkRow.length) {
  760. if (checkRow.find('.' + rowSettings.target)) {
  761. if (this.indentEnabled) {
  762. checkRowIndentation = checkRow.find('.js-indentation').length;
  763. }
  764. if (!this.indentEnabled || checkRowIndentation === rowIndentation) {
  765. siblings.push(checkRow[0]);
  766. } else if (checkRowIndentation < rowIndentation) {
  767. break;
  768. }
  769. } else {
  770. break;
  771. }
  772. checkRow = checkRow[directions[d]]();
  773. }
  774. if (directions[d] === 'prev') {
  775. siblings.reverse();
  776. siblings.push(this.element);
  777. }
  778. }
  779. return siblings;
  780. };
  781. Drupal.tableDrag.prototype.row.prototype.removeIndentClasses = function () {
  782. for (var n in this.children) {
  783. if (this.children.hasOwnProperty(n)) {
  784. $(this.children[n]).find('.js-indentation').removeClass('tree-child').removeClass('tree-child-first').removeClass('tree-child-last').removeClass('tree-child-horizontal');
  785. }
  786. }
  787. };
  788. Drupal.tableDrag.prototype.row.prototype.markChanged = function () {
  789. var marker = Drupal.theme('tableDragChangedMarker');
  790. var cell = $(this.element).find('td:first-of-type');
  791. if (cell.find('abbr.tabledrag-changed').length === 0) {
  792. cell.append(marker);
  793. }
  794. };
  795. Drupal.tableDrag.prototype.row.prototype.onIndent = function () {
  796. return null;
  797. };
  798. Drupal.tableDrag.prototype.row.prototype.onSwap = function (swappedRow) {
  799. return null;
  800. };
  801. $.extend(Drupal.theme, {
  802. tableDragChangedMarker: function tableDragChangedMarker() {
  803. return '<abbr class="warning tabledrag-changed" title="' + Drupal.t('Changed') + '">*</abbr>';
  804. },
  805. tableDragIndentation: function tableDragIndentation() {
  806. return '<div class="js-indentation indentation">&nbsp;</div>';
  807. },
  808. tableDragChangedWarning: function tableDragChangedWarning() {
  809. return '<div class="tabledrag-changed-warning messages messages--warning" role="alert">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('You have unsaved changes.') + '</div>';
  810. }
  811. });
  812. })(jQuery, Drupal, drupalSettings);