// Themple Framework admin scripts jQuery(document).ready(function($) { "use strict"; /* TABLE OF CONTENTS ----------------- 1. Variable definition 2. Scripts for single data types 2.1 Image 2.2 Color 2.3 Select 2.4 TinyMCE 2.5 Date 2.6 Boolean 3. Scripts for repeater fields 3.1 Repeater Previews 4. Common settings 4.1 Tabs in the backend 5. Conditional settings */ /* 1. DEFINING THE VARIABLES NECESSARY FOR THIS SCRIPT =================================================== */ // Needed for the Image data type var custom_uploader; // Needed for the Select data type // Basic settings for all types of dropdowns TPL_Admin.basic_select2_settings = { escapeMarkup: function(m) { return m; }, width: "100%", } // General settings for simple select dropdowns var select2_settings = $.extend( { minimumResultsForSearch: 10, }, TPL_Admin.basic_select2_settings ); // Font Awesome dropdown settings var fa_icon_settings = $.extend( { templateSelection: tpl_fa_icon_template, templateResult: tpl_fa_icon_template, formatSelection: tpl_fa_icon_template, formatResult: tpl_fa_icon_template, minimumResultsForSearch: 10, }, TPL_Admin.basic_select2_settings ); // Do an initial row arrangement, just in case... tpl_arrange_rows(); // Remove the dummy editor from the TO/FO DOM after initialization $('#wp-dummy_editor-wrap').remove(); /* 2. SCRIPTS FOR SINGLE DATA TYPES ================================ 2.1 IMAGE DATA TYPE ------------------- */ // Main uploader popup handler $('body').on('click', '.tpl-uploader .button, .tpl-uploader .tpl-uploaded-image, .tpl-img-placeholder', function(e) { e.preventDefault(); var imgurl = $(this).parent().find('.tpl-uploaded-image'); var current_item = imgurl.closest('.tpl-field'); //Extend the wp.media object custom_uploader = wp.media.frames.file_frame = wp.media({ title: TPL_Admin.uploader_title, button: { text: TPL_Admin.uploader_button }, multiple: false }); //When a file is selected, grab the URL and set it as the text field's value custom_uploader.on('select', function() { var attachment = custom_uploader.state().get('selection').first().toJSON(); if ( typeof attachment.sizes.thumbnail !== 'undefined' ) { imgurl.attr('src', attachment.sizes.thumbnail.url); } else { imgurl.attr('src', attachment.sizes.full.url); } imgurl.show(); current_item.find('.tpl-img_id').val(attachment.id).trigger('change'); current_item.find('.tpl-img-placeholder').hide(); current_item.find('.tpl-closer').show(); tpl_set_repeater_headers(); }); //Open the uploader dialog custom_uploader.open(); }); // Clear the uploaded picture with the "X" icon $('body').on('click', '.tpl-uploader .tpl-closer', function(){ var imgurl = $(this).parent().find('.tpl-uploaded-image'); var current_item = imgurl.closest('.tpl-field'); imgurl.attr('src', ''); current_item.find('.tpl-img-placeholder').show(); current_item.find('.tpl-uploaded-image').hide(); $(this).closest('.tpl-field').find('.tpl-img_id').val('').trigger('change'); $(this).hide(); tpl_set_repeater_headers(); }); /* 2.2 COLOR DATA TYPE ------------------- */ // Common color picker settings used by all instances var color_picker_settings = { width : 258, change : function(event,ui){ $(this).val($(this).wpColorPicker('color')); tpl_condition_updater(); tpl_set_repeater_headers(); } } // Color picker script $('body .tpl-color-field').each(function(){ $(this).wpColorPicker( color_picker_settings ); }); /* 2.3 SELECT DATA TYPE -------------------- */ // Select scripts function tpl_select2_init(){ $('body .tpl-dt-select').each(function(){ if ( $(this).has('.select2').length < 1 && !$(this).hasClass('no-select2') && !$(this).parents('#tpl_repeater_bank').length ) { if ( $(this).is('.tpl-dt-font_awesome') ) { $(this).find('select').select2( fa_icon_settings ); } else { $(this).find('select').select2( select2_settings ); } } }); } tpl_select2_init(); // Font Awesome select field template function tpl_fa_icon_template(data) { if ( data.id != '' ) { return ' ' + data.text; } else { return data.text; } } /* 2.4 TINYMCE DATA TYPE --------------------- */ // Settings for the TinyMCE editor function tpl_tinymce_init() { $( 'body .tpl-field.tpl-dt-tinymce' ).not( $('body .tpl-field.tpl-dt-tinymce.tpl-admin-hide') ).each(function(){ var id = $(this).find('textarea').attr('id'); tinyMCE.execCommand( 'mceAddEditor', false, id ); }); $( 'body .tpl-field.tpl-dt-tinymce.tpl-admin-hide').each(function(){ var id = $(this).find('textarea').attr('id'); tinyMCE.execCommand( 'mceRemoveEditor', false, id ); }); } /* 2.5 DATE DATA TYPE ------------------ */ // Date picker for the Date type if ($.datepicker !== undefined) { $('body .tpl-field.tpl-dt-date input.tpl-date-field').datepicker({ dateFormat: 'yy-mm-dd', firstDay: TPL_Admin.date_starts_with }); } /* 2.6 BOOLEAN DATA TYPE --------------------- */ // Setting the value for the boolean DT $('body').on('click', '.tpl-field.tpl-dt-boolean label', function(){ var old_value = parseInt( $('input', this).val() ); if ( old_value == 1 ) { var new_value = 0; } if ( old_value == 0 || isNaN( old_value ) ) { var new_value = 1; } $('input', this).val( new_value ).trigger('change'); $(this).attr('class', 'checked-' + new_value ); }); /* 3. REPEATER FIELDS ================== */ // Post metaboxes and settings pages use different containers, that's why we need this function function tpl_repeat_set_container( elem ){ var url = window.location.href; // Primary Options page (e.g. Plugin Settings) if ( url.indexOf('themes.php') > -1 || url.indexOf('options-general.php') > -1 ) { if ( elem.parent().prev().hasClass('tpl-subitem-repeat-wrapper') ) { var container = elem.parent().prev('.tpl-subitem-repeat-wrapper'); } else { var container = elem.closest('tr').prev().find('td'); } } // Post options branch if ( url.indexOf('post.php') > -1 || url.indexOf('post-new.php') > -1 ) { if ( elem.parent().prev().hasClass('tpl-subitem-repeat-wrapper') ) { var container = elem.parent().prev('.tpl-subitem-repeat-wrapper'); } else { var container = elem.parent().prev('.tpl-meta-option-wrapper'); } } return container; } // Add rows to repeater $('body').on('click', 'button.tpl-repeat-add', function(e){ e.preventDefault(); var container = tpl_repeat_set_container( $(this) ); tpl_add_row( container, $(this).attr('data-for') ); }); // Adds a repeater row into the container picking the fields connected with data_name function tpl_add_row( container, data_name ) { var donor = $("#tpl_repeater_bank .tpl-field[data-name='" + data_name + "']").clone(); container.append(donor); tpl_repeater_refresh(container); tpl_arrange_rows(); tpl_condition_updater(); // Launch color picker if ( $('.tpl-dt-color').length > 0 ) { $('body .tpl-color-field').wpColorPicker( color_picker_settings ); } // Launch Select2 on select fields tpl_select2_init(); // Launch date picker if ($.datepicker !== undefined) { $('body .tpl-field.tpl-dt-date input.tpl-date-field').datepicker({ dateFormat: 'yy-mm-dd', firstDay: TPL_Admin.date_starts_with }); } tpl_tinymce_init(); tpl_set_repeater_headers(); } // Remove rows from repeater $('body').on('click', '.tpl-remover', function(){ tpl_remove_row( $(this) ); }); // elem is the remover icon, then this function finds what to remove function tpl_remove_row( elem ) { var container = $(elem).closest('.tpl-repeater'); var remove = confirm( TPL_Admin.remover_confirm_text ); if ( remove == true ) { $(elem).closest('.tpl-field').remove(); tpl_repeater_refresh(container); } }; // Arrange rows function tpl_arrange_rows(){ $('.tpl-repeat').each(function(){ $(this).parent().addClass('tpl-repeater'); }); if ( typeof $.ui.sortable != 'undefined' ) { $('.tpl-repeater').sortable({ handle : '.tpl-arranger', update : function( event, ui ) { tpl_repeater_refresh( $(this) ); }, start : function( event, ui ){ ui.placeholder.height( ui.item.height() ); ui.item.closest('.tpl-repeater').find('.tpl-field.tpl-dt-tinymce textarea').each(function(){ var id = $(this).attr('id'); tinyMCE.execCommand('mceRemoveEditor', false, id); }); }, stop: function(event, ui) { // re-initialize TinyMCE when sort is completed tpl_tinymce_init(); } }); } } // Update order numbers after repeater item added, removed or rearranged function tpl_repeater_refresh(container){ var url = window.location.href; var i = []; i[0] = 0; var name = ''; container.find('.tpl-field').each(function(){ // Setting up levels + instances for the current field var level = parseInt($(this).attr('data-level')); var name_array = $(this).attr('data-name').split('/'); if ( level > 0 ) { for (var k=0; k -1 || url.indexOf('post-new.php') > -1 ) && j == 0 ) { newname += '[' + i[j] + ']'; } else { newname += '[' + name_array[j] + '][' + i[j] + ']'; } } else { if ( $(this).closest('.tpl-field').hasClass('tpl-repeat') ) { newname += '[' + name_array[j] + '][' + i[j] + ']'; } else { newname += '[' + name_array[j] + ']'; } } } $(this).attr('name', newname); $(this).attr('id', newname); $(this).closest('.tpl-field').prevAll('label').attr('for', newname); } }); }); } // Show / hide block $('body').on('click', '.tpl-toggle-close', function(){ $(this).closest('.tpl-repeat').children('.tpl-field-inner').addClass('tpl-admin-hide'); $(this).closest('.tpl-repeat-header').addClass('tpl-repeat-header-closed'); $(this).attr('title', TPL_Admin.Repeat_Maximize); $(this).removeClass('tpl-toggle-close'); $(this).addClass('tpl-toggle-open'); }); $('body').on('click', '.tpl-toggle-open', function(){ $(this).closest('.tpl-repeat').children('.tpl-field-inner').removeClass('tpl-admin-hide'); $(this).closest('.tpl-repeat-header').removeClass('tpl-repeat-header-closed'); $(this).attr('title', TPL_Admin.Repeat_Minimize); $(this).addClass('tpl-toggle-close'); $(this).removeClass('tpl-toggle-open'); }); /* 3.1 REPEATER PREVIEWS --------------------- */ // Gets the Data Type class (tpl-dt-xxx) out of the .tpl-field element function tpl_get_type_class(tpl_field){ var class_names = tpl_field.attr('class').split(/\s+/); var ret = ''; $.each(class_names, function(index, item) { if ( item.indexOf( "tpl-dt-" ) == 0 && item != 'tpl-dt-combined' ) { ret = item; } }); return ret; } // Get the preview value of an element function tpl_get_preview_value(tpl_preview_field){ var pure_preview = ''; if ( typeof tpl_preview_field.attr('data-preview-value') !== 'undefined' ) { pure_preview = tpl_preview_field.attr('data-preview-value'); } else { var tag = tpl_preview_field.prop("tagName").toLowerCase(); switch (tag) { case 'select': if ( tpl_preview_field.closest('.tpl-dt-select').is('.tpl-select-preview-key') ) { pure_preview = tpl_preview_field.val(); } else { pure_preview = tpl_preview_field.closest('.tpl-dt-select').find('.select2-selection__rendered').html(); } break; case 'span': pure_preview = tpl_preview_field.html(); break; case 'textarea': pure_preview = tpl_preview_field.html().replace( /<([\s\S]*?)>/g, '' ); break; case 'img': pure_preview = tpl_preview_field.attr('src'); break; default: pure_preview = tpl_preview_field.val(); } } return pure_preview; } // Get the parent data name function tpl_get_data_name_parent(data_name){ data_name = data_name.split('/'); var res = ''; for (var i=0;i -1 && $('[data-name="'+tpl_get_data_name_parent(data_name)+'"]').is('.tpl-repeat') && $(this).closest('[data-name="'+tpl_get_data_name_parent(data_name)+'"]').parent().find('[data-name="'+tpl_get_data_name_parent(data_name)+'"]').length > parseInt($(this).closest('[data-name="'+tpl_get_data_name_parent(data_name)+'"]').attr('data-instance')) + 1 && parseInt($(cfield).attr('data-level')) < 3 && $(orig_repeat).is('.tpl-preview-multi') ) { preview = preview.replace( item, tpl_get_preview_value($(this)) ) + ' / '+item; } else { preview = preview.replace( item, tpl_get_preview_value($(this)) ); } } }); }); }); // Clean up the remaining shortcodes $.each(to_change, function(i, item){ preview = preview.replace( item, '' ); }); } // If not, add the subitems' templates one-by-one else { var l = $('.tpl-field', this).length; $('.tpl-field', this).each(function(i){ data_name = $(this).attr('data-name'); dt_class = tpl_get_type_class($(this)) + '_preview-template'; // If have a template, use it if ( typeof TPL_Admin[dt_class] !== 'undefined' ) { preview += TPL_Admin[dt_class]; $('*[class*=tpl-preview-]', this).each(function(index){ preview = preview.replace( '[tpl-preview-'+index+']', tpl_get_preview_value($(this)) ); }); } // Else put the values after each other else { $('*[class*=tpl-preview-]', this).each(function(index){ preview += tpl_get_preview_value($(this)); }); } if ( i < (l-1) ) { preview += ' / '; } }); } } // Finally, setting up the repeater header $('.tpl-header-title-preview', this).html(preview); }); } /* 4. COMMON SETTINGS ================== 4.1 TABS IN THE BACKEND ----------------------- */ // Tabs in Plugin Settings if (typeof $.ui.tabs !== 'undefined') { $('#tpl-settings-tabs').tabs(); if (typeof Storage !== "undefined" && $('#tpl-settings-tabs').length != 0) { // Set the active tab if present in sessionStorage var tabName = $('#tpl-settings-tabs').attr('data-store'); var tabValue = sessionStorage.getItem(tabName); if (typeof tabValue !== "undefined") { $('#tpl-settings-tabs').tabs('option', 'active', tabValue); } // Save the active tab to sessionStorage for future use $('#tpl-settings-tabs .nav-tab').click(function(){ var tabName = $('#tpl-settings-tabs').attr('data-store'); var tabValue = $('#tpl-settings-tabs').tabs('option', 'active'); sessionStorage.setItem(tabName, tabValue); }); } } /* 5. CONDITIONAL SETTINGS ======================= */ // Retrieves (name) parameter's value from (url) function tpl_get_url_param(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); } // Checks the current post type in admin function tpl_get_post_type(){ var attrs, attr, post_type; post_type = null; attrs = $( 'body' ).attr( 'class' ).split( ' ' ); $( attrs ).each(function() { if ( 'post-type-' === this.substr( 0, 10 ) ) { post_type = this.split( 'post-type-' ); post_type = post_type[ post_type.length - 1 ]; return; } }); return post_type; } // Checks if a variable is numeric function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } // Updates the state of the conditional options. Use it after every change in the conditions. function tpl_condition_updater() { var url = window.location.href; $('body .tpl-field, body .tpl-subitem-repeat-wrapper, body .tpl-meta-option').each(function(){ // Primary Options page (e.g. Plugin Settings) if ( url.indexOf('themes.php') > -1 || url.indexOf('options-general.php') > -1 ) { var section = tpl_get_url_param('page', url); var container = 'tr'; } // Post options branch if ( url.indexOf('post.php') > -1 || url.indexOf('post-new.php') > -1 ) { var section = ''; var container = '.tpl-meta-option'; } var option_name = $(this).attr('data-name'); var data_connected = $(this).attr('data-connected'); if ( $(this).hasClass('tpl-subitem-repeat-wrapper') || $(this).hasClass('tpl-meta-option') ) { option_name = data_connected; } // Section is different when we're dealing with a post option if ( section == '' ) { section = $(this).closest('.postbox').attr('id'); } // Do things only if the condition is registered in the Conditions object if ( TPL_Admin.Conditions !== undefined && TPL_Admin.Conditions[option_name] !== undefined ) { var Olength = Object.keys(TPL_Admin.Conditions[option_name]).length; var ci; var matches = []; for ( ci = 0; ci < Olength; ci++ ) { if ( typeof TPL_Admin.Conditions[option_name][ci] !== 'undefined' ) { var condition_type = TPL_Admin.Conditions[option_name][ci]["type"]; var condition_name = TPL_Admin.Conditions[option_name][ci]["name"]; var condition_relation = TPL_Admin.Conditions[option_name][ci]["relation"]; var condition_value = TPL_Admin.Conditions[option_name][ci]["value"]; var base_id = ''; var base_val = ''; var cname_array = []; var c_array = []; var dname_array = []; // If the condition is an option if ( condition_type == 'option' ) { // Modifications on the name if it's a cobined field if ( condition_name.indexOf( '/' ) > -1 ) { cname_array = condition_name.split("/"); dname_array = option_name.split("/"); // If the base of the condition is a sibling field of the current one if ( cname_array[0] == "_THIS_" ) { for ( var j = 0; j < dname_array.length - 1; j++ ) { c_array[2*j] = dname_array[j]; var current_data_name = ''; for ( var k = 0; k <= j; k++ ) { current_data_name += dname_array[k]; if ( k < j ) { current_data_name += '/'; } } c_array[2*j+1] = $(this).closest('.tpl-field[data-name="'+ current_data_name +'"]').attr('data-instance'); } c_array.push( cname_array[cname_array.length-1] ); } // If the base of the condition is an absolute path else { c_array = cname_array; } } // Condition is a single variable else { c_array[0] = condition_name; c_array[1] = 0; } base_id = '#' + section; if ( url.indexOf('post.php') > -1 || url.indexOf('post-new.php') > -1 ) { base_id += '_' + c_array[0]; } for ( var l = 0; l < c_array.length; l++ ) { if ( url.indexOf('post.php') > -1 || url.indexOf('post-new.php') > -1 ) { if ( l > 0 ) { base_id += '\\[' + c_array[l] + '\\]'; } } else { base_id += '\\[' + c_array[l] + '\\]'; } } // base_val: the base element's value base_val = $(base_id).val(); } // If the condition is a post type if ( condition_type == 'post' ) { // In this case base_val is the post type caught from the current post if ( condition_name == 'type' ) { base_val = tpl_get_post_type(); } // In this case base_val is the ID of a specific post if ( condition_name == 'id' ) { base_val = tpl_get_url_param( 'post', url ); } } // If the condition is a page template if ( condition_type == 'page' ) { // In this case base_val is the post type caught from the current post if ( condition_name == 'template' ) { base_val = $('#page_template').val(); } } // If the condition is a taxonomy if ( condition_type == 'taxonomy' ) { // Post formats are a special case if ( condition_name == 'post_format' ) { $('#post-formats-select input').each(function(){ if ( $(this).is(':checked') ) { base_val = $(this).attr('id').replace( 'post-format-', '' ); } }); } // Other taxonomies work in the same way (except tags - they are not supported at the moment) else { var base_val = []; var cat_no = 0; $('#' + condition_name + 'checklist li').each(function(){ cat_no = $(this).attr('id').replace( condition_name + '-', '' ); if ( $('input', this).is(':checked') ) { base_val.push( cat_no ); } }); } } // Setting up the results of the relations switch ( condition_relation ) { case '=': if ( $.isArray( base_val ) ) { if ( $.inArray( condition_value, base_val ) > -1 ) { matches.push( true ); } else { matches.push( false ); } } else { if ( base_val == condition_value ) { matches.push( true ); } else { matches.push( false ); } } break; case '!=': if ( $.isArray( base_val ) ) { if ( $.inArray( condition_value, base_val ) < 0 ) { matches.push( true ); } else { matches.push( false ); } } else { if ( base_val != condition_value ) { matches.push( true ); } else { matches.push( false ); } } break; case '<': if ( base_val < condition_value ) { matches.push( true ); } else { matches.push( false ); } break; case '>': if ( base_val > condition_value ) { matches.push( true ); } else { matches.push( false ); } break; } } } // Conditions FOR cycle // Now displaying it or not based on the results var met = false; var logic = 'and'; if ( TPL_Admin.Conditions[option_name]["logic"] !== undefined ) { var logic = TPL_Admin.Conditions[option_name]["logic"]; } // If logic is (AND) and there is no FALSE result in the matches array, then the condition is met if ( logic == 'and' && $.inArray( false, matches ) < 0 ) { met = true; } // If logic is (OR) and there is at least one TRUE result in the matches array, then the condition is met if ( logic == 'or' && $.inArray( true, matches ) > -1 ) { met = true; } // Now show or hide the option based on the (met) variable data_connected = data_connected.replace('/', '\/'); // Showing elements if ( met == true ) { if ( typeof data_connected !== "undefined" ) { $(this).parent().parent().parent().find('[data-connected="'+ data_connected +'"]').removeClass('tpl-admin-hide'); if ( container == 'tr' && $(this).attr('data-level') == '0' ) { $(this).closest(container).next(container).has('.tpl-optiondesc').removeClass('tpl-admin-hide'); $(this).closest(container).removeClass('tpl-admin-hide'); } else { $(this).closest(container).next('p.tpl-optiondesc').removeClass('tpl-admin-hide'); } $(this).find('input, select, textarea').each(function(){ $(this).attr('name', $(this).attr('id')); }); } } // Hiding elements else { if ( typeof data_connected !== "undefined" ) { $(this).parent().parent().parent().find('[data-connected="'+ data_connected +'"]').addClass('tpl-admin-hide'); if ( container == 'tr' && $(this).attr('data-level') == '0' ) { $(this).closest(container).next(container).has('.tpl-optiondesc').addClass('tpl-admin-hide'); $(this).closest(container).addClass('tpl-admin-hide'); } else { $(this).closest(container).next('p.tpl-optiondesc').addClass('tpl-admin-hide'); } $(this).find('input, select, textarea').removeAttr('name'); $(this).closest(container).find('.tpl-field.tpl-dt-tinymce.tpl-admin-hide textarea').each(function(){ var editor_id = $(this).attr('id'); tinymce.execCommand('mceRemoveEditor', false, editor_id); }); } } } // Closing check for the Conditions object }); $('.postbox').each(function(){ var meta_hide = []; $('.tpl-meta-option', this).each(function(){ if ( $(this).hasClass('tpl-admin-hide') ) { meta_hide.push( true ); } else { meta_hide.push( false ); } }); if ( $.inArray( true, meta_hide ) > -1 && $.inArray( false, meta_hide ) < 0 ) { $(this).addClass('tpl-admin-hide'); } else { $(this).removeClass('tpl-admin-hide'); } }); } tpl_condition_updater(); tpl_tinymce_init(); $('body').on('change', 'select, input, textarea', function(){ tpl_condition_updater(); tpl_set_repeater_headers(); }); $('body').on('keyup', 'input, textarea', function(){ // Because the condition updater is a resource-heavy operation, run it only if the value length is 0 or 1 if ( $(this).val().length < 2 ) { tpl_condition_updater(); } }); });