0

Firstly, I cannot access the HTML. It's generated by a system I cannot edit.

I have a list like this:

<ol>
    <li class="odd a one">List Item (type1)</li>
    <li class="even b two">List Item (type1)</li>
    <li class="odd c three">List Item (type1)</li>
    <li class="even d one">List Item (type1)</li>
    <li class="odd a two">List Item (type1)</li>
    <li class="even b three">List Item (type1)</li>
    <li class="odd c one">List Item (type1)</li>
    <li class="even d two">List Item (type2)</li>
    <li class="odd a three">List Item (type2)</li>
    <li class="even b four">List Item (type2)</li>
</ol>

I want to split this list and put a heading in using jQuery like so:

$('li:contains("type2")').first().before('</ol><h2>Type 2 starts here</h2><ol>')

However, the code that results is this (according to Firebug):

<ol>
    <li class="odd a one">List Item (type1)</li>
    <li class="even b two">List Item (type1)</li>
    <li class="odd c three">List Item (type1)</li>
    <li class="even d one">List Item (type1)</li>
    <li class="odd a two">List Item (type1)</li>
    <li class="even b three">List Item (type1)</li>
    <li class="odd c one">List Item (type1)</li>
    <h2>Type 2 starts here</h2>
    <ol></ol>
    <li class="even d two">List Item (type2)</li>
    <li class="odd a three">List Item (type2)</li>
    <li class="even b one">List Item (type2)</li>
</ol>

Is there a way of doing this to generate the following code?:

<ol>
    <li class="odd a one">List Item (type1)</li>
    <li class="even b two">List Item (type1)</li>
    <li class="odd c three">List Item (type1)</li>
    <li class="even d one">List Item (type1)</li>
    <li class="odd a two">List Item (type1)</li>
    <li class="even b three">List Item (type1)</li>
    <li class="odd c one">List Item (type1)</li>
</ol>
<h2>Type 2 starts here</h2>
<ol>
    <li class="even d two">List Item (type2)</li>
    <li class="odd a three">List Item (type2)</li>
    <li class="even b one">List Item (type2)</li>
</ol>

Here's a fiddle for it all: http://jsfiddle.net/a78pT/1/

  • This may be really helpful http://stackoverflow.com/questions/1644668/jquery-split-long-ul-list-in-smaller-lists – Djave Jul 02 '13 at 14:55

4 Answers4

3

Something like this, perhaps?

$(document).ready(function () {
    var type1 = $('li:contains("type1")'),
        type2 = $('li:contains("type2")'),
        ol = $('ol'),
        newOL = $('<ol />')
        h2 = $('<h2 />').text('Type 2 starts here');
    ol.empty().append(type1).parent().append(h2).append(newOL.append(type2));
});

Working demo: http://jsfiddle.net/7U3Me/

pete
  • 24,141
  • 4
  • 37
  • 51
  • It's worth noting that this method will remove any jquery data added to the "li" elements. For example, any events added will be stripped away. – Smeegs Jul 02 '13 at 15:12
1

Try this:

$('li:first').nextUntil('li:contains("type2")').addBack().wrapAll('<ol>');
$('li:contains("type2"):first').nextAll().addBack().wrapAll('<ol>');
$('ol:eq(1)').after('<h2>Type 2 starts here</h2>');
$('li:first').closest('ol').unwrap();

jsFiddle example

This produces the HTML:

  <ol>
    <li class="odd a one">List Item (type1)</li>
    <li class="even b two">List Item (type1)</li>
    <li class="odd c three">List Item (type1)</li>
    <li class="even d one">List Item (type1)</li>
    <li class="odd a two">List Item (type1)</li>
    <li class="even b three">List Item (type1)</li>
    <li class="odd c one">List Item (type1)</li>
</ol>
<h2>Type 2 starts here</h2>
<ol>
    <li class="even d two">List Item (type2)</li>
    <li class="odd a three">List Item (type2)</li>
    <li class="even b four">List Item (type2)</li>
</ol>
j08691
  • 204,283
  • 31
  • 260
  • 272
  • 1
    I like this too. Nice to see all the different methods I was missing(!) –  Jul 02 '13 at 15:06
0

My solution may be a little simpler than @pete's.

$('body').append("<h2>Type 2 starts here</h2>");
$('body').append("<ol class='two'>");
$('li:contains("type2")').appendTo("ol.two");

It'll probably need a little tweaking, but that's the basics.

Demo: http://jsfiddle.net/a78pT/9/

Tim Wasson
  • 3,606
  • 16
  • 16
  • Might be simpler but it also doesn't do what the OP asked for. – j08691 Jul 02 '13 at 15:07
  • Yeah, interesting. I wouldn't want them to appear in both lists but I see where you're heading. Thanks for your answer. –  Jul 02 '13 at 15:09
  • Ooops... I guess I didn't need the `clone()` after all. I've edited the code and the jsfiddle. Sorry to mislead. – Tim Wasson Jul 02 '13 at 15:18
0

You can use detach to remove and reinsert the list items. Then append them all to the parent

http://jsfiddle.net/a78pT/7/

$("ol").parent().append("<h2>Type 2 starts here</h2>");
var newList = $("<ol></ol>");
$(newList).append($('li:contains("type2")').detach());
$("ol").parent().append(newList);
Smeegs
  • 9,151
  • 5
  • 42
  • 78
  • No problem. There is a problem with the accepted answer though. Completely rebuilding the lists removes any previously added functionality. So if an event is attached to any of the list items. That even will longer fire after being rebuilt. for example: http://jsfiddle.net/7U3Me/1/ The click event is no longer in effect. However, using detach protects all functionality for example: http://jsfiddle.net/a78pT/8/ – Smeegs Jul 02 '13 at 15:10
  • Ok, I'll do some experimentation on this as I may need to `addClass()` stuff to the `li`s at some point. Thanks. –  Jul 02 '13 at 15:13
  • Any time, good luck. For reference you should read about detach http://api.jquery.com/detach/ – Smeegs Jul 02 '13 at 15:13