diff --git a/src/ColorStaves.js b/src/ColorStaves.js new file mode 100644 index 000000000..de4af6422 --- /dev/null +++ b/src/ColorStaves.js @@ -0,0 +1,45 @@ +// Color staff lines and their children so it's easy to see which components belong to which staff + +export default class ColorStaves { + setColor() { + let staves = Array.from(document.getElementsByClassName("staff")); + for (var i = 0; i < staves.length; i++) { + let staffColor = ColorStaves.Colors[i % ColorStaves.Colors.length]; + let children = Array.from($("#" + staves[i].id).children()); + children.forEach(child => { + if (child.tagName === "path") { + child.setAttribute("stroke", staffColor); + } else { + child.setAttribute("fill", staffColor); + } + child.setAttribute("class", child.getAttribute("class") + " highlighted"); + }); + } + } + unsetColor() { + let highlighted = Array.from(document.getElementsByClassName("highlighted")); + highlighted.forEach(elem => { + if (elem.tagName === "path") { + elem.setAttribute("stroke", "#000000"); + } else { + elem.removeAttribute("fill"); + } + }); + $(".highlighted").removeClass("highlighted"); + } +} + +// Color palette from Figure 2 (Colors optimized for color-blind +// individuals) from "Points of view: Color blindness" by Bang Wong +// published in Nature Methods volume 8 on 27 May 2011 +// https://www.nature.com/articles/nmeth.1618?WT.ec_id=NMETH-201106 +ColorStaves.Colors = [ + "rgb(0,0,0)", + "rgb(230, 159, 0)", + "rgb(86, 180, 233)", + "rgb(0, 158, 115)", + "rgb(240, 228, 66)", + "rgb(0, 114, 178)", + "rgb(213, 94, 0)", + "rgb(204, 121, 167)" +]; diff --git a/src/Controls.js b/src/Controls.js index e9403a994..52b401968 100644 --- a/src/Controls.js +++ b/src/Controls.js @@ -1,8 +1,12 @@ -export default function Controls (zoomHandler) { +import ColorStaves from "./ColorStaves.js"; +export default function Controls (zoomHandler) { + var color = new ColorStaves(); setZoomControls(); setOpacityControls(); setBackgroundOpacityControls(); + setSylControls(); + setHighlightControls(); function setZoomControls() { $("#reset-zoom").click( function() { @@ -45,14 +49,9 @@ export default function Controls (zoomHandler) { }); } - function shouldHideText() { - return (!$("#displayText").is(":checked")); - } - - function setSylControls(view) { - $("#displayText").click( function () { - view.refreshPage(); - }); + function setSylControls() { + updateSylVisibility(); + $("#displayText").click(updateSylVisibility); } function setOpacityFromSlider() { @@ -61,11 +60,34 @@ export default function Controls (zoomHandler) { meiSel.style("opacity", opacitySliderValue / 100.0); }; + function setHighlightControls(view) { + updateHighlight(); + $("#highlightStaves").click(updateHighlight); + } + + function updateSylVisibility() { + if ($("#displayText").is(":checked")) { + $(".syl").css("visibility", "visible"); + } else { + $(".syl").css("visibility", "hidden"); + } + } + + function updateHighlight() { + if ($("#highlightStaves").is(":checked")) { + color.setColor(); + } else { + color.unsetColor(); + } + } + Controls.prototype.constructor = Controls; Controls.prototype.setZoomControls = setZoomControls; Controls.prototype.setOpacityControls = setOpacityControls; Controls.prototype.setBackgroundOpacityControls = setBackgroundOpacityControls; - Controls.prototype.shouldHideText = shouldHideText; Controls.prototype.setSylControls = setSylControls; Controls.prototype.setOpacityFromSlider = setOpacityFromSlider; + Controls.prototype.setHighlightControls = setHighlightControls; + Controls.prototype.updateHighlight = updateHighlight; + Controls.prototype.updateSylVisibility = updateSylVisibility; } diff --git a/src/NeonView.js b/src/NeonView.js index 2d6a51e66..c9c42520f 100644 --- a/src/NeonView.js +++ b/src/NeonView.js @@ -21,8 +21,9 @@ export default function NeonView (params) { zoomHandler = new ZoomHandler(); infoBox = new InfoBox(neon); controls = new Controls(zoomHandler); - controls.setSylControls(this); loadView(); + controls.setSylControls(); + controls.setHighlightControls(); }); function loadView () { @@ -33,7 +34,6 @@ export default function NeonView (params) { var svg = neon.getSVG(); $("#mei_output").html(svg); d3.select("#mei_output").select("svg").attr("id", "svg_container"); - setSvgText(); var height = parseInt(d3.select("#svg_container").attr("height")); var width = parseInt(d3.select("#svg_container").attr("width")); @@ -48,24 +48,17 @@ export default function NeonView (params) { .attr("width", viewWidth) .attr("height", viewHeight) .attr("viewBox", "0 0 " + width + " " + height); + controls.updateHighlight(); + controls.updateSylVisibility(); resetListeners(); } function refreshPage () { $("mei_output").html(neon.getSVG()); - setSvgText(); resetListeners(); resetTransformations(); } - function setSvgText () { - if (controls.shouldHideText()) { - d3.select("#mei_output").selectAll(".syl").style("visibility", "hidden"); - } else { - d3.select("#mei_output").selectAll(".syl").style("visibility", "visible"); - } - } - function resetListeners () { d3.select("body") .on("keydown", () => { diff --git a/views/editor.pug b/views/editor.pug index 92b365a34..737dbb838 100644 --- a/views/editor.pug +++ b/views/editor.pug @@ -30,6 +30,8 @@ html a.panel-block label.checkbox Display Text: input.checkbox#displayText(type="checkbox") + label.checkbox Highlight Staves: + input.checkbox#highlightStaves(type="checkbox") #neume_info article.message(style={visibility: "hidden"}) .message-header