Plugin Directory

Changeset 581482


Ignore:
Timestamp:
08/03/2012 07:45:52 PM (14 years ago)
Author:
jazzigor
Message:

Updating trunk to v0.10

Location:
jazzy-forms/trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • jazzy-forms/trunk/back/gui.css

    r530820 r581482  
    228228
    229229.jzzf_type_n { background-image: url('img/n.png'); }
     230.jzzf_type_a { background-image: url('img/a.png'); }
    230231.jzzf_type_c { background-image: url('img/c.png'); }
    231232.jzzf_type_r { background-image: url('img/r.png'); }
  • jazzy-forms/trunk/back/tpl-forms.php

    r566668 r581482  
    8383                    <li>
    8484                        <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>
    85100                        <input type="text" id="jzzf_element_{{id}}_default" class="jzzf_element_default" value="{{default}}">
    86101                    </li>
     
    318333                <ul id="jzzf_toolbox_input" class="jzzf_elements_toolbox_items">
    319334                    <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>
    320336                    <li jzzf_type="d"><div class="jzzf_type jzzf_type_d"></div>Drop-down Menu</li>
    321337                    <li jzzf_type="r"><div class="jzzf_type jzzf_type_r"></div>Radio Buttons</li>
  • jazzy-forms/trunk/core/Graph.php

    r567987 r581482  
    4040    private $form;
    4141    private $graph;
     42    private $direct_dependencies = array();
    4243
    4344    public function __construct() {
     
    4849        $this->form = $form;
    4950
    50         foreach($form->elements as $elem) {
    51             $this->process_element($elem);
    52         }
     51        $this->elements();
     52        $this->dependencies();
    5353        $this->graph->email = $this->get_email_formulas();
    5454        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;
    5599    }
    56100   
     
    96140    }
    97141   
     142    function is_output($type) {
     143        return in_array($type, array('f', 'm', 't', 'h'));
     144    }
     145   
    98146    function get_email_formulas() {
    99147        $formulas = null;
     
    142190    function add_dependencies($dependencies, $id) {
    143191        foreach($dependencies as $dep) {
    144             $this->graph->dependencies[$dep][] = $id;
     192            $this->direct_dependencies[$dep][] = $id;
    145193        }
    146194    }
  • jazzy-forms/trunk/core/Parser.php

    r508925 r581482  
    11<?php
     2
     3/* (* Extended Backus-Naur Form (EBNF): *)
     4 
     5formula = comparison;
     6comparison = concatenation, [("<" | ">" | "<=" | "=>" | "<>"), comparison];
     7concatenation = sum, [ "&", concatenation ];
     8sum = product, [("+" | "-"), sum];
     9product = exponentiation, [("*" | "/"), term];
     10exponentiation = term, ["^", exponentiation];
     11term = number | identifier | function | string;
     12
     13arguments = comparison, { ",", comparison};
     14function = identifier, "(", arguments ")";
     15
     16*/
     17
    218
    319function jzzf_parse($notation) {
     
    3349
    3450    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');
    3656    }
    3757
  • jazzy-forms/trunk/core/Tokenizer.php

    r502411 r581482  
    3535           
    3636    private function operator() {
    37         return $this->match('<=|>=|<>|[\-\+\*\/\^\,<>=]');
     37        return $this->match('<=|>=|<>|[\-\+\*\/\^\,<>=&]');
    3838    }
    3939
  • jazzy-forms/trunk/front/ctrl-shortcode.php

    r566668 r581482  
    7373                $tpl->number($element);
    7474                break;
     75            case 'a':
     76                $tpl->textarea($element);
     77                break;
    7578            case 'f':
    7679                if(!in_array($element->name, $graph->formulas)) {
  • jazzy-forms/trunk/front/jazzy-forms.js

    r567987 r581482  
    88   
    99    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;
    1117   
    1218    jzzf_precision = Math.pow(10,9);
     
    2127    }
    2228   
    23     $(function() {
     29    $(function(args) {
    2430        retrieve_all_ids();
    25         update(all_ids);
     31        update_all();
    2632        bind();
    2733    });
     
    4551                case 'u':
    4652                    element(id).click(function() {
    47                         update(all_ids);
     53                        update_all();
    4854                    });
    4955                    break;
     
    6470        switch(graph.types[id]) {
    6571        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')));
    6874            });
    6975            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)));
    7383            });
    7484        }
    7585    }
    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           
    8887    function set_message(node, msg) {
    8988        $(node).parentsUntil('.jzzf_row').siblings('.jzzf_message').text(msg);   
     
    9897        var values = {};
    9998        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]);
    106100        }
    107101        $.ajax(jzzf_ajax_url, {
     
    122116    }
    123117   
    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) {
    151119        switch(graph.types[id]) {
    152120            case 'f':
    153                 element(id).val(sanitize_result(value, id));
     121                update_output(id);
    154122                break;
    155123            case 'm':
    156                 if(value!==false) {
    157                     element(id).html(value);
    158                 }
     124                update_template(id, true);
    159125                break;
    160126            case 't':
    161127            case 'h':
    162                 if(value!==false) {
    163                     element(id).text(value);
    164                 }
     128                update_template(id, false);
    165129                break;
    166130        }
    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) {
    180134        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;
    186193        }
    187194        return result;
    188195    }
    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) {
    225198        switch(graph.types[id]) {
    226199            case 'n':
    227200                var input = element(id).val();
     201                var result;
    228202                if(id in graph.data) {
    229203                    var factor = to_float_for_factor(graph.data[id]);
    230204                    if(!isNaN(factor)) {
    231                         return input*factor;
     205                        result = input*factor;
    232206                    } else {
    233                         return input;
     207                        result = input;
    234208                    }
    235209                } else {
    236                     return input;
     210                    result = input;
    237211                }
     212                return types.value(result);
     213            case 'a':
     214                var input = element(id).val();
     215                return types.value(input);
    238216            case 'r':
    239217                var idx = element(id).find('input:checked').parent().index();
     218                var result;
    240219                if(idx>=0) {
    241                     return graph.data[id][idx];
     220                    result = graph.data[id][idx];
    242221                } else {
    243                     return 0;
     222                    result = 0;
    244223                }
     224                return types.value(result);
    245225            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]);
    247227            case 'd':
    248228                var idx = element(id).find('option:selected').index();
     229                var result;
    249230                if(idx>=0) {
    250                     return graph.data[id][idx];
     231                    result = graph.data[id][idx];
    251232                } else {
    252                     return 0;
     233                    result = 0;
    253234                }
     235                return types.value(result);
    254236            case 'f':
    255                 return formula(id);
     237                return calculator.formula(graph.formulas[id]);
    256238            case 'm':
    257239            case 't':
    258240            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   
    268254    function to_float_for_factor(val) {
    269255        if(typeof val == 'string' && val.match(/^\s*$/)) {
     
    274260    }
    275261   
    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        }
    346277    }
    347278   
    348279}
    349280
    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);
     281function 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           
    369327            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           
    378340            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           
    384347            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           
    390353            return Math.log(x);
    391354        },
    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);
    395358            return Math.log(x) / Math.log(b);
    396359        },
    397         'log10': function() {
    398             var x = numarg(0);
     360        'log10': function(args) {
     361            var x = _number(args);
    399362            return Math.log(x) / Math.log(10);
    400363        },
    401         'exp': function() {
    402             var x = numarg(0);
     364        'exp': function(args) {
     365            var x = _number(args);
    403366            return Math.exp(x);
    404367        },
    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);
    408371            return Math.pow(x, y);
    409372        },
    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) {
    432402            return Math.PI;
    433403        },
    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) {
    447425            return true;
    448426        },
    449         'false': function() {
     427        'false': function(args) {
    450428            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);
    451437        }
    452438       
    453439    };
    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    }
    456502}
    457503
     
    507553    }
    508554   
     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   
    509573    round();
    510574   
    511     var str = "" + input;
     575    var str = to_text(input);
    512576    var parts = str.split('.');
    513577    var sign;
     
    523587    return sign + args.prefix + natural + (decimals.length ? args.point + decimals + args.postfix : args.postfix);
    524588}
     589
     590function Jzzf_Error(code) {
     591    this.code = code;
     592    this.toString = function() { return this.code; }
     593}
     594
     595function 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
     699function 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
     738function 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
     751function 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  
    1818   
    1919    function theme($num) {?>
    20     <style type="text/css">
     20    <style type="text/css" scoped="scoped">
    2121        @import url(<?php echo plugins_url('themes/' . ((int) $num)  . '.css', JZZF_ROOT . 'front/tmpl-list.php') ?>);
    2222    </style>
     
    4545        };
    4646        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 ?>);
    4848    </script>
    4949<?php
     
    7676   
    7777    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>
    8086<?php
    8187    }
     
    8692    <?php $idx = 0; foreach($element->options as $option) { $idx++; ?>
    8793    <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>
    9096    </li>
    9197<?php
     
    95101   
    96102    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) ?>">
    99105    <?php foreach($element->options as $option) : ?>
    100106    <option<?php if($option->default): ?> selected="selected"<?php endif ?>><?php esc_html_e($option->title) ?></option>
     
    105111
    106112    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>
    109115<?php
    110116    }
     
    116122   
    117123    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 ?>>
    120126<?php
    121127    }
  • jazzy-forms/trunk/jazzy-forms.php

    r567987 r581482  
    44Plugin URI: http://www.jazzyforms.com/
    55Description: Online form builder with an emphasis on calculation
    6 Version: 0.9.10
     6Version: 0.10
    77Author: Igor Prochazka
    88Author URI: http://www.l90r.com/
     
    2828*/
    2929
    30 define(JZZF_VERSION, 0.0910);
    31 define(JZZF_VERSION_STRING, "0.0910");
     30define(JZZF_VERSION, 0.1000);
     31define(JZZF_VERSION_STRING, "0.1000");
    3232define(JZZF_OPTION_VERSION, 'jzzf_version');
    3333
  • jazzy-forms/trunk/readme.txt

    r567987 r581482  
    119119== Changelog ==
    120120
     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
    121133= 0.9.10 =
    122134* Take into account text elements without placeholders (urgent fix)
Note: See TracChangeset for help on using the changeset viewer.