Archive | jQuery

How to get the count of items returned in jQuery Autocomplete

In this post I used jQuery to autocomplete an input box with results from CRM 2011. I wanted to give the number of results returned for the particular autocomplete query. I chose to use the autocomplete open: parameter to get the number of results returned, and I put that result in a div with an ID of “Count”

 

open: function(event,ui){
	    var len = $(this).autocomplete("widget").find( "li" ).length;
	    var resultText='RESULTS';
	    if (len==1) resultText='RESULT'
	    $('#Count').text('FOUND '+len+' '+resultText);
	  	},
close: function(event,ui){
	    $('#Count').text('ENTERPRISE SEARCH');
  	}

SharePoint 2010, Client OM, jQuery Autocomplete and BCS/External lists

In this previous post, I used jQuery/SOAP/SPServices to access a SharePoint BCS list (an external list). I wanted to do the same thing using the Client Object Model (Some call it Clien OM? Or maybe CSOM?). Below is the code to access contact data in a BCS connection to Microsoft CRM 2011, and use it for autocomplete values. Things to note:

  1. You need to have a method tag in your CAML statement. This tells the list which “Operation” (as it is listed in SharePoint Designer) to use
  2. You need to use the “include method” with the executeQueryAsync method
  3. You need to include the ViewFields tags in the CAML statement, and I think they should match the include statement above
$('#ContactsSearchTextbox').autocomplete({
    source: function( request, response ) {
	    var CAMLQuery= "<View><Method Name='ContactReadList' /><Query><Where><Contains><FieldRef Name='FullName' /><Value Type='Text'>"+request.term+"</Value></Contains></Where></Query><ViewFields><FieldRef Name='FullName' /><FieldRef Name='ContactId' /><FieldRef Name='ParentCustomerIdName' /></ViewFields></View>";
		var context = new SP.ClientContext.get_current();
		var web = context.get_web();
		var list = web.get_lists().getByTitle('Contacts');
		var query = new SP.CamlQuery;
		query.set_viewXml(CAMLQuery);
		allItems = list.getItems(query);
		context.load(allItems, 'Include(FullName,ContactId,ParentCustomerIdName)');
		context.executeQueryAsync(function (){
			var arrayOfResults = new Array();
			var listItemEnumerator = allItems.getEnumerator(); 
			while(listItemEnumerator.moveNext()) {
				var oListItem = listItemEnumerator.get_current();
				arrayOfResults.push(oListItem);
			}
			response($.map(arrayOfResults ,function( item ) {
				return {
				label: item.get_item('FullName') + ' (' + item.get_item('ParentCustomerIdName') + ')',
				value: item.get_item('ContactId'),
				id: item.get_item('FullName')
				}
			}));
		},function(sender, args){
		   alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
		});        
	},
	minLength: 5,
});

Accessing SharePoint 2010 BCS lists via SOAP/WebServices for use in a jQuery autocomplete

So it seems that you can’t access BCS list data via REST, according to this article. But it seems that you can access the list data through SOAP. I used the code below to query a BCS list that points to a MSCRM 2011 backend (I know I could go right to CRM via REST, but then I would have XSS issues). I then take the results and use them for a jQuery autocomplete for an input box. Obviously in the code below, Contacts is a BCS “external List”

 


$('#ContactSearchTextbox').autocomplete({
source: function( request, response ) {
	$().SPServices({
	operation: "GetListItems",
	async: false,
	listName: "Contacts",
	CAMLViewFields: "<ViewFields><FieldRef Name='FullName' /><FieldRef Name='ContactId' /><FieldRef Name='ParentCustomerIdName' /></ViewFields>",
	CAMLQuery: "<Query><Where><Contains><FieldRef Name='FullName' /><Value Type='Text'>"+request.term+"</Value></Contains></Where></Query>",
	completefunc: function (xData, Status) {
	$('#SearchResults').html(xData.responseText);
	response($.map( $(xData.responseXML).SPFilterNode("z:row"), function( item ) {
	return {
	label: $(item).attr('ows_FullName') + "(" + $(item).attr('ows_ParentCustomerIdName') +")",
	value: $(item).attr('ows_ContactId')
		}
	}));
	}
	});	    
},
minLength: 4
});

Pseudo workflow approval with out SharePoint Workflows.

I wanted to have a form that a person would submit (for an example a request of some type) and then it would be approved by the appropriate people. I find the built in workflow functionality too limiting and too difficult for users, so this is what I came up with:

I would have one list that contained fields for both the user to enter data and for each approver to approve or disapprove. In addition, there would be a “Final Approval” field that cold only be set once everyone approved or disapproved and an “I agree” to terms checkbox.

First up, I hid all the fileds on the NewForm.aspx that were related to the approval process. Just the data that was to be collected was shown. I did this with jquery and a CEWP:

<script type="text/javascript">
$(document).ready(function(){
$('tr:has(select[title="User 1"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 2"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 3"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 4"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 5"])').not('tr:has(tr)').hide();
$('tr:has(select[title="Final Status"])').not('tr:has(tr)').hide();
$('nobr:contains("User 1 Comments")').closest('tr').hide();
$('nobr:contains("User 2 Comments")').closest('tr').hide();
$('nobr:contains("User 3 Comments")').closest('tr').hide();
$('nobr:contains("User 4 Comments")').closest('tr').hide();
$('nobr:contains("User 5 Comments")').closest('tr').hide();
});
</script>

Once this is submitted by the user, and email is sent by a SharePoint workflow (I still don’t like them) telling the approvers to look at the request and approve it (link to the edit page in the email)

Then on the edit page, I used the jquery below to hide the “I agree” so the user could not go back and change it. Also I hid the final approval until all drop downs (Approvals) have changed from “Pending” to Approved or Declined. Obviously there would be security issues, but this is a small use case and we weren’t worried about malicious users (famous last words) – people were on their honor.

<script type="text/javascript">
$(document).ready(function(){
$('tr:has(select[title=IAgree])').not('tr:has(tr)').hide();
$('tr:has(select[title=IAgree])').not('tr:has(tr)').append('<tr><td nowrap="true" valign="top" width="190px" class="ms-formlabel"><H3 class="ms-standardheader">I Agree</H3></TD><td valign="top" class="ms-formbody" width="400px">'+$('select[title=IAgree] :selected').text()+'</td></tr>');

$('select :selected').each(function(){
if($(this).text() == "Pending") {
$('tr:has(select[title=Final Status])').not('tr:has(tr)').hide();
}
});

});
</script

Using ajax to query XML in SharePoint Doc Lib, for use in a form’s input autocomplete

Long title, but I wanted to get across what I was trying to do. If I had and XML file in a document library (you could mail enable the doc lib, and send XML from a query in SQL server using the “FOR XML” statement!), could I use jquery to add Autocomplete values to an input field in a newform.aspx? Ended up being not that difficult.

  1. Once the ajax call sucessfully retrievs the xml file, the parseXml routine is called.
  2. Seems there is an issue that IE will not think the file is XML, but rather as txt, so there some quick code to load the file as XML
  3. Then I just look in the file and grab the values I want, and append them to an array
  4. Then just set the array to be used as the autocomplete source
<script type="text/javascript">
$(document).ready(function() {
$.ajax({ 	
	type: "GET",
	url: "http://URL/To/xmlfile.xml",
	dataType: ($.browser.msie) ? "text" : "xml",
	success: parseXml
});
});
function parseXml(data)
{
    var xml;
     if (typeof data == "string") {
       xml = new ActiveXObject("Microsoft.XMLDOM");
       xml.async = false;
       xml.loadXML(data);
     } else {
       xml = data;
     };
 	var results = []; 
	$(xml).find("ID").each(function(){  
		var ClientName = $.trim($(this).find('Name').text());
		var ClientCode = $.trim($(this).find('ZipCode').text());
		results[results.length] = ClientName + "(" + ClientCode + ")"
	});

	$('input[title=Title]').autocomplete({
	source: results,
	delay:10,
	minLength: 3
	});
};
</script>

My CEWP JQuery code to play flash files in a Modal

I have Flash files in a Document Library. I wanted to have users click the flash files (swf) and have them open up in a hidden div, rather than opening in a different window. I added the code below to a CEWP:

<script type="text/javascript" src="http://jquery.thewikies.com/swfobject/jquery.swfobject.1-1-1.min.js"></script>
<script>
$(document).ready(function() {
//
$("#popupclose").click(function () {
	$("#popup").Hide();
	$('.media').flash().remove();
	return false;
});
//
$("a[href*='\.swf']").each(function(){
	this.onclick = function(){
	var filetoopen = $(this).attr("href");
	$("#popup").Show;
	$('.media').flash({swf:filetoopen,height:600,width:1000});
	return false;
	};
}); 
//
});
</script>
<style type="text/css">
#popup{  
 display:none;    
 position:absolute;  
 top: 10px; 
 left: 10px;
 background:#FFFFFF;  
 border:2px solid #cecece;  
 z-index:2;  
 font-size:12px;
 }   
</style>
<div id="popup">  
  <a id="popupclose" href="javascript:void()">close</a>
<br/>
  <div class="media" style="vertical-align:top;"></div>
</div>

Hide a field in a SharePoint edit form based on other values

We have a form (list) that we want to have everyone edit and give comments. Once everyone has edited the item, we want an “overall status” field to trigger a workflow (send extended email). Be we did not want the overall status to be changed until everyone has chimed in. To achieve this, we created a list and there was a dropdown with everyone’s name to Approve the item. The default of the dropdown was “Pending”. I used the jquery below to hide the “overall status” until there were no dropdowns that said “Pending”

$('select :selected').each(function(){
if($(this).text() == "Pending") {
$('tr:has(input[title=Overall Status])').not('tr:has(tr)').hide();
};
});

The hide code is code that Paul Galvin published here.
jquery is cool.

How to make a field in a SharePoint Edit form readonly

Paul Galvin showed how to hide a field in a SharePoint. I wanted to use this code to make a field “read only” once a from has been submitted. Forgetting about DataSheet view (for now), we can put a Content Editor Webpart on the top of the EditFrom.aspx page (to add a CEWP to the top of the edit from, append the URL to this -> EditForm.aspx?ToolPaneView=2) and include his code:

$('tr:has(input[title=Disclaimer])').not('tr:has(tr)').hide();

This will hide the filed based on the Column Name (Disclaimer). Taking this a step further, we can get the selected value (a drop down box in this case), and append a column after the hidden column with some formatting, a column name and the selected value. Effectively making the column readonly.

<script type="text/javascript">
$(document).ready(function(){
$('tr:has(select[title=Disclaimer])').not('tr:has(tr)').hide();
$('tr:has(select[title=Disclaimer])').not('tr:has(tr)').append( '<tr><td nowrap="true" valign="top" width="190px" class="ms-formlabel"><H3 class="ms-standardheader">Disclaimer Accepted:</H3></TD><td valign="top" class="ms-formbody" width="400px">'+$('select[title=Disclaimer] :selected').text()+'</td></tr>');
});
</script>

How I created a “Copy to new item” functionality for a SharePoint list – Part 2

Second part. First Part can be found here. On the second page (NewForm.aspx), I grabbed out of the querystring the values for the source list item and the name of the list.
I used this person’s query string parser.

Then I used the following SOAP query :

$(document).ready(function() {
 var sourceID = getQuerystring('SourceID');
 var listName = getQuerystring('ListName');

 var soapEnv = &quot;&lt;soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'&gt; \
&lt;soapenv:Body&gt; \
&lt;GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'&gt; \
&lt;listName&gt;&quot; + listName + &quot;&lt;/listName&gt; \
&lt;viewName&gt;{GUID}&lt;/viewName&gt; \
&lt;viewFields /&gt; \
&lt;ViewFields /&gt; \
&lt;query&gt; \
&lt;Query&gt;&lt;Where&gt; \
&lt;Eq&gt; \
&lt;FieldRef Name='ID' /&gt; \
&lt;Value Type='Integer'&gt;&quot; + sourceID + &quot;&lt;/Value&gt; \
&lt;/Eq&gt; \
&lt;/Where&gt;&lt;/Query&gt;\
&lt;/query&gt; \
&lt;/GetListItems&gt; \
&lt;/soapenv:Body&gt; \
&lt;/soapenv:Envelope&gt;&quot;;

 $.ajax({
 async: false,
 url: &quot;http://site.com/subsite/_vti_bin/lists.asmx&quot;,
 type: &quot;POST&quot;,
 dataType: &quot;xml&quot;,
 data: soapEnv,
 complete: processResult,
 contentType: &quot;text/xml; charset=\&quot;utf-8\&quot;&quot;
 });

 });
 function processResult(xData, status) {
 $(xData.responseXML).find(&quot;z\\:row&quot;).each(function() {
 $(&quot;input[title='Input']&quot;).val($(this).attr(&quot;ows_Input&quot;));
 $(&quot;textarea[title='TextArea']&quot;).val($(this).attr(&quot;ows_TextArea&quot;));
 $(&quot;select[title='DropDown']&quot;).val($(this).attr(&quot;ows_DropDown&quot;)).attr(&quot;selected&quot;, &quot;selected&quot;); 
 }
 )};

In the last three lines I changed the input box, textbox and dropdown boxes to their values in the results fromt the SOAP query.

Kinda fun. Just need to figure out how to do check boxes!

How I created a “Copy to new item” functionality for a SharePoint list – Part 1

I wanted to create a “copy to new item” functionality for a SharePoint list.

Steps I came up with:

  1. The first thing I had to do was add a link to the context menu (I learned that it is called an ECB) and have it point to the NewForm.aspx.
  2. Once I got that, I could append a querystring variable to the url that contained the “Source ID” of the item to copy and the name of the current list.
  3. Then I would grab that querystring value on the other side – in the NewForm.aspx page
  4. Next I would use that variable to query the SharePoint List via SOAP
  5. Inject the results the  into the form

Here is my script (add to a CEWP, I already have the jquery pointers to google in a Delegate control)

<script language="javascript">
function Custom_AddListMenuItems(m, ctx) {
var editURL = window.location.protocol + "//" + window.location.host + ctx.listUrlDir + "/NewForm.aspx?SourceID=" + currentItemID + "&amp;ListName=" + ctx.ListTitle;
 CAMOpt(m, "Copy To New Item" ,"window.location=('" + editURL + "');" , "/_layouts/images/Copy.GIF");
 CAMSep(m);
}
</script>

More to come.