Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I've searched numerous StackOverflow and Wordpress Awnsers questions, but I couldn't find any solution that matches my situation or even remotely points me in the right direction.

I have a custom media frame in my plugin where I have pre-selected certain images out of a media library of about 3000 images. However, these pre-selected images aren't sorted on top of the list by default, which results in you browsing the list for hours to find your selected images. In short I want these to be on top of the list. I have their ID's.

I found that in media-models.js where the code goes:

Query = media.model.Query = Attachments.extend({ ...

it handles the querying / sorting of the attachments that are displayed in the media manager.

I've tried extending it like this in my main plugin javascript file

wp.media.model.Query = wp.media.model.Attachments.extend({ ...

which gave me no result and numerous other suggestions in question that looked similar to my situation. Now I'm at the point where I'm out of idea's of how to tackle this. Could someone point me in the right direction?


EDIT: Well I have been able to influence the queries made by my media frame.

In my main.js in my plugin I do this now:

file_frame = wp.media.frames.file_frame = wp.media({
    id: 'multi_image',
    title: 'Select images',
    button: {
        text: 'Use selected images'
    },
    library: {
        type: 'image', post__in:[3322,3323,3324,3325,3326,3327,3328]
    },
    multiple: true,
}); 

This way I can show the media frame only displaying the image attachments with certain id's. However I also want to display the rest of the attachments, only with my selected images on top. So I would need to either combine the results of this query by making a new query with post__not_in instead of post__in or by custom ordering the attacments giving the attachments with those id's priority. I don't know how to do that. The arguments I can pass to the library seem limited to me.

share|improve this question
    
Try it with dumping $GLOBALS['wpdb']->last_query and $GLOBALS['wpdb']->last_result in a callback hooked to pre_get_posts. If you find the query that is responsible, you can simply narrow your scenario down until all other queries are excluded. Update your question in between. –  kaiser Aug 26 '13 at 15:37
    
Is this going to work for AJAX calls aswell? Should i dump it in the AJAX call itself? Or can I just dump it on the admin page and refresh the page? –  Ogier Schelvis Aug 28 '13 at 7:54
    
I'd say: "Give it a try!" :) ... dump inside your ajax calls, check your dev tools to inspect the return value. –  kaiser Aug 28 '13 at 8:07
    
I feel I'm almost there. Could someone please enlighten me? –  Ogier Schelvis Aug 29 '13 at 10:02

1 Answer 1

up vote 4 down vote accepted

After reading up on the Backbone.js documentation I found out it's quite easy to manually add attachments by ID to the library of the media frame.

You can just assign a reference to the library on the open event. Then create an instance of wp.media.attachment. Fetch it. And then call the add function on your library reference and passing the attachment with it. I had my attachment id's in an array and looped through them like so:

file_frame.on('open',function(){

        var lib = file_frame.state().get('library');
        for (var i=0;i<ids.length;i++){
            var attachment = wp.media.attachment(ids[i]);
            attachment.fetch();
            lib.add(attachment);
        }
});

EDIT: Additionally I encountered a problem where the sorting got messed up sometimes and some of my attachments weren't being placed on top of the list. So to make sure that they did I overrode the comparator function of the library like this to force compare on ID . It used to do get(key), but I turned it into get('id'):

lib.comparator = function ( a, b, options ) {
                var key   = this.props.get('orderby'),
                order = this.props.get('order') || 'DESC',
                ac    = a.cid,
                bc    = b.cid;

            a = a.get( 'id' );
            b = b.get( 'id' );

            if ( 'date' === key || 'modified' === key ) {
                a = a || new Date();
                b = b || new Date();
            }

            // If `options.ties` is set, don't enforce the `cid` tiebreaker.
            if ( options && options.ties )
                ac = bc = null;

            return ( 'DESC' === order ) ? compare( a, b, ac, bc ) : compare( b, a, bc, ac );
        } 

However it's going to whine about the compare function being undefined. So I just declared it myself the same it is as in wp.media:

compare = function( a, b, ac, bc ) {
        if ( _.isEqual( a, b ) )
            return ac === bc ? 0 : (ac > bc ? -1 : 1);
        else
            return a > b ? -1 : 1;
    };

This comparator needs to be set before adding new attachments to the library. Because otherwise the problem will persist.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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