0

My goal is to strip the images and iframes out of WordPress posts (they are in .para divs) and move them to a <ul> above the post, just inside the local wrapper (.wrapper940).

The jQuery below works, but moves ALL image and iframes from all posts to a single new <ul> above the first post. Instead of this, I am trying to move the images and iframes PER POST to a new <ul> just inside the wrapper of each post.

Here's the jQuery:

jQuery("document").ready (function($){
    var matchesEl = $(".para img, .para iframe");
    if ( matchesEl.length > 0) {

    var newUl = $("<ul></ul>");
    newUl.prependTo(matchesEl.parents(".wrapper940"));

    matchesEl.each(function() {

        var newLi = $("<li></li>").append($(this)).appendTo(newUl);

        });

    }   
});

The html is:

<div class="news-item-wrap">
<div class="date">the date</div>
<div class="wrapper940">
    <div class="title">the title</div>
    <div class="para">
        <p>The main content of the post.</p>
        <p>Which could be several paragraphs</p>
        <p>And include iframes...</p>
        <p><iframe src="//www.youtube.com/embed/uGMbZNTym-g" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen">...</iframe>
        </p>
        <p>Followed by more text... and maybe some images....</p>
        <p><a href="http://www.joujouka.org/wp-content/uploads/2014/05/festival-interculture.jpg"><img class="alignnone size-medium wp-image-404" alt="festival intercultural" src="http://www.joujouka.org/wp-content/uploads/2014/05/festival-interculture-213x300.jpg" width="213" height="300"/></a>
        </p>
    </div>
</div>

<div class="news-item-wrap">
<div class="date">the date</div>
<div class="wrapper940">
    <div class="title">the title</div>
    <div class="para">
        <p>A second post would follow like this.</p>
        <p>Which could also be several paragraphs</p>
        <p>And include iframes...</p>
        <p><iframe src="//www.youtube.com/embed/uGMbZNTym-g" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen">...</iframe>
        </p>
        <p>Followed by more text... and maybe some images....</p>
        <p><a href="http://www.joujouka.org/wp-content/uploads/2014/05/festival-interculture.jpg"><img class="alignnone size-medium wp-image-404" alt="festival intercultural" src="http://www.joujouka.org/wp-content/uploads/2014/05/festival-interculture-213x300.jpg" width="213" height="300"/></a>
        </p>
    </div>
</div>

This would continue for as many posts as there were. So I need to be able to move the images and iframes FOR EACH POST to appear just inside the .wrapper940 that wraps EACH POST. (i.e. above the title of each post.)

I think that using .parents() is sending all images and iframes from all posts to the first .wrapper940; .closest() seems like it should work, but doesn't, maybe because it breaks the loop?

Any help very much appreciated!

user2654408
  • 213
  • 2
  • 10

1 Answers1

1

Check this:

jQuery("document").ready (function($){
  var matchesEl = ".para a:has(img), .para iframe"
  $('.wrapper940').each(function(index){

    if ($(this).find(matchesEl).length > 0) {

      $('<ul>').insertBefore($(this).children('.title'));

      $(this).find(matchesEl).each(function() {
        //The line code under will only works if all your .wrappers940 always have at least one matched element.
        //$("<li>").append($(this)).appendTo($('.wrapper940 ul').eq(index));
        //So the right code is:
        $("<li>").append($(this)).appendTo($('.wrapper940').eq(index).children('ul'));
      });

    }
    $('p').filter(function () { return $.trim(this.innerHTML) == "" }).remove();
  });
});

Commenting code:

1) If you want only to move the image, you use .para img, but I think you want to move the element <a> with the <img>, so you can use: .para a:has(img).

2) The index var here $('.wrapper940').each(function(index){ is important to match the right ul in this line: $("<li>").append($(this)).appendTo($('.wrapper940 ul').eq(index));

3) This line will remove blank <p> tags: $('p').filter(function () { return $.trim(this.innerHTML) == "" }).remove(); after you move their content into <li>s

Codepen: http://codepen.io/anon/pen/wDmsi

Answering your questions in comments:

1) The index is the index number of your element matched in each(). The base number is 0. So if you have 10 .wrapper940 in your page, the first one will have index = 0, the second will have index = 1, til the last and 10th will have index = 9. We use it here to force code not send the img and iframes to the wrong .wrapper940. It says img and iframes from .wrapper940 index 6 belongs to .wrapper940 index 6. Writing this I just discovered a fail in my code. Check the code above to see the changes.

2) I always used this for pure javascript and $(this) for jquery. It seems like $(this) have more properties, like we see here: Difference between $(this) and this in jquery but using the $(...) consume more processing. So you can always test if both works on each case and use just this.

3) You can simplify:

var newUl = $("<ul></ul>");
newUl.insertBefore($(this).children('.title'));

To

$('<ul></ul>').insertBefore($(this).children('.title'));

And from this to

$('<ul>').insertBefore($(this).children('.title'));

4) The funcion appendTo(), insertBefore() and similars are already a kind of echo. I believe that if the element exist, the jQuery will move it. If it won't exist, jQuery will create it, but I can't confirm conclusively.

5) This trick of clear <p> tags is kind magic to me too. I don't know exactly how it works. I got the code from here: Remove "empty" paragraphs with jQuery

Community
  • 1
  • 1
Leo
  • 580
  • 7
  • 22
  • Doesn't seem to be catching the iframes? Or is that a quirk of Codepen? – user2654408 Aug 07 '14 at 05:06
  • Oh, It is working! I removed unintentionally from html. Corrected on Codepen! – Leo Aug 07 '14 at 05:11
  • Fantastic - thankyou! Yes, I noticed that also and was simultaneously correcting! – user2654408 Aug 07 '14 at 05:12
  • Can I fling one more question at you - a variant on this for another site? Basically the same thing but moving the post attachments to a div rather than a list, and adding a class. Should be very quick to answer, but would pose a problem for me. Can create a new question? – user2654408 Aug 07 '14 at 05:14
  • Great! Feel free to vote the answer if it solved your question. I really encourage you to try for yourself, but I can help you! – Leo Aug 07 '14 at 05:16
  • Thanks - setting it up, but can only post a question every 90 minutes! Many thanks for your quick and clear answers - and really appreciate the comments that explain how it works - I'm learning a lot from you! – user2654408 Aug 07 '14 at 05:34
  • You are welcome! This website and the programmers community helped me a lot so I try to give my help when I can. I try to answer keeping the questioner logic to help him to assimilate the new things. Well, while you cannot post a new question, try for yourself, and if you cannot get it post your attempts on question post. The community will appreciate it! – Leo Aug 07 '14 at 05:42
  • Trying it now, and appreciating the beauty of your solution above for this question. Couple of questions about this one: what does the `(index)` on line 3 do? And, as per the suggestion in the other thread/post, do you need `($(this))` or could you just use `(this)`? Third, how is the `ul` being created on line 7? That seems to defy logic! And is it enough to simply have `$("
  • ") at the beginning of that line - you don't need to 'echo' it or something to get it to display? Finally, the final line - trimming html - is pure witchcraft to me! Need to look into that.
  • – user2654408 Aug 07 '14 at 05:52
  • Have posted the new question here: http://stackoverflow.com/questions/25175757/use-jquery-to-move-wordpress-post-attachments-to-per-post-dynamically-created-di – user2654408 Aug 07 '14 at 06:41