@flourish/controls
Advanced tools
Comparing version 0.2.3 to 0.3.0
{ | ||
"name": "@flourish/controls", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "Switchable dropdown/buttons/slider control", | ||
@@ -13,3 +13,4 @@ "main": "controls.js", | ||
"prepare": "npm run build && npm run minify", | ||
"minify": "uglifyjs -m -o controls.min.js controls.js" | ||
"minify": "uglifyjs -m -o controls.min.js controls.js", | ||
"lint": "eslint src" | ||
}, | ||
@@ -28,3 +29,11 @@ "author": "Kiln Enterprises Ltd", | ||
"uglify-js": "^2.7.5" | ||
} | ||
}, | ||
"devDependencies": { | ||
"@flourish/eslint-plugin-flourish": "^0.7.2", | ||
"eslint": "git://github.com/robinhouston/eslint.git#bug-ignoredNodes", | ||
"pre-commit": "^1.2.2" | ||
}, | ||
"precommit": [ | ||
"lint" | ||
] | ||
} |
@@ -9,7 +9,6 @@ import { select } from "d3-selection"; | ||
var buttons, button_nodes; | ||
var setStyles = function() { | ||
}; | ||
var show = function() { | ||
@@ -19,9 +18,9 @@ setStyles(); | ||
button_container.style("width", null) | ||
.style("display", "inline-block") | ||
.classed("button-group", false); | ||
.style("display", "inline-block") | ||
.classed("button-group", false); | ||
} | ||
else { | ||
button_container.style("width", props.width) | ||
.style("display", "table") | ||
.classed("button-group", true); | ||
.style("display", "table") | ||
.classed("button-group", true); | ||
if (props.buttons_type === "auto") { | ||
@@ -31,3 +30,3 @@ var buttons_fit = button_nodes.every(function(el) { | ||
}); | ||
if(!buttons_fit){ | ||
if (!buttons_fit) { | ||
hide(); | ||
@@ -39,3 +38,3 @@ dropdown_obj.show(); | ||
}; | ||
var hide = function() { | ||
@@ -46,5 +45,5 @@ button_container.style("display", "none"); | ||
var setValue = function() { | ||
buttons && buttons.each(function(d,i) { select(this).classed("selected", i===props.index); }); | ||
} | ||
buttons && buttons.each(function(d, i) { select(this).classed("selected", i===props.index); }); | ||
}; | ||
var setOptions = function() { | ||
@@ -56,3 +55,3 @@ buttons = button_container.text("").selectAll(".button") | ||
.attr("class", "button") | ||
.classed("selected", function(d,i) { return i === props.index; } ) | ||
.classed("selected", function(d, i) { return i === props.index; }) | ||
.text(function(d) { return d; }) | ||
@@ -67,3 +66,3 @@ .attr("title", function(d) { return d; }) | ||
}; | ||
var buttons_obj = { handle: button_container }; | ||
@@ -74,7 +73,7 @@ buttons_obj.show = function() { show(); return buttons_obj; }; | ||
buttons_obj.setOptions = function() { setOptions(); return buttons_obj; }; | ||
return buttons_obj; | ||
}; | ||
} | ||
export { createButtons }; | ||
export { createButtons }; |
@@ -16,24 +16,24 @@ import { select } from "d3-selection"; | ||
var onChangeCallbacks = core.onChangeCallbacks; | ||
// Add dropdown elements to DOM | ||
// Add dropdown elements to DOM | ||
var dropdown = container.append("div").attr("class", "dropdown"); | ||
var dropdown_main = dropdown.append("div").attr("class", "main"); | ||
var dropdown_current = dropdown_main.append("span").attr("class", "current"); | ||
dropdown_main.append("span").attr("class", "symbol").style("background-image", createDropdownIcon("#333333")); | ||
var dropdown_symbol = dropdown_main.append("span").attr("class", "symbol"); | ||
var dropdown_list = dropdown.append("div").attr("class", "list"); | ||
var hideDropdownList = function(){ | ||
var hideDropdownList = function() { | ||
dropdown.classed("open", false); | ||
}; | ||
var toggleDropdownList = function(){ | ||
var toggleDropdownList = function() { | ||
dropdown.classed("open", !dropdown.classed("open")); | ||
} | ||
var dropdown_node = dropdown.node(); | ||
document.querySelector("body").addEventListener('click', function(event) { | ||
}; | ||
var dropdown_node = dropdown.node(); | ||
document.querySelector("body").addEventListener("click", function(event) { | ||
if (!dropdown.classed("open")) return; // If already closed, nothing to close | ||
var el = event.target; | ||
var parent = el.parentElement; | ||
while ( parent ) { | ||
while (parent) { | ||
if (el === dropdown_node) return; // We've clicked the dropdown, don't close it here | ||
@@ -43,17 +43,23 @@ el = parent; | ||
} | ||
hideDropdownList(); //Clicked somewhere else, hide the dropdown | ||
}, false); | ||
dropdown_main.on("click", function() { toggleDropdownList(); } ); | ||
var setStyles = function() { | ||
}; | ||
hideDropdownList(); // Clicked somewhere else, hide the dropdown | ||
}, false); | ||
dropdown_main.on("click", function() { toggleDropdownList(); }); | ||
var setStyles = (function() { | ||
var icon_colour; | ||
return function() { | ||
if (icon_colour !== props.dropdown_icon_colour) { | ||
icon_colour = props.dropdown_icon_colour; | ||
dropdown_symbol.style("background-image", createDropdownIcon(icon_colour)); | ||
} | ||
}; | ||
} )(); | ||
var show = function() { | ||
setStyles(); | ||
dropdown.style("width", props.width) | ||
.style("display", "inline-table"); | ||
.style("display", "inline-table"); | ||
}; | ||
var hide = function() { | ||
@@ -63,7 +69,7 @@ hideDropdownList(); | ||
}; | ||
var setValue = function() { | ||
dropdown_current.text(props.value).attr("title", props.value); | ||
} | ||
}; | ||
var setOptions = function() { | ||
@@ -84,3 +90,3 @@ dropdown_list.text("") | ||
}; | ||
var dropdown_obj = { handle: dropdown }; | ||
@@ -91,6 +97,6 @@ dropdown_obj.show = function() { show(); return dropdown_obj; }; | ||
dropdown_obj.setOptions = function() { setOptions(); return dropdown_obj; }; | ||
return dropdown_obj; | ||
} | ||
export { createDropdown }; | ||
export { createDropdown }; |
import Slider from "@flourish/slider"; | ||
import { select } from "d3-selection"; | ||
import { makeBackgroundString } from "../core/css.js"; | ||
@@ -24,5 +23,5 @@ | ||
var container_selector = core.container_selector; | ||
var play_string, pause_string; | ||
var slider_holder = container.append("div").attr("class", "slider-holder animatable"); | ||
@@ -33,10 +32,10 @@ var slider_play_button = slider_holder.append("div").attr("class", "slider-play"); | ||
var slider = Slider(container_selector + " .slider-holder .slider") | ||
.channelHeight(6) | ||
.snap(true) | ||
.on("change", function(index) { | ||
if (index === props.index) return; | ||
props.index = index; | ||
onChangeCallbacks(); | ||
}); | ||
.channelHeight(6) | ||
.snap(true) | ||
.on("change", function(index) { | ||
if (index === props.index) return; | ||
props.index = index; | ||
onChangeCallbacks(); | ||
}); | ||
var sliderplayer; | ||
@@ -53,3 +52,3 @@ | ||
var setSliderPlayerMove = function(next_index) { | ||
if (next_index === 0 && !props.loop_time) { | ||
if (next_index === 0 && !props.slider_loop) { | ||
stopSliderPlayer(); | ||
@@ -59,7 +58,7 @@ return; | ||
var next_time_step = 1000 * Math.abs(props.step_time) * (next_index ? 1 : props.loop_time); | ||
var next_time_step = 1000* (Math.abs(props.slider_step_time) + (next_index ? 0 : props.slider_loop_pause)); | ||
sliderplayer = setTimeout(function() { | ||
var n_options = props.options.length; | ||
var index = props.step_time>0 ? next_index : n_options-(1+next_index); | ||
var n_options = props.n_options; | ||
var index = props.slider_step_time>=0 ? next_index : n_options-(1+next_index); | ||
slider.value(index).update(); | ||
@@ -74,7 +73,7 @@ props.index = index; | ||
var startSliderPlayer = function() { | ||
var n_options = props.options.length; | ||
var n_options = props.n_options; | ||
if (n_options < 2) return; | ||
var final_index = n_options - 1; | ||
var index = slider.value(); | ||
var step_time = props.step_time; | ||
var index = props.index; | ||
var step_time = props.slider_step_time; | ||
slider_holder.classed("playing", true); | ||
@@ -100,5 +99,5 @@ slider_play_button.style("background-image", pause_string); | ||
if (slider_holder.classed("playing")) stopSliderPlayer(); | ||
else if (props.step_time) startSliderPlayer(); | ||
else if (props.slider_play_button) startSliderPlayer(); | ||
}); | ||
var setWidths = function() { | ||
@@ -116,3 +115,3 @@ slider_holder.style("width", props.width); | ||
}; | ||
var setHandles = (function() { | ||
@@ -123,3 +122,3 @@ var handle_col; | ||
slider_holder.classed("animatable", true); | ||
slider_play_button.style("transform", props.step_time < 0 ? "rotate(180deg)" : null); | ||
slider_play_button.style("transform", props.slider_step_time < 0 ? "rotate(180deg)" : null); | ||
} | ||
@@ -130,4 +129,4 @@ else { | ||
} | ||
if (handle_col !== props.slider_handle_colour){ | ||
slider.update(); //Make sure slider-handle actually exists before changing its colour | ||
if (handle_col !== props.slider_handle_colour) { | ||
slider.update(); // Make sure slider-handle actually exists before changing its colour | ||
handle_col = props.slider_handle_colour; | ||
@@ -137,7 +136,7 @@ slider_holder.select(".slider-handle").style("fill", handle_col); | ||
pause_string = createPauseButton(handle_col); | ||
slider_play_button.style("background-image", sliderplayer ? pause_string : play_string); | ||
slider_play_button.style("background-image", sliderplayer ? pause_string : play_string); | ||
} | ||
} | ||
}; | ||
})(); | ||
var setLabel = function() { | ||
@@ -150,3 +149,3 @@ var label; | ||
}; | ||
var setStyles = function() { | ||
@@ -157,9 +156,9 @@ setWidths(); | ||
}; | ||
var show = function() { | ||
slider_holder.style("display", "inline-block"); | ||
setStyles(); | ||
slider_holder.style("display", "inline-block"); | ||
slider.update(); | ||
}; | ||
var hide = function() { | ||
@@ -169,12 +168,12 @@ stopSliderPlayer(); | ||
}; | ||
var setValue = function() { | ||
slider.value(props.index); | ||
} | ||
}; | ||
var setOptions = function() { | ||
slider.domain([0, props.options.length - 1]).update(); | ||
slider.domain([0, props.n_options - 1]).update(); | ||
}; | ||
var slider_obj = { handle: slider_holder }; | ||
@@ -185,7 +184,7 @@ slider_obj.show = function() { show(); return slider_obj; }; | ||
slider_obj.setOptions = function() { setOptions(); return slider_obj; }; | ||
return slider_obj; | ||
}; | ||
return slider_obj; | ||
} | ||
export { createSlider } | ||
export { createSlider }; |
import { select } from "d3-selection"; | ||
import { injectCSS, css_string } from "./css.js"; | ||
@@ -6,10 +7,14 @@ var control_types = Object.freeze(["auto-buttons", "grouped-buttons", "floating-buttons", "dropdown", "slider", "none"]); | ||
function createCore(container_selector) { | ||
injectCSS(css_string); | ||
var output_obj = {}; | ||
var props = { | ||
"step_time": 2, | ||
"loop_time": 1.5, | ||
"slider_step_time": 2, | ||
"slider_loop": true, | ||
"slider_loop_pause": 0, | ||
"slider_play_button": true, | ||
"slider_handle_colour": "#333", | ||
"slider_play_button": true, | ||
"slider_label": true | ||
"slider_label": true, | ||
dropdown_icon_colour: "#333333" | ||
}; | ||
@@ -20,3 +25,3 @@ | ||
var methodName = key.replace(/_\w/g, function(substr) { return substr.charAt(1).toUpperCase(); }); | ||
output_obj[methodName] = function(val){ | ||
output_obj[methodName] = function(val) { | ||
if (val === undefined) return props[key]; | ||
@@ -26,3 +31,3 @@ props[key] = val; | ||
}; | ||
} ); | ||
}); | ||
@@ -36,3 +41,3 @@ props.type = "auto_buttons"; | ||
}; | ||
Object.defineProperty(props, "control", { | ||
@@ -44,4 +49,4 @@ get: function() { | ||
set: function() { console.warn("Nothing changed: control is read only"); } | ||
} ); | ||
}); | ||
Object.defineProperty(props, "buttons_type", { | ||
@@ -55,3 +60,3 @@ get: function() { | ||
set: function() { console.warn("Nothing changed: button_type is read only"); } | ||
} ); | ||
}); | ||
@@ -66,6 +71,11 @@ props.index = 0; | ||
return output_obj; | ||
} | ||
}; | ||
props.options = []; | ||
Object.defineProperty(props, "n_options", { | ||
get: function() { return props.options.length; }, | ||
set: function() { console.warn("Nothing changed: n_options is read only"); } | ||
} ); | ||
output_obj.options = function(opts) { | ||
@@ -75,3 +85,3 @@ if (opts === undefined) return props.options.slice(); | ||
props.options = Object.freeze(opts.slice()); | ||
return output_obj | ||
return output_obj; | ||
}; | ||
@@ -82,24 +92,24 @@ | ||
set: function() { console.warn("Nothing changed: value is read only"); } | ||
} ); | ||
}); | ||
output_obj.value = function(value){ | ||
output_obj.value = function(value) { | ||
if (value === undefined) return props.value; | ||
var index = props.options.indexOf(value); | ||
if(index !== -1) props.index = index; | ||
if (index !== -1) props.index = index; | ||
else console.warn("Nothing changed: value not in options list"); | ||
return output_obj; | ||
}; | ||
Object.defineProperty(props, "width", { | ||
get: function() { return container_node.getBoundingClientRect().width + "px"; }, | ||
set: function() { console.warn("Nothing changed: width is read only"); } | ||
} ); | ||
}); | ||
props.changeHandlers = []; | ||
output_obj.on = function(event, callback){ | ||
if(event === "change") props.changeHandlers.push(callback.bind(output_obj)); | ||
output_obj.on = function(event, callback) { | ||
if (event === "change") props.changeHandlers.push(callback.bind(output_obj)); | ||
return output_obj; | ||
}; | ||
var onChangeCallbacks = function() { | ||
@@ -112,5 +122,5 @@ var value = props.value; | ||
}; | ||
Object.seal(props); | ||
// Grab container | ||
@@ -120,5 +130,5 @@ var container = select(container_selector).classed("controls-container", true); | ||
output_obj.container = container; | ||
//var heading = container.append("div").attr("class", "heading"); | ||
// var heading = container.append("div").attr("class", "heading"); | ||
return { | ||
@@ -131,6 +141,5 @@ output_obj: output_obj, | ||
container_selector: container_selector | ||
} | ||
}; | ||
} | ||
export { createCore }; | ||
export { createCore }; |
@@ -11,18 +11,17 @@ var css_string = ".controls-container {display: inline-block; } .controls-container, .controls-container * {box-sizing: border-box; text-align: left; vertical-align: bottom; } .button-container .button, .dropdown .current {overflow: hidden; text-overflow: ellipsis; height: 100%; white-space: nowrap; text-align: left; font-size: 12px; line-height: 21px; } .button-container .button, .dropdown .current, .dropdown .list .list-item {white-space: nowrap; } .slider, .slider-play {pointer-events: all; vertical-align: bottom } .button {display: inline-block; cursor: pointer } .button:hover {opacity: .5 } .button.selected, .button.selected:hover {color: #fff; cursor: default; opacity: 1; background-image: linear-gradient(transparent, rgba(0, 0, 0, .05) 40%, rgba(0, 0, 0, .1)) } .button-container {pointer-events: all; width: auto; line-height: 0; margin-bottom: 18px; width: 100%; text-align: center; } .button-container.button-group {display: table; border: 1px solid #ccc; width: 100%; table-layout: fixed; border-radius: 3px; margin-bottom: 20px; } .button-container .button {font-size: 12px; border: 1px solid #ccc; background: #fff; padding: 0 8px; color: #333; font-weight: 400; text-align: center; height: 24px; border-radius: 3px; margin: 0 1px 2px; } .button-container.button-group .button {border: none; border-left: 1px solid #ccc; border-radius: 0; display: table-cell; text-align: center; vertical-align: middle; margin: 0; height: 22px; } .button-container.button-group .button:first-child {border-radius: 3px 0 0 3px } .button-container.button-group .button:last-child {border-radius: 0 3px 3px 0 } .button-container .button:hover {background: #eee; opacity: .8 } .button-container.button-group .button:first-child {border: none } .button-container .button.selected, .button-container .button.selected:hover {opacity: 1; background: #ececec; color: #333 } .dropdown {pointer-events: all; display: inline-table; color: #333; font-weight: 400; font-size: 16px; position: relative } .dropdown .heading {margin-bottom: .4em; font-weight: 300 } .dropdown .main {background: #fff; padding: 0 60px 0 6px; cursor: pointer; position: relative; border: 1px solid #ccc; border-radius: 3px; height: 24px; line-height: 26px } .dropdown .list, .dropdown .symbol {position: absolute } .dropdown .current {width: 100%; display: inline-block; vertical-align: top; } .dropdown .symbol {width: 30px; height: 100%; right: 0; top: 0; background: 80% 40% no-repeat; background-size: auto 50%; display: inline-block } .dropdown .list {top: 100%; left: -1px; min-width: calc(100% + 2px); background: rgba(255, 255, 255, 1); padding: 0 2px; text-align: left; display: none; line-height: 1.4em; max-height: 160px; overflow-y: scroll; color: #333; box-shadow: 0 1px 2px rgba(0, 0, 0, .2) } .dropdown .list .list-item {font-size: 12px; height: 24px; padding: 0 5px } .dropdown .list .list-item:hover {cursor: pointer; background: #eee } .dropdown.open .list {display: block; z-index: 1 } .dropdown .list .list-item.selected, .dropdown .list .list-item.selected:hover {color: #57c1fc; cursor: default; opacity: 1 } .dropdown .list .list-item.header, .dropdown .list .list-item.header:hover {font-size: .66em; letter-spacing: 1px; text-transform: uppercase; color: #888; opacity: 1; cursor: default; font-weight: 300; margin-top: .5em } .dropdown .list .list-item.header:first-child {margin-top: 0 } .controls-container .dropdown {margin: 0 0 20px; } .controls-container .dropdown .heading {color: #333 } .slider-holder {margin-bottom: 20px } .slider-play {width: 24px; height: 24px; background-repeat: no-repeat; background-size: 100% 100%; background-position: center; cursor: pointer; display: none; margin-right: 2px } .slider, .slider-holder.animatable .slider-play {display: inline-block } .slider-play:hover {opacity: .7 } .slider {height: 46px; width: 100%; bottom: 0 } .slider-holder.animatable .slider {width: calc(100% - 37px) } .slider-holder.playing .slider {pointer-events: none } .slider .tick line {stroke: #333 } .slider text {fill: #333 } .slider .slider-end-labels {font-size: 11px; fill: #9e9e9e } @media(min-width:520px) {.dropdown .main {height: 30px; } .slider-play {width: 30px; height: 30px } .button-container .button, .dropdown .current {font-size: 14px; line-height: 26px; height: 30px; } .button-container.button-group .button {height: 28px; } .dropdown .list .list-item {height: 30px; font-size: 14px; line-height: 27px; } } "; | ||
function injectCSS(css) { | ||
if (css_injected || typeof document === 'undefined') return; | ||
css = css; | ||
var head = document.head || document.getElementsByTagName('head')[0]; | ||
var style = document.createElement('style'); | ||
style.type = 'text/css'; | ||
head.appendChild(style); | ||
if (style.styleSheet){ | ||
style.styleSheet.cssText = css; | ||
} else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
if (css_injected || typeof document === "undefined") return; | ||
var head = document.head || document.getElementsByTagName("head")[0]; | ||
var style = document.createElement("style"); | ||
style.type = "text/css"; | ||
head.appendChild(style); | ||
if (style.styleSheet) { | ||
style.styleSheet.cssText = css; | ||
} | ||
else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
css_injected = true; | ||
return; | ||
}; | ||
} | ||
export { injectCSS, css_string, makeBackgroundString }; | ||
export { injectCSS, css_string, makeBackgroundString }; |
@@ -1,3 +0,1 @@ | ||
import { select } from "d3-selection"; | ||
import { injectCSS, css_string } from "./core/css.js"; | ||
import { createCore } from "./core/core.js"; | ||
@@ -10,11 +8,7 @@ import { createDropdown } from "./controls/dropdown.js"; | ||
function createControlsGroup(container_selector) { | ||
injectCSS(css_string); | ||
var core = createCore(container_selector); | ||
var output_obj = core.output_obj; | ||
var props = core.props; | ||
var onChangeCallbacks = core.onChangeCallbacks; | ||
var container = core.container; | ||
var container_node = container.node(); | ||
var dropdown_obj = createDropdown(core); | ||
@@ -24,4 +18,2 @@ var buttons_obj = createButtons(core, dropdown_obj); | ||
var options; | ||
var updateCurrentOptions = (function() { | ||
@@ -42,3 +34,3 @@ var options = []; | ||
})(); | ||
var updateCurrentValue = (function() { | ||
@@ -48,3 +40,3 @@ var current_index, current_value; | ||
if (current_index === props.index && current_value === props.value) return false; | ||
var n_options = props.options.length; | ||
var n_options = props.n_options; | ||
if (props.index > n_options - 1) props.index = n_options - 1; | ||
@@ -54,11 +46,11 @@ current_index = props.index; | ||
return true; | ||
} | ||
} )(); | ||
}; | ||
})(); | ||
var setControlOptions = function() { | ||
dropdown_obj.setOptions(); | ||
buttons_obj.setOptions(); | ||
slider_obj.setOptions(); | ||
slider_obj.setOptions(); | ||
}; | ||
var setControlValues = function() { | ||
@@ -69,6 +61,6 @@ dropdown_obj.setValue(); | ||
}; | ||
var setVisibleControl = function(control) { | ||
if (control === "none") container.style("display", "none"); | ||
else container.style("display", null); | ||
else container.style("display", null); | ||
if (control === "dropdown") dropdown_obj.show(); | ||
@@ -81,6 +73,6 @@ else dropdown_obj.hide(); | ||
}; | ||
var update = function() { | ||
var options_updated = updateCurrentOptions(); | ||
if (props.options.length < 2) { | ||
if (props.n_options < 2) { | ||
props.index = 0; | ||
@@ -92,3 +84,3 @@ setVisibleControl("none"); | ||
if (value_updated || options_updated) { | ||
if(options_updated) setControlOptions(); | ||
if (options_updated) setControlOptions(); | ||
setControlValues(); | ||
@@ -105,2 +97,2 @@ } | ||
export default createControlsGroup; | ||
export default createControlsGroup; |
Sorry, the diff of this file is too big to display
127513
11
3482
3