As in topic, how to unbind i.e click event on svg element? Click event is added by "on()" function on the element.
$(e.element).unbind('click');
e.element.removeEventListener();
Seems to also not working.
The unbind method works Ok with jQuery, I've created a JSFiddle that shows it: http://jsfiddle.net/sPJqN/
My JS Code:
$('#r').on('click', function() {
alert('Clicked');
});
$('#b').on('click', function() {
$('#r').unbind('click');
});
The HTML code:
<button id="b">Remove listener</button>
<svg>
<rect x="10" y="10" width="100" height="100" id="r" />
</svg>
So, I suspect, that the problem is your object e.element, If you post some more code, maybe the root cause would be identified.
Related
I want to create an SVG file with four buttons, one of which is lit up while the other three are darkened, and where clicking/tapping on one of the unlit buttons lights it up while darkening the previously-lit button. In regular HTML I would simply use a radio-group of <input type="radio"> elements, but that doesn't seem to work in SVG.
The buttons don't have to do anything besides lighten/darken (there's no action to perform or form to submit). This is purely a decorative image, I just want to jazz it up with some interactivity.
Is this at all possible to achieve inside a self-contained SVG file? I know you can include JavaScript in SVGs, but I'm not super familiar with JS so I'm not sure if that's the way to go or if there's a better option.
SVG does not have buttons or input elements. Here is an example of how you can switch between "buttons" by adding and/or removing a class name.
document.getElementById('tabs').addEventListener('click', e => {
let svg = e.target.closest('svg');
let btn = e.target.closest('.btn');
if(btn){
[...svg.querySelectorAll('.btn')].forEach(btn => btn.classList.remove('on'));
btn.classList.add('on');
console.log(btn.id, 'was clicked');
}
});
.btn {
fill: PeachPuff;
cursor: pointer;
}
.btn.on {
fill: orange;
}
<svg id="tabs" xmlns="http//www.w3.org/2000/svg" width="400" viewBox="0 0 30 10">
<rect id="btn1" class="btn" width="9" height="5" rx="1" />
<rect id="btn2" class="btn" width="9" height="5" x="10" rx="1" />
<rect id="btn3" class="btn" width="9" height="5" x="20" rx="1" />
</svg>
I'm trying to define a tspan early in an SVG document so it can be transcluded later inside a text. At least in Firefox, the following code does not produce this result.
<svg version="1.1" width="500" height="500" xmlns="http://www.w3.org/2000/svg">
<defs>
<tspan id="transcluded-text">This is a text</tspan>
</defs>
<text>
<use href="#transcluded-text"/>
</text>
</svg>
Using Firefox's Inspect tool, the use element contains a shadow DOM (#shadow-root) as expected, but the shadow DOM itself is empty.
Without using Javascript, is it possible to transclude a tspan inside a text like this?
The text element can only contain text content child elements (so, not <use>) and the only text related element the defs element can contain is <text>. So, it all points to that the <tspan> cannot be used in this way.
<svg version="1.1" width="500" height="500" xmlns="http://www.w3.org/2000/svg">
<defs>
<text x="10" y="20" font-size="20" id="transcluded-text">This is a text</text>
</defs>
<use href="#transcluded-text"/>
</svg>
Since you can not use <use> elements within a <text> element;
or a bare <tspan> within <defs>
A modern Native Web Component can do the replace job:
(this will cause a FOUC you might want to deal with)
<script>
customElements.define("svg-use-replacer", class extends HTMLElement {
connectedCallback() {
setTimeout(() => { // make sure SVG is parsed
this.querySelectorAll('use').forEach(use => {
let href = use.getAttribute("href");
let tspan = this.querySelector(href);
use.replaceWith(tspan); // .replaceWith was not available in IE
});
// if the bare <svg> is required in the DOM:
// this.replaceWith(this.querySelector("svg"));
});
}
});
</script>
<svg-use-replacer>
<svg version="1.1" width="500" height="500" xmlns="http://www.w3.org/2000/svg">
<defs>
<tspan id="foo" stroke="green">Wonderful</tspan>
</defs>
<text x="10" y="20" font-size="20">
Hello
<use href="#foo" /> Web Component
</text>
</svg>
</svg-use-replacer>
Notes
The oldskool way is to attach a class and after that Element is parsed run JavaScript on it.
With Web Components it totally does not matter WHEN the Web Component is defined.
You can execute the above script any time you want.
I have searched through the net and have come to discover that images are made clickable when they are converted to SVG format, however I am still not sure how to do this.
the image below for example, I need every box to be clickable, how do you go about doing this and is there any app that can help me, thank you in advance
enter image description here
You could do this with an SVG. But you would probably find it much easier to do with an HTML image map.
If you're able to edit the SVG itself you can wrap each element with an anchor tag.
<svg>
<a href="www.link1.com">
<rect x="10" y="10" width="60" height="50" fill="#ddd">
</a>
<a href="www.link2.com">
<rect x="75" y="10" width="60" height="50" fill="#ddd">
</a>
</svg>
Otherwise you can use Javascript to add a click handler to each element.
document.getElementById("rect1").addEventListener("click", function() {
window.open('www.link1.com')
});
document.getElementById("rect2").addEventListener("click", function() {
window.open('www.link2.com')
});
<svg>
<rect id="rect1" x="10" y="10" width="60" height="50" fill="#ddd"/>
<rect id="rect2" x="75" y="10" width="60" height="50" fill="#ddd"/>
</svg>
I have a svg and I can draw multiple shapes on this svg. Now my requirement is I want to listen keyboard events like ctrl+C, ctrl+V, ctrl+D, Esc, Delete so that I can copy, paste , duplicate selected shape. But I have no idea about listening keyboard events on SVG . I tried following code but no luck !!
mySVG.on("keydown", function () {
//code to handle keydown
});
Any help ? Thanks in advance.
Because SVG is not an input-type, listen for the event on the window instead:
$(window).on('keypress', function (evt){ ... })
Add tabindex="0" attribute to the <svg> and it will work:
const svgElement = document.querySelector('svg');
svgElement.addEventListener('keydown', event => {
console.log('svg keydown: ', event.key);
});
<svg tabindex="0" width="300" height="200">
<rect width="100%" height="100%" fill="#555" />
<text x="50%" y="50%" font-size="20" text-anchor="middle" fill="white">
Click me and start typing
</text>
</svg>
The tabindex attribute allows you to control whether an element is
focusable, and ...
See MDN docs for more info.
So I have a webpage here. Under "frame background" there are patterns. When clicked they display in the photo frame. The problem is that some of them seem really blocky. Particularly the last one.
My code for this.
jquery:
$(" #borders #pattern1").click (function() {
$(".border").css("fill", "url(#patt1)");
});
svg:
<defs>
<pattern id="patt1" patternUnits="userSpaceOnUse" width="400" height="500">
<image xlink:href="Images/pattern1.jpg" x="0" y="0" width="542" height="774" />
</pattern>
</defs>
I hope this makes sense. If down voting for some reason please give me feedback as to why.