dojox.calendar and JsonRest - how to update? - json

I'm very new to dojo, so please bear with me. I'm currently working on creating a dojo calendar, with events sourced from a database. The calendar defaults to the grid (monthly) view, and on load, makes an initial call to get the first set of events. The default view makes a call to get the current months events +/- one week. I'm using a JsonRest object in an Observable to accomplish this.
This is currently working without issue. Where I'm having an issue is pulling / updating data for other months. The desired effect is to have the user click the forward or back button to move to the next or previous month. When this occurs, I would like to query the database for the new events to display. I'm able to return the new data and log it to the console, but I cannot get it to display on the calendar. I'm sure I'm missing something (hopefully) simple, but I cant figure it out, or find any good documentation. Here's what I have:
require(['dojo/parser',
'dojo/ready',
'dojox/calendar/Calendar',
'dojo/store/Observable',
'dojo/store/JsonRest',
'dijit/registry'],
function(parser, ready, Calendar, Observable, JsonRest, registry) {
ready(function(){
var MM = new Date().getMonth() + 1;
if (MM < 10)
{ MM = '0' + MM};
var YYYY = new Date().getFullYear();
var monthStore = new Observable(JsonRest({target: '/levelx/teamSchedule/getMonthInfo/'}));
calendar = new Calendar({
store: monthStore,
dateInterval: 'month',
style: styleText,
editable: false,
cssClassFunc: function(e){
return e.calendar;
},
query: '?q=' + YYYY + '-' + MM
}, 'calendar');
calendar.on("timeIntervalChange",function(e){
var YYYY = e.startTime.getFullYear();
var MM = e.startTime.getMonth() + 1;
if (MM < 10)
{ MM = '0' + MM};
monthStore.query('?q=' + YYYY + '-' + MM).then(function(results){
console.log(results);
});
});
I feel like I'm so close. Like I said, I have the correct data being returned to the console (console.log(results)), but no clue how to get it to show in the actual calendar.

I was able to accomplish what I needed with the following modifications. Whenever the user changes the displayed date range, it will automatically run a query to gather and display the proper events.
require(['dojo/parser',
'dojo/ready',
'dojox/calendar/Calendar',
'dojo/store/JsonRest',
'dijit/registry',
'dojo/dom',
'dojo/html'],
function(parser, ready, Calendar, JsonRest, registry, dom, html) {
ready(function(){
var MM = new Date().getMonth() + 1;
if (MM < 10)
{ MM = '0' + MM};
var YYYY = new Date().getFullYear();
var detailStore = JsonRest({target: '/levelx/teamSchedule/getDayInfo/'});
var monthStore = JsonRest({target: '/levelx/teamSchedule/getMonthInfo/'});
calendar = new Calendar({
dateInterval: 'month',
style: styleText,
editable: false,
cssClassFunc: function(e){
return e.calendar;
}
}, 'calendar');
calendar.on("timeIntervalChange",function(e){
var YYYY = e.startTime.getFullYear();
var MM = e.startTime.getMonth() + 1;
if (MM < 10)
{ MM = '0' + MM};
calendar.set('query','?q=' + YYYY + '-' + MM);
calendar.set('store', monthStore);
});
});
});

Try changing the interval-change function so that query is set via Calendar object and not directly onto the store.
calendar.on("timeIntervalChange",function(e){
var YYYY = e.startTime.getFullYear();
var MM = e.startTime.getMonth() + 1;
if (MM < 10)
{ MM = '0' + MM};
// this
this.query('?q=' + YYYY + '-' + MM).then(function(results){
console.log(results);
});
});
Have never used the calendar just yet, so its a guess tbh.. But it looks like there's an initial query to be set in the calendar properties, and that this should reflect in the dojo.store.api. The calendar itself most likely does not observe correctly and then in turn does not render when new data arrives.

Related

How to put data from Google Sheets to Timeline in web app [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
I want to make a TimeLine chart based on data in the "TimeLineData" sheet. Those data will change sometimes so I want to make it dynamic. I am not sure if you can achieve it using regular charts so I have tried with script that I found in google documentation and then got help from #WhiteHat.
In the data sheet Column D and E are not necessary for this project. Only the colored columns.
As you can see on the picture I want to group orders by machines and to see time left to the end of production. Column F is showing how much time left in minutes. I also added extra cell for a start date H2 and I2.
From the left should be orders with the closest "Out for Delivery" date
So my problem is:
how to move data to the left? As you can see on the picture above. I want to make the same start point for all first values in a row and then add next time value. I've tried 'promise()' but coudn't make it.
This is what I am getting now:
Any advice will be helpful!
Let me know if something is unclear
The code provided by #WhiteHat:
// load google charts
google.charts.load('current', {
packages:['timeline']
}).then(function () {
// get ss data
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
});
// get data table column index by column label
function getColumnIndex(label, dataTable) {
// loop columns until column label is found
for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
if (label === dataTable.getColumnLabel(i)) {
return i;
}
}
// label not found
return -1;
}
});
to get the data to the page for use by the chart,
we can use the Query class.
append the query settings and sheetname to the end of the spreadsheet url...
/gviz/tq?gid=0&headers=1&sheet=TimelineData
use the query class to get the data and wait for the response.
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1SaGo-yA6YPP-Um68Sgm8H3yMyfqXclDQWl5_l4cxgs4/gviz/tq?gid=0&headers=1&sheet=TimelineData');
query.send(function (response) {
// build data table - ss
var dataSS = response.getDataTable();
...
then we need to process each row in order to build the start and end dates for each process.
first, sort the spreadsheet data...
// sort by machine, delivery date, order #
dataSS.sort([{
column: getColumnIndex('Machine', dataSS)
}, {
column: getColumnIndex('Out for Delivery', dataSS)
}, {
column: getColumnIndex('Order NO', dataSS)
}]);
then build the data table for the timeline...
// build data table - timeline
var dataTimeline = new google.visualization.DataTable();
dataTimeline.addColumn('string', 'Machine');
dataTimeline.addColumn('string', 'Order NO');
dataTimeline.addColumn('date', 'Start');
dataTimeline.addColumn('date', 'End');
then we need to get the overall start date and time.
we can use data table method --> getColumnRange(columnIndex)
this will return the min & max values for the column we specify.
in this case, we'll use the min value.
// get overall start date & time
var startDate = dataSS.getColumnRange(getColumnIndex('start date', dataSS)).min;
var startTime = dataSS.getColumnRange(getColumnIndex('start time', dataSS)).min;
then we remove any time portion from the start date.
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate());
the format of the start time column will be timeofday
it will be an array of four numbers --> [hours, minutes, seconds, milliseconds]
we then add the start time to the start date.
startTime.forEach(function (timeSegment, index) {
// determine time segment
var milliseconds;
switch (index) {
// hours
case 0:
milliseconds = 1000 * 60 * 60 * timeSegment;
break;
// minutes
case 1:
milliseconds = 1000 * 60 * timeSegment;
break;
// seconds
case 2:
milliseconds = 1000 * timeSegment;
break;
// milliseconds
case 3:
milliseconds = timeSegment;
break;
}
// add milliseconds to start date
startDate = new Date(startDate.getTime() + milliseconds);
});
then we process the rows from the spreadsheet.
first, calculate the minutes processed for the row and calculate the end date.
add the data table row for the timeline.
finally, determine if 8 hours has passed.
if so, move to next week day, otherwise, use the end date for the next start date.
// process rows
var endDate;
var minutesProcess;
var minutesTotal = 0;
for (var row = 0; row < dataSS.getNumberOfRows(); row++) {
// calculate minutes processed and end date
minutesProcess = dataSS.getValue(row, getColumnIndex('Production Time Left', dataSS));
minutesTotal += minutesProcess;
endDate = new Date(startDate.getTime() + (1000 * 60 * minutesProcess));
// add row
dataTimeline.addRow([
dataSS.getValue(row, getColumnIndex('Machine', dataSS)),
dataSS.getValue(row, getColumnIndex('Order NO', dataSS)),
startDate,
endDate
]);
// determine if 8 hours has passed
if ((minutesTotal / 60) >= 8) {
// increment day until not the weekend
do {
startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() + 1, 8);
} while ((startDate.getDate() === 0) || (startDate.getDate() === 6));
} else {
startDate = endDate;
}
}
calculate the chart height, and draw the chart...
// determine chart height
var rowHeight = 42;
var options = {
height: (dataTimeline.getNumberOfRows() * rowHeight) + rowHeight
};
// draw chart
var chart = new google.visualization.Timeline(document.getElementById('timeline'));
chart.draw(dataTimeline, options);
window.addEventListener('resize', function () {
chart.draw(dataTimeline, options);
});
see following fiddle for a working example...
https://jsfiddle.net/WhiteHat/cthqur2o/10/
Note: the chart will fill the width of the screen by default,
you may need to increase the width in the options

How would I check for a proper custom input of mm/dd/yyyy in actionscript 3?

I have a DataField with editable="true" and format mm/dd/yyyy. Then lets say user typed in month mm section 13 which is not correct. How can I validate it as well as dd section and yyyy section and show a pop up when it's incorrect?
Here is what happening when apply button was clicked:
var newDate:Date = dfDate.selectedDate;
var month:String = (newDate.month + 1) < 10 ? "0" + (newDate.month + 1).toString() : (newDate.month + 1).toString();
var date:String = newDate.date < 10 ? "0" + newDate.date.toString() : newDate.date.toString();
var year:Number = newDate.getFullYear();
var dateString:String = month + "/" + date + "/" + year;
Button section:
<mx:FormItem id="itemDate">
<mx:DateField id="dfDate" yearNavigationEnabled="true" editable="true"/>
</mx:FormItem>
You can use just a simple regular expression
var customRegExp:RegExp = new RegExp(/(0[1-9]|1[012])[\/](0[1-9]|[12][0-9]|3[01])[\/](19|20)\d\d/);
And then use .test function along with some formatting stuff
var fmt:DateFormatter = new DateFormatter();
fmt.formatString = "MM/DD/YYYY";
if(!customRegExp.test(fmt.format(dfDate.selectedDate)))
{
Alert.show("Please input date in format MM/DD/YYYY");
enableForm(true);
}
Worked for me just fine and I think will work for others as well!
Here is code all together:
var customRegExp:RegExp = new RegExp(/(0[1-9]|1[012])[\/](0[1-9]|[12][0-9]|3[01])[\/](19|20)\d\d/);
var fmt:DateFormatter = new DateFormatter();
fmt.formatString = "MM/DD/YYYY";
if(!customRegExp.test(fmt.format(dfDate.selectedDate)))
{
Alert.show("Please input date in format MM/DD/YYYY");
enableForm(true);
}

HTML - Time Input with up to 100 minutes

Is there any way to manipulate the html time input, so I can add up to 100 Minutes and 59 seconds?
No. Time input is for time. Your clock is more than 60 minutes?
Another way is to write custom input field with JavaScript. Or add number input field and then with JavaScript calculate hours/minutes/seconds ...
Edit: After re-reading the original post, I'm pretty sure I'm answering the wrong question here. But I'll leave it in case someone else finds it useful.
If you're referring to <input type="time">, you can access and modify the value like a normal input element:
var time = document.getElementById('time');
var button = document.getElementById('button');
function handleButtonClick() {
var parts = time.value.split(':');
var hour = parseInt(parts[0]);
var minute = parseInt(parts[1]);
hour += 1;
minute += 7;
// TODO: Need to validate the new time
time.value = hour + ':' + minute;
}
button.addEventListener('click', handleButtonClick, false);
<input id="time" type="time">
<button id="button">Process</button>
You can use Jquery for this:
function addMinutes(time, minsToAdd) {
function D(J){ return (J<10? '0':'') + J;};
var piece = time.split(':');
var mins = piece[0]*60 + +piece[1] + +minsToAdd;
return D(mins%(24*60)/60 | 0) + ':' + D(mins%60);
}
$("#add").click(function(){
var time = $("#time").val();
var new_time = addMinutes(time, '100');
alert(new_time);
});
Working DEMO

Google Maps and Fusion Tables

A map I created last year using Google Maps API V3 and Fusion Tables V1 has stopped functioning properly in the last week or so. I am not sure if I missed an update that has deprecated my code or if there's another explanation. In brief, the following code queries my fusion table and if a match is found it returns data for an info window. However, it is now returning false every time. The addInfoWindow() function is firing fine. The issue appears to be either in the query itself or the data that's returned. Additionally, the pin is dropping in the correct location on the map so the coordinates are not the issue.
This issue can be replicated by entering an address in the field. For demonstration purposes, 9132 Kingston Pike 37923 should return true. Clicking inside any polygon will return the intended results.
Thank you for any guidance you can provide.
// query
var script = document.createElement('script');
var url = ['https://www.googleapis.com/fusiontables/v1/query?'];
url.push('sql=');
var query = "SELECT * FROM " +
tableid + " WHERE ST_INTERSECTS(geometry, CIRCLE(LATLNG(" + coordinate.lat() + "," + coordinate.lng() + "), 0.001))";
var encodedQuery = encodeURIComponent(query);
url.push(encodedQuery);
url.push('&callback=addInfoWindow');
url.push('&key=' + apiKey);
script.src = url.join('');
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
// call back function
function addInfoWindow(data) {
infowindow.close();
initialize();
var rows = data['rows'];
if (rows)
{
console.log("inside if statement");
for (var i = 0; i < 1; i++)
{
console.log("inside for loop: " + rows[i][0]);
infowindow.setContent("<div style='width:250px;'><h2>"+ rows[i][1] + "</h2><p>The neighborhood contact in your area would love to hear from you! </p><p>Click <a href='https://cspctystn.infellowship.com/GroupSearch/ShowGroup/" + rows[i][0] + "' target='_blank'>here</a> to get their information.</p><p> </p><p>If you desire to communicate with Community Life staff, contact -- removed --.<p><br/><br/></div>");
//console.log(rows[i][1] + ": " + rows[i][0]);
infowindow.setPosition(coordinate);
map.setCenter(coordinate);
map.setZoom(15);
infowindow.open(map);
}
}
else
{
console.log("error");
infowindow.setContent("<div style='width:250px;'><h2>Oops!</h1><p> It seems we don't have a neighborhood contact in your area.</p><p>Please communicate with our <a href='http://www.cspc.net/communitylife' target= '_blank' >Community Life</a> staff for more information. -- removed --<p></div>");
infowindow.setPosition(coordinate);
map.setCenter(coordinate);
map.setZoom(15);
infowindow.open(map);
}
}

Run JQuery Function on Page Load and Store the Result

I've got a script that hides most of the page when you first load the webpage.
When it does this, I want it to run a function which gets the current date, then saves it.
I've having trouble getting to do this for a few reasons.
Here is the page load code, where it hides the page if it's not been setup:
$(document).ready(
function() {
if (setup=="true") {
$("#show-page").show();
loadSetup();
} else {
$("#page-nav").hide();
}
});
Here is the date function:
function getStartDate() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth();
var yyyy = today.getYear();
var startDate = dd + (mm * 30) + (yyyy * 360)
//edit
// return startDate
$("#start-date").val(startDate);
localStorage.startDate = $("#start-date").val();
}
I then want an if function in the first part of the loading page which says if the stored start date + 30 is less than the current date, show a message that gives them an updated url (isNewUrlNeeded()).
This was my attempt:
$(document).ready(
function() {
if (setup=="true") {
$("#show-page").show();
loadSetup();
isNewUrlNeeded();
} else {
$("#page-nav").hide();
getStartDate();
}
});
The problem here is that the getStartDate value isn't stored and I'm not sure how to store it. The reason it needs to be stored is so I can call on it later in the function isNewUrlNeeded.
Any help would be greatly appreciated.
Thank you!
Kind Regards,
Gary
You can try this :
function getStartDate() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth();
var yyyy = today.getYear();
var startDate = dd + (mm * 30) + (yyyy * 360)
$("#show-page").data("start-date", startDate);
}
To retrieve this date you could do the follow :
var startDate = $("#show-page").data("start-date");