How to further enhance this code? - javascript

$( document ).ready( function() {
var dynamicChargableForm = 1;
var dynamicDiscountForm = 1;
var selectedId = 1;
var newTextarea = null;
var chargableHeader = document.getElementById( 'chargable-header' );
var disountHeader = document.getElementById( 'discount-header' );
var execute = null;
$(document).on('keyup','.dynamic',function() {
var typeName = this.id.split('-')[0];
switch( typeName ) {
case 'chargable':
execute = dynamicRow( this, 'chargable', dynamicChargableForm , chargableHeader );
execute ? dynamicChargableForm++ : execute = null;
break;
case 'discount' :
execute = dynamicRow( this, 'discount', dynamicDiscountForm, disountHeader );
execute ? dynamicDiscountForm++ : execute = null;
break;
}
});
});
function dynamicRow( element, type , relatedTracker , relatedHeader )
{
selectedId = element.id.split('-')[1];
if ( selectedId == relatedTracker )
{
relatedTracker++;
newTextarea = document.createElement( 'TEXTAREA' );
newTextarea.setAttribute( 'name', type + '-' + relatedTracker );
newTextarea.setAttribute( 'class' , 'form-control dynamic ' + type );
newTextarea.setAttribute( 'id' , type + '-' + relatedTracker );
relatedHeader.append( newTextarea );
return true;
}
return false;
}
This is my first attempt to add a dynamically populate textarea when user input on the last added form . I would like to have advise and review on my code as i think that this code is not very efficient. I would like to have better understanding and standpoint from the expert.
Thank you

Replace
execute = dynamicRow( this, 'chargable', dynamicChargableForm , chargableHeader );
execute ? dynamicChargableForm++ : execute = null;
By
if(dynamicRow( this, 'chargable', dynamicChargableForm , chargableHeader )) {
dynamicChargableForm++;
}
I don't know why you need to add the dynamic name. Best way would be to set the name to chargable[]. The field will then be sent to the server as array.

Related

Adding multi-line javascript to a page via DOM

I'm tinkering with some things, more just experimenting and learning how DOM manipulation works.
<script type="text/javascript">
(function()
{
var config = {
};
var get = CKFinder.tools.getUrlParam;
var getBool = function( v )
{
var t = get( v );
if ( t === null )
return null;
return t == '0' ? false : true;
};
var tmp;
if ( tmp = get( 'basePath' ) )
CKFINDER.basePath = tmp;
if ( tmp = get( 'startupPath' ) )
config.startupPath = decodeURIComponent( tmp );
config.id = get( 'id' ) || '';
if ( ( tmp = getBool( 'rlf' ) ) !== null )
config.rememberLastFolder = tmp;
if ( ( tmp = getBool( 'dts' ) ) !== null )
config.disableThumbnailSelection = tmp;
if ( tmp = get( 'data' ) )
config.selectActionData = tmp;
if ( tmp = get( 'tdata' ) )
config.selectThumbnailActionData = tmp;
if ( tmp = get( 'type' ) )
config.resourceType = tmp;
if ( tmp = get( 'skin' ) )
config.skin = tmp;
if ( tmp = get( 'langCode' ) )
config.language = tmp;
// Try to get desired "File Select" action from the URL.
var action;
if ( tmp = get( 'CKEditor' ) )
{
if ( tmp.length )
action = 'ckeditor';
}
if ( !action )
action = get( 'action' );
var parentWindow = ( window.parent == window )
? window.opener : window.parent;
switch ( action )
{
case 'js':
var actionFunction = get( 'func' );
if ( actionFunction && actionFunction.length > 0 )
config.selectActionFunction = parentWindow[ actionFunction ];
actionFunction = get( 'thumbFunc' );
if ( actionFunction && actionFunction.length > 0 )
config.selectThumbnailActionFunction = parentWindow[ actionFunction ];
break ;
case 'ckeditor':
var funcNum = get( 'CKEditorFuncNum' );
if ( parentWindow['CKEDITOR'] )
{
config.selectActionFunction = function( fileUrl, data )
{
parentWindow['CKEDITOR'].tools.callFunction( funcNum, fileUrl, data );
};
config.selectThumbnailActionFunction = config.selectActionFunction;
}
break;
default:
if ( parentWindow && parentWindow['FCK'] && parentWindow['SetUrl'] )
{
action = 'fckeditor' ;
config.selectActionFunction = parentWindow['SetUrl'];
if ( !config.disableThumbnailSelection )
config.selectThumbnailActionFunction = parentWindow['SetUrl'];
}
else
action = null ;
}
config.action = action;
// Always use 100% width and height when nested using this middle page.
config.width = config.height = '100%';
var ckfinder = new CKFinder( config );
ckfinder.replace( 'ckfinder', config );
})();
</script>
What I am trying to figure out how to do, is add that code to a page through the DOM. I know I can do it if I put this function in a >JS file, as I know how to call .JS files and have them load properly.
If I wanted to write that script out, as shown there, directly on the page, how would I do that? I have found some simple examples, like this:
window.onload = function() {
var s = document.createElement('script');
s.type = 'text/javascript';
var code = 'alert("hello world!");';
try {
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
} catch (e) {
s.text = code;
document.body.appendChild(s);
}
}
But it doesn't seem to work when I put a long, multi-line, block of javascript in it. How can I do this?
DOM is a Tag based mark up structure. So a defined structure of Tags has to come in a defined order. Everything in DOM goes in Tags. If you want JavaScript in DOM, that will also be added to a Script Tag.
Within this tag you can put all your JavaScript and that will be just in the page for you.
Following link contains a JavaScript JQuery example that is the code on the same page and it is a very beginner level article with a detail on how to use Script on the page and how to use event handling etc.
JavaScript Basic Tutorial on JQuery and Event Handling

after upgrading to Angular 1.4 my directive breaks

I have a form directive that injects some bootstrap classes and adds ng-messages to a form. Once i upgraded to angular 1.4 it breaks.
I was able to pinpoint the problem to this method:
var setupDom = function ( element ) {
var input = element.querySelector( 'input,textarea,select' );
var label = element.querySelector( 'label' );
var type = input.getAttribute( 'type' );
var name = input.getAttribute( 'name' );
//checkbox and radio need a different class
if ( type !== 'checkbox' && type !== 'radio' ) {
input.classList.add( 'form-control' );
}
element.classList.add( 'form-group' );
return name;
};
The html element that this code runs on looks like this:
<input type="url" name="{{'videoLink' + $index}}" id="{{'videoLink' + $index}}"
ng-model="item.videoLink" placeholder="Youtube or Vimeo video link"/>
The problem is in var name, since it gets the non-compiled version {{'videoLink' + $index}} instead of videoLink0 , videoLink1... as it used to in 1.3.
Any idea why is it happening and how to overcome this problem?
UPDATE:
here is the entire directive code:
'use strict';
(function ( module ) {
var setupDom = function ( element, scope ) {
var input = element.querySelector( 'input,textarea,select' );
var label = element.querySelector( 'label' );
var type = input.getAttribute( 'type' );
var name = scope.$eval(input.getAttribute( 'name' ));
//checkbox and radio need a different class
if ( type !== 'checkbox' && type !== 'radio' ) {
input.classList.add( 'form-control' );
}
element.classList.add( 'form-group' );
return name;
};
var addMessages = function ( form , element , name , $compile , scope ) {
var messages = '<div class="help-block am-fade-and-scale" ' + 'ng-messages=" ' + form.$name + '.' + name + '.$error' + '" ' + 'ng-show="' + form.$name + '.' + name + '.$dirty">' + '<div ng-messages-include="/assets/angular-client/app/html/common/forms/message.html"></div></div>';
element.append( $compile( messages )( scope ) );
};
var watcherFor = function ( form , name ) {
return function () {
if ( name && form[ name ] ) {
return form[ name ].$invalid;
}
};
};
var updaterFor = function ( element ) {
return function ( hasError ) {
if ( hasError ) {
element.removeClass( 'vl-success' ).addClass( 'vl-error' );
} else {
element.removeClass( 'vl-error' ).addClass( 'vl-success' );
}
};
};
var link = function ( $compile ) {
return function ( scope , element , attr , formCtrl ) {
var name = setupDom( element[ 0 ] ,scope );
addMessages( formCtrl , element , name , $compile , scope );
scope.$watch( watcherFor( formCtrl , name ) , updaterFor( element ) );
};
};
var forminput = /*ngInject*/
function ( $compile ) {
return {
restrict : 'A' ,
require : '^form' ,
link : link( $compile )
};
};
forminput.$inject = [ '$compile' ];
module.directive( 'vlForminput' , forminput );
}( angular.module( 'html.common' ) ));
I encountered the same issue and addressed it using the replace method.
HTML:
<input type="text" ng-model="carrierBillingRateException.rate" name="rate{{$index}}" required />
Angular Directive:
var setupDOM = function (element, scope) {
var input = element[0].querySelector("input, textarea, select");
var type = input.getAttribute("type");
var name = input.getAttribute("name").replace('{{$index}}', scope.$index);
return name;
};
Why not try using something like the following:
var app = angular.module('html.common', []);
app.directive('vlFormInput', function () {
return {
restrict: 'EA',
templateUrl: 'path/to/html/file/with/ng-repeat.html',
link: {
post: function(scope,elem,attr){
scope.setUpDom = function(){
var input = angular.element( 'input,textarea,select' );
var label = angular.element( 'label' );
var type = input.getAttribute( 'type' );
var name = input.getAttribute( 'name' );
}
}
}
};
});
I honestly have not tested this code but it should point you in the right direction. By using a post: function the values should be compiled when you go looking for them.

Loop through array to factorize javascript code

I have a javascript code that I need to repeat many times with just a slight change:
I need to take the function below and repeat it EXACTLY the same apart from changing info_throbber to video_throbber, then, to map_throbber, then picture_throbber and do tyhese changes only on 2 lines: line 2 and 9)
I don't want to just repeat theses dozens of line one after the other, even if it works. I would like to factorize it.
$(function() {
var $modal_types = $('select#game_info_throbber_modal_types') # FIRST INJECTION HERE
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=game_info_throbber][type=hidden]') # SECOND INJECTION HERE
;
$add_modal.click(function(e) {
e.preventDefault();
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
});
Using Loop through an array in JavaScript, here what I tried but it fails:
var i, s, myStringArray = [ "info_throbber", "video_throbbe", "map_throbber", "picture_throbber" ], len = myStringArray.length
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
// ... do stuff with s ...
$(function() {
var $modal_types = $('select#deal_' + s + '_modal_types')
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
;
$add_modal.click(function(e) {
e.preventDefault();
$(this).closest('li')
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
};
}
};
The problem is it seems to work but not fully as it did not append on both $add_modal nor does it allow to change values. I don't think it's necessary to understand deeply the complexe code above but the thing is it does not work while when I just put all of the 4 functions one after the other one (first for info_throbber, then video_throbber, and so on...), it works. So me creating an iteraiton through the array should be work.
thanks for yourt help,
You have a JavaScript scope issue. The function within the loop is only using the last i value provided for all iterations of that function. You need to pass the index into the function to make it work correctly.
See this stack question, JavaScript loop variable scope, for more information.
The simplest fix is to wrap your function like so
var i, myStringArray = [ "info_throbber", "video_throbber", "map_throbber", "picture_throbber" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
(function(index) {
var s = myStringArray[index];
// ... do stuff with s ...
$(function() {
var $modal_types = $('select#deal_' + s + '_modal_types')
, $li = $modal_types.parent('li')
, $ol = $li.parent('ol')
, $form = $modal_types.closest('form')
, $submit = $form.find('input[type=submit]')
, $add_modal = $('Add Modal')
, $remove_modal = $('Remove Modal')
, $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
;
$add_modal.click(function(e) {
e.preventDefault();
$(this).closest('li')
.append($remove_modal.clone(true));
create_info_modal($li.clone());
});
$remove_modal.click(function(e) {
e.preventDefault();
$(this).parent('li').remove();
});
$submit.click(function(e) {
var components = JSON.stringify( collect_info_modals() )
;
$ol.find('ol.info_modal').remove();
$modal_types.remove();
$hidden_info_modals.val( components );
});
var modal_types_change = function() {
var $el = $(this)
, $li = $(this).closest('li')
, id = $(this).val()
, $components = $li.find('ol.components')
;
$components.remove();
get_modal_structure(id, $li.find('select') );
};
$modal_types.attr({ id: null, name: null });
$li.remove();
var create_info_modal = function($modal, modal_type_id) {
var $select = $modal_types.clone();
if($modal.find('select').length) { $select = $modal.find('select'); }
$select.val(modal_type_id);
$select.change(modal_types_change);
$modal.prepend($select);
$modal.append($add_modal);
$ol.append($modal);
};
var collect_info_modals = function() {
var $info_modals = $ol.find('ol.components')
, components = []
;
$.each($info_modals, function(_, $info_modal) {
$info_modal = $($info_modal);
var info_modal = {}
, $components = $info_modal.find('li.component input')
, modal_id = $info_modal.parent('li').find('select').val()
;
info_modal['modal_id'] = modal_id;
$.each($components, function(_, component) {
component = $(component);
key = component.attr('name');
val = component.val();
info_modal[key] = val;
component.remove();
});
$info_modal.parent('li').remove();
components.push(info_modal);
});
return components;
};
function get_modal_structure(id, $select) {
// Grab modal structure
var url = '/admin/modal_types/modal_structure?id='+id;
$.getJSON(url, function(modal_structure) {
var $ol = $('<ol class="components">');
modal_structure.forEach(function(component){
$ol.append(build(component));
});
$ol.insertAfter($select);
});
};
function build(component, value) {
value = value || '';
var text_maxlength = 300
, $li = $('<li class="component string input stringish" />')
, $label = $('<label>'+component+'</label>')
, $input = $('<input name="'+component+'" type="text" required="required" maxlength='+text_maxlength+' value="' + value + '"/>')
;
// validations
if(component.match(/^text/)) {
$input.attr('maxlength', text_maxlength);
}
$li
.append($label) // returns the LI NOT THE LABEL
.append($input);
return $li;
};
(function() {
var hidden_info_modals = ($hidden_info_modals.val().length) ? $hidden_info_modals.val() : '[]';
hidden_info_modals = JSON.parse( hidden_info_modals );
hidden_info_modals.forEach(function(info_modal) {
var modal_type_id
, $info_modal = $li.clone(true)
, $ol = $('<ol class="components">');
;
modal_type_id = info_modal['modal_id'];
delete info_modal['modal_id'];
for (var key in info_modal) {
$ol.append(build(key, info_modal[key]));
}
$info_modal.append($ol)
$info_modal.append($remove_modal.clone(true))
create_info_modal($info_modal, modal_type_id);
});
})();
create_info_modal($li.clone(true));
});
})(i);
}
Also, you should remove if (i in myStringArray) as that is only needed when you do a foreach loop over the attributes of an object, not when you are looping over the indexes of an array.

Jquery UI Dialog Buttons Firing Multiple click Events

I am working on a WP plugin for a client that communicates with UPS, USPS and FEDEX. USPS requires multiple steps so I am using a UI Dialog Modal in which I add content dynamically via AJAX (PHP). The content is great, but it seems that when I click the continue button on the first dialog it fires all successive dialog button functions. I have a function that I call to change dialog content, and each calling function sends AJAX data and sets the options for the next dialog. I need the button to simply complete its function and allow the user to make selections on the next dialog. While I have been using JQuery, JS and PHP for quite sometime I am fairly new to jQuery UI. Please see my code below for reference. Any help on this would be greatly appreciated.
"obj" is an object returned from PHP containing shippment data and html for dialog.
Function for updating dialog content
show_dialog = function( title, html, options ) {
$( "#dialog" ).dialog({
autoOpen: false,
});
$('#dialog').html( html );
$('#dialog').dialog( 'option', 'title', title );
$('#dialog').dialog( options );
$('div.ui-dialog-buttonset button.ui-button span.ui-button-text').each(function() {
$(this).html($(this).parent().attr('text'));})
}
Function for address validation
usps_address_check = function( obj ) {
if( obj.VStatus === 'AddressMatch' ) {
var title = obj.Title;
var options = {
resizable: false,
width:800,
modal:true,
buttons: {
//when this button is clicked it fires the function in the next dialog below process shipment.
'Continue': function(event) {
if( $('#verified').attr('checked') ) {
data = {
action: 'usps_ajax',
call: 'check_rate',
post: $('#post_id').val(),
};
ajax_request( data );
} else {
$(this).dialog( 'option', 'title', "Please click the checkbox to confirm corrected address..." );
}
},
Cancel: function() {
$(this).dialog( 'close' );
}
}
}
}
show_dialog( title, obj.StatusMessage, options );
$('#dialog').dialog('open');
}
Function for confirming shipping rates and selecting service addons prior to processing shipment request with USPS
usps_confirm_rates = function( obj ) {
var title = obj.Title;
var html = obj.StatusMessage;
var options = {
resizable: true,
width:800,
height:800,
modal:true,
buttons: {
//This function is fired when the button on the first modal above is clicked.
'Process Shipment': function() {
data = {
action: 'usps_ajax',
call: 'process_shipment',
post: $('#post_id').val(),
};
ajax_request( data );
},
'Cancel': function(e) {
$(this).dialog( 'close' );
}
}
}
show_dialog( title, html, options );
var total_shipping = parseFloat( $('#total_shipping').text() );
var customer_paid = parseFloat( $('#shipping_paid').text() );
var total_addons = parseFloat( $('#total_addons').text() );
var difference;
$('.btn_addons').click( function(e) {
var key = $(this).attr('id');
$('#' + key + '_addon_options').slideToggle();
$('.cb_addon_sel').change( function(e) {
var addons = obj.AddOns;
var thisCheck = $(this);
var thisTable = $(this).closest('table').attr('id');
var curr_addon = $(this).val();
var addon_name = $("#" + curr_addon + "_name").text();
var thisAddon = new Array();
var price = get_price( thisTable, curr_addon );
if( obj.AddOns[thisTable][curr_addon].ProhibitedWithAnyOf !== undefined ) {
var prohibited = obj.AddOns[thisTable][curr_addon].ProhibitedWithAnyOf.AddOnTypeV5;
}
if( obj.AddOns[thisTable][curr_addon].RequiresAllOf !== undefined ) {
var required = obj.AddOns[thisTable][curr_addon].RequiresAllOf.RequiresOneOf.AddOnTypeV5;
}
if($(this).attr('checked') ) {
total_addons += parseFloat( price );
total_shipping += parseFloat( price );
if( addons_selected[thisTable] === undefined )
addons_selected[thisTable] = new Array();
addons_selected[thisTable].push( curr_addon );
for( var p in prohibited ) {
if( typeof prohibited === 'object' )
element = prohibited[p];
else
element = prohibited;
$('#' + thisTable + '_row_' + element).hide();
if( $('#' + thisTable + '_' + element).attr('checked') ) {
$('#' + thisTable + '_' + element).removeAttr('checked');
}
}
for( var r in required ) {
if( typeof required === 'object' )
element = required[r];
else
element = required;
price = get_price( thisTable, element);
$('#' + thisTable + '_' + element).attr('checked', 'checked');
total_addons += parseFloat( price );
total_shipping += parseFloat( price );
}
} else {
var name = addon_required( curr_addon, thisTable );
if( typeof name === 'string' ) {
$('#' + curr_addon + '_info').text('Required when ' + name + ' is selected.');
$('#' + thisTable + '_' + curr_addon).attr('checked','checked');
} else {
total_addons -= parseFloat( price );
total_shipping -= parseFloat( price );
for( var p in prohibited ) {
if( typeof prohibited === 'object' )
element = prohibited[p];
else
element = prohibited;
$('#' + thisTable + '_row_' + element).show();
//removeByValue( prohibited[p], prohibited );
}
for( var r in required ) {
if( typeof required === 'object' )
element = required[r];
else
element = required;
price = get_price( thisTable, element);
$('#' + thisTable + '_' + element).attr('checked', 'checked');
$('#' + thisTable + '_' + element).removeAttr('checked');
$('#' + element + '_info').text('');
total_addons -= parseFloat( price );
total_shipping -= parseFloat( price );
//removeByValue( required[r], required );
}
removeByValue( curr_addon, addons_selected[thisTable] );
}
}
difference = customer_paid - total_shipping;
$('#total_addons').text( total_addons.toFixed(2) );
$('#total_shipping').text( total_shipping.toFixed(2) );
$('#total_difference').text( difference.toFixed(2) );
});
});
function addon_required( addon, box ) {
if( typeof required === 'undefined' ) {
return false;
} else {
for(var a in addons_selected[box]) {
var reqs = obj.AddOns[box][addons_selected[box][a]].RequiresAllOf.RequiresOneOf.AddOnTypeV5;
if( $.inArray(addon, reqs) == -1) {
return false;
} else {
return $("#" + addons_selected[a] + "_name").text();
}
}
}
}
function get_price( box, addon ) {
if( obj.AddOns[box][addon].Amount === undefined ) {
price = 0.00;
} else {
price = obj.AddOns[box][addon].Amount;
}
return price;
}
}
So I was unable to fix the issue directly, so I created a workaround per se. Instead of using the dialog buttons as navigation, I added control buttons to the dialog content in php. I then access them directly via Jquery. See example below.
public function verify_address( $authenticator ) {
$order = $this->order;
$params = array(
'Authenticator' => $authenticator,
'Address' => array(
'FullName' => $order->shipping_first_name . ' ' . $order->shipping_last_name,
'Company' => $order->shipping_company,
'Address1' => $order->shipping_address_1,
'Address2' => $order->shipping_address_2,
'City' => $order->shipping_city,
'State' => $order->shipping_state,
'Zipccode' => $order->shipping_postcode,
'Country' => $order->shipping_country
),
);
$check = $this->stamps->CleanseAddress( $params );
$this->xml_response['Call'] = 'VerifyAddress';
if( ! $check->AddressMatch ) {
if( $check->CityStateZipOK ) {
$this->xml_response['ResponseStatusCode'] = 1;
$this->xml_response['VStatus'] = 'CityStateZipOK';
$this->xml_response['StatusMessage'] = 'The street address could not be verified; however, the City, State, & ZipCode are valid. Click continue to use this address or cancel.';
}
$this->xml_response['ResponseStatusCode'] = 0;
$this->xml_response['VStatus'] = 'InvalidAddress';
$this->xml_response['StatusMessage'] = 'invalid address. Please verify address and resubmit.';
} else {
$message = '<span id="usps_error"></span></br>';
$message .= "The address was matched. Please review updated address below and click continue to proceed.";
$message .= '<table><tr><td><input type="checkbox" id="verified" value="true" /></td>';
$message .= '<td>' . $check->Address->FullName . '</br>';
$message .= $check->Address->Address1 . '</br>';
$message .= count( $check->Address->Address2 ) < 0 ? $check->Address->Address2 . '</br>' : '';
$message .= $check->Address->City . ', ' . $check->Address->State . ' ' . $check->Address->ZIPCode . '-' . $check->Address->ZIPCodeAddOn . '</td></tr><table>';
//Added html button here for navigation purposes. This can be accessed by its ID in Js after it is added to the dialog box.
$message .= '</br></br><div><button class="dialog_nav" id="btn_continue">Continue</button></div>';
$this->xml_response['ResponseStatusCode'] = 1;
$this->xml_response['VStatus'] = 'AddressMatch';
$this->xml_response['StatusMessage'] = $message;
$this->xml_response['Authenticator'] = $check->Authenticator;
$this->xml_response['Method'] = 'USPS';
$this->xml_response['Title'] = 'Step 1: Address Verfication';
}
if( is_soap_fault( $check ) ) {
$this->xml_response = handle_errors( $check );
}
return $this->xml_response;
}
Then in JS I can access the button via jQuery.
usps_address_check = function( obj ) {
if( obj.VStatus === 'AddressMatch' ) {
var title = obj.Title;
var options = {
resizable: false,
width:800,
modal:true,
buttons: {
//Cancel button functions correctly
'Cancel': function() {
$(this).dialog( 'close' );
}
}
}
show_dialog( title, obj.StatusMessage, options );
$('#dialog').dialog('open');
//Button is accessed here and is code is only executed once.
$('#btn_continue').click( function(e) {
if( $('#verified').attr('checked') ) {
data = {
action: 'usps_ajax',
call: 'check_rate',
post: $('#post_id').val(),
};
ajax_request( data );
} else {
$('#usps_error').text("Please click the checkbox to confirm corrected address, and click continue to proceed." ).css('color','red');
}
});
}
}
Still looking for a better solution, but this will work for now.

Coding DRY how to combine common functionality in these two objects?

DRY - Don't Repeat Yourself
ControlSignUp and ControSignIn are nearly identical. I've commented a "here" on the only 4 lines which are different. How can I combine this common functionality?
Actually it seem obvious..I can just pass in a single variable through the constructor...just a sec.
Answer:
/**
* ControlSign
*/
var ControlSign = function( type )
{
var form_element = document.getElementById( type );
var response_element = document.getElementById( type + '_response' );
var text_object = new Text( form_element );
var message_object = new Message( response_element );
this.invoke = function( )
{
if( Global.validate_input_on === 1 )
{
if( !text_object.checkEmpty() )
{
message_object.display( 'empty' );
return false;
}
if( type === 'signup' && !text_object.checkPattern( 'name' ) )
{
message_object.display( 'name' );
return false;
}
if( !text_object.checkPattern( 'email' ) )
{
message_object.display( 'email' );
return false;
}
if( !text_object.checkPattern( 'pass' ) )
{
message_object.display( 'pass' );
return false;
}
}
AjaxNew.repeatUse( ajaxSerialize( form_element ) + '&ajax_type=' + type + '_control', function( server_response_text ) { ajaxType( server_response_text, response_element, 'respond' ); } );
}
};
ControlSign.in = function()
{
new ControlSignIn( 'signin' ).invoke();
};
ControlSign.up = function()
{
new ControlSignUp( 'signup' ).invoke();
};
Simple solution: Make it a function ControlSign with a parameter, invoked with "in" or "up". You could call this "factory pattern".
Complex solution: you use a factory function to create the two constructors. OK, what I meant is the use of a closure to create constructors:
function makeControlSign(type) {
function constructor(...) {
this.invoke = function(){...};
// use the variable "type" where needed
...
}
constructor[type] = function(){...};
return constructor;
}
var ControlSignUp = makeControlSign("up");
var ControlSignIn = makeControlSign("in");
I guess this should neither be called "factory pattern" nor "abstract factory pattern".

Categories

Resources