/*global jQuery, UMP, janrain, wp, console, UMP_ExactTarget_exports */
var UMP_ExactTarget = (function($) {
"use strict";
var self = {
tabId : '#tab_subscription',
subscriptions : null,
subscriptionsByListId: null,
originalSubscriptions: false,
listIdClass : '.ump-subscription-list-id',
listNameClass : '.ump-subscription-list-name',
listSubButton : '.ump-subscription-list-button',
saveLoadingClass : '.capture_processing',
saveButtonId : '#capture_editNewsletters_saveButton',
saveMessageClass : '.message-result',
unsubscribeAllLink : '#unsubscribe-all',
screenShowHandlers : {},
currentScreen : null,
updateUnsubscribeKey : false,
modalIdPrefix : '#umpUnsubscribeModal',
lastAction : '',
lastListID : '',
isLoading : false,
attributeNames: {
newsletterPlural: '', // was JANRAIN_NEWSLETTER_ATTRIBUTE
newsletterSite: '' //was JANRAIN_NEWSLETTER_SITE_ATTR
},
flags: {
update: '',
send_welcome_email: ''
},
siteUrl: '', // was JANRAIN_NEWSLETTER_SITE_NAME
unsubscribeStatusParamPattern: '' // was JANRAIN_QUERY_STRING_UNSUBSCRIBE_STATUS
};
$.extend( self, UMP_ExactTarget_exports );
self.init = function() {
// Initialize screenShow handlers.
self.screenShowHandlers.editProfile = self.editProfileScreenHandler;
self.screenShowHandlers.traditionalRegistration = self.registrationScreenHandler;
self.screenShowHandlers.socialRegistration = self.registrationScreenHandler;
// Bind handlers to events.
self.bindEvents();
// If self.unsubscribeStatusParamPattern exists URL query string, refresh
// user data and open the modal.
var re = new RegExp( self.unsubscribeStatusParamPattern + '=(\\w+)', 'i' );
var matches = location.search.match(re);
if ( matches ) {
var status = matches[1] || 'error';
if ('success' !== status && 'error' !== status) {
status = 'error';
}
$(self.modalIdPrefix + status.charAt(0).toUpperCase() + status.substr(1)).modal('show');
UMP.authenticated.watch( function ( is_authenticated ) {
if ( is_authenticated ) {
UMP.refreshUserData();
}
});
}
};
/**
* Binds events to handlers.
*/
self.bindEvents = function() {
// Listen on the document because subscribe buttons are added dynamically
$(document).on('click', self.subscribeClick);
// When editProfile is shown populates subscriptions property.
janrain.events.onCaptureScreenShow.addHandler(self.screenShowHandler);
// Updates entity' rdm_newsletters attribute.
$(document).on('click', self.saveButtonId, self.updateEntityAttribute);
// Updates entity' rdm_newsletters attribute on successful registration.
janrain.events.onCaptureRegistrationSuccess.addHandler(function() {
self.updateUnsubscribeKey = true;
self.triggerWelcomeEmailSend = true;
$( UMP ).one( 'user_data_success', self.updateEntityAttribute );
});
// Updates entity' rdm_newsletters when user update his/her profile.
janrain.events.onCaptureProfileSaveSuccess.addHandler( function() {
$( UMP ).one( 'user_data_success', self.updateEntityAttribute );
} );
// Reload subscriptions when we get Ajax success
$( UMP ).on( 'user_data_success', self.editProfileScreenHandler );
};
/**
* Use cases
* We get to site and we have no subscriptions and we sub
* We get to sute and we have have no subscriptions and we unsub from all
*
* We get to site and we have all subscriptions and we select unsub/sub from one
* We get to site and we have some subscriptions and we select unsub/sub from one
* We get to site and we have subscriptions and we select unsub all
*
* Error message needs to be updated to red
*
* If we sign up on that site then subscriptions for all the inital newsletter are set
* If we signed up on another site then subcriptions don't exist
*
* @param {[type]} e [description]
* @return {[type]} [description]
*/
self.subscribeClick = function(e) {
var el = e.target;
var subscriptions = self.mapMySubscriptionsByListId( self.subscriptions )
// If its not a sub/unsub button then return.
if ( ! $(el).hasClass('ump-subscription-list-button') && ! $(el).hasClass('ump-unsubscribe-all-link') ) {
return;
}
e.preventDefault();
if ( self.subscriptions === null ) {
self.editProfileScreenHandler();
}
if ( $(el).hasClass('ump-unsubscribe-all-link') ) {
// Handle unsubscribe all (except allusers)
Array.prototype.forEach.call(self.subscriptions, function(item, index){
if ( ! item.newsletterID.match(/allusers$/)) {
self.updateSubscriptionStatus( index, false );
}
});
self.lastAction = 'unsubscribe_all';
} else {
// Handle sub/unsub for one
// Add Subscribe/Unsubscribe actions here.
var newsletterID = $(el).attr('data-newsletter-id')
var subIndex = false;
Array.prototype.forEach.call(self.subscriptions, function(item, index){
if ( item.newsletterID === newsletterID ) {
subIndex = index
}
});
if ( false !== subIndex ) {
self.updateSubscriptionStatus( subIndex, ! self.subscriptions[subIndex].subscribed );
}
}
self.updateEntityAttribute(e);
self.lastAction = '';
}
/**
* Update subscription status
*/
self.updateSubscriptionStatus = function( subIndex, status ) {
self.subscriptions[subIndex].subscribed = status;
var t = new Date();
self.subscriptions[subIndex].timestamp = t.toISOString() || ''
if ( self.subscriptions[subIndex].subscribed ) {
} else {
self.subscriptions[subIndex].unsubscribeTimestamp = t.toISOString() || ''
}
};
/**
* Update self.subscriptions when user changes his/her lists
* preference.
*/
self.watchListsChange = function() {
self.populateSubscriptions();
};
/**
* Handler when Janrain screen is shown. We're not interested to handle
* all screens, check `self.screenShowHandlers` for supported screens.
*/
self.screenShowHandler = function(r) {
self.currentScreen = r.screen;
if ( 'function' === typeof self.screenShowHandlers[r.screen] ) {
self.screenShowHandlers[r.screen]();
}
};
/**
* Handler when editProfile screen is shown. This handler updates self.subscriptions
* property which will be used to post to WP AJAX handler.
*/
self.editProfileScreenHandler = function() {
var user = UMP.user_data.get();
if (typeof user === 'undefined') {
self.populateSubscriptions();
self.showLoadingIndicator();
}
else if ( (typeof user !== 'undefined') && user[ self.attributeNames.newsletterPlural ] && user[ self.attributeNames.newsletterPlural ].length ) {
self.subscriptions = user[ self.attributeNames.newsletterPlural ];
self.updateMySubscriptionsView( self.mapMySubscriptionsByListId( self.subscriptions ) );
self.hideLoadingIndicator( false, '' );
}
// No newsletter preferences for this site
else if ( (typeof user !== 'undefined') && user[ self.attributeNames.newsletterPlural ] && (user[ self.attributeNames.newsletterPlural ].length === 0) ) {
self.hideLoadingIndicator( false, '' );
self.populateSubscriptions();
}
else {
// If the user is undefined then populate
self.populateSubscriptions();
}
if (typeof user !== 'undefined') {
self.originalSubscriptions = self.getOriginalDescriptions(
self.mapSiteLists( self.lists ),
self.mapMySubscriptionsByListId( user.rdm_newsletters )
);
}
};
/**
* Handler when socialRegistration or traditionalRegistration is shown. Does the same thing
* as editProfileScreenHandler, except there's no check on existing user data.
*/
self.registrationScreenHandler = function() {
self.populateSubscriptions();
};
/**
* Populates self.subscriptions property before being sent to WP AJAX handler.
*/
self.populateSubscriptions = function() {
var container = self.tabId;
if ('editProfile' !== self.currentScreen) {
container = '#' + self.currentScreen;
}
self.subscriptions = [];
};
/**
* Updates self.attributeNames.newsletterPlural of current entity via AJAX.
*/
self.updateEntityAttribute = function(event) {
if ( 'editProfile' === self.currentScreen ) {
self.showLoadingIndicator();
}
var UpdateEntityError = function( msg ) {
this.name = 'UpdateEntityError';
this.message = msg || 'unknown error';
this.message = self.labels.subscription_status.newslettersUpdateFailed + ' ' + this.message;
};
UpdateEntityError.prototype = new Error();
UpdateEntityError.prototype.constructor = UpdateEntityError;
var user = UMP.user_data.get();
var data = {
'action' : 'update_entity_info',
'uuid' : user.uuid,
'access_token': UMP.getAccessToken(),
'nonce' : UMP.update_entity_info_nonce,
'attributes' : {}
};
if ( self.updateUnsubscribeKey ) {
data.attributes[ self.flags.update ] = true;
}
if ( self.triggerWelcomeEmailSend ) {
data.attributes[ self.flags.send_welcome_email ] = true;
}
self.triggerWelcomeEmailSend = false;
self.updateUnsubscribeKey = false;
/**
* Determine if there are lists the user needs to be added to.
*/
var siteLists = self.mapSiteLists( self.lists );
var mappedSubscriptions = self.mapMySubscriptionsByListId( self.subscriptions );
/**
* Loop through each of the site lists and add it to the user's subscriptions status
* if this list's button was clicked. If it's not in the list of subscriptions then we add it
*/
$.each( siteLists, function(idx, list) {
// if we are adding them to a new newsletter not in the subscriptions list
if ( typeof mappedSubscriptions !== 'undefined' && null !== mappedSubscriptions && ! mappedSubscriptions.hasOwnProperty( list.newsletterID )
&& $( event.target ).attr('data-newsletter-id') === list.newsletterID )
{
var item = list;
item.opt_newsletter_email = user.email;
item.parm1 = event.target.baseURI;
item.subscribeFromIdOrURL = event.target.baseURI;
item.subscribed = true;
self.subscriptions.push( item );
//subscriptionsToUpdate.push( item );
}
// if ( ($( event.target ).attr('data-newsletter-id') === list.newsletterID) || ('unsubscribe_all' !== self.lastAction) ) {
// var item = list;
// item.opt_newsletter_email = user.email;
// item.parm1 = event.target.baseURI;
// //item.subscribeFromIdOrURL = event.target.baseURI;
// //item.subscribed = true; // This was already updated in updateSubscriptionStatus
// item.subscribeFromIdOrURL = location.href;
// //self.subscriptions.push( item );
// subscriptionsToUpdate.push( item );
// }
});
var subscriptionsToUpdate = [];
// Loop through subscripions, set the proper values then add to array to send for update
$.each(self.subscriptions, function(i, v) {
v.subscribeFromIdOrURL = location.href;
v.parm1 = location.href;
v.parm2 = 'fromJanrain'; //tempSourceVariable to see our source
v.parm3 = 'explicit';
v.parm4 = self.lastAction;
v.opt_newsletter_email = user.email;
self.subscriptions[i] = v;
if (($( event.target ).attr('data-newsletter-id') === v.newsletterID) || ('unsubscribe_all' === self.lastAction)) {
subscriptionsToUpdate.push( v );
}
});
//data.attributes[ self.attributeNames.newsletterPlural ] = self.subscriptions;
data.attributes[ self.attributeNames.newsletterPlural ] = subscriptionsToUpdate;
data.attributes[ 'original_values' ] = self.originalSubscriptions;
data.attributes = JSON.stringify(data.attributes);
self.lastListID = $( event.target ).attr('data-newsletter-id');
var mappedOriginalSubscriptions = self.mapMySubscriptionsByListId( self.originalSubscriptions );
if ( 'unsubscribe_all' !== self.lastAction && typeof mappedOriginalSubscriptions !== 'undefined' && null !== mappedOriginalSubscriptions ) {
self.lastAction = ( typeof mappedOriginalSubscriptions[ self.lastListID ] !== 'undefined' && mappedOriginalSubscriptions[ self.lastListID ].subscribed ) ? 'unsubscribe' : 'subscribe';
}
/**
* DEBUG:
* Once issue with missing object is reolved we can remove this.
*/
var wp = wp || {};
wp.ajax = wp.ajax || {
settings: {
url: '/wp-admin/admin-ajax.php'
}
}
// Updates rdm_newsletter via ajax.
var xhr = jQuery.ajax( {
url: wp.ajax.settings.url,
type: 'POST',
data: data
} );
var callback = function ( error ) {
if ( 'editProfile' !== self.currentScreen && window.console ) {
console.log( error.toString() );
}
if ( error && 'UpdateEntityError' === error.name ) {
console.warn( "UpdateEntityError", error );
var message = self.labels.subscription_status[ 'fail' ];
message = message.replace( '\%CONTACT_US\%', '' + self.labels.link_titles.contact_us + '' );
self.hideLoadingIndicator( true, message );
} else {
var message = self.labels.subscription_status[ 'fail' ];
message = message.replace( '\%CONTACT_US\%', '' + self.labels.link_titles.contact_us + '' );
self.hideLoadingIndicator( true, message );
}
};
// Capture lastAction here because it will be reset befor async task is done.
var lastAction = self.lastAction;
xhr.done( function(r) {
try {
if ( ! r.success ) {
throw new UpdateEntityError( r.data.toString() );
}
var user_data = UMP.user_data.get();
user_data[ self.attributeNames.newsletterPlural ] = self.subscriptions;
user_data = $.extend( {}, user_data ); // Clone to trigger watch
user_data.accessToken = UMP.getAccessToken();
UMP.user_data.set(user_data);
UMP.refreshUserData( function() {
if ( 'editProfile' === self.currentScreen ) {
self.updateMySubscriptionsView( self.mapMySubscriptionsByListId( self.subscriptions ) );
var message = self.labels.subscription_status[ lastAction ];
var lists = self.mapMySubscriptionsByListId( self.subscriptions );
if ( 'unsubscribe_all' !== lastAction && typeof lists !== 'undefined' && null !== lists ) {
var name = ( typeof lists[self.lastListID] !== 'undefined' ) ? lists[self.lastListID].name : 'null';
message = message.replace( '\%LIST_NAME\%', name );
}
message = message.replace( '\%SITE_NAME\%', self.siteName );
message = message.replace( '\%CONTACT_US\%', '' + self.labels.link_titles.contact_us + '' );
self.hideLoadingIndicator( false, message );
}
} );
self.originalSubscriptions = self.getOriginalDescriptions(
self.mapSiteLists( self.lists ),
self.mapMySubscriptionsByListId( self.subscriptions )
);
} catch (e) {
callback( e );
$('.ump-subscription-list-button').attr('disabled', 'disabled');
}
} );
xhr.fail( function( xhr, textStatus ) {
callback( new UpdateEntityError( textStatus ) );
$('.ump-subscription-list-button').attr('disabled', 'disabled');
} );
};
/**
* Shows loading indicator in newsletters tab. This is called
* when doing AJAX request.
*/
self.showLoadingIndicator = function() {
if ( self.isLoading )
return;
self.isLoading = true;
// Shows loading indicator.
$(self.saveLoadingClass, self.tabId).show();
// Hides save button.
// $(self.saveButtonId, self.tabId).hide();
$(self.listSubButton).attr('disabled', 'disabled');
// Removes save message.
$(self.saveMessageClass, self.tabId)
.removeClass('save-success')
.removeClass('save-error')
.html('');
$(self.saveMessageClass, self.tabId).show();
self.isLoading = false;
};
/**
* Hides loading indicator after made a request via AJAX.
*/
self.hideLoadingIndicator = function( isError, message ) {
// Hides loading indicator.
$(self.saveLoadingClass, self.tabId).hide();
// Shows save button.
// $(self.saveButtonId, self.tabId).show();
$(self.listSubButton).removeAttr('disabled');
// Shows save message, whether succeed or failed.
var className = 'save-success';
if ( isError ) {
className = 'save-error';
}
$(self.saveMessageClass, self.tabId).addClass(className).html(message);
if ( message == '' || message == 'Success. You have subscribed to null') {
$(self.saveMessageClass, self.tabId).hide();
} else {
$(self.saveMessageClass, self.tabId).show();
}
};
/**
* Populates self.subscriptionsByListId with object where its
* key is list ID and the value is list object.
*/
self.mapMySubscriptionsByListId = function(subscriptions) {
self.subscriptionsByListId = {};
if ( null !== subscriptions && subscriptions.length ) {
self.subscriptionsByListId = {};
$.each(subscriptions, function(idx, list) {
self.subscriptionsByListId[ list.newsletterID ] = list;
});
}
return self.subscriptionsByListId;
};
/**
* Transforms provided self.lists object mapped to same schema as subscriptions.
*
* @param lists
* @returns {{}}
*/
self.mapSiteLists = function(lists) {
var mapped = {};
if ( null !== lists && lists.length ) {
$.each(lists, function(idx, list) {
mapped[list.newsletterID] =
{
'name' : list.name,
'newsletterID' : list.newsletterID,
'opt_newsletter_email' : '',
'parm1' : self.siteUrl,
'parm2' : '',
'parm3' : '',
'parm4' : '',
'subscribeFromIdOrURL' : self.siteUrl,
'subscribed' : false,
'timestamp' : null,
'unsubscribeTimestamp' : null
};
});
}
return mapped;
};
/**
* Updates subscriptions lists in "My Subscriptions" tab
* to match with current user preferences, that's, if
* user subscribes to list "A" then "A"'s button must read 'Unsubscribe'.
* It's assumed that subscriptions is an object where its
* key is newsletterID. If still an array, creates a map with
* self.mapMySubscriptionsByListId.
*/
self.updateMySubscriptionsView = function(subscriptions) {
$(self.listSubButton).each(function() {
var button = $(this);
var newsletterID = button.attr('data-newsletter-id');
if ( typeof subscriptions[ newsletterID ] !== 'undefined' && subscriptions[ newsletterID ].subscribed ) {
// Button labels defined in ump-exacttarget.php for JS object `UMP_ExactTarget_exports`
button.val( self.labels.subscribe_button.unsubscribe );
button.parent( '.list' ).addClass( 'user-subscribed' );
} else {
button.val( self.labels.subscribe_button.subscribe );
button.parent( '.list' ).removeClass( 'user-subscribed' );
}
});
};
/**
* Merges user subscriptions with available site lists to get the original
* state of a user's subscription status. This value is passed via an AJAX
* handler to ensure unnecessary actions are not recorded in ExactTarget history.
*
* @param siteLists
* @param rdmLists
* @returns {Array}
*/
self.getOriginalDescriptions = function( siteLists, rdmLists ) {
var mergedLists = $.extend( true, siteLists, rdmLists );
var subscriptions = [];
for (var item in mergedLists) {
subscriptions.push(mergedLists[item])
}
return subscriptions;
}
// Call init.
UMP.deferred.loaded.done(self.init);
return self;
}(jQuery));