Changeset 581482
- Timestamp:
- 08/03/2012 07:45:52 PM (14 years ago)
- Location:
- jazzy-forms/trunk
- Files:
-
- 1 added
- 10 edited
-
back/gui.css (modified) (1 diff)
-
back/img/a.png (added)
-
back/tpl-forms.php (modified) (2 diffs)
-
core/Graph.php (modified) (4 diffs)
-
core/Parser.php (modified) (2 diffs)
-
core/Tokenizer.php (modified) (1 diff)
-
front/ctrl-shortcode.php (modified) (1 diff)
-
front/jazzy-forms.js (modified) (9 diffs)
-
front/tmpl-list.php (modified) (7 diffs)
-
jazzy-forms.php (modified) (2 diffs)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
jazzy-forms/trunk/back/gui.css
r530820 r581482 228 228 229 229 .jzzf_type_n { background-image: url('img/n.png'); } 230 .jzzf_type_a { background-image: url('img/a.png'); } 230 231 .jzzf_type_c { background-image: url('img/c.png'); } 231 232 .jzzf_type_r { background-image: url('img/r.png'); } -
jazzy-forms/trunk/back/tpl-forms.php
r566668 r581482 83 83 <li> 84 84 <label for="jzzf_element_{{id}}_default">Default</label> 85 <input type="text" id="jzzf_element_{{id}}_default" class="jzzf_element_default" value="{{default}}"> 86 </li> 87 </ul> 88 </div> 89 </fieldset> 90 {{>foot}} 91 </script> 92 <script id="jzzf_tmpl_a" type="text/html"> 93 {{>common}} 94 <fieldset class="jzzf_div_collapsable"> 95 <h3 class="jzzf_toggler"><div></div>Value</h3> 96 <div class="jzzf_collapsable_body"> 97 <ul> 98 <li> 99 <label for="jzzf_element_{{id}}_default">Default text</label> 85 100 <input type="text" id="jzzf_element_{{id}}_default" class="jzzf_element_default" value="{{default}}"> 86 101 </li> … … 318 333 <ul id="jzzf_toolbox_input" class="jzzf_elements_toolbox_items"> 319 334 <li jzzf_type="n"><div class="jzzf_type jzzf_type_n"></div>Input</li> 335 <li jzzf_type="a"><div class="jzzf_type jzzf_type_a"></div>Text Area</li> 320 336 <li jzzf_type="d"><div class="jzzf_type jzzf_type_d"></div>Drop-down Menu</li> 321 337 <li jzzf_type="r"><div class="jzzf_type jzzf_type_r"></div>Radio Buttons</li> -
jazzy-forms/trunk/core/Graph.php
r567987 r581482 40 40 private $form; 41 41 private $graph; 42 private $direct_dependencies = array(); 42 43 43 44 public function __construct() { … … 48 49 $this->form = $form; 49 50 50 foreach($form->elements as $elem) { 51 $this->process_element($elem); 52 } 51 $this->elements(); 52 $this->dependencies(); 53 53 $this->graph->email = $this->get_email_formulas(); 54 54 return $this->graph; 55 } 56 57 function elements() { 58 foreach($this->form->elements as $elem) { 59 $this->process_element($elem); 60 } 61 } 62 63 function dependencies() { 64 foreach($this->direct_dependencies as $id => $directs) { 65 $this->get_recursive_dependencies($id); 66 } 67 $this->clean_dependencies(); 68 } 69 70 // remove empty dependencies and dependencies for output fields 71 function clean_dependencies() { 72 foreach($this->graph->dependencies as $id => $dependent) { 73 if(!array_key_exists($id, $this->graph->types) || $this->is_output($this->graph->types[$id]) || !$dependent) { 74 unset($this->graph->dependencies[$id]); 75 } 76 } 77 } 78 79 function get_recursive_dependencies($id) { 80 if(array_key_exists($id, $this->graph->dependencies)) { 81 return $this->graph->dependencies[$id]; 82 } 83 $this->graph->dependencies[$id] = array(); // this avoids endless recursion 84 $dependencies = array(); 85 if(array_key_exists($id, $this->direct_dependencies)) { 86 $directs = $this->direct_dependencies[$id]; 87 foreach($directs as $direct) { 88 $recursive = $this->get_recursive_dependencies($direct); 89 $dependencies[] = $direct; 90 foreach($recursive as $r) { 91 if(!in_array($r, $dependencies)) { 92 $dependencies[] = $r; 93 } 94 } 95 } 96 } 97 $this->graph->dependencies[$id] = $dependencies; 98 return $dependencies; 55 99 } 56 100 … … 96 140 } 97 141 142 function is_output($type) { 143 return in_array($type, array('f', 'm', 't', 'h')); 144 } 145 98 146 function get_email_formulas() { 99 147 $formulas = null; … … 142 190 function add_dependencies($dependencies, $id) { 143 191 foreach($dependencies as $dep) { 144 $this-> graph->dependencies[$dep][] = $id;192 $this->direct_dependencies[$dep][] = $id; 145 193 } 146 194 } -
jazzy-forms/trunk/core/Parser.php
r508925 r581482 1 1 <?php 2 3 /* (* Extended Backus-Naur Form (EBNF): *) 4 5 formula = comparison; 6 comparison = concatenation, [("<" | ">" | "<=" | "=>" | "<>"), comparison]; 7 concatenation = sum, [ "&", concatenation ]; 8 sum = product, [("+" | "-"), sum]; 9 product = exponentiation, [("*" | "/"), term]; 10 exponentiation = term, ["^", exponentiation]; 11 term = number | identifier | function | string; 12 13 arguments = comparison, { ",", comparison}; 14 function = identifier, "(", arguments ")"; 15 16 */ 17 2 18 3 19 function jzzf_parse($notation) { … … 33 49 34 50 private function comparison() { 35 return $this->operation('comparison', array('<=', '>=', '<', '>', '=', '<>'), 'sum'); 51 return $this->operation('comparison', array('<=', '>=', '<', '>', '=', '<>'), 'concatenation'); 52 } 53 54 private function concatenation() { 55 return $this->operation('concatenation', array('&'), 'sum'); 36 56 } 37 57 -
jazzy-forms/trunk/core/Tokenizer.php
r502411 r581482 35 35 36 36 private function operator() { 37 return $this->match('<=|>=|<>|[\-\+\*\/\^\,<>= ]');37 return $this->match('<=|>=|<>|[\-\+\*\/\^\,<>=&]'); 38 38 } 39 39 -
jazzy-forms/trunk/front/ctrl-shortcode.php
r566668 r581482 73 73 $tpl->number($element); 74 74 break; 75 case 'a': 76 $tpl->textarea($element); 77 break; 75 78 case 'f': 76 79 if(!in_array($element->name, $graph->formulas)) { -
jazzy-forms/trunk/front/jazzy-forms.js
r567987 r581482 8 8 9 9 var all_ids = []; 10 var cache = {}; 10 11 var cache = new Jzzf_Cache(); 12 var types = new Jzzf_Types(this); 13 var library = new Jzzf_Library(types, this); 14 var formatter = new Jzzf_Formatter(types, graph.types, graph.params); 15 var calculator = new Jzzf_Calculator(this, types, library, formatter); 16 var self = this; 11 17 12 18 jzzf_precision = Math.pow(10,9); … … 21 27 } 22 28 23 $(function( ) {29 $(function(args) { 24 30 retrieve_all_ids(); 25 update (all_ids);31 update_all(); 26 32 bind(); 27 33 }); … … 45 51 case 'u': 46 52 element(id).click(function() { 47 update (all_ids);53 update_all(); 48 54 }); 49 55 break; … … 64 70 switch(graph.types[id]) { 65 71 case 'r': 66 element(id).find('input:radio').bind('change ready', function() {67 update([element_id($(this).parents('.jzzf_radio'))]);72 element(id).find('input:radio').bind('change', function() { 73 change(element_id($(this).parents('.jzzf_radio'))); 68 74 }); 69 75 break; 70 default: 71 element(id).bind('change ready', function() { 72 update([element_id($(this))]); 76 case 'n': 77 case 'a': 78 case 'd': 79 case 'r': 80 case 'c': 81 element(id).bind('change', function() { 82 change(element_id($(this))); 73 83 }); 74 84 } 75 85 } 76 77 var just_updated; 78 79 function update(ids) { 80 just_updated = []; 81 for(var i=0; i<ids.length; i++) { 82 var id = ids[i]; 83 delete cache[id] 84 updating_worker(id); 85 } 86 } 87 86 88 87 function set_message(node, msg) { 89 88 $(node).parentsUntil('.jzzf_row').siblings('.jzzf_message').text(msg); … … 98 97 var values = {}; 99 98 for(var key in graph.email) { 100 var value = evaluate_formula(graph.email[key]); 101 if(graph.email[key].length == 1 && graph.types[key] == 'f') { 102 values[key] = sanitize_result(value, key); 103 } else { 104 values[key] = value; 105 } 99 values[key] = calculator.placeholder(graph.email[key]); 106 100 } 107 101 $.ajax(jzzf_ajax_url, { … … 122 116 } 123 117 124 function sanitize_result(val, id) { 125 var f = parseFloat(val); 126 if(!isNaN(f)) { 127 val = f; 128 } 129 switch(typeof val) { 130 case 'undefined': 131 val = 'Invalid formula'; 132 break; 133 case 'number': 134 if(!isNaN(val)) { 135 val = jzzf_format(val, graph.params[id]); 136 } 137 break; 138 case 'boolean': 139 val = val ? 1 : 0; 140 break; 141 } 142 return val; 143 } 144 145 function updating_worker(id) { 146 update_dependent(id); 147 if(id in just_updated) { 148 return; 149 } 150 var value = evaluate(id); 118 function update(id) { 151 119 switch(graph.types[id]) { 152 120 case 'f': 153 element(id).val(sanitize_result(value, id));121 update_output(id); 154 122 break; 155 123 case 'm': 156 if(value!==false) { 157 element(id).html(value); 158 } 124 update_template(id, true); 159 125 break; 160 126 case 't': 161 127 case 'h': 162 if(value!==false) { 163 element(id).text(value); 164 } 128 update_template(id, false); 165 129 break; 166 130 } 167 just_updated.push(id); 168 } 169 170 function update_dependent(id) { 171 if(id in graph.dependencies) { 172 var deps = graph.dependencies[id]; 173 for(var i=0; i<deps.length; i++) { 174 updating_worker(deps[i]); 175 } 176 } 177 } 178 179 function evaluate(id) { 131 } 132 133 function update_output(id) { 180 134 var result; 181 if(!(id in cache) || !(id in just_updated)) { 182 result = evaluation_worker(id); 183 cache[id] = result; 184 } else { 185 result = cache[id]; 135 try { 136 result = self.formatted(id); 137 } catch(err) { 138 if(err instanceof Jzzf_Error) { 139 result = err.toString(); 140 } else { 141 throw(err); 142 } 143 } 144 element(id).val(result); 145 } 146 147 function update_template(id, html) { 148 if(graph.templates[id]) { 149 var value = self.evaluate(id).text(); 150 if(html) { 151 element(id).html(value); 152 } else { 153 element(id).text(value); 154 } 155 } 156 } 157 158 function update_text(id) { 159 var value = self.evaluate(id).text(); 160 } 161 162 function change(id) { 163 var dependencies = graph.dependencies[id]; 164 if(dependencies) { 165 cache.mark_dirty(dependencies); 166 for(var idx=0; idx<dependencies.length; idx++) { 167 update(dependencies[idx]); 168 } 169 } 170 } 171 172 function update_all() { 173 cache.reset(); 174 for(var idx=0; idx<all_ids.length; idx++) { 175 update(all_ids[idx]); 176 } 177 } 178 179 this.evaluate = function(id) { 180 var result = cache.get(id); 181 if(result !== undefined) { 182 return result; 183 } 184 try { 185 result = this.evaluation_worker(id); 186 cache.set(result); 187 } catch(err) { 188 if(err instanceof Jzzf_Error) { 189 cache.set_error(err); 190 result = err; 191 } 192 throw err; 186 193 } 187 194 return result; 188 195 } 189 190 function template(id) { 191 var result = ''; 192 var chunks = graph.templates[id]; 193 if(chunks) { 194 for(var i=0; i<chunks.length; i++) { 195 var chunk = chunks[i]; 196 if(typeof chunk == 'object') { 197 if(is_formatted_variable(chunk)) { 198 result += evaluate_formatted_variable(chunk); 199 } else { 200 result += evaluate_formula(chunk); 201 } 202 } else { 203 result += chunk; 204 } 205 } 206 return result; 207 } 208 return false; 209 } 210 211 function is_formatted_variable(formula) { 212 if(formula && formula.length == 1 && formula[0][0] == 'v') { 213 return graph.types[formula[0][1]] == 'f'; 214 } else { 215 return false; 216 } 217 } 218 219 function evaluate_formatted_variable(formula) { 220 var id = formula[0][1]; 221 return sanitize_result(evaluate(id), id); 222 } 223 224 function evaluation_worker(id) { 196 197 this.evaluation_worker = function(id) { 225 198 switch(graph.types[id]) { 226 199 case 'n': 227 200 var input = element(id).val(); 201 var result; 228 202 if(id in graph.data) { 229 203 var factor = to_float_for_factor(graph.data[id]); 230 204 if(!isNaN(factor)) { 231 re turninput*factor;205 result = input*factor; 232 206 } else { 233 re turninput;207 result = input; 234 208 } 235 209 } else { 236 re turninput;210 result = input; 237 211 } 212 return types.value(result); 213 case 'a': 214 var input = element(id).val(); 215 return types.value(input); 238 216 case 'r': 239 217 var idx = element(id).find('input:checked').parent().index(); 218 var result; 240 219 if(idx>=0) { 241 re turngraph.data[id][idx];220 result = graph.data[id][idx]; 242 221 } else { 243 re turn0;222 result = 0; 244 223 } 224 return types.value(result); 245 225 case "c": 246 return element(id).is(':checked') ? graph.data[id][1] : graph.data[id][0];226 return types.value(element(id).is(':checked') ? graph.data[id][1] : graph.data[id][0]); 247 227 case 'd': 248 228 var idx = element(id).find('option:selected').index(); 229 var result; 249 230 if(idx>=0) { 250 re turngraph.data[id][idx];231 result = graph.data[id][idx]; 251 232 } else { 252 re turn0;233 result = 0; 253 234 } 235 return types.value(result); 254 236 case 'f': 255 return formula(id);237 return calculator.formula(graph.formulas[id]); 256 238 case 'm': 257 239 case 't': 258 240 case 'h': 259 return template(id); 260 } 261 return 0; 262 } 263 264 function to_float_for_calculation(val) { 265 return Number(val); 266 } 267 241 var chunks = graph.templates[id]; 242 if(chunks) { 243 return types.value(calculator.template(chunks)); 244 } else { 245 return types.value(""); 246 } 247 default: 248 types.raise_ref(); 249 break; 250 } 251 return types.value(""); 252 } 253 268 254 function to_float_for_factor(val) { 269 255 if(typeof val == 'string' && val.match(/^\s*$/)) { … … 274 260 } 275 261 276 function formula(id) { 277 var f = graph.formulas[id]; 278 if(!f) { 279 return undefined; 280 } 281 return evaluate_formula(f); 282 } 283 284 function evaluate_formula(f) { 285 var stack = []; 286 for(var i=0; i<f.length; i++) { 287 switch(f[i][0]) { 288 case 'n': 289 case 's': 290 stack.push(f[i][1]); 291 break; 292 case 'v': 293 stack.push(evaluate(f[i][1])); 294 break; 295 case 'o': 296 var right = to_float_for_calculation(stack.pop()); 297 var left = to_float_for_calculation(stack.pop()); 298 var result; 299 switch(f[i][1]) { 300 case '+': 301 result = left + right; 302 break; 303 case '-': 304 result = left - right; 305 break; 306 case '*': 307 result = left * right; 308 break; 309 case '/': 310 result = left / right; 311 break; 312 case '^': 313 result = Math.pow(left, right); 314 break; 315 case '<': 316 result = prcsn(left) < prcsn(right); 317 break; 318 case '>': 319 result = prcsn(left) > prcsn(right); 320 break; 321 case '<>': 322 result = prcsn(left) != prcsn(right); 323 break; 324 case '<=': 325 result = prcsn(left) <= prcsn(right); 326 break; 327 case '>=': 328 result = prcsn(left) >= prcsn(right); 329 break; 330 case '=': 331 result = prcsn(left) == prcsn(right); 332 break; 333 } 334 stack.push(result); 335 break; 336 case 'f': 337 var args=[]; 338 for(var j=0; j<f[i][2]; j++) { 339 args.unshift(stack.pop()); 340 } 341 stack.push(jzzf_functions(f[i][1], args)); 342 break; 343 } 344 } 345 return stack.pop(); 262 this.formatted = function(id) { 263 var value = self.evaluate(id).value(); 264 return formatter.format(id, value); 265 } 266 267 this.label = function(id) { 268 var type = graph.types[id]; 269 switch(type) { 270 case "d": 271 return element(id).find('option:selected').text(); 272 case "r": 273 return element(id).find('input:checked').siblings("label").text(); 274 default: 275 types.raise_ref(); 276 } 346 277 } 347 278 348 279 } 349 280 350 function jzzf_functions(id, args) { 351 352 function arg(idx, def) { 353 if(idx >= args.length) { 354 return def; 355 } 356 return args[idx]; 357 } 358 359 function numarg(idx, def) { 360 return Number(arg(idx, def)); 361 } 362 363 var all = { 364 'abs': function() { 365 return Math.abs(numarg(0)); 366 }, 367 'round': function() { 368 var digits = numarg(1, 0); 281 function Jzzf_Library(types, engine) { 282 283 function _default(def) { 284 if(def === undefined) { 285 types.raise_name(); 286 } 287 return def; 288 } 289 290 function _number(args, def) { 291 if(!args.length) { 292 return _default(def); 293 } 294 return args.shift().number(); 295 } 296 297 function _bool(args, def) { 298 if(!args.length) { 299 return _default(def); 300 } 301 return args.shift().bool(); 302 } 303 304 function _raw(args, def) { 305 if(!args.length) { 306 return _default(def); 307 } 308 return args.shift().raw(args); 309 } 310 311 function _id(args, def) { 312 if(!args.length) { 313 return _default(def); 314 } 315 return args.shift().id(); 316 } 317 318 var functions = { 319 'abs': function(args) { 320 var x = _number(args); 321 return Math.abs(x); 322 }, 323 'round': function(args) { 324 var x = _number(args); 325 var digits = _number(args, 0); 326 369 327 var decimal = Math.pow(10, digits); 370 return Math.round(numarg(0)*decimal)/decimal; 371 }, 372 'mround': function() { 373 var multiple = numarg(1); 374 return Math.round(numarg(0)/multiple)*multiple; 375 }, 376 'roundup': function() { 377 var digits = numarg(1, 0); 328 return Math.round(x*decimal)/decimal; 329 }, 330 'mround': function(args) { 331 var x = _number(args); 332 var multiple = _number(args); 333 334 return Math.round(x/multiple)*multiple; 335 }, 336 'roundup': function(args) { 337 var x = _number(args); 338 var digits = _number(args, 0); 339 378 340 var decimal = Math.pow(10, digits); 379 var x = numarg(0); 380 return (x > 0) ? Math.ceil(numarg(0)*decimal)/decimal : Math.floor(numarg(0)*decimal)/decimal; 381 }, 382 'rounddown': function() { 383 var digits = numarg(1, 0); 341 return (x > 0) ? Math.ceil(x*decimal)/decimal : Math.floor(x*decimal)/decimal; 342 }, 343 'rounddown': function(args) { 344 var x = _number(args); 345 var digits = _number(args, 0); 346 384 347 var decimal = Math.pow(10, digits); 385 var x = numarg(0);386 return (x > 0) ? Math.floor(numarg(0)*decimal)/decimal : Math.ceil(numarg(0)*decimal)/decimal;387 },388 'ln': function() {389 var x = numarg(0);348 return (x > 0) ? Math.floor(x*decimal)/decimal : Math.ceil(x*decimal)/decimal; 349 }, 350 'ln': function(args) { 351 var x = _number(args); 352 390 353 return Math.log(x); 391 354 }, 392 'log': function( ) {393 var x = numarg(0);394 var b = numarg(1, 10);355 'log': function(args) { 356 var x = _number(args); 357 var b = _number(args, 10); 395 358 return Math.log(x) / Math.log(b); 396 359 }, 397 'log10': function( ) {398 var x = numarg(0);360 'log10': function(args) { 361 var x = _number(args); 399 362 return Math.log(x) / Math.log(10); 400 363 }, 401 'exp': function( ) {402 var x = numarg(0);364 'exp': function(args) { 365 var x = _number(args); 403 366 return Math.exp(x); 404 367 }, 405 'power': function( ) {406 var x = numarg(0);407 var y = numarg(1);368 'power': function(args) { 369 var x = _number(args); 370 var y = _number(args); 408 371 return Math.pow(x, y); 409 372 }, 410 'sqrt': function() { 411 return Math.sqrt(numarg(0)); 412 }, 413 'sin': function() { 414 return Math.sin(numarg(0)); 415 }, 416 'cos': function() { 417 return Math.cos(numarg(0)); 418 }, 419 'tan': function() { 420 return Math.tan(numarg(0)); 421 }, 422 'asin': function() { 423 return Math.asin(numarg(0)); 424 }, 425 'acos': function() { 426 return Math.acos(numarg(0)); 427 }, 428 'atan': function() { 429 return Math.atan(numarg(0)); 430 }, 431 'pi': function() { 373 'sqrt': function(args) { 374 var x = _number(args); 375 return Math.sqrt(x); 376 }, 377 'sin': function(args) { 378 var x = _number(args); 379 return Math.sin(x); 380 }, 381 'cos': function(args) { 382 var x = _number(args); 383 return Math.cos(x); 384 }, 385 'tan': function(args) { 386 var x = _number(args); 387 return Math.tan(x); 388 }, 389 'asin': function(args) { 390 var x = _number(args); 391 return Math.asin(x); 392 }, 393 'acos': function(args) { 394 var x = _number(args); 395 return Math.acos(x); 396 }, 397 'atan': function(args) { 398 var x = _number(args); 399 return Math.atan(x); 400 }, 401 'pi': function(args) { 432 402 return Math.PI; 433 403 }, 434 'not': function() { 435 return !arg(0); 436 }, 437 'and': function() { 438 return arg(0) && arg(1); 439 }, 440 'or': function() { 441 return arg(0) || arg(1); 442 }, 443 'if': function() { 444 return arg(0) ? arg(1) : arg(2, false); 445 }, 446 'true': function() { 404 'not': function(args) { 405 var e = _bool(args); 406 return !e; 407 }, 408 'and': function(args) { 409 var e = _bool(args); 410 var f = _bool(args); 411 return e && f; 412 }, 413 'or': function(args) { 414 var e = _bool(args); 415 var f = _bool(args); 416 return e || f; 417 }, 418 'if': function(args) { 419 var c = _bool(args); 420 var y = _raw(args, 0); 421 var n = _raw(args, 0); 422 return c ? y : n; 423 }, 424 'true': function(args) { 447 425 return true; 448 426 }, 449 'false': function( ) {427 'false': function(args) { 450 428 return false; 429 }, 430 'formatted': function(args) { 431 var id = _id(args); 432 return engine.formatted(id); 433 }, 434 'label': function(args) { 435 var id = _id(args); 436 return engine.label(id); 451 437 } 452 438 453 439 }; 454 455 return (all[id])(); 440 441 var operations = { 442 "+": function(left, right) { 443 return left.number() + right.number(); 444 }, 445 "-": function(left, right) { 446 return left.number() - right.number(); 447 }, 448 "*": function(left, right) { 449 return left.number() * right.number(); 450 }, 451 "/": function(left, right) { 452 var divisor = right.number(); 453 if(divisor == 0) { 454 types.raise_div0(); 455 } 456 return left.number() / right.number(); 457 }, 458 "^": function(left, right) { 459 return Math.pow(left.number(), right.number()); 460 }, 461 "<": function(left, right) { 462 return left.precise_number() < right.precise_number(); 463 }, 464 ">": function(left, right) { 465 return left.precise_number() > right.precise_number(); 466 }, 467 "<>": function(left, right) { 468 return left.precise_number() != right.precise_number(); 469 }, 470 "<=": function(left, right) { 471 return left.precise_number() <= right.precise_number(); 472 }, 473 ">=": function(left, right) { 474 return left.precise_number() >= right.precise_number(); 475 }, 476 "=": function(left, right) { 477 return left.precise_number() == right.precise_number(); 478 }, 479 "&": function(left, right) { 480 return left.text() + right.text(); 481 } 482 } 483 484 this.execute = function(name, args) { 485 if(!(name in functions)) { 486 types.raise_name(); 487 } 488 var result = functions[name](args); 489 490 if(args.length) { 491 types.raise_name(); 492 } 493 return result; 494 } 495 496 this.operation = function(name, left, right) { 497 if(!(name in operations)) { 498 types.raise_name(); 499 } 500 return operations[name](left, right); 501 } 456 502 } 457 503 … … 507 553 } 508 554 555 function to_text(x) { 556 if (Math.abs(x) < 1.0) { 557 var e = parseInt(x.toString().split('e-')[1]); 558 if (e) { 559 x *= Math.pow(10,e-1); 560 x = '0.' + (new Array(e)).join('0') + x.toString().substring(2); 561 } 562 } else { 563 var e = parseInt(x.toString().split('+')[1]); 564 if (e > 20) { 565 e -= 20; 566 x /= Math.pow(10,e); 567 x += (new Array(e+1)).join('0'); 568 } 569 } 570 return "" + x; 571 } 572 509 573 round(); 510 574 511 var str = "" + input;575 var str = to_text(input); 512 576 var parts = str.split('.'); 513 577 var sign; … … 523 587 return sign + args.prefix + natural + (decimals.length ? args.point + decimals + args.postfix : args.postfix); 524 588 } 589 590 function Jzzf_Error(code) { 591 this.code = code; 592 this.toString = function() { return this.code; } 593 } 594 595 function Jzzf_Types(engine) { 596 var types = this; 597 598 this.raise_null = function() { throw new Jzzf_Error("#NULL!") }; 599 this.raise_div0 = function() { throw new Jzzf_Error("#DIV/0!") }; 600 this.raise_value = function() { throw new Jzzf_Error("#VALUE!") }; 601 this.raise_ref = function() { throw new Jzzf_Error("#REF!"); }; 602 this.raise_name = function() { throw new Jzzf_Error("#NAME?"); }; 603 this.raise_num = function() { throw new Jzzf_Error("#NUM!"); }; 604 this.raise_na = function() { throw new Jzzf_Error("#N/A!") }; 605 606 var precision = Math.pow(10,9); 607 608 this.precise = function(x) { 609 return Math.round(x*precision)/precision; 610 } 611 612 var breadcrumbs = {}; 613 614 function place_breadcrumb(id) { 615 if(id in breadcrumbs) { 616 types.raise_ref(); 617 } 618 breadcrumbs[id] = true; 619 } 620 621 function withdraw_breadcrumb(id) { 622 delete breadcrumbs[id]; 623 } 624 625 function wipe_away_breadcrumbs() { 626 breadcrumbs = {}; 627 } 628 629 function Value(data) { this.data = data; } 630 Value.prototype.text = function() { 631 if(typeof this.data == 'boolean') { 632 return this.data ? "TRUE" : "FALSE"; 633 } else if(typeof this.data == 'number') { 634 return String(types.precise(this.data)); 635 } 636 return String(this.data); 637 } 638 Value.prototype.number = function() { 639 var x = Number(this.data); 640 if(isNaN(x)) { 641 types.raise_value(); 642 } 643 return x; 644 } 645 Value.prototype.precise_number = function() { 646 return types.precise(this.number()); 647 } 648 649 Value.prototype.bool = function() { 650 if(typeof this.data == 'string') { 651 var trimmed = this.data.replace(/^\s\s*/, '').replace(/\s\s*$/, '').toUpperCase(); 652 if(trimmed == 'TRUE') { 653 return true; 654 } else if(trimmed == 'FALSE') { 655 return false; 656 } 657 } 658 return this.number() != 0; 659 } 660 Value.prototype.id = function() { types.raise_value(); } 661 Value.prototype.raw = function() { return this.data; } 662 Value.prototype.value = function() { return this; } 663 Value.prototype.is_numeric = function() { 664 if(this.data === "") { 665 return false; 666 } 667 var x = Number(this.data); 668 return !isNaN(x); 669 } 670 Value.prototype.is_reference = function() { return false; } 671 672 function Reference(id) { 673 this.ref_id = id; 674 } 675 Reference.prototype.value = function() { 676 place_breadcrumb(this.ref_id); 677 var val = engine.evaluate(this.ref_id); 678 if(val === undefined) { 679 wipe_away_breadcrumbs(); 680 types.raise_ref(); 681 } 682 val = val.value(); 683 withdraw_breadcrumb(this.ref_id); 684 return val; 685 } 686 Reference.prototype.raw = function() { return this.value().raw(); } 687 Reference.prototype.text = function() { return this.value().text(); } 688 Reference.prototype.number = function() { return this.value().number(); } 689 Reference.prototype.precise_number = function() { return this.value().precise_number(); } 690 Reference.prototype.bool = function() { return this.value().bool(); } 691 Reference.prototype.id = function() { return this.ref_id; } 692 Reference.prototype.is_numeric = function() { return this.value().is_numeric(); } 693 Reference.prototype.is_reference = function() { return true; } 694 695 this.value = function(val) { return new Value(val); } 696 this.reference = function(id) { return new Reference(id); } 697 } 698 699 function Jzzf_Cache() { 700 var data = {}; 701 var errors = {}; 702 703 this.get = function(id) { 704 var result = data[id]; 705 if(result === null) { 706 var error = errors[id]; 707 if(error) { 708 throw error; 709 } 710 } 711 return result; 712 } 713 714 this.set = function(id, value) { 715 data[id] = value; 716 delete errors[id]; 717 } 718 719 this.set_error = function(id, err) { 720 data[id] = null; 721 errors[id] = err; 722 } 723 724 this.mark_dirty = function(ids) { 725 for(var idx=0; idx<ids.length; idx++) { 726 delete data[ids[idx]]; 727 delete errors[ids[idx]]; 728 } 729 } 730 731 this.reset = function() { 732 data = {}; 733 errors = {}; 734 } 735 736 } 737 738 function Jzzf_Formatter(types, element_types, params) { 739 this.format = function(id, value) { 740 if(element_types[id] != 'f') { 741 return value.text(); 742 } 743 if(value.is_numeric()) { 744 return jzzf_format(value.number(), params[id]); 745 } else { 746 return value.text(); 747 } 748 } 749 } 750 751 function Jzzf_Calculator(engine, types, library) { 752 this.formula = function(f) { 753 if(f === null) { 754 types.raise_name(); 755 } 756 if(f.length == 0) { 757 return types.value(""); 758 } 759 var stack = []; 760 for(var i=0; i<f.length; i++) { 761 switch(f[i][0]) { 762 case 'n': 763 case 's': 764 stack.push(types.value(f[i][1])); 765 break; 766 case 'v': 767 stack.push(types.reference(f[i][1])); 768 break; 769 case 'o': 770 var right = stack.pop(); 771 var left = stack.pop(); 772 if(left === undefined || right === undefined) { 773 types.raise_name(); 774 } 775 var result = library.operation(f[i][1], left, right); 776 stack.push(types.value(result)); 777 break; 778 case 'f': 779 var args=[]; 780 for(var j=0; j<f[i][2]; j++) { 781 args.unshift(stack.pop()); 782 } 783 stack.push(types.value(library.execute(f[i][1], args))); 784 break; 785 } 786 } 787 return stack.pop(); 788 } 789 790 this.template = function(chunks) { 791 var result = ""; 792 for(var i=0; i<chunks.length; i++) { 793 var chunk = chunks[i]; 794 if(typeof chunk == 'object') { 795 result += this.placeholder(chunk); 796 } else { 797 result += chunk; 798 } 799 } 800 return result; 801 } 802 803 this.placeholder = function(formula) { 804 try { 805 return this.formula(formula).text(); 806 } catch(err) { 807 if(err instanceof Jzzf_Error) { 808 return err.toString(); 809 } else { 810 throw(err); 811 } 812 } 813 } 814 } -
jazzy-forms/trunk/front/tmpl-list.php
r566668 r581482 18 18 19 19 function theme($num) {?> 20 <style type="text/css" >20 <style type="text/css" scoped="scoped"> 21 21 @import url(<?php echo plugins_url('themes/' . ((int) $num) . '.css', JZZF_ROOT . 'front/tmpl-list.php') ?>); 22 22 </style> … … 45 45 }; 46 46 var jzzf_ajax_url = "<?php esc_attr_e(admin_url('admin-ajax.php')) ?>"; 47 jazzy_forms(jQuery, <?php echo $form->id ?>, jzzf_graph_<?php echo $form->id ?>);47 var jzzf = new jazzy_forms(jQuery, <?php echo $form->id ?>, jzzf_graph_<?php echo $form->id ?>); 48 48 </script> 49 49 <?php … … 76 76 77 77 function number($element) { ?> 78 <label class="jzzf_number_label jzzf_element_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label> 79 <input type="text" id="<?php $this->id($element) ?>" value="<?php esc_attr_e($element->default) ?>"> 78 <label class="jzzf_number_label jzzf_element_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label><?php // avoid line-feed 79 ?><input type="text" id="<?php $this->id($element) ?>" value="<?php esc_attr_e($element->default) ?>"> 80 <?php 81 } 82 83 function textarea($element) { ?> 84 <label class="jzzf_textarea_label jzzf_element_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label><?php // avoid line-feed 85 ?><textarea id="<?php $this->id($element) ?>"><?php esc_html_e($element->default) ?></textarea> 80 86 <?php 81 87 } … … 86 92 <?php $idx = 0; foreach($element->options as $option) { $idx++; ?> 87 93 <li> 88 <input type="radio" name="<?php $this->id($element) ?>" id="<?php echo $this->id($element) . '-' . $idx ?>"<?php if($option->default): ?> checked="checked"<?php endif ?>> 89 <label class="jzzf_radio_option_label" for="<?php echo $this->id($element) . '-' . $idx ?>"><?php esc_html_e($option->title) ?></label>94 <input type="radio" name="<?php $this->id($element) ?>" id="<?php echo $this->id($element) . '-' . $idx ?>"<?php if($option->default): ?> checked="checked"<?php endif ?>><?php // avoid line-feed 95 ?><label class="jzzf_radio_option_label" for="<?php echo $this->id($element) . '-' . $idx ?>"><?php esc_html_e($option->title) ?></label> 90 96 </li> 91 97 <?php … … 95 101 96 102 function dropdown($element) { ?> 97 <label class="jzzf_element_label jzzf_dropdown_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label> 98 <select id="<?php $this->id($element) ?>">103 <label class="jzzf_element_label jzzf_dropdown_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label><?php // avoid line-feed 104 ?><select id="<?php $this->id($element) ?>"> 99 105 <?php foreach($element->options as $option) : ?> 100 106 <option<?php if($option->default): ?> selected="selected"<?php endif ?>><?php esc_html_e($option->title) ?></option> … … 105 111 106 112 function checkbox($element) { ?> 107 <input type="checkbox" id="<?php $this->id($element) ?>"<?php if($element->default): ?> checked="checked"<?php endif ?>> 108 <label class="jzzf_checkbox_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label>113 <input type="checkbox" id="<?php $this->id($element) ?>"<?php if($element->default): ?> checked="checked"<?php endif ?>><?php // avoid line-feed 114 ?><label class="jzzf_checkbox_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label> 109 115 <?php 110 116 } … … 116 122 117 123 function output($element) { ?> 118 <label class="jzzf_element_label jzzf_output_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label> 119 <input type="text" readonly="readonly" id="<?php $this->id($element) ?>"<?php if($element->invalid) : ?> value="Invalid formula"<?php endif ?>>124 <label class="jzzf_element_label jzzf_output_label" for="<?php $this->id($element) ?>"><?php esc_html_e($element->title) ?></label><?php // avoid line-feed 125 ?><input type="text" readonly="readonly" id="<?php $this->id($element) ?>"<?php if($element->invalid) : ?> value="Invalid formula"<?php endif ?>> 120 126 <?php 121 127 } -
jazzy-forms/trunk/jazzy-forms.php
r567987 r581482 4 4 Plugin URI: http://www.jazzyforms.com/ 5 5 Description: Online form builder with an emphasis on calculation 6 Version: 0. 9.106 Version: 0.10 7 7 Author: Igor Prochazka 8 8 Author URI: http://www.l90r.com/ … … 28 28 */ 29 29 30 define(JZZF_VERSION, 0. 0910);31 define(JZZF_VERSION_STRING, "0. 0910");30 define(JZZF_VERSION, 0.1000); 31 define(JZZF_VERSION_STRING, "0.1000"); 32 32 define(JZZF_OPTION_VERSION, 'jzzf_version'); 33 33 -
jazzy-forms/trunk/readme.txt
r567987 r581482 119 119 == Changelog == 120 120 121 = 0.10 = 122 * performance improvements 123 * label(id) function to access the label of currently selected dropdown option/radio button 124 * formatted(id) function to get the textual representation of a field's formatted content 125 * text concatenation operator (&) and support for formulas with text output 126 * mitigate the risk of extra linebreaks being introduced by external text filters 127 * new textarea element 128 * fix number formatting for very large and small numbers 129 * detect circular dependencies 130 * spreadsheet-like error codes 131 * fixed 3w validation 132 121 133 = 0.9.10 = 122 134 * Take into account text elements without placeholders (urgent fix)
Note: See TracChangeset
for help on using the changeset viewer.