assets/js/view-admin-as.js
/* eslint-disable no-extra-semi */
;/**
* View Admin As
* https://wordpress.org/plugins/view-admin-as/
*
* @author Jory Hogeveen <info@keraweb.nl>
* @package View_Admin_As
* @since 0.1.0
* @version 1.8.5
* @preserve
*/
/* eslint-enable no-extra-semi */
if ( 'undefined' === typeof VAA_View_Admin_As ) {
/**
* Property reference to script localization from plugin.
* Only the properties from script localization are documented here.
*
* @see VAA_View_Admin_As_UI::enqueue_scripts()
*
* @property {string} ajaxurl Current site/blog ajax callback (/wp-admin/admin-ajax.php).
* @property {string} siteurl Current site/blog url.
* @property {array} settings The global settings.
* @property {array} settings_user The user settings.
* @property {array} view The current view (empty if no view is active).
* @property {array} view_types The available view types.
* @property {string} _loader_icon The loader icon URL.
* @property {string} _vaa_nonce
* @property {boolean} _debug
* @property {string} __no_users_found 'No users found.'.
* @property {string} __key_already_exists 'Key already exists.'.
* @property {string} __success 'Success'.
* @property {string} __confirm 'Are you sure?'.
* @property {string} __download 'Download'.
*/
var VAA_View_Admin_As = {};
}
( function( $ ) {
VAA_View_Admin_As.prefix = '#wpadminbar #wp-admin-bar-vaa ';
VAA_View_Admin_As.root = '#wp-admin-bar-vaa';
var $document = $( document ),
$window = $( window ),
$body = $( 'body' ),
$vaa = $( VAA_View_Admin_As.prefix ); // Validated in load().
VAA_View_Admin_As.maxHeightListenerElements = null;
VAA_View_Admin_As._mobile = false;
if ( ! VAA_View_Admin_As.hasOwnProperty( '_debug' ) ) {
VAA_View_Admin_As._debug = false;
}
if ( ! VAA_View_Admin_As.hasOwnProperty( 'ajaxurl' ) ) {
if ( 'undefined' === typeof ajaxurl ) {
// Does not work with websites in sub-folders.
var ajaxurl = window.location.origin + '/wp-admin/admin-ajax.php';
}
VAA_View_Admin_As.ajaxurl = ajaxurl;
}
// @since 1.6.1 Prevent swipe events to be seen as a click (bug in some browsers).
VAA_View_Admin_As._touchmove = false;
$document.on( 'touchmove', function() {
VAA_View_Admin_As._touchmove = true;
} );
$document.on( 'touchstart', function() {
VAA_View_Admin_As._touchmove = false;
} );
/**
* Safely try to parse as JSON. If it isn't JSON it will return the original string.
* @since 1.7.0
* @since 1.7.5 Renamed from `VAA_View_Admin_As.json_decode()`.
* @param {string} val The string to decode.
* @return {string|object} Parsed JSON object or original string.
*/
VAA_View_Admin_As.maybe_json_decode = function( val ) {
if ( 0 === val.indexOf( "{" ) || 0 === val.indexOf( "[" ) ) {
try {
val = JSON.parse( val );
} catch ( err ) {
// No JSON data.
}
}
return val;
};
/**
* Plugin initializer.
* @since 1.5.1
* @since 1.7.5 Called on window load.
* @return {void} Nothing.
*/
VAA_View_Admin_As.init = function() {
// Selector sometimes only works after window load (frontend).
if ( ! $vaa.length ) {
$vaa = $( VAA_View_Admin_As.prefix );
}
// Preload loader icon.
if ( VAA_View_Admin_As._loader_icon ) {
var loader_icon = new Image();
loader_icon.src = VAA_View_Admin_As._loader_icon;
}
// Load autoMaxHeight elements.
VAA_View_Admin_As.maxHeightListenerElements = $( VAA_View_Admin_As.prefix + '.vaa-auto-max-height' );
VAA_View_Admin_As.init_caps();
VAA_View_Admin_As.init_users();
VAA_View_Admin_As.init_combine_views();
VAA_View_Admin_As.init_module_role_defaults();
VAA_View_Admin_As.init_module_role_manager();
VAA_View_Admin_As.init_auto_js();
// Toggle content with title.
$vaa.find( '.ab-vaa-toggle' ).each( function() {
var $this = $( this ),
$toggle = $this.parent().children().not( '.ab-vaa-toggle' );
if ( ! $this.hasClass('active') ) {
$toggle.hide();
}
$this.on( 'click touchend', function( e ) {
e.preventDefault();
e.stopPropagation();
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
if ( $( this ).hasClass( 'active' ) ) {
$toggle.slideUp( 'fast' );
$( this ).removeClass( 'active' );
} else {
$toggle.slideDown( 'fast' );
$( this ).addClass( 'active' );
}
VAA_View_Admin_As.autoMaxHeight();
} );
// @since 1.6.1 Keyboard a11y.
$this.on( 'keyup', function( e ) {
e.preventDefault();
/**
* @see https://api.jquery.com/keyup/
* 13 = enter
* 32 = space
* 38 = arrow up
* 40 = arrow down
*/
var key = parseInt( e.which, 10 );
if ( $( this ).hasClass( 'active' ) && ( 13 === key || 32 === key || 38 === key ) ) {
$toggle.slideUp( 'fast' );
$( this ).removeClass( 'active' );
} else if ( 13 === key || 32 === key || 40 === key ) {
$toggle.slideDown( 'fast' );
$( this ).addClass( 'active' );
}
VAA_View_Admin_As.autoMaxHeight();
} );
} );
/**
* @since 1.6.3 Toggle items on hover.
* @since 1.7.3 Allow multiple targets + add delay option.
*/
$vaa.find( '[vaa-showhide]' ).each( function() {
var $this = $( this ),
args = VAA_View_Admin_As.maybe_json_decode( $this.attr( 'vaa-showhide' ) ),
delay = 200;
if ( 'object' !== typeof args ) {
args = { 0: { target: args, delay: delay } };
}
$.each( args, function( key, data ) {
var timeout = null,
$target = $( data.target );
// Don't validate target property. It's mandatory so let the console notify the developer.
if ( ! data.hasOwnProperty( 'delay' ) ) {
data.delay = delay;
}
$target.hide();
$this.on( 'mouseenter', function() {
timeout = setTimeout( function() {
$target.slideDown( 'fast' );
}, data.delay );
}).on( 'mouseleave', function() {
if ( timeout ) {
clearTimeout( timeout );
}
$target.slideUp( 'fast' );
} );
} );
} );
// @since 1.7.0 Conditional items.
$vaa.find( '[vaa-condition-target]' ).each( function() {
var $this = $( this ),
$target = $( $this.attr( 'vaa-condition-target' ) ),
checkbox = ( 'checkbox' === $target.attr( 'type' ) ),
compare = $this.attr( 'vaa-condition' );
if ( checkbox ) {
if ( 'undefined' !== typeof compare ) {
compare = Boolean( compare );
} else {
compare = true;
}
}
$this.hide();
$target.on( 'change.vaa', function() {
if ( checkbox && $target.is( ':checked' ) ) {
if ( compare ) {
$this.slideDown( 'fast' );
} else {
$this.slideUp( 'fast' );
}
} else if ( ! checkbox && compare === $target.val() ) {
$this.slideDown( 'fast' );
} else {
$this.slideUp( 'fast' );
}
VAA_View_Admin_As.autoMaxHeight();
} ).trigger( 'change.vaa' ); // Trigger on load.
} );
// @since 1.7.0 Init mobile fixes.
if ( $body.hasClass( 'mobile' ) || 783 > $body.innerWidth() ) {
$body.addClass( 'vaa-mobile' );
VAA_View_Admin_As._mobile = true;
VAA_View_Admin_As.init_touch();
}
// @since 1.7.1 Auto max height trigger.
VAA_View_Admin_As.maxHeightListenerElements.each( function() {
$( this ).parents( '.menupop' ).on( 'mouseenter', VAA_View_Admin_As.autoMaxHeight );
} );
// @since 1.7.4 Auto resizable.
// @since 1.8.2 Enhance height calc + provide trigger for content changes
$vaa.find( '.vaa-resizable' ).each( function() {
var $this = $( this ),
maxHeight = parseInt( $this.css( 'max-height' ), 10 ),
height, innerHeight, newHeight;
// Check for empty containers.
$this.find( '.ab-empty-item:empty' ).remove();
$this.on( 'vaa-resizable', function() {
if ( $this.is( ':empty' ) ) {
$this.css( {
'max-height': '',
'height': '',
'resize': ''
} );
return;
}
newHeight = maxHeight;
height = $this.height();
$this.css( {
'max-height': '',
'height': '',
'resize': ''
} );
if ( height ) {
$this.css( { 'max-height': 'none' } );
innerHeight = $this.height();
$this.css( { 'max-height': '' } );
if ( innerHeight < maxHeight ) {
// New content height is reduces below max height.
newHeight = innerHeight;
} else if ( height >= maxHeight ) {
// Box was resized and new content is still higher than the max height.
if ( innerHeight < height ) {
// The new content is lower than the current resized height.
newHeight = innerHeight;
} else {
// Content is above current height, keep it as is.
newHeight = height;
}
}
}
if ( newHeight && ( ! height || newHeight >= maxHeight ) ) {
$this.css( {
'max-height': 'none',
'height': ( newHeight ) ? newHeight + 'px' : '',
'resize': 'vertical'
} );
}
} ).trigger( 'vaa-resizable' ); // Trigger on load.
} );
// Process reset.
$vaa.on( 'click touchend', '.vaa-reset-item > .ab-item', function( e ) {
e.preventDefault();
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
if ( 'vaa_reload' === $( 'button', this ).attr( 'name' ) ) {
window.location.reload();
} else {
VAA_View_Admin_As.ajax( { reset : true }, true );
return false;
}
} );
// @since 1.6.2 Process basic views.
$.each( VAA_View_Admin_As.view_types, function( index, type ) {
$vaa.on( 'click touchend', '.vaa-' + type + '-item > a.ab-item', function( e ) {
e.preventDefault();
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
var $this = $( this );
// Fix for responsive views (first click triggers show child items).
if ( VAA_View_Admin_As._mobile ) {
var $parent = $this.parent();
if ( $parent.hasClass( 'menupop' ) && ! $parent.hasClass( 'active' ) ) {
$parent.addClass( 'active' );
$this.next().show();
return false;
}
}
$this.data( 'vaa-continue-event', true ).trigger( 'vaa-apply-view' );
if ( ! $this.parent().hasClass( 'not-a-view' ) && $this.data( 'vaa-continue-event' ) ) {
var view_data = {},
val = $this.find( '.vaa-view-data' ).attr( 'vaa-view-value' );
// If the value is an object (JSON) we assume it contains the view type key.
view_data[ type ] = VAA_View_Admin_As.maybe_json_decode( val );
if ( 'object' === typeof view_data[ type ] ) {
view_data = view_data[ type ];
}
VAA_View_Admin_As.ajax( view_data, true );
return false;
}
} );
} );
// @since 1.6.3 Removable items.
$vaa.on( 'click touchend', '.remove', function( e ) {
e.preventDefault();
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
$( this ).parent().slideUp( 'fast', function() { $( this ).remove(); } );
} );
};
/**
* Initialize for touch devices.
* @since 1.7.0
* @since 1.7.5 Renamed from `VAA_View_Admin_As.mobile()`.
* @return {void} Nothing.
*/
VAA_View_Admin_As.init_touch = function() {
var $root = $( '.vaa-mobile ' + VAA_View_Admin_As.prefix );
// @since 1.7 Fix for clicking within sub secondary elements. Overwrites WP core 'hover' functionality.
$root.on( 'click touchend', ' > .ab-sub-wrapper .ab-item', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
e.stopPropagation();
var $sub = $( this ).parent( '.menupop' ).children( '.ab-sub-wrapper' );
if ( $sub.length ) {
if ( $sub.hasClass( 'active' ) ) {
$sub.slideUp( 'fast' ).removeClass( 'active' );
} else {
$sub.slideDown( 'fast' ).addClass( 'active' );
}
}
} );
/**
* @since 1.7.0 Mimic default form handling because this gets overwritten by WP core.
*/
// Form elements.
$root.on( 'click touchend', 'input, textarea, select', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.stopPropagation();
var $this = $( this );
if ( $this.is( '[type="checkbox"]' ) ) {
// Checkboxes.
e.preventDefault();
if ( $this.is( ':checked' ) ) {
$this.prop( 'checked', false );
} else {
$this.prop( 'checked', true );
}
$this.trigger( 'change' );
return false;
} else if ( $this.is( '[type="radio"]' ) ) {
// Radio.
e.preventDefault();
$( 'input[name="' + $this.attr['name'] + '"]' ).removeAttr( 'checked' );
$this.prop( 'checked', true );
$this.trigger( 'change' );
return false;
}
return true;
} );
// Labels.
$root.on( 'click touchend', 'label', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
e.stopPropagation();
$( '#' + $( this ).attr( 'for' ) ).trigger( e.type );
return false;
} );
};
/**
* Add an overlay.
* @since 1.7.0
* @param {string|boolean} html The content to show in the overlay. Pass `false` to remove the overlay.
* @return {void} Nothing.
*/
VAA_View_Admin_As.overlay = function( html ) {
var $overlay = $( '#vaa-overlay' );
if ( false === html ) {
$overlay.fadeOut( 'fast', function() { $( this ).remove(); } );
$document.off( 'mouseup.vaa_overlay' );
return;
}
if ( ! $overlay.length ) {
html = '<div id="vaa-overlay">' + html + '</div>';
$body.append( html );
$overlay = $( 'body #vaa-overlay' );
} else if ( html.length ) {
$overlay.html( html );
}
$overlay.fadeIn( 'fast' );
// Remove overlay.
$overlay.find( '.remove' ).click( function() {
VAA_View_Admin_As.overlay( false );
} );
// Remove overlay on click outside of container.
$document.on( 'mouseup.vaa_overlay', function( e ) {
$overlay.find( '.vaa-popup' ).each( function() {
if ( ! $( this ).is( e.target ) && 0 === $( this ).has( e.target ).length ) {
VAA_View_Admin_As.overlay( false );
return false;
}
} );
} );
};
/**
* Apply the selected view.
*
* @param {object} data The data to send, view format: { VIEW_TYPE : VIEW_TYPE_DATA }
* @param {boolean|string} refresh Reload/redirect the page?
* @return {void} Nothing.
*/
VAA_View_Admin_As.ajax = function( data, refresh ) {
$( '.vaa-notice', '#wpadminbar' ).remove();
// @todo dashicon loader?
var loader_icon = '';
if ( VAA_View_Admin_As._loader_icon ) {
loader_icon = ' style="background-image: url(' + VAA_View_Admin_As._loader_icon + ')"';
}
VAA_View_Admin_As.overlay( '<span class="vaa-loader-icon"' + loader_icon + '></span>' );
var post_data = {
'action': 'view_admin_as',
'_vaa_nonce': VAA_View_Admin_As._vaa_nonce,
// @since 1.6.2 Use JSON data.
'view_admin_as': JSON.stringify( data )
};
var isView = false;
$.each( VAA_View_Admin_As.view_types, function( index, type ) {
if ( 'undefined' !== typeof data[ type ] ) {
isView = true;
return true;
}
} );
/**
* @since 1.5.0 Check view mode.
* @todo Improve form creation.
*/
if ( $( VAA_View_Admin_As.prefix + '#vaa-settings-view-mode-single' ).is( ':checked' ) && isView ) {
$body.append( '<form id="vaa_single_mode_form" style="display:none;" method="post"></form>' );
var $form = $( '#vaa_single_mode_form' );
$form.append( '<input type="hidden" name="action" value="' + post_data.action + '">' );
$form.append( '<input type="hidden" name="_vaa_nonce" value="' + post_data._vaa_nonce + '">' );
$form.append( '<input id="data" type="hidden" name="view_admin_as">' );
$form.find( '#data' ).val( post_data.view_admin_as );
$form.submit();
} else {
$.post(
VAA_View_Admin_As.ajaxurl,
post_data,
function( response ) {
var success = ( response.hasOwnProperty( 'success' ) && true === response.success ),
data = {},
display = false;
// Maybe show debug info in console.
VAA_View_Admin_As.debug( response );
if ( response.hasOwnProperty( 'data' ) ) {
if ( 'object' === typeof response.data ) {
data = response.data;
if ( data.hasOwnProperty( 'display' ) ) {
display = data.display;
}
if ( data.hasOwnProperty( 'refresh' ) ) {
refresh = data.refresh;
}
}
}
if ( success ) {
// @todo Enhance download handler.
if ( 'download' === refresh ) {
VAA_View_Admin_As.download( data );
VAA_View_Admin_As.overlay( false );
return;
} else if ( refresh ) {
VAA_View_Admin_As.refresh( data );
return;
} else {
if ( ! data.hasOwnProperty( 'text' ) ) {
data.text = VAA_View_Admin_As.__success;
}
}
}
if ( ! data.hasOwnProperty( 'type' ) ) {
data.type = ( success ) ? 'success' : 'error';
}
if ( 'popup' === display ) {
VAA_View_Admin_As.popup( data, data.type );
} else {
if ( ! data.hasOwnProperty( 'text' ) ) {
data.text = response.data;
}
VAA_View_Admin_As.notice( String( data.text ), data.type, 5000 );
VAA_View_Admin_As.overlay( false );
}
}
);
}
};
/**
* Reload the page or optionally redirect the user.
* @since 1.7.0
* @see VAA_View_Admin_As.ajax()
* @param {object} data Info for the redirect: { redirect: URL }
* @return {void} Nothing.
*/
VAA_View_Admin_As.refresh = function( data ) {
if ( data.hasOwnProperty( 'redirect' ) ) {
/**
* Optional redirect.
* Currently I use "replace" since no history seems necessary. Other option would be "assign" which enables history.
* @since 1.6.4
*/
window.location.replace( String( data.redirect ) );
} else {
/**
* Reload the page.
* @since 1.6.1 Fix issue with anchors.
*/
window.location.hash = '';
window.location.reload();
}
};
/**
* Show global notice.
* @since 1.0.0
* @see VAA_View_Admin_As.ajax()
* @param {string} notice The notice text.
* @param {string} type The notice type (notice, error, message, warning, success).
* @param {int} timeout Time to wait before auto-remove notice (milliseconds), pass `false` or `0` to prevent auto-removal.
* @return {void} Nothing.
*/
VAA_View_Admin_As.notice = function( notice, type, timeout ) {
var root = '#wpadminbar .vaa-notice',
html = notice + '<span class="remove ab-icon dashicons dashicons-dismiss"></span>';
type = ( 'undefined' === typeof type ) ? 'notice' : type;
timeout = ( 'undefined' === typeof timeout ) ? 5000 : timeout;
if ( VAA_View_Admin_As._mobile ) {
// Notice in VAA bar.
html = '<div class="vaa-notice vaa-' + type + '" style="display: none;">' + html + '</div>';
$( VAA_View_Admin_As.prefix + '> .ab-sub-wrapper' ).prepend( html ).children( '.vaa-notice' ).slideDown( 'fast' );
$( 'html, body' ).animate( { scrollTop: '0' } );
// Remove it after # seconds.
if ( timeout ) {
setTimeout( function () { $( root ).slideUp( 'fast', function () { $( this ).remove(); } ); }, timeout );
}
} else {
// Notice in top level admin bar.
html = '<li class="vaa-notice vaa-' + type + '">' + html + '</li>';
$( '#wp-admin-bar-top-secondary' ).append( html );
$( root + ' .remove' ).on( 'click', function() { $( this ).parent().remove(); } );
// Remove it after # seconds.
if ( timeout ) {
setTimeout( function () { $( root ).fadeOut( 'fast', function () { $( this ).remove(); } ); }, timeout );
}
}
};
/**
* Show notice for an item node.
* @since 1.7.0
* @see VAA_View_Admin_As.ajax()
* @param {string} parent The HTML element selector to add the notice to (selector or jQuery object).
* @param {string} notice The notice text.
* @param {string} type The notice type (notice, error, message, warning, success).
* @param {int} timeout Time to wait before auto-remove notice (milliseconds), pass `false` or `0` to prevent auto-removal.
* @return {void} Nothing.
*/
VAA_View_Admin_As.item_notice = function( parent, notice, type, timeout ) {
var root = '.vaa-notice',
html = notice + '<span class="remove ab-icon dashicons dashicons-dismiss"></span>',
$element = $( parent );
type = ( 'undefined' === typeof type ) ? 'notice' : type;
timeout = ( 'undefined' === typeof timeout ) ? 5000 : timeout;
html = '<div class="vaa-notice vaa-' + type + '" style="display: none;">' + html + '</div>';
$element.append( html ).children( '.vaa-notice' ).slideDown( 'fast' );
// Remove it after # seconds.
if ( timeout ) {
setTimeout( function(){ $element.find( root ).slideUp( 'fast', function() { $( this ).remove(); } ); }, timeout );
}
};
/**
* Show confirm warning.
* Returns a jQuery confirm element selector to add your own confirm actions.
* @since 1.7.0
* @param {string} parent The HTML element selector to add the notice to (selector or jQuery object).
* @param {string} text The confirm text.
* @return {object} jQuery confirm element.
*/
VAA_View_Admin_As.item_confirm = function( parent, text ) {
$( parent ).find( '.vaa-notice' ).slideUp( 'fast', function() { $( this ).remove(); } );
text = '<button class="vaa-confirm button"><span class="ab-icon dashicons dashicons-warning"></span>' + text + '</button>';
VAA_View_Admin_As.item_notice( parent, text, 'warning', 0 );
return $( parent ).find( '.vaa-confirm' );
};
/**
* Show popup with return content.
* @since 1.5.0
* @since 1.7.0 Renamed from `VAA_View_Admin_As.overlay()`.
* @see VAA_View_Admin_As.ajax()
* @param {object} data Data to use.
* @param {string} type The notice/overlay type (notice, error, message, warning, success).
* @return {void} Nothing.
*/
VAA_View_Admin_As.popup = function( data, type ) {
type = ( 'undefined' === typeof type ) ? 'notice' : type;
/*
* Build overlay HTML.
*/
var html = '';
html += '<div class="vaa-popup vaa-' + type + '">';
html += '<span class="remove dashicons dashicons-dismiss"></span>';
html += '<div class="vaa-popup-content">';
// If it's not an object assume it's a string and convert it to the proper object form.
if ( 'object' !== typeof data ) {
data = { text: data };
}
// Simple text.
if ( data.hasOwnProperty( 'text' ) ) {
html += '<p>' + String( data.text ) + '</p>';
}
// List items.
if ( data.hasOwnProperty( 'list' ) && 'object' === typeof data.list ) {
html += '<ul>';
$.each( data.list, function ( key, value ) {
html += '<li>' + String( value ) + '</li>';
} );
html += '</ul>';
}
// Textarea.
if ( data.hasOwnProperty( 'textarea' ) ) {
html += '<textarea style="width: 100%;" readonly>' + String( data.textarea ) + '</textarea>';
}
// End: .vaa-popup-content & .vaa-popup
html += '</div></div>';
// Trigger the overlay.
VAA_View_Admin_As.overlay( html );
/*
* Overlay handlers.
*/
var root = '#vaa-overlay',
$overlay = $( root ),
$popup = $overlay.find( '.vaa-popup' ),
$popup_content = $popup.find( '.vaa-popup-content' );
var textarea = $( 'textarea', $popup_content );
if ( textarea.length ) {
// Select full text on click.
textarea.on( 'click', function() { $( this ).select(); } );
}
var popupMaxHeight = function() {
if ( textarea.length ) {
textarea.each( function() {
$( this ).css( { 'height': 'auto', 'overflow-y': 'hidden' } ).height( this.scrollHeight );
});
}
// 80% of screen height - padding + border;
var max_height = ( $overlay.height() * .8 ) - 24;
$popup.css( 'max-height', max_height );
$popup_content.css( 'max-height', max_height );
};
popupMaxHeight();
$window.on( 'resize', popupMaxHeight );
};
/**
* Download text content as a file.
* @since 1.7.4
* @see VAA_View_Admin_As.ajax()
* @param {object|string} data Data to use.
* @return {void} Nothing.
*/
VAA_View_Admin_As.download = function( data ) {
var content = '',
filename = '';
if ( 'string' === typeof data ) {
content = data;
} else {
if ( data.hasOwnProperty( 'download' ) ) {
content = String( data.download );
} else if ( data.hasOwnProperty( 'textarea' ) ) {
content = String( data.textarea );
} else if ( data.hasOwnProperty( 'content' ) ) {
content = String( data.content );
}
}
// Maybe format JSON data.
content = VAA_View_Admin_As.maybe_json_decode( content );
if ( 'object' === typeof content ) {
content = JSON.stringify( content, null, '\t' );
}
if ( ! content ) {
return; //@todo Notice.
}
if ( data.hasOwnProperty( 'filename' ) ) {
filename = data.filename;
}
// https://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server
var link = 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent( content );
$body.append( '<a id="vaa_temp_download" href="' + link + '" download="' + String( filename ) + '"></a>' );
document.getElementById( 'vaa_temp_download' ).click();
$( 'a#vaa_temp_download' ).remove();
};
/**
* Automatic option handling.
* @since 1.7.2
* @return {void} Nothing.
*/
VAA_View_Admin_As.init_auto_js = function() {
$( VAA_View_Admin_As.root + ' [vaa-auto-js]' ).each( function() {
var $this = $( this ),
data = VAA_View_Admin_As.maybe_json_decode( $this.attr( 'vaa-auto-js' ) );
if ( 'object' !== typeof data ) {
return;
}
if ( ! data.hasOwnProperty( 'event' ) ) {
data.event = 'change';
}
if ( 'click' === data.event ) {
data.event = 'click touchend';
}
$this.on( data.event, function( e ) {
if ( 'change' !== data.event && true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
VAA_View_Admin_As.do_auto_js( data, this );
return false;
} );
} );
/**
* Get the values of the option data.
* @since 1.7.2
* @param {object} data {
* The option data.
* @type {string} setting The setting key.
* @type {boolean} confirm Confirm before sending ajax?
* @type {boolean} refresh Refresh after sending ajax?
* @type {object} values {
* A object of multiple values as option_key => data (see below parameters).
* Can also contain another values parameter to build the option data recursive.
* @type {boolean} required Whether this option is required or not (default: true).
* @type {mixed} element The option element (overwrites the second elem parameter).
* @type {string} parser The value parser.
* @type {string} attr Get an attribute value instead of using .val()?
* OR
* @type {object} values An object of multiple values as option_key => data (see above parameters).
* }
* }
* @param {mixed} elem The element (runs through $() function).
* @return {void} Nothing.
*/
VAA_View_Admin_As.do_auto_js = function( data, elem ) {
if ( 'object' !== typeof data ) {
return;
}
var $elem = $( elem ),
setting = ( data.hasOwnProperty( 'setting' ) ) ? String( data.setting ) : null,
confirm = ( data.hasOwnProperty( 'confirm' ) ) ? Boolean( data.confirm ) : false,
refresh = ( data.hasOwnProperty( 'refresh' ) ) ? Boolean( data.refresh ) : false;
// Callback overwrite.
if ( data.hasOwnProperty( 'callback' ) ) {
VAA_View_Admin_As[ data.callback ]( data );
return;
}
var val = VAA_View_Admin_As.get_auto_js_values_recursive( data, elem );
if ( null !== val ) {
if ( ! setting ) {
return;
}
var view_data = {};
view_data[ setting ] = val;
// @todo Enhance download handler.
if ( data.hasOwnProperty( 'download' ) && data.download ) {
refresh = 'download';
}
if ( confirm ) {
confirm = VAA_View_Admin_As.item_confirm( $elem.parent(), VAA_View_Admin_As.__confirm );
$( confirm ).on( 'click', function() {
VAA_View_Admin_As.ajax( view_data, refresh );
} );
} else {
VAA_View_Admin_As.ajax( view_data, refresh );
}
} else {
// @todo Notifications etc.
}
};
/**
* Get the values of the option data.
* @since 1.7.2
* @param {object} data {
* The option data.
* @type {boolean} required Whether this option is required or not (default: true).
* @type {mixed} element The option element (overwrites the second elem parameter).
* @type {string} parser The value parser.
* @type {string} attr Get an attribute value instead of using .val()?
* OR
* @type {object} values An object of multiple values as option_key => data (see above parameters).
* }
* @param {mixed} elem The element (runs through $() function).
* @return {object} Value data.
*/
VAA_View_Admin_As.get_auto_js_values_recursive = function( data, elem ) {
if ( 'object' !== typeof data ) {
return null;
}
var stop = false,
val = null;
if ( data.hasOwnProperty( 'values' ) ) {
val = {};
$.each( data.values, function( val_key, auto_js ) {
if ( 'object' !== typeof auto_js || null === auto_js ) {
auto_js = {};
}
auto_js.required = ( auto_js.hasOwnProperty( 'required' ) ) ? Boolean( auto_js.required ) : true;
var val_val = VAA_View_Admin_As.get_auto_js_values_recursive( auto_js, elem );
if ( null !== val_val ) {
val[ val_key ] = val_val;
} else if ( auto_js.required ) {
val = null;
stop = true;
return false;
}
} );
if ( stop ) {
return null;
}
} else {
val = VAA_View_Admin_As.parse_auto_js_value( data, elem );
}
return val;
};
/**
* Get the value of an option through various parsers.
* @since 1.7.2
* @param {object} data {
* The option data.
* @type {mixed} element The option element (overwrites the second elem parameter).
* @type {string} parser The value parser.
* @type {string} attr Get an attribute value instead of using .val()?
* @type {boolean} attr Parse as JSON?
* }
* @param {mixed} elem The element (runs through $() function).
* @return {*} Value.
*/
VAA_View_Admin_As.parse_auto_js_value = function( data, elem ) {
if ( 'object' !== typeof data ) {
return null;
}
var $elem = ( data.hasOwnProperty( 'element' ) ) ? $( data.element ) : $( elem ),
parser = ( data.hasOwnProperty( 'parser' ) ) ? String( data.parser ) : '',
val = null;
switch ( parser ) {
case 'multiple':
case 'multi':
val = {};
$elem.each( function() {
var $this = $( this ),
value;
if ( 'checkbox' === $this.attr( 'type' ) ) {
// JSON not supported and always a boolean value.
value = ( data.hasOwnProperty( 'attr' ) ) ? $this.attr( data.attr ) : $this.val();
val[ value ] = this.checked;
} else {
value = VAA_View_Admin_As.get_auto_js_value( this, data );
val[ $this.attr( 'name' ) ] = value;
}
} );
break;
case 'selected':
val = [];
$elem.each( function() {
var $this = $( this ),
value;
if ( 'checkbox' === $this.attr( 'type' ) ) {
// JSON not supported.
value = ( data.hasOwnProperty( 'attr' ) ) ? $this.attr( data.attr ) : $this.val();
if ( this.checked && value ) {
val.push( value );
}
} else {
value = VAA_View_Admin_As.get_auto_js_value( this, data );
if ( value ) {
val.push( value );
}
}
} );
break;
default:
val = VAA_View_Admin_As.get_auto_js_value( $elem, data );
break;
}
return val;
};
/**
* Get the value of an option through various parsers.
* @since 1.7.2
* @param {mixed} elem Required. The element (runs through $() function).
* @param {object} data {
* The option data.
* @type {string} attr Optional. Get an attribute value instead of using .val()?
* @type {boolean} json Optional. Parse as JSON?
* }
* @return {*} Value.
*/
VAA_View_Admin_As.get_auto_js_value = function( elem, data ) {
if ( 'object' !== typeof data ) {
data = {};
}
var $elem = $( elem ),
val = null,
attr = ( data.hasOwnProperty( 'attr' ) ) ? String( data.attr ) : false,
json = ( data.hasOwnProperty( 'json' ) ) ? Boolean( data.json ) : false,
value = ( attr ) ? $elem.attr( attr ) : $elem.val();
if ( 'checkbox' === $elem.attr( 'type' ) ) {
var checked = $elem.is( ':checked' );
if ( attr ) {
if ( checked && value ) {
val = value;
}
} else {
val = checked;
}
} else {
if ( value ) {
val = value;
}
}
if ( json ) {
try {
val = JSON.parse( val );
} catch ( err ) {
val = null;
// @todo Improve error message.
VAA_View_Admin_As.popup( '<pre>' + err + '</pre>', 'error' );
}
}
return val;
};
};
/**
* USERS.
* Extra functions for user views.
* @since 1.2.0
* @return {void} Nothing.
**/
VAA_View_Admin_As.init_users = function() {
var root = VAA_View_Admin_As.root + '-users',
root_prefix = VAA_View_Admin_As.prefix + root,
$root = $( root_prefix ),
$search_node = $( root_prefix + ' .ab-vaa-search.search-users' ),
ajax_delay_timer;
if ( $search_node.length ) {
var search_ajax = $search_node.hasClass( 'search-ajax' ),
$search_results = $search_node.find( '.ab-vaa-results' ),
no_results = '<div class="ab-item ab-empty-item vaa-not-found">' + VAA_View_Admin_As.__no_users_found + '</div>';
// Search users.
$root.on( 'keyup', '.ab-vaa-search.search-users input', function() {
var $this = $( this ),
search = $this.val();
if ( 1 <= search.trim().length ) {
if ( search_ajax ) {
search = {
'search': search,
'return': 'links'
};
var search_by = $root.find( '.ab-vaa-search.search-users select' ).val();
if ( search_by ) {
search[ 'search_by' ] = search_by;
}
VAA_View_Admin_As.search_users_ajax( search, $search_results );
} else {
search_users( search );
}
} else {
VAA_View_Admin_As.search_users_ajax( null, $search_results );
}
} );
}
/**
* Search users from the DOM.
*
* @since 1.2.0
* @since 1.8.0 As a function.
* @param {string} search The search value.
* @return {void} Nothing.
*/
function search_users( search ) {
$search_results.empty();
$( VAA_View_Admin_As.prefix + '.vaa-user-item' ).each( function() {
var $this = $( this ),
name = $this.find( '.ab-item' ).text();
if ( -1 < name.toLowerCase().indexOf( search.toLowerCase() ) ) {
var exists = false;
$search_results.find( '.vaa-user-item .ab-item' ).each(function() {
if ( -1 < $( this ).text().indexOf( name ) ) {
exists = $( this );
}
} );
var role = $this.parents( '.vaa-role-item' ).find( '> .ab-item > .vaa-view-data' );
role = ( role ) ? role.text() : '';
if ( role && false !== exists && exists.length ) {
exists.find( '.user-role' ).text( exists.find( '.user-role' ).text().replace( ')', ', ' + role + ')' ) );
} else {
role = ( role ) ? ' <span class="user-role ab-italic">(' + role + ')</span>' : '';
$this.clone()
.appendTo( $search_results )
.children( '.ab-item' )
.append( role );
}
}
} );
if ( '' === $.trim( $search_results.html() ) ) {
$search_results.html( no_results );
}
VAA_View_Admin_As.autoMaxHeight();
}
/**
* Search users with AJAX.
*
* @since 1.8.0
* @since 1.8.2 Refactored for general use.
* @param {object} search The search parameters. Pass empty value to reset results container.
* @param {object|function} results_container The results container element. Can also be a callback.
* @return {void} Nothing.
*/
VAA_View_Admin_As.search_users_ajax = function( search, results_container ) {
clearTimeout( ajax_delay_timer );
var $results_container = $( results_container );
// Reset.
if ( ! search ) {
$results_container.empty();
if ( $results_container.hasClass( 'vaa-resizable' ) ) {
$results_container.trigger( 'vaa-resizable' );
}
return;
}
ajax_delay_timer = setTimeout( function() {
$results_container.html( '<div class="ab-item ab-empty-item">. . . </div>' );
var $loading = $( '.ab-item', $results_container ),
loading = '. . . ',
loading_interval = setInterval( function() {
if ( 20 < loading.length ) {
loading = '. . . ';
}
loading += '. ';
$loading.html( loading );
}, 500 );
var post_data = {
'action': 'view_admin_as_search_users',
'_vaa_nonce': VAA_View_Admin_As._vaa_nonce,
'view_admin_as_search_users': search
};
$.post( VAA_View_Admin_As.ajaxurl, post_data, function( response ) {
clearInterval( loading_interval );
clearTimeout( ajax_delay_timer );
// Run optional callback.
if ( 'function' === typeof results_container ) {
results_container( response );
return;
}
if ( response.hasOwnProperty( 'success' ) && response.success ) {
$results_container.html( response.data );
VAA_View_Admin_As.reinit_combine_views();
} else {
$results_container.html( no_results );
if ( response.hasOwnProperty( 'data' ) && 'string' === typeof response.data ) {
$results_container.children().first().html( response.data );
}
}
if ( $results_container.hasClass( 'vaa-resizable' ) ) {
$results_container.trigger( 'vaa-resizable' );
}
if ( $results_container.hasClass( 'vaa-auto-max-height' ) ) {
VAA_View_Admin_As.autoMaxHeight();
}
} );
}, 500 );
}
};
/**
* CAPABILITIES.
* @since 1.3.0
* @return {void} Nothing.
**/
VAA_View_Admin_As.init_caps = function() {
var root = VAA_View_Admin_As.root + '-caps',
root_prefix = VAA_View_Admin_As.prefix + root,
$root = $( root_prefix );
VAA_View_Admin_As.caps_filter_settings = {
selectedRole : 'default',
selectedRoleCaps : {},
selectedRoleReverse : false,
filterString : ''
};
// Filter capability handler.
VAA_View_Admin_As.filter_capabilities = function() {
var reverse = ( true === VAA_View_Admin_As.caps_filter_settings.selectedRoleReverse ),
isDefault = ( 'default' === VAA_View_Admin_As.caps_filter_settings.selectedRole ),
filterString = VAA_View_Admin_As.caps_filter_settings.filterString;
$( root_prefix + '-select-options .vaa-cap-item' ).each( function() {
var $this = $( this ),
exists = ( $( 'input', this ).attr( 'value' ) in VAA_View_Admin_As.caps_filter_settings.selectedRoleCaps ),
name;
$this.hide();
if ( reverse || exists || isDefault ) {
if ( 1 <= filterString.length ) {
name = $this.text(); // $( '.ab-item', this ).text();
if ( -1 < name.toLowerCase().indexOf( filterString.toLowerCase() ) ) {
$this.show();
}
} else {
$this.show();
}
if ( reverse && exists && ! isDefault ) {
$this.hide();
}
}
} );
};
// Since 1.7.0 Get the selected capabilities.
VAA_View_Admin_As.get_selected_capabilities = function() {
var capabilities = {};
$( root_prefix + '-select-options .vaa-cap-item input' ).each( function() {
var val = $( this ).attr( 'value' );
if ( 'undefined' === typeof capabilities[ val ] ) {
capabilities[ val ] = $( this ).is( ':checked' );
}
} );
return capabilities;
};
/**
* Set the selected capabilities.
* @since 1.7.0
* @param {object} capabilities The capabilities.
* @return {void} Nothing.
*/
VAA_View_Admin_As.set_selected_capabilities = function( capabilities ) {
$( root_prefix + '-select-options .vaa-cap-item input' ).each( function() {
var $this = $( this ),
val = $this.attr( 'value' );
if ( capabilities.hasOwnProperty( val ) ) {
if ( capabilities[ val ] ) {
$this.prop( 'checked', true );
} else {
$this.prop( 'checked', false );
}
} else {
$this.prop( 'checked', false );
}
} );
};
// Enlarge caps.
$root.on( 'click', '#open-caps-popup', function() {
$( VAA_View_Admin_As.prefix ).addClass( 'fullPopupActive' );
$( this ).closest( '.ab-sub-wrapper' ).addClass( 'fullPopup' );
VAA_View_Admin_As.autoMaxHeight();
} );
// Undo enlarge caps.
$root.on( 'click', '#close-caps-popup', function() {
$( VAA_View_Admin_As.prefix ).removeClass( 'fullPopupActive' );
$( this ).closest( '.ab-sub-wrapper' ).removeClass( 'fullPopup' );
VAA_View_Admin_As.autoMaxHeight();
} );
// Select role capabilities.
$root.on( 'change', '.ab-vaa-select.select-role-caps select', function() {
VAA_View_Admin_As.caps_filter_settings.selectedRole = $( this ).val();
if ( 'default' === VAA_View_Admin_As.caps_filter_settings.selectedRole ) {
VAA_View_Admin_As.caps_filter_settings.selectedRoleCaps = {};
VAA_View_Admin_As.caps_filter_settings.selectedRoleReverse = false;
} else {
var selectedRoleElement = $( root_prefix + '-selectrolecaps #vaa-caps-selectrolecaps option[value="' + VAA_View_Admin_As.caps_filter_settings.selectedRole + '"]' );
VAA_View_Admin_As.caps_filter_settings.selectedRoleCaps = JSON.parse( selectedRoleElement.attr( 'data-caps' ) );
VAA_View_Admin_As.caps_filter_settings.selectedRoleReverse = ( 1 === parseInt( selectedRoleElement.attr( 'data-reverse' ), 10 ) );
}
VAA_View_Admin_As.filter_capabilities();
} );
// Filter capabilities with text input.
$root.on( 'keyup', '.ab-vaa-filter input', function() {
VAA_View_Admin_As.caps_filter_settings.filterString = $( this ).val();
VAA_View_Admin_As.filter_capabilities();
} );
// Select all capabilities.
$root.on( 'click touchend', 'button#select-all-caps', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
$( root_prefix + '-select-options .vaa-cap-item' ).each( function() {
if ( $( this ).is( ':visible' ) ) {
$( 'input', this ).prop( "checked", true );
}
} );
return false;
} );
// Deselect all capabilities.
$root.on( 'click touchend', 'button#deselect-all-caps', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
$( root_prefix + '-select-options .vaa-cap-item' ).each( function() {
if ( $( this ).is( ':visible' ) ) {
$( 'input', this ).prop( "checked", false );
}
} );
return false;
} );
// Process view: capabilities.
$root.on( 'click touchend', 'button#apply-caps-view', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
var new_caps = VAA_View_Admin_As.get_selected_capabilities();
VAA_View_Admin_As.ajax( { caps : new_caps }, true );
return false;
} );
};
/**
* Combine views tool.
* @since 1.8.0
* @return {void} Nothing.
*/
VAA_View_Admin_As.init_combine_views = function() {
var root = VAA_View_Admin_As.root + '-combine-views',
prefix = 'vaa-combine-views',
root_prefix = VAA_View_Admin_As.prefix + root,
$root = $( root_prefix ),
is_active = false,
combine_types = $.extend( [], VAA_View_Admin_As.view_types ),
combine_selectors = [],
selection = {},
$selection_container = root_prefix + ' #' + prefix + '-selection',
$combine_items;
if ( ! $root.length ) {
return;
}
combine_types.splice( combine_types.indexOf( 'caps' ), 1 );
combine_types.splice( combine_types.indexOf( 'visitor' ), 1 );
for ( var key in combine_types ) {
if ( combine_types.hasOwnProperty( key ) ) {
combine_selectors[ combine_types[ key ] ] = VAA_View_Admin_As.prefix + '.vaa-' + combine_types[ key ] + '-item > .ab-item';
}
}
// Custom selector for capability view.
combine_types.push( 'caps' );
combine_selectors['caps'] = VAA_View_Admin_As.prefix + VAA_View_Admin_As.root + '-caps > .menupop > .ab-item';
// Re-init. Checks for new view type nodes.
VAA_View_Admin_As.reinit_combine_views = function() {
if ( is_active ) {
enable_combine_views();
} else {
add_combine_checkboxes();
}
$.each( selection, function ( type, data ) {
data.el = $( data.el );
if ( ! data.el.length || ! data.el.closest( 'body' ).length ) {
// Try to find the element.
data.el = $( VAA_View_Admin_As.prefix + '.vaa-combine-item[vaa-view-type=' + data.type + '][vaa-view-value=' + data.value + ']' );
}
if ( data.el.length ) {
data.el.prop( 'checked', true );
activate_combine_type( data.el, data.type, data.value );
}
} );
};
// Show checkboxes.
function enable_combine_views() {
is_active = true;
add_combine_checkboxes();
$combine_items = $( VAA_View_Admin_As.prefix + '.vaa-combine-item' );
$combine_items.fadeIn( 'fast' );
update_selection_list();
}
// Hide checkboxes and results container.
function disable_combine_views() {
is_active = false;
$( VAA_View_Admin_As.prefix + '.vaa-combine-item' ).fadeOut( 'fast' );
if ( $selection_container.is( ':visible' ) ) {
$selection_container.slideUp( 'fast' );
} else {
$selection_container.hide();
}
}
/**
* Generate the checkboxes for combine types.
* @param {string} elements The elements selector to search for.
* @param {string} type The view type.
* @return {void} Nothing.
*/
function add_combine_checkboxes( elements, type ) {
if ( ! elements || ! type ) {
for ( var key in combine_selectors ) {
if ( combine_selectors.hasOwnProperty( key ) ) {
add_combine_checkboxes( combine_selectors[ key ], key );
}
}
return;
}
// Late selection init needed for frontend.
var $elements = $( elements );
$elements.each( function () {
var $this = $( this ),
$parent = $this.parent(),
val = null,
text = $this.text(),
$data_el = $this.find( '.vaa-view-data' ),
label,
attr;
if ( $parent.find( '.vaa-combine-item' ).length ) {
// Already exists.
return true;
}
if ( $data_el.length ) {
val = $data_el.attr( 'vaa-view-value' );
text = $data_el.text();
label = $data_el.attr( 'vaa-view-type-label' );
}
if ( 'caps' === type ) {
val = '';
text = $( VAA_View_Admin_As.root + '-caps-title > .ab-item' ).text();
}
attr = [
'type="checkbox"',
'class="checkbox vaa-right vaa-combine-item vaa-combine-' + type + '"',
'vaa-view-type="' + type + '"',
"vaa-view-value='" + val + "'", // Switch quote types for JSON data.
'vaa-view-text="' + text + '"',
'style="display:none;"'
];
if ( label ) {
attr.push( 'vaa-view-type-label="' + label + '"' );
}
$parent.prepend( '<input ' + attr.join( ' ' ) + '>' );
} );
}
/**
* Parse new combine selection. Also checks for multiple views.
* @param {string} element The element selector.
* @param {string} type The view type.
* @return {void} Nothing.
*/
function parse_combine_type( element, type ) {
var $element = $( element ),
val;
if ( 'caps' === type ) {
val = type;
} else {
val = VAA_View_Admin_As.maybe_json_decode( $element.attr( 'vaa-view-value' ) );
// Check if it contains a combination of view types parsed as a JSON object.
if ( 'object' === typeof val ) {
$.each( val, function( val_type, data ) {
var $val_element = $( VAA_View_Admin_As.prefix + '.vaa-combine-' + val_type + '[vaa-view-value=' + data + ']' );
activate_combine_type( $val_element, val_type, data );
} );
// Also check the current item since this way the user can deactivate the combination as a whole.
$element.prop( { checked: true, disabled: false } );
return;
}
}
activate_combine_type( $element, type, val );
}
/**
* Activate/select a combine type.
* @param {string} element The element selector.
* @param {string} type The view type.
* @param {string} value The view value.
* @return {void} Nothing.
*/
function activate_combine_type( element, type, value ) {
var $element = $( element );
deactivate_combine_type( type, false );
selection[ type ] = {
'el': $element,
'type': type,
'value': value
};
$( VAA_View_Admin_As.prefix + '.vaa-combine-' + type ).prop( { checked: false, disabled: true } );
$element.prop( { checked: true, disabled: false } );
update_selection_list();
}
/**
* Deactivate/deselect a combine type.
* @param {string|object} types The view types.
* @param {boolean} update Update selection list?
* @return {void} Nothing.
*/
function deactivate_combine_type( types, update ) {
if ( 'object' !== typeof types ) {
type = types;
types = {};
types[ type ] = 0;
}
for ( var type in types ) {
if ( types.hasOwnProperty( type ) ) {
delete selection[ type ];
$( VAA_View_Admin_As.prefix + '.vaa-combine-' + type ).prop( { checked: false, disabled: false } );
}
}
if ( update ) {
update_selection_list();
}
}
// Update the list with current selections.
function update_selection_list() {
// Remove view types that are deselected.
$( root_prefix + ' .vaa-combine-selection' ).each( function() {
var $this = $( this ),
type = $this.attr( 'vaa-view-type' );
if ( ! selection.hasOwnProperty( type ) ) {
$this.slideUp( 'fast', function() { $( this ).remove() } );
}
} );
// Append or update view types selection.
$.each( selection, function( type, data ) {
var text = data.el.attr( 'vaa-view-text' ) + '<span class="remove ab-icon dashicons dashicons-dismiss"></span>',
$existing = $( root_prefix + ' .vaa-combine-selection-' + type ),
label = data.el.attr( 'vaa-view-type-label' );
if ( label ) {
text = '<span class="ab-bold">' + label + ':</span> ' + text;
}
if ( $existing.length ) {
$existing.html( text );
if ( 'none' === $existing.css( 'display' ) || ! $existing.is( ':visible' ) ) {
$existing.slideDown( 'fast' );
}
} else {
var attr = [
'class="ab-item ab-empty-item vaa-combine-selection vaa-combine-selection-' + type + '"',
'vaa-view-type="' + type + '"',
'style="display:none;"'
];
var html = '<li ' + attr.join( ' ' ) + '>' + text + '</li>';
$selection_container.append( html );
$( root_prefix + ' .vaa-combine-selection-' + type ).slideDown( 'fast' );
}
} );
if ( is_active && ! $.isEmptyObject( selection ) ) {
if ( 'none' === $selection_container.css( 'display' ) || ! $selection_container.is( ':visible' ) ) {
$selection_container.slideDown( 'fast' );
}
} else {
$selection_container.slideUp( 'fast' );
}
}
// Enable view combinations.
$root.on( 'change', 'input#' + prefix, function() {
// Late selection init needed for frontend.
$selection_container = $( $selection_container );
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
if ( this.checked ) {
enable_combine_views();
} else {
disable_combine_views();
}
} );
// Toggle view type combination.
$vaa.on( 'change', 'input.vaa-combine-item', function() {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
var $this = $( this ),
type = $this.attr('vaa-view-type');
if ( this.checked ) {
parse_combine_type( $this, type );
} else {
var val = VAA_View_Admin_As.maybe_json_decode( $this.attr( 'vaa-view-value' ) );
// Check if it contains a combination of view types parsed as a JSON object.
if ( 'object' === typeof val ) {
deactivate_combine_type( val, true );
return;
}
deactivate_combine_type( type, true );
}
} );
// Remove view type from combinations.
$root.on( 'click touchend', '.vaa-combine-selection .remove', function() {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
deactivate_combine_type( $( this ).parent().attr( 'vaa-view-type' ), true );
} );
// Apply view combination.
$root.on( 'click touchend', 'button#' + prefix + '-apply', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
var view_data = {};
for ( var type in selection ) {
if ( selection.hasOwnProperty( type ) ) {
if ( 'caps' === type ) {
view_data[ type ] = VAA_View_Admin_As.get_selected_capabilities();
} else {
view_data[ type ] = selection[ type ].value;
}
}
}
if ( ! $.isEmptyObject( view_data ) ) {
VAA_View_Admin_As.ajax( view_data, true );
} else {
// @todo Notice text.
}
} );
// Prevent default view item handling and trigger checkbox click.
$.each( combine_types, function( index, type ) {
$vaa.on( 'vaa-apply-view', '.vaa-' + type + '-item > a.ab-item', function( e ) {
if ( ! is_active ) {
return;
}
e.preventDefault();
var $this = $( this );
if ( ! $this.parent().hasClass( 'not-a-view' ) ) {
if ( ! VAA_View_Admin_As._mobile ) {
var $combine_item = $this.parent().children( '.vaa-combine-item' );
if ( $combine_item.is( ':checked' ) ) {
$combine_item.prop( 'checked', false );
} else {
$combine_item.prop( 'checked', true );
}
$combine_item.trigger( 'change' );
}
// Prevent default view item handling.
e.stopPropagation();
e.stopImmediatePropagation();
$this.data( 'vaa-continue-event', false );
return false;
}
} );
} );
};
/**
* MODULE: Role Defaults.
* @since 1.4.0
* @return {void} Nothing.
*/
VAA_View_Admin_As.init_module_role_defaults = function() {
var root = VAA_View_Admin_As.root + '-role-defaults',
prefix = 'vaa-role-defaults',
root_prefix = VAA_View_Admin_As.prefix + root,
$root = $( root_prefix );
if ( ! $root.length ) {
return;
}
// @since 1.6.3 Add new meta.
$root.on( 'click touchend', root + '-meta-add button#' + prefix + '-meta-add', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
var val = $( root_prefix + '-meta-add input#' + prefix + '-meta-new' ).val(),
item = $( root_prefix + '-meta-add #' + prefix + '-meta-template' ).html().toString();
val = val.replace( / /g, '_' );
item = item.replace( /vaa_new_item/g, val );
if ( $( root_prefix + '-meta-select input[value="' + val + '"]' ).length ) {
VAA_View_Admin_As.item_notice( $( this ).parent(), VAA_View_Admin_As.__key_already_exists, 'error', 2000 );
} else {
$( root_prefix + '-meta-select > .ab-item' ).prepend( item );
}
} );
// @since 1.4.0 Filter users.
if ( $root.find( root + '-bulk-users-filter' ).length ) {
$root.on( 'keyup', root + '-bulk-users-filter input#' + prefix + '-bulk-users-filter', function( e ) {
e.preventDefault();
var $this = $( this ),
$items = $( root_prefix + '-bulk-users-select .ab-item.vaa-item' );
if ( 1 <= $this.val().length ) {
var input_text = $this.val();
$items.each( function() {
var $this = $( this ),
name = $this.find( '.user-name' ).text();
if ( -1 < name.toLowerCase().indexOf( input_text.toLowerCase() ) ) {
$this.show();
} else {
$this.hide();
}
} );
} else {
$items.each( function() {
$( this ).show();
} );
}
} );
}
// @since 1.8.2 AJAX search users.
var $search = $root.find( root + '-bulk-users-search' );
if ( $search.length ) {
var $search_results = $root.find( root + '-bulk-users-select' );
$search.on( 'keyup', 'input#' + prefix + '-bulk-users-search', function() {
var $this = $( this ),
search = $this.val();
if ( 1 <= search.trim().length ) {
search = {
'search': search,
'return': 'role_defaults'
};
var search_by = $search.find( 'select#' + prefix + '-bulk-users-search-by' ).val();
if ( search_by ) {
search[ 'search_by' ] = search_by;
}
VAA_View_Admin_As.search_users_ajax( search, $search_results );
} else {
VAA_View_Admin_As.search_users_ajax( null, $search_results );
}
} );
}
};
/**
* MODULE: Role Manager.
* @since 1.7.0
* @return {void} Nothing.
*/
VAA_View_Admin_As.init_module_role_manager = function() {
/**
* Capability functions.
*/
var root = VAA_View_Admin_As.root + '-caps-manager-role-manager',
prefix = 'vaa-caps-manager-role-manager',
root_prefix = VAA_View_Admin_As.prefix + root,
$root = $( root_prefix );
if ( ! $root.length ) {
return;
}
// @since 1.7.0 Update capabilities when selecting a role.
$root.on( 'change', 'select#' + prefix + '-edit-role', function() {
var $this = $( this ),
role = $this.val(),
caps = {},
$selected_role = $( root_prefix + ' select#' + prefix + '-edit-role option[value="' + role + '"]' );
if ( $selected_role.attr( 'data-caps' ) ) {
caps = JSON.parse( $selected_role.attr( 'data-caps' ) );
}
// Reset role filters.
VAA_View_Admin_As.caps_filter_settings.selectedRole = 'default';
VAA_View_Admin_As.caps_filter_settings.selectedRoleCaps = {};
VAA_View_Admin_As.caps_filter_settings.selectedRoleReverse = false;
VAA_View_Admin_As.filter_capabilities();
VAA_View_Admin_As.set_selected_capabilities( caps );
} );
// @since 1.7.0 Add/Modify roles.
$root.on( 'click touchend', 'button#' + prefix + '-save-role', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
var role = $( root_prefix + ' select#' + prefix + '-edit-role' ).val(),
refresh = false;
if ( ! role ) {
return false;
}
// @todo Enhance refresh check.
if ( '__new__' === role ) {
role = $( root_prefix + ' input#' + prefix + '-new-role' ).val();
refresh = true;
} else if ( VAA_View_Admin_As.view.hasOwnProperty( 'role' ) && role === VAA_View_Admin_As.view.role ) {
// This role is the current view.
refresh = true;
} else if ( -1 < $.inArray( role, $vaa.find( '> .ab-item .user-role' ).data( 'role' ) ) ) {
// @since 1.8.4 Current view (probably user) has this role.
refresh = true;
}
var data = {
role: role,
capabilities: VAA_View_Admin_As.get_selected_capabilities()
};
VAA_View_Admin_As.ajax( { role_manager : { save_role : data } }, refresh );
return false;
} );
// @since 1.7.0 Add new capabilities.
$root.on( 'click touchend', root + '-new-cap button#' + prefix + '-add-cap', function( e ) {
if ( true === VAA_View_Admin_As._touchmove ) {
return;
}
e.preventDefault();
var existing = VAA_View_Admin_As.get_selected_capabilities(),
val = $( root_prefix + '-new-cap input#' + prefix + '-new-cap' ).val(),
item = $( root_prefix + '-new-cap #' + prefix + '-cap-template' ).html().toString();
val = val.replace( / /g, '_' );
item = item.replace( /vaa_new_item/g, val );
if ( 'undefined' !== typeof existing[ val ] ) {
VAA_View_Admin_As.item_notice( $( this ).parent(), VAA_View_Admin_As.__key_already_exists, 'error', 2000 );
} else {
$( VAA_View_Admin_As.root + '-caps-select-options > .ab-item' ).prepend( item );
}
} );
};
/**
* Read file content and place it in a target value.
* https://developer.mozilla.org/en-US/docs/Web/API/FileReader
* http://www.javascripture.com/FileReader
*
* @todo Is this the correct method name?
*
* @since 1.7.4
* @param {object} data The auto_js data.
* @return {void} Nothing.
*/
VAA_View_Admin_As.assign_file_content = function( data ) {
if ( 'function' !== typeof FileReader ) {
// @todo Remove file element on load if the browser doesn't support FileReader.
return;
}
var param = ( data.hasOwnProperty( 'param' ) ) ? data.param : {},
$target = ( param.hasOwnProperty( 'target' ) ) ? $( param.target ) : null,
$element = ( param.hasOwnProperty( 'element' ) ) ? $( param.element ) : null,
wait = true;
if ( ! $target || ! $element ) {
return;
}
var files = $element[0].files,
length = files.length,
val = '';
if ( length ) {
$.each( files, function( key, file ) {
var reader = new FileReader();
reader.onload = function() { //progressEvent
var content = VAA_View_Admin_As.maybe_json_decode( this.result );
if ( 'object' === typeof content ) {
// Remove JSON format.
content = JSON.stringify( content );
}
val += content;
length--;
if ( ! length ) {
wait = false;
}
};
reader.readAsText( file );
} );
}
var areWeThereYet = setInterval( function() {
if ( ! wait ) {
$target.val( val );
clearInterval( areWeThereYet );
}
}, 100 );
};
/**
* Auto resize max height elements.
* @since 1.7.0
* @return {null} Nothing.
*/
VAA_View_Admin_As.autoMaxHeight = function() {
if ( ! VAA_View_Admin_As.maxHeightListenerElements ) {
return null;
}
var timeout = 100;
setTimeout( function() {
// @link http://stackoverflow.com/questions/11193453/find-the-vertical-position-of-scrollbar-without-jquery
var scroll_top = ( 'undefined' !== typeof window.pageYOffset ) ? window.pageYOffset : ( document.documentElement || document.body.parentNode || document.body ).scrollTop;
VAA_View_Admin_As.maxHeightListenerElements.each( function() {
var $element = $( this ),
count = 0,
wait = setInterval( function() {
var offset = $element.offset(),
offset_top = ( offset.top - scroll_top );
if ( $element.is( ':visible' ) && 0 < offset_top ) {
clearInterval( wait );
var max_height = $window.height() - offset_top - 100;
max_height = ( 100 < max_height ) ? max_height : 100;
$element.css( { 'max-height': max_height + 'px' } );
}
count++;
if ( 5 < count ) {
clearInterval( wait );
}
}, timeout );
} );
}, timeout );
};
$window.on( 'resize', VAA_View_Admin_As.autoMaxHeight );
/**
* Maybe show a debug message.
* @since 1.7.4
* @param {mixed} message The data to debug.
* @return {null} Nothing.
*/
VAA_View_Admin_As.debug = function( message ) {
if ( true === VAA_View_Admin_As._debug ) {
// Show debug info in console.
console.log( message );
}
};
// We require a nonce to use this plugin.
if ( VAA_View_Admin_As.hasOwnProperty( '_vaa_nonce' ) ) {
$window.on( 'load', VAA_View_Admin_As.init );
}
} ( jQuery ) );