From e206d509db58dc6944b72eb224e7ace9f6411c81 Mon Sep 17 00:00:00 2001 From: Ben Boyle Date: Tue, 24 Feb 2015 14:28:45 +1000 Subject: [PATCH 1/3] simplify regexp for extracting values from hints --- src/relevance.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/relevance.js b/src/relevance.js index 7b059c4..093d340 100644 --- a/src/relevance.js +++ b/src/relevance.js @@ -215,7 +215,7 @@ if ( jQuery !== 'undefined' ) { this.find( options.instructionSelector ).each(function() { var $this = $( this ), - value = $this.text().replace( /^[\S\s]*chose \W([^'"’]+)['"’] above[\S\s]*$/, '$1' ), + value = $this.text(), question = $this.closest( options.questionSelector ), toggle = question.prevAll( options.questionSelector ), i, answers, @@ -229,6 +229,7 @@ if ( jQuery !== 'undefined' ) { value = toggle.find( ':checkbox' ).val(); negate = true; } else { + value = value.replace( /^.*chose\s+\S([^'"’]+)\S\s+above.*$/, '$1' ); // which of the previous questions is the toggle? i = 0; while ( i < toggle.length ) { From d595b68fbfa8ae5c1068faf0d0ad5991db653982 Mon Sep 17 00:00:00 2001 From: Ben Boyle Date: Tue, 24 Feb 2015 15:55:48 +1000 Subject: [PATCH 2/3] prevent questions from being hidden forever detects that instructions can be satisfied before hiding a question. i.e. a select control with the appropriate value to make a question relevant must exist. --- src/relevance.js | 12 ++++++++---- test/instructions.html | 30 +++++++++++++++++++++++++++++- test/instructions.js | 28 +++++++++++++++++----------- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/relevance.js b/src/relevance.js index 093d340..b12e11a 100644 --- a/src/relevance.js +++ b/src/relevance.js @@ -219,12 +219,14 @@ if ( jQuery !== 'undefined' ) { question = $this.closest( options.questionSelector ), toggle = question.prevAll( options.questionSelector ), i, answers, + match = false, negate = false ; // pattern: (If different to ) if ( /If different to/.test( value )) { // assume previous 'li' is the toggle + match = true; toggle = toggle.eq( 0 ); value = toggle.find( ':checkbox' ).val(); negate = true; @@ -238,15 +240,17 @@ if ( jQuery !== 'undefined' ) { // does this item have the answer we need? answers = $.map( toggle.eq( i ).find( 'option,:radio,:checkbox' ), valueMap ); if ( valueInArray( value, answers )) { - toggle = toggle.eq( i ); + match = true; + toggle = toggle.eq( i ); // toggle.length becomes 1, loop will exit } } i++; } } - toggle = toggle.add( toggle.find( 'select,input' )).filter( 'select,:radio,:checkbox' ); - - question.relevance( 'relevantWhen', { name: toggle.attr( 'name' ), value: value, negate: negate }); + if ( match ) { + toggle = toggle.add( toggle.find( 'select,input' )).filter( 'select,:radio,:checkbox' ); + question.relevance( 'relevantWhen', { name: toggle.attr( 'name' ), value: value, negate: negate }); + } }); return this; diff --git a/test/instructions.html b/test/instructions.html index dad0853..22e9cee 100644 --- a/test/instructions.html +++ b/test/instructions.html @@ -26,7 +26,7 @@ } .relevance { - color: red; + color: fuchsia; font-weight: bold; } @@ -421,6 +421,17 @@ + +
  • + + +
  • + + +
  • +
    + + Before gates + +
      +
    • + + +
    • +
    • + + +
    • +
    +
    +
  • diff --git a/test/instructions.js b/test/instructions.js index 3621a2d..277aaba 100644 --- a/test/instructions.js +++ b/test/instructions.js @@ -1,6 +1,6 @@ (function( $ ) { 'use strict'; - + var relevanceLifecycle = { setup: function() { @@ -28,10 +28,10 @@ module( 'environment' ); - test( 'test fields are in test form', 18, function() { + test( 'test fields are in test form', 20, function() { strictEqual( $( 'form#test' ).length, 1, 'form#test exists' ); - strictEqual( $( '.relevance', '#test' ).length, 14, '14 `.relevance` instructions found' ); + strictEqual( $( '.relevance', '#test' ).length, 15, '`.relevance` instructions found' ); strictEqual( $( '.relevance', '#test' ).eq( 0 ).text(), '(If different to home address)', 'correct instruction text' ); strictEqual( $( '.relevance', '#test' ).eq( 1 ).text(), '(If you chose ‘Current working visa’ above)', 'correct instruction text' ); strictEqual( $( '.relevance', '#test' ).eq( 2 ).text(), '(If you chose ‘Yes’ above)', 'correct instruction text' ); @@ -42,16 +42,20 @@ strictEqual( $( '.relevance', '#test' ).eq( 7 ).text(), '(If you chose ‘Bird’ above)', 'correct instruction text' ); strictEqual( $( '.relevance', '#test' ).eq( 8 ).text(), '(If you chose ‘Bar’ above)', 'correct instruction text' ); strictEqual( $( '.relevance', '#test' ).eq( 9 ).text(), '(If you chose ‘Baz’ above)', 'correct instruction text' ); - strictEqual( $( '.relevance', '#test' ).eq( 10 ).text(), '(If you chose \'$1000.00\' above)', 'correct instruction text' ); - strictEqual( $( '.relevance', '#test' ).eq( 11 ).text(), '(If you chose \'other amount\' above)', 'correct instruction text' ); - strictEqual( $( '.relevance', '#test' ).eq( 12 ).text(), '(If you chose \'A\' above)', 'correct instruction text' ); + strictEqual( $( '.relevance', '#test' ).eq( 10 ).text(), '(If you chose ‘Quux’ above)', 'correct instruction text' ); + strictEqual( $( '.relevance', '#test' ).eq( 11 ).text(), '(If you chose \'$1000.00\' above)', 'correct instruction text' ); + strictEqual( $( '.relevance', '#test' ).eq( 12 ).text(), '(If you chose \'other amount\' above)', 'correct instruction text' ); strictEqual( $( '.relevance', '#test' ).eq( 13 ).text(), '(If you chose \'A\' above)', 'correct instruction text' ); + strictEqual( $( '.relevance', '#test' ).eq( 14 ).text(), '(If you chose \'A\' above)', 'correct instruction text' ); // dependence strictEqual( $( '#foo' ).val(), 'Foo', '#foo != Bar' ); // baz would be relevant, if bar was relevant strictEqual( $( '#bar' ).val(), 'Baz', '#bar == Baz' ); + // there is no match for quux + strictEqual( $( 'input[value="Quux"]' ).length, 0, 'no elements match input[value="Quux"]' ); + }); test( 'test fields are in custom form', 8, function() { @@ -71,7 +75,7 @@ module( 'before .relevance( \'instructions\' )' ); test( 'all sections are relevant', 1, function() { - strictEqual( $( '.relevance', '#test' ).filter( ':visible' ).length, 14, '12 `.relevance` instructions visible' ); + strictEqual( $( '.relevance', '#test' ).filter( ':visible' ).length, 15, '`.relevance` instructions visible' ); }); test( 'custom sections are relevant', 1, function() { @@ -81,8 +85,10 @@ module( 'after .relevance( \'instructions\' )', relevanceLifecycle ); - test( 'initial irrelevant elements are hidden', 1, function() { - strictEqual( $( '.relevance', '#test' ).filter( ':visible' ).length, 0, 'no `.relevance` instructions visible' ); + test( 'initial irrelevant elements are hidden', 2, function() { + strictEqual( $( '.relevance', '#test' ).filter( ':visible' ).length, 1, 'no `.relevance` instructions visible' ); + // quux should be visibile (not orphaned) + strictEqual( $( '.relevance', '#test' ).filter( ':visible' ).text(), '(If you chose ‘Quux’ above)', 'Orphaned question remains visible' ); }); test( 'custom sections are ignored', 1, function() { @@ -90,13 +96,13 @@ }); test( 'initial relevant elements are shown', 10, function() { - + // test radio buttons strictEqual( $( '#job-title' ).filter( ':hidden' ).length, 1, '#job-title is hidden' ); strictEqual( $( '#job-title' ).closest( '.section' ).filter( ':hidden' ).length, 1, '#job-title section is hidden' ); strictEqual( $( '#retirement-date' ).filter( ':hidden' ).length, 1, '#retirement-date is hidden' ); strictEqual( $( '#retirement-date' ).closest( '.questions > li' ).filter( ':hidden' ).length, 1, '#retirement-date question is hidden' ); - + // test select strictEqual( $( '#permit-expiry-date' ).filter( ':hidden' ).length, 1, '#permit-expiry-date is hidden' ); strictEqual( $( '#permit-expiry-date' ).closest( '.questions > li' ).filter( ':hidden' ).length, 1, '#permit-expiry-date question is hidden' ); From 9c18bae0fa87c7e5f8269b4ec319c7d5017f2b9e Mon Sep 17 00:00:00 2001 From: Ben Boyle Date: Tue, 24 Feb 2015 16:01:20 +1000 Subject: [PATCH 3/3] bump version --- dist/relevance.js | 17 +++++++++++------ dist/relevance.min.js | 4 ++-- package.json | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/dist/relevance.js b/dist/relevance.js index db8e567..44aedb6 100644 --- a/dist/relevance.js +++ b/dist/relevance.js @@ -1,4 +1,4 @@ -/*! relevance - v1.1.4 - 2015-02-19 +/*! relevance - v1.6.0-beta.1 - 2015-02-24 * https://github.com/bboyle/relevance * Copyright (c) 2015 Ben Boyle; Licensed MIT */ if ( jQuery !== 'undefined' ) { @@ -217,20 +217,23 @@ if ( jQuery !== 'undefined' ) { this.find( options.instructionSelector ).each(function() { var $this = $( this ), - value = $this.text().replace( /^[\S\s]*chose \W([^'"’]+)['"’] above[\S\s]*$/, '$1' ), + value = $this.text(), question = $this.closest( options.questionSelector ), toggle = question.prevAll( options.questionSelector ), i, answers, + match = false, negate = false ; // pattern: (If different to ) if ( /If different to/.test( value )) { // assume previous 'li' is the toggle + match = true; toggle = toggle.eq( 0 ); value = toggle.find( ':checkbox' ).val(); negate = true; } else { + value = value.replace( /^.*chose\s+\S([^'"’]+)\S\s+above.*$/, '$1' ); // which of the previous questions is the toggle? i = 0; while ( i < toggle.length ) { @@ -239,15 +242,17 @@ if ( jQuery !== 'undefined' ) { // does this item have the answer we need? answers = $.map( toggle.eq( i ).find( 'option,:radio,:checkbox' ), valueMap ); if ( valueInArray( value, answers )) { - toggle = toggle.eq( i ); + match = true; + toggle = toggle.eq( i ); // toggle.length becomes 1, loop will exit } } i++; } } - toggle = toggle.add( toggle.find( 'select,input' )).filter( 'select,:radio,:checkbox' ); - - question.relevance( 'relevantWhen', { name: toggle.attr( 'name' ), value: value, negate: negate }); + if ( match ) { + toggle = toggle.add( toggle.find( 'select,input' )).filter( 'select,:radio,:checkbox' ); + question.relevance( 'relevantWhen', { name: toggle.attr( 'name' ), value: value, negate: negate }); + } }); return this; diff --git a/dist/relevance.min.js b/dist/relevance.min.js index 19eb5ed..085f088 100644 --- a/dist/relevance.min.js +++ b/dist/relevance.min.js @@ -1,4 +1,4 @@ -/*! relevance - v1.1.4 - 2015-02-19 +/*! relevance - v1.6.0-beta.1 - 2015-02-24 * https://github.com/bboyle/relevance * Copyright (c) 2015 Ben Boyle; Licensed MIT */ -"undefined"!==jQuery&&!function(a){"use strict";var b="relevant",c="irrelevant",d="relevant-done",e="irrelevant-done",f="button, input, select, textarea",g=function(b,c){return a(b.elements[c]).filter('[name="'+c+'"]')},h=function(a){return a.value},i=function(b,c){var d;for("object"!=typeof b&&(b=[b]),d=0;d li"},b),this.find(b.instructionSelector).each(function(){var c,d,e=a(this),f=e.text().replace(/^[\S\s]*chose \W([^'"’]+)['"’] above[\S\s]*$/,"$1"),g=e.closest(b.questionSelector),j=g.prevAll(b.questionSelector),k=!1;if(/If different to/.test(f))j=j.eq(0),f=j.find(":checkbox").val(),k=!0;else for(c=0;c li"},b),this.find(b.instructionSelector).each(function(){var c,d,e=a(this),f=e.text(),g=e.closest(b.questionSelector),j=g.prevAll(b.questionSelector),k=!1,l=!1;if(/If different to/.test(f))k=!0,j=j.eq(0),f=j.find(":checkbox").val(),l=!0;else for(f=f.replace(/^.*chose\s+\S([^'"’]+)\S\s+above.*$/,"$1"),c=0;c