handleman
2/28/2015 - 9:33 AM

JavaScript Module with Absctract factory pattern realization

JavaScript Module with Absctract factory pattern realization

var MYAPP = MYAPP || {}; //isolated namespace
if (MYAPP.company){
	console.warn('WARNING: MYAPP.company is already defined!');
}else{

	MYAPP.company = (function() {
	// variables
		var that = {};

			
		// factory for on page form objects
		function Forms(){}
		// methods to perform ajax responses to send and receive data from the server
		Forms.prototype = {
			/**
			 * submit() realization
			 */
			// ajax request realization
			submit: function (dataToSend) {
				var self = this;
				if(!dataToSend){
					dataToSend = '';
				}
				$.ajax({
					type: 'POST',
					url: self.ajaxPath,
					data:dataToSend,
					processData: false,
					contentType: false,
					success: function(data) {
						self.afterSubmit(data);
					}
				});

			},
			// check if there exists custom data manipulation handler and evaluate it
			beforeSubmit: function (data, formName) {
				var handler = this.beforeSubmitHandler,
					formData = data;
				
				this.formData = JSON.parse('{"' + decodeURI(formData).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
				
				this.formId = formName;

				if(typeof handler == 'function'){
					// if particular data change required
					this.formData = handler(data, formName);
					this.submit(data);
				} else{
					this.submit(data);
				}

			},
			afterSubmit: function (data) {
				var handler = this.afterSubmitHandler;
				if(typeof handler == 'function'){
					handler(data);
				} else{
					throw{
						name: 'Error',
						message: " handler function for processing response after form submit not defined, please define it!"
					};
				}

			},
			/**
			 * refreshes form state: if value was entered by user, then there will be label with rhis value
			 * or there will be prompt to enter value
			 * @function
			 * @public
			 */
			refreshHtml: function () {
				var pureText = $.trim( this.$staticValue.text()).replace(/[^0-9a-zA-Zа-я\s]/g,'').replace( /(\d)\s/, '' ).replace(/\s+/g,'');
				if(($.trim( this.$staticValue.text()) == '' || pureText  == 'NoneNone') && this.$wrapper.length && this.refrashable){
					this.$editable.addClass('hidden');
					this.$editable.removeClass("active");
					this.$description.removeClass('hidden');

				}else if(this.$wrapper.length  && this.refrashable){
					this.$editable.removeClass('hidden');
					this.$description.addClass('hidden');
				}
			}
		};
		/**
		 * factory object directly
		 * @param {String} type - type of fabricated object 
		 * @param {String} ajaxpath - attribute action from each form html element
		 */
		Forms.factory = function (type, ajaxpath) {
			var constr = type,
				newForm;
			if (typeof Forms[constr] !== 'function'){
				throw{
					name: 'Error',
					message: constr + "doesen't exist"
				};
			}
			if(typeof Forms[constr].prototype.beforeSubmit !== "function"){
				Forms[constr].prototype = new Forms();
			}
			newForm = new Forms[constr](ajaxpath);
			return newForm;
		};

		/**
		 * set of child objects that will override the factory default
		 */	
		Forms.name_form = function (path) {
			this.afterSubmitHandler = function (data) {
				if (data.success){
					$('#static-name-value').text($('#id_name').val());
					this.refreshHtml();

				}else{
					this.$editable.addClass('err');
				}
			};
			this.ajaxPath = path;

		};
		Forms.email_form = function (path) {
			var mailValue;
			this.afterSubmitHandler = function (data) {
				if (data.success){
					mailValue = $('#id_email').val();
					$('#static-email-value').attr('href', 'mailto:'+mailValue).text(mailValue);
					this.refreshHtml();
				}else{
					this.$editable.addClass('err');
				}
			};
			this.ajaxPath = path;

		};
		Forms.found_form = function (path) {
			var currValue,
				$input;
			this.afterSubmitHandler = function (data) {
				if (data.success){
					var $fullComplete = $('.full-complete',this.$staticValue);

					$input = $('#id_foundation');
					currValue = $.trim($input.val());

					$fullComplete.text(currValue);

					this.refreshHtml();

				}
			};
			this.refreshHtml = function () {

				var $fullComplete = $('.full-complete',this.$staticValue),
					$notComplete = $('.not-complete',this.$staticValue);
				if($.trim($fullComplete.text()) == ''){
					$fullComplete.addClass('hidden');
					$notComplete.removeClass('hidden');

				}else{
					$fullComplete.removeClass('hidden');
					$notComplete.addClass('hidden');
				}
				return false;
			};

			this.ajaxPath = path;

		};
	
		 /**
		 * initialize and configure the whole module
		 */
		that.init = function(options) {

			$.extend(this.lang, options.lang);
			$.extend(this.opt, options);

			this.forms = {};
			$(function () {
				

			
				//forms init
				$('.ajax-form').each(function () {
					var formName = $(this).attr('id'),
						path = $(this).attr('action'),
						inputData,
						$wrapper = $(this).closest('.'+self.opt.formWrapperClass),
						$staticValue = $('.'+self.opt.staticValueClass, $wrapper),
						$description = $('.'+self.opt.descriptionClass, $wrapper),
						$editable = $('.'+self.opt.editableClass, $wrapper),
						$closeButton = $('.'+self.opt.closeButtonClass, $wrapper),
						

					//make and initialize form objects
					/**
					 * It is where is magic happen
					 * Forms.factory(formName,path) factory method call
					 */
					self.forms[formName] = Forms.factory(formName,path);
					/*
					 * form object properties assignation 
					 */
					self.forms[formName].$form = $(this);
					self.forms[formName].$wrapper = $wrapper;
					self.forms[formName].$staticValue = $staticValue;
					self.forms[formName].$description = $description;
					self.forms[formName].$editable = $editable;
				

					// submit events handler
					$(this).off('submit');
					$(this).on('submit', function () {
						inputData = $(this).serialize();
						self.forms[formName].beforeSubmit(inputData, formName);
						
					});
					$closeButton.on('click', function() {
						$editable.removeClass(self.opt.formCurrentClass);
						self.forms[formName].refreshHtml();
						return false;
					});
				});
			});
		};
		return that;
	}());
}