JavaScript: SharePoint Survey Customizations
/** | |
* Checks to see if a string includes a substring | |
* Part of ECMA 6 | |
*/ | |
if (!String.prototype.includes) { | |
String.prototype.includes = function() { | |
'use strict'; | |
return String.prototype.indexOf.apply(this, arguments) !== -1; | |
}; | |
} | |
// Ensure the WPS class | |
_EnsureJSNamespace('WPS'); | |
_EnsureJSNamespace('ClientSurvey'); | |
// RNDC Options object | |
var ClientSurvey = ClientSurvey || {}; | |
/** | |
* SharePoint Survey script | |
* | |
* Contains: | |
* Utility functions | |
* Script Class: Loads a non-SP script | |
* User Class: Current user information | |
* Web Class: SP Current context & opens web | |
* List Class: Gets current or specific list | |
* Survey Class (extends List) | |
*/ | |
(function(jQ, window, document, ClientSurvey) { | |
"use strict"; | |
var $ = jQ.noConflict(), | |
debug = true, | |
wps = { | |
utils: {} | |
}, | |
utils = wps.utils, | |
defaults = { | |
hide: { | |
ListActionsMenu: true, | |
SaveAndClose: false, | |
ViewSelectorMenu: true | |
}, | |
remove: { | |
//Show all responses = diidResultsByUser | |
AllResponses: true, | |
//Show a graphical summary of responses = diidSurveyResults | |
GraphicalSummary: true | |
}, | |
redirectPage: "/Pages/ThankYou.aspx" | |
}, | |
OPTIONS = {}; | |
// Set the options we are going to follow | |
OPTIONS = $.extend({}, defaults, ClientSurvey); | |
/** UTILS **/ | |
/** | |
* Performs any REST calls to SharePoint | |
* | |
* @param {string} endpoint REST endpoint being called. Endpoint needs to include beginning "/" | |
* @param {function} success Called on AJAX success. | |
* @param {function} error Called on AJAX error. | |
* @param {object} scope Scope to be carried forward. | |
*/ | |
utils.doAjax = function(endpoint, success, error, scope) { | |
return $.ajax({ | |
url: _spPageContextInfo.webAbsoluteUrl + endpoint, | |
type: "POST", | |
contentType: "application/json;odata=verbose", | |
headers: { | |
'accept' : 'application/json;odata=verbose', | |
'X-RequestDigest': $('#__REQUESTDIGEST').val(), | |
}, | |
success: function (data) { | |
utils.callCb(success, data, this); | |
}, | |
error: function (jqxr, errorCode, errorThrown) { | |
console.log(jqxr.responseText); | |
utils.callCb(error, {jqxr:jqxr, errorCode:errorCode, errorThrown:errorThrown}, this); | |
} | |
}); | |
}; | |
/** | |
* Determines whether the variable is a function. | |
* | |
* @param {function} fn Variable to determine whether it is a function. | |
* @returns {boolean} Whether variable is a function. | |
*/ | |
utils.isFunction = function (fn) { | |
return ("function" === typeof fn); | |
}; | |
/** | |
* Performs a sanitized callback | |
* | |
* @param {function} Function to be called. | |
* @param {object} Argument(s) to be passed to function being called. | |
* @param {object} Scope (e.g., this). | |
* @returns {mixed} Function results or null. | |
*/ | |
utils.callCb = function(fn, args, scope) { | |
if (utils.isFunction(fn)) { | |
if (scope) { | |
return fn.apply(scope, [args]); | |
} else { | |
return fn.call(scope, args); | |
} | |
} | |
return null; | |
}; | |
/** | |
* Gets the length of an object (number of key:value) | |
* | |
* @param {object} Object being measured. | |
* @returns {integer} Length of the object. | |
*/ | |
utils.getObjectLength = function(obj) { | |
var size = 0, key; | |
for (key in this) { | |
if (obj.hasOwnProperty(key)) size++; | |
} | |
return size; | |
}; | |
/** | |
* Executes a SharePoint context Async Query. | |
* | |
* @param {SP.ClientContext} ctx SharePoint Context. | |
* @param {object} scope Scope to be maintained. | |
* @param {function} Function called on successful query. | |
* @param {function} Function called on failed query. | |
*/ | |
utils.execute = function(ctx, scope, onSuccess, onFail) { | |
ctx.executeQueryAsync( | |
Function.createDelegate(scope, onSuccess), | |
Function.createDelegate(scope, function(sender, args) { | |
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace()); | |
utils.callCb(onFail, {sender: sender, args: args}, scope); | |
}) | |
); | |
}; | |
/** WEB **/ | |
/** | |
* Web Type | |
* @typedef Web | |
* @type {object} | |
* @property {SP.ClientContext} context SP Context. | |
* @property {SP.Web} web SP Site. | |
*/ | |
/** | |
* Web Function Class | |
* | |
* @class | |
*/ | |
function Web() { | |
this.context = new SP.ClientContext.get_current(); | |
this.web = this.context.get_web(); | |
} | |
/** MODAL **/ | |
/** | |
* Modal Type | |
* @typedef Modal | |
* @type {object} | |
* @property {string} type Either "normal" or "wait". | |
* @property {string} title Title of modal. | |
* @property {string} waitMsg Message to be displayed. | |
* @property {integer} height Height of modal dialogue. | |
* @property {integer} width Width of modal dialogue. | |
* @property {SP.UI.Dialogue} _dialogue | |
* @property {string} state "opened" or "closed" | |
* @property {boolean} ready Whether modal is ready to be used. | |
* @property {SP.UI.DialogueOptions} options Options for SP Dialogue. | |
*/ | |
/** | |
* Modal class | |
* | |
* @class | |
*/ | |
function Modal(options, type) { | |
// Default values for options (SP.UI.DialogueOptions). | |
var defaults = this.getDefaults(); | |
if (type) { | |
this.type = type; | |
} else { | |
if ('object' === typeof options && (options.url || options.html)) { | |
this.type = 'normal'; | |
} else { | |
this.type = 'wait'; | |
} | |
} | |
this._dialogue = null; | |
this.state = 'closed'; | |
this.ready = false; | |
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', | |
Function.createDelegate(this, function(){ | |
SP.SOD.executeFunc('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', | |
Function.createDelegate(this, function(){ | |
this.ready = true; | |
this.options = SP.UI.$create_DialogOptions(); | |
this.options = $.extend(this.options, defaults, (options || {})); | |
}) | |
); | |
}) | |
); | |
} | |
/** | |
* Default values for options (SP.UI.DialogueOptions). | |
* | |
* @method | |
* @returns {object} Default values. | |
*/ | |
Modal.prototype.getDefaults = function() { | |
return { | |
title: '', | |
url: undefined, | |
html: undefined, | |
x: null, | |
y: null, | |
width: 300, | |
height: 300, | |
//autoSizeStartWidth: false, | |
allowMaximize: false, | |
showMaximized: false, | |
showClose: true, | |
autoSize: true, | |
dialogReturnValueCallback: undefined, | |
args: {} | |
}; | |
}; | |
/** | |
* Gets HTML | |
* | |
* @method | |
* @param {string} Content to be placed in an HTML element. | |
* @returns {object} DOM Element HTML div. | |
*/ | |
Modal.prototype.getHTML = function(content) { | |
if ('object' === typeof this.options.html) { | |
return this.options.html; | |
} | |
var element = document.createElement('div'); | |
if ('string' === typeof this.options.html && this.options.html) { | |
element.innerHTML = this.options.html; | |
} else if ('undefined' !== typeof content) { | |
element.innerHTML = content; | |
} | |
this.options.html = element; | |
return this.options.html; | |
}; | |
/** | |
* Get title of modal. | |
* | |
* @returns {string} Title of modal. | |
*/ | |
Modal.prototype.getTitle = function() { | |
return this.title || $('title').text(); | |
}; | |
/** | |
* Shows the modal dialogue. | |
*/ | |
Modal.prototype.show = function() { | |
if (!this.ready) { | |
return false; | |
} | |
if ('normal' === this.type) { | |
if (this.options.html || !this.options.url) { | |
this.options.html = this.getHTML(); | |
} | |
this.options.title = this.options.title || this.getTitle(); | |
this._dialogue = SP.UI.ModalDialog.showModalDialog(this.options); | |
this.state = 'opened'; | |
} else { | |
this.showWait(); | |
} | |
}; | |
/** | |
* Shows waiting modal dialogue. | |
*/ | |
Modal.prototype.showWait = function() { | |
this.title = this.title || SP.Res.dialogLoading15; | |
this.waitMsg = this.waitMsg || null; | |
this.height = this.height || 138; | |
this.width = this.width || 365; | |
try { | |
if (this._dialogue === null) { | |
this._dialogue = SP.UI.ModalDialog.showWaitScreenWithNoClose(this.title, this.waitMsg, this.height, this.width); | |
this.state = 'opened'; | |
} | |
} catch (ex) { } | |
}; | |
/** | |
* Closes the modal dialogue. | |
* | |
* @method | |
*/ | |
Modal.prototype.close = function() { | |
try { | |
this._dialogue.close(); | |
this.state = 'closed'; | |
} catch (ex) { } | |
}; | |
/** | |
* Opens a waiting dialogue with no close button. | |
* | |
* @method | |
*/ | |
Modal.prototype.working = function() { | |
try { | |
this._dialogue = SP.UI.ModalDialog.showWaitScreenWithNoClose(SP.Res.dialogLoading15); | |
this.state = 'opened'; | |
} catch (ex) { } | |
}; | |
/** SCRIPT **/ | |
/** | |
* Script Type | |
* @typedef Script | |
* @type {object} | |
* @property {boolean} loaded Whether the script has been loaded or not. | |
* @property {function} callback Function to be called when loaded. | |
* @property {object} element DOM HTML script element. | |
* @property {string} src Source of the script. | |
*/ | |
/** | |
* Script Function Class | |
* | |
* @class | |
*/ | |
function Script(src, cb) { | |
this.loaded = false; | |
this.callback = 'function' === typeof cb ? cb : undefined; | |
this.element = document.createElement('script'); | |
this.src = this.element.src = src; | |
// debugger; | |
this.element.onload = this.element.onreadystatechange = Function.createDelegate(this, function () { | |
if (!this.loaded && (!this.element.readyState || this.element.readyState == 'loaded' || this.element.readyState == 'complete')) { | |
this.loaded = true; | |
utils.callCb(this.callback, null, this); | |
this.element.onload = this.element.onreadystatechange = null; | |
} | |
}); | |
} | |
/** | |
* Loads the script into the DOM through normal HTML means. | |
* | |
* @method | |
*/ | |
Script.prototype.load = function() { | |
var head = document.getElementsByTagName('head')[0]; | |
if (this.src) { | |
head.appendChild(this.element); | |
} | |
}; | |
/** | |
* SPScript Type | |
* @typedef SPScript | |
* @type {object} | |
* @property {boolean} loaded Whether the script has been loaded or not. | |
* @property {function} callback Function to be called when loaded. | |
* @property {object} element DOM HTML script element. | |
* @property {string} src Source of the script. | |
*/ | |
/** | |
* Loads the script into | |
*/ | |
function SPScript(name, cb) { | |
Script.call(this, name, cb); | |
//this.load(); | |
} | |
SPScript.prototype = Object.create(Script.prototype); | |
SPScript.prototype.constructor = SPScript; | |
/** | |
* Loads the script by SP means. | |
* | |
* @param {function} callAfterFn Callback function. | |
*/ | |
SPScript.prototype.load = function(callAfterFn) { | |
callAfterFn = callAfterFn || 'SP.ClientContext'; // '_spBodyOnLoadCalled'; | |
SP.SOD.executeFunc(this.name, callAfterFn, function(){ | |
console.log(this.name + ' loaded'); | |
utils.callCb(this.cb); | |
}); | |
}; | |
/** USER **/ | |
/** | |
* User Type | |
* @typedef User | |
* @type {object} | |
* @property {integer} Id User ID. | |
* @property {Web} site SP Web. | |
* @property {SP.User} waitMsg Message to be displayed. | |
* @property {Permissions} permissions User Permissions | |
*/ | |
/** | |
* Permissions Type | |
* @typedef Permissions | |
* @type {object} | |
* @property {SP.BasePermissions} base SharePoint Permissions. | |
* @property {boolean} loaded Whether the permissions have been loaded. | |
*/ | |
/** | |
* User class | |
* | |
* @class | |
* @requires {@link Web} | |
*/ | |
function User(id) { | |
this.Id = id || undefined; | |
this.site = new Web(); | |
this.currentUser = this.site.web.get_currentUser(); | |
this.permissions = { | |
base: new SP.BasePermissions(), | |
loaded: false | |
}; | |
/** | |
* Gets user by ID. | |
* | |
* @method | |
* @param {function} onSuccess Called on AJAX success. | |
* @param {function} onFail Called on AJAX error. | |
*/ | |
this.getUserById = function(onSuccess, onFail) { | |
utils.doAjax( | |
'/_api/Web/GetUserById(' + this.Id + ')', | |
onSuccess, | |
onFail | |
); | |
}; | |
} | |
/** | |
* Get the SharePoint permission kind (integer) | |
* | |
* @method | |
* @param {string} per Permission by string. | |
* @returns {integer} SP.PermissionKind Integer. | |
*/ | |
User.prototype.getPermissionKind = function(per) { | |
return SP.PermissionKind[per]; | |
}; | |
/** | |
* Gets all SP Permission Kinds | |
* | |
* @method | |
* @returns {object} Associative array of Permission - SP.PermissionKind value. | |
*/ | |
User.prototype.getPermissionKinds = function() { | |
return { | |
emptyMask: SP.PermissionKind.emptyMask, // Has no permissions on the Web site. Not available through the user interface. | |
viewListItems: SP.PermissionKind.viewListItems, // View items in lists, documents in document libraries, and Web discussion comments. | |
addListItems: SP.PermissionKind.addListItems, // Add items to lists, add documents to document libraries, and add Web discussion comments. | |
editListItems: SP.PermissionKind.editListItems , // Edit items in lists, edit documents in document libraries, edit Web discussion comments in documents, and customize Web Part Pages in document libraries. | |
deleteListItems: SP.PermissionKind.deleteListItems, // Delete items from a list, documents from a document library, and Web discussion comments in documents. | |
approveItems: SP.PermissionKind.approveItems, // Approve a minor version of a list item or document. | |
openItems: SP.PermissionKind.openItems, // View the source of documents with server-side file handlers. | |
viewVersions: SP.PermissionKind.viewVersions, // View past versions of a list item or document. | |
deleteVersions: SP.PermissionKind.deleteVersions, // Delete past versions of a list item or document. | |
cancelCheckout: SP.PermissionKind.cancelCheckout, // Cancel or check in a document that is checked out to another user. | |
managePersonalViews: SP.PermissionKind.managePersonalViews, // Create, change, and delete personal views of lists. | |
manageLists: SP.PermissionKind.manageLists, // Create and delete lists, add or remove columns in a list, and add or remove public views of a list. | |
viewFormPages: SP.PermissionKind.viewFormPages, // View forms, views and application pages, and enumerate lists. | |
open: SP.PermissionKind.open, // Open a Web site, list, or folder to access items inside the container. | |
viewPages: SP.PermissionKind.viewPages, // View pages in a Web site. | |
addAndCustomizePages: SP.PermissionKind.addAndCustomizePages, // Add, change, or delete HTML pages, and edit the Web site using an editor that is compatible with Microsoft SharePoint Server 2010. | |
applyThemeAndBorder: SP.PermissionKind.applyThemeAndBorder, // Apply a theme or borders to the Web site. | |
applyStyleSheets: SP.PermissionKind.applyStyleSheets, // Apply a style sheet (.css file) to the Web site. | |
viewUsageData: SP.PermissionKind.viewUsageData, // View reports on Web site usage. | |
createSSCSite: SP.PermissionKind.createSSCSite, // Create a Web site using Self-Service Site Creation. | |
manageSubwebs: SP.PermissionKind.manageSubwebs, // Create subsites such as team sites, Meeting Workspace sites, and Document Workspace sites. | |
createGroups: SP.PermissionKind.createGroups, // Create a group of users that can be used anywhere within the site collection. | |
managePermissions: SP.PermissionKind.managePermissions, // Create and change permission levels on the Web site and assign permissions to users and groups. | |
browseDirectories: SP.PermissionKind.browseDirectories, // Enumerate files and folders on a site using Microsoft SharePoint Designer and WebDAV interfaces. | |
browseUserInfo: SP.PermissionKind.browseUserInfo, // View information about the users of the Web site. | |
addDelPrivateWebParts: SP.PermissionKind.addDelPrivateWebParts, // Add or remove personal Web Parts on a Web Part Page. | |
updatePersonalWebParts: SP.PermissionKind.updatePersonalWebParts, // Update Web Parts to display personalized information. | |
manageWeb: SP.PermissionKind.manageWeb, // Grant the ability to perform all administration tasks for the Web site and manage Web site content. | |
useClientIntegration: SP.PermissionKind.useClientIntegration, // Launch client applications on the server. Otherwise, users must work on documents locally and upload changes. | |
useRemoteAPIs: SP.PermissionKind.useRemoteAPIs, // Use SOAP, WebDAV, or Microsoft SharePoint Designer interfaces to access the Web site. | |
manageAlerts: SP.PermissionKind.manageAlerts, // Manage alerts for all users of the Web site. | |
createAlerts: SP.PermissionKind.createAlerts, // Create e-mail alerts. | |
editMyUserInfo: SP.PermissionKind.editMyUserInfo, // Change user information, such as adding a picture. | |
enumeratePermissions: SP.PermissionKind.enumeratePermissions, // Enumerates permissions on the Web site, list, folder, document, or list item. | |
fullMask: SP.PermissionKind.fullMask // Has all permissions on the Web site. Not available through the user interface. | |
}; | |
}; | |
/** | |
* Determine whether a user has a specific permission | |
* | |
* @method | |
* @param {string|integer} permission Permission (SP.PermissionKind integer) being checked. | |
* @returns {boolean} Whether the current user has the permission. | |
*/ | |
User.prototype.hasPermission = function(permission) { | |
if (this.permissions.loaded && 'function' === typeof this.has) { | |
if ('string' === typeof permission) { | |
// return this.has(this.getPermissionKind(permission)); | |
return this.has(SP.PermissionKind[permission]); | |
} | |
return this.has(permission); | |
} else { | |
return null; | |
} | |
}; | |
/** | |
* Loads the current user's permissions. | |
* | |
* @method | |
* @param {function} onSuccess Called on async query success. | |
* @param {function} onFail Called on async query fail. | |
*/ | |
User.prototype.loadPermissions = function(onSuccess, onFail) { | |
this.site.context.load(this.currentUser); | |
this.site.context.load(this.site.web, 'EffectiveBasePermissions'); | |
this.execute( | |
Function.createDelegate(this, function(clientRequest, args) { | |
this.permissions.loaded = true; | |
this.has = this.site.web.get_effectiveBasePermissions().has; | |
utils.callCb(onSuccess, {request: clientRequest, args: args}, this); | |
}), | |
function(data) { | |
console.log('Request failed. ' + data.args.get_message() + '\n' + data.args.get_stackTrace()); | |
utils.callCb(onFail, data, this); | |
} | |
); | |
}; | |
/** | |
* Loads stuff into SP Client Context. | |
* | |
* @method | |
* @param {object} stuff Things to be loaded into the SP context. | |
* @param {function} success Called on AJAX success. | |
* @param {function} error Called on AJAX error. | |
*/ | |
User.prototype.load = function(stuff, onSuccess, onFail) { | |
this.site.context.load(stuff); | |
this.execute( | |
Function.createDelegate(this, onSuccess), | |
function(sender, args) { | |
console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace()); | |
utils.callCb(onFail, {sender: sender, args: args}, this); | |
} | |
); | |
}; | |
/** | |
* Executes an async function on the SP Context. | |
* | |
* @method | |
* @param {function} onSuccess Called on async query success. | |
* @param {function} onFail Called on async query fail. | |
*/ | |
User.prototype.execute = function(onSuccess, onFail) { | |
utils.execute(this.site.context, this, onSuccess, onFail); | |
}; | |
/** | |
* Gets the current user's information via REST | |
* | |
* @method | |
*/ | |
User.prototype._getCurrentUser = function() { | |
if (this._currentUser) { | |
return this._currentUser; | |
} | |
utils.doAjax( | |
'/_api/sp.userprofiles.peoplemanager/GetMyProperties', | |
function (data) { | |
console.log(data); | |
this._currentUser = data.d; | |
} | |
); | |
}; | |
/** LIST **/ | |
/** | |
* List Type | |
* @typedef List | |
* @type {object} | |
* @property {Web} site SP Web. | |
* @property {SP.ListCollection} lists SP Lists. | |
* @property {SP.List} list SP List. | |
* @property {boolean} loaded Whether the list has been loaded into the SP Context. | |
* @property {integer} templateId List template ID. | |
* @property {string} name Name/Title of list. | |
*/ | |
/** | |
* List class | |
* | |
* @class | |
* @requires {@link Web} | |
*/ | |
function List(name) { | |
this.site = new Web(); | |
this.list = undefined; | |
this.lists = undefined; | |
this.loaded = false; | |
this.templateId = g_wsaListTemplateId; | |
this.name = name || undefined; | |
this.loadList(); | |
} | |
/** | |
* Loads the list in the context. | |
*/ | |
List.prototype.loadList = function() { | |
this.list = this.getList(); | |
this.load(this.list, function() { | |
this.loaded = true; | |
this.baseTemplate = this.list.get_baseTemplate(); | |
this.baseType = this.list.get_baseType(); | |
//this.items = this.list.getItems(); | |
this.title = this.list.get_title(); | |
this.description = this.list.get_description(); | |
this.contentTypes = this.list.get_contentTypes(); | |
}); | |
}; | |
/** | |
* Loads stuff into SP Client Context. | |
* | |
* @method | |
* @param {object} stuff Things to be loaded into the SP context. | |
* @param {function} success Called on AJAX success. | |
* @param {function} error Called on AJAX error. | |
*/ | |
List.prototype.load = function(stuff, onSuccess, onFail) { | |
this.site.context.load(stuff); | |
this.execute(onSuccess, onFail); | |
}; | |
/** | |
* Executes an async function on the SP Context. | |
* | |
* @method | |
* @param {function} onSuccess Called on async query success. | |
* @param {function} onFail Called on async query fail. | |
*/ | |
List.prototype.execute = function(onSuccess, onFail) { | |
utils.execute(this.site.context, this, onSuccess, onFail); | |
}; | |
/** | |
* Gets the SP list (via JSOM). | |
* | |
* @returns {SP.List} SP List. | |
*/ | |
List.prototype.getList = function () { | |
if (this.lists && this.list) { | |
return this.list; | |
} | |
this.lists = this.site.web.get_lists(); | |
if (this.name) { | |
this.list = this.lists.getByTitle(this.name); | |
} else { | |
this.list = this.lists.getById(_spPageContextInfo.pageListId); | |
} | |
return this.list; | |
}; | |
/** | |
* Gets the fields of a SP List (via REST). | |
*/ | |
List.prototype.getFields = function() { | |
utils.doAjax( | |
"/_api/lists/getbytitle('" + this.name + "')?$select=Fields&$expand=Fields", | |
// success | |
function (data) { | |
this.fields = data.d.Fields.results; | |
for (i = 0; i < fields.length; i++) { | |
console.log( | |
"Title: " + fields[i].Title + " | " + | |
"Internal Name: " + fields[i].InternalName + " | " + | |
"Type: " + fields[i].TypeAsString + " | " + | |
"GUID: " + fields[i].Id + " " | |
); | |
} | |
} | |
); | |
}; | |
/** SURVEY **/ | |
/** | |
* Survey Type | |
* @typedef Survey | |
* @type {object} | |
* @property {Web} site SP Web. | |
* @property {SP.ListCollection} lists SP Lists. | |
* @property {SP.List} list SP List. | |
* @property {boolean} loaded Whether the list has been loaded into the SP Context. | |
* @property {integer} templateId List template ID. | |
* @property {string} name Name/Title of list. | |
*/ | |
/** | |
* Survey class | |
* | |
* @class | |
* @requires {@link Web} | |
* @requires {@link List} | |
* @requires {@link Modal} | |
*/ | |
function Survey(name) { | |
List.call(this, name); | |
} | |
Survey.prototype = Object.create(List.prototype); | |
Survey.prototype.constructor = Survey; | |
/** | |
* Gets the number of survey submissions made. | |
* | |
* @method | |
* @param {function} User Survey Callback. | |
*/ | |
Survey.prototype.getUserSurveySubmissions = function(userSurveyCb) { | |
var items, | |
query = new SP.CamlQuery(); | |
query.set_viewXml('<View><Where><Eq><FieldRef Name="Author"/><Value Type="Integer"><UserID Type="Integer"/></Value></Eq></Where></View>'); | |
items = this.list.getItems(query); | |
this.load(items, | |
Function.createDelegate(this, function() { | |
var submissionCount = items.get_count(); | |
console.log('getSubmissions Success'); | |
utils.callCb(userSurveyCb, submissionCount, this); | |
}), | |
Function.createDelegate(this, function() { | |
console.log('getSubmissions Failed'); | |
utils.callCb(userSurveyCb, null, this); | |
}) | |
); | |
}; | |
/** | |
* Hides a specific element. | |
* | |
* @method | |
* @uses action | |
* @param {string} option Option for action to be taken. | |
*/ | |
Survey.prototype.hide = function(option) { | |
this.action('hide', option); | |
}; | |
/** | |
* Hides a specific elements. | |
* | |
* @method | |
* @uses actionItems | |
* @param {object} items Items for hide action to be taken. | |
*/ | |
Survey.prototype.hideItems = function(items) { | |
this.actionItems('hide', items); | |
}; | |
/** | |
* Hides a specific element. | |
* | |
* @method | |
* @uses action | |
* @param {string} option Option for action to be taken. | |
*/ | |
Survey.prototype.remove = function(option) { | |
this.action('remove', option); | |
}; | |
/** | |
* Removes a specific elements. | |
* | |
* @method | |
* @uses actionItems | |
* @param {object} items Items for remove action to be taken. | |
*/ | |
Survey.prototype.removeItems = function(items) { | |
this.actionItems('remove', items); | |
}; | |
/** | |
* Takes action on a specific element. | |
* Possible actions: "hide" or "remove" | |
* | |
* @method | |
* @param {string} action Action to be taken. | |
* @param {string} option Item/option for action to be taken. | |
*/ | |
Survey.prototype.action = function(action, option) { | |
var jQelement, | |
selectors = { | |
AllResponses: "#diidResultsByUser", | |
GraphicalSummary: "#diidSurveyResults", | |
ListActionsMenu: "id$='ListActionsMenu'", | |
ViewSelectorMenu: "id$='ViewSelectorMenu'", | |
SaveAndClose: "input[type='button']" | |
}; | |
if (!selectors[option]) { | |
return; | |
} | |
switch(option) { | |
case 'ViewSelectorMenu': | |
// console.log(action + ' ViewSelectorMenu'); | |
jQelement = $("a[id$='ViewSelectorMenu']").closest('table').closest('td'); | |
break; | |
case 'ListActionsMenu': | |
// console.log(action + ' ListActionsMenu'); | |
jQelement = $("a[id$='ListActionsMenu']").closest('td'); | |
break; | |
case 'SaveAndClose': | |
// console.log(action + ' SaveAndClose'); | |
jQelement = $(selectors[option]); | |
/* | |
var x = document.getElementsByTagName("input"); | |
for (var i=0; i < x.length; i++) { | |
if (x.item(i).type === "button" && x.item(i).value === "Save and Close") { | |
x.item(i).style.display = "none"; | |
} | |
} | |
*/ | |
break; | |
default: | |
// console.log('default: ' + action + ' ' + option); | |
jQelement = $(selectors[option]).closest('tr'); | |
break; | |
} | |
switch(action) { | |
case 'hide': | |
jQelement.hide(); | |
break; | |
case 'remove': | |
jQelement.remove(); | |
break; | |
} | |
}; | |
/** | |
* Takes action on a specific elements. | |
* | |
* @method | |
* @uses actionItems | |
* @param {string} action Action to be taken. | |
* @param {object} items Items for action to be taken. | |
*/ | |
Survey.prototype.actionItems = function(action, items) { | |
for (var key in items) { | |
if (items.hasOwnProperty(key) && items[key]) { | |
this.action(action, key); | |
} | |
} | |
}; | |
/** | |
* Adds a good UX for response error message. | |
*/ | |
Survey.prototype.addSingleResponseErrorMessage = function() { | |
var that = this; | |
window.NewItem2 = (function () { | |
var NewItem2Orig = window.NewItem2; | |
return Function.createDelegate(that, function() { | |
var evt = arguments[0]; | |
var url = arguments[1]; | |
//Read survey for current user to find out if he have already submitted | |
that.getUserSurveySubmissions(function(submissionsCount){ | |
//if submitted then display custom message | |
if (submissionsCount > 0) { | |
// debugger; | |
console.log('You have already submitted to this survey.'); | |
var d = new Modal({title: 'You have already submitted to this survey.'}, 'normal'); | |
d.show(); | |
} | |
//if not, call original function for opening response form | |
else { | |
// debugger; | |
NewItem2Orig(evt, url); | |
} | |
}); | |
}); | |
})(); | |
}; | |
/** FUNCTIONS **/ | |
/** | |
* Determines whether the current context/list is a SharePoint list via JSOM. | |
* | |
* @private | |
* @link http://joelblogs.co.uk/2011/06/16/sharepoint-2010-base-types-list-template-and-definition-ids-and-content-types-ids/ | |
* @param {string} guid GUID of the current List. | |
*/ | |
function _isSurvey(guid) { | |
guid = guid || _spPageContextInfo.pageListId; | |
var deferred = $.Deferred(), | |
site = new Web(), | |
lists = site.web.get_lists(), | |
list = lists.getById(guid); | |
site.context.load(list); | |
site.context.executeQueryAsync( | |
Function.createDelegate(this, function(clientRequest, args) { | |
if(4 === list.get_baseType() || 102 === list.get_baseTemplate()) { | |
var s = new Survey(list.get_title()); | |
deferred.resolve(s); | |
} else { | |
deferred.resolve(false); | |
} | |
}), | |
Function.createDelegate(this, function(sender, args) { | |
var msg = 'Request failed. ' + args.get_message() + '\n' + args.get_stackTrace(); | |
console.log(msg); | |
deferred.resolve(false); | |
}) | |
); | |
return deferred.promise(); | |
// return deferred.resolve().pipe(function(d){console.log('PIPED RESULT: ' + d); return d;}); | |
//return deferred.resolve() | |
} | |
/** | |
* Determines whether the current context/list is a SharePoint list by list template ID. | |
* | |
* @private | |
* @param {integer} id ID of current list template. | |
* @returns {boolean|null} Whether the current list is a Survey List. | |
*/ | |
function _isSurveyByTemplate(id) { | |
id = id || g_wsaListTemplateId; | |
if ('undefined' !== typeof id) { | |
return (102 === id); | |
} | |
return null; | |
} | |
/** | |
* Determines whether the current context/list is a SharePoint list by list type ID. | |
* | |
* @private | |
* @param {integer} id ID of current list type. | |
* @returns {boolean|null} Whether the current list is a Survey List. | |
*/ | |
function _isSurveyByType(id) { | |
if ('undefined' !== typeof id) { | |
return (4 === id); | |
} | |
return null; | |
} | |
/** | |
* Determines whether the current context/list is a SharePoint list. | |
* | |
* @private | |
* @param {integer} id ID of current list type. | |
* @returns {boolean|null} Whether the current list is a Survey List. | |
*/ | |
function isSurvey(id) { | |
id = id || g_wsaListTemplateId; | |
if ('undefined' === typeof id) { | |
if ('undefined' !== typeof ctx) { | |
id = ctx.listTemplate || ctx.listBaseType; | |
} | |
} | |
if ('undefined' !== typeof id) { | |
return (102 === +id || 4 === +id); | |
} | |
// Still unsure what we have! | |
return null; | |
} | |
/** | |
* Add isSurvey to the List Class | |
* | |
* @see isSurvey | |
* @method | |
*/ | |
List.prototype.isSurvey = isSurvey; | |
/** | |
* Determines whether the current context/page contains a Survey (web part) via REST. | |
* | |
* @private | |
*/ | |
wps.containsSurvey = function () { | |
// Check for List Web Parts using ECB (Edit Control Block) | |
$('div[id^="ECBItems_"]').each(function (i,e) { | |
var m, | |
re = /{([a-zA-Z0-9-]*)}/; | |
if ((m = re.exec($(e).attr('id'))) !== null) { | |
if (m.index === re.lastIndex) { | |
re.lastIndex++; | |
} | |
utils.doAjax( | |
"/_api/Web/Lists(guid'" + m[1] + "')", | |
function(data) { | |
if (isSurvey(data.d.BaseTemplate)) { | |
// Got Survey!! | |
var s = new Survey(data.d.Title); | |
wps.doSurvey(s); | |
} | |
}, | |
null, | |
this | |
); | |
// View your result using the m-variable. | |
// eg m[ 0] etc. | |
} | |
// Regex, parse ID attributes | |
// Check to see if list is a survey via _isSurvey(name) | |
}); | |
}; | |
/** | |
* Starts everything off!! | |
* | |
* @private | |
* @function | |
*/ | |
wps.init = function() { | |
// For responsiveness, let's get rid of empty blank images | |
$('img').each(function(i,e) { | |
if ($(e).attr('src').includes('blank.gif')) { | |
$(e).attr('width', 1); | |
} | |
}); | |
// Let's GO!! | |
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() { | |
wps.run(); | |
}); | |
}; | |
/** | |
* The Initial Work Horse. Loads the User, User's permissions, & checks the context for a survey. | |
* | |
* @private | |
* @function | |
*/ | |
wps.run = function() { | |
wps.user = new User(); | |
wps.user.loadPermissions(function() { | |
console.log('Permissions loaded'); | |
wps.checkSurvey(); | |
}, function() { | |
console.log('Permissions failed'); | |
}); | |
}; | |
/** | |
* Checking for Survey List | |
* | |
* @function | |
* @private | |
*/ | |
wps.checkSurvey = function() { | |
// Check if we have a survey | |
var amIaSurveyPage = isSurvey(); | |
if (null === amIaSurveyPage) { | |
console.log('amIaSurveyPage: UNSURE, val: null'); | |
// Means we still are not sure what we have... | |
_isSurvey().then(function(d){ | |
if (d) { | |
console.log('AFTER _isSurvey: '); | |
console.log(d); | |
wps.doSurvey(d); | |
} | |
}); | |
} else if (false !== amIaSurveyPage) { | |
console.log('Have a survey! doSurvey w/o sending List information'); | |
wps.doSurvey(); | |
} else { | |
console.log('Does page contain survey: running wps.containsSurvey()'); | |
// Check if page contains a survey | |
wps.containsSurvey(); | |
} | |
}; | |
/** | |
* The Survey Work. Hides/Removes used & adds UX Single Response Error Message. | |
* | |
* @private | |
* @function | |
* | |
* @param {Survey} s Survey list. | |
*/ | |
wps.doSurvey = function(s) { | |
if ('undefined' === s || 'undefined' === typeof s) { | |
s = new Survey(); | |
} | |
console.log("wps.user.hasPermission('manageweb')"); | |
if (!wps.user.hasPermission('manageWeb')) { | |
s.hideItems(OPTIONS.hide); | |
s.removeItems(OPTIONS.remove); | |
} else { | |
console.log('Not hiding anything for admins'); | |
} | |
// Prevent Ugly Error Page if User has taken Survey | |
//window.PreSaveItem = wps.PreSaveItem; | |
s.addSingleResponseErrorMessage(); | |
// Redirect Survey | |
wps.redirectSurvey(); | |
}; | |
/** | |
* Changes the action page of the survey optionally redirecting it to another page. | |
*/ | |
wps.redirectSurvey = function() { | |
var oldPostbackUrl = $('form#aspnetForm').get(0).action, | |
currentSourceValue = GetUrlKeyValue('Source', true, oldPostbackUrl); | |
$('input[id$=SaveItem]').each(function(index, element){ | |
$(element).removeAttr('onclick'); | |
$(element).on('click', function(event) { | |
event.preventDefault(); | |
//event.stopPropogation(); | |
var elementName = $(this).attr('name'), | |
newPostbackUrl = oldPostbackUrl.replace(currentSourceValue, OPTIONS.redirectPage); | |
if (!PreSaveItem()) { | |
return false; | |
} | |
WebForm_DoPostBackWithOptions( | |
new WebForm_PostBackOptions(elementName, "", true, "", newPostbackUrl, false, true) | |
); | |
}); | |
}); | |
/* HAVEN'T TRIED THIS ONE YET | |
$('input[type="button"]').each(function(i,e){ | |
if ('Finish' === $(e).val()) { | |
$(e).attr('onclick', "javascript: {ddwrt:GenFireServerEvent('__commit;__redirect={" + OPTIONS.redirectPage + "}')}"); | |
} | |
}); | |
*/ | |
}; | |
/** | |
* PreSaveItem | |
* | |
* @deprecated | |
*/ | |
wps.PreSaveItem = function () { | |
console.log('PreSaveItem'); | |
}; | |
// Expose classes | |
WPS = $.extend({}, WPS, { | |
Survey: Survey, | |
List: List, | |
User: User, | |
Web: Web, | |
Script: Script, | |
SPScript: SPScript, | |
Modal: Modal, | |
utils: utils | |
}); | |
if (debug) { | |
WPS = $.extend({}, WPS, {wps:wps}); | |
} | |
// Use jQuery | |
/* | |
$(document).ready(function() { | |
wps.init(); | |
}); | |
*/ | |
// GO TIME! | |
_spBodyOnLoadFunctionNames.push('WPS.init'); | |
})(jQuery, window, document, ClientSurvey); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
ruizkunis commentedFeb 16, 2017
Hi, how can I use this script ?