(function($){ /* * Gallery * * static model for this field * * @type event * @date 28/07/13 * */ // reference var _media = acf.media; // field acf.fields.gallery = { $el : null, o : {}, set : function( o ){ // merge in new option $.extend( this, o ); // find input this.$input = this.$el.children('input[type="hidden"]'); // get options this.o = acf.helpers.get_atts( this.$el ); // wp library query this.o.query = {}; // library if( this.o.library == 'uploadedTo' ) { this.o.query.uploadedTo = acf.o.post_id; } // view this.o.view = 'grid'; if( this.$el.hasClass('view-list') ) { this.o.view = 'list'; } // return this for chaining return this; }, init : function(){ // is clone field? if( acf.helpers.is_clone_field(this.$input) ) { return; } // update count this.render(); // sortable this.$el.find('> .thumbnails > .inner').sortable({ items : '> .thumbnail', forceHelperSize : true, forcePlaceholderSize : true, scroll : true, start : function (event, ui) { // alter width / height to allow for 2px border ui.placeholder.width( ui.placeholder.width() - 4 ); ui.placeholder.height( ui.placeholder.height() - 4 ); } }); }, view : function( view ){ this.o.view = view; this.render(); }, render : function(){ // vars var count = this.$el.find('.thumbnails .thumbnail').length, s = acf.l10n.gallery[ 'count_' + Math.min( count, 2) ].replace('%d', count), $span = this.$el.find('.toolbar .count'); // update span text $span.html( s ); // toolbar if( this.o.view == 'list' ) { this.$el.addClass('view-list'); this.$el.find('.toolbar .view-grid-li').removeClass('active'); this.$el.find('.toolbar .view-list-li').addClass('active'); } else { this.$el.removeClass('view-list'); this.$el.find('.toolbar .view-grid-li').addClass('active'); this.$el.find('.toolbar .view-list-li').removeClass('active'); } }, add : function( image ){ // IMPORTANT: this may not be the field we think it is. // Opening a popup will cause the acf/setup_fields action to run, and this may be updated with the fields found in the popup! // Reset this using the _media.div // reset this.set({ $el : _media.div }); // vars var tmpl = this.$el.find('.tmpl-thumbnail').html(); // update tmpl $.each(image, function( k, v ){ var regex = new RegExp('{' + k + '}', 'g'); tmpl = tmpl.replace(regex, v); }); // add div this.$el.find('.thumbnails > .inner').append( tmpl ); // update gallery count this.render(); // validation this.$el.closest('.field').removeClass('error'); }, edit : function( id ){ // set global var _media.div = this.$el; // clear the frame _media.clear_frame(); // create the media frame _media.frame = wp.media({ title : acf.l10n.gallery.edit, multiple : false, button : { text : acf.l10n.gallery.update } }); // open _media.frame.on('open',function() { // set to browse if( _media.frame.content._mode != 'browse' ) { _media.frame.content.mode('browse'); } // add class _media.frame.$el.closest('.media-modal').addClass('acf-media-modal acf-expanded'); // set selection var selection = _media.frame.state().get('selection'), attachment = wp.media.attachment( id ); attachment.fetch(); selection.add( attachment ); // change events for list view _media.frame.$el.on('change', '.setting input, .setting textarea', function(){ // vars var $el = $(this), setting = $el.closest('.setting').attr('data-setting'); // update galleries $('.acf-gallery .thumbnail[data-id="' + id + '"] .td-' + setting).html( $el.val() ); }); }); // close _media.frame.on('close',function(){ // remove class _media.frame.$el.closest('.media-modal').removeClass('acf-media-modal'); }); // Finally, open the modal _media.frame.open(); }, remove : function( id ){ // reference var _this = this; // vars $thumb = this.$el.find('.thumbnails .thumbnail[data-id="' + id + '"]'); // fade and remove $thumb.animate({ opacity : 0 }, 250, function(){ $thumb.remove(); _this.render(); }); }, render_collection : function(){ // Note: Need to find a differen 'on' event. Now that attachments load custom fields, this function can't rely on a timeout. Instead, hook into a render function foreach item // set timeout for 0, then it will always run last after the add event setTimeout(function(){ // vars var $gallery = _media.div, $content = _media.frame.content.get().$el collection = _media.frame.content.get().collection || null; if( collection ) { var i = -1; collection.each(function( item ){ i++; var $li = $content.find('.attachments > .attachment:eq(' + i + ')'); // if image is already inside the gallery, disable it! if( $gallery.find('.thumbnails .thumbnail[data-id="' + item.id + '"]').exists() ) { item.off('selection:single'); $li.addClass('acf-selected'); } }); } }, 0); }, popup : function() { // reference var _this = this; // set global var _media.div = this.$el; // clear the frame _media.clear_frame(); // Create the media frame _media.frame = wp.media({ states : [ new wp.media.controller.Library({ library : wp.media.query( this.o.query ), multiple : true, title : acf.l10n.gallery.select, priority : 20, filterable : 'all' }) ] }); // customize model / view _media.frame.on('content:activate', function(){ // vars var toolbar = null, filters = null; // populate above vars making sure to allow for failure try { toolbar = _media.frame.content.get().toolbar; filters = toolbar.get('filters'); } catch(e) { // one of the objects was 'undefined'... perhaps the frame open is Upload Files //console.log( e ); } // validate if( !filters ) { return false; } // no need for 'uploaded' filter if( _this.o.library == 'uploadedTo' ) { filters.$el.find('option[value="uploaded"]').remove(); filters.$el.after('<span>' + acf.l10n.gallery.uploadedTo + '</span>') $.each( filters.filters, function( k, v ){ v.props.uploadedTo = acf.o.post_id; }); } // hide selected items from the library _this.render_collection(); _media.frame.content.get().collection.on( 'reset add', function(){ _this.render_collection(); }); }); // When an image is selected, run a callback. _media.frame.on( 'select', function() { // get selected images selection = _media.frame.state().get('selection'); if( selection ) { selection.each(function(attachment){ // is image already in gallery? if( _this.$el.find('.thumbnails .thumbnail[data-id="' + attachment.id + '"]').exists() ) { return; } // vars var image = { id : attachment.id, title : attachment.attributes.title, name : attachment.attributes.filename, url : attachment.attributes.url, caption : attachment.attributes.caption, alt : attachment.attributes.alt, description : attachment.attributes.description }; // file? if( attachment.attributes.type != 'image' ) { image.url = attachment.attributes.icon; } // is preview size available? if( attachment.attributes.sizes && attachment.attributes.sizes[ _this.o.preview_size ] ) { image.url = attachment.attributes.sizes[ _this.o.preview_size ].url; } // add file to field _this.add( image ); }); // selection.each(function(attachment){ } // if( selection ) }); // _media.frame.on( 'select', function() { // Finally, open the modal _media.frame.open(); return false; } }; /* * Events * * jQuery events for this field * * @type function * @date 1/03/2011 * * @param N/A * @return N/A */ $(document).on('click', '.acf-gallery .acf-button-edit', function( e ){ e.preventDefault(); // vars var id = $(this).closest('.thumbnail').attr('data-id'); acf.fields.gallery.set({ $el : $(this).closest('.acf-gallery') }).edit( id ); $(this).blur(); }); $(document).on('click', '.acf-gallery .acf-button-delete', function( e ){ e.preventDefault(); // vars var id = $(this).closest('.thumbnail').attr('data-id'); acf.fields.gallery.set({ $el : $(this).closest('.acf-gallery') }).remove( id ); $(this).blur(); }); $(document).on('click', '.acf-gallery .add-image', function( e ){ e.preventDefault(); acf.fields.gallery.set({ $el : $(this).closest('.acf-gallery') }).popup(); $(this).blur(); }); $(document).on('click', '.acf-gallery .view-grid', function( e ){ e.preventDefault(); acf.fields.gallery.set({ $el : $(this).closest('.acf-gallery') }).view( 'grid' ); $(this).blur(); }); $(document).on('click', '.acf-gallery .view-list', function( e ){ e.preventDefault(); acf.fields.gallery.set({ $el : $(this).closest('.acf-gallery') }).view( 'list' ); $(this).blur(); }); /* * acf/setup_fields * * run init function on all elements for this field * * @type event * @date 20/07/13 * * @param {object} e event object * @param {object} el DOM object which may contain new ACF elements * @return N/A */ $(document).on('acf/setup_fields', function(e, el){ $(el).find('.acf-gallery').each(function(){ acf.fields.gallery.set({ $el : $(this) }).init(); }); }); })(jQuery);