I've got a relatively complex svg depicting a cell embedded into my html page via an tag. If you hover over certain paths of the svg (e.g. the nucleus), I've already managed to get them to change colour, and I've added a tooltip which shows a tiny window with a bit of text. So far so good.
I've also got a bunch of simple html checkboxes which are related to the svg (i.e. they are labelled 'nucleus' etc). All clicking on these checkboxes does is to set their value to 1.
Now, what I really want to achieve is to be able to click on a svg path (e.g. nucleus) which then
changes the color of the path - this I've managed to do with a simple function:
function buttonClick(evt){
document.getElementById("nucleus").style["fill"] = "yellow";
}
and then a
onmouseup="buttonClick(evt)"
in the corresponding path.
selects the corresponding checkbox. (My supervisor likes to be on the safe side and is all about browser compatibility so he wants the plain checkboxes as a backup, so unfortunately I can't just hide them behind the svg or something like that...)
On second click, everything needs to be reversed/unselected
Now, is that possible?
All I could find was:
- how to replace a checkbox by an entire image (not what I need, just a svg path) OR
- how to make style checkboxes in svg/css. (Nice, but also not what I need) OR
- how to select a checkbox in jquery. I've tried this
$('.comp_nuc')[0].checked = true;
but it doesn't seem to do anything.
Give this a try:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
myCheckbox:<input onClick=myCheckChecked() id=myCheckbox type="checkbox" />
<svg width=400 height=400>
<circle id="myCircle" onClick=circleClicked() cx=200 cy=200 fill=red r=100 />
</svg>
<script>
function circleClicked()
{
if( myCircle.getAttribute("fill")=="red")
{
myCircle.setAttribute("fill","yellow")
myCheckbox.checked=true
}
else
{
myCircle.setAttribute("fill","red")
myCheckbox.checked=false
}
}
function myCheckChecked()
{
if(myCheckbox.checked==true)
myCircle.setAttribute("fill","yellow")
else
myCircle.setAttribute("fill","red")
}
</script>
</body>
</html>
Related
I'm trying to make a custom cursor setter. You can customize cursors in CSS, so I went there first.
html {
cursor: url(MY URL GOES HERE), auto !important;
}
It works at this point. However, I want the average user to be able to enter an image URL and see the cursor change to that. I decided to use JavaScript to do that.
function customCursor() {
var v1 = prompt("Enter the image URL you want to be your mouse cursor.");
var style = document.createElement('style');
style.innerHTML = `html {cursor:url(` + v1 + `); } `;
document.head.appendChild(style);
}
However, it doesn't work. I checked the current page HTML with Firebug, and the tag is added. And when I use JavaScript to add it manually, it works. So why would it not work?
I also made sure to keep the images I chose below 128x128.
After massive changes to the code, it still is not working. However, I now understand a reason why (by using devtools to read what was actually being added):
Instead of dynamically using my variable, it was treating the variable name as the URL itself. This makes this question mostly irrelevant.
I've run into a problem while attempting to use SVG marker elements in an SVG based visualization. I'm adding my changes to a web application which happens to include a base tag on every page, so that any references to CSS files, javascript files, etc can be relative.
I have some example code below which reproduces the issue. There is a line element, and a marker element defined. The marker element is referenced by the line in its 'marker-end' attribute, via uri and id of marker. Without the base tag, the arrow displays fine. With the base tag, it is not shown. The reason is because the base tag changes the way the browser resolves urls.. even for the simple id based url specified in the marker-end attribute of the line.
Is there any way I can get around this problem without having to remove the base tag?
I can't really remove it because the use of it is fairly ingrained in the product I'm working on. I need to support Firefox, Chrome and IE9+ for my webapp. Firefox and chrome both produce this problem. IE works fine (ie. arrow marker displays).
<html>
<head>
<base href=".">
<style>
.link { stroke: #999; stroke-opacity: .6; }
marker#arrow { fill: black; }
</style>
</head>
<body>
<svg width="100%" height="100%">
<defs>
<marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="20" markerHeight="20" orient="auto">
<path d="M0,-5L10,0L0,5"></path>
</marker>
</defs>
<line x1="100" y1="100" x2="333" y2="333" marker-start="url(#arrow)" class="link"></line>
</svg>
</body>
</html>
The HTML <base> element is used to say "resolve all relative URLs relative not to this page, but to a new location". In your case, you've told it to resolve relative to the directory with the HTML page.
The SVG marker-mid="url(…)" attribute is a FuncIRI Reference. When you use a value like url(#foo) that relative IRI is normally resolved relative to the current page, finding the element with the foo id. But, when you use <base>, you change where it looks.
To solve this problem, use a better value. Since your base reference is the current directory, you can simply use the name of the current file:
<line … marker-mid="url(this_page_name.html#arrow)" />
If you have a different <base> href, than what you've shown, like:
<base href="http://other.site.com/whee/" />
then you will need to use an absolute href, e.g.
<line … marker-mid="url(http://my.site.com/this_page_name.html#arrow)" />
Try with javascript:
<line id="something" />
With native:
document.getElementById('something').setAttribute('marker-mid', 'url(' + location.href + '#arrow)');
With jQuery:
$('#something').attr('marker-mid', 'url(' + location.href + '#arrow)');
It just works.
In the context of a rich web app like one built on Angular, where you need to set the <base> tag to make HTML5-style navigation work, it can get messy to try to fix that in a permanent way.
In my case, the app I was working on was showing a SVG-based interactive diagram builder that would change the app url as I selected elements therein.
What I did was to add a global event handler that would fix all url(#...) inline styles in any <path> element found in the page:
$rootScope.$on 'fixSVGReference', ->
$('path').each ->
$path = $ this
if (style = $path.attr 'style')?
$path.attr 'style', style.replace /url\([^)#]*#/g, "url(#{location.href}\#"
Then trigger this handler in key places, like when the app state changes (I'm using ui-router)
$rootScope.$on '$stateChangeSuccess', ->
$timeout (-> $rootScope.$emit 'fixSVGReference'), 5
As well as anywhere where I know there'd be new/updated paths like these. Here, the $timeout thing is to account for the fact that the DOM nodes really are changed asynchronously sometime after the $stateChangeSuccess event is triggered.
In Angular 2+, you can inject the base path in your app module instead of using the <base> tag. This resolved the issue in Edge and Firefox for me.
import { APP_BASE_HREF } from '#angular/common';
#NgModule({
providers: [{
provide: APP_BASE_HREF,
useValue: '/'
}]
})
export class AppModule { }
https://angular.io/docs/ts/latest/api/common/index/APP_BASE_HREF-let.html
Ember 2.7 will replace the <base> tag with rootURL which should fix this issue.
In the meantime in my d3 for gradients I'm using the following:
.attr('fill', `url(${Ember.$(location).attr('href')}#my-gradient)`);
If you don't do this, the item you are targeting will seem to be transparent.
On Windows currently (04-2017) all Browsers behave as expected ( mask=url("#svgmask") ). Chrome, Firefox, even IE 11!! - but Edge comes up with an error.
So for Microsoft Edge you still need to give the absolute path ( mask="url(path/to/this-document.htm#svgmask)" ) for your mask ID´s when you are using a base tag in your document:
<svg viewBox="0 0 600 600" >
<defs>
<mask id="svgmask">
<image width="100%" height="100%" xlink:href="path/to/mask.svg" ></image>
</mask>
</defs>
<image mask="url(path/to/this-document.htm#svgmask)" width="600" height="600" xlink:href="path/to/image.jpg"></image>
</svg>
If you do not want want to modify / animate the svg there is a simpler solution than changing the url() parameter.
Include the svg as image:
<img src="yourpath/image.svg">
You can archive it with:
$("[marker-mid]").attr("marker-mid", function () {
return $(this).attr("marker-mid").replace("url(", "url(" + location.href);
});
I am Building a Javascript app
Now I want to have a image button that I have given already now I want to change the image to another image on clicking current image.
When i click again I want to get back the old image please any one help me by giving a coding example pls..
Try this:
function diffImage(img)
{
if(img.src.match(/blank/)) img.src = "black.jpg";
else img.src = "blank.jpg";
}
HTML
<img src="black.jpg" id="image1" onclick=diffImage(this) />
Just try to change image path as per your requirements or you can add multiple images.
DEMO.
Hope this work.
You could also do it with only using CSS if you wanted to.
Just make a checkbox so you can click it without having to trigger an event and put the image in there and then have a different image for when it has been clicked.
<input type="checkbox"/>
And your CSS:
input[type="checkbox"] {
content: url(image url here);
}
input[type="checkbox"]:checked {
content: url(different image here);
}
I don't remember where I learned this trick, but it's worked for me in the past.
Is is possible to both define an anchor to scroll to a URL and set a variable in the frament? I tried with code the below, but this does not work in Chrome. Can I make it work using another delimiter than the ampersand?
<!doctype html>
<html>
<head>
<title>Scroll to anchor test</title>
</head>
<body>
<p>Scroll to bottom (works)</p>
<p><a href="#bottom&test=testing">Scroll to bottom and include
variable in the frament</a> (doesn't work)</p>
<p style="margin-top: 2000px">Bottom of page</p>
<p><a name="bottom">#bottom</a></p>
</body>
</html>
JSFiddle with the code above: http://jsfiddle.net/janaagaard/FHdQr/
As pointed out before #bottom&var=value will not work. The page will scroll to the element with id="bottom&var=value". The page scrolls down without reloading.
?var=value#bottom would reload the page with that variable and scroll to the element with id="bottom" on that new page. This is useful if you need to know the value of the 'var' variable on the server to perform some server-side action. E.g. In PHP you would see the value value in $_GET['var'].
If you need to change something with javascript and want to alter a variable because of that reason, you should use the onclick event (either by using it in-line or binding it to the element in an other way). Usually you wouldn't want to change a variable, but do whatever you need to do in a (nameless) function instead. This is useful if you want to do a client-side action.
Edit: I quickly want to add. To do a server-sided action, you don't necessarely need to reload the page. Lookup ajax-requests if you need to do that. This is done with javascript.
No, it's not possible to both link to an anchor and use the fragment for storing variables.
I ended up scrolling the page using JavaScript, using this answer as a template: https://stackoverflow.com/a/4801719/37147.
I would preffer this if I were you:
javascript
function GetTop(ele){
if (ele.offsetParent)
return (ele.offsetTop + GetTop(ele.offsetParent));
else
return (ele.offsetTop);
}
function scrollToAnchor(id,offset){
var aTop;
if(id=='0')
aTop=0;
else
aTop = GetTop(document.getElementById(id));
//40px to leave room for #title
$('body, html').animate({scrollTop:aTop+offset},900);
//body for chrome/safari and html for ie/firefox/opera
}
Put this in your HTML next to an ID orso:
onclick="scrollToAnchor('div name to scroll to', -10)"
the -10 stands for the pixels he will be above or beneath the place you want to scroll to.
In my page I have a hidden <div>, such as the following:
<div id="myid" style="display:none;">
...
</div>
When the user clicks a button, I have a javascript code that calls $('#myid').show("slow");, thus displaying this <div>.
My question is when does the code inside the <div> gets called: when the page first loads or only when it's shown?
My concern is that inside this <div> I'd like to place a page counter (with an <iframe>), which should only be called when the <div> is shown. The alternative would be to put the code inside the javascript, but I'd rather keep it in the page.
The code inside the div get called as you load the page.
So the counter will get called everytime the page is loaded even if the div stays hidden.
So you have to use javascript somehow like this:
<div id="myid" style="display:none;">
...
</div>
<script>
function showCounter() {
document.getElementById("myid").innerHTML = '<script>counter-code</script>';
document.getElementById("myid").show('slow');
}
</script>
and add the function showCounter to your button.
It will be run when the page loads, display:none only affects visibility and has nothing to do with code operation layer (in fact, some browsers ignore CSS entirely and may show it anyway).
If you want a piece of code to only run when clicking a JavaScript button, you should attach that code to the Javascript function. Make an empty div on your page and then use the function to put code inside it:
<div id="jsDiv"></div>
<script>
function jsCode() {
document.getElementById('jsDiv').innerHTML = 'Whatever you want';
}
</script>
Then attach the jsCode() function to your button, and the HTML will only be rendered when the function is called. If you're using server-side scripting (PHP, Rails etc.) or something more complex, look into jQuery and AJAX functions.
Try like this:
$(document).ready( function() {
$('#myid').show("slow")
}