<commit_before>/* **************************************************************

   Copyright 2013 Zoovy, Inc.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

************************************************************** */



//    !!! ->   TODO: replace 'username' in the line below with the merchants username.     <- !!!

var admin_config = function() {
	var theseTemplates = new Array(
		'paymentManagerPageTemplate',
/*		
		'paymentAvailabilityTemplate',
		'paymentHandlingFeeTemplate',
		'paymentTransferInstructionsTemplate',
		'paymentCCTemplate',
		'paymentEcheckTemplate',
		'paymentWallet_google',
		'paymentWallet_paypalec',
		'paymentWallet_amzcba',
		'paymentSuppInputsTemplate_manual',
		'paymentSuppInputsTemplate_paypalwp',
		'paymentSuppInputsTemplate_verisign',
		'paymentSuppInputsTemplate_authorizenet',
		'paymentSuppInputsTemplate_linkpoint',
		'paymentSuppInputsTemplate_echo',
		'paymentSuppInputsTemplate_skipjack',
*/		
		'shippingManagerPageTemplate',
		'shippingGeneralTemplate',
		'shippingBlacklistTemplate',
/*		
		'shippingZone_fedex',
		'shippingZone_usps',
		'shippingZone_ups',
		
		'shippingGlobal_handling',
		'shippingGlobal_insurance',

		'shippingFlex_shared',
		'shippingFlex_fixed',
		'shippingFlex_local',
		'shippingFlex_local_canada',
		'shippingFlex_free',
		'shippingFlex_simple',
		'shippingFlex_weight',
		'shippingFlex_price',
		
		'shippingLocalRowTemplate',
		'shippingWeightRowTemplate',
		'shippingPriceRowTemplate',
*/		
		'ruleBuilderTemplate',
		'ruleBuilderRowTemplate_shipping',
		'rulesInputsTemplate_shipping',
		
		'contactInformationTemplate',
		'taxConfigTemplate',
		'taxConfigRuleRowTemplate'
		);
	var r = {


////////////////////////////////////   CALLBACKS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\



	callbacks : {
//executed when extension is loaded. should include any validation that needs to occur.
		init : {
			onSuccess : function()	{
				var r = false; //return false if extension won't load for some reason (account config, dependencies, etc).
//the list of templates in theseTemplate intentionally has a lot of the templates left off.  This was done intentionally to keep the memory footprint low. They'll get loaded on the fly if/when they are needed.
				app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/config.html',theseTemplates);
				r = true;

				return r;
				},
			onError : function()	{
//errors will get reported for this callback as part of the extensions loading.  This is here for extra error handling purposes.
//you may or may not need it.
				app.u.dump('BEGIN admin_orders.callbacks.init.onError');
				}
			}
		}, //callbacks



////////////////////////////////////   ACTION    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		a : {
			showPaymentManager : function($target)	{
				$target.showLoading({'message':'Fetching your Active Payment Methods'});
				app.model.destroy('adminConfigDetail|payment|'+app.vars.partition);
				app.ext.admin.calls.adminConfigDetail.init({'payment':true},{datapointer : 'adminConfigDetail|payment|'+app.vars.partition,callback : function(rd){
					if(app.model.responseHasErrors(rd)){
						$('#globalMessaging').anymessage({'message':rd});
						}
					else	{
						$target.hideLoading();
						$target.anycontent({'templateID':'paymentManagerPageTemplate',data:{}});
						app.u.handleAppEvents($target);
						
						var
							$leftColumn = $("[data-app-role='slimLeftNav']",$target),
							$contentColumn = $("[data-app-role='slimLeftContent']",$target);
						
						$leftColumn.find('li').each(function(){
							var $li = $(this);
							$li.addClass('ui-corner-none pointer').on('click',function(){
								$('.ui-state-focus',$leftColumn).removeClass('ui-state-focus');
								$li.addClass('ui-state-focus');
								$("[data-app-role='slimLeftContentSection'] .heading",$target).text("Edit: "+$li.text());
								app.u.handleAppEvents($contentColumn); //handles app events outside the content area.
								app.ext.admin_config.a.showPaymentTypeEditorByTender($li.data('tender'),$contentColumn);
								});
							});
						}
					}},'mutable');
				app.model.dispatchThis('mutable');
				},
			
			showPaymentTypeEditorByTender : function(tender,$target){
//				app.u.dump("BEGIN showPaymentTypeEditorByTender ["+tender+"]");
				if(tender && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset:first').show().find('button').button('disable').find('.numChanges').text("");
					var payData = app.ext.admin_config.u.getPaymentByTender(tender);
//					app.u.dump(" -> payData: "); app.u.dump(payData);
					$target.append($("<input \/>",{'name':'tender','type':'hidden'}).val(tender));
					switch(tender){
/* offline payment types */
						case 'CASH':
						case 'GIFTCARD':
						case 'PO':
						case 'MO':
						case 'PICKUP':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$target.anycontent({'templateID':'paymentAvailabilityTemplate',data : payData});
							break;
						
						
						case 'CHECK':
						case 'COD':
						case 'CHKOD':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentHandlingFeeTemplate',data : payData}).appendTo($target);
							break;
						
						case 'WIRE':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentHandlingFeeTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentTransferInstructionsTemplate',data : payData}).appendTo($target);
						
							break;

/* gateways */
						case 'ECHECK':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('GATEWAY'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentEcheckTemplate',data : payData}).appendTo($target);
							break;

						case 'CC':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('GATEWAY'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentCCTemplate',data : payData}).appendTo($target);
							break;


/* wallets/third party payments */
						case 'GOOGLE':
						case 'PAYPALEC':
						case 'AMZCBA':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('WALLET'));
							$target.anycontent({'templateID':'paymentWallet_'+tender.toLowerCase(),data : payData});
							break;


						default:
							$target.anymessage({'message':'In admin_config.a.showPaymentTypeEditorByTender, unrecognized tender: '+tender+'.','gMessage':true});
						}
					app.u.handleAppEvents($target);
					app.ext.admin.u.applyEditTrackingToInputs($target.closest('form'));
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showPaymentTypeEditorByTender, both $target ['+typeof $target+'] and tender ['+tender+'] are required.','gMessage':true});
					}
				}, //showPaymentTypeEditorByTender
				
			showContactInformation : function($target)	{
				$target.showLoading({'message':'Fetching Contact Details'});
//				app.model.destroy('adminConfigDetail|account|'+app.vars.partition);
				app.ext.admin.calls.adminConfigDetail.init({'account':true},{'templateID':'contactInformationTemplate','datapointer' : 'adminConfigDetail|account|'+app.vars.partition, 'callback' : 'anycontent','jqObj':$target},'mutable');
				app.model.dispatchThis('mutable');
				},
		
			showTaxConfig : function($target)	{
				$target.empty().showLoading({'message':'Fetching Tax Details'});
				var datapointer = 'adminConfigDetail|taxes|'+app.vars.partition
				app.model.destroy(datapointer);
				app.ext.admin.calls.adminConfigDetail.init({'taxes':true},{'datapointer' : datapointer, 'callback' : function(rd){
if(app.model.responseHasErrors(rd)){
	$('#globalMessaging').anymessage({'message':rd});
	}
else	{
	$target.hideLoading();
	$target.anycontent({'templateID':'taxConfigTemplate','datapointer':rd.datapointer});
	
	$('.gridTable',$target).anytable();
	$('.toolTip',$target).tooltip();
	$(':checkbox',$target).anycb();
	$("[name='expires']",$target).datepicker({
		changeMonth: true,
		changeYear: true,
		minDate: 0,
		dateFormat : "yymmdd"
		});
	
	app.u.handleAppEvents($target,{'$form':$("[data-app-role='taxTableExecForm']",$target),'$container':$("[data-app-role='taxTableInputForm']",$target),'$dataTbody':$("[data-app-role='dataTableTbody']",$target)});
	}

					}},'mutable');
				app.model.dispatchThis('mutable');
				}, //showContactInformation
			
			showShippingManager : function($target)	{
				$target.showLoading({'message':'Fetching your Active Shipping Methods'});
				
				app.model.destroy('adminConfigDetail|shipping|'+app.vars.partition);
				app.model.destroy('adminConfigDetail|shipmethods|'+app.vars.partition);
				app.ext.admin.calls.appResource.init('shipcountries.json',{},'mutable');
				app.ext.admin.calls.adminConfigDetail.init({'shipping':true},{datapointer : 'adminConfigDetail|shipping|'+app.vars.partition},'mutable');
				app.ext.admin.calls.adminConfigDetail.init({'shipmethods':true},{datapointer : 'adminConfigDetail|shipmethods|'+app.vars.partition,callback : function(rd){
					if(app.model.responseHasErrors(rd)){
						$target.hideLoading();
						$('#globalMessaging').anymessage({'message':rd});
						}
					else	{
						
						$target.anycontent({
							'templateID':'shippingManagerPageTemplate',
							'data':$.extend(true,{},app.data['adminConfigDetail|shipping|'+app.vars.partition],app.data['adminConfigDetail|shipmethods|'+app.vars.partition])
							});

						var shipmethods = new Array();
						if(app.data['adminConfigDetail|shipmethods|'+app.vars.partition] && app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'])	{
							shipmethods = app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'];
							}

						var
							L = shipmethods.length,
							$flexUL = $("[data-app-role='shipMethodsByFlex']",$target);
//genrate the list of flex methods.
//disabled methods will get a class to help indicate they're disabled.
						for(var i = 0; i < L; i += 1)	{
							if(shipmethods[i].provider.indexOf('FLEX:') === 0)	{
//								app.u.dump("shipmethods[i].enabled: "+shipmethods[i].enable);
								$("<li \/>").data('provider',shipmethods[i].provider).text(shipmethods[i].name).appendTo($flexUL).addClass((shipmethods[i].enable == 1) ? '' :'opacity50');
								}
							}
						
						
						
						app.u.handleAppEvents($target);
						
						var
							$leftColumn = $("[data-app-role='slimLeftNav']",$target),
							$contentColumn = $("[data-app-role='slimLeftContent']",$target);

//add classes to fedex,ups and usps to indicate they are enabled/disabled.
						
//						$("[data-provider='FEDEX']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('FEDEX')['enable'] == 1 ? '' : 'opacity50');
//						$("[data-provider='UPS']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('UPS')['enable'] == 1 ? '' : 'opacity50');
//						$("[data-provider='USPS']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('USPS')['enable'] == 1 ? '' : 'opacity50');
						
 
						$("[data-app-role='shipMethodsByZone']:first, [data-app-role='shipMethodsGlobal']:first, [data-app-role='shipMethodsByFlex']:first",$leftColumn).find('li').each(function(){
							var $li = $(this);
							$li.addClass('ui-corner-none pointer').on('click',function(){
								$('.ui-state-focus',$leftColumn).removeClass('ui-state-focus');
								$li.addClass('ui-state-focus');
								$("[data-app-role='slimLeftContentSection'] .heading",$target).text("Edit: "+$li.text());
								app.ext.admin_config.a.showShipMethodEditorByProvider($li.data('provider'),$contentColumn)
								
								});
							});
						
						app.ext.admin_config.a.showShipMethodEditorByProvider('GENERAL',$contentColumn);
						
						}
					}},'mutable');
				app.model.dispatchThis('mutable');
				}, //showShippingManager

			showAddFlexShipment : function(shipmethod,$target)	{
				if(shipmethod && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset:first').hide() //this contains the buttons for the editor. create has it's own button.
					$("<div \/>").anycontent({'templateID':'shippingFlex_shared',data:{'provider':"FLEX:"+shipmethod+"_"+Math.round(+new Date()/1000)}}).appendTo($target);
					$("[data-app-role='rulesFieldset']",$target).hide(); //disallow rule creation till after ship method is created.
					$target.append("<p><b>Once you save the ship method, more specific inputs and rules will be available.<\/b><\/p>");
					$target.append("<button data-app-event='admin_config|shipmethodAddUpdateExec'>save<\/button>");
//					$("<div \/>").anycontent({'templateID':'shippingFlex_'+shipmethod.toLowerCase(),data:{}}).appendTo($target);
					app.u.handleAppEvents($target,{'handler':shipmethod,'mode':'insert'});
					}
				else if($target)	{
					$target.anymessage({'message':'In admin_config.a.showAddFlexShipment, shipmethod not passed.','gMessage':true});
					}
				else	{
					$("#globalMessaging").anymessage({'message':'In admin_config.a.showAddFlexShipment, shipmethod and target not passed.','gMessage':true});
					}
				}, //showAddFlexShipment

			showShipMethodEditorByProvider : function(provider,$target)	{
				
				if(provider && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset').hide(); //turn this off always. turn on when needed.
					
					if(provider == 'GENERAL')	{
						$target.anycontent({
							'templateID':'shippingGeneralTemplate',
							'data':$.extend(true,{},app.data['adminConfigDetail|shipping|'+app.vars.partition],app.data['adminConfigDetail|shipmethods|'+app.vars.partition],app.data['appResource|shipcountries.json'])
							});
						}
					else	{
						var shipData = app.ext.admin_config.u.getShipMethodByProvider(provider);
						
						app.ext.admin.u.handleSaveButtonByEditedClass($target.closest('form')); //reset the save button.
						
						if(provider.indexOf('FLEX:') === 0 && shipData.handler)	{
							$target.closest('form').find('.buttonset').show();
							$("<div \/>").anycontent({'templateID':'shippingFlex_shared',data:shipData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'shippingFlex_'+shipData.handler.toLowerCase(),data:shipData}).appendTo($target);
							}
						else if(provider == 'FEDEX' && !shipData.meter)	{
//the fedex account has not been registered through us yet. show reg form.
							$target.anycontent({'templateID':'shippingFedExRegTemplate',data:{}});
							}
						else if(provider == 'UPS' && !shipData.shipper_number)	{
//the UPS account has not been registered through us yet. show reg form.
							$target.anycontent({'templateID':'shippingUPSOnlineToolsRegTemplate',data:{}});
							}
						
						else if(provider == 'FEDEX' || provider == 'UPS' || provider == 'USPS')	{
							$target.closest('form').find('.buttonset').show();
							$target.anycontent({'templateID':'shippingZone_'+provider.toLowerCase(),data:shipData});
							}
						else if(provider == 'INSURANCE' || provider == 'HANDLING')	{
							$target.closest('form').find('.buttonset').show();
							$target.anycontent({'templateID':'shippingGlobal_'+provider.toLowerCase(),data:shipData});
							}
						else	{
							$target.anymessage({'message':'In admin_config.a.showShipMethodEditorByProvider, unrecognized provider ['+provider+'] passed and/or handler for shipping method could not be determined.','gMessage':true,'persistent':true});
							}
						
						}

					$('label :checkbox',$target).anycb();
					$('.toolTip',$target).tooltip();
					app.u.handleAppEvents($target);
					app.ext.admin.u.applyEditTrackingToInputs($target.closest('form'));


					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showShipMethodEditorByProvider, both $target ['+typeof $target+'] and provider ['+provider+'] are required.','gMessage':true});
					}
				
				}, //showShipMethodEditorByProvider
				
				
			showPromotionsManager : function($target)	{
				
				$target.empty().anycontent({'templateID':'promotionsPageTemplate','showLoading':false});
				$("[data-app-role='promotionsTabContainer']",$target).anytabs();
				
				var $table = app.ext.admin.i.DMICreate($("[data-anytab-content='coupon']",$target),{
					'header' : '', //left off because the interface is in a tab.
					'className' : 'couponManager',
					'controls' : "",
					'buttons' : ["<button data-app-event='admin_config|couponCreateShow'>Add Coupon<\/button>"],
					'thead' : ['','Enabled','Code','Title','Created','Begins','Expires',''],
//					'controls' : "<form action='#' onsubmit='return false'><label>Product ID: <input type='search' name='PID' \/><\/label><button>Search<\/button><\/form>",
					'tbodyDatabind' : "var: users(@COUPONS); format:processList; loadsTemplate:couponsResultsRowTemplate;"
					});

				if($table)	{
					app.ext.admin.calls.adminConfigDetail.init({'coupons':true},{'datapointer':'adminConfigDetail|coupons|'+app.vars.partition,'callback':'anycontent','jqObj':$table},'mutable');
					app.model.dispatchThis();
					}
				else	{} //buildDualMode will handle the error display.

/*				
				var $promoTable = app.ext.admin.i.DMICreate($("[data-anytab-content='coupon']",$target),{
					'header' : 'Coupons',
					'className' : 'couponManager',
					'controls' : "",
					'buttons' : ["<button data-app-event='admin_customer|couponCreateShow'>Add Coupon<\/button>"],
					'thead' : ['','Enabled','Code','Title','Created','Begins','Expires',''],
//					'controls' : "<form action='#' onsubmit='return false'><label>Product ID: <input type='search' name='PID' \/><\/label><button>Search<\/button><\/form>",
					'tbodyDatabind' : "var: users(@COUPONS); format:processList; loadsTemplate:couponsResultsRowTemplate;"
					});

				if($promoTable)	{
					app.ext.admin.calls.adminProductReviewList.init({'filter':'UNAPPROVED'},{'callback':'anycontent','jqObj':$promoTable},'mutable');
					app.model.dispatchThis();
					}
				else	{} //buildDualMode will handle the error display.
*/


				},//showPromotionsManager
			
			showRulesBuilderInModal : function(vars)	{
				vars = vars || {};

				if(vars.table && ((vars.rulesmode == 'shipping' && vars.provider) || vars.rulesmode == 'coupons'))	{



var $D = app.ext.admin.i.dialogCreate({
	'title' : 'Rules Builder',
	'dataAttribs' : {'data-table':vars.table,'rulesmode' : vars.rulesmode}
	});

$D.dialog('option','buttons',[ 
	{text: 'Cancel', click: function(){
		$D.dialog('close');
		if(typeof vars.closeFunction === 'function')	{
			vars.closeFunction($(this));
			}
		}}	
	]);
$D.dialog('open');

//these will be tailored based on which set of rules is showing up, then passed into the DMICreate function.
var DMIVars = {
	'header' : 'Rules Editor'
	}; 

//set the mode specific variables for DMI create and add any 'data' attribs to the modal, if necessary.
if(vars.rulesmode == 'shipping')	{
	DMIVars.thead = ['Code','Name','Created','Exec','Match','Schedule','Value'];
	DMIVars.tbodyDatabind = 'var: rules(@RULES); format:processList; loadsTemplate:ruleBuilderRowTemplate_shipping;';
	DMIVars.showLoading = true; //need to get schedules before allowing use of interface.
	$D.attr('provider',vars.provider);
	}
else if(vars.rulesmode == 'coupons')	{
	DMIVars.thead = ['Code','Name','Created','Expires'];
	DMIVars.showLoading = false; //There's no data request required. this allows immediate editing.
	DMIVars.tbodyDatabind = 'var: rules(@RULES); format:processList; loadsTemplate:ruleBuilderRowTemplate_coupons;'
	}
else	{}

var $DMI = app.ext.admin.i.DMICreate($D,DMIVars);
//
$("[data-app-role='dualModeListContents']",$D).sortable().on("sortupdate",function(evt,ui){
	ui.item.addClass('edited');
	app.ext.admin.u.handleSaveButtonByEditedClass(ui.item.closest('form'));
	});
app.u.handleAppEvents($D);


if(vars.rulesmode == 'shipping')	{
//need pricing schedules. This is for shipping.
	app.ext.admin.calls.adminWholesaleScheduleList.init({},'mutable');
	app.ext.admin.calls.adminConfigDetail.init({'shipmethods':true},{datapointer : 'adminConfigDetail|shipmethods|'+app.vars.partition,callback : function(rd){
		$D.hideLoading();
		if(app.model.responseHasErrors(rd)){
			$D.anymessage({'message':rd});
			}
		else	{
			$D.anycontent({'data':app.ext.admin_config.u.getShipMethodByProvider(vars.provider)});
			}
		}},'mutable');
	app.model.dispatchThis('mutable');

	}
else if(vars.rulesmode == 'coupons')	{

	}
else	{
	 //should never get here. if statement above accounts for mode being shipping or coupons. failsafe.
	$('#globalMessaging').anymessage({'message':'In admin_config.a.showRulesBuilderInModal, rulesmode value is not valid ['+vars.rulesmode+']. must be shipping or coupons','gMessage':true});
	}

					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showRulesBuilderInModal, invalid/no mode ['+vars.rulesmode+'] was passed or a required param based on mode was not set. see console for vars.','gMessage':true});
					app.u.dump("admin_config.a.showRulesBuilderInModal vars: "); app.u.dump(vars);
					}

				}, //showRulesBuilderInModal


			showUPSOnlineToolsRegInModal : function(vars)	{
vars = vars || {}; //may include supplier
var $D = $("<div \/>").attr('title',"Apply for UPS onLine Tools / Change Shipper Number")
$D.anycontent({'templateID':'shippingUPSOnlineToolsRegTemplate','data':{},'dataAttribs' : vars });
$D.dialog({
	width : '90%',
	modal: true,
	autoOpen: false,
	close: function(event, ui)	{
		$(this).dialog('destroy').remove();
		}
	});
app.u.handleAppEvents($D);
$D.dialog('open');	
				},
			
			showFedExMeterInModal : function(vars)	{
vars = vars || {}; //may include supplier
var $D = app.ext.admin.i.dialogCreate({'title':'Renew FedEx Meter','templateID':'shippingFedExRegTemplate','data':app.ext.admin_config.u.getShipMethodByProvider('FEDEX')});
app.u.handleAppEvents($D);
$D.addClass('labelsAsBreaks alignedLabels');
$D.dialog('open');	
				}

			}, //Actions

////////////////////////////////////   RENDERFORMATS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		renderFormats : {
			blacklistedCountries : function($tag,data)	{
				if(data.bindData.loadsTemplate)	{
					for(var i in data.value)	{
						$tag.append(app.renderFunctions.transmogrify({'country':data.value[i]},data.bindData.loadsTemplate,{'country':data.value[i]}));
						}
					}
				else	{
					$tag.anymessage({'message':'Unable to render list item - no loadsTemplate specified.','persistent':true});
					}
				}
			}, //renderFormats

////////////////////////////////////   UTIL [u]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		u : {

			getPaymentByTender : function(tender)	{
				var r = false; //returns false if an error occurs. If no error, either an empty object OR the payment details are returned.
				if(tender)	{
					if(app.data['adminConfigDetail|payment|'+app.vars.partition] && app.data['adminConfigDetail|payment|'+app.vars.partition]['@PAYMENTS'])	{
						r = {};
						var payments = app.data['adminConfigDetail|payment|'+app.vars.partition]['@PAYMENTS'], //shortcut
						L = payments.length;
						
						for(var i = 0; i < L; i += 1)	{
							if(payments[i].tender == tender)	{
								r = payments[i];
								break; //have a match. exit early.
								}
							}
						}
					else	{
						$('#globalMessaging').anymessage({'message':'In admin_config.u.getPaymentByTender, adminConfigDetail|payment|'+app.vars.partition+' not in memory and is required.','gMessage':true});
						}
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.u.getPaymentByTender, no tender passed.','gMessage':true});
					}
				return r;
				},

			getShipMethodByProvider : function(provider)	{
				var r = false; //returns false if an error occurs. If no error, either an empty object OR the payment details are returned.
				if(provider)	{
					if(app.data['adminConfigDetail|shipmethods|'+app.vars.partition] && app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'])	{
						r = {};
						var
							shipmethods = app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'], //shortcut
							L = shipmethods.length;
						
						for(var i = 0; i < L; i += 1)	{
							if(shipmethods[i].provider == provider)	{
								r = shipmethods[i];
								break; //have a match. exit early.
								}
							}
						}
					else	{
						$('#globalMessaging').anymessage({'message':'In admin_config.u.getShipMethodByProvider, adminConfigDetail|shipmethods not in memory and is required.','gMessage':true});
						}
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.u.getShipMethodByProvider, no provider passed.','gMessage':true});
					}
				return r;
				}
			
			}, //u [utilities]

//this is used in conjunction w/ admin.a.processForm.
//in the form, set _tag/macrobuilder='extension/name' where name is the name of the function in mb. should be same or derive from macro cmd.
		macrobuilders : {
			
			"GLOBAL/ACCOUNT" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 
				delete sfo._tag; //removed from original object so serialization into key value pair string doesn't include it.
				delete sfo._macrobuilder;
				newSfo['@updates'].push("GLOBAL/ACCOUNT?"+$.param(sfo));
//				app.u.dump(" -> newSfo:"); app.u.dump(newSfo);
				return newSfo;
				},
// !!! Update this to match the macro name.
			"couponUpdate" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 				
				
				return newSfo;
				},
// !!! Update this to match the macro name.
			"couponCreate" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 				
				
				return newSfo;
				}
			},


////////////////////////////////////   EVENTS [e]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

		e : {
			
			
			couponDetailDMIPanel : function($btn)	{
				$btn.button({icons: {primary: "ui-icon-pencil"},text: false});
				$btn.off('click.couponDetailDMIPanel').on('click.couponDetailDMIPanel',function(event){
					event.preventDefault();
					var couponCode = $btn.closest('tr').data('code');
					
					var $panel = app.ext.admin.i.DMIPanelOpen($btn,{
						'templateID' : 'couponAddUpdateContentTemplate',
						'panelID' : 'coupon_'+couponCode,
						'header' : 'Edit Coupon: '+couponCode,
						'handleAppEvents' : true,
						'data' : app.data['adminConfigDetail|coupons|'+app.vars.partition]['@COUPONS'][$btn.closest('tr').data('obj_index')]
						});

					$('form',$panel)
						.append("<input type='hidden' name='_macrobuilder' value='admin_config|couponUpdate' /><input type='hidden' name='_tag/callback' value='DMIUpdateResults' /><input type='hidden' name='_tag/message' value='The coupon has been successfully updated.' />")
					 	.find(".applyDatepicker").datepicker({
							changeMonth: true,
							changeYear: true,
							dateFormat : 'yymmdd'
							});
					});
				},

			couponCreateShow : function($btn)	{

				$btn.button();
				$btn.off('click.couponCreateShow').on('click.couponCreateShow',function(event){

					event.preventDefault();
					var $D = app.ext.admin.i.dialogCreate({
						'title':'Add New Coupon',
						'templateID':'couponAddUpdateContentTemplate',
						'showLoading':false //will get passed into anycontent and disable showLoading.
						});
					$D.dialog('open');
//These fields are used for processForm on save.
					$('form',$D).first().append("<input type='hidden' name='_macrobuilder' value='admin_config|couponCreate' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/jqObjEmpty' value='true' /><input type='hidden' name='_tag/message' value='Thank you, your review has been created.' />");
					 $( ".applyDatepicker",$D).datepicker({
						changeMonth: true,
						changeYear: true,
						dateFormat : 'yymmdd'
						});
					});
				},	
			
			showCCSuppInputs : function($ele)	{
				$ele.off('change.showCCSuppInputs').on('change.showCCSuppInputs',function(){
					var
						gateway = $ele.val(),
						$suppContainer = $("[data-app-role='providerSpecificInputs']",$ele.closest('form'));
					$suppContainer.empty();
//the contents are emptied rather than having several hidden fieldsets so that no extra/unnecesary data is sent on the post (and no white/blacklisting needs to be done).
					if(gateway != 'TESTING' && gateway != 'NONE')	{
						$suppContainer.anycontent({'data':{},'templateID':'paymentSuppInputsTemplate_'+gateway.toLowerCase()});
						}
					});
				$ele.trigger('change.showCCSuppInputs'); //trigger the change to show the selected fieldset (for initial load)
				}, //showCCSuppInputs

//this is applied to the 'add flex method' shipping button.  It adds the dropdown for choosing the method type and also the click events.
			handleAddShipment : function($ele)	{
				var
					$menu = $ele.next('ul'),
					$pageContainer = $ele.closest("[data-app-role='slimLeftContainer']");
					
				$menu.menu().hide().css({'width':'200','position':'absolute'});
				$('button:first',$ele).button().off('click.handleAddShipment').on('click.handleAddShipment',function(){
					$(this).next('button').trigger('click'); //trigger the dropdown on the down arrow button.
					});
				$('button:last',$ele).button({text: false,icons: {primary: "ui-icon-triangle-1-s"}}).off('click.handleAddShipment').on('click.handleAddShipment',function(){
					//show the menu for selecting what type of flex method.
					$menu.show().position({
						my: "right top",
						at: "right bottom",
						of: this
						});
//hide the menu if the doc is clicked anywhere else. add w/ timeout so initial 'click' doesn't trigger the one.click.
					setTimeout(function(){
						$( document ).one( "click", function() {
							$menu.hide();
							});
						},500);

					});
				$ele.buttonset();
				
				$('a',$menu).each(function(){
					var $a = $(this);
//					app.u.dump("$a.data('shipmethod'): "+$a.data('shipmethod'));
					$a.on('click',function(event){
						event.preventDefault();
						app.u.dump(" -> add new "+$a.data('shipmethod')+" shipmethod");
						$("h3.heading:first",$pageContainer).text("Add New Flex Shipmethod: "+$a.text());
						app.ext.admin_config.a.showAddFlexShipment($a.data('shipmethod'),$("[data-app-role='slimLeftContent']:first",$pageContainer));
						});
					});
				
				}, //handleAddShipment

			shippingPartnerRegExec : function($btn)	{
				$btn.button();
				$btn.off('click.shippingPartnerRegExec').on('click.shippingPartnerRegExec',function(){
					var $form = $btn.closest('form');
					if(app.u.validateForm($form))	{
						
						var sfo = $form.serializeJSON({'cb':true});
					//supplier 'may' be set on the parent container. This is used in supply chain.
						if($btn.closest("[data-app-role='shippingPartnerRegContainer']").data('supplier'))	{
							sfo.supplier = $btn.closest("[data-app-role='shippingPartnerRegContainer']").data('supplier');
							}
						
						if(sfo.provider == 'FEDEX' || sfo.provider == 'UPS')	{
							$form.showLoading({'message':'Registering account. This may take a few moments.'});
							var macroCmd = (sfo.provider == 'FEDEX') ? "FEDEX-REGISTER" : "UPSAPI-REGISTER";
							app.ext.admin.calls.adminConfigMacro.init(["SHIPMETHOD/"+macroCmd+"?"+$.param(sfo)],{'callback':function(rd){
								$form.hideLoading();
								if(app.model.responseHasErrors(rd)){
									$form.anymessage({'message':rd});
									}
								else	{
									$form.empty().anymessage(app.u.successMsgObject('Activation successful!'));
									}
								}},'immutable');
							app.model.dispatchThis('immutable');

							}
						else	{
							$form.anymessage({"message":"In admin_config.e.shippingPartnerRegExec, unable to ascertain provider. Was expecting it in the serialized form.","gMessage":true});
							}
						}
					else	{} //validateForm handles error display.
					});
				},

			shippingGeneralUpdateExec : function($btn)	{
				$btn.button();
				$btn.off('click.shippingGeneralUpdateExec').on('click.shippingGeneralUpdateExec',function(){
					var $form = $btn.closest('form');
					if(app.u.validateForm($form))	{
						var macros = new Array();
						macros.push("SHIPPING/CONFIG?"+$.param($form.serializeJSON({'cb':true})));

//if any new bans have occured, update the list.
						var $bannedContainer = $("[data-app-role='bannedlistContainer']",$form);
						if($bannedContainer.find('.edited').length)	{
							macros.push("SHIPPING/BANNEDTABLE-EMPTY");
							var countries = "";
							$('tbody tr',$bannedContainer).each(function(){
								var $tr = $(this);
								if($(this).hasClass('rowTaggedForRemove'))	{} //row is being deleted. do not add. first macro clears all, so no specific remove necessary.
								else	{
									macros.push("SHIPPING/BANNEDTABLE-INSERT?match="+$tr.data('match')+"&type="+$tr.data('type'));
									}
								});
							}
// COUNTRIES!
//if any changes have occured to the blacklisted countries, update the list.
						var $blacklistContainer = $("[data-app-role='blacklistContainer']",$form);
						if($blacklistContainer.find('.edited').length)	{
							var blacklistMacro = "SHIPPING/CONFIG?blacklist="
							$('tbody tr',$blacklistContainer).each(function(){
								if($(this).hasClass('rowTaggedForRemove'))	{} //row is being deleted. do not add. first macro clears all, so no specific remove necessary.
								else	{
									blacklistMacro += $(this).data('country')+',';
									}
								});
							macros.push(blacklistMacro);
							}
//						app.u.dump("macros: "); app.u.dump(macros);
						app.ext.admin.calls.adminConfigMacro.init(macros,{'callback':'showMessaging','jqObj':$form,'message':'Your changes have been saved.'},'immutable');
						app.model.destroy('adminConfigDetail|shipping|'+app.vars.partition);
						app.ext.admin.calls.adminConfigDetail.init({'shipping':true},{datapointer : 'adminConfigDetail|shipping|'+app.vars.partition},'immutable');
						app.model.dispatchThis('immutable');


						}
					else	{} //validateForm handles error display
					});
				},

			paymentMethodUpdateExec : function($btn)	{
				$btn.button();
				$btn.off('click.paymentMethodUpdateExec').on('click.paymentMethodUpdateExec',function(){
					app.u.dump(" -> BEGIN click.paymentMethodUpdateExec (admin_config).");
					var
						$form = $btn.closest('form'),
						sfo = $form.serializeJSON({'cb':true}) || {},
						macroCmd;
					
					if(sfo.tender && sfo.tenderGroup)	{
						
						app.u.dump(" -> tender: "+sfo.tender);
						app.u.dump(" -> tenderGroup: "+sfo.tenderGroup);
						
						if(app.u.validateForm($form))	{
							if(sfo.tenderGroup == 'WALLET')	{
								macroCmd = "PAYMENT/WALLET-"+sfo.tender;
								}
							else	{
								macroCmd = "PAYMENT/"+sfo.tenderGroup;
								}
							app.u.dump(" -> macroCmd: "+macroCmd);
							app.ext.admin.calls.adminConfigMacro.init([macroCmd+"?"+$.param(sfo)],{'callback':'showMessaging','message':'Payment has been updated.','jqObj':$form},'immutable');
					
							app.model.destroy('adminConfigDetail|payment|'+app.vars.partition);
							app.ext.admin.calls.adminConfigDetail.init({'payment':true},{datapointer : 'adminConfigDetail|payment|'+app.vars.partition},'immutable');
							app.model.dispatchThis('immutable');
							}
						else	{app.u.dump("Did not pass validation in admin_config.e.paymentMethodUpdateExec");} //validateForm will display the error logic.
						}
					else	{
						$form.anymessage({"message":"In admin_config.e.paymentMethodUpdateExec, either tender ["+sfo.tender+"] or tenderGroup ["+sfo.tenderGroup+"] not set. Expecting these within the form/sfo.","gMessage":true});
						}
					});
				},

//this is a generic button for use on a update macro.  For simple ones, like company information. Anything more complicated like shipping or tax will need a custom handler.
/*
NOT COMPLETED YET
			adminConfigMacroExec : function($btn)	{
				$btn.button();
				$btn.off('click.adminConfigMacroExec').on('click.adminConfigMacroExec',function(){
var $form = $btn.closest('form');
if($form.data('macroCmd'))	{
	if(app.u.validateForm($form))	{
		$form.showLoading({"Message":"Saving Changes"});
		
		
		}
	else	{} //form validation will handle error display.
	}
else	{
	$form.anymessage();
	}
					});
				},
*/
//This is where the magic happens. This button is used in conjunction with a data table, such as a shipping price or weight schedule.
//It takes the contents of the fieldset it is in and adds them as a row in a corresponding table. it will allow a specific table to be set OR, it will look for a table within the fieldset (using the data-app-role='dataTable' selector).
//the 'or' was necessary because in some cases, such as handling, there are several tables on one page and there wasn't a good way to pass different params into the appEvent handler (which gets executed once for the entire page).
// $form = the parent form of the data table. It's used for updating the corresponding 'save' button w/ the number of changes.
// $dataTbody = the tbody of the dataTable to be updated (where rows get added when the entry form is saved).
// $container = the fieldset (or some other element) that contains the form inputs used to generate a new row. NOT always it's own form.
			dataTableAddExec : function($btn,vars)	{
				$btn.button();
				$btn.off('click.dataTableAddExec').on('click.dataTableAddExec',function(event){
event.preventDefault();

app.u.dump("BEGIN admin_config.e.dataTableAddExec");

var
	$container = vars['$container'] ? vars['$container'] : $btn.closest('fieldset'),
//tbody can be passed in thru vars or, if not passed, it will look for one within the fieldset. rules engine uses vars approach. shipping doesn't. same for form.
	$dataTbody = (vars['$dataTbody']) ? vars['$dataTbody'] : $("[data-app-role='dataTable'] tbody",$container),
	$form = (vars['$form']) ? vars['$form'] : $container.closest('form');


if($container.length && $dataTbody.length && $dataTbody.data('bind'))	{
	app.u.dump(" -> all necessary jquery objects found. databind set on tbody.");
//none of the table data inputs are required because they're within the parent 'edit' form and in that save, are not required.
//so temporarily make inputs required for validator. then unrequire them at the end. This feels very dirty.
//	$('input',$container).attr('required','required'); 
	if(app.u.validateForm($container))	{
		app.u.dump(" -> form is validated.");
		var 
			bindData = app.renderFunctions.parseDataBind($dataTbody.attr('data-bind')),
			sfo = $container.serializeJSON(),
			$tr = app.renderFunctions.createTemplateInstance(bindData.loadsTemplate,sfo);
		
		app.u.dump(" -> sfo: "); app.u.dump(sfo);
		
		$tr.anycontent({data:sfo});
		$tr.addClass('edited');
		$tr.addClass('isNewRow'); //used in the 'save'. if a new row immediately gets deleted, it isn't added.

//if a row already exists with this guid, this is an UPDATE, not an ADD.
		if(sfo.guid && $("tr[data-guid='"+sfo.guid+"']",$dataTbody).length)	{
			$("tr[data-guid='"+sfo.guid+"']",$dataTbody).replaceWith($tr);
			}
		else	{
			$tr.appendTo($dataTbody);
			}
		app.u.handleAppEvents($tr);
//this function will look for .edited in the form and, if present, enable and update the save button.
		app.ext.admin.u.handleSaveButtonByEditedClass($form);
		}
	else	{
		app.u.dump("form did not validate");
		//validateForm handles error display.
		}
//	$('input',$container).attr('required','').removeAttr('required');
	
	}
else	{
	$btn.closest('form').anymessage({"message":"In admin_config.e.dataTableAddExec, unable to ascertain container ["+$container.length+"], tbody for data table or that tbody ["+$dataTbody.length+"] has no bind-data.","gMessage":true});<commit_msg>admin config - enhancement to dataTable feature<commit_after>/* **************************************************************

   Copyright 2013 Zoovy, Inc.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

************************************************************** */



//    !!! ->   TODO: replace 'username' in the line below with the merchants username.     <- !!!

var admin_config = function() {
	var theseTemplates = new Array(
		'paymentManagerPageTemplate',
/*		
		'paymentAvailabilityTemplate',
		'paymentHandlingFeeTemplate',
		'paymentTransferInstructionsTemplate',
		'paymentCCTemplate',
		'paymentEcheckTemplate',
		'paymentWallet_google',
		'paymentWallet_paypalec',
		'paymentWallet_amzcba',
		'paymentSuppInputsTemplate_manual',
		'paymentSuppInputsTemplate_paypalwp',
		'paymentSuppInputsTemplate_verisign',
		'paymentSuppInputsTemplate_authorizenet',
		'paymentSuppInputsTemplate_linkpoint',
		'paymentSuppInputsTemplate_echo',
		'paymentSuppInputsTemplate_skipjack',
*/		
		'shippingManagerPageTemplate',
		'shippingGeneralTemplate',
		'shippingBlacklistTemplate',
/*		
		'shippingZone_fedex',
		'shippingZone_usps',
		'shippingZone_ups',
		
		'shippingGlobal_handling',
		'shippingGlobal_insurance',

		'shippingFlex_shared',
		'shippingFlex_fixed',
		'shippingFlex_local',
		'shippingFlex_local_canada',
		'shippingFlex_free',
		'shippingFlex_simple',
		'shippingFlex_weight',
		'shippingFlex_price',
		
		'shippingLocalRowTemplate',
		'shippingWeightRowTemplate',
		'shippingPriceRowTemplate',
*/		
		'ruleBuilderTemplate',
		'ruleBuilderRowTemplate_shipping',
		'rulesInputsTemplate_shipping',
		
		'contactInformationTemplate',
		'taxConfigTemplate',
		'taxConfigRuleRowTemplate'
		);
	var r = {


////////////////////////////////////   CALLBACKS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\



	callbacks : {
//executed when extension is loaded. should include any validation that needs to occur.
		init : {
			onSuccess : function()	{
				var r = false; //return false if extension won't load for some reason (account config, dependencies, etc).
//the list of templates in theseTemplate intentionally has a lot of the templates left off.  This was done intentionally to keep the memory footprint low. They'll get loaded on the fly if/when they are needed.
				app.model.fetchNLoadTemplates(app.vars.baseURL+'extensions/admin/config.html',theseTemplates);
				r = true;

				return r;
				},
			onError : function()	{
//errors will get reported for this callback as part of the extensions loading.  This is here for extra error handling purposes.
//you may or may not need it.
				app.u.dump('BEGIN admin_orders.callbacks.init.onError');
				}
			}
		}, //callbacks



////////////////////////////////////   ACTION    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		a : {
			showPaymentManager : function($target)	{
				$target.showLoading({'message':'Fetching your Active Payment Methods'});
				app.model.destroy('adminConfigDetail|payment|'+app.vars.partition);
				app.ext.admin.calls.adminConfigDetail.init({'payment':true},{datapointer : 'adminConfigDetail|payment|'+app.vars.partition,callback : function(rd){
					if(app.model.responseHasErrors(rd)){
						$('#globalMessaging').anymessage({'message':rd});
						}
					else	{
						$target.hideLoading();
						$target.anycontent({'templateID':'paymentManagerPageTemplate',data:{}});
						app.u.handleAppEvents($target);
						
						var
							$leftColumn = $("[data-app-role='slimLeftNav']",$target),
							$contentColumn = $("[data-app-role='slimLeftContent']",$target);
						
						$leftColumn.find('li').each(function(){
							var $li = $(this);
							$li.addClass('ui-corner-none pointer').on('click',function(){
								$('.ui-state-focus',$leftColumn).removeClass('ui-state-focus');
								$li.addClass('ui-state-focus');
								$("[data-app-role='slimLeftContentSection'] .heading",$target).text("Edit: "+$li.text());
								app.u.handleAppEvents($contentColumn); //handles app events outside the content area.
								app.ext.admin_config.a.showPaymentTypeEditorByTender($li.data('tender'),$contentColumn);
								});
							});
						}
					}},'mutable');
				app.model.dispatchThis('mutable');
				},
			
			showPaymentTypeEditorByTender : function(tender,$target){
//				app.u.dump("BEGIN showPaymentTypeEditorByTender ["+tender+"]");
				if(tender && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset:first').show().find('button').button('disable').find('.numChanges').text("");
					var payData = app.ext.admin_config.u.getPaymentByTender(tender);
//					app.u.dump(" -> payData: "); app.u.dump(payData);
					$target.append($("<input \/>",{'name':'tender','type':'hidden'}).val(tender));
					switch(tender){
/* offline payment types */
						case 'CASH':
						case 'GIFTCARD':
						case 'PO':
						case 'MO':
						case 'PICKUP':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$target.anycontent({'templateID':'paymentAvailabilityTemplate',data : payData});
							break;
						
						
						case 'CHECK':
						case 'COD':
						case 'CHKOD':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentHandlingFeeTemplate',data : payData}).appendTo($target);
							break;
						
						case 'WIRE':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('OFFLINE'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentHandlingFeeTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentTransferInstructionsTemplate',data : payData}).appendTo($target);
						
							break;

/* gateways */
						case 'ECHECK':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('GATEWAY'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentEcheckTemplate',data : payData}).appendTo($target);
							break;

						case 'CC':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('GATEWAY'));
							$("<div \/>").anycontent({'templateID':'paymentAvailabilityTemplate',data : payData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'paymentCCTemplate',data : payData}).appendTo($target);
							break;


/* wallets/third party payments */
						case 'GOOGLE':
						case 'PAYPALEC':
						case 'AMZCBA':
							$target.append($("<input \/>",{'name':'tenderGroup','type':'hidden'}).val('WALLET'));
							$target.anycontent({'templateID':'paymentWallet_'+tender.toLowerCase(),data : payData});
							break;


						default:
							$target.anymessage({'message':'In admin_config.a.showPaymentTypeEditorByTender, unrecognized tender: '+tender+'.','gMessage':true});
						}
					app.u.handleAppEvents($target);
					app.ext.admin.u.applyEditTrackingToInputs($target.closest('form'));
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showPaymentTypeEditorByTender, both $target ['+typeof $target+'] and tender ['+tender+'] are required.','gMessage':true});
					}
				}, //showPaymentTypeEditorByTender
				
			showContactInformation : function($target)	{
				$target.showLoading({'message':'Fetching Contact Details'});
//				app.model.destroy('adminConfigDetail|account|'+app.vars.partition);
				app.ext.admin.calls.adminConfigDetail.init({'account':true},{'templateID':'contactInformationTemplate','datapointer' : 'adminConfigDetail|account|'+app.vars.partition, 'callback' : 'anycontent','jqObj':$target},'mutable');
				app.model.dispatchThis('mutable');
				},
		
			showTaxConfig : function($target)	{
				$target.empty().showLoading({'message':'Fetching Tax Details'});
				var datapointer = 'adminConfigDetail|taxes|'+app.vars.partition
				app.model.destroy(datapointer);
				app.ext.admin.calls.adminConfigDetail.init({'taxes':true},{'datapointer' : datapointer, 'callback' : function(rd){
if(app.model.responseHasErrors(rd)){
	$('#globalMessaging').anymessage({'message':rd});
	}
else	{
	$target.hideLoading();
	$target.anycontent({'templateID':'taxConfigTemplate','datapointer':rd.datapointer});
	
	$('.gridTable',$target).anytable();
	$('.toolTip',$target).tooltip();
	$(':checkbox',$target).anycb();
	$("[name='expires']",$target).datepicker({
		changeMonth: true,
		changeYear: true,
		minDate: 0,
		dateFormat : "yymmdd"
		});
	
	app.u.handleAppEvents($target,{'$form':$("[data-app-role='taxTableExecForm']",$target),'$container':$("[data-app-role='taxTableInputForm']",$target),'$dataTbody':$("[data-app-role='dataTableTbody']",$target)});
	}

					}},'mutable');
				app.model.dispatchThis('mutable');
				}, //showContactInformation
			
			showShippingManager : function($target)	{
				$target.showLoading({'message':'Fetching your Active Shipping Methods'});
				
				app.model.destroy('adminConfigDetail|shipping|'+app.vars.partition);
				app.model.destroy('adminConfigDetail|shipmethods|'+app.vars.partition);
				app.ext.admin.calls.appResource.init('shipcountries.json',{},'mutable');
				app.ext.admin.calls.adminConfigDetail.init({'shipping':true},{datapointer : 'adminConfigDetail|shipping|'+app.vars.partition},'mutable');
				app.ext.admin.calls.adminConfigDetail.init({'shipmethods':true},{datapointer : 'adminConfigDetail|shipmethods|'+app.vars.partition,callback : function(rd){
					if(app.model.responseHasErrors(rd)){
						$target.hideLoading();
						$('#globalMessaging').anymessage({'message':rd});
						}
					else	{
						
						$target.anycontent({
							'templateID':'shippingManagerPageTemplate',
							'data':$.extend(true,{},app.data['adminConfigDetail|shipping|'+app.vars.partition],app.data['adminConfigDetail|shipmethods|'+app.vars.partition])
							});

						var shipmethods = new Array();
						if(app.data['adminConfigDetail|shipmethods|'+app.vars.partition] && app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'])	{
							shipmethods = app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'];
							}

						var
							L = shipmethods.length,
							$flexUL = $("[data-app-role='shipMethodsByFlex']",$target);
//genrate the list of flex methods.
//disabled methods will get a class to help indicate they're disabled.
						for(var i = 0; i < L; i += 1)	{
							if(shipmethods[i].provider.indexOf('FLEX:') === 0)	{
//								app.u.dump("shipmethods[i].enabled: "+shipmethods[i].enable);
								$("<li \/>").data('provider',shipmethods[i].provider).text(shipmethods[i].name).appendTo($flexUL).addClass((shipmethods[i].enable == 1) ? '' :'opacity50');
								}
							}
						
						
						
						app.u.handleAppEvents($target);
						
						var
							$leftColumn = $("[data-app-role='slimLeftNav']",$target),
							$contentColumn = $("[data-app-role='slimLeftContent']",$target);

//add classes to fedex,ups and usps to indicate they are enabled/disabled.
						
//						$("[data-provider='FEDEX']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('FEDEX')['enable'] == 1 ? '' : 'opacity50');
//						$("[data-provider='UPS']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('UPS')['enable'] == 1 ? '' : 'opacity50');
//						$("[data-provider='USPS']",$leftColumn).addClass(app.ext.admin_config.u.getShipMethodByProvider('USPS')['enable'] == 1 ? '' : 'opacity50');
						
 
						$("[data-app-role='shipMethodsByZone']:first, [data-app-role='shipMethodsGlobal']:first, [data-app-role='shipMethodsByFlex']:first",$leftColumn).find('li').each(function(){
							var $li = $(this);
							$li.addClass('ui-corner-none pointer').on('click',function(){
								$('.ui-state-focus',$leftColumn).removeClass('ui-state-focus');
								$li.addClass('ui-state-focus');
								$("[data-app-role='slimLeftContentSection'] .heading",$target).text("Edit: "+$li.text());
								app.ext.admin_config.a.showShipMethodEditorByProvider($li.data('provider'),$contentColumn)
								
								});
							});
						
						app.ext.admin_config.a.showShipMethodEditorByProvider('GENERAL',$contentColumn);
						
						}
					}},'mutable');
				app.model.dispatchThis('mutable');
				}, //showShippingManager

			showAddFlexShipment : function(shipmethod,$target)	{
				if(shipmethod && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset:first').hide() //this contains the buttons for the editor. create has it's own button.
					$("<div \/>").anycontent({'templateID':'shippingFlex_shared',data:{'provider':"FLEX:"+shipmethod+"_"+Math.round(+new Date()/1000)}}).appendTo($target);
					$("[data-app-role='rulesFieldset']",$target).hide(); //disallow rule creation till after ship method is created.
					$target.append("<p><b>Once you save the ship method, more specific inputs and rules will be available.<\/b><\/p>");
					$target.append("<button data-app-event='admin_config|shipmethodAddUpdateExec'>save<\/button>");
//					$("<div \/>").anycontent({'templateID':'shippingFlex_'+shipmethod.toLowerCase(),data:{}}).appendTo($target);
					app.u.handleAppEvents($target,{'handler':shipmethod,'mode':'insert'});
					}
				else if($target)	{
					$target.anymessage({'message':'In admin_config.a.showAddFlexShipment, shipmethod not passed.','gMessage':true});
					}
				else	{
					$("#globalMessaging").anymessage({'message':'In admin_config.a.showAddFlexShipment, shipmethod and target not passed.','gMessage':true});
					}
				}, //showAddFlexShipment

			showShipMethodEditorByProvider : function(provider,$target)	{
				
				if(provider && $target)	{
					$target.empty();
					$target.closest('form').find('.buttonset').hide(); //turn this off always. turn on when needed.
					
					if(provider == 'GENERAL')	{
						$target.anycontent({
							'templateID':'shippingGeneralTemplate',
							'data':$.extend(true,{},app.data['adminConfigDetail|shipping|'+app.vars.partition],app.data['adminConfigDetail|shipmethods|'+app.vars.partition],app.data['appResource|shipcountries.json'])
							});
						}
					else	{
						var shipData = app.ext.admin_config.u.getShipMethodByProvider(provider);
						
						app.ext.admin.u.handleSaveButtonByEditedClass($target.closest('form')); //reset the save button.
						
						if(provider.indexOf('FLEX:') === 0 && shipData.handler)	{
							$target.closest('form').find('.buttonset').show();
							$("<div \/>").anycontent({'templateID':'shippingFlex_shared',data:shipData}).appendTo($target);
							$("<div \/>").anycontent({'templateID':'shippingFlex_'+shipData.handler.toLowerCase(),data:shipData}).appendTo($target);
							}
						else if(provider == 'FEDEX' && !shipData.meter)	{
//the fedex account has not been registered through us yet. show reg form.
							$target.anycontent({'templateID':'shippingFedExRegTemplate',data:{}});
							}
						else if(provider == 'UPS' && !shipData.shipper_number)	{
//the UPS account has not been registered through us yet. show reg form.
							$target.anycontent({'templateID':'shippingUPSOnlineToolsRegTemplate',data:{}});
							}
						
						else if(provider == 'FEDEX' || provider == 'UPS' || provider == 'USPS')	{
							$target.closest('form').find('.buttonset').show();
							$target.anycontent({'templateID':'shippingZone_'+provider.toLowerCase(),data:shipData});
							}
						else if(provider == 'INSURANCE' || provider == 'HANDLING')	{
							$target.closest('form').find('.buttonset').show();
							$target.anycontent({'templateID':'shippingGlobal_'+provider.toLowerCase(),data:shipData});
							}
						else	{
							$target.anymessage({'message':'In admin_config.a.showShipMethodEditorByProvider, unrecognized provider ['+provider+'] passed and/or handler for shipping method could not be determined.','gMessage':true,'persistent':true});
							}
						
						}

					$('label :checkbox',$target).anycb();
					$('.toolTip',$target).tooltip();
					app.u.handleAppEvents($target);
					app.ext.admin.u.applyEditTrackingToInputs($target.closest('form'));


					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showShipMethodEditorByProvider, both $target ['+typeof $target+'] and provider ['+provider+'] are required.','gMessage':true});
					}
				
				}, //showShipMethodEditorByProvider
				
				
			showPromotionsManager : function($target)	{
				
				$target.empty().anycontent({'templateID':'promotionsPageTemplate','showLoading':false});
				$("[data-app-role='promotionsTabContainer']",$target).anytabs();
				
				var $table = app.ext.admin.i.DMICreate($("[data-anytab-content='coupon']",$target),{
					'header' : '', //left off because the interface is in a tab.
					'className' : 'couponManager',
					'controls' : "",
					'buttons' : ["<button data-app-event='admin_config|couponCreateShow'>Add Coupon<\/button>"],
					'thead' : ['','Enabled','Code','Title','Created','Begins','Expires',''],
//					'controls' : "<form action='#' onsubmit='return false'><label>Product ID: <input type='search' name='PID' \/><\/label><button>Search<\/button><\/form>",
					'tbodyDatabind' : "var: users(@COUPONS); format:processList; loadsTemplate:couponsResultsRowTemplate;"
					});

				if($table)	{
					app.ext.admin.calls.adminConfigDetail.init({'coupons':true},{'datapointer':'adminConfigDetail|coupons|'+app.vars.partition,'callback':'anycontent','jqObj':$table},'mutable');
					app.model.dispatchThis();
					}
				else	{} //buildDualMode will handle the error display.

/*				
				var $promoTable = app.ext.admin.i.DMICreate($("[data-anytab-content='coupon']",$target),{
					'header' : 'Coupons',
					'className' : 'couponManager',
					'controls' : "",
					'buttons' : ["<button data-app-event='admin_customer|couponCreateShow'>Add Coupon<\/button>"],
					'thead' : ['','Enabled','Code','Title','Created','Begins','Expires',''],
//					'controls' : "<form action='#' onsubmit='return false'><label>Product ID: <input type='search' name='PID' \/><\/label><button>Search<\/button><\/form>",
					'tbodyDatabind' : "var: users(@COUPONS); format:processList; loadsTemplate:couponsResultsRowTemplate;"
					});

				if($promoTable)	{
					app.ext.admin.calls.adminProductReviewList.init({'filter':'UNAPPROVED'},{'callback':'anycontent','jqObj':$promoTable},'mutable');
					app.model.dispatchThis();
					}
				else	{} //buildDualMode will handle the error display.
*/


				},//showPromotionsManager
			
			showRulesBuilderInModal : function(vars)	{
				vars = vars || {};

				if(vars.table && ((vars.rulesmode == 'shipping' && vars.provider) || vars.rulesmode == 'coupons'))	{



var $D = app.ext.admin.i.dialogCreate({
	'title' : 'Rules Builder',
	'dataAttribs' : {'data-table':vars.table,'rulesmode' : vars.rulesmode}
	});

$D.dialog('option','buttons',[ 
	{text: 'Cancel', click: function(){
		$D.dialog('close');
		if(typeof vars.closeFunction === 'function')	{
			vars.closeFunction($(this));
			}
		}}	
	]);
$D.dialog('open');

//these will be tailored based on which set of rules is showing up, then passed into the DMICreate function.
var DMIVars = {
	'header' : 'Rules Editor'
	}; 

//set the mode specific variables for DMI create and add any 'data' attribs to the modal, if necessary.
if(vars.rulesmode == 'shipping')	{
	DMIVars.thead = ['Code','Name','Created','Exec','Match','Schedule','Value'];
	DMIVars.tbodyDatabind = 'var: rules(@RULES); format:processList; loadsTemplate:ruleBuilderRowTemplate_shipping;';
	DMIVars.showLoading = true; //need to get schedules before allowing use of interface.
	$D.attr('provider',vars.provider);
	}
else if(vars.rulesmode == 'coupons')	{
	DMIVars.thead = ['Code','Name','Created','Expires'];
	DMIVars.showLoading = false; //There's no data request required. this allows immediate editing.
	DMIVars.tbodyDatabind = 'var: rules(@RULES); format:processList; loadsTemplate:ruleBuilderRowTemplate_coupons;'
	}
else	{}

var $DMI = app.ext.admin.i.DMICreate($D,DMIVars);
//
$("[data-app-role='dualModeListContents']",$D).sortable().on("sortupdate",function(evt,ui){
	ui.item.addClass('edited');
	app.ext.admin.u.handleSaveButtonByEditedClass(ui.item.closest('form'));
	});
app.u.handleAppEvents($D);


if(vars.rulesmode == 'shipping')	{
//need pricing schedules. This is for shipping.
	app.ext.admin.calls.adminWholesaleScheduleList.init({},'mutable');
	app.ext.admin.calls.adminConfigDetail.init({'shipmethods':true},{datapointer : 'adminConfigDetail|shipmethods|'+app.vars.partition,callback : function(rd){
		$D.hideLoading();
		if(app.model.responseHasErrors(rd)){
			$D.anymessage({'message':rd});
			}
		else	{
			$D.anycontent({'data':app.ext.admin_config.u.getShipMethodByProvider(vars.provider)});
			}
		}},'mutable');
	app.model.dispatchThis('mutable');

	}
else if(vars.rulesmode == 'coupons')	{

	}
else	{
	 //should never get here. if statement above accounts for mode being shipping or coupons. failsafe.
	$('#globalMessaging').anymessage({'message':'In admin_config.a.showRulesBuilderInModal, rulesmode value is not valid ['+vars.rulesmode+']. must be shipping or coupons','gMessage':true});
	}

					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.a.showRulesBuilderInModal, invalid/no mode ['+vars.rulesmode+'] was passed or a required param based on mode was not set. see console for vars.','gMessage':true});
					app.u.dump("admin_config.a.showRulesBuilderInModal vars: "); app.u.dump(vars);
					}

				}, //showRulesBuilderInModal


			showUPSOnlineToolsRegInModal : function(vars)	{
vars = vars || {}; //may include supplier
var $D = $("<div \/>").attr('title',"Apply for UPS onLine Tools / Change Shipper Number")
$D.anycontent({'templateID':'shippingUPSOnlineToolsRegTemplate','data':{},'dataAttribs' : vars });
$D.dialog({
	width : '90%',
	modal: true,
	autoOpen: false,
	close: function(event, ui)	{
		$(this).dialog('destroy').remove();
		}
	});
app.u.handleAppEvents($D);
$D.dialog('open');	
				},
			
			showFedExMeterInModal : function(vars)	{
vars = vars || {}; //may include supplier
var $D = app.ext.admin.i.dialogCreate({'title':'Renew FedEx Meter','templateID':'shippingFedExRegTemplate','data':app.ext.admin_config.u.getShipMethodByProvider('FEDEX')});
app.u.handleAppEvents($D);
$D.addClass('labelsAsBreaks alignedLabels');
$D.dialog('open');	
				}

			}, //Actions

////////////////////////////////////   RENDERFORMATS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		renderFormats : {
			blacklistedCountries : function($tag,data)	{
				if(data.bindData.loadsTemplate)	{
					for(var i in data.value)	{
						$tag.append(app.renderFunctions.transmogrify({'country':data.value[i]},data.bindData.loadsTemplate,{'country':data.value[i]}));
						}
					}
				else	{
					$tag.anymessage({'message':'Unable to render list item - no loadsTemplate specified.','persistent':true});
					}
				}
			}, //renderFormats

////////////////////////////////////   UTIL [u]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
		u : {

			getPaymentByTender : function(tender)	{
				var r = false; //returns false if an error occurs. If no error, either an empty object OR the payment details are returned.
				if(tender)	{
					if(app.data['adminConfigDetail|payment|'+app.vars.partition] && app.data['adminConfigDetail|payment|'+app.vars.partition]['@PAYMENTS'])	{
						r = {};
						var payments = app.data['adminConfigDetail|payment|'+app.vars.partition]['@PAYMENTS'], //shortcut
						L = payments.length;
						
						for(var i = 0; i < L; i += 1)	{
							if(payments[i].tender == tender)	{
								r = payments[i];
								break; //have a match. exit early.
								}
							}
						}
					else	{
						$('#globalMessaging').anymessage({'message':'In admin_config.u.getPaymentByTender, adminConfigDetail|payment|'+app.vars.partition+' not in memory and is required.','gMessage':true});
						}
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.u.getPaymentByTender, no tender passed.','gMessage':true});
					}
				return r;
				},

			getShipMethodByProvider : function(provider)	{
				var r = false; //returns false if an error occurs. If no error, either an empty object OR the payment details are returned.
				if(provider)	{
					if(app.data['adminConfigDetail|shipmethods|'+app.vars.partition] && app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'])	{
						r = {};
						var
							shipmethods = app.data['adminConfigDetail|shipmethods|'+app.vars.partition]['@SHIPMETHODS'], //shortcut
							L = shipmethods.length;
						
						for(var i = 0; i < L; i += 1)	{
							if(shipmethods[i].provider == provider)	{
								r = shipmethods[i];
								break; //have a match. exit early.
								}
							}
						}
					else	{
						$('#globalMessaging').anymessage({'message':'In admin_config.u.getShipMethodByProvider, adminConfigDetail|shipmethods not in memory and is required.','gMessage':true});
						}
					}
				else	{
					$('#globalMessaging').anymessage({'message':'In admin_config.u.getShipMethodByProvider, no provider passed.','gMessage':true});
					}
				return r;
				}
			
			}, //u [utilities]

//this is used in conjunction w/ admin.a.processForm.
//in the form, set _tag/macrobuilder='extension/name' where name is the name of the function in mb. should be same or derive from macro cmd.
		macrobuilders : {
			
			"GLOBAL/ACCOUNT" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 
				delete sfo._tag; //removed from original object so serialization into key value pair string doesn't include it.
				delete sfo._macrobuilder;
				newSfo['@updates'].push("GLOBAL/ACCOUNT?"+$.param(sfo));
//				app.u.dump(" -> newSfo:"); app.u.dump(newSfo);
				return newSfo;
				},
// !!! Update this to match the macro name.
			"couponUpdate" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 				
				
				return newSfo;
				},
// !!! Update this to match the macro name.
			"couponCreate" : function(sfo)	{
				sfo = sfo || {};
//a new object, which is sanitized and returned.
				var newSfo = {
					'_cmd':'adminConfigMacro',
					'_tag':sfo._tag,
					'@updates':new Array()
					}; 				
				
				return newSfo;
				}
			},


////////////////////////////////////   EVENTS [e]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

		e : {
			
			
			couponDetailDMIPanel : function($btn)	{
				$btn.button({icons: {primary: "ui-icon-pencil"},text: false});
				$btn.off('click.couponDetailDMIPanel').on('click.couponDetailDMIPanel',function(event){
					event.preventDefault();
					var couponCode = $btn.closest('tr').data('code');
					
					var $panel = app.ext.admin.i.DMIPanelOpen($btn,{
						'templateID' : 'couponAddUpdateContentTemplate',
						'panelID' : 'coupon_'+couponCode,
						'header' : 'Edit Coupon: '+couponCode,
						'handleAppEvents' : true,
						'data' : app.data['adminConfigDetail|coupons|'+app.vars.partition]['@COUPONS'][$btn.closest('tr').data('obj_index')]
						});

					$('form',$panel)
						.append("<input type='hidden' name='_macrobuilder' value='admin_config|couponUpdate' /><input type='hidden' name='_tag/callback' value='DMIUpdateResults' /><input type='hidden' name='_tag/message' value='The coupon has been successfully updated.' />")
					 	.find(".applyDatepicker").datepicker({
							changeMonth: true,
							changeYear: true,
							dateFormat : 'yymmdd'
							});
					});
				},

			couponCreateShow : function($btn)	{

				$btn.button();
				$btn.off('click.couponCreateShow').on('click.couponCreateShow',function(event){

					event.preventDefault();
					var $D = app.ext.admin.i.dialogCreate({
						'title':'Add New Coupon',
						'templateID':'couponAddUpdateContentTemplate',
						'showLoading':false //will get passed into anycontent and disable showLoading.
						});
					$D.dialog('open');
//These fields are used for processForm on save.
					$('form',$D).first().append("<input type='hidden' name='_macrobuilder' value='admin_config|couponCreate' /><input type='hidden' name='_tag/callback' value='showMessaging' /><input type='hidden' name='_tag/jqObjEmpty' value='true' /><input type='hidden' name='_tag/message' value='Thank you, your review has been created.' />");
					 $( ".applyDatepicker",$D).datepicker({
						changeMonth: true,
						changeYear: true,
						dateFormat : 'yymmdd'
						});
					});
				},	
			
			showCCSuppInputs : function($ele)	{
				$ele.off('change.showCCSuppInputs').on('change.showCCSuppInputs',function(){
					var
						gateway = $ele.val(),
						$suppContainer = $("[data-app-role='providerSpecificInputs']",$ele.closest('form'));
					$suppContainer.empty();
//the contents are emptied rather than having several hidden fieldsets so that no extra/unnecesary data is sent on the post (and no white/blacklisting needs to be done).
					if(gateway != 'TESTING' && gateway != 'NONE')	{
						$suppContainer.anycontent({'data':{},'templateID':'paymentSuppInputsTemplate_'+gateway.toLowerCase()});
						}
					});
				$ele.trigger('change.showCCSuppInputs'); //trigger the change to show the selected fieldset (for initial load)
				}, //showCCSuppInputs

//this is applied to the 'add flex method' shipping button.  It adds the dropdown for choosing the method type and also the click events.
			handleAddShipment : function($ele)	{
				var
					$menu = $ele.next('ul'),
					$pageContainer = $ele.closest("[data-app-role='slimLeftContainer']");
					
				$menu.menu().hide().css({'width':'200','position':'absolute'});
				$('button:first',$ele).button().off('click.handleAddShipment').on('click.handleAddShipment',function(){
					$(this).next('button').trigger('click'); //trigger the dropdown on the down arrow button.
					});
				$('button:last',$ele).button({text: false,icons: {primary: "ui-icon-triangle-1-s"}}).off('click.handleAddShipment').on('click.handleAddShipment',function(){
					//show the menu for selecting what type of flex method.
					$menu.show().position({
						my: "right top",
						at: "right bottom",
						of: this
						});
//hide the menu if the doc is clicked anywhere else. add w/ timeout so initial 'click' doesn't trigger the one.click.
					setTimeout(function(){
						$( document ).one( "click", function() {
							$menu.hide();
							});
						},500);

					});
				$ele.buttonset();
				
				$('a',$menu).each(function(){
					var $a = $(this);
//					app.u.dump("$a.data('shipmethod'): "+$a.data('shipmethod'));
					$a.on('click',function(event){
						event.preventDefault();
						app.u.dump(" -> add new "+$a.data('shipmethod')+" shipmethod");
						$("h3.heading:first",$pageContainer).text("Add New Flex Shipmethod: "+$a.text());
						app.ext.admin_config.a.showAddFlexShipment($a.data('shipmethod'),$("[data-app-role='slimLeftContent']:first",$pageContainer));
						});
					});
				
				}, //handleAddShipment

			shippingPartnerRegExec : function($btn)	{
				$btn.button();
				$btn.off('click.shippingPartnerRegExec').on('click.shippingPartnerRegExec',function(){
					var $form = $btn.closest('form');
					if(app.u.validateForm($form))	{
						
						var sfo = $form.serializeJSON({'cb':true});
					//supplier 'may' be set on the parent container. This is used in supply chain.
						if($btn.closest("[data-app-role='shippingPartnerRegContainer']").data('supplier'))	{
							sfo.supplier = $btn.closest("[data-app-role='shippingPartnerRegContainer']").data('supplier');
							}
						
						if(sfo.provider == 'FEDEX' || sfo.provider == 'UPS')	{
							$form.showLoading({'message':'Registering account. This may take a few moments.'});
							var macroCmd = (sfo.provider == 'FEDEX') ? "FEDEX-REGISTER" : "UPSAPI-REGISTER";
							app.ext.admin.calls.adminConfigMacro.init(["SHIPMETHOD/"+macroCmd+"?"+$.param(sfo)],{'callback':function(rd){
								$form.hideLoading();
								if(app.model.responseHasErrors(rd)){
									$form.anymessage({'message':rd});
									}
								else	{
									$form.empty().anymessage(app.u.successMsgObject('Activation successful!'));
									}
								}},'immutable');
							app.model.dispatchThis('immutable');

							}
						else	{
							$form.anymessage({"message":"In admin_config.e.shippingPartnerRegExec, unable to ascertain provider. Was expecting it in the serialized form.","gMessage":true});
							}
						}
					else	{} //validateForm handles error display.
					});
				},

			shippingGeneralUpdateExec : function($btn)	{
				$btn.button();
				$btn.off('click.shippingGeneralUpdateExec').on('click.shippingGeneralUpdateExec',function(){
					var $form = $btn.closest('form');
					if(app.u.validateForm($form))	{
						var macros = new Array();
						macros.push("SHIPPING/CONFIG?"+$.param($form.serializeJSON({'cb':true})));

//if any new bans have occured, update the list.
						var $bannedContainer = $("[data-app-role='bannedlistContainer']",$form);
						if($bannedContainer.find('.edited').length)	{
							macros.push("SHIPPING/BANNEDTABLE-EMPTY");
							var countries = "";
							$('tbody tr',$bannedContainer).each(function(){
								var $tr = $(this);
								if($(this).hasClass('rowTaggedForRemove'))	{} //row is being deleted. do not add. first macro clears all, so no specific remove necessary.
								else	{
									macros.push("SHIPPING/BANNEDTABLE-INSERT?match="+$tr.data('match')+"&type="+$tr.data('type'));
									}
								});
							}
// COUNTRIES!
//if any changes have occured to the blacklisted countries, update the list.
						var $blacklistContainer = $("[data-app-role='blacklistContainer']",$form);
						if($blacklistContainer.find('.edited').length)	{
							var blacklistMacro = "SHIPPING/CONFIG?blacklist="
							$('tbody tr',$blacklistContainer).each(function(){
								if($(this).hasClass('rowTaggedForRemove'))	{} //row is being deleted. do not add. first macro clears all, so no specific remove necessary.
								else	{
									blacklistMacro += $(this).data('country')+',';
									}
								});
							macros.push(blacklistMacro);
							}
//						app.u.dump("macros: "); app.u.dump(macros);
						app.ext.admin.calls.adminConfigMacro.init(macros,{'callback':'showMessaging','jqObj':$form,'message':'Your changes have been saved.'},'immutable');
						app.model.destroy('adminConfigDetail|shipping|'+app.vars.partition);
						app.ext.admin.calls.adminConfigDetail.init({'shipping':true},{datapointer : 'adminConfigDetail|shipping|'+app.vars.partition},'immutable');
						app.model.dispatchThis('immutable');


						}
					else	{} //validateForm handles error display
					});
				},

			paymentMethodUpdateExec : function($btn)	{
				$btn.button();
				$btn.off('click.paymentMethodUpdateExec').on('click.paymentMethodUpdateExec',function(){
					app.u.dump(" -> BEGIN click.paymentMethodUpdateExec (admin_config).");
					var
						$form = $btn.closest('form'),
						sfo = $form.serializeJSON({'cb':true}) || {},
						macroCmd;
					
					if(sfo.tender && sfo.tenderGroup)	{
						
						app.u.dump(" -> tender: "+sfo.tender);
						app.u.dump(" -> tenderGroup: "+sfo.tenderGroup);
						
						if(app.u.validateForm($form))	{
							if(sfo.tenderGroup == 'WALLET')	{
								macroCmd = "PAYMENT/WALLET-"+sfo.tender;
								}
							else	{
								macroCmd = "PAYMENT/"+sfo.tenderGroup;
								}
							app.u.dump(" -> macroCmd: "+macroCmd);
							app.ext.admin.calls.adminConfigMacro.init([macroCmd+"?"+$.param(sfo)],{'callback':'showMessaging','message':'Payment has been updated.','jqObj':$form},'immutable');
					
							app.model.destroy('adminConfigDetail|payment|'+app.vars.partition);
							app.ext.admin.calls.adminConfigDetail.init({'payment':true},{datapointer : 'adminConfigDetail|payment|'+app.vars.partition},'immutable');
							app.model.dispatchThis('immutable');
							}
						else	{app.u.dump("Did not pass validation in admin_config.e.paymentMethodUpdateExec");} //validateForm will display the error logic.
						}
					else	{
						$form.anymessage({"message":"In admin_config.e.paymentMethodUpdateExec, either tender ["+sfo.tender+"] or tenderGroup ["+sfo.tenderGroup+"] not set. Expecting these within the form/sfo.","gMessage":true});
						}
					});
				},

//this is a generic button for use on a update macro.  For simple ones, like company information. Anything more complicated like shipping or tax will need a custom handler.
/*
NOT COMPLETED YET
			adminConfigMacroExec : function($btn)	{
				$btn.button();
				$btn.off('click.adminConfigMacroExec').on('click.adminConfigMacroExec',function(){
var $form = $btn.closest('form');
if($form.data('macroCmd'))	{
	if(app.u.validateForm($form))	{
		$form.showLoading({"Message":"Saving Changes"});
		
		
		}
	else	{} //form validation will handle error display.
	}
else	{
	$form.anymessage();
	}
					});
				},
*/
//This is where the magic happens. This button is used in conjunction with a data table, such as a shipping price or weight schedule.
//It takes the contents of the fieldset it is in and adds them as a row in a corresponding table. it will allow a specific table to be set OR, it will look for a table within the fieldset (using the data-app-role='dataTable' selector).
//the 'or' was necessary because in some cases, such as handling, there are several tables on one page and there wasn't a good way to pass different params into the appEvent handler (which gets executed once for the entire page).
// $form = the parent form of the data table. It's used for updating the corresponding 'save' button w/ the number of changes.
// $dataTbody = the tbody of the dataTable to be updated (where rows get added when the entry form is saved).
// $container = the fieldset (or some other element) that contains the form inputs used to generate a new row. NOT always it's own form.
			dataTableAddExec : function($btn,vars)	{
				$btn.button();
				$btn.off('click.dataTableAddExec').on('click.dataTableAddExec',function(event){
event.preventDefault();

app.u.dump("BEGIN admin_config.e.dataTableAddExec");

var
	$container = vars['$container'] ? vars['$container'] : $btn.closest('fieldset'),
//tbody can be passed in thru vars or, if not passed, it will look for one within the fieldset. rules engine uses vars approach. shipping doesn't. same for form.
	$dataTbody = (vars['$dataTbody']) ? vars['$dataTbody'] : $("[data-app-role='dataTable'] tbody",$container),
	$form = (vars['$form']) ? vars['$form'] : $container.closest('form');


if($container.length && $dataTbody.length && $dataTbody.data('bind'))	{
	app.u.dump(" -> all necessary jquery objects found. databind set on tbody.");
//none of the table data inputs are required because they're within the parent 'edit' form and in that save, are not required.
//so temporarily make inputs required for validator. then unrequire them at the end. This feels very dirty.
//	$('input',$container).attr('required','required'); 
	if(app.u.validateForm($container))	{
		app.u.dump(" -> form is validated.");
		var 
			bindData = app.renderFunctions.parseDataBind($dataTbody.attr('data-bind')),
			sfo = $container.serializeJSON({'cb':true}),
			$tr = app.renderFunctions.createTemplateInstance(bindData.loadsTemplate,sfo);
		
		app.u.dump(" -> sfo: "); app.u.dump(sfo);
		
		$tr.anycontent({data:sfo});
		$tr.addClass('edited');
		$tr.addClass('isNewRow'); //used in the 'save'. if a new row immediately gets deleted, it isn't added.

//if a row already exists with this guid, this is an UPDATE, not an ADD.
		if(sfo.guid && $("tr[data-guid='"+sfo.guid+"']",$dataTbody).length)	{
			$("tr[data-guid='"+sfo.guid+"']",$dataTbody).replaceWith($tr);
			}
		else	{
			$tr.appendTo($dataTbody);
			}
		app.u.handleAppEvents($tr);
//this function will look for .edited in the form and, if present, enable and update the save button.
		app.ext.admin.u.handleSaveButtonByEditedClass($form);
		}
	else	{
		app.u.dump("form did not validate");
		//validateForm handles error display.
		}
//	$('input',$container).attr('required','').removeAttr('required');
	
	}
else	{
	$btn.closest('form').anymessage({"message":"In admin_config.e.dataTableAddExec, unable to ascertain container ["+$container.length+"], tbody for data table or that tbody ["+$dataTbody.length+"] has no bind-data.","gMessage":true});
{'fraction_non_alphanumeric': 0.1858961111583861, 'fraction_numerical': 0.0010454528877596918, 'mean_word_length': 3.815148677124795, 'pattern_counts': {'":': 14, '<': 117, '<?xml version=': 0, '>': 131, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1848777', 'n_tokens_mistral': 31553, 'n_tokens_neox': 25516, 'n_words': 4718}