Skip to content

Commit

Permalink
Add visibleIf attribute to page and question objects: #60
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtelnov committed Sep 7, 2016
1 parent 3fea810 commit cbd51e2
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/survey-knockout-bootstrap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "survey-knockout-bootstrap",
"version": "0.9.10",
"version": "0.9.11",
"description": "survey.js is a JavaScript Survey Library. It is a modern way to add a survey to your website. It uses JSON for survey metadata and results.",
"keywords": [
"Survey",
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-knockout/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "survey-knockout",
"version": "0.9.10",
"version": "0.9.11",
"description": "survey.js is a JavaScript Survey Library. It is a modern way to add a survey to your website. It uses JSON for survey metadata and results.",
"keywords": [
"Survey",
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-react-bootstrap/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "survey-react-bootstrap",
"version": "0.9.10",
"version": "0.9.11",
"description": "survey.js is a JavaScript Survey Library. It is a modern way to add a survey to your website. It uses JSON for survey metadata and results.",
"keywords": [
"Survey",
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "survey-react",
"version": "0.9.10",
"version": "0.9.11",
"description": "survey.js is a JavaScript Survey Library. It is a modern way to add a survey to your website. It uses JSON for survey metadata and results.",
"keywords": [
"Survey",
Expand Down
7 changes: 5 additions & 2 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@
storeOthersAsComment: boolean;
uploadFile(name: string, file: File, storeDataAsText: boolean, uploadingCallback: (status: string) => any): boolean;
}
export interface IQuestion {
export interface IConditionRunner {
runCondition(values: HashTable<any>);
}
export interface IQuestion extends IConditionRunner {
name: string;
visible: boolean;
hasTitle: boolean;
setVisibleIndex(value: number);
onSurveyValueChanged(newValue: any);
}
export interface IPage {
export interface IPage extends IConditionRunner {
visible: boolean;
}

Expand Down
12 changes: 11 additions & 1 deletion src/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,16 @@ module Survey {
public perform(left: any = null, right: any = null): boolean {
if (!left) left = this.left;
if (!right) right = this.right;
return Condition.operators[this.operator](left, right);

return Condition.operators[this.operator](this.getPureValue(left), this.getPureValue(right));
}
private getPureValue(val: any): any {
if (!val || (typeof val != "string")) return val;
var str = "";
if (val.length > 0 && (val[0] == "'" || val[0] == '"')) val = val.substr(1);
var len = val.length;
if (len > 0 && (val[len - 1] == "'" || val[len - 1] == '"')) val = val.substr(0, len - 1);
return val;
}
}
export class ConditionNode {
Expand Down Expand Up @@ -65,6 +74,7 @@ module Survey {
}
public get expression(): string { return this.expressionValue; }
public set expression(value: string) {
if (this.expression == value) return;
this.expressionValue = value;
new ConditionsParser().parse(this.expressionValue, this.root);
}
Expand Down
12 changes: 10 additions & 2 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ module Survey {
private calcVisible(): boolean { return this.getVisibleCount() > 0; }
}

export class PageModel extends Base implements IPage {
export class PageModel extends Base implements IPage, IConditionRunner {
private rowValues: Array<QuestionRowModel> = null;
private conditionRunner: ConditionRunner = null;
questions: Array<QuestionBase> = new Array<QuestionBase>();
public data: ISurvey = null;
public visibleIf: string = "";

public title: string = "";
public visibleIndex: number = -1;
Expand Down Expand Up @@ -185,8 +187,14 @@ module Survey {
list.push(this.questions[i]);
}
}
public runCondition(values: HashTable<any>) {
if (!this.visibleIf) return;
if (!this.conditionRunner) this.conditionRunner = new ConditionRunner(this.visibleIf);
this.conditionRunner.expression = this.visibleIf;
this.visible = this.conditionRunner.run(values);
}
protected onNumChanged(value: number) {
}
}
JsonObject.metaData.addClass("page", ["name", { name: "questions", baseClassName: "question" }, { name: "visible:boolean", default: true }, "title"], function () { return new PageModel(); });
JsonObject.metaData.addClass("page", ["name", { name: "questions", baseClassName: "question" }, { name: "visible:boolean", default: true }, "visibleIf", "title"], function () { return new PageModel(); });
}
14 changes: 11 additions & 3 deletions src/questionbase.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/// <reference path="base.ts" />
/// <reference path="jsonobject.ts" />
module Survey {
export class QuestionBase extends Base implements IQuestion {
export class QuestionBase extends Base implements IQuestion, IConditionRunner {
private static questionCounter = 100;
private static getQuestionId(): string {
return "sq_" + QuestionBase.questionCounter++;
}
protected data: ISurveyData;
protected survey: ISurvey;
private conditionRunner: ConditionRunner = null;
public visibleIf: string = "";
private idValue: string;
private visibleValue: boolean = true;
public startWithNewLine: boolean = true;
Expand Down Expand Up @@ -67,7 +69,13 @@ module Survey {
}
protected onSetData() { }
protected onCreating() { }
//IQuestion
public runCondition(values: HashTable<any>) {
if (!this.visibleIf) return;
if (!this.conditionRunner) this.conditionRunner = new ConditionRunner(this.visibleIf);
this.conditionRunner.expression = this.visibleIf;
this.visible = this.conditionRunner.run(values);
}
//IQuestion
onSurveyValueChanged(newValue: any) {
}
setVisibleIndex(value: number) {
Expand All @@ -76,6 +84,6 @@ module Survey {
this.fireCallback(this.visibleIndexChangedCallback);
}
}
JsonObject.metaData.addClass("questionbase", ["!name", { name: "visible:boolean", default: true },
JsonObject.metaData.addClass("questionbase", ["!name", { name: "visible:boolean", default: true }, "visibleIf",
{ name: "width" }, { name: "startWithNewLine:boolean", default: true}, {name: "indent:number", default: 0, choices: [0, 1, 2, 3]}]);
}
12 changes: 12 additions & 0 deletions src/survey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ module Survey {
}
}
this.notifyAllQuestionsOnValueChanged();
this.runConditions();
}
public get comments(): any {
var result = {};
Expand Down Expand Up @@ -431,6 +432,15 @@ module Survey {
}
}
}
private runConditions() {
this.runConditionsForList(this.getAllQuestions(false));
this.runConditionsForList(this.pages);
}
private runConditionsForList(list: Array<IConditionRunner>) {
for (var i = 0; i < list.length; i++) {
list[i].runCondition(this.valuesHash);
}
}
public sendResult(postId: string = null, clientId: string = null, isPartialCompleted: boolean = false) {
if (!postId && this.surveyPostId) {
postId = this.surveyPostId;
Expand Down Expand Up @@ -506,6 +516,7 @@ module Survey {
if (this.hasCookie) {
this.doComplete();
}
this.runConditions();
this.updateVisibleIndexes();
}
protected onBeforeCreating() { }
Expand Down Expand Up @@ -579,6 +590,7 @@ module Survey {
}
this.notifyQuestionOnValueChanged(name, newValue);
this.checkTriggers(name, newValue, false);
this.runConditions();
this.tryGoNextPageAutomatic();
}
private isValueEqual(name: string, newValue: any): boolean {
Expand Down
6 changes: 6 additions & 0 deletions tests/conditionstests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ module Survey.Tests {
op.left = 5; assert.equal(op.perform(), false, "lessorequal: 4 <= 5");
op.left = 4; assert.equal(op.perform(), true, "less: 4 <= 4");
});
QUnit.test("Condition with quotes", function (assert) {
var op = new Condition();
op.left = "yes";
op.right = "'yes'";
assert.equal(op.perform(), true, "equal: yes == 'yes'");
});
function checkItemCondition(op: string, expectedOp: string): boolean {
var parser = new ConditionsParser();
var node = new ConditionNode();
Expand Down
28 changes: 28 additions & 0 deletions tests/surveytests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,34 @@ module Survey.Tests {
dropDownQ.comment = "other value";
assert.equal(survey.state, "completed", "complete the survey");
});
QUnit.test("simple condition test", function (assert) {
var survey = new SurveyModel({
pages: [{ name: "page1",
questions: [
{ type: "checkbox", name: "q1", choices: ["yes", "no"] },
{ type: "checkbox", name: "q2", choices: ["yes", "no"] }]
}, { name : "page2", visibleIf: "q1 = 'yes' or 'q2' = 'no'",
questions: [
{ type: "text", name: "q3", visibleIf: "q1 = 'yes' and 'q2' = 'no'", },
{ type: "text", name: "q4" }]
}
]
});
var q3 = survey.getQuestionByName("q3");
assert.equal(survey.pages[1].visible, false, "initially the page becomes invisible");
assert.equal(q3.visible, false, "initially q3 becomes invisible");
survey.setValue("q1", "yes");
survey.setValue("q2", "no");
assert.equal(survey.pages[1].visible, true, "the page becomes visible, q1 = 'yes'");
assert.equal(q3.visible, true, "q3 becomes visible, q1 = 'yes' and q2 = 'no'");
survey.setValue("q2", "yes");
assert.equal(survey.pages[1].visible, true, "the page becomes visible, q1 = 'yes'");
assert.equal(q3.visible, false, "q3 becomes invisible, q1 = 'yes' and q2 = 'yes'");
survey.setValue("q1", "no");
assert.equal(survey.pages[1].visible, false, "the page becomes invisible, q1 = 'no'");
assert.equal(q3.visible, false, "q3becomes invisible, q1 = 'no' and q2 = 'yes'");
});

QUnit.test("multiple triger on checkbox stop working.", function (assert) {
var survey = new SurveyModel({
pages: [{
Expand Down

0 comments on commit cbd51e2

Please sign in to comment.