I have a list and I want to retrieve and modify it.
Like If I want to change fontsize from 14px to 10px.
Also I am not able to alert it in a different function even thought its in a global variable.
alert(options) shows undefined.
var options = {
colors: ['#795548', '#EF851C', '#6633CC'],
fontsize: "14px",
}
Actually I am working on google charts and want to get this static list(declared globally) in below function.
Calling function :-
function LoadCurrentChartData(currentChart) {
alert(options);
var chart = new google.visualization.Table(document.getElementById('Graph1'));
chart.draw(data, options);
}
You need to define your variable before using this. Check below
function func1(){
console.log(options.fontsize);
}
//func1();//calling from here will give error
var options = {
colors: ['#795548', '#EF851C', '#6633CC'],
fontsize: "14px",
}
func1();
//Edit fontsize value
options.fontsize = "10px";
console.log("After chage");
func1();
Related
I need to be able to add some custom info to the pie.info.contentsFunction in Zoomcharts. I have multiple charts on the page, each one created like so...
var pc = new PieChart({
pie: {
innerRadius: 0.5,
},
container: chartContainer1,
area: { height: 500 },
data:chartData,
toolbar: {
"fullscreen": true,
"enabled": true
},
info: {
contentsFunction: boomChartTT
}
});
In the "boomChartTT" function I need to know what chart is being hovered upon. I'd like to be able to do something like this...
info: {
contentsFunction: boomChartTT(i)
}
...where 'i' is the index of the chart.
The reason I need to know the chart index is because I have some other data saved in an indexed array for each chart. The index of the chart matches the index of the data.
EXAMPLE: if user hovers on a slice in chart2 I'd want to pass '2' to the boomChartTT function so I can access the totals data for that chart (say, totalsData[2]).
I've done this in the past with other chart libraries by simply adding a data attribute to the chart container to give me the index like so...
<div id="chartContainer1" data-index="1"></div>
...and then I'm able to access the chartContainer from the hover function (contentsFunction) and then get that index.
I don't want to add the totals data to the actual chart data because I'd have to add it to each slice which is redundant.
Is there a way to do this?
Please let me know if my post is unclear.
EDITED TO ADD:
I don't think it matters but here is the boomChartTT function:
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
//var thisData=dataSearch(totalsData[i],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
The commented line is where I would need the index (i) to to get the correct totalsData.
SOLVED. I simply added "chartIndex" to the data like so...
for(var i=0;i<r.length;i++){
var thisDataObj ={
id:r[i].REFERRINGSITE,
value:r[i].PCTOFSALES,
name:r[i].REFERRINGSITE,
chartIndex: arguments[1],//<----- arguments[1] is the chart index
style: { expandable: false, fillColor: dataSearch(dataRSList,"REFERRINGSITE",r[i].REFERRINGSITE)[0].COLOR }
};
chartData.preloaded.subvalues.push(thisDataObj);
}
Then in the boomChartTT function...
function boomChartTT(data,slice){
var tt="<div class=\"charttooltip\">";
if(data.name==="Others" || data.name==="Previous"){return tt+=data.name+"</div>";}
var thisData=dataSearch(totalsData[data.chartIndex-1],"REFERRINGSITE",data.id);
tt+="<h5 class=\"strong\">"+data.id+"</h5>"+oHoverTable.render(thisData)+"</div>";
return tt;
}
I feared that adding custom fields to the chart data would break the chart (which I believe I've experienced with other libraries). So, there you go.
I'm going crazy here trying o work out why the scoping of my variable won't pick up the right value from a loop of 60 items from a DB in my Appcelerator project.
My map marker displays the correct label, but when I click it, no matter what combo of scoping I try, I cannot get the correct value in the alert. It just returns the 60th entry every time.
Likely a schoolboy error, but this is driving me nuts.
This is my function
function loadAnimals() {
var db = Ti.Database.open('myDB');
var getSpecies = db.execute('select * from species');
while (getSpecies.isValidRow()) {
var speciesID = getSpecies.fieldByName('speciesnid');
var speciesName = getSpecies.fieldByName('speciesname');
var speciesDesc = getSpecies.fieldByName('speciesdescription');
var speciesLatitude = getSpecies.fieldByName('specieslatitude');
var speciesLongitude = getSpecies.fieldByName('specieslongitude');
var speciesConStatus = getSpecies.fieldByName('speciesconservationstatus');
var speciesMarkerFilename = getSpecies.fieldByName('speciesiconfilename');
var speciesMarkerIcon = getSpecies.fieldByName('speciesmapicon');
var speciesMarkerURI = getSpecies.fieldByName('speciesmapiconurl');
var speciesImageFullPath = speciesMarkerURI.replace("public://", "http://myurl.com/");
var speciesImageFullPath = speciesImageFullPath.replace(" ", "%20");
var imageFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerIcon);
var iconFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, speciesMarkerFilename);
var annotationView = Ti.UI.createView({
backgroundColor: '#222222',
width: 150,
height: 75,
layout:'vertical'
});
var addtoTourView = Ti.UI.createView({
height:20,
backgroundColor:'#6ea108'
});
var addtoTourTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'ADD TO TOUR',
width: 150,
height: 15,
top:3,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'bold'
}
});
var annotationTitle = Ti.UI.createLabel({
color: '#FFF',
text: 'test',
width: 150,
height:15,
top:0,
textAlign: 'center',
font: {
fontSize: 14,
fontWeight: 'normal'
}
});
var blankView = Ti.UI.createView({
backgroundColor: '#222222',
width: 1,
height: 73,
borderRadius: 0
});
annotationView.add(addtoTourView);
addtoTourView.add(addtoTourTitle);
annotationView.add(annotationTitle);
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID,
rightView: annotationView,
leftView: blankView
}));
addtoTourView.addEventListener('click', function(e) {
//alert(speciesName + ' has dded to Tour');
var dialog = Ti.UI.createAlertDialog({
message: 'Added to your Tour',
ok: 'Continue',
title: speciesName //this is the 60th entry, not the correct one
});
dialog.show();
// do the insert into the DB
var db = Ti.Database.open('myDB');
db.execute('INSERT INTO tour (speciesnid) VALUES (?)', speciesID); // same with this ID, needs to the correct ID
db.close();
});
annotationTitle.text = speciesName;
//load up the next record
getSpecies.next();
};
// close the database
getSpecies.close();
// add markers to map
mapview.annotations = annotations;
};// end of loadAnimals fucntion
Can anyone suggest what I'm doing wrong?
Michaels solution sounds right.
Let me post what I was gonna say anyway. I focus on explaining the scope problem, on why your code doesn't do what you expected.
In javascript the scope is bound to the function. When you declare a variable within a loop (for/while/do...) things can get a little confusing. You are not creating new variables, you are just overriding the value of the first (and only) variable with that name.
So, you have 1 variable in function loadAnimals, called speciesName. In the while-loop you just override the value of that variable. After the 60'th iteration, the variable just remembers the last thing you set it to.
When the client clicks on the marker, the loop is finished, the value has been set a long time ago.
Notice: there are probably solutions provided by your map service, but I don't know about that.
1 solution: 'this'.
The 'this' variable tells you what has been affected. Inside a onClick callback, this is the element that was clicked on.
The solution to your problem will probably involve 'this'. But I'm not sure exactly how.
Here an example of what I mean.
<h2>Click on the animal</h2>
<p>dog</p>
<p>cat</p>
<p>hamster</p>
<script>
function loadAnimals() {
var speciesName = '';
var animalElements = document.getElementsByTagName('p');
for (var i=0; i<animalElements.length; i++) {
speciesName = animalElements[i].innerHTML ; // notice, this variable will be overridden, so this variable is useless within the onClick callback.
animalElements[i].addEventListener('click', function(e) {
// variable 'this' is the <p> that was clicked on.
var value_clicked_on = this.innerHTML;
alert(value_clicked_on);
});
}
}
window.onload = loadAnimals;
</script>
When creating your annotations array to add to to the map add your title to the annotation paramters as well as the speciesID which you are setting with the key - myid.
annotations.push(Map.createAnnotation({
latitude: speciesLatitude,
longitude: speciesLongitude,
title: ' ',
//pincolor: Map.ANNOTATION_RED,
image: iconFile,
animate: true,
myid: speciesID, // We'll be querying this
myname: speciesName, // and also this
rightView: annotationView,
leftView: blankView
}));
Then add your event listener once onto the map object instead of each individual annotation object. This manages memory more efficiently and is the correct way to add it. Don't add the event listener on for every annotation, this is bad practise.
// Handle click events on any annotations on this map.
mapview.addEventListener('click', function(evt) {
Ti.API.info("speciesID " + evt.annotation.myid + " clicked, speciesName: " + evt.annotation.myname);
});
On this single event listener you can now create your alert dialog and DB insert by accessing each annotations individual properties by inspecting
evt.annotation
On the Map object you can do the following as well:
The click event includes a value which you can interrogate clicksource
This clicksource will let you know the source - pin, annotation, leftButton, rightButton, leftView, rightView, title, or subtitle which you can use in the event listener.
Also available is the source object that fired the event - source. You can then test if the clicksource is not null and the source is coming from the "ADD TO TOUR" element that you want to place the trigger on. still getting all your annotation properties from evt.annotation
Though I have successfully colored the bars of google chart individually but not able to keep them when we hover mouse over it. It is getting reset back to blue(which is default).
Here is the jsfiddle of what I have done jsfiddle.
I tried to control the hover behaviour with multiple ways like below.
This I am keeping outside (document.ready) but inside script tag.
1)
$('#chart_div').hover(
function() {
$('#chart_client').hide(); // chart_client is another google chart div.
}, function() { // just for testing I was doing hide/show of that.
$('#chart_client').show();
}
);
2)
$("#chart_div").on({
mouseenter: function () {
$('#chart_client').hide();
},
mouseleave:function () {
$('#chart_client').show();
}
},'rect');
3)
google.visualization.events.addListener('#chart_div', 'ready', function () {
$('#chart_div rect').mouseover(function (e) {
alert('hello');
});
});
I must be doing something wrong, could you please tell me what and where.
I solved it using below code. Earlier I was trying to create charts using dynamically adding rows into chart(please visit my jsfiddle) but with this below approach I am first preparing data(converting dynamic to static) and adding that static data in to chart's 'arrayToDataTable' method.
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawUserKeywordChart);
function drawUserKeywordChart() {
var val = 'Tax:47;Finance:95;Awards:126;Bank:137;Debt:145;';
var length = val.length;
var array = [];
//preparing data
while(length>0){
var sepAt = val.indexOf(";");
var value = parseInt(val.substring(val.indexOf(":")+1, sepAt));
array.push(val.substring(0, val.indexOf(":")));
array.push(value);
val = val.substring(val.indexOf(";")+1, length);
length = val.length;
}
var data = google.visualization.arrayToDataTable([
['Keyword', 'Occurences', { role: 'style' }],
[array[0], array[1], '#8AA3B3'],
[array[2], array[3], '#A9B089'],
[array[4], array[5], '#848C49'],
[array[6], array[7], '#44464A'],
[array[8], array[9], '#704610'],
]);
var options = {
title: 'Keyword Matches',
width: 660,
height: 450,
titleTextStyle:{bold:true,fontSize:20},
legend:{position:'none'}
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_keyword1'));
chart.draw(data, options);
}
Please advice if you find anything wrong here or you have better approach than this.
when I click the red circle, the window will popup a alert once.
It works fine in firefox and chrome, but in ie8, it's popup alerts twice.
How could I fix it?
please see my code in the following:
Raphael("world", 1000, 400, function () {
var r = this;
r.rect(0, 0, 1000, 400, 0).attr({
stroke: "none",
fill: "0-#9bb7cb-#adc8da"
});
var click = function(){
alert(this.type);
};
r.setStart();
var hue = Math.random();
for (var country in worldmap.shapes) {
r.path(worldmap.shapes[country]).attr({stroke: "#ccc6ae", fill: "#f0efeb", "stroke-opacity": 0.25});
}
var dot = r.circle(772.9870633333333, 166.90446666666668).attr({
title: "Point",
fill: "red",
stroke: "#fff",
"stroke-width": 2,
r: 5
});
var world = r.setFinish();
world.click(click);
});
I've had this problem a few time. Solved it by using a mouse up event instead of a click event. IE sucks.
I find a way to fix this issue, replace the Raphael Set Object with a array Object to push all Rahpael Elements Object, then loop the array to add click event for each Element.
see the following code:
var set = [];
// r.setStart();
for (var country in worldmap.shapes) {
var element = r.path(worldmap.shapes[country]).attr({stroke: "#ccc6ae", fill: "#f0efeb", "stroke-opacity": 0.25});
set.push(element);
}
var dot = r.circle(772.9870633333333, 160.90446666666668 , 5).attr({
title: "Point",
fill: "red",
stroke: "#fff",
"stroke-width": 2
});
set.push(dot);
for(var i = 0; i < set.length; i++){
var element = set[i];
element.click(click);
}
// var world = r.setFinish();
// world.click(click);
I had a similar problem in Firefox, although what I was doing was completely different.
The way I solved it was to prevent the event from firing twice in too short of an interval.
I would use this function:
function rateLimit(func) {
var lastcall = func.lastcall || 0,
now = new Date().getTime();
if( now-lastcall < 250) return false;
func.lastcall = now;
return true;
}
Then in the function I want to limit from firing too often, I can do this:
if( !rateLimit(arguments.callee)) return false;
However, you might have a small issue if you are using alert(), since that will completely block execution and the second run will still fire. I would strongly suggest using console.log() instead of alert() to keep track of values, as this will avoid interrupting the flow of the program (especially when you get into asynchronous stuff, you can get real mysteries if you stop things with an alert)
Hope this helps!
In creating a svg map using raphael js where I have hover states. How ever I am trying to write the country names onto the map. The problem I am facing is the names become their own object and block the country so I loose hover and click when the cursor is directly over the text. Is there a way where I can draw the text and not have it block the map. I've tried set() but with no sucess.
Thanks,
What I have below doesn't have the text() or print() included:
var r = Raphael('map', 1450, 2180);
arr = new Array();
for (var country in paths) {
var obj = r.path(paths[country].path);
countryName = paths[country].name;
color = paths[country].color;
scolor = paths[country].stroke;
obj.attr({fill:color,stroke:scolor,
'stroke-width': 1,
'stroke-linejoin': 'round'});
arr[obj.id] = country;
obj
.hover(function(){
console.log(arr[this.id]);
this.animate({
fill: paths[arr[this.id]].hover
}, 300);
}, function(){
this.animate({
fill: paths[arr[this.id]].color
}, 300);
})
});
Try setting the pointer-events attribute to none for the text elements.
Documentation:
http://www.w3.org/TR/SVG/interact.html#PointerEventsProperty