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).

I have written this code, which as far as I can see should work. Any help very much appreciated.

jQuery("document").ready (function($){

// First I set up a conditional loop: if images or iframes are found in .para, do the following
if ( $(".para img, .para iframe").length > 0) {

    // ... create the <ul>
    var newUl = $("<ul></ul>");
    // and move it to the desired location, just inside .wrapper940
    newUl.prependTo($(this).parents(".wrapper940"));

    // Now I start the loop for each image or iframe found
    $(this).each(function() {

        // For each one I create an <li> element.
        var newLi = $("<li></li>");

        // Now I put the li element into the <ul> that I created above
        newLi.appendTo($(this).parents("newUl"));

        // Last I put 'this' into the new <li>.
        newLi.append(this);

        });
    });
});

I have created a jsfiddle here to show this in context with the html.

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?

user2654408
  • 213
  • 2
  • 10
  • I believe it would be easier if you post the html code you have and the html code you want to get. The html code this script is generating would be helpful too. – Leo Aug 05 '14 at 04:05
  • @Leo I have added a link to a jsfiddle that shows the code. I am trying to extract the images and iframes from the .para div and display them above the title as list items in a newly created unordered list. – user2654408 Aug 05 '14 at 05:14

2 Answers2

0

The li you create have no parent or parents when you create them. Also .parents("newUl") is using invalid selector which would be looking for a tagName newul.

It is better to do all the appending of the new elements outside the DOM and then only make one append at the end

var newUl = $("<ul></ul>");    

// Now I start the loop for each image or iframe found
$(this).each(function () {

    // For each one I create an <li> element.
    var newLi = $("<li></li>");

    // Now I put the li element into the <ul> that I created above
    newLi.appendTo(newUl);

    // Last I put 'this' into the new <li>.
    newLi.append(this);

});

// now that all the children are created, make one DOM insertion only     
newUl.prependTo($(this).parents(".wrapper940"));
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Please see the jsfiddle link added to my original post above - I tried your suggestion but am unable to get it to work - not sure why. – user2654408 Aug 05 '14 at 05:17
  • `$(this)` is the window. You need to loop over the image and iframe elements as selectors for `$.each()` – charlietfl Aug 05 '14 at 13:24
  • I've created another fiddle showing how I've implemented your code suggestion - http://jsfiddle.net/conrad89/Jc2NX/ - it seems to be having no effect, even though I have looped over the image and iframe elements as you suggest. Any ideas? – user2654408 Aug 05 '14 at 15:17
0

Some basic mistakes:

  • After you close the if condition with }, you added a );, which breaks the script
  • You forgot to add jQuery on your jsFiddle

Main corrections:

1

You did a great script, but the main mistake was the this reference all over the script. When you do a condition like:

if ( $(".para img, .para iframe").length > 0) {
    $(this).(...)
}

The jQuery does not understand that the $(this) is related to the $(".para img, .para iframe") into the if ( $(".para img, .para iframe").length > 0){ condition.

My approach is create a new var to match elements:

    var matchesEl = $(".para img, .para iframe");
    if ( matchesEl.length > 0) {
        var newUl = $("<ul></ul>");
        newUl.prependTo(matchesEl.parents(".wrapper940"));

        matchesEl.each(function() {
            ...
        }
    }

2 Into your each loop, the jQuery understands the $(this), but you used only this. Convert: newLi.append(this); to newLi.append($(this));

As @charlietfl said, the information above is not true.


3

And there is no $(this).parents("newUl")) because newUl is a var, it isn't an element. Convert:

newLi.appendTo($(this).parents("newUl"));

to

newLi.appendTo(newUl);

Tip

You can use this:

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

as a chained single line:

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

Or if you won't use newLi as a var, you don't need create it. You could do only:

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


Check jsfiddle for full code:

CodenPen - Code working: http://codepen.io/anon/pen/qzuha (Jsfiddle website is out right now).

Leo
  • 580
  • 7
  • 22
  • 1
    `append($(this))` is not neeeded to wrap `this` in `$()`. Methods do accept DOM nodes – charlietfl Aug 06 '14 at 06:48
  • You are right! I always used `this` only for pure javascript e `$(this)` for jquery. Sorry for misinformation and thanks for pointing that! I edited the answer. – Leo Aug 06 '14 at 14:43
  • @Leo Thankyou for your amazing answer. It does almost exactly what I need. However, is there a way to make this local to each post? i.e. there will be multiple `.wrapper940` divs on a page - one around each post. Currently this code is stripping the images and iframes from all posts and adding them to one single new list. I'd presumably need something like `.closest` rather than `.parents` to do this.. but this doesn't work? – user2654408 Aug 07 '14 at 03:26
  • Yes, you are right. Please, edit your question and add the full (or more complete) html structure. I mean, is the `.wrapper940` for each post or is it parent of all posts? There is a `
    ` tag separating posts maybe?
    – Leo Aug 07 '14 at 03:32
  • Or create a new question, I believe it would be more helpful for another users. – Leo Aug 07 '14 at 04:00
  • @Leo Actually, moving it to a new question for clarity's sake and more useful for others - will post link here. – user2654408 Aug 07 '14 at 04:45
  • @Leo Ok, new question posted here: http://stackoverflow.com/questions/25174429/use-jquery-to-move-wordpress-post-attachments-to-per-post-dynamically-created-li – user2654408 Aug 07 '14 at 04:57
  • Great choice @user2654408! I suggest you to backup your question (manually) and vote for an answer to close this topic. – Leo Aug 07 '14 at 05:01