|
From: <ken...@us...> - 2009-01-14 17:11:26
|
Revision: 1079
http://andro.svn.sourceforge.net/andro/?rev=1079&view=rev
Author: kendowns
Date: 2009-01-14 17:11:14 +0000 (Wed, 14 Jan 2009)
Log Message:
-----------
Moved all androLib.js dependencies into x6.js, x6 no longer loads androLib.js
Modified Paths:
--------------
trunk/andro/clib/x6.js
Modified: trunk/andro/clib/x6.js
===================================================================
--- trunk/andro/clib/x6.js 2009-01-12 20:59:14 UTC (rev 1078)
+++ trunk/andro/clib/x6.js 2009-01-14 17:11:14 UTC (rev 1079)
@@ -27,6 +27,7 @@
window.androIsIE = false;
}
+
/* **************************************************************** *\
Cookie functions.
@@ -131,7 +132,341 @@
return "##SELECTION_MARKER_" + Math.random() + "##";
}
+/* **************************************************************** *\
+ Javasript Language Extensions
+
+\* **************************************************************** */
+
+
+/****M* Javascript-API/Date-Extensions
+*
+* NAME
+* Date-Extensions
+*
+* FUNCTION
+* Javascript lacks a handful of useful date functions,
+* such as returning the day of the week as a string.
+* These extensions to the Date object provide those
+* facilities.
+*
+******
+*/
+
+/****m* Date-Extensions/getDow
+*
+* NAME
+* Date.getDow
+*
+* FUNCTION
+* The Javascript method Date.getDow returns the day of
+* the week as a string.
+*
+* If logical true is passed for the first parameter,
+* a 3-digit abbreviation is returned, using 'Thu' for
+* Thursday.
+*
+* INPUTS
+* boolean - If true, returns a 3-digit abbreviation
+*
+*
+* SOURCE
+*
+*/
+Date.prototype.getDow = function(makeItShort) {
+ var days = ['Sunday','Monday','Tuesday','Wednesday'
+ ,'Thursday','Friday','Saturday'
+ ];
+ var retval = days[this.getDay()];
+ if(makeItShort) {
+ return retval.slice(0,3);
+ }
+ return retval;
+}
+/******/
+
+
+/****M* Javascript-API/String-Extensions
+*
+* NAME
+* String-Extensions
+*
+* FUNCTION
+* Javascript lacks a handful of useful string functions,
+* such as padding and trimming, which we have added
+* to our standard library.
+*
+******
+*/
+
+
+/****m* String-Extensions/trim
+*
+* NAME
+* String.trim
+*
+* FUNCTION
+* The Javascript function trim removes leading and trailing
+* spaces from a string.
+*
+* EXAMPLE
+* Example usage:
+* var x = ' abc ';
+* var y = x.trim(); // returns 'abc'
+*
+* SOURCE
+*/
+String.prototype.trim = function() {
+ return this.replace(/^\s+|\s+$/g,"");
+}
+/******/
+
+/****m* String-Extensions/ltrim
+*
+* NAME
+* String.ltrim
+*
+* FUNCTION
+* The Javascript function ltrim removes leading spaces
+* from a string (spaces on the left side).
+*
+* EXAMPLE
+* Example usage:
+* var x = ' abc ';
+* var y = x.ltrim(); // returns 'abc '
+*
+* SOURCE
+*/
+String.prototype.ltrim = function() {
+ return this.replace(/^\s+/,"");
+}
+/******/
+
+/****m* String-Extensions/rtrim
+*
+* NAME
+* String.rtrim
+*
+* FUNCTION
+* The Javascript function rtrim removes trailing spaces
+* from a string (spaces on the right side).
+*
+* EXAMPLE
+* Example usage:
+* var x = ' abc ';
+* var y = x.ltrim(); // returns ' abc'
+*
+* SOURCE
+*/
+String.prototype.rtrim = function() {
+ return this.replace(/\s+$/,"");
+}
+/******/
+
+
+/****m* String-Extensions/pad
+*
+* NAME
+* String.pad
+*
+* FUNCTION
+* The Javascript function pad pads out a string to a given
+* length on either left or right with any character.
+*
+* INPUTS
+* int - the size of the resulting string
+*
+* string - the string that should be added. You can provide
+* a string of more than one character. The resulting string
+* will be clipped to ensure it is returned at the requested
+* size.
+*
+* character - either an 'L' or left padding or an 'R' for
+* right padding.
+*
+* EXAMPLE
+* Example usage:
+* var x = 'abc';
+* var y = x.pad(6,'0','L'); // returns '000abc';
+*
+* SOURCE
+*/
+String.prototype.pad = function(size,character,where) {
+ var val = this;
+ while(val.length < size) {
+ if(where == 'L')
+ val = character + val;
+ else
+ val += character;
+ if(val.length > size) {
+ val = val.slice(0,size);
+ }
+ }
+ return val;
+}
+/******/
+
+
+// Taken from http://www.sourcesnippets.com/javascript-string-pad.html
+var STR_PAD_LEFT = 1;
+var STR_PAD_RIGHT = 2;
+var STR_PAD_BOTH = 3;
+
+String.prototype.strpad = function(str, len, pad, dir) {
+
+ str = String(str);
+ if (typeof(len) == "undefined") { var len = 0; }
+ if (typeof(pad) == "undefined") { var pad = ' '; }
+ if (typeof(dir) == "undefined") { var dir = STR_PAD_RIGHT; }
+
+ if (len + 1 >= str.length) {
+
+ switch (dir){
+
+ case STR_PAD_LEFT:
+ str = Array(len + 1 - str.length).join(pad) + str;
+ break;
+
+ case STR_PAD_BOTH:
+ var right = Math.ceil((padlen = len - str.length) / 2);
+ var left = padlen - right;
+ str = Array(left+1).join(pad) + str + Array(right+1).join(pad);
+ break;
+
+ default:
+ str = str + Array(len + 1 - str.length).join(pad);
+ break;
+
+ } // switch
+
+ }
+
+ return str;
+
+}
+
+String.prototype.pad = function(len, pad, dir) {
+
+ str = this.toString();
+ if (typeof(len) == "undefined") { var len = 0; }
+ if (typeof(pad) == "undefined") { var pad = ' '; }
+ if (typeof(dir) == "undefined") { var dir = STR_PAD_RIGHT; }
+
+ if (len + 1 >= str.length) {
+
+ switch (dir){
+
+ case STR_PAD_LEFT:
+ str = Array(len + 1 - str.length).join(pad) + str;
+ break;
+
+ case STR_PAD_BOTH:
+ var right = Math.ceil((padlen = len - str.length) / 2);
+ var left = padlen - right;
+ str = Array(left+1).join(pad) + str + Array(right+1).join(pad);
+ break;
+
+ default:
+ str = str + Array(len + 1 - str.length).join(pad);
+ break;
+
+ } // switch
+
+ }
+
+ return str;
+
+}
+
+/****m* String-Extensions/repeat
+*
+* NAME
+* String.repeat
+*
+* FUNCTION
+* The Javascript function repeat returns the input string
+* repeated any number of times
+*
+* INPUTS
+* * int - the number of times to repeat the string.
+*
+*
+* EXAMPLE
+* Example usage:
+* alert( 'abc'.repeat(3));
+*
+* SOURCE
+*/
+String.prototype.repeat = function(count) {
+ if(count==null) count = 1;
+ retval = '';
+ for(var x = 1; x<= count; x++) {
+ retval+= this;
+ }
+ return retval;
+}
+/******/
+
+/****m* String-Extensions/htmlDisplay
+*
+* NAME
+* String.htmlDisplay
+*
+* FUNCTION
+* The Javascript function htmlDisplay converts the HTML
+* characters ampersand '&', less than '<' and
+* greater-than '>' to their HTML entities equivalents
+* for safe display.
+*
+* The reverse function is htmlEdit.
+*
+* SOURCE
+*/
+String.prototype.htmlDisplay = function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+}
+/******/
+
+/****m* String-Extensions/htmlEdit
+*
+* NAME
+* String.htmlEdit
+*
+* FUNCTION
+* The Javascript function htmlEdit removes HTML entities
+* from a string and replaces them with literal characters,
+* suitable for editing in an input. The characters replaced
+* are ampersand '&', less-than '<', greater-than '>'
+* and non-breaking space '&nbsp;'.
+*
+* SOURCE
+*/
+String.prototype.htmlEdit = function() {
+ return this.replace(/&/g,'&')
+ .replace(/</g,'<')
+ .replace(/>/g,'>')
+ .replace(/ /g,' ');
+}
+/******/
+
+/* ---------------------------------------------------- *\
+
+ FIX BRAIN-DAMAGED INTERNET EXPLORER
+
+\* ---------------------------------------------------- */
+
+if(!Array.indexOf){
+ Array.prototype.indexOf = function(obj){
+ for(var i=0; i<this.length; i++){
+ if(this[i]==obj){
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+
+
/* **************************************************************** *\
@@ -155,9 +490,9 @@
$(document).keydown(function(e) {
//e = e ? e : window.event;
x6.console.group("Document Keydown");
- if(u.bb.vgfGet('noKeyPress',false)==true) {
+ if(x6bb.fwGet('noKeyPress',false)==true) {
x6.console.log("noKeyPress was set, ignoring");
- u.bb.vgfSet('noKeyPress',false);
+ x6bb.fwSet('noKeyPress',false);
}
else {
// no log entry, key dispatcher does that
@@ -173,9 +508,9 @@
// Initialize an object that has been sent from the server
initOne: function(id) {
- var obj = u.byId(id);
- var pin = u.p(obj,'x6plugin');
- obj.zTable = u.p(obj,'x6table');
+ var obj = x6.byId(id);
+ var pin = x6.p(obj,'x6plugin');
+ obj.zTable = x6.p(obj,'x6table');
x6.console.log(pin,obj.zTable);
x6.console.log(obj);
x6plugins[pin](obj,obj.id,obj.zTable);
@@ -200,10 +535,10 @@
else {
var z=0;
while(z < x.length) {
- if(u.p(x[z],'id','').trim()!='') break;
+ if(x6.p(x[z],'id','').trim()!='') break;
z++;
}
- if(u.p(x[z],'id','').trim() !='') {
+ if(x6.p(x[z],'id','').trim() !='') {
x[z].focus();
}
}
@@ -223,7 +558,16 @@
}
}
+ // Trap IE/Firefox refresh buttons so they work
+ // the same on both platforms.
+ if(retval=='ShiftF5' && !window.androIsIE) {
+ window.location.reload(true);
+ }
+ if(retval=='CtrlF5' && window.androIsIE) {
+ window.location.reload(true);
+ }
+
// Make list of keys to stop no matter what
var stopThem = [ 'CtrlF5', 'F10' ];
@@ -231,7 +575,8 @@
'CtrlS', 'CtrlN', 'CtrlI', 'CtrlD',
'CtrlL', 'CtrlO', 'CtrlW', 'CtrlP',
'CtrlQ', 'CtrlR', 'CtrlU', 'CtrlK',
- 'CtrlY'
+ 'CtrlY',
+ 'DownArrow','UpArrow'
];
// Set a flag now. If user hit ESC, we are trying
@@ -239,7 +584,7 @@
// cannot do so.
if(retval=='Esc') {
x6.console.log("Esc key pressed, pre-seting exitApproved=true");
- u.bb.vgfSet('exitApproved',true);
+ x6bb.fwSet('exitApproved',true);
}
// Now we have a complete key label, fire the event
@@ -255,18 +600,18 @@
// for that, because if it came back true we will exit,
// but otherwise we cannot.
if(retval=='Esc') {
- var exitApproved = u.bb.vgfGet('exitApproved',false);
+ var exitApproved = x6bb.fwGet('exitApproved',false);
x6.console.log("Key dispatch, ESC, exitapproved: ",exitApproved);
if(exitApproved) {
x6.console.log("exit for ESC was approved, going to menu");
setTimeout(
function() {
- var x6page_prior=u.p(u.byId('x6page'),'value');
- var x6mod_prior =u.p(u.byId('x6module'),'value');
+ var x6page_prior=x6.p(x6.byId('x6page'),'value');
+ var x6mod_prior =x6.p(x6.byId('x6module'),'value');
var str = '?x6page=menu'
+'&x6page_prior='+x6page_prior
+'&x6mod_prior='+x6mod_prior;
- //window.location.replace(str);
+ window.location.replace(str);
}
,10
);
@@ -293,6 +638,8 @@
return true;
},
+
+
/*
* The console object starts out with do-nothing functions.
* These are replaced if the console object exists.
@@ -537,7 +884,728 @@
keyIsMeta: function(e) {
var code = e.keyCode || e.charCode;
return typeof(this.metaKeys[code])!='undefined';
- }
+ },
+
+ /****m* x6/uniqueId
+ * NAME
+ * x6.uniqueId
+ *
+ * FUNCTION
+ * Generates a random number between 1 and 1,000,000 that is
+ * not being used as the ID for any DOM object. Useful for
+ * generating unique and content-free Id's for DOM objects.
+ *
+ * EXAMPLE
+ * Example usage would be:
+ *
+ * var x = document.createElement('div');
+ * x.id = x6.uniqueId();
+ *
+ * RESULT
+ * id - returns the id
+ *
+ * SOURCE
+ */
+ uniqueId: function() {
+ var retval = 0;
+ while( $('#'+retval).length > 1 || retval==0) {
+ var retval=Math.floor(Math.random()*1000000);
+ }
+ return retval;
+ },
+ /******/
+
+ /*
+ * KFD 1/13/09. We put this here so we do not have to
+ * load up androLib.js anymore. We will
+ * gradually eliminate use of this function
+ * and make it go away. We will use
+ * $(id)... instead.
+ */
+ byId: function(id) {
+ return document.getElementById(id );
+ },
+
+ p: function(obj,propname,defvalue) {
+ if(typeof(obj)!='object') {
+ return defvalue;
+ }
+
+ // First try, maybe it is a direct property
+ if(typeof(obj[propname])!='undefined') {
+ return obj[propname];
+ }
+ // Second try, maybe it is an attribute
+ if(obj.getAttribute) {
+ if(obj.getAttribute(propname)!=null) {
+ return obj.getAttribute(propname);
+ }
+ }
+ // Give up, return the defvalue
+ return defvalue;
+ },
+
+ openWindow: function(url) {
+ window.open(url);
+ },
+
+ /****O* ua/json
+ *
+ * NAME
+ * x6.json
+ *
+ * FUNCTION
+ * The Javascript object x6.json is used to send any request
+ * to the web server, either for a new complete page or for
+ * data and HTML fragments.
+ * Examples include requesting a single row from a table,
+ * requesting search results, fetching HTML fragments, or
+ * popping up a new window.
+ *
+ * Andromeda uses the term JSON instead of AJAX because
+ * the term AJAX does not describe how Andromeda works.
+ * Specifically, Andromeda PHP pages return JSON data
+ * instead of XML (hence no "X" in AJA"X"), and many calls
+ * are actually synchronous (hence no "A" in "A"JAX).
+ *
+ * The x6.json object is always present on all pages, and
+ * you can use it in Javascript code on any custom page.
+ *
+ * NOTES
+ * Andromeda handles all of the values returned in the
+ * request automatically. On custom pages you do not have
+ * to code a response handler because Andromeda handles
+ * the response for you.
+ *
+ * The PHP code that handles a JSON request sends data back
+ * by using the routines x4Debug, x4Data, x4HTML, x4Script,
+ * x4Error. While the complete PHP-API documentation on
+ * those functions will give you most of what you need, we
+ * must note here how the returned data is handled:
+ * * x4Debug - ignored, but you can examine the results in
+ * firebug.
+ * * x4Error - any errors sent back by this function are reported
+ * to the user and x6.json.execute returns false.
+ * * x4HTML - calls to this function in PHP code provide an
+ * element Id and a fragment of HTML. The HTML replaces the
+ * innerHTML of the specific item.
+ * * x4Data - calls to this function in PHP code provide a name
+ * and some data value (including arrays and objects). The
+ * result can be examined when the call completes in x6.data.<name>.
+ * * x4Script - provides script that should execute on the browser
+ * when the call returns.
+ *
+ * EXAMPLE
+ *
+ * The basic usage of x6.json is to initialize a call
+ * with x6.json.init, and then to add parameters with
+ * x6.json.addParm, and finally to execute and process the
+ * call with x6.json.execute and x6.json.process.
+ *
+ * There are also special-purpose methods like x6.json.inputs
+ * that will take all of the inputs inside of an object and
+ * add them to the request.
+ *
+ * You can also use the function x6.json.windowLocation to
+ * execute the call as a new page request, and x6.json.newWindow
+ * to execute the call as a new page request in a tab.
+ *
+ * <script>
+ * // Initialize the call
+ * x6.json.init('x4Page','myCustomPage');
+ * // Name the server-side PHP method to call
+ * x6.json.addParm('x4Action','getSomething');
+ * // Add some parms
+ * x6.json.addParm('parm1','value');
+ * x6.json.addParm('parm2','value');
+ * // Execute and process in one step. Note that this
+ * // is synchronous, there is no need for a callback
+ * // function.
+ * x6.json.execute(true);
+ *
+ * for(var x in x6.data.returnedStuff) {
+ * ....
+ * }
+ * </script>
+ *
+ * This call requires an Extended-Desktop page to be defined
+ * in PHP that will service the request. A super-simple example
+ * is here, more information is provided in the
+ * Extended-Desktop documentation.
+ *
+ * <?php
+ * # This is file application/x4MyCustomPage.php
+ * class x4MyCustomPage extends androX4 {
+ * # this function handles the call given above
+ * function getSomething() {
+ * $parm1 = gp('parm1');
+ * $parm2 = gp('parm2');
+ * $sql = "Select blah blah blah";
+ * $rows = SQL_AllRows($sql);
+ * x4Data('returnedStuff',$rows
+ * }
+ * }
+ * ?>
+ *
+ * Sometimes you make a call that returns replacement HTML
+ * for a single object. In this case your PHP code supplies
+ * the HTML by calling x4HTML with the value of '*MAIN*' for
+ * the first parameter, as in x4HTML('*MAIN*',$html);
+ * Such a call is handled this way in script:
+ *
+ * <script>
+ * x6.json.init('x4Page','myCustomPage');
+ *
+ * // We need the conditional in case the server returns
+ * // an error and we should not replace the html
+ * if(x6.json.execute()) {
+ * x6.json.process('nameofItemToReplace');
+ * }
+ * </script>
+ *
+ ******
+ */
+ data: { }, // required for json
+ json: {
+ callString: '',
+ http: false,
+ active: false,
+ jdata: { },
+ data: { dd: {} },
+ requests: { },
+ parms: { },
+ reportErrors: true,
+ x4Page: '',
+ x4Action: '',
+ explicitParms: '',
+ hadErrors: false,
+
+ /****m* json/init
+ *
+ * NAME
+ * x6.json.init
+ *
+ * FUNCTION
+ * The Javascript method x6.json.init initiates a new
+ * JSON request.
+ *
+ * Optionally you can pass two inputs and eliminate one
+ * call to x6.json.addParm.
+ *
+ * INPUTS
+ * string - if provided, a parameter name
+ * mixed - if provided, the value for the parameter
+ *
+ * EXAMPLE
+ * Here are two examples for initiating a JSON request
+ *
+ * <script>
+ * // The short way
+ * x6.json.init('x4Page','myCustomPage');
+ *
+ * // Passing w/o parameters requires at least one
+ * // call to x6.json.addParm.
+ * x6.json.init();
+ * x6.json.addParm('x4Page','myCustomPage');
+ * </script>
+ *
+ * SOURCE
+ */
+ init: function(name,value) {
+ this.x4Page = '';
+ this.x4Action = '';
+ this.callString = '';
+ this.parms = { };
+ this.reportErrors=true;
+ this.explicitParms= '';
+ if(name!=null) {
+ this.addParm(name,value);
+ }
+ },
+ /******/
+
+ /****** json/addParm
+ *
+ * NAME
+ * x6.json.addParm
+ *
+ * FUNCTION
+ * The Javascript method x6.json.addParm adds one parameter
+ * to a JSON call previously initiated with x6.json.init.
+ *
+ * INPUTS
+ * string - required, a parameter name
+ * mixed - required, the value for the parameter
+ *
+ * EXAMPLE
+ * Here are two examples for initiating a JSON request
+ *
+ * <script>
+ * x6.json.init();
+ * // Name the server-side page to call
+ * x6.json.addParm('x4Page','myCustomPage');
+ * // Name the server-side method to call
+ * x6.json.addParm('x4Action','fetchSomething');
+ * </script>
+ *
+ * SOURCE
+ */
+ addParm: function(name,value) {
+ this.parms[name] = value;
+ if(name=='x4Page') this.x4Page = value;
+ if(name=='x4Action') this.x4Action = value;
+ },
+ /******/
+
+ makeString: function() {
+ if(this.explicitParms!='') {
+ return this.explicitParms;
+ }
+ var list = [ ];
+ for(var x in this.parms) {
+ list[list.length] = x + "=" +encodeURIComponent(this.parms[x]);
+ }
+ return list.join('&');
+ },
+ //addValue: function(name,value) {
+ // if(this.callString!='') this.callString+="&";
+ // this.callString += 'x4c_' + name + '=' + encodeURIComponent(value);
+ //},
+
+ /****** json/inputs
+ *
+ * NAME
+ * x6.json.inputs
+ *
+ * FUNCTION
+ * The Javascript method x6.json.inputs adds inputs to
+ * a JSON call previously initiated with x6.json.init.
+ *
+ * This method accepts an object as its parameter, and
+ * will add every input that is a child (at any level)
+ * of that object.
+ *
+ * This method uses the "id" property of the input to
+ * name the parameter, not the "name" property. Andromeda
+ * makes no use of the "name" property.
+ *
+ * This method is equivalent to use x6.json.addParm
+ * for each of the desired inputs.
+ *
+ * Checkboxes receive special treatment. If the box is
+ * checked a value of 'Y' is sent, and if the box is not
+ * checked a value of 'N' is sent.
+ *
+ * The name of each parameter is normally the Id of the
+ * input. If the inputs were generated by Andromeda
+ * on an Extended-Desktop page, they will have the names
+ * 'x4inp_<tableId>_<columnId>.
+ *
+ * INPUTS
+ * object - optional, the object to recurse. You must
+ * pass the object itself, not its Id. If no object is
+ * passed the Extended-Desktop top-level object x4Top
+ * is used, which means you get every input on the page,
+ * whether or not it is visible or
+ *
+ * direct - a special flag that says to name the parameters
+ * 'x4c_<columnId>'. This is required when you are sending
+ * Direct-Database-Access calls.
+ *
+ *
+ * SOURCE
+ */
+ inputs: function(obj,direct) {
+ if(direct==null) direct=false;
+ if(obj==null) {
+ if(x6.byId('x4Top')!=null) {
+ obj = x6.byId('x4Top');
+ }
+ else {
+ obj = $('.x6main')[0];
+ }
+ }
+ if(typeof(obj)=='string') {
+ if(obj.indexOf('input')==-1) {
+ var jqObjects = $(obj).find(':input');
+ }
+ else {
+ var jqObjects = $(obj);
+ }
+ }
+ else {
+ var jqObjects = $(obj).find(":input");
+ }
+ jqObjects.each( function() {
+ if(direct)
+ var id = 'x4c_'+x6.p(this,'xColumnId');
+ else
+ var id = this.id;
+
+
+ if(this.type=='checkbox') {
+ if(this.checked) {
+ x6.json.addParm(id,'Y');
+ }
+ else {
+ x6.json.addParm(id,'N');
+ }
+ }
+ else {
+ if(typeof(x6)=='undefined') {
+ if(this.value!='') {
+ x6.json.addParm(id,this.value);
+ }
+ }
+ else {
+ var zOrig = x6.p(this,'zOriginalValue','').trim();
+ if(this.value.trim()!=zOrig) {
+ x6.json.addParm(id,this.value);
+ }
+ }
+ }
+ });
+ },
+ /******/
+
+ /****** json/serialize
+ *
+ * NAME
+ * x6.json.serialize
+ *
+ * FUNCTION
+ * The Javascript method x6.json.serialize takes a
+ * Javascript Object or Array and serializes it and
+ * adds the values to a JSON request previously
+ * initialized with x6.json.init.
+ *
+ * This method accepts an object as its parameter.
+ *
+ * When you call this function, the parameters sent
+ * back take the form of an associative array.
+ *
+ * INPUTS
+ * prefix - The base name of the parameter
+ *
+ * object - the object to serialize.
+ *
+ * EXAMPLE
+ * Consider the following object that is serialized
+ *
+ * <script>
+ * var x = {
+ * parm1: [ 1, 2, 3],
+ * parm2: 'hello',
+ * parm3: {
+ * x: 5,
+ * y: 10,
+ * }
+ * x6.json.init('x4Page','myCustomPage');
+ * x6.json.addParm('x4Action','serialHandler');
+ * x6.json.serialize('example',x);
+ * <script>
+ *
+ * Then on the server, you can grab the "example" parameter
+ * and you will get the following associative array:
+ *
+ * <?php
+ * # this is file x4myCustomPage.php
+ * class x4myCustomPage extends androX4 {
+ *
+ * # this handles the 'x4Action' specified above
+ * function serialHandler() {
+ * $example = gp('example');
+ *
+ * # ...the following code shows how
+ * # the values that are in x4
+ * $example['parm1'][0] = 1;
+ * $example['parm1'][1] = 2;
+ * $example['parm1'][2] = 3;
+ * $example['parm2'] = 'hello';
+ * $example['parm3']['x'] = 5;
+ * $example['parm3']['y'] = 10;
+ * }
+ * }
+ * ?>
+ *
+ * SOURCE
+ */
+ serialize: function(prefix,obj) {
+ for(var x in obj) {
+ if(typeof(obj[x])=='object') {
+ this.serialize(prefix+'['+x+']',obj[x]);
+ }
+ else {
+ this.addParm(prefix+'['+x+']',obj[x]);
+ }
+ }
+ },
+ /******/
+
+ /****** json/windowLocation
+ *
+ * NAME
+ * x6.json.windowLocation
+ *
+ * FUNCTION
+ * The Javascript method x6.json.windowLocation takes a
+ * JSON request and executes it as a page request.
+ *
+ * EXAMPLE
+ * The following example loads a new page
+ *
+ * <script>
+ * x6.json.init('x4Page','calendar');
+ * x6.json.windowLocation();
+ * </script>
+ *
+ * SOURCE
+ */
+ windowLocation: function() {
+ var entireGet = 'index.php?'+this.makeString()
+ window.location = entireGet;
+ },
+ /******/
+
+ /****** json/newWindow
+ *
+ * NAME
+ * x6.json.newWindow
+ *
+ * FUNCTION
+ * The Javascript method x6.json.newWindow takes a
+ * JSON request and executes it as a page request, popping
+ * the result up in a new tab or window.
+ *
+ * When the user exits the resulting tab or window, it
+ * will close.
+ *
+ * EXAMPLE
+ * The following example loads a new page
+ *
+ * <script>
+ * x6.json.init('x4Page','calendar');
+ * x6.json.newWindow();
+ * </script>
+ *
+ * SOURCE
+ */
+ newWindow: function() {
+ var entireGet = 'index.php?'+this.makeString()+'&x4Return=exit';
+ $a.openWindow(entireGet);
+ },
+ /******/
+
+ /****** json/executeAsync
+ *
+ * NAME
+ * x6.json.executeAsync
+ *
+ * FUNCTION
+ * By default Andromeda sends JSON requests synchronously,
+ * which is more appropriate for business database applications
+ * than asynchronous requests.
+ *
+ * There are however some times when you do not want the user
+ * to wait, and so you can make asynchronous calls.
+ *
+ * Andromeda does not make use of response handlers, see the
+ * above section on x6.json for more details.
+ *
+ * SOURCE
+ */
+ executeAsync: function() {
+ this.execute(true,true);
+ },
+ /******/
+
+ /****** json/execute
+ *
+ * NAME
+ * x6.json.execute
+ *
+ * FUNCTION
+ * The Javascript method x6.json.execute sends a request to
+ * the server that has been initialized with x6.json.init
+ * and has received parameters with any of x6.json.addParm,
+ * x6.json.inputs and x6.json.serialize.
+ *
+ * In normal usage, you call this routine and check for
+ * a return value of true. If the routine returns true
+ * you call x6.json.process to process the returned
+ * results.
+ *
+ * RESULTS
+ * This routine returns true if the server reports no
+ * errors.
+ *
+ * If the server reports errors, they are displayed to the
+ * user using u.dialogs.alert, and this routine returns
+ * false.
+ *
+ *******
+ */
+ execute: function(autoProcess,async) {
+ this.hadErrors = false;
+ if(async==null) async = false;
+ if(autoProcess==null) autoProcess=false;
+
+ // Create an object
+ var browser = navigator.appName;
+ if(browser == "Microsoft Internet Explorer"){
+ // KFD 11/24
+ var http = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ // KFD 11/24
+ var http = new XMLHttpRequest();
+ }
+ // KFD 7/8/08, When the user is clicking on
+ // search boxes, they can click faster
+ // than we can get answers, so if
+ // we notice we are running an action
+ // that is already in progress, we
+ // cancel the earlier action.
+ var key = this.x4Page + this.x4Action;
+ if( typeof(this.requests[key])!='undefined') {
+ this.requests[key].abort();
+ }
+ this.requests[key] = http;
+
+ // If async, we have to do it a little differently
+ // KFD 11/24, did nothing yet for async
+ if(async) {
+ http.onreadystatechange = function() {
+ if(this.readyState!=4) return;
+ x6.json.processPre(this,key,false);
+ x6.json.process();
+ }
+ }
+
+ // Execute the call
+ var entireGet = 'index.php?json=1&'+this.makeString();
+ http.open('POST' , entireGet, async);
+ http.send(null);
+
+ // KFD 11/24A
+ this.active = false;
+
+
+ // An asynchronous call now exits, but a
+ // synchronous call continues
+ if (async) return;
+ else return this.processPre(http,key,autoProcess);
+
+ },
+
+ processPre: function(http,key,autoProcess) {
+ // Attempt to evaluate the JSON
+ try {
+ eval('this.jdata = '+http.responseText);
+ }
+ catch(e) {
+ x6dialogs.alert("Could not process server response!");
+ if(x6.byId('x6Log')) {
+ x6.byId('x6Log').innerHTML = http.responseText;
+ x6.byId('x6Log').style.display='block';
+ }
+ return false;
+ }
+
+ // KFD 7/8/08, additional housekeeping, throw away
+ // references to the object
+ delete this.requests[key];
+ delete http;
+
+ // If there were server errors, report those
+ if(this.jdata.error.length>0 && this.reportErrors) {
+ this.hadErrors = true;
+ $a.dialogs.alert(this.jdata.error.join("\n\n"));
+ return false;
+ }
+ if(this.jdata.notice.length>0 && this.reportErrors) {
+ $a.dialogs.alert(this.jdata.notice.join("\n\n"));
+ }
+
+ if(autoProcess) {
+ this.process();
+ }
+
+ return true;
+ },
+
+ /****** json/process
+ *
+ * NAME
+ * x6.json.process
+ *
+ * FUNCTION
+ * The Javascript method x6.json.execute is the final
+ * step in sending and receiving JSON requests. This
+ * routine does the following:
+ * * Any HTML sent back via PHP x4HTML replaces the
+ * innerHTML of the named items (actually item Ids are used).
+ * * Any script sent back via PHP x4Script is executed.
+ * * Any data sent back via PHP x4Data is placed into
+ * x6.data.
+ *
+ * EXAMPLE
+ * This example shows how you can retrieve table data and
+ * then process it:
+ *
+ * <script>
+ * x6.json.init('x4Page','myCustomPage');
+ * x6.json.addParm('x4Action','getStates');
+ * // x6.json.execute will return false on errors
+ * if(x6.json.execute()) {
+ * // x6.json.process puts everything in its place...
+ * x6.json.process();
+ * // ...so that we can handle the returned data
+ * for (var idx in x6.data.states) {
+ * // do something
+ * }
+ * }
+ * <script>
+ *
+ * This code requires the following PHP code on the server:
+ *
+ * <?php
+ * # this is file application/x4myCustomPage.php
+ * class x4myCustomPage extends androX4 {
+ * function getStates() {
+ * $states = SQL("Select * from states");
+ * x4Data('states',$states);
+ * }
+ * }
+ *
+ *******
+ */
+ process: function(divMain) {
+ for(var x in this.jdata.html) {
+ if(x=='*MAIN*') {
+ $('#'+divMain).html(this.jdata.html[x]);
+ }
+ else {
+ var obj = x6.byId(x);
+ if(obj) {
+ if (obj.tagName =='INPUT') {
+ obj.value = this.jdata.html[x];
+ }
+ else {
+ obj.innerHTML = this.jdata.html[x];
+ }
+ }
+ }
+ }
+
+ // Execute any script that was provided
+ for(var x in this.jdata.script) {
+ eval(this.jdata.script[x]);
+ }
+
+ return true;
+ }
+ },
}
/* **************************************************************** *\
@@ -648,7 +1716,432 @@
if(readCookie('log_Warn') ==1) x6.console.enableWarn = true;
if(readCookie('log_Error')==1) x6.console.enableError = true;
+/****O* Javascript-API/x6dialogs
+*
+* NAME
+* Javascript-API/x6dialogs
+*
+* FUNCTION
+* The two Javascript dialogs x6dialogs.alert and
+* x6dialogs.confirm replace the Javascript native functions
+* alert() and confirm().
+*
+* The third dialog, x6dialogs.pleaseWait, puts up a
+* suitable notice if your application must do something that
+* will take more than 1-2 seconds.
+*
+* They are all fully modal, respond to appropriate keystrokes
+* like 'Y', 'N', 'Enter' and 'Esc', and maintain the same
+* style as the rest of the template.
+*
+* PORTABILITY
+* The x6dialogs object expects your HTML to contain two
+* invisible (display:none) divs. One is called "dialogoverlay"
+* and the other is called "dialogbox". These two divs are
+* provided by default on Andromeda templates. If you make
+* your own template and include androHTMLFoot.php at the bottom
+* then your templates will also have these divs.
+*
+* Making a page fully modal is difficult, because if an INPUT
+* has focus it will be possible for the user to use the keyboard
+* to navigate around. Therefore the code in x4 checks
+* the x6dialogs.currentDialog property, and disallow all activity
+* if that property is not false. If you make your own
+* custom pages that are not Extended Desktop pages, you must have
+* your input's onkeyPress methods also check this property.
+*
+* If this object is used outside of Andromeda, you must have
+* the file phpWait.php in your public web root, otherwise the
+* x6dialogs.confirm function will not work.
+*
+******
+*/
+x6dialogs = {
+ /** NO DOC **/
+ id: 'u_dialogs',
+ answer: null,
+ json: null,
+
+ /****v* dialogs/currentDialog
+ *
+ * NAME
+ * u.events.currentDialog
+ *
+ * FUNCTION
+ * This Javascript property will hold any of the value of:
+ * * false, no dialog is active
+ * * alert, an alert dialog is active
+ * * confirm, a confirm dialog is active
+ * * pleaseWait, a "Please Wait" box is being displayed
+ *
+ ******
+ */
+ currentDialog: false,
+
+ /****v* dialogs/clear
+ *
+ * NAME
+ * u.events.clear
+ *
+ * FUNCTION
+ * The Javascript Method u.events.clear
+ * clears the current modal dialog.
+ *
+ * The two dialogs x6dialogs.alert and x6dialogs.confirm are
+ * cleared by user action. But the x6dialogs.pleaseWait
+ * dialog will remain on the screen until your application
+ * Javascript code clears it by calling this method.
+ *
+ * INPUTS
+ * ignore - This method accepts a paremeter that is useful
+ * only to the framework when managing a confirm dialog.
+ *
+ * SOURCE
+ */
+ clear: function(answer) {
+ this.answer = answer;
+ this.currentDialog = false;
+
+ $('#dialogbox,#dialogoverlay').css('display','none');
+ },
+ /******/
+
+ prepare: function(type) {
+ // Tell the master what we are doing,
+ // and suppress all keystrokes except ENTER and ESC
+ this.currentDialog = type;
+ // Get some basic heights and widths
+ var wh = $(window).height();
+ var ww = $(window).width();
+
+ // Make complete assignment to the overlay
+ $('#dialogoverlay')
+ .css('position','absolute')
+ .css('top',0)
+ .css('left',0)
+ .css('width' ,ww)
+ .css('height',wh)
+ .css('background-color','black')
+ .css('opacity',0)
+ .css('display','')
+ .css('z-index',500);
+
+ // Get height and width of the inner guy and center him
+ var ch = $('#dialogbox').height();
+ $('#dialogbox').css('width',300);
+ cw = 300;
+
+ // Center and otherwise prepare the box
+ $('#dialogbox')
+ .css('position','absolute')
+ .css('top' , 300)
+ .css('left', (ww - cw)/2)
+ .css('opacity',0)
+ .css('display','')
+ .css('z-index',501)
+ .addClass('dialog');
+ x6.byId('dialogbox').notify = function(eventName,args) {
+ if(this.currentDialog == 'alert') {
+ if(eventName == 'keyPress_Enter') {
+ this.clear();
+ return true;
+ }
+ if(eventName == 'keyPress_Esc') {
+ this.clear();
+ return true;
+ }
+ }
+ if(x6dialogs.currentDialog == 'confirm') {
+ if(eventName == 'keyPress_Y') {
+ this.clear(true);
+ return true;
+ }
+ if(eventName == 'keyPress_N') {
+ this.clear(false);
+ return true;
+ }
+ }
+ return false;
+ }
+ },
+
+ /****m* dialogs/alert
+ *
+ * NAME
+ * x6dialogs.alert
+ *
+ * FUNCTION
+ * The Javascript method x6dialogs.alert replaces the native
+ * Javascript alert() function with one that is stylistically
+ * consistent with the rest of the application.
+ *
+ * Unlike Javascript's native alert() function, execution
+ * continues after you call this function. The user must
+ * clear it by clicking the OK button, hitting Enter, or
+ * hitting Esc.
+ *
+ * When this alert is active, all keyboard events are
+ * suppressed except Enter and Esc.
+ *
+ * EXAMPLE
+ * Here is a usage example:
+ *
+ * x6dialogs.alert("New data has been saved");
+ * // maybe do some other stuff while
+ * // waiting for the user
+ * u.events.notify('myEventName',objParms);
+ *
+ ******
+ */
+ alert: function(msg) {
+ alert(msg);
+ return;
+ },
+
+ /****m* dialogs/confirm
+ *
+ * NAME
+ * x6dialogs.confirm
+ *
+ * FUNCTION
+ * The Javascript method x6dialogs.confirm replaces the native
+ * Javascript confirm() function with one that is stylistically
+ * consistent with the rest of the application.
+ *
+ * Like Javascript's native confirm() function, execution
+ * *stops* until the user answers the question. This makes
+ * coding far easier because you do not have to code
+ * anonymous callback functions.
+ *
+ * When this alert is active, all keyboard events are
+ * suppressed except 'Y' and 'N'.
+ *
+ * EXAMPLE
+ * Here is a usage example:
+ *
+ * if(x6dialogs.confirm("Do you really want to delete?")) {
+ * // code to delete
+ * }
+ * else {
+ * u.events.debug("user chose not to delete");
+ * }
+ *
+ * PORTABILITY
+ * Javascript does not natively support an elegant way to
+ * pause execution. For instance, it does not have a
+ * "sleep" function that would allow a low-CPU idefinite
+ * loop to be executing while waiting for user input.
+ *
+ * We could solve this by throwing caution to the wind and
+ * doing an indefinite loop anyway, which checks over and over
+ * to see if the user has responded, but this spikes CPU usage
+ * and is very bad form.
+ *
+ * The technique used by x6dialogs.confirm is unusual, but it
+ * has the benefit of being extremely low on CPU power and
+ * extremely low on network bandwidth. The approach contains
+ * an indefinite loop that makes a call to the program
+ * phpWait.php, which does a sleep for 1/4 second and returns.
+ * Even at four calls per second, the overall CPU and network
+ * bandwidth is practically zero.
+ *
+ * Therefore, x6dialogs.confirm has a dependency that the
+ * php file phpWait.php be present in the web server's public
+ * root. This is handled automatically by Andromeda, but you
+ * must provide such a file if you use this object in
+ * a non-Andromeda application.
+ *
+ ******
+ */
+ confirm: function(msg,options) {
+ return confirm(msg);
+ },
+
+ /****m* dialogs/pleaseWait
+ *
+ * NAME
+ * x6dialogs.pleaseWait
+ *
+ * FUNCTION
+ * The Javascript method x6dialogs.pleaseWait is not,
+ * strictly speaking, a dialog, because it does not require
+ * any user feedback, and in fact does not even allow it.
+ *
+ * When you call x6dialogs.pleaseWait, a modal box pops up
+ * that is stylistically consistent with the overall template
+ * and which has an animated gif and the message "Please Wait".
+ *
+ * Use this method when you are executing a long-running
+ * (greater than 2-3 seconds) process and you must let the
+ * user know the program is working on something.
+ *
+ * The user cannot clear this display. You must clear it
+ * yourself when work has been completed by calling
+ * x6dialogs.clear().
+ *
+ * EXAMPLE
+ * Here is a usage example:
+ *
+ * x6dialogs.pleaseWait();
+ * for(var x in rowsToSave()) {
+ * // some actions to save to server
+ * }
+ * x6dialogs.clear();
+ *
+ ******
+ */
+ pleaseWait: function(msg) {
+ if(msg==null) msg = "Please Wait...";
+ this.prepare('pleaseWait');
+
+ // Create the content for the dialog itself
+ var html =
+ "<center><br/>"
+ +"<img src='clib/ajax-loader.gif'>"
+ +"<br/><br/>"
+ +msg+"<br/><br/>"
+ +"</center>";
+
+ x6.byId('dialogbox').innerHTML=html;
+
+ // Finally, display the dialog
+ $('#dialogoverlay').css('opacity',0.4);
+ $('#dialogbox').css( 'opacity',1);
+ }
+}
+
+/****O* u/bb
+* NAME
+* x6bb
+*
+* FUNCTION
+* "Bulletin Board" object that lets you "stick" values on it
+* and "grab" them from elsewhere.
+*
+* x6bb methods should be used instead of global variables
+* because they allow you to avoid collisions with framework
+* globals. The framework uses the methods x6bb.fwGet
+* and x6bb.fwSet, and your application should use x6bb.appGet
+* and x6bb.appSet.
+*
+* EXAMPLE:
+* Example usage:
+* x6bb.appSet('myvar','value');
+* var myvar = x6bb.appGet('myvar','acceptableDefault');
+*
+******
+*/
+x6bb = {
+ /****v* x6bb/fwvars
+ * NAME
+ * x6bb.fwvars
+ *
+ * FUNCTION
+ * Global bulletin board framework variables. Not intended
+ * for direct access, manipulate at your own risk!
+ ******
+ */
+ fwvars: { },
+ /****v* x6bb/appvars
+ * NAME
+ * x6bb.appvars
+ *
+ * FUNCTION
+ * Global bulletin board application variables. Not intended
+ * for direct access, manipulate at your own risk!
+ ******
+ */
+ appvars: { },
+ /****m* x6bb/vgfSet
+ * NAME
+ * x6bb.vgfSet
+ *
+ * FUNCTION
+ * Used by the Andromeda framework to save global variables
+ * for later use. Application code should never use this,
+ * or you risk overwriting framework values and disrupting
+ * normal performance.
+ *
+ * INPUTS
+ * varName - The name of your variable
+ * varValue - The value to store
+ *
+ * SOURCE
+ */
+ fwSet: function(varName,value) {
+ this.fwvars[varName] = value;
+ },
+ /******/
+
+ /****m* x6bb/vgfGet
+ * NAME
+ * x6bb.vgfGet
+ *
+ * FUNCTION
+ * Retrieves a variable saved by the framework.
+ *
+ * Unlike vfgSet, which application code should never call,
+ * it may be appropriate from time-to-time to call this
+ * function to find out what the framework is up to.
+ *
+ * INPUTS
+ * varName - the variable you wish to retrieve
+ * defValue - the value to return if the variable does not exist.
+ *
+ * SOURCE
+ */
+ fwGet: function(varName,defValue) {
+ var retval = x6.p(this.fwvars,varName,defValue);
+ //if(typeof(console)!='undefined') {
+ // console.log("vgfGet",varName,retval,defValue);
+ //}
+ return retval;
+ },
+ /******/
+
+ /****m* x6bb/vgaSet
+ * NAME
+ * x6bb.vgaSet
+ *
+ * FUNCTION
+ * Sets a global variable. Globals saved with this method
+ * will not collide with any framework globals.
+ *
+ * INPUTS
+ * varName - the variable you wish to save
+ * varValue - the value to save
+ *
+ * SOURCE
+ */
+ appSet: function(varName,value) {
+ this.appvars[varName] = value;
+ },
+ /******/
+
+
+ /****m* bb/vgaGet
+ * NAME
+ * x6bb.vgaGet
+ *
+ * FUNCTION
+ * Retrieves a global variable, or the default value
+ * if the global has not been set.
+ *
+ * INPUTS
+ * varName - the variable you wish to save
+ * defValue - the value to return if the global does
+ * not exist.
+ *
+ * SOURCE
+ */
+ appGet: function(varName,defValue) {
+ return x6.p(this.appvars,varName,defValue);
+ }
+ /******/
+}
+
+
/****O* Javascript-API/x6events
*
* NAME
@@ -739,13 +2232,13 @@
x6.console.log("event name: ",eventName)
x6.console.log("id subscriber: ",id);
if(id=='undefined') {
- u.error('x6events.subscribeToEvent. Second parameter '
+ x6.console.error('x6events.subscribeToEvent. Second parameter '
+' undefined. First parameter: '+eventName
);
return;
}
if(id==null) {
- u.error('x6events.subscribeToEvent. Second parameter '
+ x6.console.error('x6events.subscribeToEvent. Second parameter '
+' null. First parameter: '+eventName
);
return;
@@ -753,7 +2246,7 @@
// First determine if we have any listeners for this
// event at all. If not, make up the empty object
- if( u.p(this.subscribers,eventName,null)==null) {
+ if( x6.p(this.subscribers,eventName,null)==null) {
this.subscribers[eventName] = [ ];
}
if(this.subscribers[eventName].indexOf(id)==-1) {
@@ -764,7 +2257,7 @@
/******/
unsubscribeToEvent: function(eventName,id) {
- var subs = u.p(this.subscribers,eventName);
+ var subs = x6.p(this.subscribers,eventName);
if( subs!=null) {
var i = this.subscribers[eventName].indexOf(id);
if(i >= 0) {
@@ -792,7 +2285,7 @@
* SOURCE
*/
getSubscribers: function(eventName) {
- return u.p(this.subscribers,eventName,[]);
+ return x6.p(this.subscribers,eventName,[]);
},
/******/
@@ -823,10 +2316,36 @@
*
******
*/
+ makeMap: false,
+ map: [ ],
+ mapStack: [ ],
+ mapClear: function() {
+ this.map = [ { name: 'root', kids: [ ] } ];
+ this.mapStack = [ this.map[0] ];
+ },
+ mapWrite: function(map,indent,level) {
+ if(map ==null) map = this.map;
+ if(level ==null) level = 0;
+ if(indent==null) indent='';
+ var maplen = map.length;
+ for(var x=0; x<maplen; x++) {
+ this.mapWrite(map[x].kids,indent+' ',level+1)
+ }
+
+ },
+
retvals: { },
fireEvent: function(eventName,arguments) {
if(this.eventsDisabled) return;
+ if(this.makeMap) {
+ if(this.map.length==0) this.mapClear();
+ var spot = this.mapStack[this.mapStack.length-1];
+ var len = spot.kids.length;
+ spot.kids[len] = { name: eventName, kids: [ ] };
+ this.mapStack.push(spot.kids[len]);
+ }
+
x6.console.group("fireEvent "+eventName);
x6.console.log('arguments: ',arguments);
// Find out if anybody is listening for this event
@@ -843,7 +2362,7 @@
for(var x=0; x<subscribers.length;x++) {
var id = subscribers[x];
x6.console.log("subscriber: ",id);
- var subscriber = u.byId(id);
+ var subscriber = x6.byId(id);
if(subscriber==null) {
x6.console.error(
"There is no object with that ID, cannot dispatch"
@@ -855,11 +2374,26 @@
var retval = false;
var method = 'receiveEvent_'+eventName;
if(typeof(subscriber[method])=='function') {
+ /*
+ if(this.makeMap) {
+ var spot = this.mapStack[this.mapStack.length-1];
+ var len = spot.length;
+ spot[len] = { name: id, kids: [ ] };
+ this.mapStack.push(spot[len].kids);
+ }
+ */
+
retval = subscriber[method](arguments);
x6.console.log(id,eventName,retval);
+
+ //if(this.makeMap) {
+ // this.mapStack.pop();
+ //}
}
else {
- u.error("Subscriber "+subscriber.id+" has no method: "+method);
+ x6.console.error(
+ "Subscriber "+subscriber.id+" has no method: "+method
+ );
}
if(retval==false) {
x6.console.log('id returned false, setting false');
@@ -867,11 +2401,501 @@
break;
}
}
+
+ if(this.makeMap) {
+ this.mapStack.pop();
+ }
+
x6.console.log("fireEvent ",eventName," RETURNING: ",this.retvals[eventName]);
x6.console.groupEnd();
return this.retvals[eventName];
}
}
+
+
+/* ----------------------------------------------------- *\
+ EXPERIMENTAL, json constructor
+\* ----------------------------------------------------- */
+function x6JSON(parm,value) {
+
+ this.callString = '';
+ this.http = false,
+ this.active =false,
+ this.jdata ={ },
+ this.data ={ dd: {} },
+ this.requests ={ },
+ this.parms ={ },
+ this.reportErrors= true,
+ this.x4Page ='',
+ this.x4Action ='',
+ this.explicitParms= '',
+ this.hadErrors= false,
+
+ /****m* json/addParm
+ *
+ * NAME
+ * x6.json.addParm
+ *
+ * FUNCTION
+ * The Javascript method x6.json.addParm adds one parameter
+ * to a JSON call previously initiated with x6.json.init.
+ *
+ * INPUTS
+ * string - required, a parameter name
+ * mixed - required, the value for the parameter
+ *
+ * EXAMPLE
+ * Here are two examples for initiating a JSON request
+ *
+ * <script>
+ * x6.json.init();
+ * // Name the server-side page to call
+ * x6.json.addParm('x4Page','myCustomPage');
+ * // Name the server-side method to call
+ * x6.json.addParm('x4Action','fetchSomething');
+ * </script>
+ *
+ * SOURCE
+ */
+ this.addParm = function(name,value) {
+ this.parms[name] = value;
+ if(name=='x4Page') this.x4Page = value;
+ if(name=='x4Action') this.x4Action = value;
+ }
+ /******/
+
+ // Original init code
+ this.x4Page = '';
+ this.x4Action = '';
+ this.callString = '';
+ this.parms = { };
+ this.reportErrors=true;
+ this.explicitParms= '';
+ if(parm!=null) {
+ this.addParm(parm,value);
+ }
+ // Create an object
+ var browser = navigator.appName;
+ if(browser == "Microsoft Internet Explorer"){
+ // KFD 11/24
+ this.http = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ // KFD 11/24
+ this.http = new XMLHttpRequest();
+ }
+
+ this.makeString = function() {
+ if(this.explicitParms!='') {
+ return this.explicitParms;
+ }
+ var list = [ ];
+ for(var x in this.parms) {
+ list[list.length] = x + "=" +encodeURIComponent(this.parms[x]);
+ }
+ return list.join('&');
+ }
+ //addValue: function(name,value) {
+ // if(this.callString!='') this.callString+="&";
+ // this.callString += 'x4c_' + name + '=' + encodeURIComponent(value);
+ //},
+
+ /****m* json/inputs
+ *
+ * NAME
+ * x6.json.inputs
+ *
+ * FUNCTION
+ * The Javascript method x6.json.inputs adds inputs to
+ * a JSON call previously initiated with x6.json.init.
+ *
+ * This method accepts an object as its parameter, and
+ * will add every input that is a child (at any level)
+ * of that object.
+ *
+ * This method uses the "id" property of the input to
+ * name the parameter, not the "name" property. Andromeda
+ * makes no use of the "name" property.
+ *
+ * This method is equivalent to use x6.json.addParm
+ * for each of the desired inputs.
+ *
+ * Checkboxes receive special treatment. If the box is
+ * checked a value of 'Y' is sent, and if the box is not
+ * checked a value of 'N' is sent.
+ *
+ * The name of each parameter is normally the Id of the
+ * input. If the inputs were generated by Andromeda
+ * on an Extended-Desktop page, they will have the names
+ * 'x4inp_<tableId>_<columnId>.
+ *
+ * INPUTS
+ * object - optional, the object to recurse. You must
+ * pass the object itself, not its Id. If no object is
+ * passed the Extended-Desktop top-level object x4Top
+ * is used, which means you get every input on the page,
+ * whether or not it is visible or
+ *
+ * direct - a special flag that says to name the parameters
+ * 'x4c_<columnId>'. This is required when you are sending
+ * Direct-Database-Access calls.
+ *
+ *
+ * SOURCE
+ */
+ this.inputs= function(obj,direct) {
+ if(direct==null) direct=false;
+ if(obj==null) {
+ obj = $a.byId('x4Top');
+ }
+ if(typeof(obj)=='string') {
+ var jqObjects = $(obj);
+ }
+ else {
+ var jqObjects = $(obj).find(":input");
+ }
+ jqObjects.each( function() {
+ if(direct)
+ var id = 'x4c_'+x6.p(this,'xColumnId');
+ else
+ var id = this.id;
+
+
+ if(this.type=='checkbox') {
+ if(this.checked) {
+ x6.json.addParm(id,'Y');
+ }
+ else {
+ x6.json.addParm(id,'N');
+ ...
[truncated message content] |