// TRAPEZE
// Copyright 2006 Trapeze, Inc. All Rights Reserved.
// This file is proprietary and confidential; unauthorized use or redistribution is prohibited.
/**
* @class FormManager / modded from SimplyFormed v1.0, by Adrian Stiegler
* @version 1.0
* @author Adrian Stiegler
* @availability Flash Player 8.0
* @edition Flash 8.0 / AS2
*
============================================
* Creates and manages Forms and Form Data *
============================================
*/
// Import Statements:
import com.trapeze.utils.Delegate;
import com.trapeze.utils.collections.HashMap;
import com.trapeze.bango.api.*;
class com.trapeze.managers.FormManager {
// ::: PRIVATE PROPERTIES
static private var _instance:FormManager;
// main container arrays for objects and displayable movieclips for forms
public var _formsObjectArray:Array;
public var _formsDisplayArray:Array;
private var _formsDepth:Number;
/*=====================================
* getInstance
*
*/
static public function getInstance():FormManager
{
if(_instance == undefined)
{
_instance = new FormManager();
}
return _instance;
}
/* Constructor ========================
*
*/
private function FormManager()
{
_formsObjectArray = new Array();
_formsDisplayArray = new Array();
_formsDepth = 0;
_global.formsArray = _formsDisplayArray;
}
/*
MATCH FORM TYPE
================================================================================================================================================================
Provide a formInstance to parse the Bango XML and produce a form, using 'matchFormType' to create field_types
================================================================================================================================================================
*/
public function createForm( formTarget:MovieClip, formName:String, formID:Number, userCallBack:Function, displayableForm:Boolean):Array
{
// check for user callback
if ( userCallBack == undefined ) userCallBack = null;
if ( displayableForm == undefined || displayableForm == null)
{
var _displayableForm = false;
} else {
var _displayableForm = displayableForm;
}
// create clip and form object inside
var _form = formTarget.createEmptyMovieClip(formName, _formsDepth++);
var _formBg = _form.attachMovie("_container", "back_mc", 0);
/*
SETUP FORM FUCNTIONS
================================================================================================================================================================
Next three functions set up the basic Form template
================================================================================================================================================================
*/
setupFormObjectTemplate( _form, formID, userCallBack); // set's up form object specific variables
setFormDisplayables( _form ); // set's up form displayable variables
setupFormAssets( _form ); // set's the physical movieclip assets
/*
================================================================================================================================================================
*/
// .. now get Form Data
_global.functionManager.getFormData( _form, formID, userCallBack );
// add form into our 'formsArray'
_formsDisplayArray.push(_form);
// show / hide the form to additional params
_form._visible = _displayableForm;
// send to debugger
_global.debugManager.traceMsg("FORM CREATED AT: " + _form);
return _form;
}
/*
REMOVE FORM
================================================================================================================================================================
Provide a formInstance, and the form is removed from Display and the formDisplayArray
================================================================================================================================================================
*/
public function removeForm( formInstance:MovieClip )
{
_global.debugManager.traceMsg("DELETING FORM: " + formInstance);
for (var i = 0; i < _formsDisplayArray.length; i++)
{
if (_formsDisplayArray[i] == formInstance)
{
_formsDisplayArray.splice(i,i + 1);
}
}
formInstance.removeMovieClip();
}
/*
REFRESH FORM INSTANCE
================================================================================================================================================================
Provide a formInstance, will refresh the form for re-usability purposes
================================================================================================================================================================
*/
public function refreshFormInstance( formInstance:MovieClip )
{
/*
This function will refresh a currently setup form
*/
// reset all data , array , object vars
}
/*
SETUP FORM OBJECT TEMPLATE
================================================================================================================================================================
Creates all the required Objects, Hashmaps, Arrays, LoadVars, Listeners and variables for each basic form template
================================================================================================================================================================
*/
private function setupFormObjectTemplate( formInstance:MovieClip, formID:Number, userCallBack:Function):Void
{
formInstance['formParams'] = new Object(); // displayable params for this form (used in setFormDisplayables)
formInstance['formID'] = formID; // contains unique FormID
formInstance['formUserCallBack'] = userCallBack; // contains the user specificed call back function (in case of overriding)
formInstance['attributeVarTable'] = new HashMap(); // contains all form specific attributes like sizing, spacing , inital FormID
formInstance['hiddenVarTable'] = new HashMap(); // contains all hidden data types for each form (used for cross referencing vars coming from Bango and sending back into Bango)
formInstance['attributeVarTable'].name = 'attributeVarTable'
formInstance['hiddenVarTable'].name = 'hiddenVarTable'
formInstance['formData'] = new Array(); // will contain the formData after calling to Bango
formInstance['formSendVars'] = new LoadVars(); // will contain all the formData variables to send out to Bango
formInstance['xPosition'] = 0; // used later in matchFormType for positioning formElements
formInstance['yPosition'] = 0; // ''
formInstance['elementCount'] = 0; // used to set relative ID's to both the Label and Field pair for any field type
formInstance['lastFocused'] = undefined; // used to hold as instance placeholder when swapping depths on focus
// listeners
formInstance['formListeners'] = new Object(); // used for all listeners of this form
formInstance['formCreateSuccess'] = false; // used to tell the managers if the initial form call was successful and created, if so, any other bangoCallComplete's will just be signal handled, not parsed into a new form on screen
}
/*
SETUP FORM DISPLAYABLES
================================================================================================================================================================
Parses some initial XML based params for each Form, using a rich Hash Map and storing them in the formInstance's 'attributesVarTable' object
================================================================================================================================================================
*/
public function setFormDisplayables( formInstance:MovieClip )
{
var _formParams = formInstance['formParams'];
// set each form's defaults
var _formID = getFormID( formInstance );
var formParamsXML = new XML(''
+''
+''
+''
+''
+''
);
/*
Default values: formID, recipient, from, action, cellPadding, cellSpacing, formWidth, formHeight
Later when speaking to Bango, new key's are added into the varTable on any formInstance,
rewriting a FormID, or any specific additional variables with Data_Type as hidden) from Bango
*/
// set up keys into varTable
for(var i in formParamsXML.childNodes)
{
var theParam:XMLNode = formParamsXML.childNodes[i];
var key:String = theParam.attributes.name;
var value:String = theParam.firstChild.nodeValue;
// add key / value
formInstance['attributeVarTable'].addItem(key, value);
// another example of using the internal functions to get values
//getAttributesValue( formInstance, key ));
}
}
/*
SETUP FORM DISPLAYABLES
================================================================================================================================================================
Phsyically adjusts all the form clips using the 'attributeVarTable' previously to style visual elements
================================================================================================================================================================
*/
private function setupFormAssets( formInstance:MovieClip )
{
// get our vars
var _formWidth = Number(getAttributesValue( formInstance, "formWidth" ));
var _formHeight = Number(getAttributesValue( formInstance, "formHeight" ));
var _cellPadding = Number(getAttributesValue( formInstance, "cellPadding" ));
var _cellSpacing = Number(getAttributesValue( formInstance, "cellSpacing" ));
var _colLabelWidth = Number(getAttributesValue( formInstance, "colLabelWidth" ));
// set size of background
formInstance['back_mc']._width = _formWidth;
formInstance['back_mc']._height = _formHeight;
formInstance['back_mc']._alpha = 0;
// create two columns inside container for labels and field types
var col_left = formInstance.attachMovie("_container", "col_left", 1); // visual placeholder (to line stuff up)
var col_right = formInstance.attachMovie("_container", "col_right", 2); // ''
var formTextLabels = formInstance.attachMovie("_blank", "labels_mc", 3);
var formFields = formInstance.attachMovie("_blank", "fields_mc", 4);
// left column
col_left.back_mc._width = _colLabelWidth - _cellSpacing;
col_left.back_mc._height = formInstance['back_mc']._height;
col_left._alpha = 0;
// right column
col_right.back_mc._width = _formWidth - _colLabelWidth;
col_right.back_mc._height = formInstance['back_mc']._height;
col_right._x = col_left._width + _cellSpacing;
col_right._alpha = 0;
// position form labels with left column
formTextLabels._x = col_left._x;
formTextLabels._y = col_left._y;
// position form fields with right column
formFields._x = col_right._x;
formFields._y = col_right._y;
}
/*
MATCH FORM TYPE
================================================================================================================================================================
Provide a formInstance to parse the Bango XML and produce a form, using 'matchFormType' to create field_types
================================================================================================================================================================
*/
public function parseFormData( formInstance:MovieClip )
{
var _cellSpacing = Number(getAttributesValue( formInstance, "cellSpacing" ));
var formData = formInstance['formData']; // internal data array
var refer = this;
// MATCH TYPES WITH ELEMENTS
for (var i = 0; i < formData.length; i++) {
matchFormType( formInstance, formData[i] );
}
// ::: SUBMIT
var field_type = formInstance['fields_mc'].attachMovie("Button", "submit", formInstance['fields_mc'].getNextHighestDepth());
field_type._type = "button";
field_type.label = "Submit";
field_type.setSize(72,22);
// position
field_type._y = formInstance['yPosition'];
field_type.onPress = function() {
refer.sendFormData( formInstance );
}
// ::: RESET
var field_type = formInstance['fields_mc'].attachMovie("Button", "submit", formInstance['fields_mc'].getNextHighestDepth());
field_type._type = "button";
field_type.label = "Reset";
field_type.setSize(72,22);
// ::: POSITION
field_type._y = formInstance['yPosition'];
field_type._x = formInstance['fields_mc']['submit'].x + formInstance['fields_mc']['submit'].width + _cellSpacing;
formInstance['yPosition'] += field_type._height;
field_type.onPress = function() {
refer.clearFormData( formInstance );
}
}
/*
MATCH FORM TYPE
================================================================================================================================================================
Pass a formInstance, and the XML element from a series, or a single and proper form types are created and displayed on screen
================================================================================================================================================================
*/
private function matchFormType( formInstance:MovieClip, formElement:Object )
{
/*
--------------------------------
INDEX OF ELEMENT
--------------------------------
trace(formElement.Name);
trace(formElement.Data_Type);
trace(formElement.Value);
trace(formElement.Options);
trace(formElement.Label);
trace(formElement.Required);
trace(formElement.Row_);
trace(formElement.Column_);
trace(formElement.Tab_Index);
trace(formElement.Field_Size);
trace(formElement.Restriction);
--------------------------------
*/
var _Name = formElement.Name;
var _DataType = formElement.Data_Type.toString().toLowerCase();
var _TabIndex = formElement.Tab_Index;
var _Value = formElement.Value;
var _FieldSize = Number( formElement.Field_Size );
var _cellSpacing = Number(getAttributesValue( formInstance, "cellSpacing" ));
// HIDDEN ATTRIBUTE
if (_DataType == "hidden")
{
// let's add into our 'hiddenVarTable'
formInstance['hiddenVarTable'].addItem(formElement.Name, formElement.Value);
}
// TEXT LABEL
if (_DataType == "text" || _DataType == "password")
{
// label
var field_label = formInstance["labels_mc"].attachMovie("Label", "label" + formInstance['labels_mc'].getNextHighestDepth(), formInstance['labels_mc'].getNextHighestDepth());
field_label.myID = formInstance['elementCount'];
field_label.text = formElement.Label;
field_label.setSize(formInstance["col_left"].back_mc._width);
// field
var field_type = formInstance['fields_mc'].attachMovie("TextInput", "input" + formInstance['fields_mc'].getNextHighestDepth(), formInstance['fields_mc'].getNextHighestDepth());
field_type.myID = formInstance['elementCount'];
field_type._type = "text";
// set formElement default settings (Tab Index, Field Size, Required, Restrictions, Row and Column (not being used in Version 1.0)
field_type.border = true;
field_type.setSize(_FieldSize, 22);
// position
field_label._y = formInstance['yPosition'];
field_type._y = formInstance['yPosition'];
formInstance['yPosition'] += field_type.height + _cellSpacing;
if (_DataType == "password") field_type.password = true;
}
// TEXT AREA
if (_DataType == "textarea")
{
// label
var field_label = formInstance["labels_mc"].attachMovie("Label", "label" + formInstance['labels_mc'].getNextHighestDepth(), formInstance['labels_mc'].getNextHighestDepth());
field_label.myID = formInstance['elementCount'];
field_label.text = formElement.Label;
field_label.setSize(formInstance["col_left"].back_mc._width);
// textarea
var field_type = formInstance['fields_mc'].attachMovie("TextArea", "input" + formInstance['fields_mc'].getNextHighestDepth(), formInstance['fields_mc'].getNextHighestDepth());
field_type.myID = formInstance['elementCount'];
field_type._type = "textarea";
// set properties
field_type.editable = true;
field_type.wordWrap = true;
field_type.border = true;
field_type.text = "";
field_type.setSize(formElement.Field_Size, 50);
field_label._y = formInstance['yPosition'];
field_type._y = formInstance['yPosition'];
formInstance['yPosition'] += field_type.height + _cellSpacing;
}
// CHECKBOX / RADIO
if (_DataType == "checkbox" || _DataType == "radio")
{
// checkbox field / label
var field_type = formInstance['fields_mc'].attachMovie("CheckBox", "checkbox" + formInstance['fields_mc'].getNextHighestDepth(), formInstance['fields_mc'].getNextHighestDepth());
field_type.myID = formInstance['elementCount'];
field_type._type = "checkbox";
// set properties
field_type.label = formElement.Label;
field_type.labelPlacement = "right";
field_type.setSize(formElement.Field_Size, 22);
field_type._y = formInstance['yPosition'];
formInstance['yPosition'] += field_type.height + _cellSpacing;
if (_Value == 1) field_type.selected = true;
}
// DROP DOWN (ComboBox)
if (_DataType == "select")
{
// label
var field_label = formInstance["labels_mc"].attachMovie("Label", "label" + formInstance['labels_mc'].getNextHighestDepth(), formInstance['labels_mc'].getNextHighestDepth());
field_label.myID = formInstance['elementCount'];
field_label.text = formElement.Label;
field_label.setSize(formInstance["col_left"].back_mc._width);
// field
var field_type = formInstance['fields_mc'].attachMovie("ComboBox", "combobox" + formInstance['fields_mc'].getNextHighestDepth(), formInstance['fields_mc'].getNextHighestDepth());
field_type.myID = formInstance['elementCount'];
field_type._type = "select";
// set properties
field_type.setSize(_FieldSize, 22);
field_type.editable = false;
// get value | label from element
var _fieldOptions = formElement.Options.split(",");
for (var i = 0; i < _fieldOptions.length; i++)
{
var _fieldAttributes = _fieldOptions[i].split('|');
var _itemValue = _fieldAttributes[0];
var _itemLabel = _fieldAttributes[1];
field_type.addItem({data:_itemValue, label:_itemLabel});
}
// position
field_label._y = formInstance['yPosition'];
field_type._y = formInstance['yPosition'];
formInstance['yPosition'] += field_type.height + _cellSpacing;
}
// RADIO GROUP
if (_DataType == "radio-group") {}
/*
FORM COMMON VARIABLES These variables will be checked on sendFormData
================================================================================================================================================================
Below are the common variables each field_type owns, this is cross referenced with 'matchFormErrors' and other 1:1 relationships of Data to Clips
================================================================================================================================================================
*/
field_type.varName = formElement.Name;
field_type.varValue = formElement.Value;
field_type.required = formElement.Required;
field_type.restrictions = formElement.Restriction;
field_type.tabIndex = _TabIndex; // set tab Index
/*
LISTENERS for each form type
================================================================================================================================================================
Each field_type has a listener for focusIn and onChanged
================================================================================================================================================================
*/
field_type.addEventListener("focusIn", formInstance['formListeners']);
formInstance['formListeners'].focusIn = function( evtObj:Object )
{
// swap depths
var _field = evtObj.target;
var _fieldContainer = _field._parent;
if (_fieldContainer._parent['lastFocused'] != undefined)
{
_field.swapDepths(_fieldContainer._parent['lastFocused']);
}
// set to last focused object
_fieldContainer._parent['lastFocused'] = _field;
}
// increment the element count for this form
formInstance['elementCount']++;
}
/*
MATCH FORM ERRORS
================================================================================================================================================================
This function is used to match any improper field's requested by Bango to adjust
================================================================================================================================================================
*/
private function matchFormErrors( formInstance:MovieClip, formErrors:Object )
{
// parse errors and highlight fields
for (var obj in formErrors) {
var _errorName = formErrors[obj].Name;
var _errorMessage = formErrors[obj].Message.toString();
// find matching field
for (var field_type in formInstance['fields_mc'])
{
if (formInstance['fields_mc'][field_type]._type != 'button')
{
if (formInstance['fields_mc'][field_type].varName == _errorName) {
var _clipInstance = formInstance['fields_mc'][field_type];
// found our matching varName to errorName
_global.debugManager.traceMsg("BANGO VALIDATION ISSUE AT: " + _clipInstance + " with errorMessage " + _errorMessage);
}
}
}
}
}
/*
CLEAR FORM DATA
================================================================================================================================================================
Provide a formInstance and all the field types will be cleared /reset
================================================================================================================================================================
*/
private function clearFormData( formInstance:MovieClip )
{
for (var clip in formInstance["fields_mc"]) {
// catalogue all fields, except any buttons
if (formInstance["fields_mc"][clip]._type != "button")
{
if (formInstance["fields_mc"][clip]._type != "select") {
// clear text
formInstance["fields_mc"][clip].text = "";
// clear varValue
formInstance["fields_mc"][clip].varValue = undefined;
} else {
// set to start index
formInstance["fields_mc"][clip].selectedIndex = 0;
}
}
}
}
/*
SEND FORM DATA
================================================================================================================================================================
Provide a formInstance, will parse the varName / varValue's iand send the form data to Bango
================================================================================================================================================================
*/
private function sendFormData( formInstance:MovieClip )
{
/*
Setup with varName and varValue for each field_type
formInstance["fields_mc"][clip].varName
formInstance["fields_mc"][clip].varValue
*/
// clean the loadVars
formInstance['formSendVars'] = new LoadVars();
// run through all clips and create seamless string to send to form URL
for (var clip in formInstance["fields_mc"]) {
// catalogue all fields, except any buttons
if (formInstance["fields_mc"][clip]._type != "button") {
// IF TEXT / TEXT AREA
if (formInstance["fields_mc"][clip]._type == "text" || formInstance["fields_mc"][clip]._type == "textarea") {
formInstance["fields_mc"][clip].varValue = formInstance["fields_mc"][clip].text;
}
// IF DROP DOWN
if (formInstance["fields_mc"][clip]._type == "select") {
formInstance["fields_mc"][clip].varValue = formInstance["fields_mc"][clip].getItemAt(formInstance["fields_mc"][clip].selectedIndex).data;
}
// IF CHECKBOX
if (formInstance["fields_mc"][clip]._type == "checkbox") {
formInstance["fields_mc"][clip].varValue = formInstance["fields_mc"][clip].selected;
}
// IF RADIO-GROUP
if (formInstance["fields_mc"][clip]._type == "radio-group") {
// ToDo: This is not yet tested, since we don't have any radio-groups in Bango yet.
// if radio button is set to true, set value to label
formInstance["fields_mc"][clip].varValue = null;
if (formInstance["fields_mc"][clip].groupName != null && formInstance["fields_mc"][clip].selected == true) {
formInstance["fields_mc"][clip].varValue = formInstance["col_right"][clip].label;
}
}
// APPLY variables into formInstance's 'formSendVars' LoadVars object to send out
if (formInstance["fields_mc"][clip].varValue != null && formInstance["fields_mc"][clip].varValue != "") {
var _sendVarName = formInstance["fields_mc"][clip].varName.toString();
var _sendVarValue = formInstance["fields_mc"][clip].varValue;
// apply varName into formSendVars, and set to varValue
formInstance['formSendVars'][_sendVarName] = _sendVarValue;
}
}
}
// add hidden attributes into formSendVars
var _hiddenVariableTableLength = formInstance['hiddenVarTable'].getLength();
var _keyArray = formInstance['hiddenVarTable'].getKeys();
var _valueArray = formInstance['hiddenVarTable'].getValues();
// add hidden variables into our 'formSendVars' LoadVars object
for (var i = 0; i < _hiddenVariableTableLength; i++) {
if (_keyArray[i] == "Form_Submit_To") {
// let's rewrite our 'Form_Submit_To' key to 'func' (This is sort of a small security gate in itself)
formInstance['formSendVars']['func'] = _valueArray[i];
} else {
formInstance['formSendVars'][_keyArray[i]] = _valueArray[i];
}
}
// send to debugger
_global.debugManager.traceMsg("CONSTRUCTED VAR OBJECT 'formSendVars' for: " + formInstance);
// let's send out now
_global.functionManager.sendFormData( formInstance );
}
/*
GET ATTRIBUTES VALUE
================================================================================================================================================================
Provide a formInstance and a searchable key to return a Form Attribute of choice ( displayable params only, etc. Spacing, Padding )
================================================================================================================================================================
*/
private function getAttributesValue( formInstance:MovieClip, key:String):String{
var value:String = String(formInstance['attributeVarTable'].getValue(key));
return value;
}
/*
GET HIDDEN VALUE
================================================================================================================================================================
Provide a formInstance and a searchable key to return a Form Hidden Value of choice ( Form_Submit_To (func), Headers, Recipients etc )
================================================================================================================================================================
*/
private function getHiddenValue( formInstance:MovieClip, key:String):String{
var value:String = String(formInstance['hiddenVarTable'].getValue(key));
return value;
}
/*
GET FORM ID
================================================================================================================================================================
Returns the proper ID number of the passed formInstance param
================================================================================================================================================================
*/
public function getFormID( formInstance:MovieClip ):Number
{
return formInstance['formID'];
}
}