/** * Main script file for WP admin * * @package PT_Content_Views_Admin * @author PT Guy * @license GPL-2.0+ * @link http://www.contentviewspro.com/ * @copyright 2014 PT Guy */ ( function ( $ ) { "use strict"; $.PT_CV_Admin = $.PT_CV_Admin || { }; PT_CV_ADMIN = PT_CV_ADMIN || { }; ajaxurl = ajaxurl || { }; var _prefix = PT_CV_ADMIN._prefix; $.PT_CV_Admin = function ( options ) { this.options = $.extend( { onload: 1, scroll_time: 500, can_preview: 1 }, options ); this.init(); }; $.PT_CV_Admin.prototype = { init: function () { this.custom(); // Validate number this.validate_number(); // Select2 $( 'select.' + _prefix + 'select2' ).select2(); }, custom: function () { var $self = this; this.preview(); this._preview_btn_toggle(); this._content_type(); this._toggle_taxonomy_relation(); this._thumbnail_settings(); // Toggle panel this._toggle_panel( '.' + _prefix + 'group .panel-heading' ); // 'Advance Settings' this.toggle_group( '.' + _prefix + 'advanced-settings-item' ); // 'Terms' (in "Taxonomy Settings") this.toggle_group( '.' + _prefix + 'taxonomy-item' ); // 'Content type' this.toggle_group( '[name="' + _prefix + 'content-type' + '"]', false ); // 'View type settings' this.toggle_group( '[name="' + _prefix + 'view-type' + '"]', false ); // Toggle dependencies this.dependence_do_all(); // Prevent click on links $( '#' + _prefix + 'preview-box' ).on( 'click', 'a', function ( e ) { e.preventDefault(); } ); $( '.pt-accordion-a' ).click( function ( e ) { e.preventDefault(); } ); // Show alert when leave page without saving View var checked = 0; $( '#' + _prefix + 'form-view input[type="submit"]' + ',' + 'a[href*="action=duplicate"]' ).click( function () { checked = 1; } ); window.onbeforeunload = function ( event ) { if ( !$self.options.onload && !checked ) { var message = 'The changes you made will be lost if you navigate away from this page.'; if ( typeof event === 'undefined' ) { event = window.event; } if ( event ) { event.returnValue = message; } return message; } }; // Handle Pagination actions $( 'body' ).bind( _prefix + 'admin-preview', function () { new $.PT_CV_Public(); } ); }, /** * Toggle panel when click Show/Hide icon on Heading * * @param {type} $selector * @returns {undefined} */ _toggle_panel: function ( $selector ) { $( 'body' ).on( 'click', $selector, function ( e ) { var $heading = $( this ); var $span = $heading.find( 'span.clickable' ); var time = 100; if ( !$span.hasClass( 'panel-collapsed' ) ) { $heading.next( '.panel-body' ).slideUp( time ); $span.addClass( 'panel-collapsed' ); $span.find( 'i' ).removeClass( 'glyphicon-minus' ).addClass( 'glyphicon-plus' ); } else { $heading.next( '.panel-body' ).slideDown( time ); $span.removeClass( 'panel-collapsed' ); $span.find( 'i' ).removeClass( 'glyphicon-plus' ).addClass( 'glyphicon-minus' ); } } ); }, /** * Toggle Taxonomy Relation setting on page load & on change * * @returns void */ _toggle_taxonomy_relation: function () { var $self = this; $self._do_toggle_taxonomy_relation(); $( '.' + _prefix + 'taxonomy-item' ).change( function () { $self._do_toggle_taxonomy_relation(); } ); }, /** * Toggle Taxonomy Relation setting by number of selected taxonomies * * @returns {undefined} */ _do_toggle_taxonomy_relation: function () { var $taxonomy_relation = $( '.' + _prefix + 'taxonomy-relation' ).parent().parent( '.form-group' ); var $wrap_taxonomies = $( '#' + _prefix + 'group-taxonomy' ); // If there is no taxonomies var is_multi = false; if ( $wrap_taxonomies.find( '.' + _prefix + 'taxonomies .checkbox' ).filter( function () { return !$( this ).hasClass( 'hidden' ) && $( this ).find( 'input:checked' ).length; } ).length > 1 ) { $taxonomy_relation.removeClass( 'hidden' ); is_multi = true; } else { $taxonomy_relation.addClass( 'hidden' ); } $( '.pt-wrap' ).trigger( _prefix + 'multiple-taxonomies', [ is_multi ] ); }, /** * Get field value, depends on field type & its parent is show/hide * * @param {type} el : string to selector * @returns {undefined} */ _get_field_val: function ( el ) { var $this = $( el ); var value = $( el ).val(); if ( $this.is( ':checkbox' ) || $this.is( ':radio' ) ) { value = $( el + ':checked' ).val(); } return value; }, /** * Do toggle all dependency groups * * @returns {undefined} */ dependence_do_all: function () { var $self = this; var $toggle_data_js = $.parseJSON( $self.options._toggle_data ); $.each( $toggle_data_js, function ( idx, obj ) { // Obj_sub: an object contains (dependence_id, operator, expect_val) $.each( obj, function ( key, obj_sub ) { // Get name of depended element (which other elements depend on it) var el_name = _prefix + key; var el = "[name='" + el_name + "']"; // Run on page load $self._dependence_group( $self._get_field_val( el ), obj_sub ); // Run on change $( el ).change( function () { $self._dependence_group( $self._get_field_val( el ), obj_sub ); } ); } ); } ); }, /** * Toggle each dependency group * @param {type} this_val : current value of depended element (which other elements depend on it) * @param {type} obj_sub : an object contains (dependence_id, expect_val, operator) * @returns {undefined} */ _dependence_group: function ( this_val, obj_sub ) { var $self = this; $.each( obj_sub, function ( key, data ) { $self._dependence_element( data[0], this_val, data[2], data[1] ); } ); }, /** * Toggle each dependency element * * @param {type} dependence_id : id of group A which depends on an element B * @param {type} this_val : current value of B * @param {type} operator : operator to comparing A's value & B's value : =, >, < ... * @param {type} expect_val : expect value of B to show A group * @returns {undefined} */ _dependence_element: function ( dependence_id, this_val, operator, expect_val ) { var dependence_el = $( "#" + dependence_id ); var pass = 0; switch ( operator ) { case "=": { if ( typeof expect_val === 'string' ) expect_val = [ expect_val ]; pass = ( $.inArray( this_val, expect_val ) >= 0 ); } break; case "!=": { if ( typeof expect_val === 'string' ) expect_val = [ expect_val ]; pass = ( $.inArray( this_val, expect_val ) < 0 ); } break; default : if ( typeof expect_val !== 'object' ) pass = eval( "this_val " + operator + " expect_val" ); break; } var action = ''; var result = 0; if ( pass ) { dependence_el.removeClass( 'hidden' ); action = 'remove'; result = !dependence_el.hasClass( 'hidden' ); } else { dependence_el.addClass( 'hidden' ); action = 'add'; result = dependence_el.hasClass( 'hidden' ); } // Log if something is wrong if ( !result ) console.log( dependence_id, this_val, operator, expect_val, action ); }, /** * Toggle a group inside Panel group when check/uncheck a checkbox inside checboxes list * * @param {type} selector * @param {type} toggle * @returns {undefined} */ toggle_group: function ( selector, toggle ) { var $self = this; // Run on page load $( selector ).each( function () { $self._toggle_each_group( $( this ), toggle ); } ); // Run on change $( selector ).each( function () { $( this ).change( function () { var this_ = $( this ); setTimeout( function () { $self._toggle_each_group( this_, toggle ); }, 200 ); } ); } ); }, /** * Toggle group depends on selector value * * @param {type} $this * @param {type} toggle * @returns {undefined} */ _toggle_each_group: function ( $this, toggle ) { var $self = this; if ( $this.is( 'select' ) || ( ( $this.is( ':checkbox' ) || $this.is( ':radio' ) ) && $this.is( ':checked' ) ) ) { // Get id of element A which needs to toggle var toggle_id = '#' + PT_CV_ADMIN._group_prefix + $this.val(); // Get siblings groups of A var other_groups = $( toggle_id ).parent().children( '.' + _prefix + 'group' ).not( toggle_id ); if ( $( toggle_id ).hasClass( _prefix + 'only-one' ) ) { // Hide other group in a same Panel group other_groups.addClass( 'hidden' ); } else { } // Show group $( toggle_id ).removeClass( 'hidden' ); // Show the content $( toggle_id ).find( '.panel-body' ).show(); // Scroll to if ( toggle !== false && !$self.options.onload && $( toggle_id ).offset() ) { $( 'html, body' ).animate( { scrollTop: $( toggle_id ).offset().top - 40 }, $self.options.scroll_time ); } // Highlight color var activate_group = _prefix + 'group-activate'; $( toggle_id ).addClass( activate_group ); // Remove highlight color setTimeout( function () { $( toggle_id ).removeClass( activate_group ); }, 2000 ); } else { $( '#' + PT_CV_ADMIN._group_prefix + $this.val() ).addClass( 'hidden' ); } }, /** * Custom function for 'Content Type' * * @returns {undefined} */ _content_type: function () { var $self = this; var $wrap_taxonomies = $( '#' + _prefix + 'group-taxonomy' ); var $taxonomy_other_settings = $( '.' + _prefix + 'taxonomy-extra' ); var $taxonomies = $( '.' + _prefix + 'taxonomy-item' ); var $no_taxonomy = $( '
', { 'id': _prefix + 'no-taxonomy', 'class': _prefix + 'text', 'text': PT_CV_ADMIN.text.no_taxonomy } ).appendTo( $( '.' + _prefix + 'taxonomies' ) ); var fn_taxonomy_hide = function ( taxonomies ) { // Hide all taxonomy checkboxes taxonomies.each( function () { $( this ).parents( '.checkbox' ).addClass( 'hidden' ); } ); $no_taxonomy.addClass( 'hidden' ); // Hide all sections of taxonomies $( '.panel-group.terms' ).find( '.' + _prefix + 'group' ).addClass( 'hidden' ); }; // Run on page load fn_taxonomy_hide( $taxonomies ); // For content type var content_type = '[name="' + _prefix + 'content-type' + '"]'; var fn_content_type = function ( is_change ) { var this_val; if ( $( content_type ).is( 'input:radio' ) ) { this_val = $( content_type + ':checked' ).val(); } else { this_val = $( content_type ).val(); } if ( typeof this_val === 'undefined' ) { return; } if ( is_change ) { // Uncheck all checkbox of taxonomies $taxonomies.attr( 'checked', false ); // Toggle Taxonomy Relation setting $self._do_toggle_taxonomy_relation(); } // Show taxonomies of selected post type if ( this_val !== '' ) { fn_taxonomy_hide( $taxonomies ); $taxonomies.filter( function () { var val = $( this ).val(); var $taxonomies_of_this = PT_CV_ADMIN.data.post_types_vs_taxonomies[this_val] || ''; return $.inArray( val, $taxonomies_of_this ) >= 0; } ).parents( '.checkbox' ).removeClass( 'hidden' ); } // Show message "there is no taxonomy" if ( $wrap_taxonomies.find( '.' + _prefix + 'taxonomies .checkbox' ).filter( function () { return !$( this ).hasClass( 'hidden' ); } ).length === 0 ) { $no_taxonomy.removeClass( 'hidden' ); $taxonomy_other_settings.addClass( 'hidden' ); } // Trigger custom actions $( '.pt-wrap' ).trigger( 'content-type-change', [ this_val ] ); }; // Run on page load fn_content_type(); // Run on change $( content_type ).change( function () { fn_content_type( 1 ); } ); }, /** * Preview handle * * @returns {undefined} */ preview: function () { var $self = this; var offset_top; $( '#' + _prefix + 'show-preview' ).click( function ( e ) { e.stopPropagation(); e.preventDefault(); $( 'body' ).trigger( _prefix + 'admin-preview-start' ); var $this_btn = $( this ); // Get Preview box var $preview = $( '#' + _prefix + 'preview-box' ); // Show/hide Preview box if ( $self.options.can_preview ) { $preview.addClass( 'in' ); } else { $preview.removeClass( 'in' ); } /** * Animation */ // Scroll to preview box if want to show it if ( $self.options.can_preview ) { // Get current offset top to go back later offset_top = $( document ).scrollTop(); // Scroll to preview box $( 'html, body' ).animate( { scrollTop: $preview.offset().top - 100 }, $self.options.scroll_time ); /// Send request $preview.css( 'opacity', '0.2' ); // Show loading icon $preview.next().removeClass( 'hidden' ); // Get settings data var data = $( '#' + _prefix + 'form-view' ).serialize(); // Call handle function $self._preview_request( $preview, data, $this_btn ); } else { // Scroll to previous position $( 'html, body' ).animate( { scrollTop: offset_top }, $self.options.scroll_time ); // Toggle text of this button $this_btn.html( PT_CV_ADMIN.btn.preview.show ); // Enable preview setTimeout( function () { $self.options.can_preview = 1; }, $self.options.scroll_time ); } } ); }, /** * Send preview Ajax request * * @param {object} preview_box The jqurey object * @param {string} _data * @param {object} $this_btn The Show/Hide preview button * @returns void */ _preview_request: function ( preview_box, _data, $this_btn ) { var $self = this; var data = { action: 'preview_request', data: _data, ajax_nonce: PT_CV_ADMIN._nonce }; // Sent POST request $.ajax( { type: "POST", url: ajaxurl, data: data } ).done( function ( response ) { var reload = false; if ( response == -1 || response == 0 ) { reload = true; response = "Your session has expired. This page will be reloaded."; } preview_box.css( 'opacity', '1' ); // Hide loading icon preview_box.next().addClass( 'hidden' ); // Update content of Preview box preview_box.html( response ); if ( reload ) { location.reload(); } $self._filter_response( preview_box ); // Toggle text of this button $this_btn.html( PT_CV_ADMIN.btn.preview.hide ); // Disable preview $self.options.can_preview = 0; // Trigger action, to recall function such as pagination, pinterest render layout... $( 'body' ).trigger( _prefix + 'admin-preview' ); } ); }, _filter_response: function ( preview_box ) { var fn_alert_visible_sc = function () { $( '.' + _prefix + 'content', preview_box ).each( function () { var tclass = _prefix + 'caution'; $( '.' + tclass ).remove(); var content = $( this ).html(); var regex = /\[[^\]]+\]/; if ( regex.test( content ) ) { $( '
', { html: PT_CV_ADMIN.text.visible_shortcode, class: tclass } ).insertBefore( preview_box ); return false; } } ); }; fn_alert_visible_sc(); $( 'body' ).trigger( _prefix + 'preview-response', [ preview_box ] ); }, /** * Toggle 'Thumbnail settings' * * @returns {undefined} */ _thumbnail_settings: function () { // Toggle 'Thumbnail settings' when change 'Layout format' var fn_thumbnail_setting = function ( this_val ) { var $show_thumbnail = $( '[name="' + _prefix + 'show-field-thumbnail' + '"]' ); // Force to show thumbnail IF it is not enabled if ( this_val === '2-col' && !$show_thumbnail.is( ':checked' ) ) { $show_thumbnail.trigger( 'click' ); } }; var layout_format = '[name="' + _prefix + 'layout-format' + '"]'; // Run on page load fn_thumbnail_setting( $( layout_format + ':checked' ).val() ); // Run on change $( layout_format ).change( function () { fn_thumbnail_setting( $( layout_format + ':checked' ).val() ); } ); /** * Toggle 'Layout format' when change 'View type' * * @param {type} this_val * @param {type} layout_format * @returns {undefined} */ var view_type = '[name="' + _prefix + 'view-type' + '"]'; var fn_layout_format = function ( layout_format ) { var this_val; if ( $( view_type ).is( 'input:radio' ) ) { this_val = $( view_type + ':checked' ).val(); } else { this_val = $( view_type ).val(); } var expect_val = [ 'scrollable' ]; // Add more layouts $( '.pt-wrap' ).trigger( 'toggle-layout-format', [ expect_val ] ); if ( $.inArray( this_val, expect_val ) >= 0 ) { // Trigger select 1-col $( layout_format + '[value="1-col"]' ).trigger( 'click' ); // Disable 2-col $( layout_format + '[value="2-col"]' ).attr( 'disabled', true ); } else { // Enable 2-col $( layout_format + '[value="2-col"]' ).attr( 'disabled', false ); } }; // Run on page load fn_layout_format( layout_format ); // Run on change $( view_type ).change( function () { fn_layout_format( layout_format ); } ); }, /** * Toggle text of Preview button * @returns {undefined} */ _preview_btn_toggle: function () { var $self = this; var _fn = function ( is_trigger ) { if ( !is_trigger ) { $self.options.onload = 0; } // Toggle text of this button $( '#' + _prefix + 'show-preview' ).html( PT_CV_ADMIN.btn.preview.update ); // Enable preview $self.options.can_preview = 1; }; // Bind on change input after page load $( '.pt-wrap .tab-content' ).on( 'change', 'input, select, textarea', function ( evt, is_trigger ) { _fn( is_trigger ); } ); $( 'body' ).bind( _prefix + 'preview-btn-toggle', function () { _fn(); } ); }, /** * Validate number: prevent negative value * @returns {undefined} */ validate_number: function () { $( 'input[type="number"]' ).on( 'keypress', function ( event ) { var min = $( this ).prop( 'min' ); if ( min == 0 && !( event.charCode >= 48 && event.charCode <= 57 ) ) event.preventDefault(); } ); } }; }( jQuery ) );