( function( $, as3cfModal ) {
var savedSettings = {};
var bucketNamePattern = /[^a-z0-9.-]/;
var $body = $( 'body' );
var $tabs = $( '.as3cf-tab' );
var $settings = $( '.as3cf-settings' );
var $activeTab;
/**
* Return the serialized string of the settings form
* excluding the bucket and region inputs as they get saved via AJAX
*
* @param string tab
*
* @returns {string}
*/
function serializedForm( tab ) {
return $( '#' + tab + ' .as3cf-main-settings form' ).find( 'input:not(.no-compare)' ).serialize();
}
/**
* Set checkbox
*
* @param string checkbox_wrap
*/
function setCheckbox( checkbox_wrap ) {
var $switch = $activeTab.find( '#' + checkbox_wrap );
var $checkbox = $switch.find( 'input[type=checkbox]' );
$switch.toggleClass( 'on' ).find( 'span' ).toggleClass( 'checked' );
var switchOn = $switch.find( 'span.on' ).hasClass( 'checked' );
$checkbox.prop( 'checked', switchOn ).trigger( 'change' );
}
/**
* Validate custom domain
*
* @param {object} $input
*/
function validateCustomDomain( $input ) {
var $error = $input.next( '.as3cf-validation-error' );
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
var pattern = /[^a-zA-Z0-9\.\-]/;
if ( pattern.test( $input.val() ) ) {
$error.show();
$submit.prop( 'disabled', true );
} else {
$error.hide();
$submit.prop( 'disabled', false );
}
}
as3cf.tabs = {
defaultTab: 'media',
/**
* Toggle settings tab
*
* @param string hash
* @param boolean persist_updated_notice
*/
toggle: function( hash, persist_updated_notice ) {
hash = as3cf.tabs.sanitizeHash( hash );
$tabs.hide();
$activeTab = $( '#tab-' + hash );
$activeTab.show();
$( '.nav-tab' ).removeClass( 'nav-tab-active' );
$( 'a.nav-tab[data-tab="' + hash + '"]' ).addClass( 'nav-tab-active' );
$( '.as3cf-main' ).data( 'tab', hash );
if ( $activeTab.data( 'prefix' ) ) {
as3cfModal.prefix = $activeTab.data( 'prefix' );
}
if ( ! persist_updated_notice ) {
$( '.as3cf-updated' ).removeClass( 'show' );
}
if ( 'support' === hash ) {
as3cf.tabs.getDiagnosticInfo();
}
},
/**
* Update display of diagnostic info.
*/
getDiagnosticInfo: function() {
var $debugLog = $( '.debug-log-textarea' );
$debugLog.html( as3cf.strings.get_diagnostic_info );
var data = {
action: 'as3cf-get-diagnostic-info',
_nonce: as3cf.nonces.get_diagnostic_info
};
$.ajax( {
url: ajaxurl,
type: 'POST',
dataType: 'JSON',
data: data,
error: function( jqXHR, textStatus, errorThrown ) {
$debugLog.html( errorThrown );
},
success: function( data, textStatus, jqXHR ) {
if ( 'undefined' !== typeof data[ 'success' ] ) {
$debugLog.html( data[ 'diagnostic_info' ] );
} else {
$debugLog.html( as3cf.strings.get_diagnostic_info_error );
$debugLog.append( data[ 'error' ] );
}
}
} );
},
/**
* Sanitize hash to ensure it references a real tab.
*
* @param string hash
*
* @return string
*/
sanitizeHash: function( hash ) {
var $newTab = $( '#tab-' + hash );
if ( 0 === $newTab.length ) {
hash = as3cf.tabs.defaultTab;
}
return hash;
}
};
/**
* Handle the bucket selection, either inline or in a modal
*/
as3cf.buckets = {
/**
* Buckets must be at least this many characters
*/
validLength: 3,
/**
* Process lock for setting a bucket
*/
bucketSelectLock: false,
/**
* Load bucket list
*
* @param {boolean} [forceUpdate]
*/
loadList: function( forceUpdate ) {
if ( 'undefined' === typeof forceUpdate ) {
forceUpdate = false;
}
var $selectBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' );
var $selectBucketRegion = $selectBucketForm.find( '.bucket-select-region' );
var $bucketList = $selectBucketForm.find( '.as3cf-bucket-list' );
var selectedBucket = $( '#' + as3cfModal.prefix + '-bucket' ).val();
if ( false === forceUpdate && $bucketList.find( 'li' ).length > 1 ) {
$( '.as3cf-bucket-list a' ).removeClass( 'selected' );
$( '.as3cf-bucket-list a[data-bucket="' + selectedBucket + '"]' ).addClass( 'selected' );
this.scrollToSelected();
return;
}
$bucketList.html( '
' + $bucketList.data( 'working' ) + '' );
// Stop accidental submit while reloading list.
this.disabledButtons();
var data = {
action: as3cfModal.prefix + '-get-buckets',
_nonce: window[ as3cfModal.prefix.replace( /-/g, '_' ) ].nonces.get_buckets
};
if ( $selectBucketRegion.val() ) {
data[ 'region' ] = $selectBucketRegion.val();
}
var that = this;
$.ajax( {
url: ajaxurl,
type: 'POST',
dataType: 'JSON',
data: data,
error: function( jqXHR, textStatus, errorThrown ) {
$bucketList.html( '' );
that.showError( as3cf.strings.get_buckets_error, errorThrown, 'as3cf-bucket-select' );
},
success: function( data, textStatus, jqXHR ) {
$bucketList.html( '' );
if ( 'undefined' !== typeof data[ 'success' ] ) {
$( '.as3cf-bucket-error' ).hide();
if ( 0 === data[ 'buckets' ].length ) {
$bucketList.html( '' + $bucketList.data( 'nothing-found' ) + '' );
} else {
$( data[ 'buckets' ] ).each( function( idx, bucket ) {
var bucketClass = bucket.Name === selectedBucket ? 'selected' : '';
$bucketList.append( ' ' + bucket.Name + '' );
} );
that.scrollToSelected();
that.disabledButtons();
}
} else {
that.showError( as3cf.strings.get_buckets_error, data[ 'error' ], 'as3cf-bucket-select' );
}
}
} );
},
/**
* Scroll to selected bucket
*/
scrollToSelected: function() {
if ( ! $( '.as3cf-bucket-list a.selected' ).length ) {
return;
}
var offset = $( 'ul.as3cf-bucket-list li' ).first().position().top + 150;
$( '.as3cf-bucket-list' ).animate( {
scrollTop: $( 'ul.as3cf-bucket-list li a.selected' ).position().top - offset
} );
},
/**
* Set the selected bucket in list.
*
* @param {object} $link
*/
setSelected: function( $link ) {
$( '.as3cf-bucket-list a' ).removeClass( 'selected' );
$link.addClass( 'selected' );
$( '#' + as3cfModal.prefix + '-bucket-select-name' ).val( $link.data( 'bucket' ) );
},
/**
* Disable bucket buttons
*/
disabledButtons: function() {
var $createBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-create' );
var $manualBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-manual' );
var $selectBucketForm = $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' );
if ( 0 === $createBucketForm.length && 0 === $manualBucketForm.length && 0 === $selectBucketForm.length ) {
return;
}
if ( 0 < $createBucketForm.length && this.isValidName( $createBucketForm.find( '.as3cf-bucket-name' ).val() ) ) {
$createBucketForm.find( 'button[type=submit]' ).prop( 'disabled', false );
} else {
$createBucketForm.find( 'button[type=submit]' ).prop( 'disabled', true );
}
if ( 0 < $manualBucketForm.length && this.isValidName( $manualBucketForm.find( '.as3cf-bucket-name' ).val() ) ) {
$manualBucketForm.find( 'button[type=submit]' ).prop( 'disabled', false );
} else {
$manualBucketForm.find( 'button[type=submit]' ).prop( 'disabled', true );
}
if ( 0 < $selectBucketForm.length && 1 === $selectBucketForm.find( '.as3cf-bucket-list a.selected' ).length ) {
$selectBucketForm.find( 'button[type=submit]' ).prop( 'disabled', false );
} else {
$selectBucketForm.find( 'button[type=submit]' ).prop( 'disabled', true );
}
},
/**
* Show bucket error
*
* @param {string} title
* @param {string} error
* @param {string} [context]
*/
showError: function( title, error, context ) {
var $activeView = $( '.as3cf-bucket-container' ).children( ':visible' );
var $bucketError = $activeView.find( '.as3cf-bucket-error' );
context = ( 'undefined' === typeof context ) ? null : context;
if ( context && ! $activeView.hasClass( context ) ) {
return;
}
$bucketError.find( 'span.title' ).html( title + ' —' );
$bucketError.find( 'span.message' ).html( error );
$bucketError.show();
// Unlock setting the bucket
this.bucketSelectLock = false;
},
/**
* Check for a valid bucket name
*
* Bucket names must be at least 3 and no more than 63 characters long.
* They can contain lowercase letters, numbers, periods and hyphens.
*
* @param {string} bucketName
*
* @return boolean
*/
isValidName: function( bucketName ) {
if ( bucketName.length < 3 || bucketName.length > 63 ) {
return false;
}
if ( true === bucketNamePattern.test( bucketName ) ) {
return false;
}
return true;
},
/**
* Update invalid bucket name notice
*
* @param {string} bucketName
*/
updateNameNotice: function( bucketName ) {
var message = null;
if ( true === bucketNamePattern.test( bucketName ) ) {
message = as3cf.strings.create_bucket_invalid_chars;
} else if ( bucketName.length < 3 ) {
message = as3cf.strings.create_bucket_name_short;
} else if ( bucketName.length > 63 ) {
message = as3cf.strings.create_bucket_name_long;
}
if ( message && bucketName.length > 0 ) {
$( '.as3cf-invalid-bucket-name' ).html( message );
} else {
$( '.as3cf-invalid-bucket-name' ).html( '' );
}
}
};
/**
* Reload the page, and show the persistent updated notice.
*
* Intended for use on plugin settings page.
*/
as3cf.reloadUpdated = function() {
var url = location.pathname + location.search;
if ( ! location.search.match( /[?&]updated=/ ) ) {
url += '&updated=1';
}
url += location.hash;
location.assign( url );
};
/**
* Show the standard "Settings saved." notice if not already visible.
*/
as3cf.showSettingsSavedNotice = function() {
if ( 0 < $( '#setting-error-settings_updated:visible' ).length || 0 < $( '#as3cf-settings_updated:visible' ).length ) {
return;
}
var settingsUpdatedNotice = '' + as3cf.strings.settings_saved + '
';
$( 'h2.nav-tab-wrapper' ).after( settingsUpdatedNotice );
$( document ).trigger( 'wp-updates-notice-added' ); // Hack to run WP Core's makeNoticesDismissible() function.
};
/**
* Get the link to the bucket on the AWS Console and update the DOM
*
* @returns {string}
*/
function setBucketLink() {
var bucket = $( '#' + as3cfModal.prefix + '-bucket' ).val();
var $objectPrefix = $activeTab.find( 'input[name="object-prefix"]' );
var prefix = $objectPrefix.val();
if ( '' !== prefix ) {
prefix = as3cf.provider_console_url_prefix_param + encodeURIComponent( prefix );
}
var url = as3cf.provider_console_url + bucket + prefix;
$( '#' + as3cfModal.prefix + '-view-bucket' ).attr( 'href', url );
}
/*
* Toggle the lost files notice
*/
function toggleLostFilesNotice() {
if ( $( '#as3cf-remove-local-file' ).is( ':checked' ) && $( '#as3cf-serve-from-s3' ).is( ':not(:checked)' ) ) {
$( '#as3cf-lost-files-notice' ).show();
} else {
$( '#as3cf-lost-files-notice' ).hide();
}
}
/*
* Toggle the remove local files notice
*/
function toggleRemoveLocalNotice() {
if ( $( '#as3cf-remove-local-file' ).is( ':checked' ) ) {
$( '#as3cf-remove-local-notice' ).show();
} else {
$( '#as3cf-remove-local-notice' ).hide();
}
}
/*
* Toggle the seo friendly url notice.
*/
function toggleSEOFriendlyURLNotice( seo_friendly ) {
if ( true !== seo_friendly ) {
$( '#as3cf-seo-friendly-url-notice' ).show();
} else {
$( '#as3cf-seo-friendly-url-notice' ).hide();
}
}
/**
* Generate URL preview
*/
function generateUrlPreview() {
$( '.as3cf-url-preview' ).html( 'Generating...' );
var data = {
_nonce: as3cf.nonces.get_url_preview
};
$.each( $( '#tab-' + as3cf.tabs.defaultTab + ' .as3cf-main-settings form' ).serializeArray(), function( i, o ) {
var n = o.name,
v = o.value;
n = n.replace( '[]', '' );
data[ n ] = undefined === data[ n ] ? v : $.isArray( data[ n ] ) ? data[ n ].concat( v ) : [ data[ n ], v ];
} );
// Overwrite the save action stored in the form
data[ 'action' ] = 'as3cf-get-url-preview';
$.ajax( {
url: ajaxurl,
type: 'POST',
dataType: 'JSON',
data: data,
error: function( jqXHR, textStatus, errorThrown ) {
alert( as3cf.strings.get_url_preview_error + errorThrown );
},
success: function( data, textStatus, jqXHR ) {
if ( 'undefined' !== typeof data[ 'success' ] ) {
$( '.as3cf-url-preview' ).html( data[ 'url' ] );
toggleSEOFriendlyURLNotice( data[ 'seo_friendly' ] );
} else {
alert( as3cf.strings.get_url_preview_error + data[ 'error' ] );
}
}
} );
}
/**
* Update the UI with the current active tab set in the URL hash.
*/
function renderCurrentTab() {
// If rendering the default tab, or a bare hash clean the hash.
if ( '#' + as3cf.tabs.defaultTab === location.hash ) {
location.hash = '';
return;
}
as3cf.tabs.toggle( location.hash.replace( '#', '' ), true );
$( document ).trigger( 'as3cf.tabRendered', [ location.hash.replace( '#', '' ) ] );
}
$( document ).ready( function() {
// Tabs
// --------------------
renderCurrentTab();
/**
* Set the hashchange callback to update the rendered active tab.
*/
window.onhashchange = function( event ) {
// Strip the # if still on the end of the URL
if ( 'function' === typeof history.replaceState && '#' === location.href.slice( -1 ) ) {
history.replaceState( {}, '', location.href.slice( 0, -1 ) );
}
renderCurrentTab();
};
// Move any compatibility errors below the nav tabs
var $navTabs = $( '.as3cf-main .nav-tab-wrapper' );
$( '.as3cf-compatibility-notice, div.updated, div.error, div.notice' ).not( '.below-h2, .inline' ).insertAfter( $navTabs );
// Settings
// --------------------
// Save the original state of the forms for comparison later
if ( $tabs.length ) {
$tabs.each( function( i, tab ) {
savedSettings[ tab.id ] = serializedForm( tab.id );
} );
}
// Prompt user with dialog if leaving the settings page with unsaved changes
$( window ).on( 'beforeunload.as3cf-settings', function() {
if ( $.isEmptyObject( savedSettings ) ) {
return;
}
var tab = $activeTab.attr( 'id' );
if ( serializedForm( tab ) !== savedSettings[ tab ] ) {
return as3cf.strings.save_alert;
}
} );
// Let the save settings submit happen as normal
$( document ).on( 'submit', '.as3cf-main-settings form', function( e ) {
// Disable unload warning
$( window ).off( 'beforeunload.as3cf-settings' );
} );
$( '.as3cf-switch' ).on( 'click', function( e ) {
if ( ! $( this ).hasClass( 'disabled' ) ) {
setCheckbox( $( this ).attr( 'id' ) );
}
} );
$tabs.on( 'change', '.sub-toggle', function( e ) {
var setting = $( this ).attr( 'id' );
$( '.as3cf-setting.' + setting ).toggleClass( 'hide' );
} );
$( '.as3cf-domain' ).on( 'change', 'input[type="radio"]', function( e ) {
var $selected = $( this ).closest( 'input:radio[name="domain"]:checked' );
var domain = $selected.val();
var $cloudfront = $( this ).parents( '.as3cf-domain' ).find( '.as3cf-setting.cloudfront' );
var cloudfrontSelected = ( 'cloudfront' === domain );
$cloudfront.toggleClass( 'hide', ! cloudfrontSelected );
} );
$( '.url-preview' ).on( 'change', 'input', function( e ) {
generateUrlPreview();
} );
toggleLostFilesNotice();
$( '#as3cf-serve-from-s3,#as3cf-remove-local-file' ).on( 'change', function( e ) {
toggleLostFilesNotice();
} );
toggleRemoveLocalNotice();
$( '#as3cf-remove-local-file' ).on( 'change', function( e ) {
toggleRemoveLocalNotice();
} );
// Don't allow 'enter' key to submit form on text input settings
$( '.as3cf-setting input[type="text"]' ).keypress( function( event ) {
if ( 13 === event.which ) {
event.preventDefault();
return false;
}
} );
// Validate custom domain
$( 'input[name="cloudfront"]' ).on( 'keyup', function( e ) {
validateCustomDomain( $( this ) );
} );
// Re-enable submit button on domain change
$( 'input[name="domain"]' ).on( 'change', function( e ) {
var $input = $( this );
var $submit = $( '#' + $activeTab.attr( 'id' ) + ' form button[type="submit"]' );
if ( 'cloudfront' !== $input.val() ) {
$submit.prop( 'disabled', false );
} else {
validateCustomDomain( $input.next( '.as3cf-setting' ).find( 'input[name="cloudfront"]' ) );
}
} );
// Change bucket link when custom path changes
$( 'input[name="object-prefix"]' ).on( 'change', function( e ) {
setBucketLink();
} );
// Bucket select
// --------------------
// Move bucket errors
$( '#tab-media > .as3cf-bucket-error' ).detach().insertAfter( '.as3cf-bucket-container h3' );
// Enable/disable change bucket's save buttons.
as3cf.buckets.disabledButtons();
// Bucket list refresh handler
$body.on( 'click', '.bucket-action-refresh', function( e ) {
e.preventDefault();
as3cf.buckets.loadList( true );
} );
// Bucket list refresh on region change handler
$body.on( 'change', '.bucket-select-region', function( e ) {
e.preventDefault();
as3cf.buckets.loadList( true );
} );
// If select bucket form is available on load, populate its list.
if ( 0 < $( '.as3cf-bucket-container.' + as3cfModal.prefix + ' .as3cf-bucket-select' ).length ) {
as3cf.buckets.loadList( true );
}
// Bucket list click handler
$body.on( 'click', '.as3cf-bucket-list a', function( e ) {
e.preventDefault();
as3cf.buckets.setSelected( $( this ) );
as3cf.buckets.disabledButtons();
} );
// External links click handler
$( '.as3cf-bucket-container' ).on( 'click', 'a.js-link', function( e ) {
e.preventDefault();
window.open( $( this ).attr( 'href' ) );
return false;
} );
// Validate bucket name on create
$body.on( 'input keyup', '.as3cf-bucket-create .as3cf-bucket-name', function( e ) {
var bucketName = $( this ).val();
as3cf.buckets.updateNameNotice( bucketName );
as3cf.buckets.disabledButtons();
} );
$body.on( 'input keyup', '.as3cf-bucket-manual .as3cf-bucket-name', function( e ) {
var bucketName = $( this ).val();
as3cf.buckets.updateNameNotice( bucketName );
as3cf.buckets.disabledButtons();
} );
// Don't allow 'enter' key to submit form on text input settings
$( '.as3cf-bucket-container input[type="text"]' ).keypress( function( event ) {
if ( 13 === event.which ) {
event.preventDefault();
return false;
}
} );
} );
} )( jQuery, as3cfModal );