Created
August 1, 2015 01:04
-
-
Save wpsmith/88e9f6ed7a6a933852bd to your computer and use it in GitHub Desktop.
JavaScript: SharePoint Survey Customizations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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
Hi, how can I use this script ?