Skip to content

Instantly share code, notes, and snippets.

@uglow
Last active August 31, 2018 05:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uglow/3376b0d0dfc207d06c1cc1d625de95d8 to your computer and use it in GitHub Desktop.
Save uglow/3376b0d0dfc207d06c1cc1d625de95d8 to your computer and use it in GitHub Desktop.
DrawIO SVG Filter Button script
//<![CDATA[
// This script is designed to be imported by an SVG file created by DrawIO.
// While we wait for DrawIO to export layers and groups correctly for SVGs,
// this is a hacky way to add filter buttons to filter shapes based on their stroke or fill.
//
// It basically works by looking for nodes with the background colour #abcdef. These nodes represent toggle buttons.
//
// Need to request this gist via rawgit.com (see https://stackoverflow.com/questions/17341122/link-and-execute-external-javascript-file-hosted-on-github)
function createButtonStyles() {
var css = `
.toggleButton {
cursor: pointer;
}
.toggleButton > rect {
fill: #0078e7;
}
.toggleButton > text {
fill: #fff;
}
.toggleButton > rect:hover {
fill: #1088f7;
}
.toggleButton.inactive > rect {
fill: #888888;
}
.toggleButton.inactive > text {
fill: #000;
}`;
var style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
style.appendChild(document.createTextNode(css));
document.querySelector('svg').appendChild(style);
}
function toArray(nodeList) {
return Array.prototype.slice.call(nodeList);
}
function toHex(cssRGBString) {
// If this is already a HEX string, bail
if (cssRGBString.indexOf('#') !== -1) {
return cssRGBString;
}
// Convert rgb( 1, 2 , 3) to [1,2,3]
var colorArray = cssRGBString.replace('rgb(', '').replace(/[ )]/g, '').split(',');
return colorArray.reduce(function(acc, curr) {
var hex = Number(curr).toString(16);
if (hex.length < 2) {
hex = '0' + hex;
}
return acc + hex;
}, '#');
};
function toRGB(cssHexString) {
// If this is already a HEX string, bail
if (cssHexString.indexOf('rgb') !== -1) {
return cssHexString;
}
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
cssHexString = cssHexString.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(cssHexString);
if (!result) {
return cssHexString;
}
return 'rgb(' + parseInt(result[1], 16) + ', ' + parseInt(result[2], 16) + ', ' + parseInt(result[3], 16) + ')'
};
function addClickListener(node) {
node.addEventListener('click', toggleLayer);
return node;
}
function init() {
// Create the button styles
createButtonStyles();
// Find the magic button string
var buttonContainers = toArray(document.querySelectorAll('svg foreignObject > div[style*="color: rgb(171, 205, 239)"]'));
buttonContainers
.map(generateButton)
.map(addClickListener);
}
function generateButton(node) {
var oldButton = node.querySelector('font');
var oldForeignObj = node.parentElement;
var switchElem = oldForeignObj.parentElement;
var button = document.createElementNS('http://www.w3.org/2000/svg', 'g');
var buttonRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
var buttonText = switchElem.querySelector('text');
buttonRect.setAttributeNS(null, 'x', 0);
buttonRect.setAttributeNS(null, 'y', 0);
buttonRect.setAttributeNS(null, 'rx', 3);
buttonRect.setAttributeNS(null, 'ry', 3);
buttonRect.setAttributeNS(null, 'width', oldForeignObj.getAttributeNS(null, 'width'));
buttonRect.setAttributeNS(null, 'height', parseInt(oldForeignObj.getAttributeNS(null, 'height'), 10) * 1.5);
buttonText.textContent = oldButton.textContent.replace(/[\[\]]/g, '');
buttonText.setAttributeNS(null, 'pointer-events', 'none');
button.appendChild(buttonRect);
button.appendChild(buttonText);
button.setAttributeNS(null, 'data-boxes', toHex(oldButton.color));
button.setAttributeNS(null, 'data-lines', toHex(oldButton.style.backgroundColor));
button.setAttributeNS(null, 'data-fonts', toRGB(oldButton.color));
button.setAttributeNS(null, 'pointer-events', 'all');
button.setAttributeNS(null, 'class', 'toggleButton');
// Replace the switch-element with our own button
switchElem.parentElement.replaceChild(button, switchElem);
return button;
}
function toggleLayer(evt) {
var button = evt.currentTarget;
var classes = button.getAttributeNS(null, 'class').split(' ');
var targetBoxes = '[stroke="' + button.getAttributeNS(null, 'data-boxes') + '"]';
var targetLines = '[stroke="' + button.getAttributeNS(null, 'data-lines') + '"]';
var targetText = 'div[style*="' + button.getAttributeNS(null, 'data-fonts') + '"]';
var allSelector = [targetBoxes, targetLines, targetText].join(',');
if (classes.indexOf('inactive') === -1) {
button.setAttributeNS(null, 'class', classes.concat('inactive').join(' '));
toArray(document.querySelectorAll(allSelector)).forEach(function(node) { node.style.opacity = 0.1; });
} else {
button.setAttributeNS(null, 'class', classes.filter(function(cls) { return cls !== 'inactive'; }).join(' '));
toArray(document.querySelectorAll(allSelector)).forEach(function(node) { node.style.opacity = 1; });
}
}
/*
// This version works when we edit the SVG to add classes and groups after exporting from Draw.io
function init() {
// Apply click event handlers to each toggleButton
var nodes = toArray(document.querySelectorAll('.toggleButton'));
nodes.forEach(addClickListener);
}
function toggleLayer(evt) {
var button = evt.currentTarget;
var classes = button.getAttributeNS(null, 'class').split(' ');
var targetLayerSelector = button.getAttributeNS(null, 'data-layer');
if (classes.indexOf('inactive') === -1) {
button.setAttributeNS(null, 'class', classes.concat('inactive').join(' '));
toArray(document.querySelectorAll(targetLayerSelector)).forEach(function(node) { node.style.opacity = 0.1; });
} else {
button.setAttributeNS(null, 'class', classes.filter(function(cls) { return cls !== 'inactive'; }).join(' '));
toArray(document.querySelectorAll(targetLayerSelector)).forEach(function(node) { node.style.opacity = 1; });
}
}
*/
window.addEventListener("load", init);
//]]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment