/**
* Controls the behaviours of custom metabox fields.
*
* @author Andrew Norcross
* @author Jared Atchison
* @author Bill Erickson
* @author Justin Sternberg
* @see https://github.com/webdevstudios/Custom-Metaboxes-and-Fields-for-WordPress
*/
/*jslint browser: true, devel: true, indent: 4, maxerr: 50, sub: true */
/*global jQuery, tb_show, tb_remove */
/**
* Custom jQuery for Custom Metaboxes and Fields
*/
(function(window, document, $, undefined){
'use strict';
// Move CMB functionality to an object
window.CMB = {
formfield : '',
iterator: 0,
file_frames: {},
init: function() {
CMB.log( window.cmb_l10 );
// hide our spinner gif if we're on a MP6 dashboard
if ( window.cmb_l10.new_admin_style ) {
$('.cmb-spinner img').hide();
}
/**
* Initialize timepicker (this will be moved inline in a future release)
*/
$('.cmb_timepicker').each( function() {
$('#' + jQuery(this).attr('id')).timePicker({
startTime: "07:00",
endTime: "22:00",
show24Hours: false,
separator: ':',
step: 30
});
});
/**
* Initialize jQuery UI datepicker (this will be moved inline in a future release)
*/
$('.cmb_datepicker').each( function() {
$('#' + jQuery(this).attr('id')).datepicker();
// $('#' + jQuery(this).attr('id')).datepicker({ dateFormat: 'yy-mm-dd' });
// For more options see http://jqueryui.com/demos/datepicker/#option-dateFormat
});
// Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
$("#ui-datepicker-div").wrap('
');
/**
* Initialize color picker
*/
if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
$('input:text.cmb_colorpicker').wpColorPicker();
} else {
$('input:text.cmb_colorpicker').each( function(i) {
$(this).after('');
$('#picker-' + i).hide().farbtastic($(this));
})
.focus( function() {
$(this).next().show();
})
.blur( function() {
$(this).next().hide();
});
}
/**
* File and image upload handling
*/
$('.cmb_metabox')
.on( 'change', '.cmb_upload_file', function() {
CMB.formfield = $(this).attr('name');
$('#' + CMB.formfield + '_id').val("");
})
.on( 'click', '.cmb_upload_button', function(event) {
event.preventDefault();
var $self = $(this);
CMB.formfield = $self.prev('input').attr('name');
var $formfield = $('#'+CMB.formfield);
var uploadStatus = true;
var attachment = true;
var isList = $self.hasClass( 'cmb_upload_list' );
// If this field's media frame already exists, reopen it.
if ( CMB.formfield in CMB.file_frames ) {
CMB.file_frames[CMB.formfield].open();
return;
}
// Create the media frame.
CMB.file_frames[CMB.formfield] = wp.media.frames.file_frame = wp.media({
title: $('label[for=' + CMB.formfield + ']').text(),
button: {
text: window.cmb_l10.upload_file
},
multiple: isList ? true : false
});
// When an file is selected, run a callback.
CMB.file_frames[CMB.formfield].on( 'select', function() {
if ( isList ) {
// Get all of our selected files
attachment = CMB.file_frames[CMB.formfield].state().get('selection').toJSON();
$formfield.val(attachment.url);
$('#'+ CMB.formfield +'_id').val(attachment.id);
// Setup our fileGroup array
var fileGroup = [];
// Loop through each attachment
$( attachment ).each( function() {
if ( this.type && this.type === 'image' ) {
// image preview
uploadStatus = ''+
''+
''+ cmb_l10.remove_image +'
'+
''+
'';
} else {
// Standard generic output if it's not an image.
uploadStatus = ''+ cmb_l10.file +' '+ this.filename +' ('+ cmb_l10.download +' / '+ cmb_l10.remove_file +')'+
''+
'';
}
// Add our file to our fileGroup array
fileGroup.push( uploadStatus );
});
// Append each item from our fileGroup array to .cmb_media_status
$( fileGroup ).each( function() {
$formfield.siblings('.cmb_media_status').slideDown().append(this);
});
} else {
// Only get one file from the uploader
attachment = CMB.file_frames[CMB.formfield].state().get('selection').first().toJSON();
$formfield.val(attachment.url);
$('#'+ CMB.formfield +'_id').val(attachment.id);
if ( attachment.type && attachment.type === 'image' ) {
// image preview
uploadStatus = '';
} else {
// Standard generic output if it's not an image.
uploadStatus = cmb_l10.file +' '+ attachment.filename +' ('+ cmb_l10.download +' / '+ cmb_l10.remove_file +')';
}
// add/display our output
$formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
}
});
// Finally, open the modal
CMB.file_frames[CMB.formfield].open();
})
.on( 'click', '.cmb_remove_file_button', function(event) {
var $self = $(this);
if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
$self.parents('li').remove();
return false;
}
CMB.formfield = $self.attr('rel');
var $container = $self.parents('.img_status');
$('input#' + CMB.formfield).val('');
$('input#' + CMB.formfield + '_id').val('');
if ( ! $container.length ) {
$self.parents('.cmb_media_status').html('');
} else {
$container.html('');
}
return false;
})
.on( 'click', '.add-row-button', function(e) {
e.preventDefault();
var $self = $(this);
var tableselector = '#'+ $self.data('selector');
var $table = $(tableselector);
var row = $('.empty-row', $table).clone(true);
row.removeClass('empty-row').addClass('repeat-row');
row.insertBefore( tableselector +' tbody>tr:last' );
var input = $('input.cmb_datepicker',row);
var id = input.attr('id');
input.attr('id', id + CMB.iterator );
CMB.iterator++;
// @todo Make a colorpicker field repeatable
// row.find('.wp-color-result').remove();
// row.find('input:text.cmb_colorpicker').wpColorPicker();
})
.on( 'click', '.remove-row-button', function(e) {
e.preventDefault();
var $self = $(this);
var $parent = $self.parents('.cmb-repeat-table');
CMB.log( 'number of tbodys', $parent.length );
CMB.log( 'number of trs', $('tr', $parent).length );
if ( $('tr', $parent).length > 2 )
$self.parents('.cmb-repeat-table tr').remove();
})
/**
* Ajax oEmbed display
*/
// ajax when typing
.on( 'keyup', '.cmb_oembed', function(event) {
// fire our ajax function
CMB.doAjax($(this), event);
});
// ajax on paste
$('.cmb_oembed').bind( 'paste', function(e) {
var pasteitem = $(this);
// paste event is fired before the value is filled, so wait a bit
setTimeout( function() {
// fire our ajax function
CMB.doAjax(pasteitem, 'paste');
}, 100);
}).blur( function() {
// when leaving the input
setTimeout( function() {
// if it's been 2 seconds, hide our spinner
CMB.spinner( '.postbox table.cmb_metabox', true );
}, 2000);
});
// on pageload
setTimeout( CMB.resizeoEmbeds, 500);
// and on window resize
$(window).on( 'resize', CMB.resizeoEmbeds );
},
/**
* Safely log things if query var is set
* @since 1.0.0
*/
log: function() {
if ( window.cmb_l10.script_debug && console && typeof console.log === 'function' ) {
console.log.apply(console, arguments);
}
},
spinner: function( context, hide ) {
if ( hide )
$('.cmb-spinner', context).hide();
else
$('.cmb-spinner', context).show();
},
// function for running our ajax
doAjax: function(obj, e) {
// get typed value
var oembed_url = obj.val();
// only proceed if the field contains more than 6 characters
if (oembed_url.length < 6)
return;
// only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
if (e === 'paste' || e.which <= 90 && e.which >= 48 || e.which >= 96 && e.which <= 111 || e.which == 8 || e.which == 9 || e.which == 187 || e.which == 190) {
// get field id
var field_id = obj.attr('id');
// get our inputs context for pinpointing
var context = obj.parents('.cmb_metabox tr td');
var embed_container = $('.embed_status', context);
var oembed_width = obj.width();
var child_el = $(':first-child', embed_container);
oembed_width = ( embed_container.length && child_el.length ) ? child_el.width() : obj.width();
// show our spinner
CMB.spinner( context );
// clear out previous results
$('.embed_wrap', context).html('');
// and run our ajax function
setTimeout( function() {
// if they haven't typed in 500 ms
if ($('.cmb_oembed:focus').val() != oembed_url)
return;
$.ajax({
type : 'post',
dataType : 'json',
url : window.cmb_l10.ajaxurl,
data : {
'action': 'cmb_oembed_handler',
'oembed_url': oembed_url,
'oembed_width': oembed_width > 300 ? oembed_width : 300,
'field_id': field_id,
'object_id': obj.data('objectid'),
'object_type': obj.data('objecttype'),
'cmb_ajax_nonce': window.cmb_l10.ajax_nonce
},
success: function(response) {
CMB.log( response );
// Make sure we have a response id
if (typeof response.id === 'undefined')
return;
// hide our spinner
CMB.spinner( context, true );
// and populate our results from ajax response
$('.embed_wrap', context).html(response.result);
}
});
}, 500);
}
},
/**
* Resize oEmbed videos to fit in their respective metaboxes
*/
resizeoEmbeds: function() {
$('table.cmb_metabox').each( function( index ) {
var self = $(this);
var parents = self.parents('.inside');
if ( ! parents.length )
return true; // continue
var tWidth = parents.width();
var newWidth = Math.round((tWidth * 0.82)*0.97) - 30;
if ( newWidth > 639 )
return true; // continue
var child_el = $('.cmb-type-oembed .embed_status', self).children().first();
var iwidth = child_el.width();
var iheight = child_el.height();
var newHeight = Math.round((newWidth * iheight)/iwidth);
child_el.width(newWidth).height(newHeight);
});
}
};
$(document).ready(CMB.init);
})(window, document, jQuery);