"logic builder"
Bootstrap 3.0.0 Snippet by evarevirus

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!DOCTYPE html><html lang='en' class=''> <head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/bernesto/pen/ybzbKW?depth=everything&order=popularity&page=48&q=Builder&show_forks=false" /> <link rel='stylesheet prefetch' href='https://static.neoreef.com/common/fonts/fontawesome/4.7.0/css/font-awesome.min.css'> <style class="cp-pen-styles">#program{ font-family: sans-serif; font-size: 14px; background-color:#ededed; border-radius: 0.5em; padding: 0.5em 1em; margin: 0.5em 0px; } #statements, #objects{ padding-left: 0; } #program .fa{ font-size: 1em; } #statements, #objects{ line-height: 2em } .statement{ background-color:rgba(0,0,0,0.2); border: 1px solid transparent; border-radius: 0.5em; padding: 0.5em 1em; margin: 0.5em 0px; display: block; transition: border 1s, box-shadow 1s; } .group{ background-color:rgba(0,255,0,0.2); padding: 1px 9px; margin: 1px; border-radius: 4px; display: inline-block; } .segment{ background-color:rgba(0,0,255,0.2); padding: 1px 9px; margin: 1px; border-radius: 4px; display: inline-block; } .condition{ background-color:white; padding: 0 6px; margin: 1px; border-radius: 4px; display: inline-block; line-height: 1.7em; } #statements input, #statements textarea, #objects input{ border: 1px solid transparent; padding: 3px; } #statements button{ border: 1px solid transparent; padding: 3px 5px; border-radius: 4px; background-color: #ededed; } #statements li{ list-style-type: none; } #statements .error{ border: 1px solid red; } .nowrap{ whitespace: nowrap; } .evaluated{ border: 1px solid rgb(0,100,250); box-shadow: 0px 0px 10px rgb(0,100,250); } </style></head><body> <div id="program"> <script type="text/html" id="group"> <select data-bind=" visible: (($index() > 0 && $parent.groups) || ($parent.conditions && $parent.conditions().length > 0)), options: booleanTypes(), optionsText: 'label', optionsValue: 'value', value: boolean, valueAllowUnset: true "></select> <span class="group"> ( <span data-bind="template: {if: conditions, name: 'condition', foreach: conditions}"></span> <span data-bind="template: {if: groups, name: 'group', foreach: groups}"></span> <button data-bind="click: addCondition, css: { error: (conditions().length == 0 && groups().length == 0) }, visible: (groups().length == 0) "><i class="fa fa-plus-square"></i> Condition</button> <button data-bind=" click: addGroup, css: { error: (conditions().length == 0 && (groups().length == 0)) }, visible: (conditions().length == 0) "><i class="fa fa-plus-square-o"></i> Group</button> ) <button data-bind=" visible: $parent.conditions, click: $parent.removeGroup "><i class="fa fa-trash"></i></button> </span> </script> <script type="text/html" id="condition"> <select data-bind="visible: ($index() > 0), options: booleanTypes(), optionsText: 'label', optionsValue: 'value', value: boolean, valueAllowUnset: true"></select> <span class="condition nowrap"> <input data-bind="datalist: { options: $root.objects(1), optionsText: 'name' }, value: value1, valueUpdate: 'afterkeydown'" placeholder="empty" size="10" type="text" list="value1List"> <select data-bind="options: conditionTypes(), optionsText: 'label', optionsValue: 'value', value: conditionType"></select> <input data-bind="datalist: { options: $root.objects(1), optionsText: 'name' }, value: value2, valueUpdate: 'afterkeydown'" placeholder="empty" size="10" type="text" list="value1List"> <button data-bind="click: $parent.removeCondition" class="fa fa-trash"></button> </span> </script> <script type="text/html" id="event"> <span class="group"><select data-bind="options: formEvents, optionsText: 'name', value: eventObject, valueAllowUnset: true, optionsCaption: 'Choose...', css: {error: !eventObject()}, disable: disabled"></select> <span data-bind="with: eventObject"> <select data-bind="options: events, value: event, valueAllowUnset: true, optionsCaption: 'Choose...', css: {error: !event}, disable: $parent.disabled"></select> </span> </span> <span class="segment">Then</span> <ul data-bind="template: {if: statements, name: 'statement-template', foreach: statements }"></ul> <ul> <li><button data-bind="click: addStatement, css: {error: statements().length == 0}"><i class="fa fa-plus"></i> Statement</button></li> </ul> <span class="segment">End Event</span> </script> <script type="text/html" id="if"> <span data-bind="template: {if: expression, name: 'group', data: expression}"></span> <span class="segment">Then</span> <ul data-bind="template: {if: statements, name: 'statement-template', foreach: statements }"></ul> <ul> <li><button data-bind="click: addStatement, css: {error: statements().length == 0}"><i class="fa fa-plus"></i> Statement</button></li> </ul> <span class="segment">End If</span> </script> <script type="text/html" id="ifelse"> <span data-bind="template: {if: expression, name: 'group', data: expression}"></span> <span class="segment">Then</span> <ul data-bind="template: {if: statements, name: 'statement-template', foreach: statements }"></ul> <ul> <li><button data-bind="click: addStatement, css: {error: !statements() || statements().length == 0}"><i class="fa fa-plus"></i> Statement</button></li> </ul> <span class="segment">Else</span> <ul data-bind="template: {if: elseStatements, name: 'else-statement-template', foreach: elseStatements }"></ul> <ul> <li><button data-bind="click: addElseStatement, css: {error: !elseStatements() || elseStatements().length == 0}"><i class="fa fa-plus"></i> Statement</button></li> </ul> <span class="segment">End If-Else</span> </script> <script type="text/html" id="variable"> <span class="group"><input data-bind="datalist: { options: $root.objects(2), optionsText: 'name' }, value: variableName, valueUpdate: 'afterkeydown', css: {error: variableName() == ''}" placeholder="name" size="10" type="text" list="nameList"> = <input data-bind="datalist: { options: $root.objects(1), optionsText: 'name' }, value: variableValue, valueUpdate: 'afterkeydown'" placeholder="empty" size="10" type="text" list="valueList"></span> </script> <script type="text/html" id="stop"> <span class="group">Stop Processing</span> </script> <script type="text/html" id="action"> <span class="group"><select data-bind="options: actionTypes(), optionsText: 'label', optionsValue: 'value', value: actionType, valueAllowUnset: true, optionsCaption: 'Choose...', css: {error: !actionType()}"></select></span> <span data-bind='template: {if: actionType, name: actionType}'></span> </script> <script type="text/html" id="email"> <div> <input data-bind=" value: $data.actionData().from, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().from && $data.actionData().from() == '')} " placeholder="from" style="width: 25%"> <input data-bind=" value: $data.actionData().to, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().to && $data.actionData().to() == '')} " placeholder="to" style="width: 25%"> </div> <input data-bind=" value: $data.actionData().subject, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().subject && $data.actionData().subject() == '')} " placeholder="subject" style="width: 99%"> <textarea data-bind=" value: $data.actionData().message, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().message && $data.actionData().message() == '')} " placeholder="message" style="width: 99%" rows="5"></textarea> </script> <script type="text/html" id="message"> <textarea data-bind=" value: $data.actionData().message, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().message && $data.actionData().message() == '')} " placeholder="message" style="width: 99%" rows="5"></textarea> </script> <script type="text/html" id="post"> <input data-bind=" value: $data.actionData().url, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().url && $data.actionData().url() == '')} " placeholder="url" style="width: 99%"> <textarea data-bind=" value: $data.actionData().body, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().body && $data.actionData().body() == '')} " placeholder="body" style="width: 99%" rows="5"></textarea> </script> <script type="text/html" id="redirect"> <input data-bind=" value: $data.actionData().url, valueUpdate: 'afterkeydown', css: {error: ($data.actionData().url && $data.actionData().url() == '')} " placeholder="url" style="width: 99%"> </script> <script type="text/html" id="submit"> <!-- Do nothing --> </script> <script type="text/html" id="click"> <input data-bind="datalist: { options: $root.objects(3), optionsText: 'name' }, value: $data.eventData().name, valueUpdate: 'afterkeydown', css: {error: $data.eventData().name == ''}" placeholder="event name" size="10" type="text" list="nameList"> </script> <script type="text/html" id="change"> <input data-bind="datalist: { options: $root.objects(4), optionsText: 'name' }, enabled: $data.enabled, value: $data.eventData().name, valueUpdate: 'afterkeydown', css: {error: $data.eventData().name == ''}" placeholder="event name" size="10" type="text" list="nameList"> </script> <script type="text/html" id="statement-template"> <li class="statement" data-bind="css: {evaluated: evaluated}"> <div> <button data-bind="click: $parent.removeStatement, visible: !disabled()" class="fa fa-trash"></button> <button data-bind="visible: ($index() > 0), click: $parent.moveUpStatement" class="fa fa-angle-up"></button> <button data-bind="visible: ($index() < $parent.statements().length - 1), click: $parent.moveDownStatement" class="fa fa-angle-down"></button> </div> <span class="segment"><select data-bind="options: statementTypes(), optionsText: 'label', optionsValue: 'value', value: statementType, valueAllowUnset: true, optionsCaption: 'Choose...', css: {error: !statementType()}, disable: disabled"></select></span> <span data-bind="template: {if: statementType, name: statementType}"></span> </li> </script> <script type="text/html" id="else-statement-template"> <li class="statement" data-bind="css: {evaluated: evaluated}"> <div> <button data-bind="click: $parent.removeElseStatement" class="fa fa-trash"></button> <button data-bind="visible: ($index() > 0), click: $parent.moveUpElseStatement" class="fa fa-angle-up"></button> <button data-bind="visible: ($index() < $parent.elseStatements().length - 1), click: $parent.moveDownElseStatement" class="fa fa-angle-down"></button> </div> <select data-bind="options: statementTypes(), optionsText: 'label', optionsValue: 'value', value: statementType"></select> <span data-bind='template: {if: statementType, name: statementType}'></span> </li> </script> <div id="program-ui"> <div><button style="float: right" data-bind="click: evaluate, visible: statements().length > 0"><i class="fa fa-check-circle"></i> Evaluate Logic</button><h2>Form Logic</h2></div> <h4>Fields</h4> <ul id="objects" data-bind="foreach: objects(0)"> <li class="statement"><span class="group"><input data-bind="value: name" disabled>=<input placeholder="empty" data-bind="value: value"></span></li> </ul> <h4>Events</h4> <ul id="statements" data-bind="template: {if: statements, name: 'statement-template', foreach: statements }"></ul> <div style="text-align: center"> <button data-bind="click: addStatement"><i class="fa fa-plus"></i> Statement</button> </div> </div> <fieldset data-bind="visible: output"><legend>Evaluation Results</legend> <div style="padding: 0em 5em" data-bind="html: output"></div> </fieldset> <textarea data-bind="value: ko.toJSON($rawData, null, 2)"></textarea> </div> <script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script><script src='https://static.neoreef.com/common/js/libs/knockout/3.2.0/knockout-3.2.0.min.js'></script> <script >$(function(){ if(console) console.clear(); ko.bindingHandlers.datalist = (function () { var uid = 0; function createId() { return "ko-datalist-" + (++uid); } function getVal(rawItem, prop) { var item = ko.unwrap(rawItem); return item && prop ? ko.unwrap(item[prop]) : item; } function findItem(options, prop, ref) { return ko.utils.arrayFirst(options, function (item) { return ref === getVal(item, prop); }); } return { after: ['value'], init: function (element, valueAccessor, allBindingsAccessor) { var setup = valueAccessor(), textProperty = ko.unwrap(setup.optionsText), valueProperty = ko.unwrap(setup.optionsValue), dataItems = ko.unwrap(setup.options), myValue = setup.value, datalist = document.createElement("DATALIST"), shouldSet = false; // create an associated <datalist> element var id = createId(); element.setAttribute("list", id); datalist.id = id; if (element.parentNode) { element.parentNode.appendChild(datalist); } else { document.body.appendChild(datalist); } // when the value is changed, write to the associated myValue observable function updateModel() { if (!shouldSet) { return; } var newVal = element.value, dataItems = ko.unwrap(setup.options), selectedItem = findItem(dataItems, textProperty, newVal), newValue = selectedItem ? getVal(selectedItem, valueProperty) : newVal; if (ko.isWriteableObservable(myValue)) { myValue(newValue); } } function updateView() { var modelValue = ko.unwrap(myValue), dataItems = ko.unwrap(setup.options), selectedItem = findItem(dataItems, valueProperty, modelValue), newValue = selectedItem ? getVal(selectedItem, textProperty) : undefined; element.value = newValue || element.value; } // The first responds to changes in the value and to element changes ko.dependentObservable(updateModel, null, { disposeWhenNodeIsRemoved: element }); ko.utils.registerEventHandler(element, "change", updateModel); // The second responds to changes in the model value (the one associated with the checked binding) ko.dependentObservable(updateView, null, { disposeWhenNodeIsRemoved: element }); shouldSet = true; }, update: function (element, valueAccessor) { var setup = valueAccessor(), datalist = element.list, dataItems = ko.unwrap(setup.options), textProperty = ko.unwrap(setup.optionsText), valueProperty = ko.unwrap(setup.optionsValue), descriptionProperty = ko.unwrap(setup.optionsDescription); // rebuild list of options when an underlying observable changes datalist.innerHTML = ""; ko.utils.arrayForEach(dataItems, function (item) { var option = document.createElement("OPTION"); option.value = getVal(item, textProperty); if (descriptionProperty) { option.innerText = getVal(item, descriptionProperty); } datalist.appendChild(option); }); ko.utils.triggerEvent(element, "change"); } }; })(); ko.observableArray.fn.move = function (from, to) { if (from !== to && 0 <= from && from <= this().length && 0 <= to && to <= this().length) { this.splice(to, 0, this.splice(from, 1)[0]); } }; var dataModel = function(init){ var self = this; init = init||[]; for(var i = 0; i < init.length; i++){if (window.CP.shouldStopExecution(1)){break;} if(Array.isArray(init[i].value)){ self[init[i].property] = ko.observableArray(init[i].value) }else{ self[init[i].property] = ko.observable(init[i].value) } } window.CP.exitedLoop(1); } var groupModel = function(init, scope){ var self = this; init=init||{}; self.booleanTypes = function(){ return [ {"label":"AND", "value":"and"}, {"label":"OR", "value":"or"} ]}; self.boolean = ko.observable(init.boolean); self.conditions = ko.observableArray((function(data){ var ar = []; if(data){ for(var i = 0; i < data.length; i++){if (window.CP.shouldStopExecution(2)){break;} ar.push(new conditionModel(data[i], scope)); } window.CP.exitedLoop(2); } return ar; })(init.conditions)); self.groups = ko.observableArray((function(data){ var ar = []; if(data){ for(var i = 0; i < data.length; i++){if (window.CP.shouldStopExecution(3)){break;} ar.push(new groupModel(data[i], scope)); } window.CP.exitedLoop(3); } return ar; })(init.groups)); self.addCondition = function(){ self.conditions.push(new conditionModel({}, scope)); }; self.removeCondition = function(){ self.conditions.remove(this); }; self.addGroup = function(){ self.groups.push(new groupModel({}, scope)); }; self.removeGroup = function(){ self.groups.remove(this); }; self.evaluate = function(){ var boolean = "" var result = true; $.each(self.conditions(), function(index, condition){ boolean = condition.boolean(); if(boolean == "and"){ result = (result && condition.evaluate()); }else{ result = (result || condition.evaluate()); } }); $.each(self.groups(), function(index, group){ boolean = group.boolean(); if(boolean == "and"){ result = (result && group.evaluate()); }else{ result = (result || group.evaluate()); } }); return result; } }; var conditionModel = function(init, scope){ var self = this; init=init||{}; self.booleanTypes = function(){ return [ {"label":"AND", "value":"and"}, {"label":"OR", "value":"or"} ]}; self.boolean = ko.observable(init.boolean); self.value1 = ko.observable(init.value1||""); self.conditionTypes = function(){ return [ {"label":"==", "value":"=="}, {"label":"<>", "value":"<>"}, {"label":">=", "value":">="}, {"label":"<=", "value":"<="}, {"label":">", "value":">"}, {"label":"<", "value":"<"}, {"label":"In", "value":"in"} ]}; self.conditionType = ko.observable(init.conditionType||"=="); self.value2 = ko.observable(init.value2||""); self.evaluate = function(){ var result = false; var v1, v2; if(scope.variables[self.value1()] != undefined){ v1 = scope.variables[self.value1()]; }else{ v1 = self.value1(); } if(scope.variables[self.value2()] != undefined){ v2 = scope.variables[self.value2()]; }else{ v2 = self.value2(); } switch(self.conditionType()){ case "==": result = v1 == v2; break; case "<>": result = v1 != v2; break; case ">=": result = v1 >= v2; break; case "<=": result = v1 <= v2; break; case ">": result = v1 > v2; break; case "<": result = v1 < v2; break; case "in": result = v1.indexOf(v2) > 0; break; } return result; } }; var statementModel = function(init, scope){ var self = this; init=init||{}; // Setup statements self.statementTypes = function(){return [ {"label":"Action", "value":"action"}, {"label":"On Event", "value":"event"}, {"label":"If", "value":"if"}, {"label":"If-Else", "value":"ifelse"}, {"label":"Set Variable", "value":"variable"}, {"label":"Stop", "value":"stop"} ]}; self.statementType = ko.observable(); self.disabled = ko.observable(init.disabled||false); // Set up actions self.actionTypes = function(){ return [ {"label":"Display Message", "value":"message"}, {"label":"Send Email", "value":"email"}, {"label":"Redirect", "value":"redirect"}, {"label":"Post Values", "value":"post"} ]}; self.actionType = ko.observable(); self.actionData = ko.observable(); var actionConfig = function(val, data){ data = data||{}; switch(val){ case "message": return new dataModel([ {"property":"message", "value": data.message||""} ]); case "email": return new dataModel([ {"property":"to", "value": data.to||""}, {"property":"from", "value": data.from||""}, {"property":"subject", "value": data.subject||""}, {"property":"message", "value": data.message||""} ]); case "post": return new dataModel([ {"property":"url", "value": data.url||""}, {"property":"body", "value": data.body||""} ]); case "redirect": return new dataModel([ {"property":"url", "value": data.url||""} ]); default: return {}; } } // Set up events self.eventObject = ko.observable(); self.formEvents = ko.observableArray(scope.objects(3)()); for(i=0;i<self.formEvents().length;i++){if (window.CP.shouldStopExecution(5)){break;} if(init.statementType == "event"){ var evo = self.formEvents()[i] var evs = evo.events() if(evs){ for(p=0;p<evs.length;p++){if (window.CP.shouldStopExecution(4)){break;} if(init.eventObject.id == evo.id && init.eventObject.event == evs[p]){ evo.event(evs[p]); self.eventObject(evo); } } window.CP.exitedLoop(4); } } } window.CP.exitedLoop(5); // Setup conditional expression self.expression = ko.observable(new groupModel(init.expression, scope)); // Setup statements self.statements = ko.observableArray((function(data){ var ar = []; if(data){ for(i=0;i<data.length; i++){if (window.CP.shouldStopExecution(6)){break;} ar.push(new statementModel(data[i], scope)); } window.CP.exitedLoop(6); } return ar; })(init.statements)); self.addStatement = function(){ self.statements.push(new statementModel({}, scope)); scope.reset(); }; self.removeStatement = function(val){ self.statements.remove(this); scope.reset(); }; self.moveUpStatement = function(){ var from = self.statements.indexOf(this); self.statements.move(from, from - 1); scope.reset(); }; self.moveDownStatement = function(){ var from = self.statements.indexOf(this); self.statements.move(from, from + 1); scope.reset(); }; // Setup else statements self.elseStatements = ko.observableArray((function(data){ var ar = []; if(data){ for(var i = 0; i < data.length; i++){if (window.CP.shouldStopExecution(7)){break;} ar.push(new statementModel(data[i], scope)); } window.CP.exitedLoop(7); } return ar; })(init.elseStatements)); self.addElseStatement = function(){ self.elseStatements.push(new statementModel({}, scope)); scope.reset(); }; self.removeElseStatement = function(val){ self.elseStatements.remove(this); scope.reset(); }; self.moveUpElseStatement = function(){ var from = self.elseStatements.indexOf(this); self.elseStatements.move(from, from - 1); scope.reset(); }; self.moveDownElseStatement = function(){ var from = self.elseStatements.indexOf(this); self.elseStatements.move(from, from + 1); scope.reset(); }; // Setup variable statements self.variableName = ko.observable(init.variableName); self.variableValue = ko.observable(init.variableValue); self.actionType.subscribe(function(val){ self.actionData(actionConfig(val)); }); self.statementType.subscribe(function(val){ switch(val){ case "action": self.expression(undefined); self.actionType(undefined); self.statements(undefined); self.elseStatements(undefined); self.variableName(undefined); self.variableName(undefined); self.variableValue(undefined); break; case "event": self.expression(undefined); if(!self.statements()) self.statements([]); self.actionType(undefined); self.actionData(undefined); self.elseStatements(undefined); self.variableName(undefined); self.variableValue(undefined); break; case "if": if(!self.expression()) self.expression(new groupModel(init.expression, scope)); if(!self.statements()) self.statements([]); self.actionType(undefined); self.actionData(undefined); self.elseStatements(undefined); self.variableName(undefined); self.variableValue(undefined); break; case "ifelse": if(!self.expression()) self.expression(new groupModel(init.expression, scope)); if(!self.statements()) self.statements([]); if(!self.elseStatements()) self.elseStatements([]); self.actionType(undefined); self.actionData(undefined); self.variableName(undefined); self.variableValue(undefined); break; case "stop": self.actionType(undefined); self.actionData(undefined); self.expression(undefined); self.statements(undefined); self.elseStatements(undefined); self.variableName(undefined); self.variableValue(undefined); break; case "variable": self.actionType(undefined); self.actionData(undefined); self.expression(undefined); self.statements(undefined); self.elseStatements(undefined); break; default: self.expression(undefined); self.actionType(undefined); self.actionData(undefined); self.statements(undefined); self.elseStatements(undefined); self.variableName(undefined); self.variableName(undefined); self.variableValue(undefined); } }); self.statementType(init.statementType); self.actionType(init.actionType); self.actionData(actionConfig(init.actionType, init.actionData)); self.evaluated = ko.observable(false) self.reset = function(){ self.evaluated(false); $.each(self.statements(), function(index, statement){ statement.reset(); }); $.each(self.elseStatements(), function(index, statement){ statement.reset(); }); } self.evaluate = function(indent){ indent = indent||0; indent++; // Reset eval on children self.reset(); self.evaluated(true); setTimeout(function(){self.reset();}, 2000); switch(self.statementType()){ case "action": scope.log(indent, "Perform action: " + self.actionType()); return true; break; case "event": scope.log(indent, "On event: " + self.eventObject().name + "." + self.eventObject().event()); for(i=0; i<self.statements().length; i++) {if (window.CP.shouldStopExecution(8)){break;} var statement = self.statements()[i]; if(!statement.evaluate(indent)){ return false; } } window.CP.exitedLoop(8); return true; break; case "if": if(self.expression().evaluate()){ scope.log(indent, "If evaluation: true"); for(i=0; i<self.statements().length; i++) {if (window.CP.shouldStopExecution(9)){break;} var statement = self.statements()[i]; if(!statement.evaluate(indent)){ return false; } } window.CP.exitedLoop(9); } return true; break; case "ifelse": if(self.expression().evaluate()){ scope.log(indent, "If evaluation: true"); for(i=0; i<self.statements().length; i++) {if (window.CP.shouldStopExecution(10)){break;} var statement = self.statements()[i]; if(!statement.evaluate(indent)){ return false; } } window.CP.exitedLoop(10); }else{ scope.log(indent, "Else evaluation: true"); for(i=0; i<self.elseStatements().length; i++) {if (window.CP.shouldStopExecution(11)){break;} var statement = self.elseStatements()[i]; if(!statement.evaluate(indent)){ return false; } } window.CP.exitedLoop(11); } return true; break; case "stop": scope.log(indent, "Stop processing"); return false; break; case "variable": var vname = self.variableName()||""; if (vname.match(/^[a-z][a-z0-9]*/i)) { if(scope.variables) scope.variables[vname] = self.variableValue(); scope.log(indent, "Set variable: " + vname + "=" + self.variableValue()); return true; }else{ if(!vname) vname = "[Empty string]"; alert("Invalid variable name:" + vname) return false; } break; } self.reset(); } }; var mainModel = function(init){ var self = this; init=init||{}; self.objects = function(ter){ return (ko.computed(function(){ // Reset variables if(self.variables) self.variables = {}; var objs = jQuery.extend(true, [], init.objects); var fields = []; var fieldsWithEvents = []; $.each(objs, function(index, obj){ $.each(obj.properties, function(index, prop){ if(Array.isArray(prop.value)){ obj[prop.property] = ko.observableArray(prop.value); }else{ obj[prop.property] = ko.observable(prop.value); } }); if(obj.type == "field"){ obj.label = "[" + obj.name + "]"; fields.push(obj); } if(obj.events){ obj.event = ko.observable(); fieldsWithEvents.push(obj); } delete obj.properties; }) var ar; // Objects only if(!ter || ter == 0){ return ko.observableArray(fields); }else if(ter == 1){ // Objects and variables ar = ko.observableArray(objs); }else if(ter == 2){ // Variables only ar = ko.observableArray([]); }else if(ter == 3){ // Objets with events only return ko.observableArray(fieldsWithEvents); } // Variables only ar = ko.observableArray([]); var findVars = function(statement){ if(statement.statementType() == "variable"){ var vname = statement.variableName()||""; if (vname.match(/^[a-z][a-z0-9]*/i)) { if(!self.variables) self.variables = {}; self.variables[vname] = statement.variableValue(); ar.push({ type: "variable", name: vname, properties: { value: statement.variableValue() } }); } }else{ $.each(statement.statements(), function(index, st){ findVars(st); }); $.each(statement.elseStatements(), function(index, st){ findVars(st); }); } } $.each(self.statements(), function(index, statement){ findVars(statement); }); if(self.variables && Object.keys(self.variables).length == 0) delete self.variables; return ar; }) )() } self.statements = ko.observableArray((function(data){ var ar = []; if(data){ for(var i=0; i<data.length; i++){if (window.CP.shouldStopExecution(12)){break;} ar.push(new statementModel(data[i], self)); } window.CP.exitedLoop(12); } return ar; })(init.statements)); self.addStatement = function(){ self.statements.push(new statementModel({}, self)); self.reset(); }; self.removeStatement = function(){ self.statements.remove(this); self.reset(); }; self.moveUpStatement = function(){ var from = self.statements.indexOf(this); self.statements.move(from, from - 1); self.reset(); }; self.moveDownStatement = function(){ var from = self.statements.indexOf(this); self.statements.move(from, from + 1); self.reset(); }; self.output = ko.observable(""); self.log = function(indent, val){ indent =indent||0; self.output(self.output() + "<br>" + Array(indent*4).join(' ') + val) } self.reset = function(){ if(console) console.log("reset") self.output(""); for(i=0; i<self.statements().length; i++) {if (window.CP.shouldStopExecution(13)){break;} var statement = self.statements()[i]; if(!statement.reset()){ return; } } window.CP.exitedLoop(13); } self.evaluate = function(indent){ if(console) console.clear(); self.output(""); for(i=0; i<self.statements().length; i++) {if (window.CP.shouldStopExecution(14)){break;} var statement = self.statements()[i]; if(!statement.evaluate(indent)){ return; } } window.CP.exitedLoop(14); } }; var main = function(init){ var self = this; init = init||{}; self.viewModel = new mainModel(init); ko.applyBindings(self.viewModel, $("#progam")[0]); } main( { objects: [ { type: "event", name: "Form", id: "form", properties: [ {property: "events", value: ["submit","validate"]} ] }, { type: "field", name: "My Dropdown", id: "123", properties: [ {property: "controlType", value: "Dropdown"}, {property: "visible", value: "false"}, {property: "value", value: "Sample"}, {property: "events", value: ["Change"]} ] }, { type: "field", name: "My Text Area", id: "456", properties: [ {property: "controlType", value: "Text_Area"}, {property: "visible", value: "false"}, {property: "value", value: "Sample"}, {property: "events", value: ["Change"]} ] }, { type: "field", name: "My Text Box", id: "789", properties: [ {property: "controlType", value: "Text_Box"}, {property: "value", value: "Sample 2"}, {property: "Validate", value: "true"}, {property: "events", value: ["Change"]} ] } ], statements: [ { "statementType": "event", "eventObject": { "type": "event", "name": "Form", "id": "form", "event": "submit" }, "disabled": true, "statements": [ { "statementType": "variable", "actionData": {}, "variableName": "Val1", "variableValue": "123" }, { "statementType": "ifelse", "actionData": {}, "expression": { "conditions": [ { "value1": "Val1", "conditionType": "<>", "value2": "123" } ], "groups": [] }, "statements": [ { "statementType": "action", "actionType": "email", "actionData": { "to": "jane@email.com", "from": "joe@email.com", "subject": "Hello World", "message": "My Message" } }, { "statementType": "stop", "actionData": {} } ], "elseStatements": [ ] }, { "statementType": "action", "actionType": "redirect", "actionData": { "url": "http://www.test.com" } } ] } ] } ); } ) /* var FormLogic = function(){ var self = this; this.LogicID = 0; this.FormID = 0; this.FieldID = 0; this.ParentID = 0; this.LogicOrder = 0; this.Type = ""; this.TypeData = {}; } var FormAction = function(){ var self = this; this.ActionID = 0; this.FormID = 0; this.FieldID = 0; this.LogicID = 0; this.ActionOrder = 0; this.Type = ""; this.TypeData = {}; } */ //# sourceURL=pen.js </script> </body></html>

Related: See More


Questions / Comments: