Sharepoint 2013 - User profiles JSOM - javascript

I have this part of code which should get me for example the "title" of the current user in Sharepoint, but everytime it gives me error: Common Language Runtime detected an invalid program.
<script type="text/javascript">
var personProperties;
// Ensure that the SP.UserProfiles.js file is loaded before the custom code runs.
SP.SOD.executeOrDelayUntilScriptLoaded(getUserProperties, 'SP.UserProfiles.js');
function getUserProperties() {
// Replace the placeholder value with the target user's credentials.
// var targetUser = "domainName\\userName";
// Get the current client context and PeopleManager instance.
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
// Get user properties for the target user.
// To get the PersonProperties object for the current user, use the
// getMyProperties method.
personProperties = peopleManager.getMyProperties();
// Load the PersonProperties object and send the request.
clientContext.load(personProperties);
clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
}
// This function runs if the executeQueryAsync call succeeds.
function onRequestSuccess() {
// Get a property directly from the PersonProperties object.
var messageText = personProperties.get_userProfileProperties()['Title'];
alert(messageText);
}
// This function runs if the executeQueryAsync call fails.
function onRequestFail(sender, args) {
alert(args.get_message());
}
</script>
Do you have any ideas why it is happening?
Thank you for any suggestions.
Tom

You can make use of SP.SOD.executeFunc to load the files in the correct manner.
Try the below code:
SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() {
// Make sure PeopleManager is available
SP.SOD.executeFunc('userprofile', 'SP.UserProfiles.PeopleManager', function() {
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
// Get user properties for the target user.
// To get the PersonProperties object for the current user, use the
// getMyProperties method.
personProperties = peopleManager.getMyProperties();
// Load the PersonProperties object and send the request.
clientContext.load(personProperties);
clientContext.executeQueryAsync(onRequestSuccess, onRequestFail);
// This function runs if the executeQueryAsync call succeeds.
function onRequestSuccess() {
// Get a property directly from the PersonProperties object.
var messageText = personProperties.get_userProfileProperties()['Title'];
alert(messageText);
}
// This function runs if the executeQueryAsync call fails.
function onRequestFail(sender, args) {
alert(args.get_message());
}
});
});

Related

ServiceNow UI Page GlideAjax

I created a form using UI Page and am trying to have some fields autopopulated onChange. I have a client script that works for the most part, but the issue arises when certain fields need to be dot-walked in order to be autopopulated. I've read that dot-walking will not work in client scripts for scoped applications and that a GlideAjax code will need to be used instead. I'm not familiar with GlideAjax and Script Includes, can someone help me with transitioning my code?
My current client script looks like this:
function beneficiary_1(){
var usr = g_user.userID;
var related = $('family_member_1').value;
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee',usr);
rec.addQuery('sys_id',related);
rec.query(dataReturned);
}
function dataReturned(rec){
//autopopulate the beneficiary fields pending on the user selection
if(rec.next()) {
$('fm1_ssn').value = rec.ssn;
$('fm1_address').value = rec.beneficiary_contact.address;
$('fm1_email').value = rec.beneficiary_contact.email;
$('fm1_phone').value = rec.beneficiary_contact.mobile_phone;
var dob = rec.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0] ;
$('fm1_date_of_birth').value = date;
}
}
fm1_address, fm1_email, and fm1_phone do not auto populate because the value is dot walking from the HR_Beneficiary table to the HR_Emergency_Contact table.
How can I transform the above code to GlideAjax format?
I haven't tested this code so you may need to debug it, but hopefully gets you on the right track. However there are a couple of steps for this.
Create a script include that pull the data and send a response to an ajax call.
Call this script include from a client script using GlideAjax.
Handle the AJAX response and populate the form.
This is part of the client script in #2
A couple of good websites to look at for this
GlideAjax documentation for reference
Returning multiple values with GlideAjax
1. Script Include - Here you will create your method to pull the data and respond to an ajax call.
This script include object has the following details
Name: BeneficiaryContact
Parateters:
sysparm_my_userid - user ID of the employee
sysparm_my_relativeid - relative sys_id
Make certain to check "Client callable" in the script include options.
var BeneficiaryContact = Class.create();
BeneficiaryContact.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getContact : function() {
// parameters
var userID = this.getParameter('sysparm_my_userid');
var relativeID = this.getParameter('sysparm_my_relativeid');
// query
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee', userID);
rec.addQuery('sys_id', relativeID);
rec.query();
// build object
var obj = {};
obj.has_value = rec.hasNext(); // set if a record was found
// populate object
if(rec.next()) {
obj.ssn = rec.ssn;
obj.date_of_birth = rec.date_of_birth.toString();
obj.address = rec.beneficiary_contact.address.toString();
obj.email = rec.beneficiary_contact.email.toString();
obj.mobile_phone = rec.beneficiary_contact.mobile_phone.toString();
}
// encode to json
var json = new JSON();
var data = json.encode(obj);
return data;
},
type : "BeneficiaryContact"
});
2. Client Script - Here you will call BeneficiaryContact from #1 with a client script
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var usr = g_user.userID;
var related = $('family_member_1').value;
var ga = new GlideAjax('BeneficiaryContact'); // call the object
ga.addParam('sysparm_name', 'getContact'); // call the function
ga.addParam('sysparm_my_userid', usr); // pass in userID
ga.addParam('sysparm_my_relativeid', related); // pass in relative sys_id
ga.getXML(populateBeneficiary);
}
3. Handle AJAX response - Deal with the response from #2
This is part of your client script
Here I put in the answer.has_value check as an example, but you may want to remove that until this works and you're done debugging.
function populateBeneficiary(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
answer = answer.evalJSON(); // convert json in to an object
// check if a value was found
if (answer.has_value) {
var dob = answer.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0];
$('fm1_ssn').value = answer.ssn;
$('fm1_address').value = answer.address;
$('fm1_email').value = answer.email;
$('fm1_phone').value = answer.mobile_phone;
$('fm1_date_of_birth').value = date;
}
else {
g_form.addErrorMessage('A beneficiary was not found.');
}
}

Save JavaScript prototype based objects in sessionStorage?

var obj = {
conn : null,
first : function(thisIdentity) {
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function(data) {
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', JSON.stringify(myObj.conn));
}
});
},
second : function(thisIdentity) {
"use strict";
var myObj = this;
var conntn = sessionStorage.getItem('connection');
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
success : function(data) {
var parsedConnection = JSON.parse(conntn);
parsedConnection.sendMsg(data.id, data.nid);
}
});
}
};
var Connection = (function() {
function Connection(uid, url) {
this.uid = uid;
this.open = false;
this.socket = new WebSocket("ws://"+url);
this.setupConnectionEvents();
},
Connection.prototype = {
sendMsg : function(id, nid) {
alert("Working");
},
// other functions
}
})();
So connection is made in the AJAX callback function of first and I store the object in the sessionStorage via JSON but when I use it in the AJAX callback of second then error is coming that
TypeError: parsedConnection.sendMsg is not a function
Now I understand that may be it is because JSON can be used to store plain objects not prototype-based objects.
My question is : Can any one tell me how to store prototype-based objects via JSON or any other way to implement this?
I don't want to use eval. Any code, reference would be much appreciated. Thanks!
UPDATE
I did as #Dan Prince mentioned but then a new problem occurred that now when in sendMsg function I use
this.socket.send(JSON.stringify({
action: 'message',
rec: receiver,
msg: message
}));
Then it stays
InvalidStateError: An attempt was made to use an object that is not,
or is no longer, usable
Any inputs? Thanks!
You could probably hack your own solution into place by storing the prototype as a property of the object, then reinstantiating it with Object.create after you read it, but the real question is why do you want to do this in the first place?
I would suggest writing a serialize method on Connection's prototype, which exposes only the essential information (there's no sense serializing a web socket for example).
Connection.prototype.toJSON = function() {
return JSON.stringify({
uid: this.uid,
url: this.url,
open: this.open
});
};
Then use this method when you save the connection object into session storage.
myObj.conn = new Connection(data.user_id, "127.0.0.1:80");
sessionStorage.setItem('connection', myObj.conn.toJSON());
Each saved connection now has the minimum amount of data you need to call the constructor and recreate the instance.
When you load a connection from session storage, parse it and pass the values back into the constructor.
var json = sessionStorage.getItem('connection');
var data = JSON.parse(json);
var connection = new Connection(data.uid, data.url)
// ...
connection.sendMsg(data.id, data.nid);
This will recreate the correct prototype chain in a natural and predictable way.
It's hard to see exactly what you are trying to achieve in every respect, but let's assume :
for various DOM elements, a click handler (delegated to document) will cause asynchronously derived data to be sent via socket.send().
the socket is to be initialized with an asynchronously derived uri.
the socket is to be kept available for immediate reuse.
data by which the socket is initialized is to be cached in local storage for future sessions. (It makes no sense to store the socket itself).
In addition, we need to acknowledge that a socket consume resources should really be disposed of if its resuse is not immediate.
The whole strategy is abnormally complex. The overhead of performing an ajax operation once per session to obtain a uri would typically be accepted, as would the creation of a socket each time one is needed. However, it's an intersting exercise to write something with all the stated characteristics.
This may not be 100% correct but could possibly give you some ideas, including the use of promises to cater for several asynchronisms. Here goes ...
var obj = {
conn: null,
init: function(thisIdentity) {
// It makes sense to attach the click handler only *once*, so let's assume this is an init function.
"use strict";
var myObj = this;
$(document).on('click', thisIdentity, function(e) {
e.preventDefault();
$.ajax ({
url : some value,
// other parameters
}).then(function(data) {
myObj.send(JSON.stringify({
'id': data.id,
'nid': data.nid
}));
});
});
},
send: function(data) {
"use strict";
var myObj = this;
return myObj.getSocket().then(function(socket) {
socket.send(data);
}).then(function() {
// by disposing in later event turn, a rapid series of send()s has at least a chance of using the same socket instance before it is closed.
if(socket.bufferedAmount == 0) { // if the socket's send buffer is empty, then dispose of it.
socket.close();
myObj.conn = null;
}
});
},
getSocket: function() {
"use strict";
var myObj = this;
//1. Test whether or not myObj.conn already exists ....
if(!myObj.conn) {
//2 .... if not, try to recreate from data stored in local storage ...
var connectionData = sessionStorage.getItem('connectionData');
if(connectionData) {
myObj.conn = myObj.makeSocket(connectionData.user_id);
} else {
//3. ... if connectionData is null, perform ajax.
myObj.conn = $.ajax({
url: some value,
// other parameters
}).then(function(data) {
sessionStorage.setItem('connectionData', JSON.stringify(data));
return myObj.makeSocket(data.user_id);
});
}
}
return myObj.conn; // note: myObj.conn is a *promise* of a socket, not a socket.
},
makeSocket: function(uid) {
"use strict";
var myObj = this;
var uri = "127.0.0.1:80"; // if this is invariant, it can be hard-coded here.
// return a *promise* of a socket, that will be resolved when the socket's readystate becomes OPEN.
return $.Deferred(function(dfrd) {
var socket = new WebSocket("ws://" + uri);
socket.uid = uid;
socket.onopen = function() {
myObj.setupConnectionEvents();// not too sure about this as we don't know what it does.
dfrd.resolve(socket);
};
}).promise();
}
};
Under this scheme, the click handler or anything else can call obj.send() without needing to worry about the state of the socket. obj.send() will create a socket if necessary.
If you were to drop the requirement for storing data between sessions, then .send() and .getSocket() would simplify to the extent that you would probably choose to roll what remains of .getSocket() into .send().

Cannot create a pointer to an unsaved ParseObject

I am having troubles referring to a "User" object from inside a query. I have the following code:
Parse.Cloud.define("getTabsBadges", function(request, response) {
var UserObject = Parse.Object.extend('User');
var user = new UserObject();
user.id = request.params.userId;
// Count all the locked messages sent to the user
var receivedMessagesQuery = new Parse.Query('Message');
receivedMessagesQuery.equalTo('status', 'L');
receivedMessagesQuery.equalTo('toUser', user); // THIS LINE GENERATES THE ERROR
receivedMessagesQuery.count({
// more code here
});
});
I call the function using CURL but I always get the following error:
{"code":141,"error":"Error: Cannot create a pointer to an unsaved
ParseObject\n at n.value (Parse.js:14:4389)\n at n
(Parse.js:16:1219)\n at r.default (Parse.js:16:2422)\n at e.a.value
(Parse.js:15:1931)\n at main.js:9:25"}
I am using the exactly same code in another project, the only difference is that instead of counting objects I find them and its works correctly. I have also verified that the tables have a column type of Pointer<_User> in both projects. What's causing the problem?
The error message Cannot create a pointer to an unsaved means that you are trying to use an object which does not exist in the Parse DB.
With var user = new UserObject();, you're creating a new user object. You cannot use it in a query until you save it to Parse.
Instead of creating a new User object and setting it's objectId, do a query for the User object. See code below:
Parse.Cloud.define("getTabsBadges", function(request, response) {
var UserObject = Parse.Object.extend('User');
var query = new Parse.Query(UserObject);
query.get(request.params.userId, {
success: function(user) {
// Count all the locked messages sent to the user
var receivedMessagesQuery = new Parse.Query('Message');
receivedMessagesQuery.equalTo('status', 'L');
receivedMessagesQuery.equalTo('toUser', user); // THIS LINE GENERATES THE ERROR
receivedMessagesQuery.count({
// more code here
});
},
error: function(error) {
// error fetching your user object
}
});
});
Your request.params.userId may be undefined or null, which causes this error.
Your query constraints cannot compare the Parse Object that is created without data (createWithoutData()) using undefined or null as its objectId.

Unable to call function within same GAS script

I have two function, one reads the Cell value upon change.
And the second one makes a Request to a URL and gets the response.
function onEdit(e) {
var range = e.range;
var data = range.getValue();
Logger.log(data)
Logger.log(test());
}
function test() {
var url = 'apps.compete.com/sites/wholesalerhinestones.org/trended/UV/?apikey=[YOUR API KEY HERE]';
var response = UrlFetchApp.fetch(url);
Logger.log(response);
}
Problem is that, test() runs successfully and Logs the output to Console but upon Cell change event, cell's value is logged but test() is not called.
One of the issues here is you're not actually calling the function, nor are you returning anything should it be called.
It should look something like this:
function onEdit(e){
var range = e.range;
var data = range.getValue();
Logger.log(data)
var testedFunction = test();
Logger.log(testedFunction);
}
function test(){
var url = 'YOUR-URL-HERE';
var response = UrlFetchApp.fetch(url);
Logger.log('Response code: ' + response.getResponseCode());
return response
}
The second issue that you're having here is that your using a Simple trigger which does not allow you to access services which require authorization.
Instead using an Installable trigger for 'onEdit' might do the trick. (This is what I was using, but I was testing against 'Google.com'). It should look like this:

Javascript can't set variable value

I'm trying to get this function to set sortedScores to a value... whenever i do console.log anywhere it seems to store the values right, but it can't actually set sortedScores properly...
function facebook(sortedfriends) {
var myID;
var access_token;
FB.init({
appId : something,
status : true,
cookie : true,
xfbml : true,
});
FB.getLoginStatus(function(response, sortedfriends) {
if(!response.session) {
FB.login(function(response) {
myId = response.session.uid;
access_token = response.session.access_token;
//does stuff
if (!response.session) {
console.log('User cancelled login or did not fully authorize.');
}
});
}
else if(response.session) {
myId = response.session.uid;
access_token = response.session.access_token;
var D = new Array();
this.access_token = access_token;
FB.api('/me/feed?access_token=' + access_token + '&limit=100', function(response, sortedfriends) {
for( i=0; i<response.data.length; i++) {
var msg = response.data[i];
D.push(msg);
}
sortedfriends = somefunction(D, myID);
//i know somefunction works because if i do console.log(sortedfriends) it shows me the right values...
});
}
});
}
when i try
var friends;
facebook(friends);
friends is just undefined... halp?
It is not clear where you are trying to access sortedfriends, but I'm guessing that your issue is that the Facebook login is asynchronous, so the response comes some time later after the facebook function has completed. Thus, if you're trying to use the sortedfriends data right after you call the facebook function, the data will not be there yet because the login call has not completed yet.
The only way to use the sortedfriends data is from the success handler to the login call (where your console.log already verifies that the data is there). If you want to use it in other code, then call that other code from the success handler to the login call. You cannot call that code right after calling the facebook function.
This logic will not work because of the asynchronous nature of the login call (it hasn't completed when the facebook call returns and execution continues after it:
var sortedfriends = [];
facebook(sortedfriends);
// use sortedfriends here
Instead, you have to do this type of structure:
var sortedfriends = [];
facebook(sortedfriends);
// nothing executes here
And, inside your facebook call where you have this, add a function call to whatever code you want to use the sortedfriends data:
else if(response.session) {
myId = response.session.uid;
access_token = response.session.access_token;
var D = new Array();
this.access_token = access_token;
FB.api('/me/feed?access_token=' + access_token + '&limit=100', function(response, sortedfriends) {
for( i=0; i<response.data.length; i++) {
var msg = response.data[i];
D.push(msg);
}
sortedfriends = somefunction(D, myID);
//i know somefunction works because if i do console.log(sortedfriends) it shows me the right values...
// call the rest of your code here that will use sortedfriends
doSomethingWithSortedFriends(sortedfriends);
});
javascript functions do not change incoming references. You cannot pass undefined and expect it will become defined after the function executes.
Instead, you should make your sortedFriends a global variable and not pass it as function parameter. Please note, that the value of sortedFriends will be set after the ajax query inside getLoginStatus is executed, so you will not be able to use it immediately after you execute your facebook function.

Categories

Resources