tag:blogger.com,1999:blog-82719983028031224362024-03-18T12:44:12.311+02:00Bordering .NET[notes on and around design and development of .net based software - especially SharePoint]Unknownnoreply@blogger.comBlogger96125tag:blogger.com,1999:blog-8271998302803122436.post-7976540361177117582018-04-10T13:14:00.000+03:002018-04-10T21:14:06.532+03:00Modern SharePoint in Office365During these past couple of years, the SharePoint field has changed drastically. Instead of loads of on-prem installations and massive brandings, intranets and team sites have largely migrated to the cloud, to Office 365 and gotten a truck load of new options and tools as time has passed.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Office 365 is so much more than just SharePoint. SharePoint still is at the core of everything and intranets and team sites can still be built as they always have been in SharePoint: by centrally creating site collections for different purposes. While this has still been and still is the chosen path by many companies, there is so much more to SharePoint and team work today, that it really should be considered in each and any organization instead of locking the usage to "the way it's always been".</div>
<div>
<br /></div>
<div>
The Office 365 tool pallette revolving around SharePoint today includes:</div>
<div>
- Classic SharePoint sites - publishing, teams, blogs, project etc. "managed" site collection created either in Admin Portal by SharePoint global admins or usually offered to users via a site provisioning tool connected to a site order form</div>
<div>
- Modern SharePoint sites - two types of sites: Team sites and Communication sites, which users can create using the self service site creation on the "SharePoint" page in O365 portal</div>
<div>
- Office 365 groups - "AD groups" created by users; users have shared mailbox and calendar and group site (modern)</div>
<div>
- Forms - app for creating polls, feedback forms etc.</div>
<div>
- PowerApps - tool for creating interactive apps and modifying list forms</div>
<div>
- Flow - app for workflows</div>
<div>
- Power BI - app for all kinds of data</div>
<div>
- Planner - Microsoft's answer to Trello, ie. canban board app connected to groups</div>
<div>
- Teams - app for team/topic conversations; connected to groups</div>
<div>
- Yammer - app for conversations</div>
<div>
<br /></div>
<div>
And more, but these are the most essential ones for modern team work, when we are looking at things from a SharePoint perspective. It is no wonder then, that so many times people are totally confused and lost in the jungle of possibilities. </div>
<div>
<br /></div>
<div>
The above mentioned set of tools is more or less loosely connected to SharePoint but not necessarily immediately. Some of them can be used, or rather launched from SharePoint sites, e.g. Flow and PowerApps from a list or library page. Some of them provide a means to show data in a SharePoint page, e.g. Forms and Power BI. Some of them are linked to groups, like e.g. Planner and Teams, and a group also always has its own modern team site with (almost) all SharePoint functionalities. </div>
<div>
<br /></div>
<div>
Modern Team sites however are only one type of SharePoint sites currently available. Modern Commucation sites are the modern version of classic publishing sites. Classic sites - publishing and teams - still exist also. A classic team site (site collection) can be groupified (soon) thus creating a "O365 group wrapper" around it, bringing the group functionalities to it.</div>
<div>
<br /></div>
<div>
In the world of modern intranets, there still are fully branded classic publishing site intranets, but also ones built using Communication sites only are quite a few already. Communication site intranets can be built either by creating subsites (like in the classic version) or in the future by using SharePoint Hub sites (currently available in targeted release) to network separate sites together into a more flexible web. </div>
<div>
<br /></div>
<div>
Since pictures usually say things better than a million words, I will let my little diagram do the rest of the explaining. Hope it helps to understand the different philosophies and technologies behind the different site types!</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNZggw2XxWJK1wHUmZ_4uEGfP_rITLohFANi1c1cBhyphenhyphenR4zg1nV4AazHFxEHaNo23xaHuk_RFFMeRImPObZ58CHwbCZ4qy-D68dyuBYhXRJhJQsvV4jmo5WgV4CK1xK34azrgdlI8FxtYU/s1600/modernandclassicsp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNZggw2XxWJK1wHUmZ_4uEGfP_rITLohFANi1c1cBhyphenhyphenR4zg1nV4AazHFxEHaNo23xaHuk_RFFMeRImPObZ58CHwbCZ4qy-D68dyuBYhXRJhJQsvV4jmo5WgV4CK1xK34azrgdlI8FxtYU/s640/modernandclassicsp.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-8271998302803122436.post-6509508753997710592016-09-29T13:23:00.000+03:002017-01-28T15:22:54.103+02:00List with Paging on the Bottom Control TemplateOne of our customers wanted to use the List with Paging control display template on their news page. For some strange reason this template positions the paging in the top right corner of the web part instead of at the bottom of the list, and preferably horizontally in the center.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
I fugured there were two options to do this:</div>
<div>
1) Use CSS only (usually my preferred way)</div>
<div>
2) Create your own display template for the purpose</div>
<div>
<br /></div>
<div>
Now the problem with approach #1 is that there are other content search web parts on the page too, so if you make general rules to create space at the bottom of the ul.cbs-List, this will be applied to all of those CSWPs. There is no special CSS class to hook into in the paging template ul. So even at best, this approach is a bit of a hack because in order to target it properly, you would need to use some container identifier and thus cause the whole hack to break if the web part is moved to a different zone on the page.</div>
<div>
<br /></div>
<div>
Number 2 seems easy enough, though, and replicable, which is even better. I set to action, downloading the original Control_ListWithPaging.html template file and opening it for editing in Expression Web and saving it with a new name. </div>
<div>
<br /></div>
<div>
First, I added another class to the ul.cbs-List element, in order to be able to target rules only to the CSWPs using my new template. Small enough change, don't you think? </div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><ul class="cbs-List pagingbtm"></span></div>
</div>
<div>
<br /></div>
<div>
Of course I also changed the title of the html document to List with Paging on the Bottom.</div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><title>List with Paging on the Bottom</title></span></div>
<div>
<br /></div>
<div>
No biggie, right? I then uploaded the file, just to check that it works. Which it didn't! This puzzled me immensely, especially since the error message said, that the div, body and html tags have not been closed. They are not closed in the original control template (at least not when I opened it in notepad to check) but that works fine. </div>
<div>
<br />
So fine, I closed those tags at the end of my new template file. The error message disappeared and instead my template worked perfectly. Well, almost. The little arrow icons weren't visible but at least there was no error anymore. I decided to ignore that for the time being and finalize my control template changes. </div>
<div>
<br /></div>
<div>
As said, I could've done it all in CSS only (after adding the new class), but I decided to make one more minor change in html to make the css shorter and less vulnerable and avoid the extra space when there are less items than the paging limit. I moved the resultset to the beginning of the list, so that the paging became the last node instead of the first one.</div>
<div>
<br /></div>
<div>
The results are displayed by this variable:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">_#= ctx.RenderGroups(ctx) =#_</span></div>
<div>
<br /></div>
<div>
It is originally right before the closing ul tag. By simply moving it right after the opening ul tag, the order is reversed.</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><ul class="cbs-List pagingbtm></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">_#= ctx.RenderGroups(ctx) =#_</span></div>
</div>
<div>
<br /></div>
<div>
When this was done and tested, I started looking into that arrow icon issue. Quirkily, the img src was pointing to a nonexistent file on my own computer! This can be blamed on Expression Web. It's a first, though! I'm quite used to SharePoint Designer pulling off sh*t like this, but Expression Web has generally been a very reliable editor and loyal to the original code. Not this time. </div>
<div>
<br /></div>
<div>
I opened the original file in notepad and sure enough, the correct source string was there, intact. </div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><img class="_#= $htmlEncode(nextPageImageClassName) =#_" alt="_#= $htmlEncode(lastPage.title) =#_" </span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">src="_#= $urlHtmlEncode(GetThemedImageUrl('spcommon.png')) =#_</span><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">"></span></div>
<div>
<br /></div>
<div>
So I copied and pasted it to my template and all was well in SharePoint Land again.</div>
<div>
<br /></div>
<div>
Here's the CSS:</div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">ul.cbs-List.pagingbtm li.ms-promlink-header {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> text-align: center;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">ul.cbs-List.pagingbtm .ms-promlink-headerNav {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> float: none;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> margin-top: 6px;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
</div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8271998302803122436.post-28040942417959040472016-05-18T11:43:00.003+03:002016-05-26T09:51:42.317+03:00Search Results vs. Content Search Web Parts: customizing and date formattingThe default way to display feeds from news, events etc. on an intranet front page is to use the Content Search Web Part. Used to be Content Query, but customizing the CQWP is way more complicated plus it is restricted to the same Site Collection only. This is still used, as is, by many of my customers, for it is easier for content managers to set up than the search queries. Anytime any custom templates are needed (or when I am setting up the feeds), definitely CSWP is the way to go.<br />
<div>
<br /></div>
<div>
Lately, though, I have had several customers with SharePoint Standard lisence only. Unfortunately this leaves out the CSWP completely. Search indexing and search driven content is still available, but building those said feeds is just a tad more complicated for you need to use the Search Results Web Part, which is not created for this kind of usage, even though it CAN be used. It requires some more work, but once you've figured out the basics, it's not that difficult. Just a bit different than the CSWP.</div>
<div>
<br /></div>
<div>
The display templates of CSWP consist of a control template and an item template (for more info, see my post "<a href="http://borderingdotnet.blogspot.fi/2013/03/the-anatomy-of-sharepoint-2013-display.html" target="_blank">The Anatomy of SharePoint 2013 Display Templates</a>"). Mostly the modifications and customizations are rather straightforward to make by following the example of things already there. The date formatting, however, is a bit tricky. What you need to do is:</div>
<div>
<br /></div>
<div>
1) Copy the item display template you want to modify from MasterPages gallery, Display Templates, Content Web Parts directory.</div>
<div>
<br /></div>
<div>
2) Create a managed property of the field you want to use, if not using Created or LastModifiedDate, in Search Schema.</div>
<div>
<br /></div>
<div>
3) Use the date field as value for desired line data, eg:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">var line1 = $getItemValue(ctx, "Line 1");</span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">var line2 = $getItemValue(ctx, "Line 2");</span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">var eventdate = new Date(line2.inputValue);</span></div>
<div>
<br /></div>
</div>
<div>
4) Format the date as you wish in the HTML where the value is rendered:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: purple; font-family: "courier new" , "courier" , monospace;"> <div class="cbs-Line2 ms-noWrap" title="_#= $htmlEncode(line2.defaultValueRenderer(line2)) =#_" id="_#= line2Id =#_">_#= <span style="background-color: yellow;">eventdate.format("d.MM.yyyy H:mm")</span> =#_</div></span></div>
</div>
<div>
<br /></div>
<div>
5) Upload your display template (remember to change the title in the HTML and rename your modified file) back to the same folder in MasterPages gallery and publish it. It's ready to be used.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOIo3aqf2Pb9wzpyigbZeduVUkYBdy5owR_5ZCehUklMqp_fUS8vdHj4pUIk2vh1E3gDdiUpQ61HZVwe3cBKJx_FHMzVfkUVLVUDL9ZSJuiHXIfiVJekKJubjPc00CFqXx1mZjGqFvcJ4/s1600/eventdate.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOIo3aqf2Pb9wzpyigbZeduVUkYBdy5owR_5ZCehUklMqp_fUS8vdHj4pUIk2vh1E3gDdiUpQ61HZVwe3cBKJx_FHMzVfkUVLVUDL9ZSJuiHXIfiVJekKJubjPc00CFqXx1mZjGqFvcJ4/s400/eventdate.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
As for the Search Results web part, the system is slightly more tricky. First off, there are more display templates involved: </div>
<div>
<ul>
<li>Control templates</li>
<li>Item templates</li>
<li>Item HoverPanel templates</li>
</ul>
</div>
<div>
Mostly, you need to work with Item templates and/or hoverpanel templates, if using the hover panel. In the case of displaying feeds on front page, the hover panel is seldom wanted. It can be removed. Simply delete highlighted parts from the display template you copied, eg. ItemDefault (note, that the Search Result templates are in the Search folder):</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><div id="_#= $htmlEncode(itemId) =#_" name="Item" data-displaytemplate="DefaultItem" class="ms-srch-item" </span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">onmouseover="_#= ctx.currentItem_ShowHoverPanelCallback =#_" onmouseout="_#= ctx.currentItem_HideHoverPanelCallback =#_"</span><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">></span></div>
</div>
<div>
<br /></div>
<div>
And then comment out the following line:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> <!-- <div id="_#= $htmlEncode(hoverId) =#_" class="ms-srch-hover-outerContainer"></div> --></span></div>
</div>
<div>
<br /></div>
<div>
Other modifications that I have found useful and quite necessary in said use case are</div>
<div>
<ul>
<li>removing the item URL - actually in default item template I just remove the whole default body render tag:<br /><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">_#=ctx.RenderBody(ctx)=#_</span></li>
<li>building your own stuff to show for each item, e.g. rollup image, a content summary, publish/create date eg. </li>
</ul>
Adding fields to the display template is simple enough. The fields need to be managed properties in Search Schema, so remember to do this first for any custom fields. Then you add the properties to the template mso:ManagedPropertyMapping tag:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><mso:ManagedPropertyMapping msdt:dt="string">'Title':'Title','Path':'Path','Description':'Description','EditorOWSUSER':'EditorOWSUSER','LastModifiedTime':'LastModifiedTime','CollapsingStatus':'CollapsingStatus','DocId':'DocId','HitHighlightedSummary':'HitHighlightedSummary','HitHighlightedProperties':'HitHighlightedProperties','FileExtension':'FileExtension','ViewsLifeTime':'ViewsLifeTime','ParentLink':'ParentLink','FileType':'FileType','IsContainer':'IsContainer','SecondaryFileExtension':'SecondaryFileExtension','DisplayAuthor':'DisplayAuthor',</span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">'Created':'Created','NewsSummary':'NewsSummary', 'PublishingImage':'PublishingImage' </span><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"></mso:ManagedPropertyMapping></span></div>
</div>
<div>
<br /></div>
<div>
Then you use this to build your own HTML for the items, eg.</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><div id="_#= $htmlEncode(itemId) =#_" name="Item" data-displaytemplate="DefaultItem" class="ms-srch-item"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> <div class="newscontainer"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><div class="newstitle"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><a href="_#=ctx.CurrentItem.Path=#_"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>_#=ctx.CurrentItem.Title=#_</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></a><br></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> </span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class=newsdate></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"> _#=ctx.CurrentItem.Created=#_</span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></div></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><div class="newsbody"></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><div class="newsimg"></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>_#=ctx.CurrentItem.PublishingImage=#_</span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></div></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><div class="newstext"></span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>_#=ctx.CurrentItem.NewsSummary=#_</span></div>
<div>
<span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></div></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></div></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span></div></span></div>
</div>
<div>
<br /></div>
<div>
Note the date there, though. It will give you a very long date format by default, but in a Search Results template it is way easier to format the date than CSWP. Simply add <i>format(yourdiesiredformatting)</i> to the value in HTML. Like this:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">_#=ctx.CurrentItem.Created.format("d.M.yyyy")=#_</span></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO8xg_suepfIEVXjq0vObLqBCrXLzeOmu50foh7lFgbgMrYRv4y9QFHU8j5MJlfjHN49dwwFYEqSSyOKAA2C4UwJG4ew41sDbijf7ZE7KY258bR3WR6rM27l8NfR7W_f3uqnGQEJjsMTc/s1600/newstemplate.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO8xg_suepfIEVXjq0vObLqBCrXLzeOmu50foh7lFgbgMrYRv4y9QFHU8j5MJlfjHN49dwwFYEqSSyOKAA2C4UwJG4ew41sDbijf7ZE7KY258bR3WR6rM27l8NfR7W_f3uqnGQEJjsMTc/s400/newstemplate.jpg" width="400" /></a></div>
<div>
<br /></div>
<div>
Then there is only one little nuisance left: the hover background color. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgYj5dxKXp5ZgutKUN08W0XtUN9oy8lUI8z0TX0dEDDZZ89Iy8QmBn6KN6aBz5mtMlYUNd5BTFbuS3NuS15gdUwlbc_6sBcP4btRyNVne6UhKQKWN_3f9xERULmndIN5ZTR55KwqrGixI/s1600/newstemplatehover.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgYj5dxKXp5ZgutKUN08W0XtUN9oy8lUI8z0TX0dEDDZZ89Iy8QmBn6KN6aBz5mtMlYUNd5BTFbuS3NuS15gdUwlbc_6sBcP4btRyNVne6UhKQKWN_3f9xERULmndIN5ZTR55KwqrGixI/s1600/newstemplatehover.jpg" /></a></div>
<div>
<br /></div>
<div>
This comes from this CSS rule: </div>
<div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">.ms-srch-item:hover, .ms-scrch-resultHover:hover, .edisc-SearchResultItemContainer:hover{</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>background-color: rgba(...);</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
</div>
<div>
<br /></div>
<div>
Now, if you override this as is, it will effect the search results pages too. So try to identify the targets in some way, use eg. .welcome or .article classes for targeting content pages only in removing the hover color.</div>
<div>
<br /></div>
<div>
Whew! All done!</div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-8271998302803122436.post-71343220827923993192016-05-04T19:47:00.000+03:002016-05-04T19:47:01.135+03:00SharePoint Dev Kitchen 2016I was really happy when I heard that the embargo was being lifted on the current SharePoint development stuff, and I could finally tell the wolrd about the amazing SharePoint Dev Kitchen experience of this past March in Brussels. An invitation only -event for SharePoint dev community, the bootcamp was full of people with ideas, views and passion, and the core of the Microsoft SharePoint team.<br />
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU9yIKW3Mq6dqtll9md5Q4FJvyWN6bSlZkakD1pocf1GIbdXtNeU2ZDpdUsFES_6f1xj285j6XbD_NCZt-v1izleuJLN5Ujsn1LPHU9JUp82AnYYYTTv0xooU_X2oxi_ixlLAJMJi3wBQ/s1600/WP_20160322_012.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU9yIKW3Mq6dqtll9md5Q4FJvyWN6bSlZkakD1pocf1GIbdXtNeU2ZDpdUsFES_6f1xj285j6XbD_NCZt-v1izleuJLN5Ujsn1LPHU9JUp82AnYYYTTv0xooU_X2oxi_ixlLAJMJi3wBQ/s320/WP_20160322_012.jpg" width="180" /></a>The big meeting room was buzzing with electricity as we all settled into our seats to hear what the SharePoint team wished to share with us. The preparation emails had given but a little hint on what was happening in our SharePoint world. </div>
<div>
<br /></div>
<div>
When the keynote ended, I felt a whoosh of delight. The SharePoint team was not only being candid with us but also looking to get feedback, thoughts and ideas from us who crowded the room. Still, the most exciting thing was the <b><i>message </i></b><span style="color: purple;">[NOTE: this is purely <b>PRE-RELEASE</b> info]</span>:</div>
<div>
<b><i><br /></i></b></div>
<blockquote class="tr_bq">
<b><i>SharePoint is going towards more and more open source coding</i></b><b><i><br /></i></b>Instead of doing a whole lot of behind the scenes closed-cirquit development, the SharePoint team has adopted the usage of JavaScript libraries and frameworks that enable the third-party developers to create add-ins and solutions for SharePoint with any JavaScript framework they wish to use. </blockquote>
<blockquote class="tr_bq">
<b><i>Mobile leads development</i></b><b><i><br /></i></b>They were pretty clear on this one. All develoment is done mobile first. Not desktop first keeping mobile in mind but actually <i style="font-weight: bold;">mobile first</i>, then desktop experienve. </blockquote>
<blockquote class="tr_bq">
<b><i>SharePoint Home</i></b><b><i><br /></i></b>If I had a euro for each time a customer has asked me: "But where's the SharePoint here in O365? There's only this Sites... is that it? But how do I find my workspaces if I haven't followed them?" As far as I understood, SharePoint Home will asnwer this question once and for all. It's where SharePoint is, it's where the workspaces are. </blockquote>
<blockquote class="tr_bq">
<b><i>A lot of nice new features are coming to SharePoint</i></b><b><i><br /></i></b>Document libraries will get a bunch of new features. Publishing sites will get a new page model as an addition to the current one (i.e. the current publishing pages aren't going anywhere; your data is safe) with the feel of Sway to them - adding modules (or cotnrols or web parts, whatever the name will be) to a page canvas (or several). Publishing sites will get a gallery of these modules - new web parts - that are fully JavaScript based. </blockquote>
<blockquote class="tr_bq">
<b><i>Office UI Fabric</i></b><b><i><br /></i></b>In addition to this new more open way of developing for SharePoint, Microsoft is providing a "fabric" of CSS and (HTML) controls for unified look and feel of any app or add-in that made for Office environments. It provides a grid for responsive design, fonts, animations etc. to be used freely - but no one is forcing it either.</blockquote>
<div>
<br /></div>
<div>
One thing the Microsoft people really emphasized: the old way is not going away; this new model simply enable <i style="font-weight: bold;">more</i>.</div>
<div>
<br /></div>
<div>
Dev Kitchen was a very social three day "training". Sure, Microsoft people were giving sessions on what they are working on, the technologies that are used and there were hands-on labs to try out the things in a test environment. However, there was also a lot of discussion of ideas and questions and priorities and wishes and whatnot. There were a lot of people already getting their hands dirty with the new stuff, trying out real life scenarios and showing their work in demo sessions. </div>
<div>
<br /></div>
<div>
Now the team is ready to come out with the stuff, but this is only the beginning. A lot is brewing in the SharePoint Dev Kitchen and it will be truly interesting to see the outcome! </div>
<div>
<b><i><br /></i></b></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-87209671269029709802016-04-19T10:44:00.000+03:002016-04-19T10:44:09.838+03:00Removing reusable SPD workflows completelyRecently I have been working on a set of different custom SharePoint Designer workflows for different customers. Sometimes the process is not so straightforward that you get things right on the first try and sometimes the errors result in the need to actually remove some trial workflows from the system. <div>
<br /></div>
<div>
Reusable workflows are slightly more tricky to remove from the SharePoint UI than the list workflows. In SharePoint Designer, the main way of managing workflows is in the Workflows section. This may well tempt you to remove the workflow simply from that list and be done with it. This, however, will not remove it from the SharePoint UI, and thus an old depracated workflow is still available for users. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN5z04omZH1_wgUD7MypbltA7w3Ih5OQ34NuO11GWDDCSx9XEAm3aIsb-ovxyD8Haepsm6PHMXXfW8E2TJAWggv0df68w3YJgj-HHWj1FRguASSVg-CWW0ROceTHMFFSO7FbnIY8Cy6HY/s1600/spdwf1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN5z04omZH1_wgUD7MypbltA7w3Ih5OQ34NuO11GWDDCSx9XEAm3aIsb-ovxyD8Haepsm6PHMXXfW8E2TJAWggv0df68w3YJgj-HHWj1FRguASSVg-CWW0ROceTHMFFSO7FbnIY8Cy6HY/s640/spdwf1.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The right place to remove the workflow from is to open the All files section, find the Workflows directory there and delete the whole workflow directory. </div>
<div>
<br /></div>
<div>
But what if you already deleted the workflow in the Workflows list and now you have no directory for it anymore but it still shows up in the SP UI? This is what I was researching this morning. The place to go in that case is - surprise surprise! - the _catalogs directory. There you will find a folder named wfpub. And in that wfpub folder, you still have the directories for even those workflows that were deleted from the Workflows section listing. Delete these directories with all their contents and you're good.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq8JWXgtbDfoncdgBAC8zNJYaltOpcM9U2tzbRrDlI6K6cQmityr0KHIFc3g1Uqc9Rks-96DkJE-wQVwGl5BHPkHYomyYA8G5uF5OxBQmujv1T8fqGSRCFBjAdHNEbhK6zpHg7_hKuaTs/s1600/spdwf2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq8JWXgtbDfoncdgBAC8zNJYaltOpcM9U2tzbRrDlI6K6cQmityr0KHIFc3g1Uqc9Rks-96DkJE-wQVwGl5BHPkHYomyYA8G5uF5OxBQmujv1T8fqGSRCFBjAdHNEbhK6zpHg7_hKuaTs/s640/spdwf2.png" width="640" /></a></div>
<div>
<br /></div>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-8271998302803122436.post-63363787864533700322016-03-18T15:16:00.000+02:002016-03-18T15:18:19.637+02:00SharePoint Branding and the winds of change<div style="font-face: tahoma; font-size: 10pt;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrajq2-iFjZr6Efk4RYMe-CmzPjlJtIC4-vtuoImB-Z0GIAEInnwjxExw73M1aUpsMFhRjBCat3Pq4ePzaKOwoQWvogIQXt4jS0tblW1IpQyiu9VcVBst9yJqA9wBqlv0xkpbVZVkaaT8/s1600/2016-03-08_14-10-08.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="105" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrajq2-iFjZr6Efk4RYMe-CmzPjlJtIC4-vtuoImB-Z0GIAEInnwjxExw73M1aUpsMFhRjBCat3Pq4ePzaKOwoQWvogIQXt4jS0tblW1IpQyiu9VcVBst9yJqA9wBqlv0xkpbVZVkaaT8/s320/2016-03-08_14-10-08.png" width="320" /></a><span style="font-family: inherit;">Not that long ago, it was quite typical to create a major SharePoint UI solution for a SharePoint intranet. It would contain one or more Master Pages, CSS stylesheets, images, JavaScript, Page Layouts etc. The solution package was deployed to the server, the feature activated and automagically the intranet got its fancy custom UI and functionalities. A slight inconvenience though, that even the smallest change or improvement in any of the shipped files required updating the whole package.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">It hasn’t been too long since I last was involved in such a big intranet solution. These days such projects are more of the exception than the rule. So, what’s changed?</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">One thing, or maybe I should say THE thing is Office 365. Cloud is becoming more and more popular and doesn’t even allow such huge full-trust solutions. Sandbox solutions are still an option, though according to Microsoft they are not the technology of the future – they already once declared them deprecated, but actually had to take it back pretty quickly. However, apps and other alternative ways of doing things (PowerShell, Azure powered functionalities etc.) are the modern and flexible way to build stuff on top of SharePoint, while keeping it separate from SharePoint.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">I believe it’s not inaccurate to say that all the rest is just a byproduct of this. While more and more companies are switching to the cloud environments and Microsoft is developing “cloud first”, it is only natural for attitudes and ways to adapt to this change. Lightweight tweaking as opposed to heavy – especially with a heavy update process – custom software development sounds quite enticing.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Years ago, when SharePoint 2010 was launched and companies started to migrate from the old 2007 environment to the shiny new SharePoint in a fast pace, the game of the day was using OOB where ever possible and doing as little customization as possible. Mostly this still meant creating easily retractable solution packages for UI and custom web parts and services, distributed as features. SharePoint wasn’t re-coded anymore as it used to be in many cases with MOSS 2007; the solutions were built on top of SharePoint without touching the OOB stuff.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Then, along came SharePoint 2013. For quite some time the development and customization story was pretty same as with 2010, up until Online made its breakthrough and started to mold the models towards the more lightweight facelifts, apps, external services etc. The process of UI customization, branding, has shrunk from a heavy solution package to creating themes, some custom CSS and maybe a bit of JavaScript.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">A color theme is a rather easy and quick way to apply the company branding colors to SharePoint. It already takes you a long way – the company colors are applied to the top suite nav, links, emphasis colors, headings etc. Creating a font scheme adds to this by implementing the company font – even a custom one – everywhere with one setting. What cannot be done by a theme is changing the placement and fancier styling of page elements.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">The current default Master Pages seattle and oslo are built using div elements. This means that working with them – the placement, float, etc. – is pretty flexible and easy without needing to change the HTML of the Master Page, i.e. there is no need to create custom Master Pages simply to change how and where the elements are rendered on the page. There are limits to this, but you can do a lot with CSS.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVUNChDqrIZ5kUXe0Ry-_JuNB9mcY_QAWGtaBUkZIqT7yFZEe25PhOoSzpG5v8p6pPRd_1hEJbryJfaM-A_q8ehu-JJ7mfd9aJpe2la9DKwbT7ox3elfQP0B6uaeRShLMfv3xwO-Okto0/s1600/2016-03-08_14-07-48.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="121" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVUNChDqrIZ5kUXe0Ry-_JuNB9mcY_QAWGtaBUkZIqT7yFZEe25PhOoSzpG5v8p6pPRd_1hEJbryJfaM-A_q8ehu-JJ7mfd9aJpe2la9DKwbT7ox3elfQP0B6uaeRShLMfv3xwO-Okto0/s640/2016-03-08_14-07-48.png" width="640" /></a></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Themes and an alternate CSS stylesheet are easy to implement in the UI of SharePoint, in the site settings, and they are inherited by any subsites with publishing feature activated. Implementing them to sites without publishing feature is a bit more work. Generally, this means pushing the inheritance from the top level each time a new site has been created.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">JavaScript adds its own challenge to the equation. It is possible to globally inject JavaScript to all sites in a site collection using PowerShell. However, this should then be done for each new site too, when one is created. In single pages the Script Editor Web Part works nicely, but the global injection is always a bit of an issue. Mainly the options apart from the manual PowerShell injection are adding the script links to the Master Pages or creating an Azure powered service for provisioning the sites. </span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">The latter option is actually something to consider. Basically the idea is that people don’t create their sites manually but order them by creating a new item into an order list. A timer job polls the list and notices a new site order and launches a PowerShell script that then provisions the site with the exact settings, stylesheets, logos, Web Parts, lists, JavaScript links that are needed for each new site. </span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Add responsive design to the equation. Currently SharePoint Online offers two view for mobile devices and the possibility to switch between them. One is the mobile list oriented view, the other one the full desktop view. The list oriented view works fine in team sites where all the content is mainly in lists, but publishing sites, the informative intranet pages, need to be viewed in full desktop experience on mobile devices too – in a responsive way so that it actually is readable.</span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Unfortunately, responsive SharePoint is still a bit of a everyone for their own – or has been, but I have just discovered that <a href="https://github.com/OfficeDev/PnP-Tools/tree/master/Solutions/SharePoint.UI.Responsive" target="_blank">PnP has actually come forth with an awesome fully responsive solution that is purely CSS based</a>! Previously the options have been e.g. bootstrap (heavy version), a responsive SharePoint solution from Codeplex (kinda heavy solution too); both of these require changes to the MasterPage. A bit of a no-no. </span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">Be as it may, responsive design is always more expensive for a customer than the basic design only. However, as the costs of branding have come down significantly with the lighter approach, it most definitely pays off to invest in responsive design, if not go mobile first. That’s where this world is headed anyway. </span></div>
<div class="MsoNormal">
<span style="font-family: inherit;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: inherit;">[Originally published <a href="http://www.onsight.fi/sharepoint-brandays-muutoksessa/" target="_blank">in Finnish in our company blog</a>]</span></div>
<div style="font-size: 10pt;">
<br /></div>
</div>
<div style="font-face: tahoma; font-size: 10pt;">
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-32523033189839376432016-03-07T12:10:00.000+02:002016-03-07T14:36:28.094+02:00Tip: Fix List Issues After Migration 2010 -> 2013Once again, faced with issue after issue. There was a SharePoint intranet that was migrated from SP2010 to SP2013. There was a list in the intranet, containing crucial information that should be easily searched. However, there was no list search available. Also, none of the columns were site columns. So I set out to create a search page for the list data. Everything runs cool if you just try to search with data in the title field (or author). However, there were some other fields including data to search wih.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Piece of cake, I thought to myself, disregarding the fact that most of the time the pieces of cake are tough to chew when it comes to SharePoint. I created some site columns and added them to the list, positioning them next to the original ones, with the intention to simply open the list in quick edit mode and copy values from list columns to site columns. Easy enough!</div>
<div>
<br /></div>
<div>
However, the list being a custom list originating in SP2010, the quick view was unavailable. I contemplated on exporting the data to Excel, modifying it there and creating a new list using that sheet. Before attempting that, I decided to google just a bit in hopes of finding a solution. And I did, hurray for <a href="http://www.sharepointdiary.com/2014/12/fix-quick-edit-disabled-in-sharepoint-2013-issue.html" target="_blank">Saludeen Rajack</a>!</div>
<div>
<br /></div>
<div>
Since I had already tried most of the tricks in the blog post, in vain, I crossed my fingers and opened the list page for editing, opened list web properties and added <b>clienttemplates.js</b> to the JS Link property of the web part (at the very bottom of the Miscellaneous section).</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-wxA5xPoFAucvQrEPdNV_63n7s5VlFig2okm0znYcPPEE8uYMjzczFseEnjyi3hDgqtxtaYMpffaAmUYc4sHQep8RnLQ0UidbkXTKpJdGiJLQWfXED1lTTXYMktIkIkLqzBrV76bN2nU/s1600/2016-03-07_12-08-25.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-wxA5xPoFAucvQrEPdNV_63n7s5VlFig2okm0znYcPPEE8uYMjzczFseEnjyi3hDgqtxtaYMpffaAmUYc4sHQep8RnLQ0UidbkXTKpJdGiJLQWfXED1lTTXYMktIkIkLqzBrV76bN2nU/s320/2016-03-07_12-08-25.jpg" width="320" /></a></div>
<div>
</div>
<div>
<br /></div>
<div>
And lo and behold! First of all, the list search box appeared at the top of the list and secondly, the quick edit button became active. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibJa02cB5dWYRM77gVVRV1LpiqAZ3nPJVe_JKddNfgW27WS5JS3TPnq0-dc93LBQVr_tFxk0p1oh0pebyPRF-M0I7G5PDfU823txcK42bfL7-6SbChsDUpx114wfVoeDtKvSxizGc7sGk/s1600/2016-03-07_11-58-26.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="50" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibJa02cB5dWYRM77gVVRV1LpiqAZ3nPJVe_JKddNfgW27WS5JS3TPnq0-dc93LBQVr_tFxk0p1oh0pebyPRF-M0I7G5PDfU823txcK42bfL7-6SbChsDUpx114wfVoeDtKvSxizGc7sGk/s400/2016-03-07_11-58-26.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBBFqogvRVgwG60V2ctgnx9FUUxR1va84rxxLKqj2yhL8tCs8yFCDQas7THQH6x62b2pDnnGEdmmjpGsLfzOaqbk3Y5drWvfyNlZeLf7iKuFiNsiChswW1hseIxFJGLP5qbNrTp0b_OmI/s1600/2016-03-07_11-59-05.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBBFqogvRVgwG60V2ctgnx9FUUxR1va84rxxLKqj2yhL8tCs8yFCDQas7THQH6x62b2pDnnGEdmmjpGsLfzOaqbk3Y5drWvfyNlZeLf7iKuFiNsiChswW1hseIxFJGLP5qbNrTp0b_OmI/s200/2016-03-07_11-59-05.jpg" width="200" /></a></div>
<div>
<br /></div>
<div>
Now I could proceed with my plans properly.</div>
Unknownnoreply@blogger.com89tag:blogger.com,1999:blog-8271998302803122436.post-49814439449001717392016-02-17T14:56:00.000+02:002016-08-05T12:05:16.908+03:00Javascript world clock with automatic time zonesOne would imagine that getting a world clock - real time with automatic time zones including daylight savings - wouldn't be that difficult to include on your web site. On a standalone web site it probably isn't since there are several free or low cost solutions available. But in SharePoint it wasn't quite as straightforward.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
One of my customers, a global company, already has one solution implemented on their intranet site, but there are two problems with it: it only refreshes the time on page refresh and the daylight savings (i.e. offset for each time zone) need to be adjusted manually every half a year. So I began to look into the options for modernizing this world clock of theirs.</div>
<div>
<br /></div>
<div>
First thing I realized was that most of the ready made solutions rely on PHP. This is already a no-no in SharePoint. Then I came accross this very cool site <a href="http://www.clocklink.com/">http://www.clocklink.com/</a> which has built in time zones and a multitude of analaog clocks (using html5 or flash). These could be used in SharePoint quite easily per se, and I even found a pretty neat solution using a SharePoint list to create a multitude of easily maintainable clocks. Check it out at <a href="https://blog.pathtosharepoint.com/2009/01/09/world-clock/" target="_blank">Path to SharePoint</a>. </div>
<div>
<br /></div>
<div>
However, this requires cross-domain queries and moreover, when working in e.g. SharePoint Online, queries from https to http wich pretty much is a showstopper here. </div>
<div>
<br /></div>
<div>
At this point I was starting to be pretty frustrated. Being so close and still so far away from a working solution. Then along came <a href="http://momentjs.com/">moment.js</a>. A life saver, so to speak. Plus a very elegantly written<a href="https://www.kirupa.com/html5/create_an_analog_clock_using_the_canvas.htm"> tutorial for creating an analog clock using javascript and html5 canvas</a>.</div>
<div>
<br /></div>
<div>
Combining all this plus a little bit of jquery I finally came up with a fully SharePoint (Online) compatible world clock solution (though I actually ripped the canvas part away, as I only needed a digital time display with some additional info). So, let's do a walk through for the benefit of the next one needing to do something similar:</div>
<div>
<br /></div>
<div>
1) Download moment.js (or min) and the suitable version of moment-timezone (from the <a href="http://momentjs.com/" target="_blank">Moment </a>and <a href="http://momentjs.com/timezone/" target="_blank">Moment Timezone</a> pages). Optionally also download jquery-file to avoid any cross-domain calls.</div>
<div>
<br /></div>
<div>
2) Upload the js-files into a suitable library in SharePoint, eg. Site Assets on the site.</div>
<div>
<br /></div>
<div>
3) Create a test file for compiling all the needed code to add to the script editor web part on your page and first off, add references to the js-files in the SharePoint library.</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><script type="text/javascript" src="../SiteAssets/jquery-1.10.2.min.js"></script></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><script type="text/javascript" src="../SiteAssets/moment.min.js"></script></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><script type="text/javascript" src="../SiteAssets/moment-timezone-with-data.min.js"></script></span></div>
</div>
<div>
<br /></div>
<div>
4) Add a bit of CSS:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><style type="text/css"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">.current-time {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>display: block;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>font-weight: bold;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>text-align: center;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>width: 200px;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>padding: 10px;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">.clockcontainer {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> background-color: lightblue;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> border: 1px solid blue;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> border-radius: 5px;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> float: left;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> margin: 5px;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"></style></span></div>
</div>
<div>
<br /></div>
<div>
5) Add the javascript logic:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><script type="text/javascript"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">document.addEventListener('DOMContentLoaded', startTimer);</span></div>
<div>
</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">function startTimer() {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> setInterval(displayTime, 1000);</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> displayTime();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">} </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">function displayTime() {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">jQuery(".clockcontainer").each(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>var timezone = jQuery(this).attr("title");</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>var zonetitle = jQuery(this.firstElementChild).attr("title");</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>var now = moment().tz(timezone).format("h:mm:ss A");</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>var day = moment().tz(timezone).format("dddd MMMM DD, YYYY");</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>jQuery(this.firstElementChild).html(zonetitle + "<br/>" + day + "<br/>" + now);</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">});</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"></script></span></div>
</div>
<div>
<br /></div>
<div>
(Note the jQuery instead of $ - in SharePoint this generally works more reliably)<br />
<br />
6) Copy and paste all of the above to a Script Editor web part on the page where you are adding the world clocks, preferably somewhere close to the bottom of the page.</div>
<div>
<br /></div>
<div>
7. Add a Content Editor web part on the page where you want to display the clocks.</div>
<div>
<br /></div>
<div>
8) Edit the source of the CEWP content and add the clock elements (as many as you wish, but note the highlighted parts):</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><div class="clockcontainer" </span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">title="Europe/London"</span><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><div class="current-time" </span><span style="background-color: yellow; color: purple; font-family: "courier new" , "courier" , monospace;">title="London"</span><span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>time</div></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"></div></span></div>
</div>
<div>
<br /></div>
<div>
9) Modify each element to put out the correct time zone (title of the clockcontainer element) and the label for the clock (title of the current-time element). Check proper time zone names at the <a href="http://momentjs.com/timezone/">momentjs site</a>.</div>
<div>
<br /></div>
<div>
That should be it, folks. Now, your SharePoint page should display correct times for your chosen time zones, e.g.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLdp5MV9NRY_f7Df5Gv2X3f_EHufP0CHhNwiE5ZjmOlAIqevppkULVJik8nYKmz4JOK6yNO0s82gfH8RsV7lExgOIl8jMzXaoRNN7lqTfIDUvGwpKGtzf9k7xILazFj89K4FCIzAme84E/s1600/worldclock.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLdp5MV9NRY_f7Df5Gv2X3f_EHufP0CHhNwiE5ZjmOlAIqevppkULVJik8nYKmz4JOK6yNO0s82gfH8RsV7lExgOIl8jMzXaoRNN7lqTfIDUvGwpKGtzf9k7xILazFj89K4FCIzAme84E/s640/worldclock.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Momentjs offers plenty of options for time and date formatting. </div>
Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-8271998302803122436.post-71891444764917288462015-12-10T10:36:00.003+02:002016-02-23T15:36:12.649+02:00Tip: Targeting a specific SharePoint site with global CSSJust a little css tip, that came out handy today. Generally, with a global css (say, an alternate style sheet that is deployed throughout the site collection), you don't even attempt targeting some specific site, but go with the global styles instead. Today, however, I was struggling to display the titlerow (logo and navigation) in the enterprise search center <i>without</i> having it become visible in the dialogs as well.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Some Microsoft logic it is, I guess, that the search center by default hides the site collection navigation <i>using the same class as the dialogs</i>, the .ms-dialogHidden. And as anyone working with SharePoint CSS knows, the sites have no IDs in the body tag so that you could e.g. tell your css to display the navigation in search site but not in the dialogs. None, except for the action attribute in the form tag.</div>
<div>
<br /></div>
<div>
I guess it never was as big of an issue before, since I never thought of it before, but indeed, in a site collection already populated with sites, you can target one specific site by using the attribute selector for form tag in your css rule, for the form action contains the relative address of the site in it + in SharePoint, the whole page is always inside of that form tag. So here's the rule for un-hiding the titlerow for this specific search center, just as an example:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">form[action*="searchcenter"] #s4-titlerow.ms-dialogHidden {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> display: block !important;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">}</span></div>
</div>
<div>
<br /></div>
<div>
And, yey, the dialogs remain untouched and furthermore, there is no need to impelemnt page level css on each and every search center page.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-30387830197611116062015-11-04T12:14:00.000+02:002015-11-04T12:14:34.957+02:00Choosing between publishing and team sites for your SharePoint intranetI have noticed, that the tech oriented SharePoint architects tend to prefer team sites over publishing sites for practically any purpose. I cannot remember the reason, and frankly, during my years of building SharePoint intranets I have not come accross any real reason for this - more like on the contrary. An intranet built with team sites causes more problems than not, in most cases. Let me explain.<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Team sites have a much more dynamic usage philosophy behind them than publishing sites. Team sites are meant to be virtual team workspaces, where a bunch of people collaborate, manage documents, manage team tasks, chat etc. The content is highly dynamic, based on lists and document libraries rather than text and images on web pages. Thus, the need to edit pages is ususally quite small. The owner creates lists and libraries, sets up the workspace and the content starts to live.</div>
<div>
<br /></div>
<div>
As for the informative intranet? This is not how it works! The content is highly static - text and images on pages, maybe some centrally managed documents that are published on for the large reader audience of the pages - I say pages, for even if the intranet is built with a site hierarchy, like it most commonly is, what users see and use, are pages. </div>
<div>
<br /></div>
<div>
True, that you can do the same with team sites too. Nobody says that team sites <b>must</b> be collaboration sites. However, using team sites to build traditional intranet sites creates a series of issues <b>for the content managers and designers of the intranet</b>. Issues, that the more technically oriented architects never see, since they rarely step into the boots of the end-user.</div>
<div>
<br /></div>
<div>
Quite many times, I as the UI "guy" and the content management "guy", am called into these situations where someone, some tech person, has built the intranet for a compnay, a Site Collection created as a team site, created a hierarchy of team sites. the customer has started to build their intranet with the blocks they have been given and they run into issues.</div>
<div>
<br /></div>
<div>
1) "I made changes to this page, but they disappeared". Most of the time the publishing features have been turned on in the site collection of team sites that are meant to act as the intranet. This results in a very strange hybrid situation, where one can edit a page without checking it out, but someone can also check it out and result in loss of data. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-5ORCv1-YxNmp3iMuLe-wuojRH0Foe6JqpUvRGcjuD4OdSpmt6oABopqyd4BhQA3KbL4eM1oxfb3XbDh5aVRs5bWytcPdZgXOVVRf85VClWnsjJC4uaoMi6l-cOnBwVj5NAMblg9Xlw/s1600/pubfeature.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="70" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-5ORCv1-YxNmp3iMuLe-wuojRH0Foe6JqpUvRGcjuD4OdSpmt6oABopqyd4BhQA3KbL4eM1oxfb3XbDh5aVRs5bWytcPdZgXOVVRf85VClWnsjJC4uaoMi6l-cOnBwVj5NAMblg9Xlw/s640/pubfeature.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX0u_rop8cSoTN20r4FPgghVEFP_pjpOv4-q2p3jAaBxaMXePUurCu7cpVhW_6Vp_KJj0QO_K2T84PFs9OJ-uSnwe39zwRGRjFQrYwqql2UL4AtydfC-vQO-qDHGEMPMgZQ0d8MHa9Dmc/s1600/check.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX0u_rop8cSoTN20r4FPgghVEFP_pjpOv4-q2p3jAaBxaMXePUurCu7cpVhW_6Vp_KJj0QO_K2T84PFs9OJ-uSnwe39zwRGRjFQrYwqql2UL4AtydfC-vQO-qDHGEMPMgZQ0d8MHa9Dmc/s200/check.png" width="200" /></a></div>
<div>
<br /></div>
<div>
2) "I was trying to edit this web part, but I get this message about checking out." Even when the check out is required for the pages, the whole editing and check out is occasionally quite confusing for the content editor. In some situations, the page allows you to edit it to an extent, until it suddenly hits the editor with the "Hey, you need to check this page out first!". Again, data may get lost in the process. </div>
<div>
<br /></div>
<div>
3) "Pages or Site pages and what is the welcome page of the site?" When publishing features are activated for the site collection and for the sites in it, each site has two libraries for the site pages. The Site Pages library (originial for the team site) and the Pages library (created by the publishing feature). Now, this creates another funky situation there. </div>
<div>
<br /></div>
<div>
If indeed pages are created within sites, they may be in each different library, depending on how they were created. And they function a bit differently when editing, not to mention that the whole page architechture is different. More confusion for the content editor. The deafult page of the site can either be the Home.aspx from the Site Pages library or the default.aspx from the Pages library. You need to choose, and set the welcome page in the site settings.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Ju11uyQABCFJJFuvfoJOEFrXomJmDCsIYVxqffMCiXPtsIJqN3L6LhQljHq2ALSarF4eVz2sU7ZOn08PrOHBYvsZ2O3NStQlLyXyY6K_pE_P21vFBi6n_4ODvoVIm50OA7qI2o_V-8k/s1600/pagelibs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Ju11uyQABCFJJFuvfoJOEFrXomJmDCsIYVxqffMCiXPtsIJqN3L6LhQljHq2ALSarF4eVz2sU7ZOn08PrOHBYvsZ2O3NStQlLyXyY6K_pE_P21vFBi6n_4ODvoVIm50OA7qI2o_V-8k/s400/pagelibs.png" width="400" /></a></div>
<div>
<br /></div>
<div>
4) "But... this page layout is not consistant and we want it to be something like this [drawing]." When using simply the welcome page of each site in the intranet site collection, the issue that the HR, PR, marketing etc. department raises when getting involved with the intranet is the layout of pages. </div>
<div>
<br /></div>
<div>
True, not an issue for all companies, but a whole lot of them. There is a need to create a consistent layout for the pages and while text layout offers some options, it rarely truly fullfills the needs here. Publishing pages with the page layouts options are required. All of a sudden you find yourself creating new welcome pages as publishing pages and building them all over again with the content that already was on the home page, the wiki type page of the team site.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguj9kqN6jjI3FOZx4t5AUG8ulYYlQrVYPgc56os06pEoRtpcbzkkhzqexHweuSF3W35Wimf2hvQ4SMU0abH6SKUDnMn9m9X0UcWF1uNk_pOEhOHakJGpmbPPkuU1Hiu8F4suOFCOsP9rA/s1600/textlayouts.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguj9kqN6jjI3FOZx4t5AUG8ulYYlQrVYPgc56os06pEoRtpcbzkkhzqexHweuSF3W35Wimf2hvQ4SMU0abH6SKUDnMn9m9X0UcWF1uNk_pOEhOHakJGpmbPPkuU1Hiu8F4suOFCOsP9rA/s640/textlayouts.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
So in order to avoit these hybrid versions of sites and the confusion of the people who actually need to work with the pages and manage the content of the intranet, <b>I highly recommend creating the informative intranet hosting site collection using the publishing site template.</b> Seriously, that's why it is there! If you need blogs or wikis or even team sites within, it is all still possible. If you need calendars etc. that are not orginally part of the publishing site, the team collaboration lists feature can be activated. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhmi2z9Ark8fDl1r7VigI1zddicG7NZ26wF97FrKlzVYS-xMlYKB2DqWXYNv_Fe6hblfaYU5Hi3e-EcPuwrVUE3RR6yYy-Xm6J7HHiSRr2MLqVgFqnaUxLGR_Cwo2iXACqkfE8bVVKMAs/s1600/teamlists.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhmi2z9Ark8fDl1r7VigI1zddicG7NZ26wF97FrKlzVYS-xMlYKB2DqWXYNv_Fe6hblfaYU5Hi3e-EcPuwrVUE3RR6yYy-Xm6J7HHiSRr2MLqVgFqnaUxLGR_Cwo2iXACqkfE8bVVKMAs/s640/teamlists.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
This said, if your intranet is not a traditional informative publishing intranet but a collaborative dynamic intranet instead, or if you prefer the wiki type content management, please do use the team sites to get the most out of that scenario! There is nothing to lose and a lot to gain to actually use the most suitable SharePoint site template for each specific purpose instead of going with the idea that one glove fits all. It doesn't! All it needs is a little bit of planning and understanding the actual use case scenario of the site collection at hand.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-73477479892417177012015-10-06T10:57:00.000+03:002015-10-06T10:57:09.424+03:00Scoped search results predefined emptyMany are the things you think should be simple in SharePoint, and yet they're not. Another day, another little issue to solve. <div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
We have made this JavaScript listing of subsites inside a site collection. A site directory. For certain reasons the Content Search Web Part nor the Table of Contents was the thing. That aside, I'm not going into that more deeply here, the other thing that was needed there, was the ability to search the directory.</div>
<div>
<br /></div>
<div>
One would imagine, that it would be simple enough to add a search box to the page, and a search results web part, and then configure it to show only results for search box queries, and show nothing unless a query is made.</div>
<div>
<br /></div>
<div>
Not so much. Not a big deal either, but requires a couple of tricks.</div>
<div>
<br /></div>
<div>
First of all, you need to set the query for the results web part. In this case, there are three things to set up: </div>
<div>
<ol>
<li>The results need to be restricted to this site (or site collection, depending on where you're setting this up) only</li>
<li>The results need to be site item type only</li>
<li>The results need to be restricted instead of filtered by the search box query (as would be the default, the results web part showing a listing of all sites unless a query is made)</li>
</ol>
With all this noted, the query would look like this:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">{?{searchTerms} path:"https://YourSiteOrSiteCollectionPath" contentclass:STS_Web}</span></div>
<div>
<br /></div>
<div>
This can be either typed in, or if you need to modify the result types etc. use whatever query settings are provided. Just be sure to wrap the whole thing inside the {parentheses} with the<br /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">?{searchTerms}</span>at the very beginning of the clause.</div>
<div>
<br /></div>
<div>
In the web part properties you might want to tick off some of the settings like eg. choose to not show the adanced search link, preferences link, language dropdown etc. The setting you <b>won't</b> find there, even though the search results display template actually hints that it <b>should </b>be there, is to select "Show nothing when there are no results". The Content Search Web Part does have this setting, so I was kinda surprised.</div>
<div>
<br /></div>
<div>
This just means, that when no query has been made or it does not provide results, you will see all these suggestions and tips in the web part:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJmZBD4GLmql2Rm9TZlQG-EZfeOvgvgZSKA6U_otY4ZkBsiDIh_KCVweqqAEdiVeHLcYUax01le6LRggVlGF2fHBzHcGBawh6c4ilQQNkbbyVSM7VHOZY506vTEwcMx65Hj0PcNjhz-0/s1600/2015-10-06_10-35-18.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJmZBD4GLmql2Rm9TZlQG-EZfeOvgvgZSKA6U_otY4ZkBsiDIh_KCVweqqAEdiVeHLcYUax01le6LRggVlGF2fHBzHcGBawh6c4ilQQNkbbyVSM7VHOZY506vTEwcMx65Hj0PcNjhz-0/s320/2015-10-06_10-35-18.png" width="320" /></a></div>
<div>
<br /></div>
<div>
In order to be rid of those (or at least the suggestions), depending on what you want - in this case, the web part needed to be completely empty unless there were some search results to show - you need to modify the display template for the search results. I.e. download a copy of the default one, make the necessary changes and upload your modified one to the gallery. </div>
<div>
<br /></div>
<div>
All the display templates of a site collection are located in the Master Pages gallery, Display templates folder. Search results display template is in the Search folder. Download a copy of the original html file.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9-UYMMZcyVRV4SXTKTeG21VMoNO-qKbn-zr9bQmqy43xYfuNhD5qPXPZOSCgQVTUffP6LTzdfdlw1E9RXW6M8R5dpq9wYG766Zvtj_EZSGdeG0eCcB6A43S3LzFFkp2CR79Yq7Lala1c/s1600/2015-10-06_10-40-38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9-UYMMZcyVRV4SXTKTeG21VMoNO-qKbn-zr9bQmqy43xYfuNhD5qPXPZOSCgQVTUffP6LTzdfdlw1E9RXW6M8R5dpq9wYG766Zvtj_EZSGdeG0eCcB6A43S3LzFFkp2CR79Yq7Lala1c/s400/2015-10-06_10-40-38.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Open the downloaded file in an editor (I prefer Notepad...) and search for the div with the id of NoResult.</div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><div id="NoResult"></span></div>
<div>
<br /></div>
<div>
Inside that div you can see a bunch of JavaScript and html. If you only wish to get rid of the suggestions, delete only the <ul> element from the page, or replace it with something of your own. </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdnKvle7LseneLZGr12bnNWvCD_bIyQhca3UuDLHS3ANfRDE9tNoXV5zQoM3zZG1vIS07gRhyphenhyphenOvYEQ_xdrXoMPokfvokMgrvZ25ZiOqa3QKFW_-E-60-a37_3xGlx1Btw7ATw4AtWIevs/s1600/2015-10-06_10-44-58.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="332" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdnKvle7LseneLZGr12bnNWvCD_bIyQhca3UuDLHS3ANfRDE9tNoXV5zQoM3zZG1vIS07gRhyphenhyphenOvYEQ_xdrXoMPokfvokMgrvZ25ZiOqa3QKFW_-E-60-a37_3xGlx1Btw7ATw4AtWIevs/s400/2015-10-06_10-44-58.png" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
As it went, I wanted nothing to be shown unless there were some results, so I emptied the NoResult div completely. </div>
<div>
<br /></div>
<div>
Change the title of your template (third row of the template) and save it locally with a new name. Upload your modified template to the same Search directory of the Display templates as the original one. Don't worry about any .js files; SharePoint will generate it upon upload. </div>
<div>
<br /></div>
<div>
You most probably will need to publish your template before it can be used in the web part. When this is done, navigate back to the page with the search results web part you are setting up and open the we part properties. (Note, the page needs to be saved and reopened for editing before it can find the new display template)</div>
<div>
<br /></div>
<div>
In the Display Templates settings select your modified template.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjOZxxcHpZUIwXp1E0pJgNWaiCyjbZ7uPwgBGa0v-uB8-iFpazM6hC-CSf-zY5sBUvTV5016Zx2dX1n2Ryb_j48rwSZITJ4E7krqc_JkXt57iwgogHE9KBgl4-OxbGAsDMACbwIUFhVPw/s1600/disptemp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjOZxxcHpZUIwXp1E0pJgNWaiCyjbZ7uPwgBGa0v-uB8-iFpazM6hC-CSf-zY5sBUvTV5016Zx2dX1n2Ryb_j48rwSZITJ4E7krqc_JkXt57iwgogHE9KBgl4-OxbGAsDMACbwIUFhVPw/s1600/disptemp.png" /></a></div>
<div>
<br /></div>
<div>
Save web part properties, save (and publish) page and the search is ready.</div>
<div>
<br /></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-6855710047127910212015-09-24T16:19:00.001+03:002015-09-24T16:19:39.202+03:00Modify SharePoint List Alert to Show IDThere is a list in SharePoint, that seems to be quite overlooked. It is, however a pretty ok light weight ticketing system for a project. Yes, I'm talking about the issue list. One advantage the issue list has over a general task list is that it automatically notifies the person if he or she is set as the assignee of the issue. It used to be, that this notification email - alert - contained the issue ID both in the subject and the email body. Not anymore. <div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
One of my customers uses issue lists for project ticketing and after migrating from an older version of SharePoint they noticed that the emails no longer had this ID in them. It is quite important for them to have the ID easily available. So I set out to modify the alert templates.</div>
<div>
<br /></div>
<div>
There is no specific alert template for issue list. However, there is one for this assigned to notification email. See the <a href="https://msdn.microsoft.com/en-us/library/office/bb802738%28v=office.15%29.aspx?f=255&MSPPError=-2147217396" target="_blank">MSDN article about alert templates</a> for further reference on all of the different templates. </div>
<div>
<br /></div>
<div>
In SharePoint 2013 all alert templates are in one XML file located in the C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\XML directory on the SharePoint App server. The file you need is alerttemplates.xml.</div>
<div>
<br /></div>
<div>
As with anything located in the SharePoint root, you should not modify the original template file, but make a copy of it in the same directory and rename it, eg. alerttemplatesIssueId.xml. Then open this copy file for editing (notepad will do, VisualStudio is more colorful ;) ).</div>
<div>
<br /></div>
<div>
It is a long winded file. The AlertTemplate elements wrap each different template. Each has the template type set as value for Name attribute, e.g. <span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">Name="SPAlertTemplateType.GenericList"</span>.</div>
<div>
<br /></div>
<div>
In order to simply make the Issue ID visible in the notification email for changed "assigned to" value, find the SPAlertTemplateType.AssignedtoNotification template. Find the properties element. Remove ID from the ImmediateNotificationExcludedFields.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9-00bcsvLKvJyRlbBTXIREUxUNDupCofB-OE65KvYV5jTeG1iODft73kpQ0McqV348KWu6ZULyBh-aC30Mf9hiX6l9J9V23ZFoU4_LqluEGIW48s3OCrzXdK_3EYsd5iBfWXyje4LME/s1600/2015-09-24_15-39-21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="52" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv9-00bcsvLKvJyRlbBTXIREUxUNDupCofB-OE65KvYV5jTeG1iODft73kpQ0McqV348KWu6ZULyBh-aC30Mf9hiX6l9J9V23ZFoU4_LqluEGIW48s3OCrzXdK_3EYsd5iBfWXyje4LME/s640/2015-09-24_15-39-21.png" width="640" /></a></div>
<div>
<br /></div>
<div>
This will make the ID visible in the email body of this notification email. If you wish to have the ID visible in any alert a user subscribes to regarding the Issue list, you will need to remove the ID from the exclude fields of the properties in the GenericList template, since issue list does not have one of its own. Note, that all the other templates have two properties, the Immediate and Digest notification exclude fields.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkNIX8S7nLNBch49sZ_WcT3qczBmO5Im1RxsVmdmOEc-_zCMYEViWMWf21aYOO6F7N9bE-VB3GJ7hW3ZKA0zbuk6eq01qpQjyvLxeXg-WknhkRTqtEysijUg5i2Fd00UUPTXIdyGEcVI4/s1600/2015-09-24_16-01-42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="90" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkNIX8S7nLNBch49sZ_WcT3qczBmO5Im1RxsVmdmOEc-_zCMYEViWMWf21aYOO6F7N9bE-VB3GJ7hW3ZKA0zbuk6eq01qpQjyvLxeXg-WknhkRTqtEysijUg5i2Fd00UUPTXIdyGEcVI4/s640/2015-09-24_16-01-42.png" width="640" /></a></div>
<div>
<br /></div>
<div>
This was not enough for my customer, since they wanted to have the ID also in the email subject. This can be achieved rather easily by adding the ID field variable to the subject element. The trick, especially with the AssignedToNotification template, is to find the correct place. </div>
<div>
<br /></div>
<div>
The ID field variable itself is added as a single tag element: <GetVar Name="NewValue#ID" /></div>
<div>
<br /></div>
<div>
The place to add it to, is next to the item name or list name, eg.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiHg6WYpft2p5dWAawWU4zZh2UztWKd6OK7UgPmd6G9HJpE4TX73J43WHHDohe3ZONeLkxWTFjpYsIae6tTd0uTMMnpGd6UuUu5NLauDqngfEUC498tpw6IcJrLhTNbni9YAChD-rtb48/s1600/2015-09-24_16-08-49.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiHg6WYpft2p5dWAawWU4zZh2UztWKd6OK7UgPmd6G9HJpE4TX73J43WHHDohe3ZONeLkxWTFjpYsIae6tTd0uTMMnpGd6UuUu5NLauDqngfEUC498tpw6IcJrLhTNbni9YAChD-rtb48/s640/2015-09-24_16-08-49.png" width="640" /></a></div>
<div>
<br /></div>
<div>
In the AssignedToNotification template this is crammed between two switch elements, inside the subject element. In the GenericList template, the subject element is far more simple:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfHO2qgCz2HwRFUoeHOV9ondSIDFaQENLHNLkitTrykfslqtXt4u_XZumX3bW8ztIGkCtongQf8ETPGKl6OzHGQrBziK6foEjucW3lXIP1oH9niz0JslnmI0qDHJ1qWJiCQDLl344HUuI/s1600/2015-09-24_16-11-39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="76" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfHO2qgCz2HwRFUoeHOV9ondSIDFaQENLHNLkitTrykfslqtXt4u_XZumX3bW8ztIGkCtongQf8ETPGKl6OzHGQrBziK6foEjucW3lXIP1oH9niz0JslnmI0qDHJ1qWJiCQDLl344HUuI/s400/2015-09-24_16-11-39.png" width="400" /></a></div>
<div>
<br /></div>
<div>
This would already display the ID in the subject, but just to make it a bit more readable, you should add some HTML between the variables, eg.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCQczlBbJRFsRtdGyB1KJznyS4tT2hLeN81rtJ6yjLthyems15yvIO0lveVNsb5DbUNt7Dkj9l2tOpyRjCMvuZwixMFLtISUsVqR8ot5bTl7neH4-3FyvwOo7k0KCJA8_0Cd9CIpW9KcI/s1600/2015-09-24_16-14-02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="64" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCQczlBbJRFsRtdGyB1KJznyS4tT2hLeN81rtJ6yjLthyems15yvIO0lveVNsb5DbUNt7Dkj9l2tOpyRjCMvuZwixMFLtISUsVqR8ot5bTl7neH4-3FyvwOo7k0KCJA8_0Cd9CIpW9KcI/s320/2015-09-24_16-14-02.png" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Now, save your alert template. In order to get SharePoint to use this template, you need to run a little stsadm command. The easiest way is to open the SharePoint Management shell, run as admin, and then run the command:</div>
<div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">stsadm -o updatealerttemplates -url http://<sitecollectionUrl> -filename "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\XML\alerttemplatesIssueID.xml"</span></div>
</div>
<div>
<br /></div>
<div>
(Note, copy-paste will probably not work for the command because of the quotation marks)</div>
<div>
<br /></div>
<div>
After running this command, you need to do an iisreset, and that's it. Your templates are ready and in use!</div>
<div>
<br /></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-76990119809811204962015-09-17T17:43:00.001+03:002015-09-17T21:01:43.944+03:00Broken Blog Post Filtering in SharePoint 2013Some time last spring I created two blog sites to a customer SharePoint 2013 intranet. I set them up quite similarily, the only difference being that I added some custom fields to the other one. This should, in my logic, not affect anything in the different blog views - such as archives and category views - since I didn't touch any of the OOB fields. Whatever the reason, the end result was however, that last week the customer noticed (hmm, not very active blogging then ;) ) that on the other blog site the category and archive pages were broken. They did not filter the posts anymore as they should.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
I banged my head against the wall for a while, googled, googled some more and tried this and that. Nothing seemed to help. One workaround I tried was this most commonly mentioned solution of adding a URL filter web part and setting it up as instructed eg. <a href="http://ukreddysharepoint2010.blogspot.fi/2014/07/issue-blog-category-view-not-filtering.html" target="_blank">in this post here</a>.</div>
<div>
<br /></div>
<div>
This, however, did not work for me, or this customer site. Be it due to the language pack (Finnish site) or something else, but it did not work. So I needed something else. This is what I did:</div>
<div>
<br /></div>
<div>
1) I created a new blog in the test environment. Really it doesn't matter where, just as long as you can access it in SharePoint Designer.</div>
<div>
<br /></div>
<div>
2) I opened both the new non-broken blog site and the old broken one in SharePoint Designer. I know. I sighed deep when I realized I really needed to go that far. But unfortunately the problem seems to reside in the corrupted query of the posts web part and in order to fix that, yes, SPD is required.</div>
<div>
<br /></div>
<div>
3) The two pages that are not working properly when categories and archive are not filtering posts, are Categories.aspx and Date.aspx. These are not in the Site Pages library of the blog site; you need to dig them out from the All files directory. </div>
<div>
All files > Lists > Categories > Category.aspx</div>
<div>
All files > Lists > Posts > Date.aspx</div>
<div>
<br /></div>
<div>
Open both files on both your broken site and the new one created.</div>
<div>
<br /></div>
<div>
4) No, copying all code from one to the other will not work because of the GUIDs. As stated earlier, the broken part is the CAML query of the Posts web part. So the first thing to do is to locate the Posts web part. Since you are working in code view only, look for the main place holder with the blog-MainArea to find the correct web part.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7DJwZi9Kbutrfqkh79vQ8qlw31V-BSERjZMvG6DqMo3lhnstYl_lmnXSPh2vS0Kvbso45PyXGlrj3kO9EVjJFTlkIoYGl_6UnJrAjX8ytFAQJhrM8KkoMudhCMiRnmDZ8WUrX6mWKZgI/s1600/spd1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="435" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7DJwZi9Kbutrfqkh79vQ8qlw31V-BSERjZMvG6DqMo3lhnstYl_lmnXSPh2vS0Kvbso45PyXGlrj3kO9EVjJFTlkIoYGl_6UnJrAjX8ytFAQJhrM8KkoMudhCMiRnmDZ8WUrX6mWKZgI/s640/spd1.png" width="640" /></a></div>
<div>
<br /></div>
<div>
5) Focus on the line starting <View Name="{...</div>
<div>
<br /></div>
<div>
6) Scroll horizontally (or set your page to wrap lines) until you find the <query> tag. This begins the CAML query for the web part. On the borken page it was missing parts. So I copied the query (everything between the <query> and </query> tags) from my new site category and date pages to the broken corresponding ones, replacing the broken queries.</div>
<div>
<br /></div>
<div>
7) I saved my files and tested them. The initial refresh filtered posts nicely, but the blog navigation (the categories list and the blog archive) links were broken, for the Blog tools web part was broken. It seems that any time you open a blog page into SharePoint Designer, this web part breaks.</div>
<div>
<br /></div>
<div>
8) So, I edited both pages in the browser, deleting the broken Blog tools part and adding it back in place and yes, things started functioning again! </div>
<div>
<br /></div>
<div>
Hope this helps someone else save some time. Boy, there's never a boring day with SharePoint!</div>
<div>
<br /></div>
Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-8271998302803122436.post-13244169343876866032015-09-04T15:51:00.003+03:002015-09-04T15:54:22.409+03:00Using SharePoint Client Context JavaScript on Publishing SiteIn order to use SharePoint Client Context (SP.ClientContext) in your own custom Javascript on a pafe, you need to ensure that sp.js is loaded. This is an onDemand file, which means it is loaded only when needed, i.e. when the browser requests it. In most cases it gets loaded because of <i>something,</i> most commonly the ribbon, on the page, so it is sufficient to start your custom Javascript with<br />
<div>
<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">ExecuteOrDelayUntilScriptLoaded(CustomFunctionUsingContext, "sp.js");</span></div>
<div>
<br /></div>
<div>
On Publishing sites, however, when the page is published, ribbon is hidden and sp.js does not get loaded unless there is some other code on the page to demand it. Thus, you might need to use a bit of force to get sp.js loaded. That is, you need to demand it yourself. The function for this would be</div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">SP.SOD.executeFunc("sp.js", "SP.ClientContext", </span><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">CustomFunctionUsingContext);</span></div>
<div>
<br /></div>
<div>
or</div>
</div>
<div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">SP.SOD.executeFunc("sp.js", "SP.ClientContext", function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> YourCustomCodeHere</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">}); </span></div>
</div>
<div>
<br />
This is exactly what I was trying to use when inserting a code snippet on a Publishing page, using the Client Context to retrieve subwebs, for some odd reason the above did not do it, so I tried something that seemed totally crazy:<br />
<br />
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">SP.SOD.executeFunc("sp.js", "SP.ClientContext", function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> </span><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">ExecuteOrDelayUntilScriptLoaded(CustomFunctionUsingContext, "sp.js");</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">});</span></div>
<br />
Strangely enough it started working after that. Later on, when none of the above seemed to work on a team site, except in page edit mode, I started to wonder if the problem really was this or something within SharePoint (throttling thresholds, script not loading every time, whatnot). I am not inclined to change it anymore since <i>now it works.</i> Anyway, might be wise to add some code there to <a href="https://msdn.microsoft.com/en-us/library/office/dn889829.aspx" target="_blank">avoid being throttled or blocked by SharePoint</a>. </div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-25100332132732323772015-06-25T18:50:00.000+03:002015-11-24T12:41:23.044+02:00Open documents in Office Web Apps from CSWPOne of my customers has a Content Search Web Part in their intranet home page, listing both documents and pages. They have Office Web Apps installed and are quite happy with the way documents open to OWA instead of the desktop client from the document library and search results. The CSWP, however, does not natively support opening documents in the OWA, so a bit of display template modification is required.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
I was already using rather heavily modified item display template for the customer, so I simply needed to modify that one, but you can also copy any item display template (from the Master Pages gallery, Display Templates > Content Web Parts folder) that best fits your purposes and modify the copy. Mind you, you only copy the html template, modify it, save it with another name and upload it back to the library. The .js file will be automatically created.</div>
<div>
<br /></div>
<div>
The things you need to do to your display template in order to enable opening documents in OWA are: </div>
<div>
<br /></div>
<div>
1) Add the managed property 'ServerRedirectedURL' to the managed properties: </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-9AUhG1F5fMWwNCf-umF5UNyq7NNv9lBobkqzbfFjhpPEZRHqWLx2LWnIdfRY1ahu0z1n5ga1kU-Hre5nHNQykPj7hvJJw_wABffiWlGDIfkcHPZVVGuvwJ4FzhljS_HA2ZzGUBchU6U/s1600/managedprop.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="30" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-9AUhG1F5fMWwNCf-umF5UNyq7NNv9lBobkqzbfFjhpPEZRHqWLx2LWnIdfRY1ahu0z1n5ga1kU-Hre5nHNQykPj7hvJJw_wABffiWlGDIfkcHPZVVGuvwJ4FzhljS_HA2ZzGUBchU6U/s640/managedprop.png" width="640" /></a></div>
<div>
<br /></div>
<div>
This is the property that provides the open in OWA url for documents. You could use this as a simple property for the LinkURL, but if you cannot be certain that each and every document that gets listed in the CSWP is in fact an office document, you need to add a bit more code to the template.</div>
<div>
<br /></div>
<div>
2) Right there, where the commented code of the display template begins, below the <span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">var encodedId</span> line, insert the following code I intecepted from the common search result item template:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">var useWACUrl = !$isEmptyString(ctx.CurrentItem.ServerRedirectedURL);</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if(ctx.ScriptApplicationManager && ctx.ScriptApplicationManager.states){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> useWACUrl = (useWACUrl && !ctx.ScriptApplicationManager.states.openDocumentsInClient);</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> var appAttribs = "";</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if(!useWACUrl)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if (!$isEmptyString(ctx.CurrentItem.csr_OpenApp)) { appAttribs += "openApp=\"" + $htmlEncode(ctx.CurrentItem.csr_OpenApp) + "\"" }; </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if (!$isEmptyString(ctx.CurrentItem.csr_OpenControl)) { appAttribs += " openControl=\"" + $htmlEncode(ctx.CurrentItem.csr_OpenControl) + "\"" };</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> var url = ctx.CurrentItem.csr_Path;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if($isEmptyString(url)){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if(useWACUrl)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> url = ctx.CurrentItem.ServerRedirectedURL;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> } else {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> url = ctx.CurrentItem.Path;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> } </span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
3) Then modify the LinkURL variable to use the url instead of the default Path:</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">var linkURL = $urlHtmlEncode(url);</span></div>
<div>
<br />
4) Finally, remove the line<br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">linkURL.overrideValueRenderer($urlHtmlEncodeValueObject);</span><br />
<div>
<br /></div>
</div>
<div>
And that's it, folks.</div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8271998302803122436.post-74934392025053161812015-02-18T15:09:00.001+02:002015-03-04T10:53:31.630+02:00Calculated string field in Content Search Web PartOne of my customers had a need. They have an intranet site collection and another one for team sites. One of the team sites contains a list from which they wanted to show five newest entries on the intranet front page. Since both site collections are indexed in search, no problem, we simply used a Content Search Web Part for it. Re-indexed the list columns and created properties in the search schema for the columns they wanted to show in the CEWP.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
One of these columns was a calculated field, that combined the name information into a neat display column of [Lastname, Firstname] string. It was quite a surprise when the CEWP showed this information with an additional <b>string;#</b> resulting in a list such as this:<br />
<ul>
<li>string;#Connor, June</li>
<li>string;#Mickowich, Mark</li>
<li>string;#Somebody, Else</li>
</ul>
You get the drift. I started to google, of course, landing several references to this behavior. The workarounds consisted mainly of two propositions: do not use a calculated field but rather a workflow, or, more specificly addressing this CSWP issue, make your own display template and fix the Javascript responsible for this starngeness. I wanted to do neither.</div>
<div>
<br /></div>
<div>
There is a very simple solution, done right there in the client side, on the page. What I did was insert a Script Editor Web part on the page underneath of the CSWP and in that editor, I added this simple piece of script: </div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><script type="text/javascript"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">$(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">$("h2.cbs-picture3LinesLine1").each(function(){$(this).text($(this).text().replace("string;#", ""))});</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">});</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"></script></span></div>
</div>
<div>
<br /></div>
<div>
Element h2.cbs-picture3LinesLine1 was the one containing the name with extra string in front of it. This Javascript insert simply replaces that extra string with nothingness. Mind you, this uses jQuery, so be sure to have the jQuery available, referred to on the page one way or the other; this site already had it in the MasterPage.</div>
<div>
<br />
[<b><i>Edit Feb 27th, 2015</i></b><br />
If SharePoint has MDS (Minimal Download Strategy) enabled, many JavaScript functions will not fire upon page refresh. To solve this issue, use the ExecuteOrDelayUntilBodyLoaded(function() in order to call your function after page refresh too, eg.<br />
<br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">function cleanstring(){</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">$("h2.cbs-picture3LinesLine1").each(function(){$(this).text($(this).text().replace("string;#", " "))});</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">}</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">ExecuteOrDelayUntilBodyLoaded(function() {</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> RegisterModuleInit('/mySite/SiteAssets/testModule.js', cleanstring);</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> cleanstring();</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">});</span></div>
<div>
<br /></div>
<div>
If your script is located in a custom MasterPage or PageLayout, you can use the SharePoint ScriptBlock element which is run on the server, instead of the Script-element. This, however, does not work if your script is added to a page using the Script editor web part or editing page source code.</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><SharePoint:ScriptBlock runat="server" ></span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">$(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">$("h2.cbs-picture3LinesLine1").each(function(){$(this).text($(this).text().replace("string;#", ""))});</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">});</span></div>
</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"></SharePoint:ScriptBlock></span></div>
</div>
<div>
<br />
Also, on a publishing page, where MDS was not the issue, the problem was solved by using<br />
<br /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">$(window).load(function(){</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">...</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">}</span><br />
<br />
whereas $(document)ready() did not do the trick.]</div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-73741745265007346412014-09-03T15:37:00.000+03:002014-09-03T15:42:41.087+03:00Using a Custom Logo in HTML MasterPagesThe Eureka-moment of the day. I admit that I have mostly avoided this whole issue after the intial notion that it just did not work - mostly because I have avoided working with HTML MasterPages alltogether since I don't really like them; I'm much more at home working with the actual .master file (and mind you! it can also be used in a Design Package - that is, creating a Design Package does not mean that you <i>need</i> to use HTML Master Pages; rather, they are an option).<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Today I was working with new labs for my Branding trainings and finally decided to take the bull by the horn and try my luck again at figuring out the proper way to actually get your own logo as default logo in the Site Logo snippet. And I did figure it out. It's really nothing new; I just hadn't thought about it this way before. </div>
<div>
<br /></div>
<div>
If I create a VisualStudio Branding solution, I prefer the 15-hive over placing the files in _catalogs/masterpage. But as it goes, this is not avoidable in all situations, so I, too, have made solutions with all the assets in the MasterPage gallery. So today I gave this logo issue some more thorough thought and got it. The link in the snippet properties needs to be in the same form as it would in my own MasterPage, when the logo is located in _catalogs/masterpage.</div>
<div>
<br /></div>
<div>
In essence: for an HTML MasterPage, store your assets (logos, css stylesheets etc.) in your own folder in _catalogs/masterpage to ensure that they are packaged with the Design Package. When you use the logo in the Site Logo snippet, set the SiteLogoImage url in the following form:<br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">&#60;% $SPUrl:~sitecollection/_catalogs/masterpage/designpackagefiles/dp_logo.gif %&#62;</span></div>
<div>
(or <span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><% $SPUrl:~sitecollection/_catalogs/masterpage/designpackagefiles/dp_logo.gif %></span>)</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtruIuSj26xf_TWMaSNmrkpNP6W4ljThbaVVqxMQimom0g_rxhxBdjbN46pLwJM4-UJNWqMSQkvNc5czmaIzkKc-ifwravsk8tVHgvALCEWPFqBwc2L2ylsh9aRH3_7BydqPd-inneZ-0/s1600/logoimgurl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtruIuSj26xf_TWMaSNmrkpNP6W4ljThbaVVqxMQimom0g_rxhxBdjbN46pLwJM4-UJNWqMSQkvNc5czmaIzkKc-ifwravsk8tVHgvALCEWPFqBwc2L2ylsh9aRH3_7BydqPd-inneZ-0/s1600/logoimgurl.png" height="270" width="400" /></a></div>
<div>
<br /></div>
<div>
As for the CSS file link, that is much more straightforward. The href url can simply be of the form folder-in-catalogs-masterpage/stylesheetname.css, e.g.<br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><link rel="stylesheet" type="text/css" href="designpackagefiles/DesignPkgStyles.css"></span><br />
<br />
Note, that the CSS link needs to be outside of all the MS-commented sections; the safe place for it is right before the closing </head> tag!</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-80595332315246989002014-04-17T12:52:00.000+03:002014-04-17T12:52:30.681+03:00Tip: Page Layout Content Type Language ResourceJust a short note. I have been using the Page Layout string as the ContentType value for page layouts in the Elements.xml manifest, when creating new page layouts within a UI package Quite many of my customers, however, prefer their sites in Finnish. The Finnish equivalent is "Sivun asettelu" and usually this works fine, but not always. The better practice however (and a must in a multilingual environment) is to use the resource-string as the value for ContentType:<br />
<div>
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><Property Name="ContentType" Value="$Resources:cmscore,contenttype_pagelayout_name;" /></span></div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-64918430476741625732014-03-20T17:13:00.000+02:002014-03-20T17:13:48.349+02:00Using SlickNav with SharePointResponsive design in the word of the day, and recently full responsiveness has become more and more required in intranets too, and not only in Internet sites. This led me to trying out the <a href="http://slicknav.com/" target="_blank">SlickNav </a>with a SharePoint site of a customer, and was happily surprised, when everything mostly went in a truly slick manner! Anyone working with SharePoint will, however know, that slick with SharePoint has a whole different meaning than slick in a simple HTML+CSS web site. So a few notes from my journey with SlickNav.<div>
<ul>
<li>For basic implementation it really is enough to download the SlickNav package from the web site, and follow the general instructions of usage.</li>
<li>Include the jquery.slicknav.js and slicknav.css files in your project, as instructed.</li>
<li>Remember to refer jQuery in your MasterPage along with the SlickNav files.</li>
<li>As for SharePoint, if using the OOB menus, there obviously is no ul with the id of "menu"; instead you can use "div.ms-core-listMenu-horizontalBox > ul.root" for the element selector and it works like a dream.</li>
<li>Remember to set the prependTo property for the initializing function, e.g.<br /><span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">prependTo: '#mainnav'</span></li>
<li>I also found it useful to set the allowParentLinks property to 'true', so users can clikc on the parent links in a similar way as the regular SharePoint navigation</li>
<li>If you are using dynamic nodes in SharePoint navigation, you need to set the styles for <br /><span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">.slicknav_open ul.dynamic {<br /> top:0;<br /> left:0; }</span><br />in order to show the dynamic navigation; otherwise it is still hidden somewhere at left:9999px etc.</li>
<li>The dropdown tends to fall behind the page content, so set the styles for<br /><span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">.slicknav_nav, .slicknav_nav ul {<br /> position: relative;<br /> z-index: 100; }</span></li>
<li>A varying amount of other css tweaking is needed to make it neat in SharePoint.</li>
</ul>
Still, I wouldn't say it was a really big issue to get the SlickNav up and working and even stylized nicely for the customer.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76MbjiEg-Do9gjoNY1Y6Qq1uJ9bHF05sfe-fbgxl2Gsd4s3H6JFONlp2EI7WeduORSNRt_CxueSn5vnif82DlF_FyAPIL5JSWUJOxCZnIzhBMdxKGPRfq0Qwl9oErpllB5bbDJXCoMpQ/s1600/slickmenu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh76MbjiEg-Do9gjoNY1Y6Qq1uJ9bHF05sfe-fbgxl2Gsd4s3H6JFONlp2EI7WeduORSNRt_CxueSn5vnif82DlF_FyAPIL5JSWUJOxCZnIzhBMdxKGPRfq0Qwl9oErpllB5bbDJXCoMpQ/s1600/slickmenu.png" height="285" width="320" /></a></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-30787830806309521012014-03-19T11:55:00.000+02:002014-03-19T11:57:24.560+02:00Discard AppWebs When Setting Custom MasterPagesI have long used a <a href="http://borderingdotnet.blogspot.fi/2012/01/setting-masterpages-to-sites.html" target="_blank">feature event receiver to set MasterPages throughout the webs</a> (i.e. sites) in a site collection when my branding feature is activated, and also an inheritance event receiver to set the MasterPage for any new web when it has been provisioned. In SharePoint 2010, search sites required a different MasterPage than the rest of the sites, so in the code of the receivers, this was always taken into consideration, as you can see in the article linked above. In 2013, this is unnecessary as the same MasterPage goes for all sites, so I have used the simplified version of the receiver code, with no webtemplateid checks.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Or, so I thought. Turned out, my testing had been lacking, since I do not use apps in my development&test environment, and thus it had not occured to me, that the app webs (which I sort of assumed to be separate, but apparently are not) respond to these event receivers too. As tests proved, my receivers actually "broke the SharePoint" when appwebs were involved. So, a little improvement to both receivers here, checking that a web is not an appweb (APP#0, WebTemplateId == 17) before making any MasterPage changes:</div>
<div>
<br /></div>
<div>
<b>Feature event receiver, activate feature:</b></div>
<div>
<b><br /></b></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">SPSite site = properties.Feature.Parent as SPSite;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> if (site != null)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> SPWeb topLevelSite = site.RootWeb;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> string WebAppRelativePath = topLevelSite.ServerRelativeUrl;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> if (!WebAppRelativePath.EndsWith("/"))</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> WebAppRelativePath += "/";</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> foreach (SPWeb web in site.AllWebs)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> if (web.WebTemplateId != 17)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> web.MasterUrl = WebAppRelativePath + "_catalogs/masterpage/mycustommaster.2013.masterpage.master";</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> web.CustomMasterUrl = WebAppRelativePath + "_catalogs/masterpage/mycustommaster.2013.masterpage.master";</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> web.Update();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
<b>Event receiver, web provisioned:</b></div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">SPWeb newWeb = properties.Web;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> SPWeb topSite = newWeb.Site.RootWeb;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> if (newWeb.WebTemplateId != 17)</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> newWeb.MasterUrl = topSite.MasterUrl;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> newWeb.CustomMasterUrl = topSite.CustomMasterUrl;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> newWeb.Update();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
</div>
<div>
<br /></div>
<div>
For the sake of consistency, I also fixed the deactivate feature code to leave the appwebs alone.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-19621844372364555592013-10-15T10:55:00.001+03:002013-10-15T10:55:11.664+03:00Using Dynamic Navigation to Create a Static Subnavigation with a Little Bit of CSS and no JavaScriptSometimes I tend to think too complicated. Working with a couple SharePoint navigation customizations involving e.g. a megamenu implementation (btw. I found <a href="http://www.myfatblog.co.uk/index.php/2013/03/how-to-achieve-a-mega-menu-using-out-of-the-box-navigation-in-sharepoint-2013-and-jquery/" target="_blank">this blog post</a> highly helpful with that!), I was trying to accomplish something quite simple with a load of jQuery. Most certainly, that would have worked fine too, but when I, for a fleeting moment, wondered why it <i>didn't </i>(eh, I was still missing the jQuery reference), I realized I really did not need it at all.<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
In this particular case, I needed a two-level navigation, even though there was no real hierarchy, since everything was decidedly in one single team workspace. Yet, there was a logical hierarchy that had to be shown in the left hand side navigation. So, what I did after my futile jQuery excursion, was</div>
<div>
<ol>
<li>to create a hierarchical managed navigation, with the terms pointing to pages that otherwise would have been a flat list in the navigation. </li>
<li>to use the global navigation in place of the QuickLaunch as the left hand side navigation (in this case, it works much better)</li>
<li>changed the navigation parameters to orientation: horizontal, static display levels: 1, maximum dynamic display levels: 1</li>
<li>picked out the two CSS classes that make the dynamic navigation appear and dispappear:<br /><b>li.hover</b> (<i>hover</i> being the class that SharePoint adds to the li.static.dynamic children on hover action)<br />and <b>li.hover-off </b>(<i>hover-off </i>being the class that SharePoint adds to the mouseout action)</li>
<li>using the classes above, I set the dynamic navigation to never appear as a dynamic submenu:<br /><br /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">li.hover ul.dynamic, li.hover-off ul.dynamic {</span><br style="color: purple; font-family: 'Courier New', Courier, monospace;" /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;"> display:none !important;</span><br style="color: purple; font-family: 'Courier New', Courier, monospace;" /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;"> left: -9999px !important;</span><br style="color: purple; font-family: 'Courier New', Courier, monospace;" /><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">}<br /></span></li>
<li>then I set the dynamic menu of the selected static parent item to be displayed right below the parent item link:</li>
</ol>
<div>
<blockquote class="tr_bq">
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">li.selected ul.dynamic, li.selected.hover ul.dynamic, li.selected.hover-off ul.dynamic {<br /> border: medium none;<br /> box-shadow: none;<br /> color: #000000;<br /> display: block !important;<br /> left: 0 !important;<br /> padding: 0;<br /> position: relative !important;<br /> top: 0 !important;<br />}</span></blockquote>
</div>
<div>
<br /></div>
<div>
With a little bit of other CSS modifications to the navigation items (for styling purposes), the menu then looked and behaved like this:</div>
</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp4h9ASO21Yu5ltFjQci6scEHRKjeYytn09rvzo3PMTzB1CQtv7xMZgYfct8DVpNOjUakKsA_jtypqaRMTmt4qSqMacbpHqNrp3zwy89EHIvmzbeoLBrGGfPzDz2nc87cbR2oK2sGdJIA/s1600/navigation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp4h9ASO21Yu5ltFjQci6scEHRKjeYytn09rvzo3PMTzB1CQtv7xMZgYfct8DVpNOjUakKsA_jtypqaRMTmt4qSqMacbpHqNrp3zwy89EHIvmzbeoLBrGGfPzDz2nc87cbR2oK2sGdJIA/s640/navigation.png" width="640" /></a></div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-63784234262070784542013-09-27T13:24:00.000+03:002013-09-27T13:40:45.857+03:00Inbuilt IE8 hack for SharePoint 2013Doing yet another UI branding for a customer, and especially the optimzation for each and any Internet Explorer version from 8 on, I stumbled upon something quite interesting and useful too.<br />
<div>
<br /></div>
<div>
I mostly prefer the CSS rule hacks (e.g. using /9 for IE8) over comments and separate stylesheets and/or classes (read more about the options in <a href="http://webdesignerwall.com/tutorials/css-specific-for-internet-explorer" target="_blank">Web Designer Wall</a>), and try to come up with the most browser-generic solutions as possible. But IE8 is a problem child, that's for sure (fortunately, with SP2013 we don't need to deal with IE7 anymore!). </div>
<div>
<br /></div>
<div>
The SharePoint team has obviously noted this too. So what I discovered today, when changing the color of the left side of the suite bar (id="suiteBarLeft") is this general class <i><b>ms-core-needIEFilter</b></i> that gets inserted to the page by some SharePoint JavaScript when the browser mode is Internet Explorer 8.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
</div>
<div>
<br /></div>
<div>
For example, this suiteBarLeft just happens to get an IE8 fix for its background, resulting in my custom background color not taking effect. And !important does not do the trick, for the overriding CSS rule is actually a filter rule, not background(-color) rule - which is there too, actually, set to transparent, so the complete fix for the suiteBar backgrouns customization is</div>
<div>
<br /></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">.ms-core-needIEFilter #suiteBarLeft {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> filter:none;</span><br />
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> </span><span style="background-color: #f3f3f3; color: purple; font-family: 'Courier New', Courier, monospace;">background-color: #92D050;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">}</span></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhELq1iKK-HpA7Z5LbIhY4pPXrhVJw31VQfrY_SdjRUPRUo7iahIyoc8KCIRVxr2nNzwBRrcvb6NrgotVc_3uLswqgxX2GthCRah2Cswbgl45s4D5nd0huSff2tH5Z3jOETZgqWpqLx_rI/s1600/suitebar.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="62" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhELq1iKK-HpA7Z5LbIhY4pPXrhVJw31VQfrY_SdjRUPRUo7iahIyoc8KCIRVxr2nNzwBRrcvb6NrgotVc_3uLswqgxX2GthCRah2Cswbgl45s4D5nd0huSff2tH5Z3jOETZgqWpqLx_rI/s640/suitebar.PNG" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
As stated, this class <i><b>ms-core-needIEFilter</b></i> exists globally (somewhere - I could not place the class in the DOM tree) on the SharePoint pages when browser is IE8, and thus is quite useful for <i>any </i>IE8 hacks that are needed in any custom UI. I tried out a few, and it works like a dream :)</div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-8271998302803122436.post-49981240627874271712013-09-18T15:20:00.000+03:002013-09-23T11:56:36.697+03:00Changing Site Logo URL with Client Side ScriptIn SharePoint, the site logo URL is set in the master page as the NavigateUrl attribute for the SPLinkButton control, usually with the value of either ~site or ~sitecollection, e.g:<br />
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><SharePoint:SPLinkButton runat="server" NavigateUrl="~sitecollection/"></span></div>
<div>
<br /></div>
<div>
Most of the time this either is what we want, or can be changed in a custom master. </div>
<div>
<br /></div>
<div>
Lately, though, I have been working on a project where the company intranet is split in two: there is one instance for general intranet, and another one for a special purpose. Both instaces use the same master pages, and the only UI customizations I have been making for the special site collection (in its own web app, not that it matters) are some special page layouts and CSS files - and a bit of JavaScript.</div>
<div>
<br /></div>
<div>
The incentive is to integrate the special site collection to the general intranet as seamlessly as possible, i.e. in a way that the average user wouldn't need to even notice that they actually navigate from one site collection to another and back. One task was to add an intranet root node to the breadcrumb trail, which did not cause too big of a headache, but the other task, changing the URL for the site logo link was not as straight forward as one would have expected.</div>
<div>
<br /></div>
<div>
The problem was created by the SharePoint control adding (invisible) empty text nodes inside the parent div. So while the <a> element <i>seemed </i>to be the firstChild of the div, this was not actually correct. Inspecting the dom tree of the div in Chrome dev console, I found this:<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiU3gDxHP16SVj4F10JXtRlL12mE_Va__Mq-ZFJ54sTQH0m6UqXvUTbWd8tXGNFp9h_GOzdBb3hFKQ6oPmXrodnD1mX78_nBI4LJcghafaNV_8mZ235ITt87dfwvcjymc9iYPlS4AOL0k/s1600/dom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiU3gDxHP16SVj4F10JXtRlL12mE_Va__Mq-ZFJ54sTQH0m6UqXvUTbWd8tXGNFp9h_GOzdBb3hFKQ6oPmXrodnD1mX78_nBI4LJcghafaNV_8mZ235ITt87dfwvcjymc9iYPlS4AOL0k/s640/dom.png" width="640" /></a></div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
<div>
firstChild was trying to change attribute for the text node [0] and childNodes[1] returned empty object for whatever reason, so finally, the problem was solved rather simply by using children[0]:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;">window.onload = function setLogoUrl() {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> var logolink = document.getElementById('DeltaSiteLogo').children[0];</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> logolink.setAttribute('href', 'http://intranet.mothership');</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> }</span></div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-8271998302803122436.post-86415510698558416042013-05-14T16:01:00.000+03:002013-05-21T15:58:37.311+03:00Content Query Web Part Breaks Page Layout in SP2013Content Search Web Part replaces Content Query Web Parts in SharePoint 2013 on many occasions. This probably is the reason why it has taken this long for me to discover this rather annoying SharePoint bug: Content Query Web Part breaks a page layout built with div-elements, because the default web part (or the XSLTs?) seems to miss a </div> closing tag!<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Everything is ok in edit mode, for what ever additional wrapper reasons:</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRVHGyHBF8cArPucuY07qmPk-C4sGhzYnJR2zRmPI9cxEYdI13M4AD7OxRglm_Gv6pNuRTp3j1_waAT8Zd_G9CLfPBN1warjhGeOCjeTHXaTv87TbLuqRtUETHESWEiXVySKoMQV8lPoA/s1600/cqwpok.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRVHGyHBF8cArPucuY07qmPk-C4sGhzYnJR2zRmPI9cxEYdI13M4AD7OxRglm_Gv6pNuRTp3j1_waAT8Zd_G9CLfPBN1warjhGeOCjeTHXaTv87TbLuqRtUETHESWEiXVySKoMQV8lPoA/s640/cqwpok.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
but when I click my way out of edit mode, the page breaks:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_rDTkcxamm2LKvULFczkekpqOXLEP7m6doEJZCoYB4Ncj-soCLXn7UsYMtjGy-rrKN_0pOdAOs9Ys8eaf0FnPzcneKvSIVGuUH2g-CiHfZejvOvJGKzm9K4FYLygRpTPt7vwqOg8jxg/s1600/cqwpbr.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="244" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_rDTkcxamm2LKvULFczkekpqOXLEP7m6doEJZCoYB4Ncj-soCLXn7UsYMtjGy-rrKN_0pOdAOs9Ys8eaf0FnPzcneKvSIVGuUH2g-CiHfZejvOvJGKzm9K4FYLygRpTPt7vwqOg8jxg/s640/cqwpbr.png" width="640" /></a></div>
<div>
<br /></div>
<div>
In FireBug, I added a </div> tag to the page's source code (which is perfectly ok when no CQWP is added to the page) and this fixes the problem:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3JU0pX52ZhCntjQ4ThC2AW9OmOoTe771XoJCrjRVAwTusF2BFNXVKswdZRa_Zv9uND0fqASmwQXJi4uFiKA02riuiGMD2C8goW3JArjtA7nRI6pRoP9mnKsIZW799k_WMlj9Df1dyx-g/s1600/addeddiv.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3JU0pX52ZhCntjQ4ThC2AW9OmOoTe771XoJCrjRVAwTusF2BFNXVKswdZRa_Zv9uND0fqASmwQXJi4uFiKA02riuiGMD2C8goW3JArjtA7nRI6pRoP9mnKsIZW799k_WMlj9Df1dyx-g/s640/addeddiv.png" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
In real life, this obviously won't do. So as a workaround, I added a table element to the Page Layout code, inside the div-elements as a wrapper for the web part zones: </div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"><div id="rightcolumn"></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> <b> <table width="100%"><tr><td></b></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> <div class="ms-webpart-zone ms-fullWidth"></span></div>
</div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> ...</span></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> </div></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"> <b></td></tr></table></b></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: Courier New, Courier, monospace;"></div></span></div>
</div>
<div>
<br /></div>
<div>
Not an especially pretty insert, but the easiest fix I came up with for now.</div>
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-8271998302803122436.post-39998644800643013672013-04-03T15:42:00.000+03:002016-03-07T10:37:43.432+02:00Accordion "Left Navigation" (Quick Launch) for SharePoint 2013[<i><b>Edit 7.3.2016</b></i>: Since posting this, a lot has changed both in the browser and SharePoint world. This still works, at least in IE, but there have been a whole lot of issues with it. Thus I would urge you to consider <a href="http://yakovenkomax.com/converting-sharepoint-2013-quick-launch-to-accordion-menu/" target="_blank">the solution by MaxYakovenko</a> instead of implementing this one (I am not attempting to solve the issues of this one anymore).]<br />
<br />
One of my customers is working on their new SharePoint 2013 intranet site. They needed the Current Navigation (Foundation: Quick Lauch) to be an accordion. We tried a couple different jQuery code bits, but whereas they used to work in SharePoint 2010, in 2013 they only flashed the subnavigation instead of leaving it open.<br />
<div style="font-face: tahoma; font-size: 10pt;">
</div>
<div>
<br /></div>
<div>
Googling for one that would work with SharePoint 2013, I found a code snippet in <a href="http://joao-pinho.blogspot.de/2012/11/sharepoint-2013-accordion-quicklaunch.html">http://joao-pinho.blogspot.de/2012/11/sharepoint-2013-accordion-quicklaunch.html</a>, but it did not do everything as intended (s.o. the links did not function anymore as the click was completely captured by jQuery). So, with a couple modifications:</div>
<div>
<br /></div>
<div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">$(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*set dynamic css logic*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if($('#sideNavBox .menu-item.selected').length){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> //propagates the selected class, up the three.</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $('li.static').removeClass('selected');</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $('#sideNavBox .menu-item.selected').parents('li.static').addClass('selected');</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> //collapses top siblings of selected branch</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $('#sideNavBox .menu-item.selected').parents('li.static').last().siblings()</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> .find('> ul').hide();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> else $('#sideNavBox .root.static > li.static > ul').hide();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*set accordion effect*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $('#sideNavBox .root.static > li.static').each(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if($(this).find('ul').length){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $(this).addClass('father').click(function(){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> if($(this).children('ul').css('display') != 'none'){</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $(this).removeClass('selected').children('ul').slideUp();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> else {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*collapse-siblings*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $(this).siblings().removeClass('selected').children('ul').slideUp();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*expand*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $(this).addClass('selected').children('ul').slideDown();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*added: stop event propagation to link nodes*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> $('a.static').click(function(event) {</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> event.stopPropagation();</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> });</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> /*added*/</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> return false;</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> });</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> }</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;"> });</span></div>
<div>
<span style="background-color: #f3f3f3; color: purple; font-family: "courier new" , "courier" , monospace;">});</span></div>
</div>
<div>
<br /></div>
<div>
This piece of code assumes that the SharePoint navigation levels in the MasterPage are set to <b>3 static ones and no dynamic levels</b>, the SiteMapProvider is <b>CurrentNavigation</b>, and the navigation settings in the sites are set to:</div>
<div>
<br /></div>
<div>
- SITE WHOSE CHILDREN FORM THE ACCORDION: <i>Structural Navigation: Display only the navigation items below the current site, Show subsites</i></div>
<div>
<i><br /></i></div>
<div>
- ACCORDION HEADING LEVEL SITES (PARENTS): <i>Structural Navigation: Display the current site, the navigation items below the current site, and the current site's siblings, Show subsites</i><br />
<i><br /></i>
- ACCORDION SUB LEVEL SITES (CHILDREN): <i> Display the same navigation items as the parent site</i></div>
Unknownnoreply@blogger.com35