Use jQuery to move WordPress post attachments to p

2020-05-03 13:39发布

问题:

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!

回答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