patch_commit_b4b346b8a5fb.patch 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. diff --git a/images/bullet_move.png b/images/bullet_move.png
  2. new file mode 100644
  3. index 0000000000000000000000000000000000000000..45f869428fd24f50acd6a16be70bf04a9f014e08
  4. Binary files /dev/null and b/images/bullet_move.png differ
  5. diff --git a/term_reference_tree.css b/term_reference_tree.css
  6. index 40ba2cfbe530fa873c2fd7809636b9201eeb2623..5b72ebbfe96c05ff9ea680bf4105ec880c3d7370 100644
  7. --- a/term_reference_tree.css
  8. +++ b/term_reference_tree.css
  9. @@ -94,6 +94,37 @@
  10. background-position: middle left;
  11. }
  12. +.term-reference-tree-track-list.order-list li.track-item {
  13. + padding-left:0;
  14. +}
  15. +
  16. +.term-reference-tree-track-list.order-list li.track-item:hover {
  17. + color:#000;
  18. + background-image: none;
  19. +}
  20. +
  21. +.term-reference-tree-track-list.order-list .term-reference-tree-button-move, .term-reference-tree-track-list.order-list .term-reference-tree-button-delete{
  22. + display:inline-block; vertical-align:middle; zoom:1;
  23. + width:16px; height:16px;
  24. + background-repeat: no-repeat;
  25. + background-position: bottom center;
  26. + margin:0 5px;
  27. +}
  28. +
  29. +
  30. +.term-reference-tree-track-list.order-list li.track-item .term-reference-tree-button-move{
  31. + background-image: url("images/bullet_move.png");
  32. +}
  33. +.term-reference-tree-track-list.order-list li.track-item .term-reference-tree-button-move:hover{
  34. + cursor:move;
  35. +}
  36. +.term-reference-tree-track-list.order-list li.track-item .term-reference-tree-button-delete{
  37. + background-image: url("images/bullet_delete.png"); float:right;
  38. +}
  39. +.term-reference-tree-track-list.order-list li.track-item .term-reference-tree-button-:hover{
  40. + cursor:pointer;
  41. +}
  42. +
  43. .term-reference-tree-track-list li.term_ref_tree_nothing_message {
  44. list-style-type: none;
  45. list-style-image: none;
  46. diff --git a/term_reference_tree.js b/term_reference_tree.js
  47. index 319312f2dd0626ef4545bc66e3310f0467a8fb9e..23e742b3ed68653a749ebbabd0b7e7bbb71af887 100644
  48. --- a/term_reference_tree.js
  49. +++ b/term_reference_tree.js
  50. @@ -28,7 +28,26 @@
  51. //currently selected items to it.
  52. if($(this).hasClass('term-reference-tree-track-list-shown')) {
  53. var track_list_container = $(this).find('.term-reference-tree-track-list');
  54. -
  55. + var tracklist_is_orderable = track_list_container.is('.order-list');
  56. + if(tracklist_is_orderable){
  57. + track_list_container.sortable({
  58. + update: function(event, ui) {
  59. + console.log('sort update : event', event);
  60. + console.log('sort update : ui', ui);
  61. +
  62. + $.each(event.target.children, function(index, val) {
  63. + var $item = $(val),
  64. + // event.target = ul.list
  65. + // ui.item = li.track-item
  66. + control_id = $item.data('control_id'),
  67. + $hiddenInput = $('#'+control_id).parent('.form-item').next('input[type=hidden]');
  68. + // $hiddenInput.attr('value', $item.index());
  69. + $hiddenInput.val($item.index());
  70. + });
  71. + },
  72. + });
  73. + }
  74. +
  75. //Var to track whether using checkboxes or radio buttons.
  76. var input_type =
  77. ( $(this).has('input[type=checkbox]').size() > 0 ) ? 'checkbox' : 'radio';
  78. @@ -40,14 +59,22 @@
  79. var labels = checked_controls.next();
  80. var label_element;
  81. + //get delta
  82. + if(tracklist_is_orderable){
  83. + var weights = checked_controls.parent('.form-item').next('input[type=hidden]');
  84. + }
  85. +
  86. //For each label of the checked boxes, add item to the track list.
  87. labels.each(function(index) {
  88. label_element = $(labels[index]);
  89. + delta = tracklist_is_orderable ? $(weights[index]).val() : -1;
  90. +
  91. addItemToTrackList(
  92. track_list_container, //Where to add new item.
  93. label_element.html(), //Text of new item.
  94. $(label_element).attr('for'), //Id of control new item is for.
  95. - input_type //checkbox or radio
  96. + input_type, //checkbox or radio
  97. + delta //delta
  98. );
  99. }); //End labels.each
  100. @@ -62,10 +89,14 @@
  101. //Remove the "nothing selected" message if showing - add it later if needed.
  102. //removeNothingSelectedMessage(track_list_container);
  103. var event_target = $(event.target);
  104. - var control_id = event_target.data('control_id');
  105. -
  106. - if(control_id) {
  107. - event_target.remove();
  108. + var event_parent_list = event_target.parent('li');
  109. + var control_id = event_parent_list.data('control_id');
  110. + // console.log('event', event);
  111. + // console.log('event_target.parent("li")', event_target.parent('li'));
  112. + // console.log('control_id', control_id);
  113. + // console.log('event_target.is(term-reference-tree-delete)', event_target.is('term-reference-tree-delete'));
  114. + if(event_target.is('.term-reference-tree-button-delete') && control_id) {
  115. + event_parent_list.remove();
  116. var checkbox = $('#' + control_id);
  117. checkbox.removeAttr('checked');
  118. @@ -89,7 +120,8 @@
  119. track_list_container, //Where to add new item.
  120. label_element.html(), //Text of new item.
  121. $(label_element).attr('for'), //Id of control new item is for.
  122. - input_type //checkbox or radio
  123. + input_type, //checkbox or radio
  124. + -1 // delta
  125. );
  126. }
  127. else {
  128. @@ -144,8 +176,9 @@
  129. *
  130. * @param control_type Control type - 'checkbox' or 'radio'.
  131. */
  132. - function addItemToTrackList(track_list_container, item_text, control_id, control_type) {
  133. - var new_item = $('<li class="track-item">' + item_text + '</li>');
  134. + function addItemToTrackList(track_list_container, item_text, control_id, control_type, delta) {
  135. + console.log('addItemToTrackList');
  136. + var new_item = $('<li class="track-item" delta="'+ delta +'"><div class="term-reference-tree-button-move"></div>' + item_text + '<div class="term-reference-tree-button-delete"></div></li>');
  137. new_item.data('control_id', control_id);
  138. //Add an id for easy finding of the item.
  139. @@ -173,35 +206,66 @@
  140. }
  141. return;
  142. }
  143. -
  144. - //Using checkboxes, so there can be more than one selected item.
  145. - //Find the right place to put the new item, to match the order of the
  146. - //checkboxes.
  147. +
  148. + //Using checkboxes, so there can be more than one selected item.
  149. + //Find the right place to put the new item,
  150. + // to match the order of the checkboxes.
  151. + // OR order of delta
  152. var list_items = track_list_container.find('li');
  153. var item_comparing_to;
  154. -
  155. +
  156. //Flag to tell whether the item was inserted.
  157. var inserted_flag = false;
  158. - list_items.each(function(index){
  159. - item_comparing_to = $(list_items[index]);
  160. +
  161. + if(!track_list_container.is('.order-list')){
  162. +
  163. + list_items.each(function(index){
  164. + item_comparing_to = $(list_items[index]);
  165. - //If item is already on the track list, do nothing.
  166. - if ( control_id == item_comparing_to.data('control_id') ) {
  167. - inserted_flag = true;
  168. - return false; //Returning false stops the loop.
  169. - }
  170. - else if ( control_id < item_comparing_to.data('control_id') ) {
  171. - //Add it here.
  172. - item_comparing_to.before(new_item);
  173. - inserted_flag = true;
  174. - return false; //Returning false stops the loop.
  175. - }
  176. - });
  177. + //If item is already on the track list, do nothing.
  178. + if ( control_id == item_comparing_to.data('control_id') ) {
  179. + inserted_flag = true;
  180. + return false; //Returning false stops the loop.
  181. + }
  182. + else if ( control_id < item_comparing_to.data('control_id') ) {
  183. + //Add it here.
  184. + item_comparing_to.before(new_item);
  185. + inserted_flag = true;
  186. + return false; //Returning false stops the loop.
  187. + }
  188. + });
  189. - //If not inserted yet, add new item at the end of the track list.
  190. - if ( ! inserted_flag ) {
  191. - track_list_container.append(new_item);
  192. - }
  193. + //If not inserted yet, add new item at the end of the track list.
  194. + if ( ! inserted_flag ) {
  195. + track_list_container.append(new_item);
  196. + }
  197. +
  198. + }else{
  199. + if( ! track_list_container.find('#'+new_item.attr('id')).size() ){
  200. +
  201. + if(delta == -1){
  202. + track_list_container.append(new_item);
  203. + inserted_flag = true;
  204. + }else{
  205. + list_items.each(function(index){
  206. + item_comparing_to = $(this);
  207. + if ( delta < item_comparing_to.attr('delta') ) {
  208. + //Add it here.
  209. + item_comparing_to.before(new_item);
  210. + inserted_flag = true;
  211. + return false; //Returning false stops the loop.
  212. + }
  213. + });
  214. + //If not inserted yet, add new item at the end of the track list.
  215. + if ( ! inserted_flag )
  216. + track_list_container.append(new_item);
  217. +
  218. + }
  219. +
  220. + track_list_container.sortable('refresh');
  221. + }
  222. + }
  223. +
  224. }
  225. /**
  226. @@ -246,7 +310,7 @@
  227. // This helper function checks if the maximum number of choices is already selected.
  228. // If so, it disables all the other options. If not, it enables them.
  229. - function checkMaxChoices(item, checkbox) {
  230. + function checkMaxChoices(item, checkbox, order_list) {
  231. var maxChoices = -1;
  232. try {
  233. maxChoices = parseInt(Drupal.settings.term_reference_tree.trees[item.attr('id')]['max_choices']);
  234. diff --git a/term_reference_tree.module b/term_reference_tree.module
  235. index 1aea8b531d81c88ea58f3a1bcd05443483ab19a2..4346ed47a589bd32c68d2982bcd3ff80f82160c6 100644
  236. --- a/term_reference_tree.module
  237. +++ b/term_reference_tree.module
  238. @@ -33,7 +33,7 @@ function term_reference_tree_element_info() {
  239. '#input' => false,
  240. '#theme' => array('checkbox_tree_track_list'),
  241. '#pre_render' => array('form_pre_render_conditional_form_element'),
  242. - ),
  243. + )
  244. );
  245. return $types;
  246. @@ -183,6 +183,7 @@ function _term_reference_tree_flatten($element, &$form_state) {
  247. $children = element_children($element);
  248. foreach($children as $c) {
  249. $child = $element[$c];
  250. + // dsm($child, '$child');
  251. if (array_key_exists('#type', $child) && ($child['#type'] == 'radio' || $child['#type'] == 'checkbox')) {
  252. $output[] = $child;
  253. }
  254. diff --git a/term_reference_tree.widget.inc b/term_reference_tree.widget.inc
  255. index 8bae7a1fb46632d924d2625b9897235506b7da0f..1d4f6b758387564850b55ed9f9d56a185fdacf1c 100644
  256. --- a/term_reference_tree.widget.inc
  257. +++ b/term_reference_tree.widget.inc
  258. @@ -19,6 +19,7 @@ function term_reference_tree_field_widget_info() {
  259. 'select_parents' => 0,
  260. 'cascading_selection' => 0,
  261. 'track_list' => 0,
  262. + 'track_list_order' => 0,
  263. 'token_display' => '',
  264. 'parent_term_id' => '',
  265. 'max_depth' => '',
  266. @@ -171,7 +172,18 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
  267. '#default_value' => $settings['track_list'],
  268. '#return_value' => 1,
  269. );
  270. +
  271. + $form['track_list_order'] = array(
  272. + '#type' => 'checkbox',
  273. + '#title' => t('Track list drag and drop order'),
  274. + '#description' => t(
  275. + 'Allow drag and drop selected terms ordering on tracklist.'),
  276. + '#default_value' => $settings['track_list_order'],
  277. + '#return_value' => 1,
  278. + '#element_validate' => array('_term_reference_tree_track_list_order_validate'),
  279. + );
  280. +
  281. $form['max_depth'] = array(
  282. '#type' => 'textfield',
  283. '#title' => t('Maximum Depth'),
  284. @@ -251,6 +263,18 @@ function _term_reference_tree_cascading_selection_validate($element, &$form_stat
  285. }
  286. }
  287. +function _term_reference_tree_track_list_order_validate($element, &$form_state){
  288. + if ($form_state['values']['instance']['widget']['settings']['track_list'] == 0 && $form_state['values']['instance']['widget']['settings']['track_list_order'] == 1) {
  289. + // This is pretty wonky syntax for the field name in form_set_error, but it's
  290. + // correct.
  291. + form_set_error('field][track_list_order', t('You must enable Track List if Track List Order is enabled.'));
  292. + }
  293. + /*
  294. + TODO check if number of values is diffrent from 1
  295. + */
  296. +}
  297. +
  298. +
  299. /**
  300. * Process the checkbox_tree widget.
  301. *
  302. @@ -310,6 +334,7 @@ function term_reference_tree_process_checkbox_tree($element, $form_state) {
  303. $element[] = array(
  304. '#type' => 'checkbox_tree_track_list',
  305. '#max_choices' => $max_choices,
  306. + '#track_list_order' => $element['#track_list_order'],
  307. );
  308. }
  309. }
  310. @@ -443,7 +468,8 @@ function theme_checkbox_tree_label($variables) {
  311. function theme_checkbox_tree_track_list($variables) {
  312. //Should the label be singular or plural? Depends on cardinality of term field.
  313. static $nothingselected;
  314. -
  315. + // dsm($variables, 'theme_checkbox_tree_track_list : $variables');
  316. +
  317. if(!$nothingselected) {
  318. $nothingselected = t('[Nothing selected]');
  319. //Add the "Nothing selected" text. To style it, replace it with whatever you want.
  320. @@ -459,17 +485,17 @@ function theme_checkbox_tree_track_list($variables) {
  321. 'Selected item (click the item to uncheck it)',
  322. 'Selected items (click an item to uncheck it)'
  323. );
  324. + $order = $variables['element']['#track_list_order'] ? 'order-list' : '';
  325. $output =
  326. '<div class="term-reference-track-list-container">
  327. <div class="term-reference-track-list-label">' . $label . '</div>
  328. - <ul class="term-reference-tree-track-list"><li class="term_ref_tree_nothing_message">'.$nothingselected.'</li></ul>
  329. + <ul class="term-reference-tree-track-list '.$order.'"><li class="term_ref_tree_nothing_message">'.$nothingselected.'</li></ul>
  330. </div>';
  331. return $output;
  332. }
  333. -
  334. /**
  335. * Implements hook_widget_field_form().
  336. */
  337. @@ -512,6 +538,7 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
  338. $element['#select_parents'] = $settings['select_parents'];
  339. $element['#cascading_selection'] = $settings['cascading_selection'];
  340. $element['#track_list'] = $settings['track_list'];
  341. + $element['#track_list_order'] = $settings['track_list_order'];
  342. $element['#parent_tid'] = $settings['parent_term_id'] || $field['settings']['allowed_values'][0]['parent'];
  343. $element['#vocabulary'] = $voc->vid;
  344. $element['#token_display'] = module_exists('token') ? $settings['token_display'] : '';
  345. @@ -523,7 +550,11 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
  346. '#element_validate' => array('_term_reference_tree_widget_validate'),
  347. '#properties' => $properties,
  348. );
  349. -
  350. +
  351. + if ($settings['track_list_order']) {
  352. + drupal_add_library('system', 'ui.sortable');
  353. + }
  354. +
  355. return $element;
  356. }
  357. @@ -544,25 +575,58 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
  358. * The validated element.
  359. */
  360. function _term_reference_tree_widget_validate(&$element, &$form_state) {
  361. + dsm($element, '_term_reference_tree_widget_validate | $element');
  362. $items = _term_reference_tree_flatten($element, $form_state);
  363. + dsm($items, '$items');
  364. $value = array();
  365. if ($element['#max_choices'] != 1) {
  366. - foreach($items as $child) {
  367. - if (array_key_exists('#value', $child) && $child['#value'] !== 0) {
  368. - array_push($value, array($element['#value_key'] => $child['#value']));
  369. -
  370. - // If the element is leaves only and select parents is on, then automatically
  371. - // add all the parents of each selected value.
  372. - if ($element['#select_parents'] && $element['#leaves_only']) {
  373. - foreach($child['#parent_values'] as $parent_tid) {
  374. - if (!in_array(array($element['#value_key'] => $parent_tid), $value)) {
  375. - array_push($value, array($element['#value_key'] => $parent_tid));
  376. - }
  377. - }
  378. - }
  379. - }
  380. - }
  381. + if(!$element['#track_list_order']){
  382. + foreach($items as $child) {
  383. + if (array_key_exists('#value', $child) && $child['#value'] !== 0) {
  384. + array_push($value, array( $element['#value_key'] => $child['#value']));
  385. +
  386. + // If the element is leaves only and select parents is on, then automatically
  387. + // add all the parents of each selected value.
  388. + if ($element['#select_parents'] && $element['#leaves_only']) {
  389. + foreach($child['#parent_values'] as $parent_tid) {
  390. + if (!in_array(array($element['#value_key'] => $parent_tid), $value)) {
  391. + array_push($value, array($element['#value_key'] => $parent_tid));
  392. + }
  393. + }
  394. + }
  395. +
  396. + }
  397. + }
  398. +
  399. + }else{
  400. + $selected_terms = array();
  401. + foreach($items as $child) {
  402. + if (array_key_exists('#value', $child) && $child['#value'] !== 0) {
  403. + $delta = $form_state['input'][$child['#value'].'-weight'];
  404. + $selected_terms[$delta] = array($element['#value_key'] => $child['#value']);
  405. +
  406. + // If the element is leaves only and select parents is on, then automatically
  407. + // add all the parents of each selected value.
  408. + if ($element['#select_parents'] && $element['#leaves_only']) {
  409. + foreach($child['#parent_values'] as $parent_tid) {
  410. + if (!in_array(array($element['#value_key'] => $parent_tid), $selected_terms)) {
  411. + $delta = $form_state['input'][$parent_tid.'-weight'];
  412. + $selected_terms[$delta] = array($element['#value_key'] => $parent_tid);
  413. + }
  414. + }
  415. + }
  416. +
  417. + }
  418. + }
  419. + // reorder items
  420. + ksort($selected_terms);
  421. + // record in value
  422. + foreach ($selected_terms as $delta => $term) {
  423. + $value[] = $term;
  424. + }
  425. +
  426. + }
  427. }
  428. else {
  429. // If it's a tree of radio buttons, they all have the same value, so we can just
  430. @@ -575,6 +639,8 @@ function _term_reference_tree_widget_validate(&$element, &$form_state) {
  431. }
  432. }
  433. + dsm($value, '$value');
  434. +
  435. if ($element['#required'] && empty($value)) {
  436. // The title is already check_plained so it's appropriate to use !.
  437. form_error($element, t('!name field is required.', array('!name' => $element['#title'])));
  438. @@ -701,7 +767,23 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
  439. $parents_for_id = array_merge($element['#parents'], array($term->tid));
  440. $e['#id'] = drupal_html_id('edit-' . implode('-', $parents_for_id));
  441. $e['#parents'] = $element['#parents'];
  442. - }
  443. + }else if($element['#track_list_order']){
  444. + $delta = 0;
  445. + $i = -1;
  446. + if(isset($value[$term->tid])){
  447. + foreach ($value as $tid) {
  448. + $i++;
  449. + if($term->tid == $tid)
  450. + break;
  451. + }
  452. + }
  453. +
  454. + $e_weight = array(
  455. + '#type' => 'hidden',
  456. + '#value' => $i,
  457. + '#name' => $term->tid.'-weight',
  458. + );
  459. + }
  460. }
  461. else {
  462. $e = array(
  463. @@ -710,9 +792,12 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
  464. );
  465. }
  466. -
  467. $container[$term->tid] = $e;
  468. + if(isset($e_weight)){
  469. + $container[$term->tid.'-weight'] = $e_weight;
  470. + }
  471. +
  472. if (($depth + 1 <= $element['#max_depth'] || !$element['#max_depth']) && property_exists($term, 'children') && count($term->children) > 0) {
  473. $parents = $parent_tids;
  474. $parents[] = $term->tid;