Archive for category SharePoint Development
Remove hyperlinks from OOTB list view Web Part using JQuery
Posted by Aleem in SharePoint, SharePoint Development on January 6, 2015
SharePoint 2013 list view Web Part display lookup columns as hyperlinks. Sometime these hyperlinks don’t point to something very useful and do a great job of confusing the users. Here’s a simple script to remove all hyperlinks except the Title from a list view.
function DisableLookupLinksInList() { $("table.ms-listviewtable").find("td.ms-vb2").each(function () { var link = $(this).find("a"); if (link.length > 0) { link.replaceWith("<span>" + link.text() + "</span>"); } }); }
And here the script to remove lookup links from a display form
function DisableLookupLinksInForm() { $("table.ms-formtable").find("td.ms-formbody").each(function () { var link = $(this).find("a"); if (link.length > 0 && link.parent().attr("id") != "SPFieldUserMulti") { link.replaceWith("<span>" + link.text() + "</span>"); } }); }
Customizing SharePoint 2013 OOTB List view using JSLink
Posted by Aleem in SharePoint, SharePoint Development on December 12, 2014
JSLink in SharePoint 2013 is a nice and only way to keep all the power of OOTB list view Web Part and add your own customizations. Here’s a simple example of highlighting an item row based on a column value.
(function () { var context = {}; context.Templates = {}; context.OnPostRender = [HighlightRowOverride]; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(context); })(); function HighlightRowOverride(context) { for (var i = 0; i &lt; context.ListData.Row.length; i++) { var listItem = context.ListData.Row[i]; if (listItem[&quot;_Status&quot;] == &quot;Change requested&quot;) { var iid = GenerateIIDForListItem(context, listItem); var row = document.getElementById(iid); if (row.length != 0) { $(row).addClass(&quot;row-highlight&quot;); } } } }
Below is an example of an another customized list view Web Part, the grey table has been added through JSLink.
Pritam Baldota has explained in his MSDN Magazine article different ways of deploying and adding JSLink scripts the list view Web Parts.
Change SharePoint list item permissions to Read only programmatically
Posted by Aleem in C#, SharePoint, SharePoint Development on October 1, 2014
It’s a simple task but keeps slipping my mind, so I though it’s better to save it in the public diary.
So I have a Projects and Tasks master detail lists. When a project is complete, it should become read only together with all its tasks. If it was for only the Project list, I could use the SharePoint designer workflow to change the item permissions.
My projects and tasks lists have ‘Contribute’ and a custom permissions level called ‘Contribute without delete’ assigned to multiple user groups. And I wanted to change all the Contribute access to Read access upon completion of the project.
Here’s the function I wrote,
public void MakeItemReadonly(SPWeb web, SPListItem item, string permissionToReplace, bool exactMatchOnly) { List<SPPrincipal> principals = new List<SPPrincipal>(); foreach (SPRoleAssignment roleAss in item.RoleAssignments) { foreach (SPRoleDefinition roleDef in roleAss.RoleDefinitionBindings) { // condition based on the flag exactMatchOnly if ((exactMatchOnly?string.Compare(roleDef.Name,permissionToReplace,true)==0: roleDef.Name.Contains(permissionToReplace))) principals.Add(roleAss.Member); } } SPRoleAssignment assignment; item.BreakRoleInheritance(true); SPRoleDefinition role = web.RoleDefinitions.GetByType(SPRoleType.Reader); foreach (SPPrincipal principal in principals) { // remove the role assignment item.RoleAssignments.Remove(principal); // Now add the read role to the same principal assignment = new SPRoleAssignment(principal); assignment.RoleDefinitionBindings.Add(role); item.RoleAssignments.Add(assignment); } }
And called the above function the following way,
MakeItemReadonly(web, listItem, "Contribute", false);
Problem with multiple HTML properties in user profile
Posted by Aleem in SharePoint, SharePoint Development on December 19, 2013
Recently I was configuring user profiles in SharePoint 2013 and I had to add several custom user properties including html fields. All other properties worked find except html ones. Html properties showed up fine on edit profile page, I entered text and saved the profile, but when I opened my profile again for edit only the last property had value and others where empty. After some investigation I figured out that the EditProfile.aspx in 15 hive had JavaScript which can’t fill in multiple html properties, it’s a bug which has not been fixed until December 2013.
I had three properties on the page, biography, qualifications and expertise, as in the picture below
EditProfile.aspx contains the values of properties in hidden fields as;
<input name="ProfileEditorEditBiography_hiddenRTEField" id="ProfileEditorEditBiography_hiddenRTEField" type="hidden" value="Bio"/>
<input name="ProfileEditorEditQualifications_hiddenRTEField" id="ProfileEditorEditQualifications_hiddenRTEField" type="hidden" value="Qualification"/>
<input name="ProfileEditorEditExperties_hiddenRTEField" id="ProfileEditorEditExperties_hiddenRTEField" type="hidden" value="Skills and stuff"/>
The JavaScript code the edit profile page generates to fill the properties is
The problem in the above code is obvious, it has three functions which are supposed to set values in biography, qualification and expertise fields, but all three functions have the same name. When they get pushed into _spBodyOnLoadFunctionNames, the second push call overwrites the first one and the third push overwrites the second function in the stack, leaving only the last function in the stack to be called.
The solution was to modify this page, and add my own javascript code, which would set proper values to proper fields.
Here’s the code I added inside AdditionalPageHead to fix the problem.
<script type="text/javascript">
_spBodyOnLoadFunctionNames.push('RePopulateEditableRegion');
function RePopulateEditableRegion(){
// SETTING BIOGRAPHY PROPERTY VALUE
var editableRegion = document.querySelector('[InputFieldId=ProfileEditorEditBiography_hiddenRTEField]');
if (editableRegion) {
var field = document.getElementById("ProfileEditorEditBiography_hiddenRTEField");
if (field) {
editableRegion.innerHTML = field.value;
}
}
// SETTING QUALIFICATIONS PROPERTY VALUE
editableRegion = document.querySelector('[InputFieldId=ProfileEditorEditQualifications_hiddenRTEField');
if (editableRegion) {
var field = document.getElementById("ProfileEditorEditQualifications_hiddenRTEField");
if (field) {
editableRegion.innerHTML = field.value;
}
}
// SETTING QUALIFICATIONS PROPERTY VALUE
editableRegion = document.querySelector('[InputFieldId=ProfileEditorEditExperties_hiddenRTEField]');
if (editableRegion) {
var field = document.getElementById("ProfileEditorEditExperties_hiddenRTEField");
if (field) {
editableRegion.innerHTML = field.value;
}
}
}
</script>
I will have to keep an eye when this bug is fixed in future updates, if the fix is only the server side, then I will have to remove my javascript and if the fix replaces EditProfile.aspx, then I won’t have to do anything.
Creating List Fields/Columns Programmatically in Sharepoint 2010
Posted by Aleem in C#, SharePoint, SharePoint Development on March 16, 2012
Here’s the starting point for creating custom fields in a SharePoint list programmatically, there’s of course much more to do in order to make them behave according to you requirements;
Single Line Text Field
string fieldInternalName = list.Fields.Add(“fieldname”, SPFieldType.Text, false);
list.Fields[fieldInternalName].Description = “field description”;
list.Fields[fieldInternalName].Update();
Multiline Text Field
string fieldInternalName = list.Fields.Add(“fieldname”, SPFieldType.Note, false);
Boolean Field
string fieldInternalName = list.Fields.Add(“fieldname”, SPFieldType.Boolean, false);
Number Field
string fieldInternalName = list.Fields.Add(“fieldname”, SPFieldType.Number, false);
SPFieldNumber fieldTimeSpent = new SPFieldNumber(list.Fields, fieldTimeSpentName);
fieldTimeSpent.DisplayFormat = SPNumberFormatTypes.NoDecimal;
fieldTimeSpent.Update();
Choice Field
string fieldStatusName = list.Fields.Add(“Status”, SPFieldType.Choice, false);
SPFieldChoice fieldStatus = (SPFieldChoice)list.Fields.GetFieldByInternalName(fieldStatusName);
string[] activityTypes = { “Active”, “Closed” };
fieldStatus.Choices.AddRange(activityTypes);
fieldStatus.DefaultValue = “Active”;
fieldStatus.Update();
User Field
string fieldUserName = list.Fields.Add(“User”, SPFieldType.User, false);
SPFieldUser userField = new SPFieldUser(list.Fields, fieldUserName);
userField.AllowMultipleValues = false;
userField.Required = true;
userField.SelectionMode = SPFieldUserSelectionMode.PeopleOnly;
userField.LookupField = “Title”;
userField.Update();
Date Time Field
string fieldInternalName = list.Fields.Add(“fieldname”, SPFieldType.DateTime, false);
SPFieldDateTime fieldDateTime = new SPFieldDateTime(list.Fields, fieldInternalName);
fieldDateTime.DisplayFormat = SPDateTimeFieldFormatType.DateOnly;
fieldDateTime.DefaultValue = “[today]”;
fieldDateTime.Update();
Lookup Field
SPList listMain = currentWeb.Lists.TryGetList(“MainList”);
SPList listActivity = currentWeb.Lists.TryGetList(“Activities”);
string fieldActivityName = listMain.Fields.AddLookup(“Activity”, listActivity.ID, false);
SPFieldLookup activityField = new SPFieldLookup(listMain.Fields, fieldActivityName);
activityField.AllowMultipleValues = false;
activityField.LookupField = “Title”;
activityField.Indexed = true;
activityField.RelationshipDeleteBehavior = SPRelationshipDeleteBehavior.Restrict;
activityField.Update();
Lookup Additional Field
string fieldActivityIdName = listMain.Fields.AddDependentLookup(“Activity:ID”, activityField.Id);
SPFieldLookup fieldLookup = (SPFieldLookup)listMain.Fields.GetFieldByInternalName(fieldActivityIdName);
fieldLookup.LookupField = listActivity.Fields[“ID”].InternalName;
fieldLookup.Update();
Modifying Default View
var view = list.DefaultView;
view.ViewFields.Delete(“Attachments”);
view.ViewFields.Add(“ID”);
view.ViewFields.Add(“field1”);
view.ViewFields.Add(“field2”);
view.ViewFields.MoveFieldTo(“ID”, 0);
view.ViewFields.MoveFieldTo(“field1”, 2);
view.ViewFields.MoveFieldTo(“field2”, 3);
view.Update();
Different views for display, edit and new item in InfoPath list forms
Posted by Aleem in InfoPath, SharePoint, SharePoint Designer, SharePoint Development on November 18, 2011
Custom lists and InfoPath forms make a good combination, although InfoPath in this scenario lacks some functionality but still this combination is hard to avoid in many situations. You can check out my previous post about the differences between InfoPath in form library, InfoPath with custom lists and aspx forms for custom lists.
When working with InfoPath custom list forms it’s sometimes required to have different views for new, edit and display item modes of the form.
Display View
There are two ways you can choose display view otehr than the default view.
First is in “advanced form options” in InfoPath file menu, here you can choose your display view.
Second options is outside InfoPath and it applies not only to display mode but also to edit and new modes.
Suppose you want a different view for display item mode.
1. Open the site in SP Designer
2. Open list detail page and open displayifs.aspx in ‘Forms’ list
3. Select the Infopath viewer webpart and look in the properties window, you will find the “DefaultView” property inside “Misc” section
Same can be done in newifs.aspx and editifs.aspx for new and edit item modes
New Item View
It’s easy just check empty ID field in InfoPath rule on form load and change view. Or use the above mentioned designer option.
Edit Item View
If you have set different display view and switching view for new item on form load based on empty ID field, then for edit item mode just leave it to the default view. And of course you can change in SP designer as mentioned above.
Comparison between Aspx forms, InfoPath list forms and InfoPath documents in SharePoint 2010
Posted by Aleem in InfoPath, SharePoint, SharePoint Development on October 25, 2011
When it comes to data entry forms in SharePoint, there are three out of the box options available, Aspx forms (default option in lists), InfoPath List forms, and InfoPath documents. The first two are interchangeable with some effort, but switching from the first two to InfoPath documents and visa versa is not possible. Therefore, it’s important to choose the right approach in the beginning of a project.
Here’s the comparison of these three technologies.
ASPX forms |
InfoPath List Forms |
InfoPath Documents |
Basics |
||
Separate forms for display, edit and new items. Forms simply work on whatever data is in the list. |
Single form works for all operations. Like aspx forms, this form works on whatever data is in the list. |
Each list/data item is a document itself. Documents can be configured to promote fields to library columns |
Form cannot be printed |
Form cannot be printed |
Form CAN BE printed |
Data cannot be saved as draft |
Data cannot be saved as draft |
Document can be saved as draft |
Coding Support |
||
Client and server side code support |
No client or server side code support |
Only server side code support, it uses XMLHttp in order to avoid full page postbacks during data entry. |
Form Design |
||
CSS can be applied |
No CSS support |
No CSS support |
Data |
||
Data can be changed or imported into the list in bulk |
Data can be changed or imported into the list in bulk |
Only existing data in promoted fields can be modified. Records cannot be added or deleted in bulk. |
Multiple data sources are not supported unless they are in the form of lookup columns or used in client or server side code |
Multiple data sources can be used |
Multiple data sources can be used |
Managed Meta data can be mapped to fields |
Can NOT use Managed Meta data |
Can NOT use Managed Meta data |
Can use external data through client or server side code |
Can consume simple SOAP and REST based services and can have connections to databases and XML files |
Can consume simple SOAP and REST based services and can have connections to databases and XML files |
Form Functionality |
||
No built in support for cascading drop downs, this functionality is achieved using JavaScript
|
Cascading drop downs can be created without code |
Cascading drop downs can be created without code |
No repeating or nested data support |
No repeating or nested data support |
Repeating and nested data support, but cannot be promoted to separate columns or lists |
Multiple views of data cannot be created |
Multiple view of data CAN BE created and switched based on rules |
Multiple view of data CAN BE created and switched based on rules |
Multiple web part can be added to the form, inline editing of records possible |
Data can be shown from multiple data sources, but can’t be changed |
Data can be shown from multiple data sources, but can’t be changed |
Validation |
||
JavaScript for all the rules and client side validation |
Rule engine does it all |
Rule engine does it all |
Workflow |
||
SPD based list and reusable workflows and VS based custom workflows can be created and attached |
SPD based list and reusable workflows and VS based custom workflows can be created and attached |
SPD based list and reusable workflows and VS based custom workflows can be created and attached. Only promoted fields can be used in SPD based workflows. |
Key Benefits |
||
Maximum control on the form |
Very easy to develop and very little testing is required |
Easy to develop and relatively less testing is required |
JavaScript/JQuery and Server side code support |
Can be developed with minimum time and effort |
Server side code support |
CSS Support |
InfoPath Views, Rules and facial features are supported |
All InfoPath features like Views, Rules, facial features and printing are supported |
Data in the list can be edited, imported and exported in bulk |
Data in the list can be edited, imported and exported in bulk |
Repeating and nesting data support |
Multiple web parts can be used on a form to view or modify items from different lists on a single form |
||
Drawbacks |
||
Increased development and testing time |
No Coding support |
No client side coding support, limited server side code ability |
Can run in Sandbox |
||
Deciding the right technology
InfoPath form library should be the first consideration for all kind of applications. They provide additional functionality compared to custom list InfoPath forms, such as;
- Repeating tables and complex schema
- Printing views
- Better deployment and change support
- Managed code support
- Forms can be digitally signed
There are few situations where list based InfoPath forms suite;
-
System needs to be built upon existing data and it’s not feasible for all that data to be entered through the forms
-
Bulk data import and edit is required throughout the life of the system
-
None of the above mentioned additional capabilities of InfoPath is required
ASPX list forms should be used only when
-
JavaScript support is a must
-
CSS support is required
-
SharePoint Managed Meta Data must be used in forms
JavaScript page load function array and pre save function in SharePoint 2010
Posted by Aleem in SharePoint, SharePoint Designer, SharePoint Development on October 11, 2011
JavaScript page load function
I have been using this function array forever, but still whenever I need it, I have to look it up on internet, so decided to post it here.
In case you are new to SharePoint, because mostly SharePoint pages don’t contain body element because it comes from master page, so this is the way to run your page body load event code in SharePoint. Add your function name to “_spBodyOnLoadFunctionNames” function array, and your function will be called when page body is loaded.
_spBodyOnLoadFunctionNames.push("pageOnLoad"); function pageOnLoad() { // Your code here }
Pre Save Custom Script
Another important function which I managed to forget when I was recently customizing a list item page, is PreSaveItem function. It is for writing custom client side script when “Save” button is pressed on New or Edit Item page in SharePoint.
function PreSaveItem() { return true // or return false; }
Return true of you want the saving process to continue or return false otherwise.
Get Element by Tag and Title
One more very useful function is the one which gets an element by its tag name and title, here it is
function getElementFromTitle(tagName, title) { var tags = document.getElementsByTagName(tagName); for (var i=0; i < tags.length; i++) { if (tags[i].title == title) { return tags[i]; } } return null; }
But if you are using JQuery, the following line replaces the above function
var subjectValue = $("input[title='ElementTitle']").val();
(“input” is the type of control)
Using JQuery you can go to any length to find something in the page markup, like the one below returns text from rich text field in SharePoint
var descriptionValue = $("textarea[Title='ElementTitle']").closest("span") .find("iframe[Title='Rich Text Editor']").contents().find("body").html();
SP Services by Marc D Anderson
Here’s some cool stuff by Marc D Anderson
http://spservices.codeplex.com/documentation
This is a library which is based on JQuery, it makes making cascading drop downs amazingly easy.
After you have referenced JQuery and SPService in your page, it’s just the following code which configures a cascading drop down
<script type="text/javascript"> $(document).ready(function() { $().SPServices.SPCascadeDropdowns({ relationshipList: "Regions", relationshipListParentColumn: "Country", relationshipListChildColumn: "Title", parentColumn: "Country", childColumn: "Region" }); }); </script> Thanks Marc, for this amazing stuff.
Warn users of double booking in SharePoint calendar in real time
Posted by Aleem in C#, SharePoint, SharePoint Designer, SharePoint Development on August 8, 2011
Recently I came across this situation where in our room booking system we needed to warn users of parallel booking, but didn’t want to stop them from making the booking because in many cases they are agreed between parties.
Initially it didn’t look like a big deal because I had Client-side Object Model which I could use in JavaScript, but I couldn’t achieve the whole functionality in JavaScript. I would explain down my post why I couldn’t write the whole solution in JavaScript, and I had to go for Server-side code.
Finally I was able to achieve the following (click on the picture to see the big version)
The thing which makes this solution interesting is that Id’s of the date controls are handled differently by SharePoint in this page. If you inspect the source of the new item page of the calendar, you will notice that the controls id’s are kept in an array in JavaScript. You can see the array declaration in the source
<script type="text/// <![CDATA[
javascript">var g_strDateTimeControlIDs = new Array();
// ]]>
And then it’s used to store id’s of the calendar controls like start date
<script type="text/javascript">
g_strDateTimeControlIDs["SPEventDate"] = "ctl00_m_g_089e7bbe_83d6_4e8a_ab8f_ca7ca3d3d0cc_ff31_ctl00_ctl00_DateTimeField_
DateTimeFieldDate";
</script>
And for end date
<script type="text/javascript">
g_strDateTimeControlIDs["SPEndDate"] = "ctl00_m_g_089e7bbe_83d6_4e8a_ab8f_ca7ca3d3d0cc_ff41_ctl00_ctl00_DateTimeField_
DateTimeFieldDate";
</script>
Hours and Minutes drop downs’ id’s are same except “Hours” and “Minutes” appended in the end of the above id’s.
The final solution consists of the following components;
1. Changing ScriptManager tag in master page to allow page methods
2. Changing web.config to add PageParser element to allow server-side code in the page
3. Creating a new item page for calendar
4. Changing the newitem page
5. Writing some javascript
6. Writing a page method in C#
The only reason I used page method in C# is that I couldn’t run the following query in JavaScript, I am still trying for this, and if I get lucky I would love to remove the server-side code from this solution
SPQuery query = new SPQuery();
query.ExpandRecurrence = true;
query.Query = "<FieldRef Name='EventDate' />";
query.CalendarDate = new DateTime( startDateTime.Year, startDateTime.Month, startDateTime.Day);
1. ScriptManager tag is already in the v4.master, but it has page methods disabled, we need to first enable the page methods by changing the “EnablePageMethods” attribute to “true” and it should then look like this;
ScriptManager id="ScriptManager" runat="server" EnablePageMethods="true" EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true" />
by enabling this you can add static page methods to an ASP.NET page and mark them as Web methods. You can then call these methods from script as if they were part of a Web service, but without creating a separate .asmx file.
If you don’t want to enable Page Methods in master page, then you can add “ScriptManagerProxy” control in your page, it’s because a page can contain only one ScriptManager control in its hierarchy and v4.master already has one.
2. Now change the web.cofig for the site to add a PageParser element, so that our page can call server-side code
<SharePoint>
<PageParserPaths>
<PageParserPath VirtualPath=”/Team/Lists/Calendar/CustomNewEvent.aspx” CompilationMode=”Always” AllowServerSideScript=”true” />
</PageParserPaths>
</SafeMode>
</SharePoint>
3. Create a custom new item page for calendar in SharePoint designer, it’s easy to do and I won’t be able to explain how to do it here.
4. Open the custom new item page in advance mode in SharePoint designer and scroll down to the place where there’s a table row (i.e) for “End Time” and add the following table row
I wanted to show the message below “End Time” but you can show it anywhere on the page and I did the styling in CSS, it’s all your choice.
Now search for place holder id “PlaceHolderAdditionalPageHead”, and the add the following inside the content tag
<asp:Content ContentPlaceHolderId=”PlaceHolderAdditionalPageHead” runat=”server”>
// <![CDATA[
src=”../../Scripts/calendar.js”>
// ]]>
<script type=”text/c#” runat=”server” src=”../../Script/calendar.cs”></script>
<script language=”javascript” type=”text/javascript”>
_spBodyOnLoadFunctionNames.push(“OnLoad”);
function OnLoad(){
// Calendar is the name of the Calendar list, I am passing the name of the list
// so that I can call this code from any Calendar library
FindOverlappedEvents(“Calendar”); }
</script>
</asp:Content>
I have only shown the code I have added inside the above content tag, there would be more already in there which you might not want to change.
Calendar.js and Calendar.cs are the files I have added in the scripts folder on the root of the site, by selecting “All Files” in the left navigation in SPD and creating a folder on the root, you can of course choose to store them somewhere else but remember to use the correct path in the above code.
5. Now add the following code in Calendar.js, the way I create a new .js or .cs in SharePoint designer is by creating a new css files and then renaming it. it’s because SharePoint designer gives you option to create only HTML, ASPX or CSS in a given folder.
var g_eventOverlapped = false;
function PreSaveAction()
{
// This is in case user presses save button right after selecting date and time
// Remember: our code runs on onblur even of date and time controls
if(g_eventOverlapped == true) {
return confirm(“Your selected time overlaps with an existing booking!\nIf you want to change the time, press ‘Cancel'”);
}
return true;
}
// This function is called from OnLoad of the form, it binds event handerl to the date and time controls
// onblur is the only event which works on these controls
function FindOverlappedEvents(listName)
{
var startDate = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]);
var startHours = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]+”Hours”);
var startMinutes = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]+”Minutes”);
if(startDate != null && startHours != null && startMinutes != null)
{
startDate.onblur = function(){validateDates(listName);};
startHours.onblur = function() {validateDates(listName);};
startMinutes.onblur = function() {validateDates(listName);};
}
var endDate = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]);
var endHours = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]+”Hours”);
var endMinutes = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]+”Minutes”);
if(endDate != null && endHours != null && endMinutes != null)
{
endDate.onblur = function(){validateDates(listName);};
endHours.onblur = function() {validateDates(listName);};
endMinutes.onblur = function() {validateDates(listName);};
}
// validate initially when new item window opens, because by default date and time are selected
validateDates(listName);
}
// This gets called every time onblur is fired on controls
function validateDates(listName)
{
var startDateCtl = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]);
var startHoursCtl = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]+”Hours”);
var startMinutesCtl = document.getElementById(g_strDateTimeControlIDs[“SPEventDate”]+”Minutes”);
var startHour = startHoursCtl.options[startHoursCtl.selectedIndex].value
var startMinutes = startMinutesCtl.options[startMinutesCtl.selectedIndex].value
var endDateCtl = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]);
var endHoursCtl = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]+”Hours”);
var endMinutesCtl = document.getElementById(g_strDateTimeControlIDs[“SPEndDate”]+”Minutes”);
var endHour = endHoursCtl.options[endHoursCtl.selectedIndex].value
var endMinutes = endMinutesCtl.options[endMinutesCtl.selectedIndex].value
// here is the call to the server-side method, which comes back to either OnCallComplete(result) or OnCallError(error)
PageMethods.GetCalendarOverlap(listName, startDateCtl.value, startHour,startMinutes,endDateCtl.value,endHour,endMinutes,OnCallComplete,OnCallError);
}
function OnCallComplete(result)
{
if(result != “”)
{
document.getElementById(“TimeOverlapLabel”).innerHTML = “Booking Error”;
document.getElementById(“TimeOverlap”).innerHTML = result;
// this makes sure that we’ve covered this event
g_eventOverlapped = true;
}
else
{
document.getElementById(“TimeOverlapLabel”).innerHTML = “”;
document.getElementById(“TimeOverlap”).innerHTML = “”;
// this makes sure that we’ve covered this event
g_eventOverlapped = false;
}
}
function OnCallError(error)
{
if(error !== null)
{
document.getElementById(“TimeOverlap”).innerHTML = “There’s an error checking for duplicate events”;
}
}
6. Create Calendar.cs in the Scripts folder and add the following code;
[System.Web.Services.WebMethod]
public static string GetCalendarOverlap(string listName, string startDate, string startHour, string startMinutes, string endDate, string endHour, string endMinutes)
{
try
{
SPWeb web = SPContext.Current.Web;
SPList calendarList = web.Lists[listName];
// Construct a query that expands recurring events
SPQuery query = new SPQuery();
// If I could run the following CAML in JavaScript using SharePoint Object Model, I wouldn’t have gone for server side code.
query.ExpandRecurrence = true;
query.Query = “<FieldRef Name=’EventDate’ />”;
startHour = startHour.TrimEnd(“:”.ToCharArray());
string[] startDateParts = startDate.Split(“/”.ToCharArray());
DateTime startDateTime = new DateTime(int.Parse(startDateParts[2]), int.Parse(startDateParts[1]), int.Parse(startDateParts[0]), int.Parse(startHour), int.Parse(startMinutes), 0);
endHour = endHour.TrimEnd(“:”.ToCharArray());
string[] endDateParts = endDate.Split(“/”.ToCharArray());
DateTime endDateTime = new DateTime(int.Parse(endDateParts[2]), int.Parse(endDateParts[1]), int.Parse(endDateParts[0]), int.Parse(endHour), int.Parse(endMinutes), 0);
query.CalendarDate = new DateTime( startDateTime.Year, startDateTime.Month, startDateTime.Day);
// Returns all items (including recurrence instances) that
// would appear in the calendar view for the current day
SPListItemCollection calendarItems = calendarList.GetItems(query);
DateTime eventStartDateTime;
DateTime eventEndDateTime;
string eventTitle;
bool timeOverlap = false;
string events = string.Empty;
foreach (SPListItem item in calendarItems)
{
eventStartDateTime = DateTime.Parse(item[“EventDate”].ToString());
eventEndDateTime = DateTime.Parse(item[“EndDate”].ToString());
eventTitle = (string)item[“Title”];
timeOverlap = false;
//if newstartdate >= eStartDate and newStartDate < eEndDate
if(startDateTime >= eventStartDateTime && startDateTime < eventEndDateTime)
{
timeOverlap = true;
}
//if newEndDate > eStartDate and newEndDate <= eEndDate
else if(endDateTime > eventStartDateTime && endDateTime <= eventEndDateTime)
{
timeOverlap = true;
}
// if eStartDate >= newStartDate and eStartDate < newEndDate
else if(eventStartDateTime >= startDateTime && eventStartDateTime < endDateTime)
{
timeOverlap = true;
}
// if eEndDate > newStartDate and eEndDate <= newEndDate
else if(eventEndDateTime > startDateTime && eventEndDateTime <= endDateTime)
{
timeOverlap = true;
}
// if newStartDate = eStartDate and newEndDate = eEndDate
else if (startDateTime == eventStartDateTime && endDateTime == eventEndDateTime)
{
timeOverlap = true;
}
if(timeOverlap == true)
{
// This HTML decoration is better done at the client side, but I was being lazy and did it here
events += “ Title : “+ eventTitle +”
“;
events += “Start Date: “+ item[“EventDate”].ToString() +”
End Date: ” + item[“EndDate”].ToString() + ”
“;
events += “Created By: ” + item[“Author”].ToString().Split(“#”.ToCharArray())[1] + ”
“;
}
}
if(events != string.Empty)
{
events = “Time Overlap Warning!<br/>Your selected time overlaps with the following booking(s);<br/><br/>”+events;
}
return events;
}
catch(Exception ex)
{
throw ex;
}
}
Remove hyperlink from Lookup column in SharePoint
Posted by Aleem in SharePoint, SharePoint Designer, SharePoint Development on July 8, 2011
For whatever reason if you don’t want users to be able to click on a lookup column in a list, there’s no straight forward method of disabling that link. Here’s the way I disable them in SharePoint 2010, and it wasn’t any different in 2007 either apart from fancy UI.
In the image below, Country is a lookup type of column
Open the list view in SharePoint designer for modification
Select the lookup column item and in the document map bar in the bottom, choose the context menu for “xsl:value-of”, and select “Edit Tag…”
You will see the “Edit Tag” window
The above XPath “$thisNode/@*[name()=current()/@Name]” when executed, returns the following hyper link tag
<a onclick=”OpenPopUpPage(‘http://servername/_layouts/listform.aspx?PageType=4&ListId={9CF20D94-56E4-426B-AAA3-97CEA2B23570}&ID=3&RootFolder=*’,RefreshPage); return false;”href=”http://servername/_layouts/listform.aspx?PageType=4&ListId={9CF20D94-56E4-426B-AAA3-97CEA2B23570}&ID=3&RootFolder=*”>United States</a>
In order to get the clean value which is in this case “United States”, we need to remove the decoration around it, so we are going to remove everything before ‘>‘ and after ‘<‘ by changing the tag in the Quick Tag Editor to
<xsl:value-of select=”substring-before(substring-after($thisNode/@*[name()=current()/@Name],’>’), ‘<’)” disable-output-escaping=”yes”>
Then press the tick button on the “Quick Tag Editor” to save the modified tag, save the page and view it in browser
Links are gone.
Neat, isn’t it?