Dropdown field - first item should be blank - For more than one field (Sharepoint) - sharepoint

I was looking for a solution to the problem of getting a blank default when using a lookup in a field in Sharepoint. Kit Menke's solution to "Dropdown field - first item should be blank" question works perfectly for my first field with a lookup. But I can't make it work if have more that one field in the same list where I need to insert a blank for each lookup field (works only for the first field). I tried adding a new "Web Part" and applying the same code to the second field, but doesn't work. Any ideas? Thanks in advance

Follow-up to my answer here: Dropdown field - first item should be blank
Version 2.0 allows you to add the names of your dropdowns to dropdownNames in the MyCustomExecuteFunction function. As with the first one, this will work only with required single select lookup fields. Also, in order to edit the page again and update your Content Editor Web Part you may have to choose a value for your dropdowns otherwise you get the dreaded An unexpected error has occurred.. Good luck! :D
<script type="text/javascript">
function GetDropdownByTitle(title) {
var dropdowns = document.getElementsByTagName('select');
for (var i = 0; i < dropdowns.length; i++) {
if (dropdowns[i].title === title) {
return dropdowns[i];
}
}
return null;
}
function GetOKButtons() {
var inputs = document.getElementsByTagName('input');
var len = inputs.length;
var okButtons = [];
for (var i = 0; i < len; i++) {
if (inputs[i].type && inputs[i].type.toLowerCase() === 'button' &&
inputs[i].id && inputs[i].id.indexOf('diidIOSaveItem') >= 0) {
okButtons.push(inputs[i]);
}
}
return okButtons;
}
function AddValueToDropdown(oDropdown, text, value, optionnumber){
var options = oDropdown.options;
var option = document.createElement('OPTION');
option.appendChild(document.createTextNode(text));
option.setAttribute('value',value);
if (typeof(optionnumber) == 'number' && options[optionnumber]) {
oDropdown.insertBefore(option,options[optionnumber]);
}
else {
oDropdown.appendChild(option);
}
oDropdown.options.selectedIndex = 0;
}
function WrapClickEvent(element, newFunction) {
var clickFunc = element.onclick;
element.onclick = function(event){
if (newFunction()) {
clickFunc();
}
};
}
function MyCustomExecuteFunction() {
// **** ADD YOUR REQUIRED SINGLE SELECT FIELDS HERE ***
var dropdownNames = [
'Large Lookup Field',
'My Dropdown Field'
];
var dropdownElements = [];
for (var d = 0; d < dropdownNames.length; d++) {
// find the dropdown
var dropdown = GetDropdownByTitle(dropdownNames[d]);
// comment this IF block out if you don't want an error displayed
// when the dropdown can't be found
if (null === dropdown) {
alert('Unable to get dropdown named ' + dropdownNames[d]);
continue;
}
AddValueToDropdown(dropdown, '', '', 0);
// collect all of our dropdowns
dropdownElements.push(dropdown);
}
// add a custom validate function to the page
var funcValidate = function() {
var isValid = true;
var message = "";
for (var d = 0; d < dropdownElements.length; d++) {
if (0 === dropdownElements[d].selectedIndex) {
// require a selection other than the first item (our blank value)
if (isValid) {
isValid = false;
} else {
message += "\n"; // already had one error so we need another line
}
message += "Please choose a value for " + dropdownNames[d] + ".";
}
}
if (!isValid) {
alert(message);
}
return isValid;
};
var okButtons = GetOKButtons();
for (var b = 0; b < okButtons.length; b++) {
WrapClickEvent(okButtons[b], funcValidate);
}
}
_spBodyOnLoadFunctionNames.push("MyCustomExecuteFunction");
</script>

How about prepending a null option to the select menu of sharepoint.Like,
$('#idOfSelectMenu').prepend('<option value="" selected>(None)</option>');
I used this approach and append this code only in the NewForm.aspx because in EditForm.aspx it will override the selected option.

Related

Unable to delete Mutiple Comp from listbox with Extendscript

I can't perform multiple delette from my listbox although I made the listbox mutiselect Why ??
I need your help . You can see the full Script down there.
(function(){
$.win = new Window("palette");
var win = $.win;
win.orientation = "column";
win.alignChildren = ["center", "top"];
win.spacing = 10;
win.margins = 16;
var listbox1 = win.add("listbox", undefined, undefined, { name: "listbox1", multiselect: true, columnTitles: "Max", showHeaders: true });
listbox1.preferredSize.width = 136;
listbox1.preferredSize.height = 208;
var button1 = win.add("button", undefined, undefined, { name: "button1" });
button1.text = "Search";
var button2 = win.add("button", undefined, undefined, { name: "button2" });
button2.text = "Delete";
win.show();
var myNewArray = [];
button1.onClick = function Search() {
var compsArray = new Array();
var myProj = app.project;
myNewArray = [];
listbox1.removeAll();
for (var i = 1; i <= myProj.numItems; i++) {
if (myProj.item(i) instanceof CompItem) {
myNewArray = compsArray[compsArray.length] = myProj.item(i);
listbox1.add("item", myNewArray.name);
}
}
}
button2.onClick = function deletecomps() {
for (var s = 1; s <= app.project.numItems; s ++) {
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection))) {
myComp = app.project.item(s);
break;
}
}
app.project.item(s).remove ();
}
})();
You can see an image to clarify the script in AE
Your problem is that listbox1.selection in line 34
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection))) {
is an array, and you're trying to match it to a string returned by app.project.item(s).name which is never going to match.
Also, what are you trying to achieve with the lines
myComp = app.project.item(s);
break;
Here's the onClick function, but it works. It loops through the selection, and looks for a matching project item, based on the text of the listbox matching the comp's name. This is dangerous, because identical comp names would create false positives. I strongly suggest you don't use this technique in production code, because it will definitely cause problems for your users.
Also I'd turn the part wherre you populate the list into a separate function, and call it after you click delete, so that the list is refreshed, because at the moment the list stays the same, even after the comp is deleted.
button2.onClick = function deletecomps() {
for (var b= 0; b < listbox1.selection.length; b++){
for (var s = 1; s <= app.project.numItems; s ++) {
if ((app.project.item(s) instanceof CompItem) && (app.project.item(s).name.match(listbox1.selection[b].text))) {
app.project.item(s).remove ();
}
}
}
}

Create custom list view with data based on condition and disable oob filter from list view webpart usign JSLink Client Side Rendering

Below is the full code for client side rendering of List View Webpart:
(function () {
var overrideCurrentContext = {};
overrideCurrentContext.OnPreRender = hideRows;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCurrentContext);
})();
function hideRows(ctx) {
var rows = ctx.ListData.Row;
//Hide whole list based on condition
if(masterlistarr.indexOf(currentUser) == -1){
//user not in master list
console.log("no access");
$('#ctl00_PlaceHolderMain_WikiField').before("<div style='height:40px;border:1px solid #AEAEAE;position:relative;text-align:center;color:red;font-weight:bold;padding:20px;'>Access Denied<br>You don't have access please contact Admin!</div>");
$(ctl00_PlaceHolderMain_WikiField).hide();
}
//following code used to disable oob list filter and hide 'new item' feature
else{
//following code used to disable oob list filter and hide 'new item' feature
if(count == 0){
$('.ms-headerSortArrowLink').hide();
$("div.ms-vh-div").attr("filterdisable", "TRUE");
$('#idHomePageNewItem').get(0).nextSibling.remove();
$('#idHomePageNewItem').hide();
}
count++;
// compare specific column value eg."TeamleadFullName" which is of type People and Group and hide rows based on that
for (var i = 0; i < rows.length; i++) {
var curTL = rows[i]["TeamleadFullName"][0].email.toLowerCase();
if(curTL !== currentUser){
// return '';
var rowId = GenerateIIDForListItem(ctx, rows[i]);
var row = document.getElementById(rowId);
// row.style.display = "none";
row.parentNode.removeChild(row);
}
}
}
}
hope this helps

Update link to heading in google docs

In google docs one can easily add headings and link to them from inside of the document. But when the heading text changes, the link text does not change.
Is there a way to change that behavior or update the link text automatically?
I know it is about 1 1/2 years, but maybe this will help. I have had the exact same problem and wrote a function that will update all the links to the headings in a document. Since I could not find any built-in functions or add-ons, the only way was to script it.
Some things to consider:
This needs a current table of contents to work. If you don't have (or do not want) a TOC, you can insert one, run that function and delete it afterwards. Also, I have only tested it with a TOC that contains page numbers.
It will update ALL texts of links to headings in the document. However, links to everything else remain untouched.
Please use at your own risk (maybe try it out in a copy of your document). I have tested it, but the testing could have been more thorough. Also, this is my first in scripting Docs.
Paste this in the Script editor of your doc and run replaceHeadingLinks. Links that the script could not update (because they link to a heading that does not exist anymore) will be output in the console.
function replaceHeadingLinks() {
var curDoc = DocumentApp.getActiveDocument();
var links = getAllLinks_(curDoc.getBody());
var headings = getAllHeadings_(curDoc.getBody());
var deprecatedLinks = []; // holds all links to headings that do not exist anymore.
links.forEach(function(link) {
if(link.url.startsWith('#heading')) {
// get the new heading text
var newHeadingText = headings.get(link.url);
// if the link does not exist anymore, we cannot update it.
if(typeof newHeadingText !== "undefined") {
var newOffset = link.startOffset + newHeadingText.length - 1;
// delete the old text, insert new one and set link
link.element.deleteText(link.startOffset, link.endOffsetInclusive);
link.element.insertText(link.startOffset, newHeadingText);
link.element.setLinkUrl(link.startOffset, newOffset, link.url);
} else {
deprecatedLinks.push(link);
}
}
}
)
// error handling: show deprecated links:
if(deprecatedLinks.length > 0) {
Logger.log("Links we could not update:");
for(var i = 0; i < deprecatedLinks.length; i++) {
var link = deprecatedLinks[i];
var oldText = link.element.getText().substring(link.startOffset, link.endOffsetInclusive);
Logger.log("heading: " + link.url + " / description: " + oldText);
}
} else {
Logger.log("all links updated");
}
}
/**
* Get an array of all LinkUrls in the document. The function is
* recursive, and if no element is provided, it will default to
* the active document's Body element.
*
* #param {Element} element The document element to operate on.
* .
* #returns {Array} Array of objects, vis
* {element,
* startOffset,
* endOffsetInclusive,
* url}
*
* Credits: https://stackoverflow.com/questions/18727341/get-all-links-in-a-document/40730088
*/
function getAllLinks_(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
var curUrl = {};
for (var ch=0; ch < text.length; ch++) {
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
links.push(curUrl); // add to links
curUrl = {};
}
}
}
// edge case: link is at the end of a paragraph
// check if object is empty
if(inUrl && (Object.keys(curUrl).length !== 0 || curUrl.constructor !== Object)) {
links.push(curUrl); // add to links
curUrl = {};
}
}
else {
// only traverse if the element is traversable
if(typeof element.getNumChildren !== "undefined") {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
// exclude Table of Contents
child = element.getChild(i);
if(child.getType() !== DocumentApp.ElementType.TABLE_OF_CONTENTS) {
links = links.concat(getAllLinks_(element.getChild(i)));
}
}
}
}
return links;
}
/**
* returns a map of all headings within an element. The map key
* is the heading ID, such as h.q1xuchg2smrk
*
* THIS REQUIRES A CURRENT TABLE OF CONTENTS IN THE DOCUMENT TO WORK PROPERLY.
*
* #param {Element} element The document element to operate on.
* .
* #returns {Map} Map with heading ID as key and the heading element as value.
*/
function getAllHeadings_(element) {
var headingsMap = new Map();
var p = element.findElement(DocumentApp.ElementType.TABLE_OF_CONTENTS).getElement();
if(p !== null) {
var toc = p.asTableOfContents();
for (var ti = 0; ti < toc.getNumChildren(); ti++) {
var itemToc = toc.getChild(ti).asParagraph().getChild(0).asText();
var itemText = itemToc.getText();
var itemUrl = itemToc.getLinkUrl(0);
var itemDesc = null;
// strip the line numbers if TOC contains line numbers
var itemText = itemText.match(/(.*)\t/)[1];
headingsMap.set(itemUrl,itemText);
}
}
return headingsMap;
}

How to change the default values when add link Sharepoint 2013

In Add Link page, is it possible to change the default values like title, address, show these links to, by using URL parameters?
According to this, it seems possible in sharepoint2010. Does anyone know whether it works in 2013??
If not, is it possible to add a link by post REST API??
This problem can be solved by the steps below.
Add a custom action. Just follow the steps here.
In my case code is as below
SP.SOD.executeFunc("callout.js", "Callout", function() {
var itemCtx = {};
itemCtx.Templates = {};
itemCtx.BaseViewID = 'Callout';
// Define the list template type
itemCtx.ListTemplateType = 101;
itemCtx.Templates.Footer = function(itemCtx) {
// context, custom action function, show the ECB menu (boolean)
return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true);
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
});
function AddCustomAction(renderCtx, calloutActionMenu) {
// Add your custom action
calloutActionMenu.addAction(new CalloutAction({
text: "FAVORITE",
// tooltip: 'This is your custom action',
onClickCallback: function() {
CreateCustomNewQuickLink(renderCtx.CurrentItem.FileLeafRef, renderCtx.CurrentItem.FileRef);
}
}));
// Show the default document library actions
CalloutOnPostRenderTemplate(renderCtx, calloutActionMenu);
}
function CreateCustomNewQuickLink(title, url) {
var urlAddress = $(location).attr('protocol') + "//" + $(location).attr('host') + '/_Layouts/quicklinksdialogformTEST.aspx?Mode=Link' +
'&title=' + encodeURIComponent(title) +
'&url=' + encodeURIComponent(url);
ShowNewQuicklinkPopup(urlAddress, PageRefreshOnDialogClose);
}
Create a new add link page which is copied from "quicklinksdialogform.aspx". I add some javascript as below.
$(init)
function init() {
var args = new Object();
args = GetUrlParms();
if (args["title"] != undefined) {
$(".ms-long")[0].value = decodeURIComponent(args["title"]);
}
if (args["url"] != undefined) {
$(".ms-long")[1].value = decodeURIComponent(args["url"]);
}
}
function GetUrlParms() {
var args = new Object();
var query = location.search.substring(1);
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf('=');
if (pos == -1) continue;
var argname = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos + 1);
args[argname] = unescape(value);
}
return args;
}
It works like below

Table search on a filtered table?

I have a search function that searches a table with 3 columns. I have now implemented a dropdown that filters the table based on a place but when using the search function, it searches the whole table not the items that are left from the dropdown. Below is my function to filter the table but is there anything I can add to filter based on what is being shown and not what the table has as a whole?
Using HTML + JS
function filterTable(event) {
var filter = event.target.value;
var rows = document.querySelector("#rosterTable tbody").rows;
for (var i = 0; i < rows.length; i++) {
var firstCol = rows[i].cells[0].textContent;
var fourthCol = rows[i].cells[3].textContent;
var fifthCol = rows[i].cells[4].textContent;
if (firstCol.indexOf(filter) > -1 || fourthCol.indexOf(filter) > -1 || fifthCol.indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
document.querySelector('#myInput').addEventListener('keyup', filterTable, false);

Resources