Dygraphs: Highlight specific point on mouse over - javascript

Is there a way to highlight a specific point when mouse is over or near that specific point ? The thing is that I don't want to highlight all the lines but only the point(s) under or near my cursor. My goal is to show a tooltip at that position with the informations for that point.
This ChartJs example demonstrate pretty well what I would like to do:
http://www.chartjs.org/samples/latest/scales/time/line.html
And these are my current options:
{
drawPoints: true,
showRoller: false,
highlightCircleSize: 5,
labels: ['Time', 'Vac', 'Temp'],
ylabel: 'Vaccum (In/Hg)',
y2label: 'Temperature ('+ TemperatureUnitFactory.getTemperatureUnit() + ')',
series : {
'Vac': {
axis: 'y'
},
'Temp': {
axis: 'y2'
}
},
axes: {
y: {
drawGrid: true,
independentTicks: true,
valueRange: [0, -32],
label: 'Vaccum'
},
y2: {
drawGrid: false,
independentTicks: true,
valueRange: [
TemperatureUnitFactory.getTemperatureForUnit(-30),
TemperatureUnitFactory.getTemperatureForUnit(35)
],
ylabel: 'Temperature'
}
}
}
If you feel like I am missing informations that would help you enlighting me, just let me know in a comment.
Thank you all!

So here's a snippet for the solution to my problem. I believe it could be optimized by throtling the mousemouve callback, but in my case it did just fine. I converted the snippet from angular to jQuery for "simplicity".
var data = [
[new Date(20070101),62,39],
[new Date(20070102),62,44],
[new Date(20070103),62,42],
[new Date(20070104),57,45],
[new Date(20070105),54,44],
[new Date(20070106),55,36],
[new Date(20070107),62,45],
[new Date(20070108),66,48],
[new Date(20070109),63,39],
[new Date(20070110),57,37],
[new Date(20070111),50,37],
[new Date(20070112),48,35],
];
var graph = new Dygraph(
document.getElementById("chart"), data, {
rollPeriod: 1,
labels: ['Time', 'Vac', 'Temp'],
showRoller: false,
drawPoints: true,
}
);
var tooltip = {
element: $('#tooltip'),
x: function(_x){
this.element.css('left', _x);
},
y: function(_y) {
this.element.css('top', _y);
},
shown: false,
throttle: null,
currentPointData: null,
show: function() {
if(!this.shown) {
this.element.show();
this.shown = true;
}
},
hide: function() {
this.cancelThrottle();
if(this.shown) {
this.element.hide();
this.shown = false;
}
},
cancelThrottle: function () {
if(this.throttle !== null) {
clearTimeout(this.throttle);
this.throttle = null;
}
},
bindPoint: function (_point) {
this.element.html([_point.point.name,_point.point.xval, _point.point.yval].join(' | '))
console.log('Handle point data', _point);
}
};
var chartElement = $('#chart');
var isMouseDown = false;
chartElement.on('mousedown', function(){ isMouseDown = true; });
chartElement.on('mouseup', function(){ isMouseDown = false; });
chartElement.on('mousemove', function(){
if(graph === null) { return; }
if(isMouseDown) {
tooltip.hide();
return;
}
const ACCEPTABLE_OFFSET_RANGE = 8;
const TOOLTIP_BOTTOM_OFFSET = 25;
const TOOLTIP_THROTTLE_DELAY = 600;
var graphPos = Dygraph.findPos(graph.graphDiv),
canvasX = Dygraph.pageX(event) - graphPos.x,
canvasY = Dygraph.pageY(event) - graphPos.y,
rows = graph.numRows(),
cols = graph.numColumns(),
axes = graph.numAxes(),
diffX, diffY, xPos, yPos, inputTime, row, col, axe;
for (row = 0; row < rows; row++)
{
inputTime = graph.getValue(row, 0);
xPos = graph.toDomCoords(inputTime, null)[0];
diffX = Math.abs(canvasX - xPos);
if (diffX < ACCEPTABLE_OFFSET_RANGE)
{
for (col = 1; col < cols; col++)
{
var inputValue = graph.getValue(row, col);
if (inputValue === null) { continue; }
for(axe = 0; axe < axes; axe++)
{
yPos = graph.toDomCoords(null, inputValue, axe)[1];
diffY = Math.abs(canvasY - yPos);
if (diffY < ACCEPTABLE_OFFSET_RANGE)
{
tooltip.cancelThrottle();
if(!tooltip.shown)
{
var self = this;
tooltip.throttle = setTimeout(function () {
var ttHeight = tooltip.element.height(),
ttWidth = tooltip.element.width();
tooltip.x((xPos - (ttWidth / 2)));
tooltip.y((yPos - (ttHeight + TOOLTIP_BOTTOM_OFFSET)));
tooltip.show();
var closestPoint = graph.findClosestPoint(xPos, yPos);
if(closestPoint) {
tooltip.bindPoint(closestPoint);
}
}, TOOLTIP_THROTTLE_DELAY);
}
return;
}
}
}
}
}
tooltip.hide();
});
.chart-container {
position:relative;
}
.chart-container > .tooltip {
position:absolute;
padding: 10px 10px;
background-color:#ababab;
color:#fff;
display:none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dygraph/2.1.0/dygraph.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chart-container">
<div id="chart"></div>
<div id="tooltip" class="tooltip">
Some data to be shown
</div>
</div>

Related

new dataset is not accepted by chartj template

I am trying to plot a line chart on the node red dashboard.
This template creates the desired scrollable chart with 100 randomly generated datapoints:
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(x);
}
return chartLabels;
}
function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}
function addData(numData, chart) {
for (var i = 0; i < numData; i++) {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
var chartData = {
labels: generateLabels(),
datasets: [{
label: "Test Data Set",
data: generateData(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
maintainAspectRatio: false,
responsive: true,
});
addData(5, chartTest);
});
});
</script>
Next I wanted to replace the generated datapoints with a payload message coming into the dashboard template node, where msg.payload[0].data is an array[2500].
I thought I would be able to achieve this by replacing generateData()like so:
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(x);
}
return chartLabels;
}
/*function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}*/
function generateData(msg) {
var chartData = [];
chartData = msg.payload[0].data;
return chartData;
}
function addData(numData, chart) {
for (var i = 0; i < numData; i++) {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
var chartData = {
labels: generateLabels(),
datasets: [{
label: "Test Data Set",
data: generateData(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
responsive: true,
options: {
maintainAspectRatio: false,
tooltips: {
titleFontSize: 0,
titleMarginBottom: 0,
bodyFontSize: 12
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
fontSize: 12,
display: false
}
}],
yAxes: [{
ticks: {
fontSize: 12,
beginAtZero: true
}
}]
},
}
});
addData(5, chartTest);
});
});
</script>
But then the chart is just showing a blank:
Why is that?
[edit]
the incoming payload is not empty:
I would try the follwing:
1.- Check that your array[2500] has values between 1 and 100 and pass in the first 100 instead the whole 2500 array to check if that works
2.- Might depend on the chartjs version, but I would try to put the maintainAspectRatio property inside an options: {} object. See below.
var chart = new Chart('blabla', {
type: 'bar',
data: {},
options: {
maintainAspectRatio: false,
}
});
Apart from that, 2500 records seems to be a too big amount of data to handle. If the graph renders for smaller amounts, I would try to keep the graph drawn with an amount that gets rendered, and the fetch the data + update the chart depending on the users x-scroll.
Edit:
I think you need to call the addData for your new array with a modified addData function that would look something like this, for the width to fit.
function addData(chart) {
for (var i = 0; i < chart.data[0].data.length; i++) {
//chart.data.datasets[0].data.push(Math.random() * 100);
//chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
Note that your script work up determined num of records with the arrangements mentioned, so if the graph goes blank can only be that your new array is empty or has some issue.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: auto;
overflow-x: scroll;
}
</style>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="300" width="1200"></canvas>
</div>
</div>
<canvas id="axis-Test" height="300" width="0"></canvas>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="351" width="4000"></canvas>
</div>
</div>
<canvas id="axis-Test" height="351" width="0"></canvas>
</div>
<script>
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push(x);
}
return chartLabels;
}
function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}
function addData(numData, chart) {
for (var i = 0; i < numData; i++) {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
var chartData = {
labels: generateLabels(),
datasets: [{
label: "Test Data Set",
data: generateData(),
pointRadius: 0,
borderColor: "#4ED7FC",
borderWidth: 2,
fill: false
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'line',
data: chartData,
options: {
maintainAspectRatio: false,
responsive: true
}
});
addData(300, chartTest);
});
});
</script>
I found out that the dashboard template node does not easily accept payload messages on the script section.
watch function
I have to use something like:
// Watch the payload and update
(function(scope) {
scope.$watch('msg.payload', function(data) {
update(data);
});
})(scope);
function update(dta) {
theScope.send({payload:dta});
bleh = dta.name;
otherStuff();
}
to watch a incoming payload and store it.
My initial question "Why is that?" is therefore answered.
Unfortunately I am not quite sure how to implement this new bit of code to the array coming in in msg.payload[0.data in my specific case.

Make y-axis sticky when having horizontal scroll on chartJS and Angular

I would like to fix y-axis position when scrolling horizontally.
Here's an example that works but without using Angular
$(document).ready(function () {
function generateLabels() {
var chartLabels = [];
for (x = 0; x < 100; x++) {
chartLabels.push("Label" + x);
}
return chartLabels;
}
function generateData() {
var chartData = [];
for (x = 0; x < 100; x++) {
chartData.push(Math.floor((Math.random() * 100) + 1));
}
return chartData;
}
function addData(numData, chart) {
for (var i = 0; i < numData; i++) {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.labels.push("Label" + i);
var newwidth = $('.chartAreaWrapper2').width() + 60;
$('.chartAreaWrapper2').width(newwidth);
}
}
var chartData = {
labels: generateLabels(),
datasets: [{
label: "Test Data Set",
data: generateData()
}]
};
$(function () {
var rectangleSet = false;
var canvasTest = $('#chart-Test');
var chartTest = new Chart(canvasTest, {
type: 'bar',
data: chartData,
maintainAspectRatio: false,
responsive: true,
options: {
tooltips: {
titleFontSize: 0,
titleMarginBottom: 0,
bodyFontSize: 12
},
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
fontSize: 12,
display: false
}
}],
yAxes: [{
ticks: {
fontSize: 12,
beginAtZero: true
}
}]
},
animation: {
onComplete: function () {
if (!rectangleSet) {
var sourceCanvas = chartTest.chart.canvas;
var copyWidth = chartTest.scales['y-axis-0'].width;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;
var targetCtx = document.getElementById("axis-Test").getContext("2d");
targetCtx.canvas.width = copyWidth;
targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
var sourceCtx = sourceCanvas.getContext('2d');
sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
rectangleSet = true;
}
},
onProgress: function () {
if (rectangleSet === true) {
var copyWidth = chartTest.scales['y-axis-0'].width;
var copyHeight = chartTest.scales['y-axis-0'].height + chartTest.scales['y-axis-0'].top + 10;
var sourceCtx = chartTest.chart.canvas.getContext('2d');
sourceCtx.clearRect(0, 0, copyWidth, copyHeight);
}
}
}
}
});
addData(5, chartTest);
});
});
.chartWrapper {
position: relative;
}
.chartWrapper > canvas {
position: absolute;
left: 0;
top: 0;
pointer-events: none;
}
.chartAreaWrapper {
width: 600px;
overflow-x: scroll;
}
<script src="https://github.com/chartjs/Chart.js/releases/download/v2.6.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chartWrapper">
<div class="chartAreaWrapper">
<div class="chartAreaWrapper2">
<canvas id="chart-Test" height="300" width="1200"></canvas>
</div>
</div>
<canvas id="axis-Test" height="300" width="0"></canvas>
</div>
When I use this in my angular example , it does not work anymore, the axis does not follow the scroll
Here's a stackblitz reproduction
In your StackBlitz, the section (rectanlge) of the y-axis is correctly created on the target canvas and removed from the source canvas. The problem is that the wrong div is horizontally scrolled. This can be fixed by changing the template and corresponding css.
Please have a look at the following StackBlitz.
UPDATE (dynamic data)
In cases where the chart component receives dynamically changing data through an #Input() property, your component needs to implement the OnChange lifecycle hook.
See the following StackBlitz.
Please note that this code is far from being optimized. Instead of creating the chart from scratch on every data change, you should simply update the data and options on the existing chart.

plotly.js how to change z data on hover to display % as well as % on colorscale

I would like to add a % tag to the z value that is show on hover. Also, right now, my colorscale is only displaying -10 to 10, but I would like it to show % so -10% to 10%. Here is the code I have.
I have tried to add the ticksuffix : "%", but I'm not sure where I should put it since it seems like the colorscale is not an axis like the x and y axis.
var xValues = ['A', 'B', 'C',];
var yValues = ['W', 'X', 'Y', 'Z'];
var zValues = [[-2.45,-0.4,1.3],
[2.9,3.9,-5.66],
[0.5,-2.6,-3.2],
[-8.3,-0.5,-0.1]];
var a_text = [["Comodities + producers","Consumer Discretionary","Utilities Equities"],
["Health and Biotech","Global Real Estate","Financial Equities"],
["Emerging Market Bonds","Technology Equities","Industrials Equities"],
["Oil and Gas","China Equities","Diversified Portfolio"]];
var data = [{
x: xValues,
y: yValues,
z: zValues,
hoverinfo: "z",
reversescale: true,
type: 'heatmap',
// zsmooth: "best",
colorscale: "Spectral",
zauto: false,
zmin:-10,
zmax:10,
showscale: true,
}];
var layout = {
title: 'Annotated Heatmap',
annotations: [],
xaxis: {
ticks: '',
side: 'top',
tickfont: {color: 'rgb(255,255,255)'}
},
yaxis: {
ticks: '',
ticksuffix: ' ',
width: 700,
height: 700,
autosize: true,
tickfont: {color: 'rgb(255,255,255)'},
}
};
for ( var i = 0; i < yValues.length; i++ ) {
for ( var j = 0; j < xValues.length; j++ ) {
var currentValue = (zValues[i][j]);
if (currentValue < -0.05) {
var textColor = 'white';
}else{
var textColor = 'black';
}
var result = {
xref: 'x1',
yref: 'y1',
x: xValues[j],
y: yValues[i],
text: a_text[i][j],
font: {
family: 'Arial',
size: 12,
color: 'rgb(50, 171, 96)'
},
showarrow: false,
font: {
color: textColor
}
};
layout.annotations.push(result);
}
}
Plotly.newPlot('myDiv', data, layout);
You need to change two things, the color bar and the hover text.
Color bar
Add this info to your variable data.
colorbar: {
title: 'Relative change',
ticksuffix: '%',
}
Hover text
First convert the z-values into strings and append %.
var zText = [];
var prefix = "+";
var i = 0;
var j = 0;
for (i = 0; i < zValues.length; i += 1) {
zText.push([]);
for (j = 0; j < zValues[i].length; j += 1) {
if (zValues[i][j] > 0) {
prefix = "+";
} else {
prefix = "";
}
zText[i].push(prefix + zValues[i][j] + "%");
}
}
Then assign the new text to the plot.
Add
text: zText,
hoverinfo: "text",
to your variable data.
Here is a fiddle with the complete data and code: https://jsfiddle.net/Ashafix/e6936boq/2/

jQuery flot hover not working when user moves down the page

I am using jQuery flot. I can't seem to explain the bug well. But by the looks of it, the hover does not work when the user moves down to the page: Here's the video:
http://screencast.com/t/qZIjJ8jsi
Notice when i'm on top of my page the hover is working, but when I'll go down the page, then the hover on the points won't work.
My page is responsive(not sure if that's related, but just saying). Looks like this is a CSS problem. So here's my code:
var graphData = decodeURIComponent(jQuery("#graphData").val());
graphData = jQuery.parseJSON(graphData);
var visitors = new Array();
var totalVisitors = 0;
jQuery.each(graphData,function(index,value){
visitors[index] = [value[0],value[1]];
totalVisitors = totalVisitors + parseInt(value[1]);
});
jQuery(".date-figures").text(totalVisitors);
var visitor = $("#activeUsers"),
data_visitor = [{
data: visitors,
color: '#058DC7'
}],
options_lines = {
series: {
lines: {
show: true,
fill: true,
fillColor: "#E5F3F9",
color:"#058DC7",
},
points: {
show: true
},
hoverable: true
},
grid: {
backgroundColor: '#FFFFFF',
borderWidth: 0,
borderColor: '#CDCDCD',
hoverable: true
},
legend: {
show: true
},
xaxis: {
mode: "time",
},
yaxis: {
show:true
},
};
$.plot(visitor, data_visitor, options_lines);
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css({
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
padding: '2px 10px 2px 10px',
opacity: 0.8,
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$('#visitor-stat, #order-stat, #user-stat,#activeUsers').bind("plothover", function (event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var d = new Date(item.datapoint[0]);
var day = parseDay(d.getDay());
var date = d.getDate();
var month = parseMonth(d.getMonth());
var year = d.getFullYear();
var tooltipWording = "<b>"+day+", "+month+" "+date+", "+year+"</b>";
tooltipWording += "<ul>";
tooltipWording += "<li>Visits: <b>"+item.datapoint[1]+"</b></li>";
tooltipWording += "</ul>";
showTooltip(item.pageX, item.pageY, tooltipWording);
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
});
});
What seems to be problem here? Your help will be greatly appreciated! Thanks! :)

Update data in matrix of cells

This code implements a 60 cell spreadsheet, 6x10 rows,columns. At the end of each row are two labels, one for row total and for running total. The main issue here is how to update the row and running total labels when the calc button is pressed.
I would also like to move the button from the bottom of the scrollview to the bottom of the window where it's always visible. Another view for buttons at the bottom?
Ti.include("toast.js"); // 3rd-party code; displays notifications
var i=0;
var r=0;
var rows = 10;
var columns = 6;
left = ["0%","12%","24%","36%","48%","60%"];
Titanium.UI.setBackgroundColor('#000');
var win1 = Titanium.UI.createWindow({
title:'Target 1',
exitOnClose: true,
backgroundColor:'#fff'
});
win1.addEventListener('androidback' , function(e){
win1.close();
var activity = Titanium.Android.currentActivity;
activity.finish();
});
var scrollView1 = Ti.UI.createScrollView({
bottom:120,
contentHeight: 'auto',
layout: 'vertical'
});
if (Ti.UI.Android){
win1.windowSoftInputMode = Ti.UI.Android.SOFT_INPUT_ADJUST_PAN;
}
var buttonCalc = Titanium.UI.createButton({
title: 'Calc',
top: 10,
width: 100,
height: 50,
left: "10%"
});
var lbAttrs1 = {
text: "000",
left: "74%",
color:'#000',width:'auto',height:'auto',textAlign:'left',
font:{fontSize:24,fontWeight:'regular'}
};
var lbAttrs2 = {
text: "000",
left: "88%",
color:'#000',width:'auto',height:'auto',textAlign:'left',
font:{fontSize:24,fontWeight:'regular'}
};
var baseAttrs = {
borderStyle : Titanium.UI.INPUT_BORDERSTYLE_ROUNDED,
keyboardType: Titanium.UI.KEYBOARD_NUMBERS_PUNCTUATION,
maxLength: 2,
top: 10,
height: 60,
value: "",
width: '12%',
color : '#000000'
};
var tfields = [];
var labels1 = [];
var labels2 = [];
buttonCalc.addEventListener('click',function(e)
{
var a = 0;
var b = 0;
for (j=0;j<rows;j++)
{
a = 0;
for (i=0;i<columns;i++)
a = parseInt(tfields[j][i].value) + a;
b = b + a;
labels1[j] = a.toString();
labels2[j] = b.toString();
}
for (j=0;j<rows;j++)
alert( labels1[j]+' '+labels2[j]+ ' ' + j.toString());
});
function createRow1(i) // start create row
{
row1 = Ti.UI.createView({
backgroundColor: 'white',
borderColor: '#bbb',
borderWidth: 1,
width:'100%', height: 70,
top: 0, left: 0 });
var tfield1 = [];
var label1 = [];
var label2 = [];
for (i=0;i<columns;i++)
{
tfield1[i] = Ti.UI.createTextField(baseAttrs);
label1[i] = Ti.UI.createLabel(lbAttrs1);
label2[i] = Ti.UI.createLabel(lbAttrs2);
}
tfield1[0].addEventListener('change', function()
{
if (tfield1[0].value > 10)
{
tfield1[0].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[1].addEventListener('change', function()
{
if (tfield1[1].value > 10)
{
tfield1[1].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[2].addEventListener('change', function()
{
if (tfield1[2].value > 10)
{
tfield1[2].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[3].addEventListener('change', function()
{
if (tfield1[3].value > 10)
{
tfield1[3].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[4].addEventListener('change', function()
{
if (tfield1[4].value > 10)
{
tfield1[4].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[5].addEventListener('change', function()
{
if (tfield1[5].value > 10)
{
tfield1[5].value = "";
showMessageTimeout("More than 10.",15);
}
});
tfield1[0].left = left[0];
tfield1[1].left = left[1];
tfield1[2].left = left[2];
tfield1[3].left = left[3];
tfield1[4].left = left[4];
tfield1[5].left = left[5];
for (i=0;i<columns;i++)
{
row1.add(tfield1[i]);
row1.add(label1[i]);
row1.add(label2[i]);
}
;
tfields.push(tfield1);
labels1.push(label1);
labels2.push(label2);
return row1;
} /// end of createrow1
for(i = 0; i < rows; i++){
row1 = createRow1(i);
scrollView1.add(row1);
}
win1.add(scrollView1);
scrollView1.add(buttonCalc);
// win1.add(buttonCalc);
win1.open();
Point 1.
That is a typo, you should substitute each occurrence of labels1[j] and labels2[j] to labels1[j].text and labels2[j].text respectively:
buttonCalc.addEventListener('click',function(e)
{
var a = 0;
var b = 0;
for (j=0;j<rows;j++)
{
a = 0;
for (i=0;i<columns;i++){
var newValue = parseInt(tfields[j][i].value);
if(!isNaN(newValue) && typeof(newValue) === 'number')
a = newValue + a;
}
b = b + a;
labels1[j].text = a.toString();
labels2[j].text = b.toString();
}
for (j=0;j<rows;j++)
Ti.API.info( labels1[j].text +' '+labels2[j].text + ' ' + j.toString());
});
And also it must be changed these parts:
function createRow1(i) // start create row
{
...
for (i=0;i<columns;i++)
{
tfield1[i] = Ti.UI.createTextField(baseAttrs);
}
label1 = Ti.UI.createLabel(lbAttrs1); //there is only one per row
label2 = Ti.UI.createLabel(lbAttrs2); //there is only one per row
...
for (i=0;i<columns;i++)
{
row1.add(tfield1[i]);
}
row1.add(label1); //there is only one per row
row1.add(label2); //there is only one per row
tfields.push(tfield1);
labels1.push(label1);
labels2.push(label2);
return row1;
} /// end of createrow1
Point 2.
you can do it this way:
var scrollView1 = Ti.UI.createScrollView({
top:0,
height:'60%', //Put your desired value here
contentHeight: 'auto',
layout: 'vertical'
});
...
var buttonCalc = Titanium.UI.createButton({
title: 'Calc',
top: '70%', // Put your desired value here greater than scrollView1.height
width: 100,
height: 50,
left: "10%"
});
...
win1.add(scrollView1);
//scrollView1.add(buttonCalc);
win1.add(buttonCalc);
Extra point.
you need to set softKeyboardOnFocus property in your baseAttrs:
var baseAttrs = {
borderStyle : Titanium.UI.INPUT_BORDERSTYLE_ROUNDED,
keyboardType: Titanium.UI.KEYBOARD_NUMBERS_PUNCTUATION,
softKeyboardOnFocus: Titanium.UI.Android.SOFT_KEYBOARD_SHOW_ON_FOCUS,
maxLength: 2,
top: 10,
height: 60,
value: "",
width: '12%',
color : '#000000'
};
this way, softKeyboard will be shown on focus the first time.
Finally, good luck with your app :-)

Categories

Resources