MouseOver or hover() or css() for changing positions - image

I have an image on my page and want that it change the position on mouseover or on click, so I tried several things but I cant find the right start.
So I started to change the top-position but that's not working, I would like that on mouseover the image it jumps to position x/y (maybe random x/y) if I mouseover it again it will jump to another position.
$('#image').one('click', function () {
$(this).css( 'top' : '+=200' );
});
But that's not working so please someone could give me some input that I can figure out what to do?

Note that while setting values for top, jQuery will not automatically get the value of top set previously and add 200 to it(like a normal programming language). You could have seen this as an error in executing if you try to see in a console. You can get the value of top first and then add 200px to it and then set it again.
This should work:
$('#image').one('click', function () {
var top = parseInt($(this).css("top"));
$(this).css( 'top' , top+ 200);
});
I had to parse the string to an integer returned by css, you could also substitute that extra operation by some method that returns only the value and not the value with "px" added to it, dunno if there is one already.

Try something like this:
<html>
<head>
<script type="text/javascript">
function switchPos(obj)
{
var divobj = document.getElementById('div1')
var x = divobj.offsetHeight - obj.height - 5;
var y = divobj.offsetWidth - obj.width - 5;
var randomx = Math.floor(Math.random()*x+1);
var randomy = Math.floor(Math.random()*y+1);
obj.style.top = randomx + 'px';
obj.style.left = randomy + 'px';
}
</script>
</head>
<body>
<div id="div1" style="width: 800px; background: red;">
<img src="image.jpg" style="position:relative;" onmouseover="switchPos(this);" onmouseout="switchPos(this);"/>
</div>
</body>
</html>

Related

add legend to dc.js scatterplot

Somewhat related to this question.
I would like to add a legend to a scatterplot using dc.js, ideally with the possibility of highlighting points based on hover/click of the corresponding legend. The source code seems to indicate that color is "legendable" for scatterplots, but I cannot find any examples where this is done.
Running the code below in the browser triggers an error:
tmp.html:26 Uncaught TypeError: Cannot read property 'key' of undefined
at Object.myChart.dimension.group.colorAccessor.d (tmp.html:26)
at Object._chart.getColor (color-mixin.js:149)
at Object._chart.legendables (scatter-plot.js:360)
at Object._legend.render (legend.js:45)
at Object._chart.render (base-mixin.js:703)
at Object.dc.renderAll (core.js:230)
at tmp.html:33
<!DOCTYPE html><html><head><title></title>
<link rel="stylesheet" type="text/css" href="dc.css"/>
<script type="text/javascript" src="https://d3js.org/d3.v5.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.4.6/crossfilter.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.9/dc.js"></script>
</head><body>
<div id="chart"></div>
<script type="text/javascript">
dc.config.defaultColors(d3.schemeCategory10);
var myChart = dc.scatterPlot("#chart");
let input = [{x:0,y:0,c:1}, {x:1,y:1,c:0},{x:0.5,y:0.5,c:2}];
(function(data) {
var ndx = crossfilter(input),
dims = ndx.dimension( d => [+d.x,+d.y,+d.c]),
grp = dims.group();
myChart
.dimension(dims)
.group(grp)
.colorAccessor(d=> +d.key[2])
.x(d3.scaleLinear().domain(d3.extent(d3.extent(input, d => +d.x))))
.valueAccessor(d => +d.key[1])
.brushOn(false)
.legend(dc.legend().x(750).y(10).itemHeight(13).gap(5));
})(input);
dc.renderAll();
</script></div></body></html>
Yes, unfortunately it is a bug that was reported a long time ago, but has never been fixed. The scatter plot is calling _chart.getColor() with no arguments.
https://github.com/dc-js/dc.js/issues/1138#issuecomment-217861014
Even if it's fixed, it's only returning one legendable, so I think it will only work for the scatter-series case. If you want to display legend items for each color in your chart, you'll have to generate that data yourself:
myChart.legendables = function () {
var byColor = {};
myChart.group().all().forEach(function(d) {
var color = myChart.colors()(myChart.colorAccessor()(d));
byColor[color] = {
chart: myChart,
name: 'color ' + myChart.colorAccessor()(d),
color: color
};
})
return Object.values(byColor);
};
Maybe the chart should do something this automatically. One complication is that there currently aren't any names defined for colors - here I just pasted 'color ' with the value returned by the color accessor, but you presumably have better names in your actual data set.
Fork of your fiddle.

compare class of path elements to a dataset

I am really new to d3 and I want to make a choropleth map with the d3 datamaps so if have to compare the classes of the pathways to my dataset. So far I did manage to get the path's
html
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script>
<script src="/d3map/datamaps.world.min.js"></script>
<div id="container" style="position: relative; width: 500px; height: 300px;"></div>
<script src="d3map.js"></script>
js code
var map = new Datamap({element: document.getElementById('container'),
})
var country = d3.selectAll("path")
Country is an array containing 177 elements
one element in country has this form:
<path d="bunch of numbers" class="datamaps-subunit AFG" style="etc"></path>
i want to see if the country code in the class (e.g. AFG) matches one in my dataset.
Country.class gives undefined
I am probably missing something really obvious
Here's an example fiddle: https://jsfiddle.net/g2v5sgmz/
You can filter specific classed elements in an array with the filter method like this:
var country = d3.selectAll("path");
var afg = country.filter(function(d,i){
if( d3.select(this).classed("AFG") ){
return d3.select(this);
}
})

Leaflet and D3js: Feature.properties are not showing in Leaflet popup

How do you add feature properties under a D3 chart in a Leafletjs popup?
I got the popup and chart working, but I can't seem to add the feature.properties below the chart.
Here's a sample of my geoJSON data:
var myData = [{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"Name":"Gulran","Province":"Hirat","Ethnic1":0.19,"Ethnic2":0.32,"Ethnic3":"0.10","Ethnic4":"0.00","Ethnic5":"0.10","Ethnic6":"0.00"},"geometry":{"type":"Polygon","coordinates":[[[60.941162109375,29.897805610155874],[61.92993164062499,31.034108344903512],[63.34716796874999,31.3348710339506],[64.05029296875,30.401306519203583],[64.412841796875,29.735762444449076],[64.09423828125,29.36302703778376],[62.29248046875,29.36302703778376],[60.941162109375,29.897805610155874]]]}},{"type":"Feature","properties":{"Name":"Chahar Burjak","Province":"Nimroz","Ethnic1":0.25,"Ethnic2":0.12,"Ethnic3":0.03,"Ethnic4":0.01,"Ethnic5":"0.00","Ethnic6":"0.00"},"geometry":{"type":"Polygon","coordinates":[[[63.38012695312499,31.3348710339506],[65.06103515625,31.80289258670676],[65.6982421875,31.156408414557],[66.016845703125,30.467614102257855],[65.291748046875,30.164126343161097],[64.22607421875,30.0405664305846],[63.38012695312499,31.3348710339506]]]}}]}];
Here's my popup code:
var popup = L.popup({minWidth: 600}).setContent(div);
layer.bindPopup(popup + '<br>' + feature.properties.NAME);
Here's my jsfiddle code to test. As you can see, the popups are working, but can't get the feature properties to display under the chart.
Thanks for any help...
I'm seeing multiple possible issues.
You are opening a <svg> element, but you are not closing it. If you add text like this it will get "swallowed" and end up within the rendered <svg>here</svg>, but the chart drawn by d3 will hide it:
// won't show the text
var div = $('<div id="chart" style="width: 600px; height: 400px;"><svg>here is some text</div>')[0];
You can fix that by using a self-closing <svg/>:
var div = $('<div id="chart" style="width: 600px; height: 400px;"><svg/><br/>here is some text</div>')[0];
Next issue is that you are trying to combine a L.popup object with strings:
layer.bindPopup(popup + 'here is some text');
Because this L.popup is an object you can not simply concatenate text to it. The result would look like this: "[object Object]here is some text".
And then you are using feature.properties.NAME which will not work because your GeoJSON properties' keys are named Name (notice the capitalization) - use instead: feature.properties.Name
To conclude, to solve your problem change the one line var div = ... in your onEachFeature_LMA function to this:
var div = $('<div id="chart" style="width: 600px; height: 400px;"><svg/><br/>'+feature.properties.Name+'</div>')[0];
Since you are using jQuery, if you want to add more graphs, other HTML elements later you can also build the popup's HTML like this:
var div = $('<div id="chart" style="width: 600px; height: 400px;"><svg/></div>')[0];
var div2 = $('<div></div>').html(feature.properties.Name);
$(div).append($(div2));

Virtual area around vml element

this is my first post, so my deepest excuses if something went wrong :)
I have a little html-control to write and biggest problem is ie6-8 support. There are no alternatives to skip ie6-8 support at all :( So after searching a while, I did found Raphael and it allows me to create custom shapes defined in SVG file. I need to attach 'mouseover' event and select element on hover. Event working great but I did find BIG problems in VML hover behavior.
Code was simplified to RAW html with VML shape.
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<style>v\: * { behavior:url(#default#VML); antialias: false; }</style>
</head>
<body>
<div id="message">hovered: nope</div>
<v:oval id="oval" style="width:100px; height:75px" fillcolor="#bbb"></v:oval>
<script>
var messageElm = document.getElementById('message');
var ovalElm = document.getElementById('oval');
ovalElm.attachEvent('onmouseover', function () { messageElm.innerText = 'hovered: yep'; });
ovalElm.attachEvent('onmouseout', function () { messageElm.innerText = 'hovered: nope'; });
</script>
</body>
</html>
If you try to move mouse over oval element you can noticed that rendered shape is not same as hover shape. I mean, hover triggers 2-3px from rendered shape (not from each side).
So question is: how to disable that virtual area (if it is possible at all)?
i had the same issue and i tried usemap;
first i create a map on a transparent png8 which covered the vml
this.dom.insertAdjacentHTML("AfterBegin",'<map name="'+_id+'"></map><img id="'+_id+'" src="'+transparent.png+
'" style="position:absolute;width:'+dom.clientWidth+';height:'+dom.clientHeight+'" />');
var map = this.dom.getElementsByTagName('map')[0];
this.dom.appendChild(map);
this.map = map;
then get the shape attach to an area; map it;
i made poly demo only;
function _getMap(shape){
this._map = this._map || {};
if(this._map[shape.id]){
}else if(shape.nodeName == 'shape'){
var arrDots = shape.childNodes[0].v.match(/(\d+),(\d+)/g)
this._map[shape.id] = _polyMap(arrDots);
}
return this.map[shape.id]
}
function _polyMap(arrDots){
var map = this.map;
var area = document.createElement('area');
area.setAttribute('shape',"poly");
area.setAttribute('coords',arrDots.join(','));
area.setAttribute('href','##');
area.setAttribute('alt','##');
map.appendChild(area);
}
then you can bind event on it;
function _onIE(shape, evtname, fn){
this._getMap(shape).attachEvent('on'+evtname, fn);
}

jQuery scrollstart, scrollstop and very quick scrolling issue

I'm having an issue with James Padolsey's custom events: scrollstart and scrolltop
When I use the mouse wheel to scroll one "notch" or I click the scroll bar somewhere far below or above its current position, causing sudden scroll by a large amount, I get the same scrollTop() values for scrollstart and scrolltop - I can't tell where the scroll started or in which direction the scroll has taken place. jsFiddle available here (note: if you have an extremely high resolution, you will have to add more text to the HTML so that a scroll bar appears in the Result window).
HTML:
<html>
<body>
<div id="scrollable">
<!-- insert lots of text here -->
</div>
</body>
</html>
CSS:
#scrollable {width: 120px;}
JavaScript:
var before = 0;
$(window).bind('scrollstart', function() {
before = $(window).scrollTop();
});
$(window).bind('scrollstop', function() {
alert('before: ' + before + "\nafter: " + $(window).scrollTop())
});
jsFiddle available here
Any ideas on how to retrieve the true scrollTop() value for the scrollstart event? Modifying the plugin is an option I guess, so all ideas welcome.
Instead of recording the before value when the scroll starts, I would suggest doing so in another event, for example mousemove()
jsFiddle of this idea working
Maybe I misunderstood your question (I haven't used that plugin), but I think you don't need to use every part of that plugin. If you only want to know the previous and current value of ScrollTop and its direction, take a look at this:
http://jsfiddle.net/C3ye7/
var currentScrollTop, temporalScroll = 0;
$(window).scroll(function(){
currentScrollTop = $(this).scrollTop();
console.log('Previous value: ' + temporalScroll)
if (currentScrollTop > temporalScroll) {
console.log('scroll down')
console.log('Current value: ' + currentScrollTop)
}
else {
console.log('scroll up');
console.log('Current value: ' + currentScrollTop)
}
temporalScroll = currentScrollTop;
});
In order to add the timing functionality, you can use only that part of that plugin (or simply, start a setTimeout to record a bigger change when scrolling).

Resources