// setup namespace Zymonic.Condition = {}; // base condition // don't do anything here, makes it easy to establish inheritance Zymonic.Condition.Condition = function() {}; // init function Zymonic.Condition.Condition.prototype.init = function(args) { for (var key in args) { this[key] = args[key]; } this.field_lookup_values = null; this.message = {}; if (this.ident != "") { Zymonic.add_to_lookup('Condition', this.ident, this); } // caches this.request_cache = {}; }; // sets/clears field lookup values Zymonic.Condition.Condition.prototype.setFieldLookupValues = function(field_lookup_values) { this.field_lookup_values = field_lookup_values; }; Zymonic.Condition.Condition.prototype.clearFieldLookupValues = function(field_lookup_values) { this.field_lookup_values = null; }; // sets message types Zymonic.Condition.Condition.prototype.setMessage = function(type, message) { this.message[type.toLowerCase()] = message; }; // return the error message run through ll Zymonic.Condition.Condition.prototype.getError = function() { return sub_ll(this.message.failure, { display_name: this.display_name }); }; // gets fields used in this condition Zymonic.Condition.Condition.prototype.getLookupFields = function() { var fields = []; if (this.field_lookup != '') { fields = fields.concat(Zymonic.Utils.getZNameReplacements(this.field_lookup, '\\[\\[', '\\]\\]')) } if (this.desired_value.indexOf('[[') != -1) { fields = fields.concat(Zymonic.Utils.getZNameReplacements(this.desired_value, '\\[\\[', '\\]\\]')); } return fields; }; // is this condition satisfied Zymonic.Condition.Condition.prototype.satisfied = function(lookup_values) { var result = { zname: this.zname, pass: 'FAIL' }; var Parameters = { display_name: this.display_name }; var value_to_check; var intermediate_result; if (this.field_lookup != '' && lookup_values) { value_to_check = Zymonic.Utils.znameReplacement(this.field_lookup, lookup_values, '\\[\\[', '\\]\\]') } else if (this.field_ident != '') { value_to_check = getZymonicField(this.field_ident).getValue(); } else if (this.system_option != '') { value_to_check = this.system_option; } else { intermediate_result = 'FAIL'; } // check if desired value also needs a lookup // TODO: remove the [[ check and have the lookup in itos own field var desired_value = this.desired_value; if (desired_value.indexOf('[[') != -1 && lookup_values) { desired_value = Zymonic.Utils.znameReplacement(desired_value, lookup_values, '\\[\\[', '\\]\\]') } // we pass desired value as a param here so we have scope in future to make the desired value dynamic if (!intermediate_result) { intermediate_result = this.check_result(value_to_check, desired_value); } result.pass = this.final_response(intermediate_result); if (result.pass != 'PASS') { result.error = this.getError() } return result; }; // is this condition satisfied, checking serverside Zymonic.Condition.Condition.prototype.satisfied_server = function(lookup_values) { var result = { zname: this.zname, pass: 'FAIL' }; var Parameters = { display_name: this.display_name }; // build a cache key, add the params we need then form fields to send var request_cache_key = this.block_id + this.zname; var form_data = Zymonic.new_form_data(); form_data.append("ZZwebservicemode", "condition"); form_data.append("ZZBzname", this.zname); form_data.append("ZZFparent_fap_from_block_id", this.block_id); for (var field_zname in this.expected_fields) { var field_value; if (lookup_values && lookup_values[field_zname]) { field_value = lookup_values[field_zname]; } else { field_value = getZymonicField(this.expected_fields[field_zname]).getValue(); } form_data.append('ZZF' + field_zname, field_value); request_cache_key += "&field_zname="+field_zname+"&field_value="+field_value; } // check cache if (!this.no_cache && this.request_cache[request_cache_key]) { if (this.request_cache[request_cache_key] == request_cache_key) { return null; } if (this.request_cache[request_cache_key].request_cache_key == request_cache_key) { return this.request_cache[request_cache_key].result; } } // call the server to run this condition this.request_cache[request_cache_key] = request_cache_key; var condition = this; Zymonic.request( "POST", form_data, false, // TODO: ever async? how would get result? null, null, function(xml) { // find and cache result condition.request_cache[request_cache_key] = new Object(); condition.request_cache[request_cache_key].request_cache_key = request_cache_key; condition.request_cache[request_cache_key].result = new Object(); condition.request_cache[request_cache_key].result.pass = $(xml).find(condition.zname).text(); condition.request_cache[request_cache_key].result.error = ''; condition.request_cache[request_cache_key].result.zname = condition.zname; } ); return this.request_cache[request_cache_key].result; }; // return result of the test between incoming values Zymonic.Condition.Condition.prototype.check_result = function(result, desired) { var as_string = (isNaN(result) ? true : false); if (!as_string) { if ( ( this.test == 'Equals' && result == desired ) || ( this.test == 'NotEquals' && result != desired ) || ( this.test == 'GreaterThanOrEqualTo' && result >= desired ) || ( this.test == 'GreaterThan' && result > desired ) || ( this.test == 'LessThanOrEqualTo' && result <= desired ) || ( this.test == 'LessThan' && result < desired ) || ( this.test == 'DivisibleBy' && !( result % desired ) ) ) { return 'PASS'; } } else { if ( ( this.test == 'Equals' && result == desired ) || ( this.test == 'NotEquals' && result != desired ) || ( this.test == 'GreaterThanOrEqualTo' && result.length >= desired ) || ( this.test == 'GreaterThan' && result.length > desired ) || ( this.test == 'LessThanOrEqualTo' && result.length <= desired ) || ( this.test == 'LessThan' && result.length < desired ) || ( this.test == 'DivisibleBy' && !( result.length % desired ) ) ) { return 'PASS'; } } return 'FAIL'; }; // final result of condition, negated if necessary Zymonic.Condition.Condition.prototype.final_response = function(result) { if (this.negated) { if (result == 'PASS') { result = 'FAIL'; } else { result = 'PASS'; } } return result; } // static function to run multiple conditions, should be run directly not via object // e.g. Zymonic.Condition.check_conditions(...) Zymonic.Condition.check_conditions = function(conditions, condition_combination, lookup_values) { var result = { conditions: {}, condition_combination: condition_combination, condition_passed: false, waiting: false, }; // return true value if no conditions if (conditions.length == 0) { result.condition_passed = true; result.condition_combination = '"PASS" == "PASS"'; return result; } // get results of each condition for (var i=0; i < conditions.length; ++i) { var condition_result = conditions[i].satisfied(lookup_values); if (condition_result == null) { result.waiting = true; return result; } else { result.conditions[condition_result.zname] = condition_result.pass; } } // build condition combination if (condition_combination == '') { var conditions_results = new Array(); for (var c in result.conditions) { if (result.conditions.hasOwnProperty(c)) { conditions_results.push('"'+result.conditions[c]+'" == "PASS"'); } } result.condition_combination = conditions_results.join(" && "); } else { var matches = result.condition_combination.match(/Clause\[(.*?)\]/g); for (var i=0; i < matches.length; ++i) { // JS RE ignores grouping, soneed to parse zname out of Clause[..] var zname = matches[i].replace(/Clause\[(.*?)\]/, '$1'); result.condition_combination = result.condition_combination.replace( new RegExp("Clause\\[" + zname + "\\]", "g"), '"' + result.conditions[zname] + '" == "PASS"' ); } // replace any and with &&, and or with || result.condition_combination = result.condition_combination.replace(/ and /g, ' && '); result.condition_combination = result.condition_combination.replace(/ or /g, ' || '); } // eval the result and return result.condition_passed = eval(result.condition_combination); return result; }