Skip to content

Instantly share code, notes, and snippets.

@wpsmith
Created August 1, 2015 01:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wpsmith/88e9f6ed7a6a933852bd to your computer and use it in GitHub Desktop.
Save wpsmith/88e9f6ed7a6a933852bd to your computer and use it in GitHub Desktop.
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);
@ruizkunis
Copy link

Hi, how can I use this script ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment