compose-form-up
Advanced tools
Comparing version 2.0.2 to 2.0.3
@@ -5,2 +5,3 @@ var toolbox = require( 'compose-toolbox' ), | ||
helpers = require( './helpers' ), | ||
stepIndex = require( '../step-index' ), | ||
Event = toolbox.event, | ||
@@ -29,7 +30,7 @@ sliders = [], | ||
// Don't update hidden sliders | ||
if (slider.offsetParent === null) { return } | ||
setInput( slider ) | ||
setLabels( slider ) | ||
setFill( slider ) | ||
if ( slider.offsetParent !== null ) { | ||
setInput( slider ) | ||
setLabels( slider ) | ||
setFill( slider ) | ||
} | ||
} | ||
@@ -47,3 +48,3 @@ | ||
var value = data.values[ sliderIndex( slider ) ] | ||
var value = data.values[ slider.value ] | ||
var input = helpers.getInput( slider ) | ||
@@ -59,5 +60,6 @@ | ||
var data = getData( slider ) | ||
var segments = document.querySelectorAll('#'+slider.id+' .slider-segment') | ||
var fills = document.querySelectorAll('#'+slider.id+' .slider-fill') | ||
var index = sliderIndex( slider ) | ||
var wrapper = '#slider-input-'+slider.dataset.sliderId+'-wrapper' | ||
var segments = document.querySelectorAll( wrapper + ' .slider-segment') | ||
var fills = document.querySelectorAll( wrapper + ' .slider-fill') | ||
var index = stepIndex( slider ) | ||
@@ -84,28 +86,23 @@ toolbox.each( fills, function( fill, elIndex ){ | ||
var data = getData(slider) | ||
var index = sliderIndex(slider) | ||
// If hidden slider or no labels set, don't update | ||
if (slider.offsetParent === null || !data.labels) { return } | ||
if ( data.labels ) { | ||
for ( var key in data.labels ) { | ||
var labelEls = document.querySelectorAll('#'+slider.id+' [data-slider-label='+key+'] .label-content') | ||
var labels = labelAtIndex( data.labels, index ) | ||
for ( var key in data.labels ) { | ||
var labelEls = document.querySelectorAll('#slider-input-'+slider.dataset.sliderId+'-wrapper [data-slider-label='+key+'] .label-content') | ||
var labels = labelAtIndex( data.labels, slider.value ) | ||
toolbox.each( labelEls, function( el ) { | ||
el.innerHTML = labels[key] | ||
el.parentElement.classList.toggle('empty-label', labels[key] === '') | ||
}) | ||
toolbox.each( labelEls, function( el ) { | ||
el.innerHTML = labels[key] | ||
el.parentElement.classList.toggle('empty-label', labels[key] === '') | ||
}) | ||
} | ||
} | ||
} | ||
// Normalize the slider value by the minimum value | ||
// If the min is not zero, the index needs to be shifted accordingly | ||
function sliderIndex( slider ){ | ||
return Number( slider.value ) - Number( slider.getAttribute('min') ) | ||
} | ||
function labelAtIndex( labels, index ) { | ||
// Find labels which have an entry for slider value | ||
function labelAtIndex( labels, value ) { | ||
var set = {} | ||
for (var key in labels) { | ||
set[key] = labels[key][index] | ||
set[key] = labels[key][value] | ||
} | ||
@@ -118,15 +115,18 @@ return set | ||
// Assign an incremental ID to track this slider with its data | ||
id: sliders.length, | ||
min: Number(slider.getAttribute('min')) || 0, | ||
max: Number(slider.getAttribute('max')) || 100 | ||
id: sliders.length, | ||
min: Number( slider.min ) || 0, | ||
max: Number( slider.max ) || 100, | ||
step: Number( slider.step ) || 1 | ||
} | ||
// Set dataset.sliderId for easy cache lookups later | ||
// Using setattribute because it forces a change to the element's tag | ||
slider.setAttribute('data-slider-id', data.id) | ||
// Get all attributes which start with `data-` | ||
data = toolbox.merge( data, extractData(slider, 'data-') ) | ||
data.values = helpers.getValues( data.min, data.max, data.values ) | ||
data.segments = data.values.length | ||
data.max = (data.min + data.values.length) - 1 | ||
data.values = helpers.getValues( data.min, data.max, data.values, data.step ) | ||
data.segments = objectSize(data.values) | ||
data.max = data.min + ((data.segments - 1) * data.step) | ||
@@ -138,4 +138,3 @@ if ( data.mark ) data.mark = helpers.split(data.mark).map(Number) | ||
// Get labels (or create them if none exist) | ||
// | ||
data.labels = helpers.getLabels( extractData( slider, 'data-label' ) ) | ||
data.labels = getLabels( slider, data ) | ||
if ( objectSize( data.labels ) == 0) data.labels.default = data.values | ||
@@ -148,18 +147,14 @@ | ||
// Set data-input name based on slider name (if unset) | ||
// Remove name so that form submission doesn't include values for slider | ||
// data-input will be used to create a hidden input which will contain | ||
// slider's custom values | ||
data.input = data.input || slider.getAttribute( 'name' ) | ||
data.inputClass = data.input.replace(/\W/g,'-')+'-'+data.id | ||
data.input = data.input || slider.name | ||
slider.dataset.input = data.input | ||
// Remove name so that form submission doesn't include values for slider | ||
slider.removeAttribute('name') | ||
// Find input and add class for queries later when updating value | ||
// Is there already an input in the DOM? | ||
var input = helpers.getInput( slider ) | ||
// If so set flag so template will not create a hidden input | ||
if ( input ) data.inputExists = true | ||
if ( input ) { | ||
input.classList.add( data.inputClass ) | ||
data.inputExists = true | ||
} | ||
sliders.push(data) | ||
@@ -169,6 +164,21 @@ return data | ||
function getLabels( slider, data ) { | ||
// Returns an object all `data-label*` attributes | ||
var labels = extractData( slider, 'data-label' ) | ||
// Since extraction starts after `data-label`, | ||
// `data-label='foo'` will be keyed by '' e.g. object['']='foo' | ||
// This corrects that oddity such that `object['default']='foo'` | ||
if (labels['']) { | ||
labels['default'] = labels[''] | ||
delete labels[''] | ||
} | ||
return helpers.getLabels( labels, data ) | ||
} | ||
module.exports = { | ||
cache: cache, | ||
watch: watch, | ||
change: change | ||
change: change, | ||
getData: getData | ||
} |
@@ -1,51 +0,59 @@ | ||
function getValues( min, max, values ) { | ||
function getValues( min, max, values, step ) { | ||
var result = {} | ||
step = step || 1 | ||
// If slider has data-value attribute | ||
if (values) values = split(values) | ||
// If slider has data-value attribute split into an array | ||
values = values ? split( values ) : [] | ||
// Add values between min and max, eg: 1,2,3,4,5… | ||
else { | ||
var values = [] | ||
for (var i = min; i <= max; i++ ) { values.push(i) } | ||
for ( var value = min; value <= max; value+=step ) { | ||
result[value] = values.shift() || value | ||
} | ||
return values | ||
return result | ||
} | ||
// Returns: | ||
// Takes label data and cunstructs hashes keyed by slider value. | ||
// | ||
// Input: | ||
// data-label='honey, bread, butter' | ||
// | ||
// as | ||
// Returns as: | ||
// data.labels['default] = ['honey', 'bread', 'butter'] | ||
// | ||
// Returns: | ||
// Input: | ||
// data-label-bread='rye,wheat,white' | ||
// data-label-spread='jelly,jam,butter,honey' | ||
// | ||
// as | ||
// data.labels['bread'] = ['rye','wheat','white'] | ||
// data.labels['spread'] = ['jelly','jam','butter','honey'] | ||
// Returns as: | ||
// data.labels['bread'] = { 0: 'rye', 1: 'wheat', 2: 'white' } | ||
// data.labels['spread'] = { 0: 'jelly'l, 1: 'jam', 2: 'butter', 3: 'honey' } | ||
// | ||
function getLabels( data ) { | ||
function getLabels( labelData, data ) { | ||
var labels = {} | ||
// If labels have been turned off (data-label=false|none), return false | ||
if ( labelData.default && labelData.default.trim().match(/^false$|^none$/) ) return false | ||
// Unless labels have been disabed with data-label='false' | ||
for (var key in data) { | ||
for ( var key in labelData ) { | ||
// Ignore non-native methods injected by some wayward lib | ||
if (!data.hasOwnProperty(key)) { continue } | ||
// Match properties: label, label-bread, external-label-id | ||
// Some labels may include commas, allow semicolons as an alternate separator | ||
// | ||
var splitLabels = split(data[key]) | ||
if ( !labelData.hasOwnProperty(key) ) { continue } | ||
// data-label | ||
if (key == '') { | ||
labels.default = ( splitLabels.join('').match(/^false$|^none$/) ? false : splitLabels ) | ||
} else { | ||
labels[key] = splitLabels | ||
// Split labels into an array. | ||
var splitLabels = split( labelData[key] ) | ||
// Construct a labels object keyed by slider values | ||
var valueLabels = {} | ||
// Walk up the slider values by step size from min to max | ||
for ( var value = data.min; value <= data.max; value+=data.step ) { | ||
valueLabels[value] = splitLabels.shift() | ||
} | ||
// Assign the new object to a label key e.g. labels['bread'] | ||
labels[key] = valueLabels | ||
} | ||
if ( labels.default === false ) labels = false | ||
return labels | ||
@@ -62,3 +70,3 @@ } | ||
// | ||
labels = [] | ||
labels = {} | ||
if ( lineLabels ) { | ||
@@ -65,0 +73,0 @@ split(lineLabels).map( function( lines, index ){ |
@@ -27,2 +27,3 @@ var toolbox = require( 'compose-toolbox' ), | ||
slider.setAttribute( 'max', data.max ) | ||
slider.setAttribute( 'step', data.step ) | ||
@@ -33,3 +34,3 @@ // Don't let the browser select a default value | ||
if(!slider.getAttribute('id')) slider.setAttribute( 'id', 'slider'+data.id ) | ||
if(!slider.getAttribute('id')) slider.setAttribute( 'id', 'slider-input-'+data.id ) | ||
// Insert the template right before the slider | ||
@@ -48,3 +49,4 @@ slider.insertAdjacentHTML( 'beforebegin', template.html( data, slider.outerHTML ) ) | ||
module.exports = { | ||
setup: setup | ||
setup: setup, | ||
getData: events.getData | ||
} |
@@ -0,3 +1,5 @@ | ||
var objectSize = require('../object-size') | ||
function html( data, sliderHTML ) { | ||
var html = '<div class="' + getClasses( data ) + '" id="slider' + data.id + '">' | ||
var html = '<div class="' + getClasses( data ) + '" id="slider-input-' + data.id + '-wrapper">' | ||
html += "<div class='slider-input-container'>" + sliderHTML + getTrack( data ) + "</div>" | ||
@@ -12,3 +14,3 @@ html += addLabels( data ) | ||
var classes = ['slider-container'] | ||
if (data.lineLabels.length > 0) classes.push('line-labels') | ||
if (objectSize(data.lineLabels) > 0) classes.push('line-labels') | ||
classes.push((data.labels) ? 'with-label' : 'without-label') | ||
@@ -25,6 +27,5 @@ return classes.join(' ') | ||
for(var index = 1; index <= data.segments; index++) { | ||
track += "<div class='slider-segment'><span class='slider-segment-content'>" | ||
track += addMark( data.mark, index ) | ||
track += addLineLabel( data.lineLabels, index ) | ||
track += addLineLabel( data.lineLabels[index] ) | ||
track += "</span></div>" | ||
@@ -46,5 +47,5 @@ } | ||
function addLineLabel( lineLabels, index ) { | ||
if (lineLabels && lineLabels[index]) | ||
return "<span class='slider-line-label'>"+lineLabels[index]+"</span>" | ||
function addLineLabel( label ) { | ||
if (label) | ||
return "<span class='slider-line-label'>"+label+"</span>" | ||
else | ||
@@ -51,0 +52,0 @@ return "" |
@@ -1,6 +0,7 @@ | ||
var toolbox = require( 'compose-toolbox' ), | ||
var toolbox = require( 'compose-toolbox' ), | ||
extractData = require( './extract-data' ), | ||
objectSize = require( './object-size' ), | ||
Event = toolbox.event, | ||
watching = false | ||
stepIndex = require( './step-index' ), | ||
objectSize = require( './object-size' ), | ||
Event = toolbox.event, | ||
watching = false | ||
@@ -34,3 +35,3 @@ | ||
function getLabels (el) { | ||
var index = getIndex( el ) | ||
var index = stepIndex( el ) | ||
@@ -57,18 +58,2 @@ if (typeof index == undefined) return {} // Element is out of bounds of input | ||
function getIndex (el) { | ||
var min = Number(el.getAttribute('min') || 0), | ||
max = Number(el.getAttribute('max') || 100), | ||
step = Number(el.getAttribute('step')) | ||
value = Number(el.value) | ||
if ( !step ) step = 1 | ||
// Element is out of bounds of input | ||
if (value % step != 0) return | ||
// The nubmer of units is the number of steps between min and max | ||
var units = ( max - min ) / step | ||
// Return the current step number | ||
return ( value / step ) - ( min / step ) | ||
} | ||
function labelHTML (label) { | ||
@@ -75,0 +60,0 @@ return "<span class='label-content'>" + label + "</span>" |
{ | ||
"name": "compose-form-up", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"description": "A lightweight HTML5 form utility including validation, progressive forms, and other handy tools.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -134,5 +134,5 @@ var u = require('./_utils.js') | ||
await u.matchText( '[data-diff-name*=range-input] .input-diff-label', 'Rate our service' ) | ||
await u.matchText( '[data-diff-name*=range-input] .input-diff-initial', 'good' ) | ||
await u.matchText( '[data-diff-name*=range-input] .input-diff-value', 'great' ) | ||
await u.matchText( '[data-diff-name*=range-input] td.input-diff-label', 'Rate our service' ) | ||
await u.matchText( '[data-diff-name*=range-input] td.input-diff-initial', 'good' ) | ||
await u.matchText( '[data-diff-name*=range-input] td.input-diff-value', 'great' ) | ||
}) | ||
@@ -139,0 +139,0 @@ |
@@ -150,3 +150,3 @@ var u = require('./_utils.js') | ||
it('updates external labels with slider-state tracking', async () => { | ||
it('updates before and after labels', async () => { | ||
@@ -164,2 +164,16 @@ // Make sure the default label is never displayed when multiple labels are present | ||
}) | ||
it('supports step values', async () => { | ||
await u.findElement('#slider-10 input[max="100"]') | ||
await u.countIs('#slider-10 .slider-segment-mark', 3) | ||
await u.countIs('#slider-10 .slider-fill', 10) | ||
await u.setValue('#slider-10 input', '20') | ||
await u.matchText('#slider-10 .slider-label', '20') | ||
await u.countIs('#slider-10 .slider-fills .filled', 2) | ||
await u.setValue('#slider-10 input', '100') | ||
await u.matchText('#slider-10 .slider-label', '100') | ||
await u.countIs('#slider-10 .slider-fills .filled', 10) | ||
}) | ||
}) |
@@ -12,22 +12,23 @@ var u = require('./_utils.js') | ||
it('sets values', async () => { | ||
expect( helpers.getValues(0,10) ).toMatchObject( [0,1,2,3,4,5,6,7,8,9,10] ) | ||
expect( helpers.getValues(null,null,'a,b,c,d,e,f,g,h,j,k,l,m,n,o') ).toMatchObject( ['a','b','c','d','e','f','g','h','j','k','l','m','n','o'] ) | ||
expect( helpers.getValues(0,10) ).toMatchObject( {"0": 0, "1": 1, "10": 10, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9} ) | ||
expect( helpers.getValues(0,10,null,2) ).toMatchObject( {"0": 0, "10": 10, "2": 2, "4": 4, "6": 6, "8": 8} ) | ||
expect( helpers.getValues(0,100,'a,b,c,d,e') ).toMatchObject( {"0": "a", "1": "b", "2": "c", "3": "d", "4": "e"} ) | ||
}) | ||
it('gets labels', async () => { | ||
expect( helpers.getLabels( { test: 'a, b, c' } )).toMatchObject( { test: ['a', 'b', 'c'] } ) | ||
expect( helpers.getLabels( {'': 'a,b,c'} )).toMatchObject( { default: ['a','b','c'] } ) | ||
expect( helpers.getLabels( {'': 'none'} )).toBe( false ) | ||
expect( helpers.getLabels( { test: 'a, b, c' }, { min: 0, max: 2, step: 1 } )).toMatchObject( { test: {"0": "a", "1": "b", "2": "c"}} ) | ||
expect( helpers.getLabels( { default: 'a,b,c'}, { min: 0, max: 2, step: 1} )).toMatchObject( { default: {"0": "a", "1": "b", "2": "c"} } ) | ||
expect( helpers.getLabels( { default: 'none'}, { min: 0, max: 2, step: 1 } )).toBe( false ) | ||
}) | ||
it('gets line labels', async () => { | ||
expect( helpers.getLineLabels( '1:hi;2:yo;howdy' ) ).toMatchObject( [undefined, 'hi','yo','howdy'] ) | ||
expect( helpers.getLineLabels( 'hi,yo,howdy' ) ).toMatchObject( [undefined, 'hi','yo','howdy'] ) | ||
expect( helpers.getLineLabels( 'hi,yo,5:howdy' ) ).toMatchObject( [undefined, 'hi','yo', undefined, undefined,'howdy'] ) | ||
expect( helpers.getLineLabels( '1:hi;2:yo;howdy' ) ).toMatchObject( {"1": "hi", "2": "yo", "3": "howdy"} ) | ||
expect( helpers.getLineLabels( 'hi,yo,howdy' ) ).toMatchObject( {"1": "hi", "2": "yo", "3": "howdy"} ) | ||
expect( helpers.getLineLabels( 'hi,yo,5:howdy' ) ).toMatchObject( {"1": "hi", "2": "yo", "5": "howdy"} ) | ||
}) | ||
it('gets label html', async () => { | ||
expect( template.labelHTML({ labels: { default: [1,2,3] }}, 'default') ).toBe("<span class='label-content'></span>") | ||
var labels = { labels: { default: [1,2,3] }, min: 1, max: 3, step: 1} | ||
expect( template.labelHTML(labels, 'default') ).toBe("<span class='label-content'></span>") | ||
var labels = { labels: { default: [1,2,3] }} | ||
labels['before-label'] = "$" | ||
@@ -58,4 +59,4 @@ labels['after-label'] = "/month" | ||
// Because they are added to the array starting at index 1 | ||
expect( template.addLineLabel([undefined, 1,2,3, undefined, undefined,5], 1) ).toMatch("<span class='slider-line-label'>1</span>") | ||
expect( template.addLineLabel([undefined, 1,2,3, undefined, undefined,5], 4) ).toBe("") | ||
expect( template.addLineLabel('test') ).toMatch("<span class='slider-line-label'>test</span>") | ||
expect( template.addLineLabel('') ).toBe("") | ||
}) | ||
@@ -62,0 +63,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
308056
44
2170