I was looking for help last week to get a simple javascript code made for SharePoint 2007 working for SharePoint 2010 and didn't really get a clear answer that i could use where i work unfortunately so i decided to try to just make my own. It's suppossed to be an Auction List and have a countdown in the "Time Left" field till the item expires, but i can't figure out what's wrong. I am very unfamiliar with javascript and sharepoint but i am an experienced programmer. Can anyone help with this? Here's the code below:
<script type="text/javascript">
var context = new SP.ClientContext.get_current();
var web = context.get_web();
var lists = web.get_lists();
var listId = SP.ListOperation.Selection.getSelectedList();
var list = lists.getById(listId);
var item = getItemByName("End Date");
var end = Date.parse(item.text())/1000;
var todayNow = new Date();
todayNow = Date.parse(today)/1000;
var result = (end-todayNow);
var item2 = getItemByName("Time Left");
item2.text(result);
</script>
The End Date is a field that will probably be hidden, but just used as a placeholder to find the difference from now till the item expires.
Thanks guys for any responses.
Edit: Ok thanks Robert, you've really helped a lot. I was just about to post this when i saw your last comment. I'm extremely close now since I've been googling and researching what you said in your first comment and I've gotten this far:
<
script type="text/javascript">
ExecuteOrDelayUntilScriptLoaded(getWebSiteData, "sp.js");
var context = null;
var web = null;
var lists = null;
var listId = null;
var list = null;
var item = null;
function getWebSiteData(){
context = new SP.ClientContext.get_current();
web = context.get_web();
lists = web.get_lists();
listId = SP.ListOperation.Selection.getSelectedList();
list = lists.getById(listId);
context.load(list, 'End Date');
context.executeQueryAsync(Function.createDelegate
(this, this.onSuccessMethod), Function.createDelegate
(this, this.onFailureMethod));
}
function onSuccessMethod(sender, args){
alert('web title:' + web.get_title() + '\n ID:' + web.get_id
());
}
function onFailureMethod(sender, args){
alert('request failed' + args.get_message
() + '\n' + args.get_stackTrace());
}
</script>
I think the only thing i have left to do is figure out how to get the current item so i can set the Time Left for that specific item. Do you know how to do that? Am i as close as i think?
Thanks again for your help.
When you use javascript to access SharePoint, you're using the ECMA Client Object Model. I haven't worked with the Client Object Model for 07, but I have for '10, and right away can tell the code you posted won't work in sp10. At least in sp10 com, every time you grab a new instance of a SharePoint object (list, web, listItem, column, etc), you need to set that item into your local context, then load the context against the server via an asynchronous method. Only after that point, can you access the fields in the referenced object that you desire. Let me know if you cna't figure it out. Here's some sample code: http://pastebin.com/3amgaEhv
edit:
As for updating list items, I just found this link, here: http://sprider.org/2011/12/13/sharepoint-ecmascript-to-adddeleteupdateget-list-items/
Related
I am in school and trying to code a google apps script where I have a function bound to a doc with a custom menu that can create a new doc with the date, subject, and email it to the teacher of said subject. All was going according to plan until I decided to make it so that if I hit cancel instead of OK in one of the parameters I would get the default value of that parameter if I had not hit edit parameters so I could easily only change 1 or 2 things. The function works spotlessly, but now what's happening is I can't get the selected button for the alert that asks me if I want to edit parameters.
It just says
"TypeError: response.getSelectedButton is not a function"
and won't let me run my function. Here's my code for the function. This has worked fine for me in the past and I'm really not sure why it doesn't work now.
function Mathdoc() { var ui = DocumentApp.getUi();
var d = new Date();
var s = (d.getDate()) + '/' + (d.getMonth()+1) + '/' + d.getFullYear();
console.log(s);
var response = ui.alert( 'Change parameters?', ui.ButtonSet.YES_NO);
if (response.getSelectedButton() == ui.Button.YES) { insert all my other code here}
Is there a glitch or something I'm missing? I'm new to JS and fairly new to web design altogether.
There is no method named getSelectedButton(). The ui.alert() just returns the button and nothing else
function Mathdoc() {
var ui=DocumentApp.getUi();
var d = new Date();
var s = (d.getDate()) + '/' + (d.getMonth()+1) + '/' + d.getFullYear();
console.log(s);
var response=ui.alert( 'Change parameters?', ui.ButtonSet.YES_NO);
if (response==ui.Button.YES) { insert all my other code here}
Look at example here
Nope, this function doesn't exist. Basically if you type a function on google and don't find anything, it means the function doesn't exist
EDIT : If you have an error message that says it doesn't exist, it means that the function really doesn't exist or that the library containing the function is missing. But in your case the function doesn't exist
The backstory here is that I'm working on a Discord bot. One of the requested functions is having it lob insults. I thought it would be fun to give users the ability to add insults via a SQLite 3 database (specifically, better-sqlite3), and in doing so, I also want to keep track of the most recent use of each insult (this is for future use in an "insultinfo" type command). I added a DATETIME column called "lastUsed". My insultadd command is able to write to this column when new insults are added. The issue is when I call the insult command, it's supposed to say the insult and then update the lastUsed field with the current date. Pasting the code below.
The problem is that I'm getting an error that says "SQLiteError: no such column:" and then it prints the date value even though I'm trying to update the lastUsed column and I can't figure out how to resolve this. The issue has to be in the db.prepare statement, I'm just not seeing what I need to do to fix it.
execute(msg, args) {
const SQLite = require("better-sqlite3");
const db = new SQLite('./userinputs.sqlite');
// Check if the table "userinputs" exists and has content from this guild.
const table = db.prepare(`SELECT count(*) FROM userinputs WHERE (guild = ${msg.guild.id} OR guild = 'Global') AND type = 'insult';`).get();
if (!table['count(*)']) {
return msg.channel.send("I don't have any insults yet");
}
var date = new Date();
const rawInsult = db.prepare(`SELECT * FROM userinputs WHERE type = 'insult' AND (guild = ${msg.guild.id} OR guild = 'Global') ORDER BY RANDOM() LIMIT 1;`).get();
const insult = rawInsult['content'];
const insultID = rawInsult['row'];
if (args[0]) {
var target = args[0];
} else {
var target = msg.author.username;
}
if (insult.includes('{}')) {
var finalInsult = insult.replace('{}', target);
} else {
var finalInsult = target + ' ' + insult;
}
msg.channel.send(finalInsult);
db.prepare(`UPDATE userinputs SET lastUsed = "${date}" WHERE row = ${insultID};`).run();
},
I think I got it. I ended up using date.toString() and it appears to have done the job. The error message I got after updating the db.prepare statement indicated it wasn't viewing that date variable as something it could work with, hence the .toString() workaround. I'll have to test this to see if that impacts my ability to sort on that column, since this is still all a pretty new to me, but at least the command itself is working and the database table is updating.
I'm open to more feedback though if anyone sees the probable folly in my ways here.
UPDATE: Upon further testing, setting date = Math.floor(new Date() / 1000) ended up working better in my case.
I'm trying to build a spreadsheet based around DataDT's excellent API for 1-minute Forex data. I'm trying to build a function that 1) Reads a value ("Date time") from a cell 2) Searches for that value in a given URL from the aforementioned API 3) Prints 2 other properties (open & close price) for that same date.
In other words, It would take input from rows N and O, and output the relevant values (OPEN and CLOSE from the API) in rows H and I.
(Link to current GSpreadsheet)
This spreadsheet would link macroeconomic news and historic prices and possibly reveal useful insights for Forex users.
I already managed to query data from the API effectively but I can't find a way to filter only for the datetimes I'm asking. Much less iterating for different dates! With the help from user #Cooper I got the following code that can query entire pages from the API but can't efficiently filter yet. I'd appreciate any help that you might provide.
This is the current status of the code in Appscript:
(Code.gs)
function searchOnEdit(e) {
//e.source.toast('Entry');// I use these lines for debugging
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);//this was commented out it should not have been sorry for that Cooper
//e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};
var dObj=getDataDT1(obj);
//Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
}
}
//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
Logger.log(JSON.stringify(obj));//I need to see this
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
(Appscript.json)
{
"timeZone": "America/Caracas",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"oauthScopes": ["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/script.scriptapp","https://www.googleapis.com/auth/spreadsheets"]
}
(Trigger.js)
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}
onEdit Search
You will need to add a column of checkboxes to column 17 and also create an installable onEdit trigger. You may use the code provided or do it manually via the Edit/Project Triggers menu. When using the trigger creation code please check to insure that only one trigger was creates as multiple triggers can cause problems.
Also, don't make the mistake of naming your installable trigger onEdit(e) because it will respond to the simple trigger and the installable trigger causing problems.
I have an animation below showing you how it operates and also you can see the spreadsheet layout as well. Please notice the hidden columns. I had to do that to make the animation as small as possible. But I didn't delete any of your columns.
It's best to wait for the the check box to get reset back to off before checking another check box. It is possible to check them so fast that script can't keep up and some searches may be missed.
I also had to add these scopes manually:
"oauthScopes":["https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/spreadsheets"]
You can put them into your appsscript.json file which is viewable using the View/Show Manifest File. Here's a reference that just barely shows you what they look like. But the basic idea is to put a comma after the last entry before the closing bracket and add the needed lines.
After you have created the trigger it's better to go into View/Current Project triggers and set the Notifications to Immediate. If you get scoping errors it will tell you which ones to add. You add them and then run a function and you can reauthorize the access with the additional scopes. You can even run a null function like function dummy(){};.
This is the onEdit function:
function searchOnEdit(e) {
//e.source.toast('Entry');// I use these lines for debugging
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';//these are the defaults if you install the checkboxes from the Insert Menu
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);
//e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};//you dont really need e here
var dObj=getDataDT1(obj);
//Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);//loading OPEN on your spreadsheet
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);//loadding CLOSE on your spreadsheet
}
}
This is the search function. I tried caching the data but it was too large. So if you can reduce the size significantly that would help speed things up for consecutive searches.
//{datetime:'',url:'',event:e}
function getDataDT1(obj) {
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
This is the create Trigger function. Becareful not to run this more than once and always go check to see that there is only one and set the notifications to immediate when you first turn it on so you'll get emails pretty quickly after errors occur.
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}
Animation:
This is a copy of your spreadsheet with the check boxes.
If you have any difficulties feel free to come back and get some help. I know some of this stuff sounds a bit daunting but it's kind of like going metric. Once you've measured and weighed a few things it begins to sound and feel natural.
Here's my code exactly as I have it in my script which is running right now. Perhaps I have a typo in it due to editing in comments. This has some debugging lines in which run the Logger and display toasts which you should probably comment out.
function searchOnEdit(e) {
e.source.toast('Entry');
var sh=e.range.getSheet();
if(sh.getName()!='API') return;
var checkedValue='TRUE';
var uncheckedValue='FALSE';
if(e.range.columnStart==17 && e.range.rowStart>1 && e.value==checkedValue) {
e.range.setValue(uncheckedValue);
e.source.toast('flag1');
var r=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var obj={datetime:r[14],url:r[13],event:e};
var dObj=getDataDT1(obj);
Logger.log(dObj);
sh.getRange(e.range.rowStart,4).setValue(dObj.OPEN);
sh.getRange(e.range.rowStart,5).setValue(dObj.CLOSE);
}
}
//{datetime:'',url:''}
function getDataDT1(obj) {
var r=UrlFetchApp.fetch(obj.url);
var data=JSON.parse(r.getContentText("UTF-8"));
//Logger.log(data);
var pair='USDJPY';
var dat=new Date(obj.datetime);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
for(var i=0;i<data.length;i++) {
var dt=data[i].DATE_TIME.split(' ');
var sd=new Date(data[i].DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv) {
var d=dt[0].split('-');
var t=dt[1].split(':');
var datestring=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var timestring=Utilities.formatString('%s:%s',t[0],t[1]);
var rObj={DATE:datestring,TIME:timestring,PAIR:pair,OPEN:data[i].OPEN.toFixed(3),CLOSE:data[i].CLOSE.toFixed(3)};
break;
}
}
//Logger.log(rObj);
return rObj;
}
function createSearchOnEditTrigger() {
var ss=SpreadsheetApp.getActive();
ScriptApp.newTrigger('searchOnEdit').forSpreadsheet(ss.getId()).onEdit().create();
}
I have created a chat feature recently and I notice a curious bug. The following is the code I am using in my controller:
myFirebase.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = msg.user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = msg.message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
});
Suppose we enter the Chat view for the first time, then when I chat, the .appendChild() is working perfectly fine and the typed message shows up in the div 'messages'. Now Suppose we leave the Chat view and re-enter it, and type and send another chat message, then the .appendChild() is executed twice and the same message is appears twice in the div 'messages'. This continues linearly so if we re-enter the controller for the fifth time and send a message, the message is appended to the div 'messages' five times...
What is going on here?
I am using the Ionic Framework and the ready-made app template 'Tabs'. My chat feature is in the chat-details controller.
The problem is because the event handler is being added twice, once when you first visit the chat page, and again when you come back. To confirm that, visit it a third time, and you should see it 3x.
The solution is to put in an $onDestroy handler to remove the event handler. If the event handler can't be removed (ie it doesn't have an off method), then you should set a variable to tell you that it is initialised, and you check that on initialising the page (to prevent you doing it twice)
So Mikkel gave the right suggestion to initialize a variable and basically use that as a flag to make sure that my event handler is not called multiple times, given multiple entries to the Chat view, but only once. The following is my solution:
if (window.localStorage.getItem("notVisited") == null){ //This initilizes a variable in localstorage
window.localStorage.setItem("notVisited","true");
}
var startListening = function() {
myFirebase.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = msg.user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = msg.message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
});
window.localStorage.setItem("notVisited","false");
}
if (window.localStorage.getItem("notVisited") == "true") {
startListening();
}
Now after implementing this, I ran into a new problem which was that with this new code, each time I re-entered the view, the previous chat messages would not show up. So I added this:
if (window.localStorage.getItem("notVisited") == "false"){
$http({
url: "https://uniff-f4136.firebaseio.com/" + chatKey + ".json",
method: "GET"
}).then(function (response) {
for (var i in response.data){
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = response.data[i].user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = response.data[i].message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
}
});
}
In the end, this made my chat work though I do not like the repetition of code. I hope others find this insightful.
Finally, to learn about using firebase to build a real time web chat app, visit this Google CodeLabs link: https://codelabs.developers.google.com/codelabs/cloud-firebase-chat/#4
I am writing a webOS app and I want the following code to present a "Good Morning!" message. What code do I need to put in my Main-scene.html file and what else do I need in the Main-assistant.js file to make this work?
Many thanks in advance.
MainAssistant.prototype.welcomeMessage = function(){
datetoday = new Date();
timenow = datetoday.getTime();
datetoday.setTime(timenow);
thehour = datetoday.getHours();
if (thehour > 18)
display = "Evening";
else
if (thehour > 12)
display = "Afternoon";
else
display = "Morning";
var greeting = ("Good " + display + "!");
document.write(greeting);
};
All the best
David
I don't know when the welcomeMessage method will be called, but if it's after the document has finished loading then it is closed. Calling document.write then will call document.open, which completely clears the document. Likely you have an element that the message should be written into, much better to use the load or DOMReady events (or whatever is available on WebOS).
Consider a much simpler form of the function and don't forget to declare variables to limit their scope to only what is necessary:
var tod = ['morning','morning','afternoon','evening'];
var now = new Date();
var greeting = 'Good ' + (tod[now.getHours()/6|0]) + '!';
If you want a library, try myLibrary. No, it's not my Library, it's your library when you use it. You can create a customised core and just the DOM ready part that is quite small and the code quality is excellent.