// What's here needs to stay global
// used in FV Player Pro to add more matchers
var fv_player_editor_matcher = {
default: {
// matches URL of the video
matcher: /\.(mp4|webm|m3u8)$/i,
// AJAX will return these fields which can be auto-updated via JS
update_fields: ['duration', 'last_video_meta_check'],
}
};
jQuery(function() {
// The actual editor
window.fv_player_editor = (function($) {
debug_log('Loading...');
var
$doc = $(document),
$el_editor,
$el_preview,
$el_save_complete = $('.fv-player-save-completed'),
$el_save_error = $('.fv-player-save-error'),
$el_save_error_p = $el_save_error.find('p'),
// data to save in Ajax
ajax_save_this_please = false,
current_player_db_id = -1,
current_video_to_edit = -1,
// stores the button which was clicked to open the editor
editor_button_clicked = 0,
// the post editor content being edited
editor_content,
// used in WP Heartbeat
edit_lock_removal = {},
// used to size the lightbox in editor_resize()
editor_resize_height_record = 0,
// TinyMCE instance, if any
instance_tinymce,
// Foliopress WYSIWYG instance, if any
instance_fp_wysiwyg,
// are we editing player which is not yet in DB?
is_unsaved = true,
// is the player already saved in the DB but actually
// still in a "draft" status? i.e. not published yet
has_draft_status = true,
// will be > 0 when any meta data are loading that need saving along with the form (example: S3 video duration, PPV product creation)
// ... this prevents overlay closing until all meta required data are loaded and stored
is_loading_meta_data = 0,
// whether we're editing a single video (true) or showing a playlist view (false)
editing_video_details = false,
// which playlist item we're currently editing, set to -1 if we're showing playlist view
// this is used when loading data from DB to avoid previewing an empty video that's in editor by default
item_index = -1,
// are we currently saving data?
is_saving = false,
// used when editing shortcode in TinyMCE
helper_tag = window.fvwpflowplayer_helper_tag,
// should preview only show a single video? if so, which one in the current playlist?
preview_single = -1,
// the part of shortcode outside of [fvplayer id="XYZ"]
// also accessed from outside
shortcode_remains,
// Some shortcode args should be kept. For example if you edit
// [fvplayer id="1" sort="newest"] that sort should not be removed
store_shortcode_args = {},
// Some shortcode args do not have a DB counterpars, so they should always
// be kept on the shortcode. For example if you edit
// [fvplayer src="some_video_url" sort="newest"] that sort should not be removed,
// as it's not been transferred into the DB
always_keep_shortcode_args = {},
// Flowplayer only lets us specify the RTMP server for the first video in plalist, so we store it here when the playlist item order is changing etc.
store_rtmp_server = '',
// stores parts of editor HTML which are later re-used when adding new items
template_playlist_item,
template_video,
template_subtitles,
template_subtitles_tab,
// used to remember which widget we are editing, if any
widget_id,
// used in Gutenberg preview to store a preview timeout task due to REACT not being fast enough to allow us previewing
// player directly after we close the editor
fv_player_preview_loading = false,
// list of errors that currently prevent auto-saving in the form of: { error_identifier_with_(plugin_)prefix : "the actual error text to show" }
// ... this will be shown in place of the "Saved!" message bottom overlay and it will always show only the first error in this object,
// as to not overload the user and UI with errors. Once that error is corrected, it gets removed from this object and next one (if any) is shown.
errors = {};
/*
* A shorthand to save you from all the "fv_wp_flowplayer_field_"
* when selecting fields
*
* @param {string} key The field key. For example "src" gives
* you "fv_wp_flowplayer_field_src"
* @param {object|string} where Lets you narrow down the element wher you
* want to locate he field. You can use a jQuery
* element or a string selector for jQuery
*
* @return {object} The field element
*/
function get_field( key, where ) {
var element = false,
selector = '.' + fv_wp_flowplayer_map_names_to_editor_fields(key) + ', [name=' + fv_wp_flowplayer_map_names_to_editor_fields(key) + ']';
if( where && typeof(where) == "object" ) {
element = where.find(selector);
} else if( where && typeof(where) == "string" ) {
element = $el_editor.find(where).find(selector);
} else {
element = $el_editor.find(selector);
}
if( !element.length ) {
console.log('FV Player Editor Error: field '+key+' not found');
}
return element;
}
/*
* Gives you "src" out of "fv_wp_flowplayer_field_src"
*
* @param {string} name The field name
*
* @return {string} The field.... real name?
*/
function get_field_name( name ) {
if (name.indexOf('fv_wp_flowplayer_field_') > -1) {
return name.replace('fv_wp_flowplayer_field_', '');
}
return name;
}
/*
* Gives you the desired tab with video information
*
* @param {int|string} index Number, or first, or last
* @param {string} tab Tab name to obtain, options:
* * video-files
* * subtitles
*
* @return {object} The tab element
*/
function get_tab( index, tab ) {
var selector = '.fv-player-tab-'+tab+' table';
if( index == 'first' ) {
selector += ':first';
} else if( index == 'last' ) {
selector += ':last';
} else {
selector += '[data-index='+index+']';
}
return $el_editor.find(selector);
}
/*
* Gives you all desired tabs of a certain kind
*
* @return {object} The tab elements
*/
function get_tabs( tab ) {
var selector = '.fv-player-tab-'+tab+' table';
return $el_editor.find(selector);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
$doc.ready( function(){
$el_editor = $('#fv-player-shortcode-editor');
$el_preview = $('#fv-player-shortcode-editor-preview');
el_spinner = $('#fv-player-shortcode-editor-preview-spinner');
el_preview_target = $('#fv-player-shortcode-editor-preview-target');
var
previous = false,
next = false,
overlay_close_waiting_for_save = false,
loading = true,
int_keyup = false;
/*$(window).on('beforeunload', function(e) {
if (is_draft && is_draft_changed) {
return e.originalEvent.returnValue = 'You have unsaved changes. Are you sure you want to close this dialog and loose them?';
}
});*/
if( jQuery().fv_player_box ) {
debug_log('Attaching click actions...');
$doc.on( 'click', '.fv-wordpress-flowplayer-button, .fv-player-editor-button, .fv-player-edit', function(e) {
// make the TinyMCE editor below this button active,
// as otherwise we would be inserting into the last TinyMCE instance
// on the page if no TinyMCE instance was clicked into - which is not what we want to do
if (typeof(tinyMCE) != 'undefined' && typeof(tinyMCE.activeEditor) != 'undefined' && this.className.indexOf('fv-wordpress-flowplayer-button') > -1) {
var
$btn = jQuery(this),
$wraper_div = $btn.parents('.wp-editor-wrap:first');
for (var i in tinyMCE.editors) {
if (tinyMCE.editors[i].editorContainer && tinyMCE.editors[i].editorContainer.id && $wraper_div.find('#' + tinyMCE.editors[i].editorContainer.id).length) {
tinyMCE.activeEditor = tinyMCE.editors[i];
break;
}
}
}
editor_button_clicked = this;
e.preventDefault();
$.fv_player_box( {
top: "100px",
initialWidth: 1100,
initialHeight: 50,
width:"1100px",
height:"100px",
href: "#fv-player-shortcode-editor",
inline: true,
title: 'Add FV Player',
onComplete : editor_open,
onClosed : editor_close,
onOpen: lightbox_open
} );
widget_id = $(this).data().number;
});
$doc.on( 'click', '.fv-player-export', function(e) {
var $element = jQuery(this);
e.preventDefault();
$.fv_player_box( {
top: "100px",
initialWidth: 1100,
initialHeight: 50,
width:"1100px",
height:"100px",
href: "#fv-player-shortcode-editor",
inline: true,
title: 'Export FV Player',
onComplete : function() {
overlay_show('loading');
debug_log('Running fv_player_db_export Ajax.');
$.post(ajaxurl, {
action: 'fv_player_db_export',
playerID : $element.data('player_id'),
nonce : $element.data('nonce'),
cookie: encodeURIComponent(document.cookie),
}, function(json_export_data) {
var overlay = overlay_show('export');
overlay.find('textarea').val( $('<div/>').text(json_export_data).html() );
jQuery('[name=fv_player_copy_to_clipboard]').select();
}).error(function() {
overlay_show('message', 'An unexpected error has occurred. Please try again.');
});
},
onClosed : overlay_hide,
onOpen: lightbox_open
} );
return false;
});
$doc.on( 'click', '.fv-player-import', function(e) {
var $element = jQuery(this);
e.preventDefault();
$.fv_player_box( {
top: "100px",
initialWidth: 1100,
initialHeight: 50,
width:"1100px",
height:"100px",
href: "#fv-player-shortcode-editor",
inline: true,
title: 'Import FV Player(s)',
onComplete : function() {
overlay_show('import');
},
onClosed : overlay_hide,
onOpen: lightbox_open
} );
return false;
});
$doc.on( 'click', '.fv-player-remove', function(e) {
jQuery(this)
.addClass('fv-player-remove-confirm')
.removeClass('fv-player-remove')
.html('Are you sure?')
.one('mouseleave', function() {
jQuery(this)
.removeClass('fv-player-remove-confirm')
.addClass('fv-player-remove')
.html('Delete');
});
return false;
});
$doc.on( 'click', '.fv-player-remove-confirm', function(e) {
var
$element = $(this),
$element_td = $element.parent(),
$spinner = $('<div class="fv-player-shortcode-editor-small-spinner"></div>');
$element_td.find('a, span').hide();
$element.after($spinner);
debug_log('Running fv_player_db_remove Ajax.');
jQuery.post(ajaxurl, {
action: "fv_player_db_remove",
nonce: $element.data('nonce'),
playerID: $element.data('player_id')
}, function(rows_affected){
if (!isNaN(parseFloat(rows_affected)) && isFinite(rows_affected)) {
// remove the deleted player's row
$element.closest('tr').hide('slow', function() {
jQuery(this).remove();
});
} else {
$spinner.remove();
alert(rows_affected);
$element_td.find('span, a:not(.fv-player-remove-confirm)').show();
}
}).error(function() {
$spinner.remove();
$element.html('Error');
$element_td.find('span, a:not(.fv-player-remove-confirm)').show();
});
return false;
});
$doc.on( 'click', '.fv-player-clone', function(e) {
var $element = jQuery(this),
$spinner = $('<div class="fv-player-shortcode-editor-small-spinner"> </div>');
$element
.hide()
.after($spinner);
debug_log('Running fv_player_db_clone Ajax.');
$.post(ajaxurl, {
action: "fv_player_db_clone",
nonce: $element.data('nonce'),
playerID: $element.data('player_id')
}, function(playerID){
if (playerID != '0' && !isNaN(parseFloat(playerID)) && isFinite(playerID)) {
// add the inserted player's row
$.get(
fv_player_editor_conf.admin_url + '&id=' + playerID,
function (response) {
$('#the-list tr:first').before(jQuery(response).find('#the-list tr:first'));
$spinner.remove();
$element.show();
}).error(function() {
$spinner.remove();
$element.show();
});
} else {
$spinner.remove();
$element.html('Error');
}
}).error(function() {
$spinner
$element.html('Error');
});
return false;
});
}
/*
* NAV TABS
*/
$('.fv-player-tabs-header a').click( function(e) {
e.preventDefault();
$('.fv-player-tabs-header a').removeClass('nav-tab-active');
$(this).addClass('nav-tab-active')
$('.fv-player-tabs > .fv-player-tab').hide();
$('.' + $(this).data('tab')).show();
editor_resize();
});
/*
* Select playlist item
* keywords: select item
*/
$doc.on('click','.fv-player-tab-playlist tr td', function(e) {
var new_index = $(this).parents('tr').attr('data-index');
preview_single = new_index;
playlist_item_show(new_index);
});
$doc.on('input','.fv_wp_flowplayer_field_width', function(e) {
$('.fv_wp_flowplayer_field_width').val(e.target.value);
})
$doc.on('input','.fv_wp_flowplayer_field_height', function(e) {
$('.fv_wp_flowplayer_field_height').val(e.target.value);
})
/*
* Playlist view thumbnail toggle
*/
var list_style_toggles = $('#fv-player-list-thumb-toggle > a');
list_style_toggles.click(function(){
var button = $(this);
if( button.hasClass('disabled') ) return;
list_style_toggles.removeClass('active');
$('.fv-player-tab-playlist').toggleClass( 'hide-thumbnails', button.attr('id') === 'fv-player-list-list-view' );
button.addClass('active');
return false;
});
/*
* Remove playlist item
* keywords: delete playlist items remove playlist items
*/
$doc.on('click','.fv-player-tab-playlist tr .fvp_item_remove', function(e) {
jQuery(this)
.addClass('fvp_item_remove-confirm')
.html('Are you sure?')
.one('mouseleave', function() {
jQuery(this)
.removeClass('fvp_item_remove-confirm')
.html('Delete');
});
return false;
});
$doc.on('click','.fv-player-tab-playlist tr .fvp_item_remove-confirm', function(e) {
e.stopPropagation();
var
$parent = $(e.target).parents('[data-index]'),
index = $parent.attr('data-index'),
id = get_tab(index,'video-files').attr('data-id_video'),
$deleted_videos_element = $('#fv-player-deleted_videos');
if (id && $deleted_videos_element.val()) {
$deleted_videos_element.val($deleted_videos_element.val() + ',' + id);
} else {
$deleted_videos_element.val(id);
}
$parent.remove();
get_tab(index,'video-files').remove();
get_tab(index,'subtitles').remove();
get_tab(index,'cues').remove();
// if no playlist item is left, add a new one
// TODO: Some better way?
if( !jQuery('.fv-player-tab-subtitles table[data-index]').length ){
playlist_item_add();
jQuery('.fv-player-tab-playlist tr td').click();
}
$doc.trigger('fv_flowplayer_shortcode_item_delete');
});
/*
* Sort playlist
*/
$('.fv-player-tab-playlist table tbody').sortable({
start: function( event, ui ) {
store_rtmp_server = get_field( 'rtmp', get_tab('first','video-files') ).val();
},
update: function( event, ui ) {
$doc.trigger('fv-player-editor-sortable-update');
var new_sort = [];
$('.fv-player-tab-playlist table tbody tr').each(function(){
var
index = $(this).attr('data-index'),
video_tab_item = get_tab(index,'video-files'),
subtitle_tab_item = get_tab(index,'subtitles');
new_sort.push({
video_tab_item : video_tab_item.clone(),
subtitle_tab_item : subtitle_tab_item.clone()
});
video_tab_item.remove();
subtitle_tab_item.remove();
});
$.each(new_sort, function(k,v) {
$('.fv-player-tab-video-files').append(v.video_tab_item);
$('.fv-player-tab-subtitles').append(v.subtitle_tab_item);
});
get_field( 'rtmp', get_tab('first','video-files') ).val( store_rtmp_server );
playlist_index();
$doc.trigger('fv_flowplayer_shortcode_item_sort');
},
axis: 'y',
//handle: '.fvp_item_sort',
containment: ".fv-player-tab-playlist"
});
/*
* Uploader
*/
var fv_flowplayer_uploader;
var fv_flowplayer_uploader_button;
$doc.on( 'click', '#fv-player-shortcode-editor .button.add_media', function(e) {
e.preventDefault();
fv_flowplayer_uploader_button = jQuery(this);
jQuery('.fv_flowplayer_target').removeClass('fv_flowplayer_target' );
fv_flowplayer_uploader_button.siblings('input[type=text]').addClass('fv_flowplayer_target' );
//If the uploader object has already been created, reopen the dialog
if (fv_flowplayer_uploader) {
fv_flowplayer_uploader.open();
return;
}
//Extend the wp.media object
fv_flowplayer_uploader = wp.media.frames.file_frame = wp.media({
title: 'Add Video',
button: {
text: 'Choose'
},
multiple: false
});
fv_flowplayer_uploader.on('open', function() {
$( document ).trigger( "mediaBrowserOpen" );
jQuery('.media-router .media-menu-item').eq(0).click();
jQuery('.media-frame-title h1').text(fv_flowplayer_uploader_button.text());
});
//When a file is selected, grab the URL and set it as the text field's value
fv_flowplayer_uploader.on('select', function() {
attachment = fv_flowplayer_uploader.state().get('selection').first().toJSON();
$('.fv_flowplayer_target').val(attachment.url).trigger('change').trigger('keyup');
$('.fv_flowplayer_target').removeClass('fv_flowplayer_target' );
if( attachment.type == 'video' ) {
if( typeof(attachment.width) != "undefined" && attachment.width > 0 ) {
$('.fv_wp_flowplayer_field_width').val(attachment.width);
}
if( typeof(attachment.height) != "undefined" && attachment.height > 0 ) {
$('.fv_wp_flowplayer_field_height').val(attachment.height);
}
if( typeof(attachment.fileLength) != "undefined" ) {
$('#fv_wp_flowplayer_file_info').show();
$('#fv_wp_flowplayer_file_duration').html(attachment.fileLength);
}
if( typeof(attachment.filesizeHumanReadable) != "undefined" ) {
$('#fv_wp_flowplayer_file_info').show();
$('#fv_wp_flowplayer_file_size').html(attachment.filesizeHumanReadable);
}
} else if( attachment.type == 'image' && typeof(fv_flowplayer_set_post_thumbnail_id) != "undefined" ) {
if( jQuery('#remove-post-thumbnail').length > 0 ){
return;
}
debug_log('Running set-post-thumbnail Ajax.');
jQuery.post(ajaxurl, {
action:"set-post-thumbnail",
post_id: fv_flowplayer_set_post_thumbnail_id,
thumbnail_id: attachment.id,
_ajax_nonce: fv_flowplayer_set_post_thumbnail_nonce,
cookie: encodeURIComponent(document.cookie)
}, function(str){
var win = window.dialogArguments || opener || parent || top;
if ( str == '0' ) {
alert( setPostThumbnailL10n.error );
} else {
jQuery('#postimagediv .inside').html(str);
jQuery('#postimagediv .inside #plupload-upload-ui').hide();
}
} );
}
});
//Open the uploader dialog
fv_flowplayer_uploader.open();
});
template_playlist_item = jQuery('.fv-player-tab-playlist table tbody tr').parent().html();
template_video = get_tab('first','video-files').parent().html();
template_subtitles = jQuery('.fv-fp-subtitle').parent().html();
template_subtitles_tab = jQuery('.fv-player-tab-subtitles').html();
/*
* End of playlist Actions
*/
jQuery('#fv_wp_flowplayer_field_end_actions').change(function(){
var value = jQuery(this).val();
jQuery('.fv_player_actions_end-toggle').hide().find('[name]').val('');
switch(value){
case 'redirect':
jQuery('#fv_wp_flowplayer_field_' + value).parents('tr').show();
break;
case 'popup':
jQuery('#fv_wp_flowplayer_field_' + value).parents('tr').show();
jQuery('#fv_wp_flowplayer_field_' + value + '_id').parents('tr').show();
break;
case 'email_list':
jQuery('#fv_wp_flowplayer_field_' + value).parents('tr').show();
break;
default:
break;
}
});
/*
* Preview iframe dialog resize
*/
$doc.on('fvp-preview-complete',function(e){
$el_preview.attr('class','preview-show');
editor_resize();
});
/*
* Video share option
*/
// TODO: Check
jQuery('#fv_wp_flowplayer_field_share').change(function(){
var value = jQuery(this).val();
switch(value){
case 'Custom':
jQuery("#fv_wp_flowplayer_field_share_custom").show();
break;
default:
jQuery("#fv_wp_flowplayer_field_share_custom").hide();
break;
}
});
$doc.on("change", "#fv-player-shortcode-editor-right input, #fv-player-shortcode-editor-right select", save );
$doc.on("keyup", "#fv-player-shortcode-editor-right input[type=text], #fv-player-shortcode-editor-right textarea", function() {
clearTimeout(int_keyup);
int_keyup = setTimeout( function() {
save();
}, 500 );
});
$doc.on('fv_flowplayer_shortcode_new fv-player-editor-non-db-shortcode', function() {
fv_player_editor.insert_button_toggle(true);
fv_player_editor.copy_player_button_toggle(true);
});
$doc.on('fv_flowplayer_video_meta_load', function() {
fv_player_editor.insert_button_toggle(false);
fv_player_editor.copy_player_button_toggle(false);
loading = false;
is_unsaved = false;
});
$doc.on('fv_flowplayer_player_editor_reset', function() {
loading = true;
is_unsaved = true;
has_draft_status = true;
//is_draft_changed = false;
});
$doc.on('fv_flowplayer_shortcode_item_sort', save );
$doc.on('fv_flowplayer_shortcode_item_delete', save );
function save(e){
// "loading" is implicitly set to true to make sure we wait with any saving until
// all existing player's data are loaded and filled into inputs
// ... but if we're creating a new player from scratch, let's ignore it and save data anyway
// if we actually have any data to save
if ( loading ) {
if ( !is_unsaved ) {
return;
} else {
// we're not loading existing player but creating a new one
loading = false;
}
}
//console.log('Change?',e.type,e.currentTarget);
var
ajax_data = build_ajax_data(true),
db_data_loading = true;
for ( var item in ajax_data.videos ) {
// we have video data already loaded from DB,
// ... this is the only way to see if we actually have
// at least a single object key while preserving
// browsers compatibility for browsers without support
// for Object.keys()
db_data_loading = false;
break;
}
if ( db_data_loading || !ajax_data.videos ) {
// editing a player and still waiting for the videos to load from DB
return;
}
if( previous && JSON.stringify(ajax_data) == JSON.stringify(previous) ) {
console.log('Not really!');
return;
}
if( is_saving ) {
console.log('Still saving!');
next = ajax_data;
return;
}
previous = ajax_data;
ajax(ajax_data);
}
function ajax( data ) {
ajax_save_this_please = data;
}
function error(msg) {
is_saving = false;
$el_editor.find('.button-primary').removeAttr('disabled');
overlay_show('message', 'An unexpected error has occurred. Please try again. '+msg, true );
}
setInterval( function() {
if ( !ajax_save_this_please || is_loading_meta_data ) return;
// show error overlay if we have errors
var err = fv_player_editor.has_errors();
if ( err ) {
$el_save_error_p
.data( 'old_txt', $el_save_error.text() )
.text( err );
$el_save_error.show();
return;
} else {
// revert error text and hide error overlay if we have no errors to show
if ( $el_save_error_p.data( 'old_txt ') ) {
$el_save_error_p
.text( $el_save_error_p.data( 'old_txt ') )
.removeData( 'old_txt' );
$el_save_error.hide();
}
}
is_saving = true;
insert_button_toggle_disabled(true);
el_spinner.show();
$('.fv-player-save-error').hide();
debug_log('Running fv_player_db_save Ajax.');
$.post(ajaxurl+'?fv_player_db_save=1', {
action: 'fv_player_db_save',
data: JSON.stringify(ajax_save_this_please),
nonce: fv_player_editor_conf.preview_nonce,
}, function(player) {
try {
$(player.videos).each( function(k,v) {
var item = $('.fv-player-playlist-item').eq(k);
if( !item.data('id_video') ) {
item.attr('data-id_video',v);
}
});
if( next ) {console.log('There is more to do...');
ajax(next);
next = false;
} else {
is_saving = false;
insert_button_toggle_disabled(false);
el_spinner.hide();
$el_save_complete.show().delay( 2500 ).fadeOut(400);
// close the overlay, if we're waiting for the save
if (overlay_close_waiting_for_save) {
// add this player's ID into players that no longer need an edit lock
if (current_player_db_id > 0) {
edit_lock_removal[current_player_db_id] = 1;
}
overlay_close_waiting_for_save = false;
$.fn.fv_player_box.close();
} else if ( player.html ) {
// auto-refresh preview
el_preview_target.html( player.html )
$doc.trigger('fvp-preview-complete');
}
// if we're creating a new player, hide the Save / Insert button and
// add all the data and inputs to page that we need for an existing player
if ( is_unsaved ) {
fv_player_editor.copy_player_button_toggle(false);
init_saved_player_fields( player.id );
current_player_db_id = player.id;
is_unsaved = false;
//is_draft_changed = false;
loading = false;
ajax_save_this_please = false;
}
}
} catch(e) {
error(e);
}
}, 'json' ).error( function() {
$('.fv-player-save-error').show();
el_spinner.hide();
is_saving = false;
});
ajax_save_this_please = false;
}, 1500 );
editor_init();
var $body = jQuery('body');
$body.on('focus', '#fv_player_copy_to_clipboard', function() {
this.select();
});
/**
* Ensure user is notified about using video types which are not supported in playlists
*/
$body.on('keyup', '#fv_wp_flowplayer_field_src, #fv_wp_flowplayer_field_src1, #fv_wp_flowplayer_field_src2', function() {
var result = {
'supported': true
}
var url = jQuery(this).val();
if (
url.indexOf('vimeo.com') > -1 ||
url.indexOf('vimeopro.com') > -1 ||
url.indexOf('youtube.com') > -1 ||
url.indexOf('youtube-nocookie.com') > -1 ||
url.indexOf('youtu.be') > -1
) {
result.supported = false;
}
// fire up a JS event for the FV Player Pro to catch,
// so it can check the URL and make sure we don't show
// a warning message for PRO-supported video types
$doc.trigger('fv-player-editor-src-change', [ url, result, this ]);
// Notice next to the input field
var input_field_notice = jQuery(this).siblings('.fv-player-src-playlist-support-notice');
if( result.supported ) {
input_field_notice.hide();
fv_player_editor.playlist_buttons_disable(false);
} else {
// Show a notice if you have a playlist already
input_field_notice.toggle( fv_player_editor.get_playlist_items_count() > 1 );
// Disable the playlist editing buttons if the video type is not supported in playlists
fv_player_editor.playlist_buttons_disable('FV Player Pro required for playlists with this video type');
}
});
$body.on('change', '#fv_wp_flowplayer_field_src', function() {
var
$element = jQuery(this),
$parent_table = $element.closest('table'),
$playlist_row = jQuery('.fv-player-tab-playlist table tr[data-index="' + $parent_table.attr('data-index') + '"] td.fvp_item_caption'),
value = $element.val(),
update_fields = null,
$chapters_element = $playlist_row = jQuery('.fv-player-tab-subtitles table[data-index="' + $parent_table.attr('data-index') + '"] #fv_wp_flowplayer_field_chapters'),
$caption_element = $parent_table.find('#fv_wp_flowplayer_field_caption'),
$splash_element = $parent_table.find('#fv_wp_flowplayer_field_splash'),
$auto_splash_element = $element.siblings('#fv_wp_flowplayer_field_auto_splash'),
$auto_caption_element = $element.siblings('#fv_wp_flowplayer_field_auto_caption');
// cancel any previous AJAX call
if (typeof($element.data('fv_player_video_data_ajax')) != 'undefined') {
$element.data('fv_player_video_data_ajax').abort();
$element.removeData('fv_player_video_data_ajax');
}
// cancel any previous auto-refresh task
/*if (typeof($element.data('fv_player_video_auto_refresh_task')) != 'undefined') {
clearInterval($element.data('fv_player_video_auto_refresh_task'));
$element.removeData('fv_player_video_auto_refresh_task');
}*/
// set jQuery data related to certain meta data that we may have for current video
if (!$auto_splash_element.length && $splash_element.val() ) {
// splash for this video was manually updated
$splash_element.data('fv_player_user_updated', 1);
console.log('splash for this video was manually updated');
}
if (!$auto_caption_element.length && $caption_element.val() ) {
// caption for this video was manually updated
$caption_element.data('fv_player_user_updated', 1);
console.log('caption for this video was manually updated');
}
// try to check if we have a suitable matcher
for (var vtype in fv_player_editor_matcher) {
if (fv_player_editor_matcher[vtype].matcher.exec(value) !== null) {
update_fields = (fv_player_editor_matcher[vtype].update_fields ? fv_player_editor_matcher[vtype].update_fields : []);
break;
}
}
// only make an AJAX call if we found a matcher
if (update_fields !== null) {
if (update_fields.length) {
// add spinners (loading indicators) to all inputs where data are being loaded
var selector = '#fv_wp_flowplayer_field_src';
if( update_fields.indexOf('caption') > 0 ) selector += ', #fv_wp_flowplayer_field_splash';
if( update_fields.indexOf('splash') > 0 ) selector += ', #fv_wp_flowplayer_field_caption';
$parent_table
.find(selector)
.filter(function () {
var
$e = jQuery(this),
updated_manually = $e.val() && typeof($e.data('fv_player_user_updated')) != 'undefined';
console.log(this.id+' has been updated? '+updated_manually,$e.val());
if (this.id == 'fv_wp_flowplayer_field_caption' && !updated_manually) {
// add spinners (loading indicators) to the playlist table
if ($playlist_row.length) {
$playlist_row.html('<div class="fv-player-shortcode-editor-small-spinner"></div>');
}
}
return !updated_manually;
})
.parent()
.append('<div class="fv-player-shortcode-editor-small-spinner"></div>');
fv_player_editor.meta_data_load_started();
var ajax_call = function () {
debug_log('Running fv_wp_flowplayer_retrieve_video_data Ajax.');
$element.data('fv_player_video_data_ajax', jQuery.post(ajaxurl, {
action: 'fv_wp_flowplayer_retrieve_video_data',
video_url: $element.val(),
cookie: encodeURIComponent(document.cookie),
}, function (json_data) {
fv_player_editor.meta_data_load_finished();
// check if we still have this element on page
if ($element.closest("body").length > 0 && update_fields.length) {
// update all fields that should be updated
for (var i in update_fields) {
switch (update_fields[i]) {
case 'caption':
if (json_data.name) {
if (!$caption_element.val() || typeof($caption_element.data('fv_player_user_updated')) == 'undefined') {
$caption_element.val(json_data.name).trigger('change');
$caption_element.closest('tr').show();
// update caption in playlist table
if ($playlist_row.length) {
$playlist_row.html('<div>' + json_data.name + '</div>');
}
}
}
break;
case 'splash':
if (json_data.thumbnail) {
if (!$splash_element.val() || typeof($splash_element.data('fv_player_user_updated')) == 'undefined') {
$splash_element.val(json_data.thumbnail).trigger('change');
$splash_element.closest('tr').show();
}
}
break;
case 'chapters':
if(json_data.chapters) {
if( !$chapters_element.val() || typeof($chapters_element.data('fv_player_user_updated')) == 'undefined' ) {
$chapters_element.val(json_data.chapters).trigger('change');
$chapters_element.closest('tr').show();
}
}
break;
case 'auto_splash':
if (!$element.siblings('#fv_wp_flowplayer_field_auto_splash').length) {
$element.after('<input type="hidden" name="fv_wp_flowplayer_field_auto_splash" id="fv_wp_flowplayer_field_auto_splash" />');
}
$element.siblings('#fv_wp_flowplayer_field_auto_splash').val(1);
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: jQuery('#fv_wp_flowplayer_field_auto_splash'),
meta_section: 'video',
meta_key: 'auto_splash',
handle_delete: true
});
break;
case 'auto_caption':
if (!$element.siblings('#fv_wp_flowplayer_field_auto_caption').length) {
$element.after('<input type="hidden" name="fv_wp_flowplayer_field_auto_caption" id="fv_wp_flowplayer_field_auto_caption" />');
}
$element.siblings('#fv_wp_flowplayer_field_auto_caption').val(1);
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: jQuery('#fv_wp_flowplayer_field_auto_caption'),
meta_section: 'video',
meta_key: 'auto_caption',
handle_delete: true
});
break;
case 'duration':
if (json_data.duration) {
if (!$element.siblings('#fv_wp_flowplayer_field_duration').length) {
$element.after('<input type="hidden" name="fv_wp_flowplayer_field_duration" id="fv_wp_flowplayer_field_duration" />');
}
var $duration_element = $element.siblings('#fv_wp_flowplayer_field_duration');
$duration_element.val(json_data.duration);
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: $duration_element,
meta_section: 'video',
meta_key: 'duration',
handle_delete: true
});
} else {
var $duration_element = $element.siblings('#fv_wp_flowplayer_field_duration');
if ($duration_element.length) {
$duration_element.val('');
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: $duration_element,
meta_section: 'video',
meta_key: 'duration',
handle_delete: true
});
}
}
break;
case 'last_video_meta_check':
if (json_data.ts) {
if (!$element.siblings('#fv_wp_flowplayer_field_last_video_meta_check').length) {
$element.after('<input type="hidden" name="fv_wp_flowplayer_field_last_video_meta_check" id="fv_wp_flowplayer_field_last_video_meta_check" />');
}
$element.siblings('#fv_wp_flowplayer_field_last_video_meta_check').val(json_data.ts);
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: $element.siblings('#fv_wp_flowplayer_field_last_video_meta_check'),
meta_section: 'video',
meta_key: 'last_video_meta_check',
handle_delete: true
});
} else {
var $last_video_meta_check_element = $element.siblings('#fv_wp_flowplayer_field_last_video_meta_check');
if ($last_video_meta_check_element.length) {
$last_video_meta_check_element.val('');
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: $last_video_meta_check_element,
meta_section: 'video',
meta_key: 'last_video_meta_check',
handle_delete: true
});
}
}
break;
}
}
}
$element.removeData('fv_player_video_data_ajax');
$element.removeData('fv_player_video_data_ajax_retry_count');
// remove spinners
$('.fv-player-shortcode-editor-small-spinner').remove();
}).error(function () {
fv_player_editor.meta_data_load_finished();
// remove element AJAX data
$element.removeData('fv_player_video_data_ajax');
// check if we should still retry
var retry_count = $element.data('fv_player_video_data_ajax_retry_count');
if (typeof(retry_count) == 'undefined' || retry_count < 2) {
ajax_call();
$element.data('fv_player_video_data_ajax_retry_count', (typeof(retry_count) == 'undefined' ? 1 : retry_count + 1));
} else {
// maximum retries reached
$element.removeData('fv_player_video_data_ajax_retry_count');
// check if we still have this element on page
if ($element.closest("body").length > 0) {
// get this element's table
var
$parent_table = $element.closest('table'),
$playlist_row = jQuery('.fv-player-tab-playlist table tr[data-index="' + $parent_table.attr('data-index') + '"] td.fvp_item_caption');
$playlist_row.html($caption_element.val());
}
}
// remove spinners
$('.fv-player-shortcode-editor-small-spinner').remove();
})
);
};
ajax_call();
}
}
});
jQuery('.fv-player-editor-wrapper').each( function() { fv_show_video( jQuery(this) ) }); // show last add more button only
$doc.on( 'fv_flowplayer_shortcode_insert', '.fv-player-editor-field', function() {
fv_load_video_preview( jQuery(this).parents('.fv-player-editor-wrapper'));
} );
/*
Custom Videos feature
TODO: Test
*/
function fv_show_video( wrapper ) {
if( wrapper.find('.fv-player-editor-field').val() ) {
wrapper.find('.edit-video').show();
wrapper.find('.add-video').hide();
}
else {
wrapper.find('.edit-video').hide();
wrapper.find('.add-video').show();
wrapper.find('.fv-player-editor-preview').html('');
}
jQuery('[data-key='+wrapper.data('key')+'] .fv-player-editor-more').last().show(); // show last add more button only
}
/*
Custom Videos feature
TODO: Test
*/
function fv_remove_video( id ) {
$( '#widget-widget_fvplayer-'+id+'-text' ).val("");
fv_show_video(id);
$('#fv_edit_video-'+id+' .video-preview').html('');
}
/*
Custom Videos feature
TODO: Test
*/
function fv_load_video_preview( wrapper ) {
var shortcode = $(wrapper).find('.fv-player-editor-field').val();
var indicator = $("<div class='fv-player-editor-player-loading'><span class='waiting spinner is-active'></span></div>").appendTo('.fp-playlist-external');
if( shortcode && shortcode.length === 0 ) {
return false;
}
shortcode = shortcode.replace( /(width=[\'"])\d*([\'"])/, "$1320$2" ); // 320
shortcode = shortcode.replace( /(height=[\'"])\d*([\'"])/, "$1240$2" ); // 240
var url = fv_player_editor_conf.home_url + '?fv_player_embed='+fv_player_editor_conf.preview_nonce+'&fv_player_preview=' + b64EncodeUnicode(shortcode);
$.get(url, function(response) {
wrapper.find('.fv-player-editor-preview').html( jQuery('#wrapper',response ) );
$doc.trigger('fvp-preview-complete', [ shortcode, wrapper.data('key'), wrapper ] );
indicator.remove();
} );
fv_show_video(wrapper);
}
$doc.on('click','.fv-player-editor-remove', function(e) {console.log('.fv-player-editor-remove');
var wrapper = $(this).parents('.fv-player-editor-wrapper');
if( $('[data-key='+wrapper.data('key')+']').length == 1 ) { // if there is only single video
wrapper.find('.fv-player-editor-field').val('');
fv_show_video(wrapper);
} else {
wrapper.remove();
jQuery('.fv-player-editor-wrapper').each( function() { fv_show_video( jQuery(this) ) }); // show last add more button only
}
return false;
});
$doc.on('click','.fv-player-editor-more', function(e) {
var wrapper = $(this).parents('.fv-player-editor-wrapper');
var new_wrapper = wrapper.clone();
new_wrapper.find('.fv-player-editor-field').val('');
fv_show_video(new_wrapper);
new_wrapper.insertAfter( $('[data-key='+wrapper.data('key')+']:last') ); // insert after last of the kind
$(this).hide();
return false;
});
$doc.on( 'click', '.fv-player-shortcode-copy', function(e) {
var button = $(this);
fv_player_clipboard( $(this).parents('tr').find('.fv-player-shortcode-input').val(), function() {
button.html('Coppied to clipboard!');
setTimeout( function() {
button.html('Copy Shortcode');
}, 1000 );
}, function() {
button.html('Error');
} );
return false;
});
$doc.on('change', '#players_selector', function() {
insert_button_toggle_disabled(false);
// TODO
$el_editor.find('.button-primary').text('Insert');
editor_open(this.value);
});
$doc.on('click', '.fv_player_field_insert-button', function() {
if (is_saving || ajax_save_this_please) {
// for some reason, clicking on already-disabled primary button re-enables it,
// so we'll just need to disable it again here
insert_button_toggle_disabled(true);
} else {
// make sure we mark this player as published in the DB
has_draft_status = false;
editor_submit();
}
});
$doc.on('click', '.playlist_add', function() {
playlist_item_add();
});
$doc.on('click', '.playlist_edit', function() {
if ( jQuery(this).hasClass('disabled') ) {
return false;
}
return playlist_show();
});
// prevent closing of the overlay if we have unsaved data
// unfortunately there is no event for this which we could use
$.fn.fv_player_box.oldClose = $.fn.fv_player_box.close;
$.fn.fv_player_box.close = function() {
// don't close editor if we have errors showing, otherwise we'd just overlay them by an infinite loader
if ( fv_player_editor.has_errors() ) {
return;
}
/*if (is_draft && is_draft_changed && !window.confirm('You have unsaved changes. Are you sure you want to close this dialog and loose them?')) {
return false;
}*/
if ( ( !is_unsaved || is_saving ) && has_draft_status && !is_fv_player_screen( editor_button_clicked ) ) {
// TODO: change into notification bubble
alert('Your new player was saved as a draft. To reopen it, open the editor again and use the "Pick existing player" button.');
}
// prevent closing if we're still saving the data
if ( ajax_save_this_please || is_saving || is_loading_meta_data ) {
// if we already have the overlay changed, bail out
if (overlay_close_waiting_for_save) {
return;
}
overlay_close_waiting_for_save = true;
$('.fv-wp-flowplayer-notice-small, .fv-player-shortcode-editor-small-spinner').hide();
overlay_show('loading');
// call fv_wp_flowplayer_submit() which will create a repeating task
// that will check for all meta data being loaded,
// so we can auto-close this overlay once that's done
editor_submit();
return;
}
// close the dialog if confirmed
$.fn.fv_player_box.oldClose();
// reset variables
is_unsaved = true;
has_draft_status = true;
//is_draft_changed = false;
// manually invoke a heartbeat to remove an edit lock immediatelly
if (current_player_db_id > -1) {
// do this asynchronously to allow our cleanup procedures set lock removal data for the next hearbeat
setTimeout(wp.heartbeat.connectNow, 500);
}
}
/*
Loads and displays a list of all players in a dropdown.
*/
$doc.on('click', '.copy_player', function() {
// show loader
overlay_show('loading');
debug_log('Running fv_player_db_retrieve_all_players_for_dropdown Ajax.');
$.post(ajaxurl, {
// TODO: Nonce
action: 'fv_player_db_retrieve_all_players_for_dropdown',
cookie: encodeURIComponent(document.cookie),
}, function (json_data) {
var overlay = overlay_show('copy_player');
// build the dropdown
var dropdown = [];
for (var i in json_data) {
dropdown.push('<option value="' + json_data[i].id + '">' + (json_data[i].name ? json_data[i].name : 'Player #' + json_data[i].id) + '</option>');
}
// prepend the "Choose a player" option
if (dropdown.length) {
dropdown.unshift('<option hidden disabled selected value>Choose a Player...</option>');
}
overlay.find('select').html( dropdown.join('') );
}).error(function () {
overlay_show('message', 'An unexpected error has occurred. Please try again.');
});
return false;
});
});
/*
* Initializes shortcode, removes playlist items, hides elements, figures out
* which actual field is edited - post editor, widget, etc.
*/
function editor_init() {
// if error / message overlay is visible, hide it
overlay_hide();
// remove hidden meta data inputs
jQuery('input[name="fv_wp_flowplayer_field_duration"], input[name="fv_wp_flowplayer_field_last_video_meta_check"], input[name="fv_wp_flowplayer_field_auto_splash"], input[name="fv_wp_flowplayer_field_auto_caption"]').remove();
// stop and remove any pending AJAX requests to retrieve video meta data
// as well as any auto-update timers
jQuery('input[name="fv_wp_flowplayer_field_src"]').each(function() {
var
$this = jQuery(this),
ajaxData = $this.data('fv_player_video_data_ajax'),
//refreshTask = $this.data('fv_player_video_auto_refresh_task'),
retryData = $this.data('fv_player_video_data_ajax_retry_count');
if (typeof(ajaxData) != 'undefined') {
ajaxData.abort();
$this.removeData('fv_player_video_data_ajax');
}
if (typeof(retryData) != 'undefined') {
$this.removeData('fv_player_video_data_ajax_retry_count');
}
/*if (typeof(refreshTask) != 'undefined') {
clearInterval(refreshTask);
$this.removeData('fv_player_video_auto_refresh_task');
}*/
});
jQuery('#fv_wp_flowplayer_field_player_name').show();
jQuery('#player_id_top_text').html('');
// is there a Custom Video field or Gutenberg field next to the button?
var field = $(editor_button_clicked).parents('.fv-player-editor-wrapper, .fv-player-gutenberg').find('.fv-player-editor-field'),
widget = jQuery('#widget-widget_fvplayer-'+widget_id+'-text');
if( field.length ) {
if (field[0].tagName != 'TEXTAREA' && !field.hasClass('attachement-shortcode')) {
field = field.find('textarea').first();
}
editor_content = jQuery(field).val();
} else if( widget.length ){
editor_content = widget.val();
} else if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length){
editor_content = jQuery('#content:not([aria-hidden=true])').val();
} else if( typeof tinymce !== 'undefined' && typeof tinymce.majorVersion !== 'undefined' && typeof tinymce.activeEditor !== 'undefined' && tinymce.majorVersion >= 4 ){
instance_tinymce = tinymce.activeEditor;
} else if( typeof tinyMCE !== 'undefined' ) {
instance_tinymce = tinyMCE.getInstanceById('content');
} else if(typeof(FCKeditorAPI) !== 'undefined' ){
instance_fp_wysiwyg = FCKeditorAPI.GetInstance('content');
}
jQuery('#fv_wp_flowplayer_file_info').hide();
jQuery(".fv_wp_flowplayer_field_src2_wrapper").hide();
jQuery("#fv_wp_flowplayer_field_src2_uploader").hide();
jQuery(".fv_wp_flowplayer_field_src1_wrapper").hide();
jQuery("#fv_wp_flowplayer_field_src1_uploader").hide();
jQuery("#add_format_wrapper").show();
jQuery(".add_rtmp_wrapper").show();
jQuery(".fv_wp_flowplayer_field_rtmp_wrapper").hide();
$el_preview.attr('class','preview-no');
jQuery('.fv-player-tab-video-files table').each( function(i,e) {
if( i == 0 ) return;
jQuery(e).remove();
} );
jQuery('.fv-player-tab-playlist table tbody tr').each( function(i,e) {
if( i == 0 ) return;
jQuery(e).remove();
} );
jQuery('.fv-player-tab-subtitles').html(template_subtitles_tab);
jQuery('.fv_wp_flowplayer_field_subtitles_lang').val(0);
/**
* TABS
*/
jQuery('#fv-player-shortcode-editor a[data-tab=fv-player-tab-playlist]').hide();
jQuery('#fv-player-shortcode-editor a[data-tab=fv-player-tab-video-files]').trigger('click');
jQuery('.nav-tab').show;
current_player_db_id = -1;
item_index = 0;
editing_video_details = true;
$el_editor.attr('class','is-singular is-singular-active');
//hide empy tabs hide tabs
jQuery('.fv-player-tab-playlist').hide();
jQuery('.fv-player-playlist-item-title').html('');
jQuery('.fv-player-tab-video-files table').show();
jQuery('.playlist_edit').html(jQuery('.playlist_edit').data('create')).removeClass('button-primary').addClass('button');
tabs_refresh();
fv_player_editor.playlist_buttons_disable(false);
fv_player_editor.playlist_buttons_toggle(true);
set_embeds('');
el_preview_target.html('');
if( typeof(fv_player_shortcode_editor_ajax) != "undefined" ) {
fv_player_shortcode_editor_ajax.abort();
}
$doc.trigger('fv-player-editor-init');
}
/*
* Checks all the input fields and created the JavaScript object.
* Works when saving and also previewing.
*/
function build_ajax_data( give_it_all ) {
var
$tabs = $el_editor.find('.fv-player-tab'),
regex = /((fv_wp_flowplayer_field_|fv_wp_flowplayer_hlskey|fv_player_field_ppv_)[^ ]*)/g,
data = {'video_meta' : {}, 'player_meta' : {}},
end_of_playlist_action = jQuery('#fv_wp_flowplayer_field_end_actions').val(),
single_video_showing = !give_it_all && editing_video_details;
// special processing for end video actions
if (end_of_playlist_action && end_of_playlist_action != 'Nothing') {
switch (end_of_playlist_action) {
case 'redirect':
data['fv_wp_flowplayer_field_end_action_value'] = jQuery('#fv_wp_flowplayer_field_redirect').val();
break;
case 'popup':
data['fv_wp_flowplayer_field_end_action_value'] = jQuery('#fv_wp_flowplayer_field_popup_id').val();
break;
case 'email_list':
data['fv_wp_flowplayer_field_end_action_value'] = jQuery('#fv_wp_flowplayer_field_email_list').val();
break;
}
}
// add playlist name
data['fv_wp_flowplayer_field_player_name'] = jQuery('#fv_wp_flowplayer_field_player_name').val();
// add post ID manually here, as it's a special meta key
fv_flowplayer_insertUpdateOrDeletePlayerMeta({
data: data,
meta_section: 'player',
meta_key: 'post_id',
element: jQuery('#fv_wp_flowplayer_field_post_id')[0],
handle_delete: false
});
// trigger meta data save events, so we get meta data from different
// plugins included as we post
jQuery(document).trigger('fv_flowplayer_player_meta_save', [data, $tabs]);
$tabs.each(function() {
var
$tab = jQuery(this),
is_videos_tab = $tab.hasClass('fv-player-tab-video-files'),
is_subtitles_tab = $tab.hasClass('fv-player-tab-subtitles'),
$tables = ((is_videos_tab || is_subtitles_tab) ? $tab.find('table') : $tab.find('input, select, textarea')),
save_index = -1;
// prepare video and subtitles data, which are duplicated through their input names
if (is_videos_tab) {
data['videos'] = {};
} else if (is_subtitles_tab) {
data['video_meta']['subtitles'] = {};
data['video_meta']['transcript'] = {};
data['video_meta']['chapters'] = {};
}
// iterate over all tables in tabs
$tables.each(function() {
// only videos, subtitles tabs have tables, so we only need to search for their inputs when working with those
var
$inputs = ((is_videos_tab || is_subtitles_tab) ? jQuery(this).find('input, select, textarea') : jQuery(this)),
table_index = jQuery(this).data('index');
save_index++;
$inputs.each(function() {
var
$this = jQuery(this),
$parent_tr = $this.closest('tr'),
optionsHaveNoValue = false, // will become true for dropdown options without values
$valueLessOptions = null,
isDropdown = this.nodeName == 'SELECT';
// exceptions for selectively hidden fields, i.e. empty tabs with no content etc.
if ($parent_tr.hasClass('fv_player_interface_hide') && $parent_tr.css('display') == 'none') {
//return;
// why? hidden tabs would have no content... have you tested this? maybe we should return the return? :-P
}
// check for a select without any option values, in which case we'll use their text
if (isDropdown) {
$valueLessOptions = $this.find('option:not([value])');
if ($valueLessOptions.length == this.length) {
optionsHaveNoValue = true;
}
}
while ((m = regex.exec(this.name)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// let plugins update video meta, if applicable
jQuery(document).trigger('fv_flowplayer_video_meta_save', [data, save_index, this]);
// videos tab
if (is_videos_tab) {
if (!data['videos'][save_index]) {
data['videos'][save_index] = {
id: jQuery('.fv-player-playlist-item[data-index=' + table_index + ']').data('id_video')
};
}
// check for a meta field
if (fv_wp_flowplayer_check_for_video_meta_field(m[1])) {
// prepare HLS data, if not prepared yet
if (!data['video_meta']['video']) {
data['video_meta']['video'] = {};
}
if (!data['video_meta']['video'][save_index]) {
data['video_meta']['video'][save_index] = {};
}
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
data: data,
meta_section: 'video',
meta_key: get_field_name(m[1]),
meta_index: save_index,
element: this
});
} else {
// ordinary video field
// check dropdown for its value based on values in it
if (isDropdown) {
var opt_value = fv_wp_flowplayer_get_correct_dropdown_value(optionsHaveNoValue, $valueLessOptions, this);
// if there were any problems, just return an empty object
if (opt_value === false) {
return {};
} else {
data['videos'][save_index][m[1]] = opt_value;
}
} else {
data['videos'][save_index][m[1]] = this.value;
}
}
}
// subtitles tab, subtitles inputs
else if (is_subtitles_tab) {
if($this.hasClass('fv_wp_flowplayer_field_subtitles')) {
if (!data['video_meta']['subtitles'][save_index]) {
data['video_meta']['subtitles'][save_index] = [];
}
// jQuery-select the SELECT element when we get an INPUT, since we need to pair them
if (this.nodeName == 'INPUT') {
data['video_meta']['subtitles'][save_index].push({
code : $this.siblings('select:first').val(),
file : this.value,
id: $this.parent().data('id_subtitles')
});
}
}
// subtitles tab, chapters input
else if ($this.attr('id') == 'fv_wp_flowplayer_field_chapters') {
if (!data['video_meta']['chapters'][save_index]) {
data['video_meta']['chapters'][save_index] = {};
}
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
data: data,
meta_section: 'chapters',
meta_key: 'file',
meta_index: save_index,
element: $this
});
}
// subtitles tab, transcript input
else if (is_subtitles_tab && $this.hasClass('fv_wp_flowplayer_field_transcript')) {
if (!data['video_meta']['transcript'][save_index]) {
data['video_meta']['transcript'][save_index] = {};
}
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
data: data,
meta_section: 'transcript',
meta_key: 'file',
meta_index: save_index,
element: $this
});
}
}
// all other tabs
else {
if (this.nodeName == 'INPUT' && this.type.toLowerCase() == 'checkbox') {
// some player attributes are meta data
if (fv_wp_flowplayer_check_for_player_meta_field(m[1])) {
// meta data input
fv_flowplayer_insertUpdateOrDeletePlayerMeta({
data: data,
meta_section: 'player',
meta_key: get_field_name(m[1]),
element: this,
handle_delete: false
});
} else {
// ordinary player attribute
data[m[1]] = (this.type.toLowerCase() == 'checkbox' ? this.checked ? 'true' : '' : this.value);
}
} else {
// check dropdown for its value based on values in it
if (isDropdown) {
var opt_value = fv_wp_flowplayer_get_correct_dropdown_value(optionsHaveNoValue, $valueLessOptions, this);
// if there were any problems, just return an empty object
if (opt_value === false) {
return {};
} else {
if (fv_wp_flowplayer_check_for_player_meta_field(m[1])) {
// meta data input
fv_flowplayer_insertUpdateOrDeletePlayerMeta({
data: data,
meta_section: 'player',
meta_key: get_field_name(m[1]),
element: this,
handle_delete: false
});
} else {
// ordinary player attribute
data[m[1]] = opt_value.toLowerCase();
}
}
} else {
if (fv_wp_flowplayer_check_for_player_meta_field(m[1])) {
// meta data input
fv_flowplayer_insertUpdateOrDeletePlayerMeta({
data: data,
meta_section: 'player',
meta_key: get_field_name(m[1]),
element: this,
handle_delete: false
});
} else {
// ordinary player attribute
data[m[1]] = this.value;
}
}
}
}
}
});
});
});
// remove any empty videos, i.e. without a source
// this is used when loading data from DB to avoid previewing an empty video that's in editor by default
if (data['videos']) {
var
data_videos_new = {},
x = 0;
for (var i in data['videos']) {
if (data['videos'][i]['src'] || data['videos'][i]['src1'] || !data['videos'][i]['src2']) {
// if we should show preview of a single video only, add that video here,
// otherwise add all videos here
if (!single_video_showing || x == item_index) {
data_videos_new[x++] = data['videos'][i];
} else {
x++;
}
}
}
data['videos'] = data_videos_new;
}
// add player ID and deleted elements for a DB update
var $updateElement = jQuery('#fv-player-id_player');
if ($updateElement.length) {
data['update'] = $updateElement.val();
data['deleted_videos'] = jQuery('#fv-player-deleted_videos').val();
data['deleted_video_meta'] = jQuery('#fv-player-deleted_video_meta').val();
data['deleted_player_meta'] = jQuery('#fv-player-deleted_player_meta').val();
}
return data;
}
function debug_log( message, details ) {
console.log( 'FV Player Editor: '+message);
if( details ) {
console.log(details);
}
}
/*
* Closing the editor
* * updates the wp-admin -> FV Player screen
* * sets data for WordPress Heartbeat to unlock the player
* * calls editor_init() for editor clean-up
*/
function editor_close() {
// don't close editor if we have errors showing, otherwise we'd just overlay them by an infinite loader
if ( fv_player_editor.has_errors() ) {
return;
}
editor_resize_height_record = 0;
// remove TinyMCE hidden tags and other similar tags which aids shortcode editing
// to prevent opening the same player over and over
editor_content = editor_content.replace(fv_wp_flowplayer_re_insert,'');
editor_content = editor_content.replace(fv_wp_flowplayer_re_edit,'');
editor_content = editor_content.replace(/#fvp_placeholder#/, '');
set_post_editor_content(editor_content);
// this variable needs to be reset here and not in editor_init
current_video_to_edit = -1;
if ( !is_fv_player_screen(editor_button_clicked) ) {
// todo: what it the point of this call being made?
// TODO: Perhaps to ensure the temporary strings in editor are removed?
//set_post_editor_content( editor_content.replace( fv_wp_flowplayer_re_insert, '' ) );
// trigger update for the FV Player Custom Videos/Meta Box and Gutenberg field for preview refresh purposes
var
$editor_button_clicked = $(editor_button_clicked),
$fv_player_custom_meta_box = $editor_button_clicked.parents('.fv-player-editor-wrapper').find('.fv-player-editor-field'),
$fv_player_gutenberg = $editor_button_clicked.parents('.fv-player-gutenberg');
if ( $fv_player_custom_meta_box.length ) {
$fv_player_custom_meta_box.trigger('fv_flowplayer_shortcode_insert');
}
if ( $fv_player_gutenberg.length ) {
var gutenbergTextarea = ($fv_player_gutenberg[0].tagName == 'TEXTAREA' ? $fv_player_gutenberg[0] : $fv_player_gutenberg.find('textarea').first()[0]);
fv_player_editor.gutenberg_preview( $fv_player_gutenberg, gutenbergTextarea.value );
}
} else if( current_player_db_id > -1 ) {
var playerRow = $('#the-list span[data-player_id="' + current_player_db_id + '"]')
if( playerRow.length == 0 ) {
var firstRow = $('#the-list tr:first'),
newRow = firstRow.clone();
newRow.find('td').html('');
playerRow = newRow.find('td').eq(0);
firstRow.before( newRow )
}
playerRow.append(' <div class="fv-player-shortcode-editor-small-spinner"> </div>');
$.get(
fv_player_editor_conf.admin_url + '&id=' + current_player_db_id,
function (response) {
playerRow.closest('tr').replaceWith( $(response).find('#the-list tr') );
});
}
// we need to do this now to make sure Heartbeat gets the correct data
if (current_player_db_id > -1 ){
edit_lock_removal[current_player_db_id] = 1;
current_player_db_id = -1;
}
editor_init();
}
/*
* removes previous values from editor
* fills new values from shortcode
*
* @param {int} db_id Optional, force load of specified player ID
*/
function editor_open(db_id) {
editor_resize_height_record = 0;
$('#fv_player_box').removeAttr('tabindex');
editor_init();
// remove any DB data IDs that may be left in the form
$el_editor.find('[data-id]').removeData('id').removeAttr('data-id');
$el_editor.find('[data-id_video]').removeData('id_video').removeAttr('data-id_video');
$el_editor.find('[data-id_subtitles]').removeData('id_subtitles').removeAttr('data-subtitles');
// fire up editor reset event, so plugins can clear up their data IDs as well
var $doc = jQuery(document);
$doc.trigger('fv_flowplayer_player_editor_reset');
// reset content of any input fields, except what has .extra-field
$el_editor.find("input:not(.extra-field)").each( function() { jQuery(this).val( '' ); jQuery(this).attr( 'checked', false ) } );
$el_editor.find("textarea").each( function() { jQuery(this).val( '' ) } );
$el_editor.find('select:not([multiple])').prop('selectedIndex',0); // select first index, ignore multiselect - let it be handled separately
$el_editor.find("[name=fv_wp_flowplayer_field_caption]").each( function() { jQuery(this).val( '' ) } );
$el_editor.find("[name=fv_wp_flowplayer_field_caption]").each( function() { jQuery(this).val( '' ) } );
$el_editor.find("[name=fv_wp_flowplayer_field_splash_text]").each( function() { jQuery(this).val( '' ) } );
$el_editor.find(".fv_player_field_insert-button").text( 'Insert' );
var
field = $(editor_button_clicked).parents('.fv-player-editor-wrapper, .fv-player-gutenberg').find('.fv-player-editor-field'),
is_gutenberg = $(editor_button_clicked).parents('.fv-player-gutenberg').length;
if (!db_id) {
// Edit button on wp-admin -> FV Player screen
if (is_fv_player_screen_edit(editor_button_clicked)) {
current_player_db_id = $(editor_button_clicked).data('player_id');
debug_log('Loading for FV Player screen, player id: '+current_player_db_id );
// create an artificial shortcode from which we can extract the actual player ID later below
editor_content = '[fvplayer id="' + current_player_db_id + '"]';
shortcode = [editor_content];
}
// Add new button on wp-admin -> FV Player screen
else if (is_fv_player_screen_add_new(editor_button_clicked)) {
debug_log('Loading for FV Player screen, new player' );
// create empty shortcode for Add New button on the list page
editor_content = '';
shortcode = '';
}
// custom Field or Widget
else if (field.length || jQuery('#widget-widget_fvplayer-' + widget_id + '-text').length) {
debug_log('Loading for custom field or a widget...');
// this is a horrible hack as it adds the hidden marker to the otherwise clean text field value
// just to make sure the shortcode varible below is parsed properly.
// But it allows some extra text to be entered into the text widget, so for now - ok
if (editor_content.match(/\[/)) {
editor_content = '[<' + helper_tag +' rel="FCKFVWPFlowplayerPlaceholder">­</' + helper_tag + '>' + editor_content.replace('[', '') + '';
} else {
editor_content = '<' + helper_tag + ' rel="FCKFVWPFlowplayerPlaceholder">­</' + helper_tag + '>' + editor_content + '';
}
}
// TinyMCE in Text Mode
else if (typeof (FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length) {
debug_log('Loading for TinyMCE in Text Mode...');
var position = jQuery('#content:not([aria-hidden=true])').prop('selectionStart');
// look for start of shortcode
for (var start = position; start--; start >= 0) {
if (editor_content[start] == '[') {
var sliced_content = editor_content.slice(start);
var matched = sliced_content.match(/^\[fvplayer[^\[\]]*]?/);
// found the shortcode!
if (matched) {
shortcode = matched;
}
break;
} else if (editor_content[start] == ']') {
break
}
}
// TODO: It would be better to use #fv_player_editor_{random number}# and remember it for the editing session
editor_content = editor_content.slice(0, position) + '#fvp_placeholder#' + editor_content.slice(position);
}
// Foliopress WYSIWYG
else if (instance_tinymce == undefined || (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor.isHidden())) {
debug_log('Loading for Foliopress WYSIWYG...' );
editor_content = instance_fp_wysiwyg.GetHTML();
if (editor_content.match(fv_wp_flowplayer_re_insert) == null) {
instance_fp_wysiwyg.InsertHtml('<' + fvwpflowplayer_helper_tag + ' rel="FCKFVWPFlowplayerPlaceholder">­</' + fvwpflowplayer_helper_tag + '>');
editor_content = instance_fp_wysiwyg.GetHTML();
}
} else {
debug_log('Loading for TinyMCE in Visual Mode...' );
// TinyMCE in Visual Mode
editor_content = instance_tinymce.getContent();
instance_tinymce.settings.validate = false;
if (editor_content.match(fv_wp_flowplayer_re_insert) == null) {
var tags = ['b', 'span', 'div'];
for (var i in tags) {
instance_tinymce.execCommand('mceInsertContent', false, '<' + tags[i] + ' data-mce-bogus="1" rel="FCKFVWPFlowplayerPlaceholder"></' + tags[i] + '>');
editor_content = instance_tinymce.getContent();
fv_wp_flowplayer_re_edit = new RegExp('\\[f[^\\]]*?<' + tags[i] + '[^>]*?rel="FCKFVWPFlowplayerPlaceholder"[^>]*?>.*?</' + tags[i] + '>.*?[^\]\\]', "mi");
fv_wp_flowplayer_re_insert = new RegExp('<' + tags[i] + '[^>]*?rel="FCKFVWPFlowplayerPlaceholder"[^>]*?>.*?</' + tags[i] + '>', "gi");
if (editor_content.match(fv_wp_flowplayer_re_insert)) {
break;
}
}
}
instance_tinymce.settings.validate = true;
}
}
var content = editor_content.replace(/\n/g, '\uffff');
// if we've got a numeric DB ID passed to this function, use it directly
// but don't replace editor_content, since we'll need that to be actually updated
// rather then set to a player ID
if (db_id) {
debug_log('Loading for player id: '+db_id );
content = db_id;
// we loose the #fvp_placeholder# placeholder in TinyMCE text mode, so let's re-add it here
if (typeof (FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length) {
var position = jQuery('#content:not([aria-hidden=true])').prop('selectionStart');
// look for start of shortcode
for (var start = position; start--; start >= 0) {
if (editor_content[start] == '[') {
var sliced_content = editor_content.slice(start);
var matched = sliced_content.match(/^\[fvplayer[^\[\]]*]?/);
// found the shortcode!
if (matched) {
shortcode = matched;
}
break;
} else if (editor_content[start] == ']') {
break
}
}
// TODO: It would be better to use #fv_player_editor_{random number}# and remember it for the editing session
editor_content = editor_content.slice(0, position) + '#fvp_placeholder#' + editor_content.slice(position);
}
}
if(typeof(shortcode) == 'undefined'){
if (!db_id) {
var shortcode = content.match( fv_wp_flowplayer_re_edit );
// Gutenberg
if (is_gutenberg) {
shortcode = [ content ];
}
} else {
var shortcode = ['fvplayer id="' + db_id + '"'];
}
}
// remove visual editor placeholders etc.
if (shortcode && shortcode[0]) {
shortcode = shortcode[0]
.replace(/^\[|]+$/gm, '')
.replace(fv_wp_flowplayer_re_insert, '')
.replace(/\\'/g, ''');
}
if( shortcode != null && typeof(shortcode) != 'undefined' && typeof(shortcode[0]) != 'undefined') {
debug_log('Loading shortcode: '+shortcode );
// check for new, DB-based player shortcode
var result = /fvplayer.* id="([\d,]+)"/g.exec(shortcode);
if (result !== null) {
var
shortcode_parse_fix = shortcode
.replace(/(popup|ad)='[^']*?'/g, '')
.replace(/(popup|ad)="(.*?[^\\\\/])"/g, '');
shortcode_remains = shortcode_parse_fix.replace( /^\S+\s*?/, '' );
// DB-based player, create a "wait" overlay
overlay_show('loading');
// store player ID into fv_player_conf, so we can keep sending it
// in WP heartbeat
current_player_db_id = result[1];
debug_log('Loading shortcode player id: '+current_player_db_id );
if (edit_lock_removal[result[1]]) {
delete edit_lock_removal[result[1]];
}
// check if we don't have multiple-playlists shortcode,
// in which case we need to stop and show an error message
if (shortcode.indexOf(',') > -1) {
overlay_show('message', 'Shortcode editor is not available for multiple players shortcode tag.');
return;
}
// stop Ajax saving that might occur from thinking it's a draft taking place
is_unsaved = false;
// now load playlist data
// load video data via an AJAX call
debug_log('Running fv_player_db_load Ajax.');
fv_player_shortcode_editor_ajax = jQuery.post(ajaxurl+'?fv_player_db_load', {
action : 'fv_player_db_load',
nonce : fv_player_editor_conf.db_load_nonce,
playerID : result[1]
}, function(response) {
var vids = response['videos'];
debug_log('Finished fv_player_db_load Ajax.',response);
if (response) {
if( typeof(response) != "object" ) {
overlay_show('message', 'Error: '+response);
// The editor failed to load, it's not locked
edit_lock_removal[current_player_db_id] = 1;
return;
}
init_saved_player_fields( result[1] );
// remove everything with index 0 and the initial video placeholder,
// otherwise our indexing & previews wouldn't work correctly
jQuery('[data-index="0"]').remove();
jQuery('.fv-player-tab-playlist table tbody tr').remove();
jQuery('.fv-player-tab-video-files table').remove();
set_embeds(response['embeds']);
// fire the player load event to cater for any plugins listening
var $doc = jQuery(document);
$doc.trigger('fv_flowplayer_player_meta_load', [response]);
// used several times below, so it's in a function
function set_player_field(key, value, id, video_table_index) {
var
real_key = fv_wp_flowplayer_map_names_to_editor_fields(key),
real_val = fv_wp_flowplayer_map_db_values_to_field_values(key, value),
// try ID first
$element = jQuery((typeof(video_table_index) != 'undefined' ? '.fv-player-tab table[data-id_video=' + video_table_index + '] ' : '') + '#' + real_key);
// special processing for end video actions
if (real_key == 'fv_wp_flowplayer_field_end_action_value') {
var end_of_playlist_action = jQuery('#fv_wp_flowplayer_field_end_actions').val();
// to actually show the value, we need to trigger a change event on the end_actions dropdown itself
jQuery('#fv_wp_flowplayer_field_end_actions').trigger('change');
switch (end_of_playlist_action) {
case 'redirect':
jQuery('#fv_wp_flowplayer_field_redirect').val(value);
break;
case 'popup':
jQuery('#fv_wp_flowplayer_field_popup_id').val(value);
break;
case 'email_list':
jQuery('#fv_wp_flowplayer_field_email_list').val(value);
break;
}
return;
} else if (['fv_wp_flowplayer_field_email_list', 'fv_wp_flowplayer_field_popup_id', 'fv_wp_flowplayer_field_redirect'].indexOf(real_key) > -1) {
// ignore the original fields, if we still use old DB values
return;
}
if (!$element.length) {
// no element with this ID found, we need to go for a name
$element = jQuery((typeof(video_table_index) != 'undefined' ? '.fv-player-tab table[data-id_video=' + video_table_index + '] ' : '') + '[name="' + real_key + '"]');
}
// player and video IDs wouldn't have corresponding fields
if ($element.length) {
// dropdowns could have capitalized values
if ($element.get(0).nodeName == 'SELECT') {
if ($element.find('option[value="' + real_val + '"]').length) {
$element.val(real_val);
} else {
// try capitalized
var caps = real_val.charAt(0).toUpperCase() + real_val.slice(1);
$element.find('option').each(function() {
if (this.text == caps) {
$element.val(caps);
}
});
}
} else if ($element.get(0).nodeName == 'INPUT' && $element.get(0).type.toLowerCase() == 'checkbox') {
if (real_val === '1' || real_val === 'on' || real_val === 'true') {
$element.attr('checked', 'checked');
} else {
$element.removeAttr('checked');
}
} else {
$element.val(real_val);
}
// if an ID exists, this is a meta field
// and the data id needs to be added to it as well
if (typeof(id) != 'undefined') {
$element.attr('data-id', id);
}
}
}
for (var key in response) {
// put the field value where it belongs
if (key !== 'videos') {
// in case of meta data, proceed with each player meta one by one
if (key == 'meta') {
for (var i in response[key]) {
set_player_field(response[key][i]['meta_key'], response[key][i]['meta_value'], response[key][i]['id']);
}
} else {
set_player_field(key, response[key]);
}
}
}
// add videos from the DB
for (var x in vids) {
var
subs = [],
transcript = null,
chapters = null,
video_meta = [];
// add all subtitles, chapters and transcripts
if (vids[x].meta && vids[x].meta.length) {
for (var m in vids[x].meta) {
// subtitles
if (vids[x].meta[m].meta_key.indexOf('subtitles') > -1) {
subs.push({
lang: vids[x].meta[m].meta_key.replace('subtitles_', ''),
file: vids[x].meta[m].meta_value,
id: vids[x].meta[m].id
});
}
// chapters
if (vids[x].meta[m].meta_key.indexOf('chapters') > -1) {
chapters = {
id: vids[x].meta[m].id,
value: vids[x].meta[m].meta_value
};
}
// transcript
if (vids[x].meta[m].meta_key === 'transcript') {
transcript = {
id: vids[x].meta[m].id,
value: vids[x].meta[m].meta_value
};
}
// general video meta
if (vids[x].meta[m].meta_key.indexOf('live') > -1 || ['dvr', 'duration', 'last_video_meta_check', 'auto_splash', 'auto_caption'].indexOf(vids[x].meta[m].meta_key) > -1) {
video_meta.push(vids[x].meta[m]);
}
}
}
$video_data_tab = playlist_item_add(vids[x], false, subs);
$subtitles_tab = $video_data_tab.parents('.fv-player-tabs:first').find('.fv-player-tab-subtitles table:eq(' + $video_data_tab.data('index') + ')');
// add chapters and transcript
if (chapters){
$subtitles_tab.find('#fv_wp_flowplayer_field_chapters').val(chapters.value).attr('data-id', chapters.id);
}
if (transcript) {
$subtitles_tab.find('.fv_wp_flowplayer_field_transcript').val(transcript.value).attr('data-id', transcript.id);
}
if (video_meta.length) {
for (var i in video_meta) {
// video duration hidden input
if (['duration', 'last_video_meta_check', 'auto_splash', 'auto_caption'].indexOf(video_meta[i].meta_key) > -1) {
$video_data_tab.find('#fv_wp_flowplayer_field_src').after('<input type="hidden" name="fv_wp_flowplayer_field_' + video_meta[i].meta_key + '" id="fv_wp_flowplayer_field_' + video_meta[i].meta_key + '" value="' + video_meta[i].meta_value + '" data-id="' + video_meta[i].id + '" />');
} else {
// predefined meta input with field already existing in the dialog
set_player_field(video_meta[i].meta_key, video_meta[i].meta_value, video_meta[i].id, video_meta[i].id_video);
}
}
}
// fire up meta load event for this video, so plugins can process it and react
$doc.trigger('fv_flowplayer_video_meta_load', [x, vids[x].meta, $video_data_tab , $subtitles_tab]);
}
// show playlist instead of the "add new video" form
// if we have more than 1 video
if( current_video_to_edit > -1 ) {
playlist_item_show(current_video_to_edit);
} else if (vids.length > 1) {
playlist_show();
} else {
playlist_item_show(0);
}
// if this player is published, mark it as such
has_draft_status = ( response.status == 'draft' );
}
overlay_hide();
if ( response.html ) {
// auto-refresh preview
el_preview_target.html( response.html )
$doc.trigger('fvp-preview-complete');
}
// show the Insert button, as this is only used when adding a new player into a post
// and using the Pick existing player button, where we need to be able to actually
// insert the player code into the editor
// ... also, keep the Pick existing player button showing, if we decided to choose
// a different player
if (db_id) {
fv_player_editor.insert_button_toggle(true);
fv_player_editor.copy_player_button_toggle(true);
} else if ( response.status == 'draft' ) {
// show Save / Insert button, as we're still
// in draft mode for this player
fv_player_editor.insert_button_toggle(true);
fix_save_btn_text();
}
// hotfix:
// make sure the width and height inputs are in sync and have the correct value,
// as we have duplicate fields for them in 2 places (video tab and options tab)
// and if there is only a single video, the video tab takes precedence,
// otherwise it's the options tab
if ( $('.fv-player-tab-playlist table .ui-sortable-handle').length > 1) {
// multiple videos playlist, options tab values must be filled-in
$('.fv-player-tab-options .fv_wp_flowplayer_field_width').val(response.width);
$('.fv-player-tab-options .fv_wp_flowplayer_field_height').val(response.height)
} else {
// single video playlist, video tab values must be filled-in
$('.fv-player-tab-video-files .fv_wp_flowplayer_field_width').val(response.width);
$('.fv-player-tab-video-files .fv_wp_flowplayer_field_height').val(response.height);
}
$doc.trigger('fv_player_editor_finished');
$('#fv_wp_flowplayer_field_src').trigger('keyup'); // to ensure we show/hide all relevent notices
}).error(function(xhr) {
if (xhr.status == 404) {
overlay_show('message', 'The requested player could not be found. Please try again.');
} else {
overlay_show('message', 'An unexpected error has occurred. Please try again.');
}
// show the Insert button, as this is only used when adding a new player into a post
// and using the Pick existing player button, where we need to be able to actually
// insert the player code into the editor
// ... also, keep the Pick existing player button showing, if we decided to choose
// a different player
if (db_id) {
fv_player_editor.insert_button_toggle(true);
fv_player_editor.copy_player_button_toggle(true);
}
});
} else {
debug_log('Loading shortcode without player id...');
$doc.trigger('fv-player-editor-non-db-shortcode');
// ordinary text shortcode in the editor
var shortcode_parse_fix = shortcode.replace(/(popup|ad)='[^']*?'/g, '');
shortcode_parse_fix = shortcode_parse_fix.replace(/(popup|ad)="(.*?[^\\\\/])"/g, '');
shortcode_remains = shortcode_parse_fix.replace( /^\S+\s*?/, '' );
var srcurl = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, 'src' );
var srcurl1 = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'src1' );
var srcurl2 = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'src2' );
var srcrtmp = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'rtmp' );
var srcrtmp_path = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'rtmp_path' );
var iwidth = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, 'width' );
var iheight = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, 'height' );
var sad_skip = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'ad_skip' );
var salign = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'align' );
var scontrolbar = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'controlbar' );
var sautoplay = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'autoplay' );
var sliststyle = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'liststyle' );
var sembed = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, 'embed' );
var sloop = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'loop' );
var slive = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'live' );
var sshare = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'share', false, fv_wp_flowplayer_share_parse_arg );
var sspeed = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'speed' );
var ssplash = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'splash' );
var ssplashend = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'splashend' );
var ssticky = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'sticky' );
var splaylist_advance = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'playlist_advance' );
var ssubtitles = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'subtitles' );
var aSubtitlesLangs = shortcode.match(/subtitles_[a-z][a-z]+/g);
for( var i in aSubtitlesLangs ){ // move
fv_wp_flowplayer_shortcode_parse_arg( shortcode, aSubtitlesLangs[i], false, fv_wp_flowplayer_subtitle_parse_arg );
}
if(!aSubtitlesLangs){ // move
subtitle_language_add(false, false );
}
var smobile = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'mobile' );
var sredirect = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'redirect' );
var sCaptions = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'caption' );
var sSplashText = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'splash_text' );
var sPlaylist = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'playlist' );
var sad = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'ad', true );
var iadwidth = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'ad_width' );
var iadheight = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'ad_height' );
if( srcrtmp != null && srcrtmp[1] != null ) {
jQuery(".fv_wp_flowplayer_field_rtmp").val( srcrtmp[1] );
jQuery(".fv_wp_flowplayer_field_rtmp_wrapper").show();
jQuery(".add_rtmp_wrapper").hide();
}
if( srcrtmp_path != null && srcrtmp_path[1] != null ) {
jQuery(".fv_wp_flowplayer_field_rtmp_path").val( srcrtmp_path[1] );
jQuery(".fv_wp_flowplayer_field_rtmp_wrapper").show();
jQuery(".add_rtmp_wrapper").hide();
}
var playlist_row = jQuery('.fv-player-tab-playlist tbody tr:first')
if( srcurl != null && srcurl[1] != null )
document.getElementById("fv_wp_flowplayer_field_src").value = srcurl[1];
if( srcurl1 != null && srcurl1[1] != null ) {
document.getElementById("fv_wp_flowplayer_field_src1").value = srcurl1[1];
jQuery(".fv_wp_flowplayer_field_src1_wrapper").css( 'display', 'table-row' );
//document.getElementById("fv_wp_flowplayer_field_src1_uploader").style.display = 'table-row';
if( srcurl2 != null && srcurl2[1] != null ) {
document.getElementById("fv_wp_flowplayer_field_src2").value = srcurl2[1];
jQuery(".fv_wp_flowplayer_field_src2_wrapper").css( 'display', 'table-row' );
//document.getElementById("fv_wp_flowplayer_field_src2_uploader").style.display = 'table-row';
document.getElementById("add_format_wrapper").style.display = 'none';
}
}
if( srcurl != null && srcurl[1] != null ) {
get_field('src').val(srcurl[1]);
playlist_row.find('.fvp_item_video-filename').html( srcurl[1] );
}
get_field('width').val(iwidth[1] || '');
get_field('height').val(iheight[1] || '');
if( sautoplay != null && sautoplay[1] != null ) {
if (sautoplay[1] == 'true')
get_field("autoplay")[0].selectedIndex = 1;
if (sautoplay[1] == 'false')
get_field("autoplay")[0].selectedIndex = 2;
if (sautoplay[1] == 'muted')
get_field("autoplay")[0].selectedIndex = 3;
}
if( sliststyle != null && sliststyle[1] != null ) {
var objPlaylistStyle = get_field("playlist")[0];
if (sliststyle[1] == 'horizontal') objPlaylistStyle.selectedIndex = 1;
if (sliststyle[1] == 'tabs') objPlaylistStyle.selectedIndex = 2;
if (sliststyle[1] == 'prevnext') objPlaylistStyle.selectedIndex = 3;
if (sliststyle[1] == 'vertical') objPlaylistStyle.selectedIndex = 4;
if (sliststyle[1] == 'slider') objPlaylistStyle.selectedIndex = 5;
if (sliststyle[1] == 'season') objPlaylistStyle.selectedIndex = 6;
if (sliststyle[1] == 'polaroid') objPlaylistStyle.selectedIndex = 7;
if (sliststyle[1] == 'text') objPlaylistStyle.selectedIndex = 8;
}
if( sembed != null && sembed[1] != null ) {
if (sembed[1] == 'true')
get_field("embed")[0].selectedIndex = 1;
if (sembed[1] == 'false')
get_field("embed")[0].selectedIndex = 2;
}
if( smobile != null && smobile[1] != null )
get_field("mobile").val(smobile[1]);
if( ssplash != null && ssplash[1] != null ) {
get_field("splash").val(ssplash[1]);
playlist_row.find('.fvp_item_splash').html( '<img width="120" src="'+ssplash[1]+'" />' );
}
var aSubtitles = false;
if( ssubtitles != null && ssubtitles[1] != null ) {
aSubtitles = ssubtitles[1].split(';');
get_field("subtitles").eq(0).val( aSubtitles[0] );
aSubtitles.shift(); // the first item is no longer needed for playlist parsing which will follow
}
if( ssticky != null && ssticky[1] != null ) {
if (ssticky[1] == 'true')
get_field("sticky")[0].selectedIndex = 1;
if (ssticky[1] == 'false')
get_field("sticky")[0].selectedIndex = 2;
}
if( sad != null && sad[1] != null ) {
sad = sad[1].replace(/'/g,'\'').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');
sad = sad.replace(/&/g,'&');
get_field("ad").val(sad);
}
if( iadheight != null && iadheight[1] != null )
get_field("ad_height").val(iadheight[1]);
if( iadwidth != null && iadwidth[1] != null )
get_field("ad_width").val(iadwidth[1]);
if( sad_skip != null && sad_skip[1] != null && sad_skip[1] == 'yes' )
get_field("ad_skip")[0].checked = 1;
if( sspeed != null && sspeed[1] != null ) {
if (sspeed[1] == 'buttons')
get_field("speed")[0].selectedIndex = 1;
if (sspeed[1] == 'no')
get_field("speed")[0].selectedIndex = 2;
}
/*
if( ssplashend != null && ssplashend[1] != null && ssplashend[1] == 'show' )
document.getElementById("fv_wp_flowplayer_field_splashend").checked = 1;
if( sloop != null && sloop[1] != null && sloop[1] == 'true' )
document.getElementById("fv_wp_flowplayer_field_loop").checked = 1;
if( sredirect != null && sredirect[1] != null )
document.getElementById("fv_wp_flowplayer_field_redirect").value = sredirect[1];
*/
if( sSplashText != null && sSplashText[1] != null ) {
get_field("splash_text").val(sSplashText[1]);
}
/*
* Video end dropdown
*/
get_field("popup")[0].parentNode.style.display = 'none'
var spopup = fv_wp_flowplayer_shortcode_parse_arg( shortcode, 'popup', true );
if( sredirect != null && sredirect[1] != null ){
get_field("end_actions")[0].selectedIndex = 1;
get_field("redirect").val(sredirect[1]);
jQuery('#fv_wp_flowplayer_field_redirect').parents('tr').show();
}else if( sloop != null && sloop[1] != null && sloop[1] == 'true' ){
get_field("end_actions")[0].selectedIndex = 2;
}else if( spopup != null && spopup[1] != null ) {
get_field("end_actions")[0].selectedIndex = 3;
spopup = spopup[1].replace(/'/g,'\'').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');
spopup = spopup.replace(/&/g,'&');
get_field("popup_id").parents('tr').show();
if (spopup === null || !isNaN(parseInt(spopup)) || spopup === 'no' || spopup === 'random' || spopup === 'email_list') {
get_field("popup_id").val(spopup)
} else if( spopup.match(/email-[0-9]*/)){
get_field("popup_id").parent().parent().hide();
get_field("email_list").parent().parent().show();
get_field("end_actions").val('email_list');
get_field("email_list").val(spopup.match(/email-([0-9]*)/)[1]);
}else {
get_field("popup").val(spopup).parent().show();
}
}else if( ssplashend != null && ssplashend[1] != null && ssplashend[1] == 'show' ){
get_field('end_actions')[0].selectedIndex = 4
}
if( splaylist_advance != null && splaylist_advance[1] != null ) {
var field = get_field("playlist_advance")[0];
if (splaylist_advance[1] == 'true') field.selectedIndex = 1;
if (splaylist_advance[1] == 'false') field.selectedIndex = 2;
}
if( salign != null && salign[1] != null ) {
var field = get_field("align")[0];
if (salign[1] == 'left') field.selectedIndex = 1;
if (salign[1] == 'right') field.selectedIndex = 2;
}
if( scontrolbar != null && scontrolbar[1] != null ) {
var field = get_field("controlbar")[0];
if (scontrolbar[1] == 'yes' || scontrolbar[1] == 'show' ) field.selectedIndex = 1;
if (scontrolbar[1] == 'no' || scontrolbar[1] == 'hide' ) field.selectedIndex = 2;
}
var aCaptions = false;
if( sCaptions ) {
aCaptions = fv_player_editor_shortcode_arg_split(sCaptions);
var caption = aCaptions.shift();
get_field("caption").val( caption );
playlist_row.find('.fvp_item_caption div').html( caption );
}
var aSplashText = false;
if( sSplashText ) {
aSplashText = fv_player_editor_shortcode_arg_split(sSplashText);
var splash_text = aSplashText.shift();
get_field("splash_text").val( splash_text );
}
if( sPlaylist ) {
// check for all-numeric playlist items separated by commas
// which outlines video IDs from a database
aPlaylist = sPlaylist[1].split(';');
for (var i in aPlaylist) {
playlist_item_add(aPlaylist[i], aCaptions[i], aSubtitles[i], aSplashText[i]);
}
}
if( jQuery('.fv-fp-subtitles .fv-fp-subtitle:first input.fv_wp_flowplayer_field_subtitles').val() == '' ) {
jQuery('.fv-fp-subtitles .fv-fp-subtitle:first').remove();
}
jQuery(document).trigger('fv_flowplayer_shortcode_parse', [ shortcode_parse_fix, shortcode_remains ] );
jQuery('.fv_wp_flowplayer_playlist_head').hover(
function() { jQuery(this).find('.fv_wp_flowplayer_playlist_remove').show(); }, function() { jQuery(this).find('.fv_wp_flowplayer_playlist_remove').hide(); } );
//???
jQuery('#cboxContent').css('background','white');
if (slive != null && slive[1] != null && slive[1] == 'true') {
jQuery("input[name=fv_wp_flowplayer_field_live]").each(function () {
this.checked = 1;
});
}
if(sPlaylist){
playlist_show();
} else {
playlist_item_show(0);
}
tabs_refresh();
}
store_shortcode_args = {};
always_keep_shortcode_args = {};
for( var i in fv_player_editor_conf.shortcode_args_to_preserve ) {
var value = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, fv_player_editor_conf.shortcode_args_to_preserve[i] );
if (value && value[1]) {
store_shortcode_args[fv_player_editor_conf.shortcode_args_to_preserve[i]] = value[1];
}
}
for( var i in fv_player_editor_conf.shortcode_args_not_db_compatible ) {
var value = fv_wp_flowplayer_shortcode_parse_arg( shortcode_parse_fix, fv_player_editor_conf.shortcode_args_not_db_compatible[i] );
if (value && value[1]) {
always_keep_shortcode_args[fv_player_editor_conf.shortcode_args_not_db_compatible[i]] = value[1];
}
}
} else {
debug_log('New player...' );
jQuery(document).trigger('fv_flowplayer_shortcode_new');
shortcode_remains = '';
fix_save_btn_text();
}
$doc.trigger('fv_player_editor_finished');
}
/**
* Makes sure that the Save / Insert button is showing the correct text
* based on current context.
*/
function fix_save_btn_text() {
// rename insert to save for new playlists if we come from list view
if ( is_fv_player_screen_add_new( editor_button_clicked ) || is_fv_player_screen_edit( editor_button_clicked ) ) {
jQuery('.fv_player_field_insert-button').text('Save');
} else {
// we're in a post / widget, rename save button to Insert
jQuery('.fv_player_field_insert-button').text('Insert');
}
}
/*
* Calculate FV Player editor popup (Colorbox) size
*/
function editor_resize() {
setTimeout(function(){
var height = $el_editor.height();
// minimal height
if( height < 50 ) height = 50;
// maximum height
if( height > $(window).height() - 160 ) height = $(window).height() - 160;
// bit of space for padding
height = height + 50;
if( editor_resize_height_record <= height ) {
editor_resize_height_record = height;
$el_editor.fv_player_box.resize({width:1100, height:height})
}
},0);
}
/*
* Saving the data
*/
function editor_submit() {
// bail out if we're already saving, we're loading meta data or we have errors
if ( ajax_save_this_please || is_saving || is_loading_meta_data || fv_player_editor.has_errors() ) {
// if we're saving a new player, let's disable the Save button and wait until meta data are loaded
if ( current_player_db_id < 0 ) {
if (is_loading_meta_data) {
insert_button_toggle_disabled(true);
$el_editor.find('.button-primary').text('Saving...');
var checker = setInterval(function() {
if (is_loading_meta_data <= 0) {
clearInterval(checker);
editor_submit(); // call this function again, so we can really save this time
}
}, 500);
return;
}
} else {
// if we're updating a player, just return here if we're loading meta data,
// as that would result in duplicate save - once with and once without meta data
if (is_loading_meta_data) {
return;
}
}
// we have errors, disable the Save button
if ( fv_player_editor.has_errors() ) {
insert_button_toggle_disabled(true);
return;
}
}
var field_rtmp = get_field("rtmp"),
field_rtmp_path = get_field("rtmp_path")
if(
field_rtmp.attr('placeholder') == '' &&
get_field("rtmp_wrapper").is(":visible") &&
(
( field_rtmp.val() != '' && field_rtmp_path.val() == '' ) ||
( field_rtmp.val() == '' && field_rtmp_path.val() != '' )
)
) {
alert('Please enter both server and path for your RTMP video.');
return false;
} else if(
get_field("src").val() == ''
&& get_field("rtmp").val() == ''
&& get_field("rtmp_path").val() == '') {
alert('Please enter the file name of your video file.');
return false;
}
var ajax_data = build_ajax_data(true);
overlay_show('loading');
var player_was_non_db = (current_player_db_id > -1 ? false : true);
// unmark DB player ID as being currently edited
if ( current_player_db_id > -1 ) {
current_player_db_id = -1;
}
// if player should be in published state, add it into the AJAX data
if ( !has_draft_status ) {
ajax_data['status'] = 'published';
}
debug_log('Running fv_player_db_save Ajax.');
// save data
jQuery.post(ajaxurl, {
action: 'fv_player_db_save',
data: JSON.stringify(ajax_data),
nonce: fv_player_editor_conf.preview_nonce
}, function(response) {
// player saved, reset draft status
is_unsaved = false;
//is_draft_changed = false;
var player = JSON.parse(response);
current_player_db_id = parseInt(player.id);
if( current_player_db_id > 0 ) {
var
has_store_shortcode_args = false,
has_always_keep_shortcode_args = false;
// since both of the above variables are length-less Objects, we need to determine their emptyness
// by iterating over them and checking that they inded contain any values
for (var i in store_shortcode_args) {
has_store_shortcode_args = true;
break;
}
for (var i in always_keep_shortcode_args) {
has_always_keep_shortcode_args = true;
break;
}
// we have extra presentation parameters to keep
if (store_shortcode_args) {
// if this was a non-DB player and is being converted into a DB-player,
// remove all parameters to keep that will go into the DB
var args_to_keep = {};
for (var i in store_shortcode_args) {
if (always_keep_shortcode_args[ i ]) {
args_to_keep[ i ] = store_shortcode_args[ i ];
}
}
store_shortcode_args = args_to_keep;
var
params = jQuery.map(store_shortcode_args, function (value, index) {
return index + '="' + value + '"';
}),
to_append = '';
if (params.length) {
to_append = ' ' + params.join(' ');
}
insert_shortcode('[fvplayer id="' + current_player_db_id + '"' + to_append + ']');
} else if (always_keep_shortcode_args && player_was_non_db) {
// we have extra parameters to keep that are DB-incompatible
var
params = jQuery.map(always_keep_shortcode_args, function (value, index) {
return index + '="' + value + '"';
}),
to_append = '';
if (params.length) {
to_append = ' ' + params.join(' ');
}
insert_shortcode('[fvplayer id="' + current_player_db_id + '"' + to_append + ']');
} else {
// simple DB shortcode, no extra presentation parameters
insert_shortcode('[fvplayer id="' + current_player_db_id + '"]');
}
jQuery(".fv-wordpress-flowplayer-button").fv_player_box.close();
} else {
json_export_data = jQuery('<div/>').text(JSON.stringify(ajax_data)).html();
var overlay = overlay_show('error_saving');
overlay.find('textarea').val( $('<div/>').text(json_export_data).html() );
jQuery('#fv_player_copy_to_clipboard').select();
}
}).error(function() {
overlay_show('message', 'An unexpected error has occurred. Please try again');
});
return;
}
function insert_button_toggle_disabled( disable ) {
var button = $('.fv_player_field_insert-button');
if( disable ) {
button.attr('disabled', 'disabled');
} else {
button.removeAttr('disabled');
}
}
/*
* Sends new shortcode to editor
*/
function insert_shortcode( shortcode ) {
// do not insert new shortcode if using button on wp-admin -> FV Player
if( is_fv_player_screen(editor_button_clicked) ) {
return;
}
var field = $(editor_button_clicked).parents('.fv-player-editor-wrapper').find('.fv-player-editor-field'),
gutenberg = $(editor_button_clicked).parents('.fv-player-gutenberg').find('.fv-player-editor-field'),
widget = jQuery('#widget-widget_fvplayer-'+widget_id+'-text');
// is there a Gutenberg field together in wrapper with the button?
if( gutenberg.length ) {
var
nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set,
gutenbergTextarea = (gutenberg[0].tagName == 'TEXTAREA' ? gutenberg[0] : gutenberg.find('textarea').first()[0]);
nativeInputValueSetter.call(gutenbergTextarea, shortcode);
var ev2 = new Event('change', { bubbles: true});
gutenbergTextarea.dispatchEvent(ev2,shortcode);
fv_player_editor.gutenberg_preview( jQuery(editor_button_clicked).parents('.fv-player-editor-wrapper'), shortcode );
// is there a plain text field together in wrapper with the button?
} else if (field.length) {
field.val(shortcode);
// Prevents double event triggering in FV Player Custom Video box
//field.trigger('fv_flowplayer_shortcode_insert', [shortcode]);
// FV Player in a Widget
} else if( widget.length ){
widget.val( shortcode );
widget.trigger('keyup'); // trigger keyup to make sure Elementor updates the content
widget.trigger('fv_flowplayer_shortcode_insert', [ shortcode ] );
// tinyMCE Text tab
} else if (typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length) {
// editing
if( editor_content.match(/\[.*?#fvp_placeholder#.*?\]/) ) {
editor_content = editor_content.replace(/\[.*?#fvp_placeholder#.*?\]/, shortcode);
//inserting
} else {
editor_content = editor_content.replace(/#fvp_placeholder#/, shortcode);
}
set_post_editor_content(editor_content);
// or are we editing a shortcode in post content?
} else if (editor_content.match(fv_wp_flowplayer_re_edit)) {
editor_content = editor_content.replace(fv_wp_flowplayer_re_edit, shortcode)
set_post_editor_content(editor_content);
// is it a new player instance
} else {
// in existing post content?
if (editor_content != '') {
editor_content = editor_content.replace(fv_wp_flowplayer_re_insert, shortcode)
set_post_editor_content(editor_content);
// in blank post?
} else {
editor_content = shortcode;
send_to_editor(shortcode);
}
}
}
/*
Determines if the button clicked is on wp-admin -> FV Player
*/
function is_fv_player_screen(button) {
return is_fv_player_screen_add_new(button) || is_fv_player_screen_edit(button);
}
/*
Determines if the button clicked is Add New on wp-admin -> FV Player
*/
function is_fv_player_screen_add_new(button) {
return typeof( $(button).data('add_new') ) != 'undefined';
}
/*
Determines if the button clicked is Edit on wp-admin -> FV Player
*/
function is_fv_player_screen_edit(button) {
return typeof( $(button).data('player_id') ) != 'undefined';
}
/*
Determines if the button clicked is Insert/Edit on wp-admin -> Appearance -> Widgets
*/
function is_fv_player_widgets(button) {
return button.id.indexOf('widget-widget_fvplayer') > -1;
}
/*
Sets lightbox class once it opens
*/
function lightbox_open() {
$("#fv_player_box").addClass("fv-flowplayer-shortcode-editor");
}
/*
* Adds playlist item
* keywords: add playlist item
*/
function playlist_item_add( input, sCaption, sSubtitles, sSplashText ) {
jQuery('.fv-player-tab-playlist table tbody').append(template_playlist_item);
var ids = jQuery('.fv-player-tab-playlist [data-index]').map(function() {
return parseInt(jQuery(this).attr('data-index'), 10);
}).get();
var newIndex = Math.max(Math.max.apply(Math, ids) + 1,0);
var current = jQuery('.fv-player-tab-playlist table tbody tr').last();
current.attr('data-index', newIndex);
current.find('.fvp_item_video-filename').html( 'Video ' + (newIndex + 1) );
jQuery('.fv-player-tab-video-files').append(template_video);
var new_item = get_tab('last','video-files');
new_item.hide().attr('data-index', newIndex);
jQuery('.fv-player-tab-subtitles').append(template_subtitles_tab);
var new_item_subtitles = get_tab('last','subtitles');
new_item_subtitles.hide().attr('data-index', newIndex);
// processing database input
if( typeof(input) == 'object' ) {
var objVid = input;
new_item.attr('data-id_video', objVid.id);
get_field('src',new_item).val(objVid.src);
if( objVid.src1 ) {
get_field('src1',new_item).val(objVid.src1);
get_field('src1_wrapper',new_item).css( 'display', 'table-row' );
}
if( objVid.src2 ) {
get_field('src2',new_item).val(objVid.src2);
get_field('src2_wrapper',new_item).css( 'display', 'table-row' );
new_item.find('#fv_wp_flowplayer_add_format_wrapper').show();
}
get_field('mobile',new_item).val(objVid.mobile);
if( objVid.rtmp || objVid.rtmp_path ) {
get_field('rtmp',new_item).val(objVid.rtmp);
get_field('rtmp_path',new_item).val(objVid.rtmp_path);
get_field('rtmp_wrapper',new_item).show();
new_item.find(".add_rtmp_wrapper").hide();
}
get_field('caption',new_item).val(objVid.caption);
get_field('splash',new_item).val(objVid.splash);
get_field('splash_text',new_item).val(objVid.splash_text);
get_field('start',new_item).val(objVid.start);
get_field('end',new_item).val(objVid.end);
jQuery(objVid.meta).each( function(k,v) {
if( v.meta_key == 'synopsis' ) get_field('synopsis',new_item).val(v.meta_value).attr('data-id',v.id);
if( v.meta_key == 'audio' ) get_field('audio',new_item).prop('checked',v.meta_value).attr('data-id',v.id);
});
if (typeof sSubtitles === 'object' && sSubtitles.length && sSubtitles[0].lang) {
for (var i in sSubtitles) {
subtitle_language_add(sSubtitles[i].file, sSubtitles[i].lang, newIndex, sSubtitles[i].id);
}
}
// processing shortcode input
} else if( input ) {
var aInput = input.split(',');
var count = 0;
for( var i in aInput ) {
if( aInput[i].match(/^rtmp:/) ) {
get_field('rtmp_path',new_item).val(aInput[i].replace(/^rtmp:/,''));
} else if( aInput[i].match(/\.(jpg|png|gif|jpe|jpeg)(?:\?.*?)?$/) ) {
get_field('splash',new_item).val(aInput[i]);
} else {
if( count == 0 ) {
get_field('src',new_item).val(aInput[i]);
} else {
get_field('src'+count,new_item).val(aInput[i]);
}
count++;
}
}
if( sCaption ) {
get_field('caption',new_item).val(sCaption);
}
if( sSubtitles ) {
get_field('subtitles',new_item_subtitles).val(sSubtitles);
}
if( sSplashText ) {
get_field('splash_text',new_item).val(sSplashText);
}
}
// fire up an update event if we're adding an empty template, which means this function is called
// outside of the player meta loading and we should inform plugins that they need to add their own
// video tab content
if (!input) {
$doc.trigger('fv-player-playlist-item-add');
}
editor_resize();
return new_item;
}
/*
Show a certain playlist item, it's Video and Subtitles tab
*/
function playlist_item_show( new_index ) {
item_index = new_index;
editing_video_details = true;
$el_editor.attr('class','is-playlist is-singular-active');
jQuery('.fv-player-tabs-header .nav-tab').attr('style',false);
$doc.trigger('fv_flowplayer_shortcode_item_switch', [ new_index ] );
$('a[data-tab=fv-player-tab-video-files]').click();
get_tabs('video-files').hide();
var video_tab = get_tab(new_index,'video-files').show();
get_tabs('subtitles').hide();
get_tab(new_index,'subtitles').show();
if($('.fv-player-tab-playlist [data-index]').length > 1){
$('.fv-player-playlist-item-title').html('Playlist item no. ' + ++new_index);
$('.playlist_edit').html($('.playlist_edit').data('edit'));
}else{
$('.playlist_edit').html($('.playlist_edit').data('create'));
$el_editor.attr('class','is-singular is-singular-active');
}
// Show or hide RTMP fields if they are filled in
var rtmp_not_provided = get_field('rtmp_path',video_tab).val().length === 0 && get_field('rtmp',video_tab).val().length === 0;
get_field('rtmp_wrapper',video_tab).toggle( !rtmp_not_provided );
$('.add_rtmp_wrapper',video_tab).toggle( rtmp_not_provided );
// As Flowplayer only lets us set RTMP server for the first video in playlist, prefill it for this new item as well
if(new_index > 1){
get_field('rtmp',video_tab).val( get_field('rtmp',$('.fv-player-tab-video-files table').eq(0) ).val()).attr('readonly',true);
}
$('.fv_wp_flowplayer_field_subtitles_lang, .subtitle_language_add_link').attr('style',false);
tabs_refresh();
}
/*
* Recalculate the data-index values for playlist items
*/
function playlist_index() {
$doc.trigger('fv-player-editor-initial-indexing');
$('.fv-player-tab-playlist table tbody tr').each(function(){
$(this).attr('data-index', $(this).index() );
});
$('.fv-player-tab-video-files table').each(function(){
$(this).attr('data-index', $(this).index() );
});
$('.fv-player-tab.fv-player-tab-subtitles table').each(function(){
$(this).attr('data-index', $(this).index() );
});
}
/*
* Displays playlist editor
* keywords: show playlist
*/
function playlist_show() {
item_index = -1;
editing_video_details = false;
$el_editor.attr('class','is-playlist-active');
// show all the tabs previously hidden
jQuery('.fv-player-tabs-header .nav-tab').attr('style',false);
jQuery('a[data-tab=fv-player-tab-playlist]').click();
preview_single = -1;
playlist_index();
// fills playlist editor table from individual video tables
var video_files = jQuery('.fv-player-tab-video-files table');
video_files.each( function() {
var current = jQuery(this);
var currentUrl = get_field("src",current).val();
if(!currentUrl.length){
currentUrl = 'Video ' + (jQuery(this).index() + 1);
}
var playlist_row = jQuery('.fv-player-tab-playlist table tbody tr').eq( current.data('index') );
var video_preview = get_field("splash",current).val();
playlist_row.find('.fvp_item_video-thumbnail').html( video_preview.length ? '<img src="' + video_preview + '" />':'');
var video_name = decodeURIComponent(currentUrl).split("/").pop();
video_name = video_name.replace(/\+/g,' ');
video_name = video_name.replace(/watch\?v=/,'YouTube: ');
playlist_row.find('.fvp_item_video-filename').html( video_name );
var playlist_row_div = playlist_row.find('.fvp_item_caption div');
// do not put in caption if it's loading
if (!playlist_row_div.hasClass('fv-player-shortcode-editor-small-spinner')) {
playlist_row_div.html( get_field("caption",current).val() );
}
});
playlist_index();
if(!jQuery('.fvp_item_video-thumbnail>img').length){
jQuery('#fv-player-list-list-view').click();
jQuery('#fv-player-list-thumb-view').addClass('disabled');
jQuery('#fv-player-list-thumb-view').attr('title',jQuery('#fv-player-list-thumb-view').data('title'));
}else{
jQuery('#fv-player-list-thumb-view').click();
jQuery('#fv-player-list-thumb-view').removeClass('disabled');
jQuery('#fv-player-list-thumb-view').removeAttr('title');
}
jQuery('.fv-player-tab-playlist').show();
editor_resize();
tabs_refresh();
return false;
}
function preview_dimensions() {
var width = parseInt( get_field('width').val() ) || 460;
var height = parseInt( get_field('height').val() ) || 300;
if ($el_preview.length && $el_preview.width() < width) {
height = Math.round(height * ($el_preview.width() / width));
width = $el_preview.width();
}
return {
width: width,
height: height
};
}
function set_post_editor_content( html ) {
if ( editor_button_clicked.className.indexOf('fv-player-editor-button') > -1 || is_fv_player_screen(editor_button_clicked) || is_fv_player_widgets(editor_button_clicked) || $(editor_button_clicked).parents('.fv-player-gutenberg').find('.fv-player-editor-field').length) {
return;
}
if( typeof(FCKeditorAPI) == 'undefined' && jQuery('#content:not([aria-hidden=true])').length ){
jQuery('#content:not([aria-hidden=true])').val(html);
}else if( typeof(instance_fp_wysiwyg) != 'undefined' && ( instance_tinymce == undefined || typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor.isHidden() ) ) {
instance_fp_wysiwyg.SetHTML( html );
}
else if ( instance_tinymce ) { // instance_tinymce will be null if we're updating custom meta box
instance_tinymce.setContent( html );
}
}
/*
* Hide any overlays
*/
function overlay_hide() {
$('.fv-player-editor-overlay').hide();
return false;
}
/*
* Show a certain kind of overlay
*/
function overlay_show( type, message ) {
overlay_hide();
var overlayDiv = $('#fv-player-editor-'+type+'-overlay');
overlayDiv.show();
if( typeof(message) != 'undefined' ) {
overlayDiv.find('p').html( message );
}
editor_resize();
return overlayDiv;
}
/*
* Populate content of the Embeds tab and show it if there is any content to be set
*
* @param string html The OL > LI list of posts which contain the same player.
*/
function set_embeds( html ) {
// ugly way of making sure that tab stays hidden as otherwise playlist_show() would reveal it
$('[data-tab=fv-player-tab-embeds]').toggleClass('always-hide',!html);
get_tabs('embeds').find('td').html(html);
}
/*
* Adds another language to subtitle menu
*/
function subtitle_language_add( sInput, sLang, iTabIndex, sId ) {
if(!iTabIndex){
var current = jQuery('.fv-player-tab-subtitles table:visible');
iTabIndex = current.length && current.data('index') ? current.data('index') : 0;
}
var oTab = jQuery('.fv-fp-subtitles').eq(iTabIndex);
oTab.append( template_subtitles );
var subElement = jQuery('.fv-fp-subtitle:last' , oTab);
if (typeof(sId) !== 'undefined') {
subElement.attr('data-id_subtitles', sId);
}
if( sInput ) {
get_field('subtitles',subElement).val(sInput);
}
if ( sLang ) {
if( sLang == 'iw' ) sLang = 'he';
if( sLang == 'in' ) sLang = 'id';
if( sLang == 'jw' ) sLang = 'jv';
if( sLang == 'mo' ) sLang = 'ro';
if( sLang == 'sh' ) sLang = 'sr';
get_field('subtitles_lang',subElement).val(sLang).change();
}
editor_resize();
return false;
}
function tabs_refresh(){
var visibleTabs = 0;
$el_editor.find('a[data-tab]').removeClass('fv_player_interface_hide');
$el_editor.find('.fv-player-tabs > .fv-player-tab').each(function(){
var bHideTab = true
$(this).find('tr:not(.fv_player_actions_end-toggle):not(.submit-button-wrapper)').each(function(){
if( $(this).css('display') === 'table-row' ){
bHideTab = false;
return false;
}
});
var tab;
var data = jQuery(this).attr('class').match(/fv-player-tab-[^ ]*/);
if(data[0]){
tab = $el_editor.find('a[data-tab=' + data[0] + ']');
}
if(bHideTab){
tab.addClass('fv_player_interface_hide')
} else {
tab.removeClass('fv_player_interface_hide');
if(tab.css('display')!=='none')
visibleTabs++
}
});
if(visibleTabs<=1){
$el_editor.find('.nav-tab').addClass('fv_player_interface_hide');
}
var end_actions_label = $('label[for=fv_wp_flowplayer_field_end_actions]');
if( $el_editor.hasClass('is-playlist-active')){
end_actions_label.html( end_actions_label.data('playlist-label') )
} else {
end_actions_label.html( end_actions_label.data('single-label') )
}
}
/*
Click handlers
*/
/*
Click on Add another format
*/
$doc.on('click', '#add_format_wrapper a', function() {
if ( get_field("src").val() != '' ) {
if ( get_field("src1_wrapper").is(":visible") ) {
if ( get_field("src1").val() != '' ) {
get_field("src2_wrapper").show();
get_field("src2_uploader").show();
$("#add_format_wrapper").hide();
}
else {
alert('Please enter the file name of your second video file.');
}
}
else {
get_field("src1_wrapper").show();
get_field("src1_uploader").show();
}
editor_resize();
}
else {
alert('Please enter the file name of your video file.');
}
return false;
});
/*
Click on Add RTMP
*/
$doc.on('click', '.add_rtmp_wrapper a', function() {
var item = $(this).parents('.fv-player-playlist-item');
get_field("rtmp_wrapper", item).show();
item.find(".add_rtmp_wrapper").hide();
editor_resize();
return false;
});
/*
Click on Add Another Language (of Subtitles)
*/
$doc.on('click', '.fv_flowplayer_language_add_link', function() {
subtitle_language_add(false,true);
return false;
});
/*
Click on X to remove a language from Subtitles
*/
$doc.on('click', '.fv-fp-subtitle-remove', function() {
var $parent = jQuery(this).parents('.fv-fp-subtitle'),
id = $parent.attr('data-id_subtitles')
if (id) {
fv_wp_delete_video_meta_record(id);
}
// if it's not the last subtitle, remove it completely
if(jQuery(this).parents('.fv-fp-subtitles').find('.fv-fp-subtitle').length > 1){
$parent.remove();
// otherwise just empty the inputs to let user add new subtitles
} else {
$parent.find('[name]').val('');
$parent.removeAttr('data-id_subtitles');
}
editor_resize();
return false;
});
/*
Click on Loading Overlay Close button
*/
$doc.on('click', '#fv-player-editor-overlay-close', function() {
$.fn.fv_player_box.close();
// hide the overlay asynchronously to allow the actual modal close animation to finish,
// so it doesn't blink from error message to an empty editor and only then starts to fade
setTimeout(overlay_hide, 1000);
});
/*
Click on Import player
*/
$doc.on('click', '#fv-player-editor-import-overlay-import', function() {
var button = this,
data = jQuery('#fv_player_import_data').val();
if (!data) {
fv_player_editor.overlay_notice( button, 'No data to import!', 'warning', 5000 );
return false;
}
try {
JSON.parse(data);
} catch(e) {
fv_player_editor.overlay_notice( button, 'Bad JSON format!', 'error', 5000 );
return false;
}
fv_player_editor.overlay_notice_close_all();
overlay_show('loading');
debug_log('Running fv_player_db_import Ajax.');
jQuery.post(ajaxurl, {
action: 'fv_player_db_import',
nonce: fv_player_editor_conf.db_import_nonce,
data: data,
cookie: encodeURIComponent(document.cookie),
}, function(response) {
if (response != '0' && !isNaN(parseFloat(response)) && isFinite(response)) {
var playerID = response;
// add the inserted player's row
jQuery.get(
fv_player_editor_conf.admin_url + '&id=' + playerID,
function (response) {
jQuery('#the-list tr:first').before(jQuery(response).find('#the-list tr:first'));
jQuery('.fv-wordpress-flowplayer-button').fv_player_box.close();
}).error(function() {
jQuery('.fv-wordpress-flowplayer-button').fv_player_box.close();
});
} else {
fv_player_editor.overlay_notice( button, response, 'error' );
}
}).error(function() {
fv_player_editor.overlay_notice( button, 'Unknown error!', 'error' );
});
return false;
});
/*
* Removes playlist item
* Also stores the RTMP server of the first item as that's the only place where
* it's stored, so in case we are removing the first playlist item, we save it
* that way and then set it again for the first item. Uff.
*
* keywords: remove palylist item
*/
$doc.on('click', '.fv_wp_flowplayer_playlist_remove', function() {
// TODO: Some method to get first playlist item data
store_rtmp_server = jQuery('#fv-flowplayer-playlist table:first .fv_wp_flowplayer_field_rtmp').val();
$(this).parents('table').remove();
jQuery('#fv-flowplayer-playlist table:first .fv_wp_flowplayer_field_rtmp').val( store_rtmp_server );
return false;
});
/*
Extra fields to reveal when using a stream
*/
$doc.on('keyup', '[name=fv_wp_flowplayer_field_src], [name=fv_wp_flowplayer_field_rtmp_path]', show_stream_fields );
$doc.on('fv_flowplayer_shortcode_item_switch fv_flowplayer_shortcode_new', show_stream_fields );
function show_stream_fields(e,index) {
// on keyup
var src = jQuery(this).val(),
item = jQuery(this).parents('table');
// on fv_flowplayer_shortcode_item_switch
if( typeof(index) != "undefined" ) {
item = jQuery('.fv-player-playlist-item[data-index='+index+']');
src = item.find('[name=fv_wp_flowplayer_field_src]').val();
}
// on fv_flowplayer_shortcode_new
if( item.length == 0 ) item = jQuery('.fv-player-playlist-item[data-index=0]');
var is_stream = item.find('[name=fv_wp_flowplayer_field_rtmp_path]').val() || src.match(/m3u8/) || src.match(/rtmp:/) || src.match(/\.mpd/),
is_vimeo_or_youtube = fv_player_editor_conf.have_fv_player_vimeo_live && src.match(/vimeo\.com\//) || src.match(/youtube\.com\//);
item.find('[name=fv_wp_flowplayer_field_live]').closest('tr').toggle(!!is_stream || !!is_vimeo_or_youtube);
item.find('[name=fv_wp_flowplayer_field_audio]').closest('tr').toggle(!!is_stream);
item.find('[name=fv_wp_flowplayer_field_dvr]').closest('tr').toggle(!!is_stream);
editor_resize();
}
function init_saved_player_fields( id_player ) {
var
$id_player_element = $('#fv-player-id_player'),
$deleted_videos_element = $('#fv-player-deleted_videos'),
$deleted_video_meta_element = $('#fv-player-deleted_video_meta'),
$deleted_player_meta_element = $('#fv-player-deleted_player_meta');
if (!$id_player_element.length) {
// add player ID as a hidden field
$el_editor.append('<input type="hidden" name="id_player" id="fv-player-id_player" value="' + id_player + '" />');
// add removed video IDs as a hidden field
$el_editor.append('<input type="hidden" name="deleted_videos" id="fv-player-deleted_videos" />');
// add removed video meta IDs as a hidden field
$el_editor.append('<input type="hidden" name="deleted_video_meta" id="fv-player-deleted_video_meta" />');
// add removed player meta IDs as a hidden field
$el_editor.append('<input type="hidden" name="deleted_player_meta" id="fv-player-deleted_player_meta" />');
} else {
$id_player_element.val( id_player );
$deleted_videos_element.val('');
$deleted_video_meta_element.val('');
$deleted_player_meta_element.val('');
}
}
/*
Mark each manually updated title or splash field as such
*/
$doc.on('keydown', '#fv_wp_flowplayer_field_splash, #fv_wp_flowplayer_field_caption', function() {
// remove spinner from playlist table row, if present
var $element = jQuery(this);
// if this element already has data set, don't do any of the selections below
if (typeof($element.data('fv_player_user_updated')) != 'undefined') {
return;
}
var
$parent_row = $element.closest('tr'),
$parent_table = $element.closest('table'),
$playlist_row = jQuery('.fv-player-tab-playlist table tr[data-index="' + $parent_table.data('index') + '"] td.fvp_item_caption'),
$playlist_row_spinner_div = $playlist_row.find('div.fv-player-shortcode-editor-small-spinner');
if (this.id == 'fv_wp_flowplayer_field_caption' && $playlist_row_spinner_div.length > 0) {
$playlist_row_spinner_div.removeClass('fv-player-shortcode-editor-small-spinner');
}
if( this.id == 'fv_wp_flowplayer_field_splash' ) {
var $input = $parent_table.find('#fv_wp_flowplayer_field_auto_splash');
var $meta_key = 'auto_splash';
} else {
var $input = $parent_table.find('#fv_wp_flowplayer_field_auto_caption');
var $meta_key = 'auto_caption';
}
if( typeof($element.data('fv_player_user_updated')) == 'undefined' && $input.length > 0 ) {
$input.val('');
fv_flowplayer_insertUpdateOrDeleteVideoMeta({
element: $input,
meta_section: 'video',
meta_key: $meta_key,
handle_delete: true
});
}
// remove spinner
$parent_row.find('.fv-player-shortcode-editor-small-spinner').remove();
console.log(this.id+' has been updated manually!');
$element.data('fv_player_user_updated', 1);
});
// Public stuff
return {
get_current_player_db_id() {
return current_player_db_id;
},
get_edit_lock_removal() {
return edit_lock_removal;
},
get_shortcode_remains: function() {
return shortcode_remains;
},
set_current_video_to_edit( index ) {
current_video_to_edit = index;
},
set_edit_lock_removal( val ) {
edit_lock_removal = val;
},
set_shortcode_remains: function(value) {
shortcode_remains = value;
},
/*
* Show a notice in the overlay above the editor
*
* @param {Object} button The button in the overlay that was clicked
* Used to find the overlay and the notice in it
* @param {string} html Content of the notice
* @param {string} type success|error
* @param {int} close_after Optional number of miliseconds to close the
* notice after
*
*/
overlay_notice: function(button, html, type, close_after ) {
var overlay = jQuery(button).closest('.fv-player-editor-overlay'),
notice = overlay.find('.fv-player-editor-overlay-notice');
notice
.html(html)
.removeClass('notice-error')
.removeClass('notice-success')
.addClass('notice-'+type)
.css('visibility', 'visible');
if( close_after ) {
setTimeout(function() {
notice.css('visibility', 'hidden');
}, close_after);
}
},
overlay_notice_close_all: function() {
$('.fv-player-editor-overlay-notice').css('visibility', 'hidden');
},
editor_resize: editor_resize,
/**
* Adds a preview to the Gutenberg FV Player block.
*
* @param parent Parent Gutenberg element in which we'll be showing the preview for.
* @param shortcode The actual player shortcode to generate the preview from.
*/
gutenberg_preview: function( parent, shortcode ) {
if (typeof(parent) == 'undefined' || typeof(shortcode) == 'undefined') {
return;
} else if (fv_player_preview_loading !== false) {
clearTimeout(fv_player_preview_loading);
}
console.log('fv_player_gutenberg_preview',parent,shortcode);
var url = window.fv_Player_site_base + '?fv_player_embed=' + window.fv_player_editor_conf.preview_nonce + '&fv_player_preview=' + b64EncodeUnicode( shortcode );
// set timeout for the loading AJAX and wait a moment, as REACT will call this function
// even when we click into the Gutenberg block without actually editing anything
// and also the user might be still typing the ID (i.e. 183 - which would make 3 preview calls otherwise)
fv_player_preview_loading = setTimeout(function() {
jQuery.get(url, function(response) {
jQuery(parent).find('.fv-player-gutenberg-preview').html( jQuery('#wrapper',response ) );
} ).always(function() {
fv_player_preview_loading = false;
})
}, 1500);
},
/**
* Returns the number of videos in a playlist for the current player.
*/
get_playlist_items_count: function() {
return jQuery('.title.column-title').length;
},
playlist_buttons_disable: function( reason ) {
if( reason ) {
$('.playlist_add, .playlist_edit').addClass('disabled').attr('title', reason);
} else {
$('.playlist_add, .playlist_edit').removeClass('disabled');
}
},
playlist_buttons_toggle: function( show ) {
$('.playlist_add, .playlist_edit').toggle( show );
},
insert_button_toggle: function( show ) {
$('.fv_player_field_insert-button').toggle( show );
},
copy_player_button_toggle: function( show ) {
$('#fv-player-shortcode-editor .copy_player').toggle( show );
},
meta_data_load_started() {
is_loading_meta_data++;
},
meta_data_load_finished() {
is_loading_meta_data--;
},
error_add( identifier, txt ) {
errors[ identifier ] = txt;
// no save button while we have errors
insert_button_toggle_disabled( true );
},
error_remove( identifier ) {
delete errors[ identifier ];
if ( !this.has_errors() ) {
// enable save button
insert_button_toggle_disabled( false );
}
},
errors_remove( prefix ) {
var errors_found = [];
for ( var key in errors ) {
if ( key.startsWith( prefix ) ) {
errors_found.push( key );
}
}
if ( errors_found.length ) {
for ( var val of errors_found ) {
delete errors[ val ];
}
}
if ( this.has_errors() ) {
// enable save button
insert_button_toggle_disabled( false );
}
},
has_errors() {
for ( var i in errors ) {
return errors[ i ];
}
return false;
},
};
})(jQuery);
});
function fv_wp_flowplayer_map_names_to_editor_fields(name) {
var fieldMap = {
'liststyle': 'playlist',
'preroll': 'video_ads',
'postroll': 'video_ads_post'
};
return 'fv_wp_flowplayer_field_' + (fieldMap[name] ? fieldMap[name] : name);
}
function fv_wp_flowplayer_map_db_values_to_field_values(name, value) {
switch (name) {
case 'playlist_advance':
return ((value == 'true' || value == 'on') ? 'on' : (value == 'default' || value == '') ? 'default' : 'off');
break;
default: return value;
}
}
function fv_wp_delete_player_meta_record(id) {
var $element = jQuery('#fv-player-deleted_player_meta');
if ($element.val()) {
$element.val($element.val() + ',' + id);
} else {
$element.val(id);
}
}
function fv_wp_delete_video_meta_record(id) {
var $element = jQuery('#fv-player-deleted_video_meta');
if ($element.val()) {
$element.val($element.val() + ',' + id);
} else {
$element.val(id);
}
}
function fv_wp_flowplayer_dialog_resize() {
console.log('WARNING! USE OF DEPRECATED FUNCTION fv_wp_flowplayer_dialog_resize() FOUND!');
console.log('Please update this to call the function as fv_player_editor.fv_wp_flowplayer_dialog_resize() instead!');
fv_player_editor.editor_resize();
}
function fv_wp_flowplayer_get_correct_dropdown_value(optionsHaveNoValue, $valueLessOptions, dropdown_element) {
// multiselect element
if(dropdown_element.multiple) {
var selected = [],
options = dropdown_element && dropdown_element.options,
opt;
for (var i=0, iLen=options.length; i<iLen; i++) {
opt = options[i];
// take only selected with value
if (opt.selected && opt.value) {
selected.push(opt.value);
}
}
return selected.length ? selected.join(',') : '';
} else if ($valueLessOptions.length) { // at least one option is value-less
if (optionsHaveNoValue) {
// all options are value-less - the first one is always default and should be sent as ''
return (dropdown_element.selectedIndex === 0 ? '' : dropdown_element.value);
} else {
// some options are value-less
if ($valueLessOptions.length > 1) {
// multiple value-less options, while some other options do have a value - this should never be
console.log('ERROR - Unhandled exception occurred while trying to get player values: more than 1 value-less options found');
return false;
} else {
// single option is value-less (
return (dropdown_element.selectedIndex === 0 ? '' : dropdown_element.value);
}
}
} else {
// normal dropdown - all options have a value, return this.value (option's own value)
return dropdown_element.value;
}
}
function fv_wp_flowplayer_check_for_player_meta_field(fieldName) {
return [].indexOf(fieldName) > -1;
}
function fv_wp_flowplayer_check_for_video_meta_field(fieldName) {
return [
'fv_wp_flowplayer_field_duration',
'fv_wp_flowplayer_field_last_video_meta_check',
'fv_wp_flowplayer_field_live',
'fv_wp_flowplayer_field_dvr',
'fv_wp_flowplayer_field_auto_splash',
'fv_wp_flowplayer_field_auto_caption',
'fv_wp_flowplayer_field_synopsis',
'fv_wp_flowplayer_field_audio'
].indexOf(fieldName) > -1;
}
jQuery(document).on('click', '#fv-player-editor-export-overlay-copy', function() {
var button = this;
fv_player_clipboard(jQuery('[name=fv_player_copy_to_clipboard]').val(), function() {
fv_player_editor.overlay_notice( button, 'Text Copied To Clipboard!', 'success', 3000 );
}, function() {
fv_player_editor.overlay_notice( button, '<strong>Error copying text into clipboard!</strong><br />Please copy the content of the above text area manually by using CTRL+C (or CMD+C on MAC).', 'error' );
});
return false;
});
// TODO: This is used in editor-screenshots.js and FV Player Pay Per View!
function fv_wp_flowplayer_submit( preview ) {
}
function fv_player_open_preview_window(url, width, height){
height = Math.min(window.screen.availHeight * 0.80, height + 25);
width = Math.min(window.screen.availWidth * 0.66, width + 100);
if(fv_player_preview_window == null || fv_player_preview_window.self == null || fv_player_preview_window.closed ){
fv_player_preview_window = window.open(url,'window','toolbar=no, menubar=no, resizable=yes width=' + width + ' height=' + height);
}else{
fv_player_preview_window.location.assign(url);
fv_player_preview_window.focus();
}
}
/*
Also used by FV Player Pro and FV Player Pay Per View
*/
function fv_wp_flowplayer_shortcode_parse_arg( sShortcode, sArg, bHTML, sCallback ) {
var rDoubleQ = new RegExp(sArg+"=\"","g");
var rSingleQ = new RegExp(sArg+"='","g");
var rNoQ = new RegExp(sArg+"=[^\"']","g");
var rMatch = false;
if( sShortcode.match(rDoubleQ) ) {
//rMatch = new RegExp(sArg+'="(.*?[^\\\\/])"',"g");
rMatch = new RegExp('[ "\']' + sArg + '="(.*?[^\\\\])"', "g");
} else if (sShortcode.match(rSingleQ)) {
rMatch = new RegExp('[ "\']' + sArg + "='([^']*?)'", "g");
} else if (sShortcode.match(rNoQ)) {
rMatch = new RegExp('[ "\']' + sArg + "=([^\\]\\s,]+)", "g");
}
if( !rMatch ){
return false;
}
var aOutput = rMatch.exec(sShortcode);
fv_player_editor.set_shortcode_remains( fv_player_editor.get_shortcode_remains().replace( rMatch, '' ) );
if( bHTML ) {
aOutput[1] = aOutput[1].replace(/\\"/g, '"').replace(/\\(\[|])/g, '$1');
}
if( aOutput && sCallback ) {
sCallback(aOutput);
} else {
return aOutput;
}
}
function fv_wp_flowplayer_subtitle_parse_arg( args ) {
var input = ('fv_wp_flowplayer_subtitle_parse_arg',args);
var aLang = input[0].match(/subtitles_([a-z][a-z])/);
subtitle_language_add( input[1], aLang[1] );
}
function fv_wp_flowplayer_share_parse_arg( args ) {
var field = get_field("share")[0];
if (args[1] == 'yes' ) {
field.selectedIndex = 1;
} else if (args[1] == 'no' ) {
field.selectedIndex = 2;
} else {
field.selectedIndex = 3;
args = args[1].split(';');
if( typeof(args[0]) == "string" ) get_field('share_url').val(args[0]);
if( typeof(args[1]) == "string" ) get_field('share_title').val(args[1]);
get_field("share_custom").show();
}
}
function fv_player_editor_shortcode_arg_split(sInput) {
sInput[1] = sInput[1].replace(/\\;/gi, '<!--FV Flowplayer Caption Separator-->').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
aInput = sInput[1].split(';');
for( var i in aInput ){
aInput[i] = aInput[i].replace(/\\"/gi, '"');
aInput[i] = aInput[i].replace(/\\<!--FV Flowplayer Caption Separator-->/gi, ';');
aInput[i] = aInput[i].replace(/<!--FV Flowplayer Caption Separator-->/gi, ';');
}
return aInput;
};
jQuery(document).on('fv_flowplayer_shortcode_insert', function(e) {
jQuery(e.target).siblings('.button.fv-wordpress-flowplayer-button').val('Edit');
});
/**
* Automatically handles new, updated or removed player meta data
* via JS.
*
* @param options Object with the following elements:
* element -> the actual element on page (input, select...) to check and get meta value from
* data -> existing player data, including player meta data
* meta_section -> section for the meta data, for example "player" for common metas, "ppv" for pay per view plugin etc.
* meta_key -> rhe actual key to check for and potentially add/update/remove
* handle_delete -> if true, value-less ('') elements will be considered indication that the meta key should be deleted
* delete_callback -> if set, this function is called when a meta key is deleted
* edit_callback -> if set, this function is called when a meta key is updated
* insert_callback -> if set, this function is called when a meta key is added
*/
function fv_flowplayer_insertUpdateOrDeletePlayerMeta(options) {
var
$element = jQuery(options.element),
$deleted_meta_element = jQuery('#fv-player-deleted_player_meta'),
optionsHaveNoValue = false, // will become true for dropdown options without values
$valueLessOptions = null,
isDropdown = $element.get(0).nodeName == 'SELECT',
value = ($element.get(0).type.toLowerCase() == 'checkbox' ? $element.get(0).checked ? 'true' : '' : $element.val());
// don't do anything if we've not found the actual element
if (!$element.length) {
return;
}
// check for a select without any option values, in which case we'll use their text
if (isDropdown) {
$valueLessOptions = $element.find('option:not([value])');
if ($valueLessOptions.length == $element.get(0).length) {
optionsHaveNoValue = true;
}
var opt_value = fv_wp_flowplayer_get_correct_dropdown_value(optionsHaveNoValue, $valueLessOptions, $element.get(0));
// if there were any problems, just set value to ''
if (opt_value === false) {
value = '';
} else {
value = opt_value.toLowerCase();
}
}
// check whether to update or delete this meta
if ($element.data('id')) {
// only delete this meta if delete was not prevented via options
// and if there was no value specified, otherwise update
if ((!options.handle_delete || options.handle_delete !== false) && !value) {
if ($deleted_meta_element.val()) {
$deleted_meta_element.val($deleted_meta_element.val() + ',' + $element.data('id'));
} else {
$deleted_meta_element.val($element.data('id'));
}
$element
.removeData('id')
.removeAttr('data-id');
// execute delete callback, if present
if (options.delete_callback && typeof(options.delete_callback) == 'function') {
options.delete_callback();
}
} else {
if (typeof(options.data) != 'undefined' && typeof(options.data['player_meta'][options.meta_section]) == 'undefined') {
options.data['player_meta'][options.meta_section] = {};
}
// update if we have an ID
if (typeof(options.data) != 'undefined') {
options.data['player_meta'][options.meta_section][options.meta_key] = {
'id': $element.data('id'),
'value': value
}
}
// execute update callback, if present
if (options.edit_callback && typeof(options.edit_callback) == 'function') {
options.edit_callback();
}
}
} else if (value) {
if (typeof(options.data) != 'undefined' && typeof(options.data['player_meta'][options.meta_section]) == 'undefined') {
options.data['player_meta'][options.meta_section] = {};
}
// insert new data if no meta ID
if (typeof(options.data) != 'undefined') {
options.data['player_meta'][options.meta_section][options.meta_key] = {
'value': value
}
}
// execute insert callback, if present
if (options.insert_callback && typeof(options.insert_callback) == 'function') {
options.insert_callback();
}
}
};
/**
* Automatically handles new, updated or removed video meta data
* via JS.
*
* @param options Object with the following elements:
* element -> the actual element on page (input, select...) to check and get meta value from
* data -> existing player data, including video meta data
* meta_section -> section for the meta data, for example "player" for common metas, "ppv" for pay per view plugin etc.
* meta_key -> rhe actual key to check for and potentially add/update/remove
* handle_delete -> if true, value-less ('') elements will be considered indication that the meta key should be deleted
* delete_callback -> if set, this function is called when a meta key is deleted
* edit_callback -> if set, this function is called when a meta key is updated
* insert_callback -> if set, this function is called when a meta key is added
*/
function fv_flowplayer_insertUpdateOrDeleteVideoMeta(options) {
var
$element = jQuery(options.element),
$deleted_meta_element = jQuery('#fv-player-deleted_video_meta'),
optionsHaveNoValue = false, // will become true for dropdown options without values
$valueLessOptions = null,
isDropdown = $element.get(0).nodeName == 'SELECT',
value = ($element.get(0).type.toLowerCase() == 'checkbox' ? $element.get(0).checked ? 'true' : '' : $element.val());
// don't do anything if we've not found the actual element
if (!$element.length) {
return;
}
// check for a select without any option values, in which case we'll use their text
if (isDropdown) {
$valueLessOptions = $element.find('option:not([value])');
if ($valueLessOptions.length == $element.get(0).length) {
optionsHaveNoValue = true;
}
var opt_value = fv_wp_flowplayer_get_correct_dropdown_value(optionsHaveNoValue, $valueLessOptions, $element.get(0));
// if there were any problems, just set value to ''
if (opt_value === false) {
value = '';
} else {
value = opt_value.toLowerCase();
}
}
// check whether to update or delete this meta
if ($element.data('id')) {
// only delete this meta if delete was not prevented via options
// and if there was no value specified, otherwise update
if ((!options.handle_delete || options.handle_delete !== false) && !$element.val()) {
if ($deleted_meta_element.val()) {
$deleted_meta_element.val($deleted_meta_element.val() + ',' + $element.data('id'));
} else {
$deleted_meta_element.val($element.data('id'));
}
$element
.removeData('id')
.removeAttr('data-id');
// execute delete callback, if present
if (options.delete_callback && typeof(options.delete_callback) == 'function') {
options.delete_callback();
}
} else {
if (typeof(options.data) != 'undefined' && typeof(options.data['video_meta'][options.meta_section]) == 'undefined') {
options.data['video_meta'][options.meta_section] = {};
}
if (typeof(options.data) != 'undefined') {
// update if we have an ID
options.data['video_meta'][options.meta_section][options.meta_index][options.meta_key] = {
'id': $element.data('id'),
'value': value
}
// execute update callback, if present
if (options.edit_callback && typeof(options.edit_callback) == 'function') {
options.edit_callback();
}
}
}
} else if (value) {
if (typeof(options.data) != 'undefined' && typeof(options.data['video_meta'][options.meta_section]) == 'undefined') {
options.data['video_meta'][options.meta_section] = {};
}
// insert new data if no meta ID
if (typeof(options.data) != 'undefined') {
options.data['video_meta'][options.meta_section][options.meta_index][options.meta_key] = {
'value': value
}
// execute insert callback, if present
if (options.insert_callback && typeof(options.insert_callback) == 'function') {
options.insert_callback();
}
}
}
};
/*
For wp-admin -> FV Player screen, should not be here
*/
if( typeof(fv_player_editor_conf) != "undefined" ) {
// extending DB player edit lock's timer
jQuery( document ).on( 'heartbeat-send', function ( event, data ) {
// FV Player might not be loaded, like in case of Elementor
if( !window.fv_player_editor ) return;
if( fv_player_editor.get_current_player_db_id() > -1 ) {
data.fv_flowplayer_edit_lock_id = fv_player_editor.get_current_player_db_id();
}
var
removals = fv_player_editor.get_edit_lock_removal(),
removalsEmpty = true;
for (var i in removals) {
removalsEmpty = false;
break;
}
if( !removalsEmpty ) {
data.fv_flowplayer_edit_lock_removal = fv_player_editor.get_edit_lock_removal();
} else {
delete(data.fv_flowplayer_edit_lock_removal);
}
});
// remove edit locks in the config if it was removed on the server
jQuery( document ).on( 'heartbeat-tick', function ( event, data ) {
if ( data.fv_flowplayer_edit_locks_removed ) {
var
edit_lock_removal = fv_player_editor.get_edit_lock_removal(),
new_edit_lock_removal = {};
// remove only edit locks that were removed server-side
for (var i in edit_lock_removal) {
if (!data.fv_flowplayer_edit_locks_removed[i]) {
new_edit_lock_removal[i] = edit_lock_removal[i];
}
}
fv_player_editor.set_edit_lock_removal(new_edit_lock_removal);
}
});
}
jQuery(document).on('click','.fv_player_splash_list_preview', function() {
fv_player_editor.set_current_video_to_edit( jQuery(this).parents('.thumbs').find('.fv_player_splash_list_preview').index(this) );
jQuery(this).parents('tr').find('.fv-player-edit').click();
});
jQuery(document).on('click','.column-shortcode input', function() {
jQuery(this).select();
});