I'm working on updating timestamps using Moment JS for a twitter feed clone.
When I add new tweets to the feed the timestamp of the older tweets also updates. I checked dev tools and the timestamp attribute isn't updated, so I'm not sure why it's refreshing.
var tweetMaker = function(tweet) {
var $tweet = $('<div></div>');
// Create HTML Nodes
var name = document.createElement('span');
var nameText = document.createTextNode('#' + tweet.user);
var timeStamp = document.createElement('time');
var timeStampText = document.createTextNode(moment(tweet.created_at).fromNow());
var linebreak = document.createElement('br');
var messageText = document.createTextNode(tweet.message);
// Add Classes
$tweet.addClass('tweet');
$(timeStamp).addClass('timeStamp');
$(timeStamp).attr('data-time', tweet.created_at);
$(name).addClass('name');
$(name).attr('tweetName', tweet.user);
// Build Nodes
name.appendChild(nameText);
timeStamp.appendChild(timeStampText);
$tweet.append(name, timeStamp, linebreak, messageText);
$('#tweetFeed').prepend($tweet)
}
//PROBLEM: All timestamps update with new batch of tweets
var timeUpdate = function(time) {
var timeStamp = $('.timeStamp');
var originalTime = timeStamp.attr('data-time');
console.log(originalTime)
timeStamp.html(moment(originalTime).fromNow());
}
$(document).ready(function() {
initialFeed();
setInterval(timeUpdate, 2000);
$('.name').on('click', filterByName);
$('#originalFeed').on('click', showFeed);
$('#newTweets').on('click', newTweets);
});
});
var timeStamp = $('.timeStamp'); will selecet ALL .timeStamp elements.
You should do something like this
var timeUpdate = function(time) {
var timeStamps = $('.timeStamp');
timeStamps.each(function (i) {
var timeStamp = $(this);
var originalTime = timeStamp.attr('data-time');
console.log(originalTime)
timeStamp.html(moment(originalTime).fromNow());
});
}
Related
I have a loop in which I am calling rec_append() recursively, apparently the first pass alone works, then the loop stops.
I have an array of 4 elements going into that $.each loop but I see only the first element going into the function recursively. Help!
I switched it for a element.forEach but that gives me only the second element and I am stuck, is there a better solution to process a tree of elements? My array is a part of a tree.
var data = JSON.parse(JSON.stringify(result))
var graph = $(".entry-point");
function rec_append(requestData, parentDiv) {
var temp_parent_details;
$.each(requestData, function (index, jsonElement) {
if (typeof jsonElement === 'string') {
//Element construction
//Name and other details in the form of a : delimited string
var splitString = jsonElement.split(':');
var details = document.createElement("details");
var summary = document.createElement("summary");
summary.innerText = splitString[0];
details.append(summary);
temp_parent_details = details;
parentDiv.append(details);
var kbd = document.createElement("kbd");
kbd.innerText = splitString[1];
summary.append(' ');
summary.append(kbd);
var div = document.createElement("div");
div.className = "col";
details.append(div);
var dl = document.createElement("dl");
div.append(dl);
var dt = document.createElement("dt");
dt.className = "col-sm-1";
dt.innerText = "Path";
div.append(dt);
var dd = document.createElement("dd");
dd.className = "col-sm-11";
dd.innerText = splitString[2];
div.append(dd);
var dt2 = document.createElement("dt");
dt2.className = "col-sm-1";
dt2.innerText = "Type";
div.append(dt2);
var dd2 = document.createElement("dd");
dd2.className = "col-sm-11";
dd2.innerText = splitString[1];
div.append(dd2);
} else {
$.each(jsonElement, function (jsonElementArrIndx, jsonChildElement) {
rec_append(jsonChildElement, temp_parent_details); //Only 1 pass works, rest skip
});
}
});
}
rec_append(data, graph);
Sample data:enter image description here
I have this code. I want to loop through the array and create a new doc for each entry. If I manually set the loop length to the number of rows it works fine. I want to set it to loop for the length of the array. However the .length property always returns null. What am I missing. I have also tried for each loops with no luck.
function createDocument()
{
//var headers = Sheets.Spreadsheets.Values.get('fileID', 'A1:Z1');
var studentHistory = Sheets.Spreadsheets.Values.get('fileID', 'A2:Z200');
var templateId = 'fileID';
var documentId;
var dstFolder = DriveApp.getFolderById('folderID');
var length = studentHistory.length;
Logger.log(studentHistory);
Logger.log(length);
//Loop through rows in sheet
for (var i = 0; i < length; i++){
//Get values from sheet row
var date = studentHistory.values[i][0];
var studentName = studentHistory.values[i][1];
var dob = studentHistory.values[i][2];
var pcDoctor = studentHistory.values[i][3];
var address = studentHistory.values[i][4];
var fgName = studentHistory.values[i][5];
var mgName = studentHistory.values[i][6];
var phoneMom = studentHistory.values[i][7];
var phoneDad = studentHistory.values[i][8];
var empMom = studentHistory.values[i][9];
var empDad = studentHistory.values[i][10];
var livesWith = studentHistory.values[i][11];
var childrenInHome = studentHistory.values[i][12];
var childrenNotInHome = studentHistory.values[i][13];
var othersInHome = studentHistory.values[i][14];
var illnesses = studentHistory.values[i][15];
var illnessDetails = studentHistory.values[i][16];
var hospitalizations = studentHistory.values[i][17];
var hospDetails = studentHistory.values[i][18];
var trauma = studentHistory.values[i][19];
var traumaDetails = studentHistory.values[i][20];
var injuries = studentHistory.values[i][21];
var injuryDetails = studentHistory.values[i][22];
var medications = studentHistory.values[i][23];
var additionalComments = studentHistory.values[i][24];
var otherSchools = studentHistory.values[i][25];
//Make a copy of the template file
documentId = DriveApp.getFileById(templateId).makeCopy(dstFolder).getId();
//Change name of newly created document
DriveApp.getFileById(documentId).setName('SocialHistory_' + studentName + '_' + date);
var body = DocumentApp.openById(documentId).getBody();
//Insert values
body.replaceText('<<date>>', date);
body.replaceText('<<studentName>>', studentName);
body.replaceText('<<dob>>', dob);
body.replaceText('<<pcDoctor>>', pcDoctor);
body.replaceText('<<address>>', address);
body.replaceText('<<fgName>>', fgName);
body.replaceText('<<mgName>>', mgName);
body.replaceText('<<phoneMom>>', phoneMom);
body.replaceText('<<phoneDad>>', phoneDad);
body.replaceText('<<empMom>>', empMom);
body.replaceText('<<empDad>>', empDad);
body.replaceText('<<livesWithe>>', livesWith);
body.replaceText('<<childrenInHome>>', childrenInHome);
body.replaceText('<<childrenNotInHome>>', childrenNotInHome);
body.replaceText('<<othersInHome>>', othersInHome);
body.replaceText('<<illnesses>>', illnesses);
body.replaceText('<<illnessDetails>>', illnessDetails);
body.replaceText('<<hospitalizations>>', hospitalizations);
body.replaceText('<<hospDetails>>', hospDetails);
body.replaceText('<<trauma>>', trauma);
body.replaceText('<<traumaDetails>>', traumaDetails);
body.replaceText('<<injuries>>', injuries);
body.replaceText('<<injuryDetails>>', injuryDetails);
body.replaceText('<<medications>>', medications);
body.replaceText('<<additionalComments>>', additionalComments);
body.replaceText('<<otherSchools>>', otherSchools);
}
}
studentHistory.values is the array.
Therefore, try this instead to get the length:
var length = studentHistory.values.length;
Solution
I see you are using Advanced Google Services to call the Sheets API. This Apps Script class allows you to call the Google APIs directly from your script handling automatically the authorization process.
However it doesn't work as the built in Classes that are available for example inside the SpreadsheetApp wrapper.
Your request will return an HTTP-like response following these specifications:
{
"range": string,
"majorDimension": enum (Dimension),
"values": [
array
]
}
You will need to parse these responses in order to achieve the desired result.
Proposed modification
function createDocument()
{
//var headers = Sheets.Spreadsheets.Values.get('fileID', 'A1:Z1');
var studentHistory = Sheets.Spreadsheets.Values.get('fileID', 'A2:Z200');
var templateId = 'fileID';
var documentId;
var dstFolder = DriveApp.getFolderById('folderID');
var length = studentHistory.values.length;
...
Reference
Google Sheets API
Advanced Google Services
I have a simple app in which users complete some basic details of a meeting in a google sheet and then export these to their google calendar. Script as follows:
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1;
var range = sheet.getDataRange();
var data = range.getValues();
// var calId = sheet.getRange("H2:H2").getValue();
var calId = "xxxxxxxxxxxx";
var cal = CalendarApp.getCalendarById(calId);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue;
var row = data[i];
var date = new Date(row[1]);
var title = row[2];
var initial = row[0];
var concatTitle = initial + " - " + title;
var tstart = new Date(row[3]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
// var tstop = new Date(row[4]);
var tstop = new Date(tstart + row[4]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[5];
var desc = row[6];
var id = row[7];
try {
var event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
if (!event) {
var newEvent = cal.createEvent(concatTitle, tstart, tstop, {description:desc,location:loc}).getId();
row[7] = newEvent;
}
else {
event.setTitle(concatTitle);
event.setDescription(desc);
event.setLocation(loc);
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
range.setValues(data);
}
The whole thing works great, except for when the user puts more than 60 mins as the length of the meeting in column 4. Anything up to 59 mins works great and the event is logged with the correct start and end time. However, when I enter 60 or more mins, the error reads 'Event start time must be before event end time."
I'm sure I'm doing something very simple very wrong, but any help would be greatly appreciated.
I have a collaborative list in google's realtime api, which is displayed in a select tab.
Currently I have this.
var managment = (function($) {
var deadline1 = undefined;
// the name of the authenticated user - once authentication has succeeded
var username = "unkown";
var realtimeLoader = undefined;
var initializeModel = function(model) {
var deadline1 = model.createList();
model.getRoot().set('deadline1', deadline1);
}
var onProjectsLoaded = function(doc) {
deadline1 = doc.getModel().getRoot().get('deadline1');
deadline1.addEventListener(gapi.drive.realtime.EventType.VALUES_ADDED, updateUi);
deadline1.addEventListener(gapi.drive.realtime.EventType.VALUES_REMOVED, updateUi);
deadline1.addEventListener(gapi.drive.realtime.EventType.VALUES_SET, updateUi);
$("#inviteId").removeAttr("disabled");
var inviteButton = $("#invite");
inviteButton.removeAttr("disabled");
inviteButton.click(inviteUser);
var saveButton = $("#save");
saveButton.click(addProject);
var updateButton = $("#demoListSet");
updateButton.click(onSetItems);
var selector = $("#demoListInput");
selector.change(onSelect);
}
var addProject = function() {
var title = $("#title").val();
var date = $("#datepicker").val();
var priority = $("#priority").val();
var description = $("#description").val();
deadline1.push( {
title : title,
date : date,
description : description,
priority : priority,
} );
}
var updateUi = function(evt) {
/*$("#demoListInput").empty();*/
var projectList = $("#demoListInput");
for (var index in evt.values) {
var deadline1 = evt.values[index];
var newOption = $("<option>").val(deadline1.title).text("Title: " + deadline1.title + " Date:" + deadline1.date + " Priority: " + deadline1.priority)
}
projectList.append(newOption);
}
My problem is with the updateUI function.
The list is called deadline1. When an item is added to the list, it updates the list but the view of this list in the select tab, This is because I am only looping through the evt.values when displaying new items. What I would like to do it delete the current view of the list each time an event is fired (see the line currently in comment), however, every time I try and call deadline1 to loop through the length of it, it comes back saying deadline1 is undefined. Is there a way to get around this? Thank you.
I want to sort results obtained from indexedDB.
Each record has structure {id, text, date} where 'id' is the keyPath.
I want to sort the results by date.
My current code is as below:
var trans = db.transaction(['msgs'], IDBTransaction.READ);
var store = trans.objectStore('msgs');
// Get everything in the store;
var keyRange = IDBKeyRange.lowerBound("");
var cursorRequest = store.openCursor(keyRange);
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result == false){
return;
}
console.log(result.value);
result.continue();
};
Actually you have to index the date field in the msgs objectStore and open an index cursor on the objectStore.
var cursorRequest = store.index('date').openCursor(null, 'next'); // or prev
This will get the sorted result. That is how indexes are supposed to be used.
Here's the more efficient way suggested by Josh.
Supposing you created an index on "date":
// Use the literal "readonly" instead of IDBTransaction.READ, which is deprecated:
var trans = db.transaction(['msgs'], "readonly");
var store = trans.objectStore('msgs');
var index = store.index('date');
// Get everything in the store:
var cursorRequest = index.openCursor();
// It's the same as:
// var cursorRequest = index.openCursor(null, "next");
// Or, if you want a "descendent ordering":
// var cursorRequest = index.openCursor(null, "prev");
// Note that there's no need to define a key range if you want all the objects
var res = new Array();
cursorRequest.onsuccess = function(e) {
var cursor = e.target.result;
if (cursor) {
res.push(cursor.value);
cursor.continue();
}
else {
//print res etc....
}
};
More on cursor direction here: http://www.w3.org/TR/IndexedDB/#cursor-concept
IDBIndex API is here: http://www.w3.org/TR/IndexedDB/#idl-def-IDBIndex
Thanks to zomg, hughfdjackson of javascript irc, I sorted the final array. Modified code as below:
var trans = db.transaction(['msgs'], IDBTransaction.READ);
var store = trans.objectStore('msgs');
// Get everything in the store;
var keyRange = IDBKeyRange.lowerBound("");
var cursorRequest = store.openCursor(keyRange);
var res = new Array();
cursorRequest.onsuccess = function(e) {
var result = e.target.result;
if(!!result == false){
**res.sort(function(a,b){return Number(a.date) - Number(b.date);});**
//print res etc....
return;
}
res.push(result.value);
result.continue();
};