0

A newbie question here.

How can I select a range of li so I can moved them inside new element?

For example:

<ul>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
  <li>test</li>
</ul>

To be like this:

<ul>
  <li>
    <div class="column1">
      <ul>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
      </ul>
    </div>
  </li>
  <li>
    <div class="column2">
      <ul>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
        <li>test</li>
      </ul>
    </div>
  </li>
</ul>

So far I tried using Jquery:

(function ($) {
  Drupal.behaviors.menu = {
    attach: function (context, settings) {

    $('#navigation ul li.expanded').hover(function() {
      $(this).find('ul').css('display', 'block');
    }, function() {
      $(this).find('ul').css('display', 'none');
    });

    var $lists = $('#navigation li.expanded ul.menu'); 

    // Loop through all target lists.
    $lists.each(function(i, e) {
      var $list = $(e);

      //These are temporary variables.
      var $new_list = $('<ul>');
      var $list_item, $sub_list, $sub_set;

      // The number of items per column.
      var per_column = 6;

      // Calculate the amount of columns needed.
      var n = Math.ceil($list.find('li').length / per_column);

      // Loop through all columns.
      for (var i = 0; i < n; ++i) {
        // Creates the sub list for the current column.
        $sub_list = $('<ul>');

        // Gets the first set of list items from the original list and adds them to the sub list created above.
        $sub_set = $list.find('li').slice(0, per_column).appendTo($sub_list);

        // Creates a new list item and adds the sub list to it.
        $list_item = $('<li>').append($sub_list);

        // Add the newly created list item to the new list.
        $new_list.append($list_item);

        // Create a div with the class 'columnX' and wrap the sub list with it.
        $sub_list.wrap('<div class="column' + (i + 1) + '"></div>');
      }

      // Replace the original list with the new one.
      $list.html($new_list.html());
    }); 

  };
})(jQuery);

The above approach generates "enter image description here

But I'm having difficulty in manipulating elements via Jquery or JS. Any thoughts will be appreciated. Thanks

  • Where is this menu visible? If you're showing this for regular visitors you should consider manipulating the structure with php due to a possible FOUC. – hampusn Sep 10 '12 at 8:37
1

This can be optimized but you should atleast get the gist of it :)

See a fiddle here: http://jsfiddle.net/XQAde/2/
Revised fiddle from new spec can be found here: http://jsfiddle.net/XQAde/3/

$(function() {
  // This is the list selector you want to manipulate.
  var $lists = $('.expanded .menu');

  // Loop through all target lists.
  $lists.each(function(i, e) {
    var $list = $(e);

    //These are temporary variables.
    var $new_list = $('<ul>');
    var $list_item, $sub_list, $sub_set;

    // The number of items per column.
    var per_column = 6;

    // Calculate the amount of columns needed.
    var n = Math.ceil($list.find('li').length / per_column);

    // Loop through all columns.
    for (var i = 0; i < n; ++i) {
    // Creates the sub list for the current column.
    $sub_list = $('<ul>');

    // Gets the first set of list items from the original list and adds them to the sub list created above.
    $sub_set = $list.find('li').slice(0, per_column).appendTo($sub_list);

    // Creates a new list item and adds the sub list to it.
    $list_item = $('<li>').append($sub_list);

    // Add the newly created list item to the new list.
    $new_list.append($list_item);

    // Create a div with the class 'columnX' and wrap the sub list with it.
    $sub_list.wrap('<div class="column' + (i + 1) + '"></div>');
    }

    // Replace the original list with the new one.
    $list.html($new_list.html());
  });

});
  • Hi hampusn..tried your script but it mixed all the subitems from other parent with submenu. – user8012 Sep 10 '12 at 9:59
  • Here is my original markup - pastebin.com/EcibzDhY – user8012 Sep 10 '12 at 10:01
  • And this is thew result of the above script - pastebin.com/XLmyciiE – user8012 Sep 10 '12 at 10:03
  • You'll have to specify select only the list you want to manipulate. Try changing the $('#target-list') to $('.menu .menu'). You might also have to run that code for each sub menu instead. Can you show what result you expect from the original markup you linked to? – hampusn Sep 10 '12 at 10:18
  • Hi hampusn...here how it should look like - pastebin.com/adbWxT7A – user8012 Sep 10 '12 at 22:59
1

I am not completely sure I understand what you are trying to do - I am assuming the html is some kind of Drupal menu you are trying to add some kind of dropdown/flyout action to?

I am not sure whether you want to be doing all this DOM manipulation on mouseover/mouseout either? At least I think that's what you are doing from looking at that code snippet.

Taking your html example at face value, this bit of javascript should do the job of splitting it out into 'columns':

var $list = $('ul'),
    $items = $('li', $list),
    column_counter = 1,
    $current_list,
    items_to_column=6;

$items.each(function(index,item){
  if (index%items_to_column==0){
    var new_column = $("<li><div class='column"+column_counter+"'><ul></ul></div></li>").appendTo($list);
    $current_list = $('ul', new_column);        
    column_counter ++;
  }
  $current_list.append( $(item).detach());
});
  • Hi Andrew...yeah this is a Drupal menu I would like to manipulate. I'm thinking if it is possible to manipulate then on load when the menu items are greater than 5, so I can avoid mouseenter/mouseout which is a bit expensive I guess. – user8012 Sep 10 '12 at 7:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.