Latest Entries »

I discovered this while giving my $0.02 to Fabian Williams. This applies to the HTC 8x, not sure of any other Windows Phone 8 Phones (seems redundant to say that twice).

Reported Bug:
There is a bug where when using Bluetooth through my car then disconnect the headphone volume for music becomes fixed. I can adjust the volume for alerts and games; however music volume becomes fixed at whatever it was set at in the car.

Remedy:
1) Reboot your phone. 2) Ask Microsoft for patch.

Here is the latest site template I am working on. It uses the Site Theme to modify the CSS and the Site Logo so site admins can “Brand” it themselves without having to involve IT. The two images you see are libraries that the site admins can upload to which automatically insert into the respective area when the display date is hit and comes off with the Expires date passes. The Navigiation menu uses a list and will track which page you are on and change the active color as appropriate.

SharePoint doesnt have to be boring

The SharePoint search center is too corporate and boring. It makes me sad just looking at it. So I wanted to spruce it up and make it inviting and engaging to users. Well the daily Bing image is great so why not use that? Well okay let’s do it. So first is how do you get the image. Well Microsoft is nice enough to provide a XML page for the image http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US

Let’s understand it first. The variable “n” is how many days you want back, you can go back up to seven days. I only care about today’s so I use 1. The variable “mkt” is which geo-region you want, en-US is United States. There are regions for England, France, Japan and many others. I also wanted to be sure that the copyright information was included. So you will see the little (i) at the bottom. You’ll have to find your own and add it to your site.

So now we modify the search center and all of the modifications are in the default.aspx page, assuming you are using the minimal.master on your search center. You don’t need to modify the minimal.master so don’t touch it.

First let’s put the CSS and jQuery in. I’m modifing these pages in SharePoint designer. Navigate to line 21 which should be <asp:Content ContentPlaceHolderId=”PlaceHolderTitleAreaClass” runat=”server”>. In the style tag add the following styles.

#bingImage{height: 768px; width:  1366px; background-repeat:no-repeat; background-position:center; border: 1px #ccc solid; text-align:center; position:relative; min-height: 500px; min-width:  1000px; max-height: 768px; max-width:  1366px; margin:auto; top: -24px;}
#bottomControls{position:absolute; bottom: 0px; width:100%;}
#btmHolder{height: 55px; margin-bottom:4px;}
#btmPositioner{top: 20px; right:15px; position:absolute;}
#s4-mini-header{width:1366px; margin: 0 auto 0 auto; position:relative; z-index:50; top: 20px;}
.ms-sblink a:link, .ms-sblink a:visited{color:#fff;}
#s4-mini-titlearea h1{font-size:16px; position:relative; left: 35px; top: -28px; width: 100px;}
#s4-mini-titlearea .s4-mini-titlesep{display:none !important;}
#s4-mini-titlearea h2{display:none;}

Then under that add some javascript. Important note here, I am using John Chapman’s SharePoint proxy page solution to prevent the cross domain browser warning. http://sharepointproxypage.codeplex.com/. CORRECTION: Bing only proves a few different sizes and 1366×768 is one of them. It’s the size I like for my organization.

<script type="text/javascript">
    //BING URL for XML of current image
    //http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US
    $(document).ready(function(){
	var encodedURL = encodeURIComponent("http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US");
			$.ajax({
				type: "GET",
				url: "/_layouts/SharePointProxyPage/Proxy.aspx?u="+encodedURL,
				dataType: "xml",
				success: function(xml) {
					$(xml).find('image').each(function(){
			                   // current document tag
			                   var Document = $(this);
			                   var img = Document.find('urlBase').text();
			                   var copyright = Document.find('copyright').text();	
			            	//send it to the Div
			            	$("#bingImage").css("background-image","url('http://www.bing.com"+img+"_1366x768.jpg')");
			            	$("#bingCopyright").attr("title",copyright);
			        });
				},
                error: function(XMLHttpRequest, textStatus, errorThrown){alert("get image failure: " + textStatus +" | " + errorThrown);}
			});
	});
	</script>

Now go to <SharePoint:UIVersionedContent UIVersion=”4″ runat=”server”>, which should be line 200 or there abouts. Between <ContentTemplate> and <div class=”srch-sb-results7″> add <div id=”bingImage” align=”center”>. Then go to </SharePoint:UIVersionedContent> and directly under it paste the following:

</div>
	<div id="bottomControls">
		<div id="btmHolder">
			<div id="btmPositioner">
				<img id="bingCopyright" src="/Style Library/Intranet/images/intranet/header_info.png" alt="" title="">
			</div>
		</div>
	</div>

It should look something like this:

I wanted to add a small weather icon on our intranet that wasn’t branded with Weather.com or accuweather or any other weather site. Luckly NOAA, whose site is weather.gov, has a free XML source so I could use that to read the weather. Using jQuery I parsed their complicated file for the current conditions temperature and icon. Then I update my div and img src and it’s done. There doesn’t seem to be to many people using it as I couldn’t find any help parsing the NOAA file. So there was a lot of trial and error.

Update the url property and then call getWeather() and it will do the rest. Here’s the code. Enjoy!

function getWeather(){
    	$(document).ready(function(){
    		jQuery.support.cors = true; //enables cross domain support
			$.ajax({
				type: "GET",
				url: "http://forecast.weather.gov/MapClick.php?lat=32.82564&lon=-117.1558867&unit=0&lg=english&FcstType=dwml",
				dataType: "xml",
				success: function(xml) {
				  $(xml).find('data').each(function(){
			            // current document tag
			            var Document = $(this);
			            var temp;
			            
			            // make sure you have the correct data type.
			            var n1 = Document.attr('type');			            	
			            if(n1=='current observations'){
			            	//the correct icon-link
			            	var iconLink = Document.find('icon-link').text();

			            	var n2 = Document.find("temperature").attr("type");
			            	//finds the correct one and only retreives the first value.
			            	if(n2=='apparent'){temp = $(this).find('value').first().text();};
			            		
			            	//set it in the DOM
			            	$("#weather-icon").attr("src",iconLink );
			            	$("#weather").prepend("<span class='temp'>"+temp+"°</span>");
			            }
			        });
				}
			});
			//refresh weather every 30 minutes if page is refreshed by browse action.
			setInterval(function(){getWeather();},1800000);
		});
    }

I ran into this today. You are too probably because you have a Style Library Module that has somes folders. You deleted the file and the reference in Elements.xml but you can’t cause it’s still reference in the SharePointProjectItem.spdata file in the Style Library foler. You’ll have to navigate to the folder through explorer and delete the references.

Recently I had a page that had “Pages – ” in the Title. Couldn’t figure out where it was coming from until I follow the clue left for me in the masterpage by Randy Drisgill.

The Title is over written by the page layout page. You can get rid of the “Pages – ” in the title by editing the page layout of the page. In the offending page layout look for:

Then:

Set the ListProperty to Visible=”false” and delete the ” – ” before FieldValue on the next line.

Conversly you could add this code to a different page layout to ensure you have similiar page title across your entire site.

My offending page layout was BlankWebPartPage.

This is under Publishing Sites. I’m not sure if it is the same for Team Sites.

Hope this helps someone.

You might run into a situation where you need to have a list template that has a lookup field in it and you want it to look up by list name, not GUID. I my case I have to replicate 3 lists to all child sites for a custom control. Well after fighting with the xml and not finding any real solutions, I stumbled upon a hidden jem barried deep in the bowels of the internet. An anonymus comment on an old blog post hinted that you can replace the GUID in the List property with “Lists/[ListName]“. Well what do you know, it works.

The important portion of your XML line should look like:

<Field Type="Lookup" List="Lists/SiteMenuSections"/>

This will also work with a List Template .stp manifest file. You can simply download the stp file, extract the manifest.xml and modify it. Then use makecab and a properly formated ddf file to create the new stp file. Upload and you’re done.

Hopefully this will save someone a headache and some time.

Microsoft doesn’t make it easy to embed Youtube videos in your SharePoint website. Well thanks to http://forum.jquery.com/topic/change-youtube-and-yahoo-video-links-to-embedded-players there is an easy way to do it using jQuery. I know you’re shocked that I’m using jQuery.

I’ve slightly modified his script as it was wiping out everything on the screen as he had the $(this).replaceWith(mystring) outside of the if videoUrl !== null statement. I also updated it to work with SharePoint. If you paste a link address into a content editor it will automatically convert it into a link. So I have it looking for the a of the link and replace the whole link with the embed code. Oh you’re going to want this code to run in the very last “$(document).ready(function()” you can possibly spare. I have mine placed at the bottom of the master page.

Users need only to paste the youtube url “http://www.youtube.com/watch?v=&#8221; and save the page. That’s it! No special code, crazy web parts, importing text files with the html or other nonsense.

EDIT 4/26/2012: I’ve changed the code to use the new iframe embed rather then the old embed code. It’s cleaner and allows youtube to decided whether it renders flash or HTML 5 video.

//This check and function will replace all <a's> that have a "http://www.youtube.com/watch?v=" with an embed video player.
$("a").each(function() {
// get paragraph text
var mystring = $(this).text(); 
// regular expression for a youtube video
var expression = /http:\/\/(\w{0,3}\.)?youtube\.\w{2,3}\/watch\?v=[\w-]{11}/gi; 
// get an array of matched video urls
var videoUrl = mystring.match(expression);
   if (videoUrl !== null) {
   // for each video url change it to embedded
      for(count = 0; count < videoUrl.length; count++) {
	// replace url with embedded video
	mystring = mystring.replace(videoUrl[count], embedVideo(videoUrl[count]));      
      };
   //Only replace the <a's> that match the string.
   $(this).replaceWith(mystring);
   };
});
   
//This function will replace all a that has a http://www.youtube.com/watch?v= with an embed video player.
function embedVideo(content) {
      var youtubeUrl = content;
      var youtubeId = youtubeUrl.match(/=[\w-]{11}/);
      var strId = youtubeId[0].replace(/=/,'');
      var result = '<iframe width="400" height="248" src="http://www.youtube.com/embed/' + strId + '?rel=0" frameborder="0" allowfullscreen></iframe>';
      return result;
}

In the last two months I’ve been deep in the middle of developing a public facing website. I’m trying to dev with a multitude of different methods to gain expereience, however I’ve been falling into the jQuery with SPServices a lot. Mostly because at first it was easier to get information up on the page without having to develop a new webpart and then deploy it, which then requires a change management form. It was also easier to manipulate the information and put one webpart with multiple tabs and multiple divs which where controlled by the tabs. But then I needed one of the divs to get content from a Pages directory. well it took a couple hours, but then I remembered that those are also “lists”. So now I can get all the info with SPServices without the need of developing a webpart to do the same thing and I can get it to “market” faster. Many thanks to Mark Rackley (@mrackely & http://www.sharepointhillbilly.com) and Marc Anderson (@sympmarc & http://sympmarc.com).

Now if I can just get that little Mark Rackley voice out of my head “bad jQuery can bring down your farm…”, sure sure, but my stuff always works sometimes.

I know, I know you’re only here for the code examples. Well you need to be full aware that I have purposely not put all the code in here. You need to figure some of it so you can understand how it all works. Otherwise I’ve just given you a very in depth, yet simple, script and you put it in without understanding it. That’s dangerous and Mr. Rackley will probably hunt me down, point his finger and laugh hysterically and I’ll have to hear him say “I Told You So” or at very least mock me on twitter.

The End Goal is:

First you need to create your Lists. I pull from three Lists and a subsite Pages. Then on the pages you want you need to setup a content editor. In this I use two divs, a UL and script element reference a .js in the SiteAssets. You might also want to add the style to your CSS file. I like a lot of what Design Chemical has to offer. I use the simple tabs in the Simple Tabs AJAX example. I also use Font Awesome.

/*will be an array to use in the document ready to split the UL's of the Homepage Section Items so they show up as two columns if there are more then what fits in the box.*/
var hpSections = new Array();

//this is where the script starts after the page is loaded
$(document).ready(function(){

/*Stupid SharePoint adds blank space if you don't type anything in a content editor. So you have to clear out the div
before you do anything, otherwise it has wierd spacing issues. */
$("#homepageItemsContent").html("");

//Fixes bug where tabs fills up with multiple set of tabs when modifing other webparts
$("#tabs").empty();

GetSections();

//loop through array and splitUL() will correct if necessary Used inconjunction with line 1
//DY 04/16/2012 I forgot to consider the length of the titles before I included this split function.
//var len=hpSections.length;
//for(var i=0; i<len; i++) {splitUL(hpSections[i],9);};

//set the click function to do nothing
$("#tabs li a").click(function(){return false});

//set the mouseover function
$("#tabs li a").mouseover(function(){
	//Hide all the divs in the content section
	$('#homepageItemsContent div').hide();
	$("#tabs li a").removeClass('current');
	var correctedLink=this.href.split("/")[4];
	$(this).addClass('current');
	$('#'+correctedLink+"Section").show();
	return false;
	});
});

function GetSections(){
var method="GetListItems";
var list="Homepage_Sections";
var fieldsToRead="<ViewFields><FieldRef Name='LinkTitle' /><FieldRef Name='List' /><FieldRef Name='Order' /><FieldRef Name='RowLimit' /></ViewFields>";
var query="<Query><Order><FieldRef Name='Order' /></Order></Query>";

  //Here is our SPServices Call where we pass in the variables that we set above
  $().SPServices({
  operation: method,
  async: false, //if you set this to true, you may get faster performance, but your order may not be accurate.
  listName: list,
  CAMLViewFields: fieldsToRead,
  CAMLQuery: query,
	//this basically means "do the following code when the call is complete"
	completefunc: function(xData, Status){
		//this code iterates through every row of data returned from the web service call
		$(xData.responseXML).SPFilterNode("z:row").each(function(){
		//here is where we are reading the field values and putting them in JavaScript variables
		//notice that when we read a field value there is an "ows_" in front of the internal field name.
		//this is a SharePoint Web Service quirk that you need to keep in mind.
		//so to read a field it is ALWAYS $(this).attr("ows_");
		//get the fields we want to display
		var Title=($(this).attr("ows_LinkTitle"));
		var List=($(this).attr("ows_List"));

		//SharePoint has every number as a decimal. I only want the value before the decimal.
		var Order=($(this).attr("ows_Order")).split(".")[0];
		var RowLimit=($(this).attr("ows_RowLimit")).split(".")[0];

		//Can't uses spaces in IDs or javascript, so we have to correct them.
		var correctedTitle = Title.replace(/ /g,"");

		//push correctedTitle to the Array
		hpSections.push(correctedTitle);

		//call a function to add the data from the row to a table on the screen
		AddRowToTab(Title,List,Order,correctedTitle);

		//Load the div with the content
		GetSectionContent(List,Title,RowLimit);

		});
	}

  });
}

function AddRowToTab(Title,List,Order,correctedTitle){
//Add a new div to the holder
$("#homepageItemsContent").append("<div id='"+correctedTitle+"Section'><ul id='"+correctedTitle+"'></ul></div>");

//Add the tab to the UL
$("#tabs").append("<li class='homepageTab' id='"+correctedTitle+"Tab'><a href='"+correctedTitle+"' class='sectionTab'>"+Title+"</a></li>");

	if(Order==100){
	$("#"+correctedTitle+"Section").show(); $("#"+correctedTitle+"Tab a").addClass('current');
	}else{
	$("#"+correctedTitle+"Section").hide();
	};
}

function GetSectionContent(List,Title,RowLimit){
//The Web Service method we are calling, to read list items we use 'GetListItems'
var method = "GetListItems";

//We need to identify the fields we want to return. You can see here that we are using the internal field names.
var fieldsToRead = "<ViewFields><FieldRef Name='LinkTitle' /><FieldRef Name='Link' /><FieldRef Name='Section' /><FieldRef Name='Icon' /></ViewFields>";

//this is that wonderful CAML query I was talking about earlier. This simple query returns
//ALL rows by saying "give me all the rows where the ID field is not equal to 0". I then
//tell the query to sort the rows by the Title field. FYI: a blank query ALSO returns
//all rows, but I like to use the below query because it helps me know that I MEANT to
//return all the rows and didn't just forget to write a query :) 
var query = "<Query><Where><Eq><FieldRef Name='Section'/><Value Type='Text'>"+Title+"</Value></Eq></Where>"+
	"<OrderBy><FieldRef Name='Sub_Section'/><FieldRef Name='ItemDate' Ascending='False' /><FieldRef Name='ID' Ascending='False' /><FieldRef Name='LinkTitle'/></OrderBy></Query>";

//Here is our SPServices Call where we pass in the variables that we set above
if(List=="[the /Pages/ List GUID]"){
//This is currently hard coded as I can't figure out another way to do this. This Applies to the News sub site.
	$().SPServices({
	operation:"GetListItems",
	async: false, //if you set this to true, you may get faster performance, but your order may not be accurate.
	listName:List,
	CAMLViewFields: "<ViewFields><FieldRef Name='LinkFilename' /><FieldRef Name='Title' /><FieldRef Name='ArticleStartDate' /></ViewFields>",
	CAMLQuery: "<Query><Where><Neq><FieldRef Name='LinkFilename'/><Value Type='Text'>default.aspx</Value></Neq></Where>"+
		"<OrderBy><FieldRef Name='ArticleStartDate' Ascending='False' /></OrderBy></Query>",
	completefunc: function(xData, Status){
		$(xData.responseXML).SPFilterNode("z:row").each(function(){
		var newsItem=($(this).attr("ows_LinkFilename"));
		var Title=($(this).attr("ows_Title"));
		var Link="/News/Pages/"+newsItem;
		var Section="News";
		var Icon="icon-file icon-large";
		AddItemToUL(Title,Link,Section,Icon);
		});
	}
	});

}else{

	$().SPServices({
	operation: method,
	async: false, //if you set this to true, you may get faster performance, but your order may not be accurate.
	listName: List,
	CAMLViewFields: fieldsToRead,
	CAMLQuery: query,
	CAMLRowLimit: RowLimit,
	//this basically means "do the following code when the call is complete"
		completefunc: function(xData, Status){
		//this code iterates through every row of data returned from the web service call
			$(xData.responseXML).SPFilterNode("z:row").each(function(){
			//here is where we are reading the field values and putting them in JavaScript variables
			//notice that when we read a field value there is an "ows_" in front of the internal field name.
			//this is a SharePoint Web Service quirk that you need to keep in mind.
			//so to read a field it is ALWAYS $(this).attr("ows_");
			//get the title field (Link Title)
			var Title=($(this).attr("ows_LinkTitle"));
			var Icon=($(this).attr("ows_Icon"));
			if(Icon==null){Icon="icon-chevron-right icon-large";}else{Icon=Icon+" icon-large";};

			//get the url, SharePoint stores a url in the form of
			//We only want the url. To accomplish this we use the javascript "split" function
			//which will turn into an array where the first element [0]
			//is the url. Catch all that? if you didn't this is another reason you should be
			//a developer if you are writing JavaScript and jQuery :) 
			var Link = ($(this).attr("ows_Link")).split(",")[0];

			//var Sub_Section = ($(this).attr("ows_Sub_Section"));

			//This has a wierd value and spaces, hence the reason we have all of this in there, to clean it up.
			//Not all list have a look up column for Section. Therefore we check if the # is there first before we split so it doesn't barf. (DY)
			var Section = ($(this).attr("ows_Section").replace(/ /g,""));
			if(Section.indexOf("#") !== -1){Section=Section.split("#")[1];};

			//call a function to add the data from the row to a table on the screen
			AddItemToUL(Title,Link,Section,Icon);
			});
		}
	});
};
}

function AddItemToUL(Title,Link,Section,Icon){
$("#"+Section).append("<li class='"+Icon+"'><a href='"+Link+"'>"+Title+"</a></li>");
}

function splitUL(ulName,noDepth){
//http://snipplr.com/view.php?codeview&id=15178
$('#'+ulName).each(function(i){
	if($(this).find("li").size()>noDepth){
	var colsize = Math.round($(this).find("li").size() / 2);
	var ulClass = $(this).attr('class');
		$(this).find("li").each(function(i){
			if (i>=colsize){
			$(this).addClass('splitcol_right');
			}
		});
	$(this).find('.splitcol_right').insertAfter(this).wrapAll("<ul class='"+ulClass+"'></ul>");
	$('#'+ulName+":first-child").css("padding-right","25px");
	}
});
}

Split the UL in two

I use this handy little javascript to split a UL in two and display them as two columns. This is a modified version of http://snipplr.com/view.php?codeview&id=15178.

You can see that you pass in the UL ID and the the depth at which you want it to check it is before splitting. That way if you have room for 10 and it’s length is 7 then you aren’t splitting it and possibly making it look funny. If you want to split it regardless of size pass 0. Also you’ll notice that it will use the class of the UL that it being split. I had a funny thing happen where the style of the new UL was very different. So I wanted to be sure that it looks the same.

function splitUL(ulName,noDepth){
$('#'+ulName).each(function(i){
if($(this).find("li").size()&gt;noDepth){
var colsize = Math.round($(this).find("li").size() / 2);

var ulClass = $(this).attr('class');
$(this).find("li").each(function(i){
if (i&gt;=colsize){
$(this).addClass('splitcol_right');
}
});
$(this).find('.splitcol_right').insertAfter(this).wrapAll("<ul class='"+ulClass+"'></ul>");
}
});
}

For added comfort use the following style with whatever padding you want. This will apply the padding only to the first UL that you are splitting and not the second UL which might bump the page and make it look funny.

[className]:first-child{padding-right:80px;}
Follow

Get every new post delivered to your Inbox.