You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

261 lines
8.0 KiB

  1. /**
  2. * Script for the tree management interface
  3. */
  4. var $GUI = jQuery('#plugin_move__tree');
  5. $GUI.show();
  6. jQuery('#plugin_move__treelink').show();
  7. /**
  8. * Checks if the given list item was moved in the tree
  9. *
  10. * Moved elements are highlighted and a title shows where they came from
  11. *
  12. * @param {jQuery} $li
  13. */
  14. var checkForMovement = function ($li) {
  15. // we need to check this LI and all previously moved sub LIs
  16. var $all = $li.add($li.find('li.moved'));
  17. $all.each(function () {
  18. var $this = jQuery(this);
  19. var oldid = $this.data('id');
  20. var newid = determineNewID($this);
  21. if (newid != oldid && !$this.hasClass('created')) {
  22. $this.addClass('moved');
  23. $this.children('div').attr('title', oldid + ' -> ' + newid);
  24. } else {
  25. $this.removeClass('moved');
  26. $this.children('div').attr('title', '');
  27. }
  28. });
  29. };
  30. /**
  31. * Check if the given name is allowed in the given parent
  32. *
  33. * @param {jQuery} $li the edited or moved LI
  34. * @param {jQuery} $parent the (new) parent of the edited or moved LI
  35. * @param {string} name the (new) name to check
  36. * @returns {boolean}
  37. */
  38. var checkNameAllowed = function ($li, $parent, name) {
  39. var ok = true;
  40. $parent.children('li').each(function () {
  41. if (this === $li[0]) return;
  42. var cname = 'type-f';
  43. if ($li.hasClass('type-d')) cname = 'type-d';
  44. var $this = jQuery(this);
  45. if ($this.data('name') == name && $this.hasClass(cname)) ok = false;
  46. });
  47. return ok;
  48. };
  49. /**
  50. * Returns the new ID of a given list item
  51. *
  52. * @param {jQuery} $li
  53. * @returns {string}
  54. */
  55. var determineNewID = function ($li) {
  56. var myname = $li.data('name');
  57. var $parent = $li.parent().closest('li');
  58. if ($parent.length) {
  59. return (determineNewID($parent) + ':' + myname).replace(/^:/, '');
  60. } else {
  61. return myname;
  62. }
  63. };
  64. /**
  65. * Very simplistic cleanID() in JavaScript
  66. *
  67. * Strips out namespaces
  68. *
  69. * @param {string} id
  70. */
  71. var cleanID = function (id) {
  72. if (!id) return '';
  73. id = id.replace(/[!"#$%§&\'()+,/;<=>?@\[\]^`\{|\}~\\;:\/\*]+/g, '_');
  74. id = id.replace(/^_+/, '');
  75. id = id.replace(/_+$/, '');
  76. id = id.toLowerCase();
  77. return id;
  78. };
  79. /**
  80. * Initialize the drag & drop-tree at the given li (must be this).
  81. */
  82. var initTree = function () {
  83. var $li = jQuery(this);
  84. var my_root = $li.closest('.tree_root')[0];
  85. $li.draggable({
  86. revert: true,
  87. revertDuration: 0,
  88. opacity: 0.5,
  89. stop : function(event, ui) {
  90. ui.helper.css({height: "auto", width: "auto"});
  91. }
  92. }).droppable({
  93. tolerance: 'pointer',
  94. greedy: true,
  95. accept : function(draggable) {
  96. return my_root == draggable.closest('.tree_root')[0];
  97. },
  98. drop : function (event, ui) {
  99. var $dropped = ui.draggable;
  100. var $me = jQuery(this);
  101. if ($dropped.children('div.li').children('input').prop('checked')) {
  102. $dropped = $dropped.add(
  103. jQuery(my_root)
  104. .find('input')
  105. .filter(function() {
  106. return jQuery(this).prop('checked');
  107. }).parent().parent()
  108. );
  109. }
  110. if ($me.parents().addBack().is($dropped)) {
  111. return;
  112. }
  113. var insert_child = !($me.hasClass("type-f") || $me.hasClass("closed"));
  114. var $new_parent = insert_child ? $me.children('ul') : $me.parent();
  115. var allowed = true;
  116. $dropped.each(function () {
  117. var $this = jQuery(this);
  118. allowed &= checkNameAllowed($this, $new_parent, $this.data('name'));
  119. });
  120. if (allowed) {
  121. if (insert_child) {
  122. $dropped.prependTo($new_parent);
  123. } else {
  124. $dropped.insertAfter($me);
  125. }
  126. }
  127. checkForMovement($dropped);
  128. }
  129. })
  130. // add title to rename icon
  131. .find('img.rename').attr('title', LANG.plugins.move.renameitem)
  132. .end()
  133. .find('img.add').attr('title', LANG.plugins.move.add);
  134. };
  135. var add_template = '<li class="type-d open created" data-name="%s" data-id="%s"><div class="li"><input type="checkbox"> <a href="%s" class="idx_dir">%s</a><img class="rename" src="' + DOKU_BASE + 'lib/plugins/move/images/rename.png"></div><ul class="tree_list"></ul></li>';
  136. /**
  137. * Attach event listeners to the tree
  138. */
  139. $GUI.find('div.tree_root > ul.tree_list')
  140. .click(function (e) {
  141. var $clicky = jQuery(e.target);
  142. var $li = $clicky.parent().parent();
  143. if ($clicky[0].tagName == 'A' && $li.hasClass('type-d')) { // Click on folder - open and close via AJAX
  144. e.stopPropagation();
  145. if ($li.hasClass('open')) {
  146. $li
  147. .removeClass('open')
  148. .addClass('closed');
  149. } else {
  150. $li
  151. .removeClass('closed')
  152. .addClass('open');
  153. // if had not been loaded before, load via AJAX
  154. if (!$li.find('ul').length) {
  155. var is_media = $li.closest('div.tree_root').hasClass('tree_media') ? 1 : 0;
  156. jQuery.post(
  157. DOKU_BASE + 'lib/exe/ajax.php',
  158. {
  159. call: 'plugin_move_tree',
  160. ns: $clicky.attr('href'),
  161. is_media: is_media
  162. },
  163. function (data) {
  164. $li.append(data);
  165. $li.find('li').each(initTree);
  166. }
  167. );
  168. }
  169. }
  170. e.preventDefault();
  171. } else if ($clicky[0].tagName == 'IMG') { // Click on IMG - do rename
  172. e.stopPropagation();
  173. var $a = $clicky.parent().find('a');
  174. if ($clicky.hasClass('rename')) {
  175. var newname = window.prompt(LANG.plugins.move.renameitem, $li.data('name'));
  176. newname = cleanID(newname);
  177. if (newname) {
  178. if (checkNameAllowed($li, $li.parent(), newname)) {
  179. $li.data('name', newname);
  180. $a.text(newname);
  181. checkForMovement($li);
  182. } else {
  183. alert(LANG.plugins.move.duplicate.replace('%s', newname));
  184. }
  185. }
  186. } else {
  187. var newname = window.prompt(LANG.plugins.move.add);
  188. newname = cleanID(newname);
  189. if (newname) {
  190. if (checkNameAllowed($li, $li.children('ul'), newname)) {
  191. var $new_li = jQuery(add_template.replace(/%s/g, newname));
  192. $li.children('ul').prepend($new_li);
  193. $new_li.each(initTree);
  194. } else {
  195. alert(LANG.plugins.move.duplicate.replace('%s', newname));
  196. }
  197. }
  198. }
  199. e.preventDefault();
  200. }
  201. }).find('li').each(initTree);
  202. /**
  203. * Gather all moves from the trees and put them as JSON into the form before submit
  204. *
  205. * @fixme has some duplicate code
  206. */
  207. jQuery('#plugin_move__tree_execute').submit(function (e) {
  208. var data = [];
  209. $GUI.find('.tree_pages .moved').each(function (idx, el) {
  210. var $el = jQuery(el);
  211. var newid = determineNewID($el);
  212. data[data.length] = {
  213. 'class': $el.hasClass('type-d') ? 'ns' : 'doc',
  214. type: 'page',
  215. src: $el.data('id'),
  216. dst: newid
  217. };
  218. });
  219. $GUI.find('.tree_media .moved').each(function (idx, el) {
  220. var $el = jQuery(el);
  221. var newid = determineNewID($el);
  222. data[data.length] = {
  223. 'class': $el.hasClass('type-d') ? 'ns' : 'doc',
  224. type: 'media',
  225. src: $el.data('id'),
  226. dst: newid
  227. };
  228. });
  229. jQuery(this).find('input[name=json]').val(JSON.stringify(data));
  230. });