Vue normale

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
À partir d’avant-hierSharePoint

Communiquez avec vos Groupes Office 365 grâce aux WebHooks

Bonjour, Microsoft a annoncé lors d’ Ignite 2016 la montée en puissance de la fonctionnalité Groupes dans Office 365. Les WebHooks sont des appels HTTP POST pour prévenir de l’apparition d’un événement quelque part. C’est d’ailleurs la technologie mère qui soutient tous les connecteurs des Groupes Office 365, lisez les lignes suivantes, vous allez comprendre pourquoi. Quel […]

webhooks

thierrybuisson

webhooks

sans-titre

snip_20161013143818

snip_20161013144442

snip_20161013145021

sans-titre001

snip_20161018140636

snip_20161018121826

snip_20161018155609

Injecting JavaScript in a SharePoint Online site collection the proper way

With recent changes in Office 365 branding guidelines, it has become significantly more difficult to insert small bits and pieces of functionality like a 10-line JavaScript, for example. I had to do this in order to bring the same global navigatoin that we use in our main site collection into the Search Center site collection (the requirement is even more difficult if you use Managed Navigation, but that's not the topic of this post).

By default, the navigation is missing from the Search Center in SPO and SharePoint 2013.
A great way to get it back is described in this post by MVP Elio Struyf. But how would you inject the JS in the whole site collection? By default, we have 7 different result pages in this site, and we plan to create more... so here are our options:

1) Insert the script in a CEWP or a Script Editor webpart - manually in each of the pages... time consuming and the need for manual adjustments arises each time you create a new results page.

2) Use custom master page for the site collection - a big No-No for SharePoint Online since a few months.

3) Build a provider-hosted app that can inject your customization :) Great video by the Office 365 PnP team, but it sounds to me like killing the fly with a hammer! 

4) Register it through another .js and forget about supportability and removal with no code... Quick & Dirty approach by Tim Ferro that I'd only ever use as a PoC.. (tested it and does the job by the way).

5) Using PowerShell! Wait, what!? Yep. After some head-banging last Friday afternoon, my friend and PowerShell guru Ivan Yankulov has reminded me that there was a pretty good cmdlet from the PnP-PowerShell project

All you need to do is... 

1) Download the project locally
2) Have WiX toolset installed (at least 3.10 if you use VS2015)
3) (Optional) Have Windows Management Framework 4.0 installed if you want to generate the cmdlet Help
4) Install the binaries (\Binaries\PnPPowerShellCommands16.msi) for SharePoint Online
5) Run PowerShell 3.0 as an admin...
6) Have a look at the AddSPOJavaScriptLink documentation.
7) Connect to your SPOnline tenant (Connect-SPOnline –Url https://yoursite.sharepoint.com –Credentials (Get-Credential)
8) Execute the command...

Let's assume I want to inject something called elementshide.js to my whole site collection. So whenever someone creates a site or a page inside, they'll get the JavaScript loaded automatically for consistent site collection-wide user experience. The key parameter is like an identifier for your script  - take a note of this if you want to remove the script reference later on :) The url is basically the path to the script (relative URL is always recommended) and then the scope could be Site for a site collection, or web for a subsite in SharePoint Online. 

 Add-SPOJavaScriptLink -key ElementsHide -url "~sitecollection/SiteAssets/elementshide.js" -Scope Site -Web https://dimitarm.sharepoint.com

9) Verify. Go to your page and view the source code... you'll have the following piece if the injection went through:

if (scriptsSrc.indexOf('/SiteAssets/elementshide.js') === -1) {
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = '/SiteAssets/elementshide.js'; 
headID.appendChild(newScript);
scriptsSrc.push('/SiteAssets/elementshide.js');
}(function(){ 


So this is it... in a little bit less than 10 steps we've managed to make our Search Center navigation show up...and we're ready for a lot more customization done this way. Hopefully the guidelines by the O365 team do not change to something even more complicated in the next months...

Collapsible Current Navigation in SharePoint...and my new job

Big news in the beginning of this week. No, I'm not back to school :) I recently accepted a new job as an internal SharePoin employee for a company which is not yet an enterprise, but not a startup either. It will be very different than all of my past experience at service providers and consultancy engagements, but I am excited as it's a very innovative organization and we met when it's just about time for some SharePoint(ing).

Now to the point... one of my first tasks is to create the organization's navigation structure for an Intranet portal. We will use Managed Navigation after an evaluation and demos of all the possible methods. I will do this on SharePoint Online for the example, but the method is the same for SharePoint 2013 as well.

The decision to use Managed Navigation is not the scope of this post, a very good comparison by Microsoft is published here, which evaluates performance, needs and in fact all pros and cons.

One of the main requirements is for the Current Navigation to become collapsible, imagine a Windows Explorer style...like the following example. Now, if you have users that will be switching from file shares to SharePoint, that type of navigation might come handy. I personally don't really like the fact that it does go very big when you expand a lot of nodes, but there's a solution for that.

If the SharePoint site structure becomes deeply nested e.g. Site Collection -> Site -> Site -> Site ... this will also be a pain to navigate in, and most users would most likely prefer the Search option (I got this feedback after conducting a few user interviews and demoing this type of navigation).



Let's review the options to achieve the closest functionality in the SharePoint Current Navigation.
We assume we'll only have one site collection, which is nowadays common for small to medium sized organizations. Especially if you go the SharePoint Online route.

Option 1: Tree View

The way to enable this is simply going to Site Settings -> Tree View -> Enable Tree View.



The Tree View looks like this in a site collection (left) and respectively in a site (right):


Now, I'll share my view, based on experience around this functionality.

Pros:

- Sites are automatically added, no admin overhead
- OOB solution. No custom master page need, hence sticking to the Office 365 best practices.
- Displays lists and libraries in addition to the sites
- Easy to use, nice icons on the left, indicating the type of each node - that's all OOB again.

Cons:

- NOT security trimmed!
- Displays the Apps (add-ins) as well, no way to hide those. The regular user might not need them.
- Can take a large part of your screen and becomes unusable if you need too much scrolling
- Enabled per site level only, e.g. you need to save your site as a template and create new sites based on that if you need Tree View enabled by default
- NOT consistent accross sites. E.g. does not show the parent navigation when you're in subsites. 
- NO way to customize it OOB, needs custom CSS (not a big deal, you still don't need to modify the master page for that and the OOB view might suit you just fine in some scenarios.)


Option 2: Managed Navigation + custom CSS

The Managed Navigation requires some planning, manual work and a lot more maintenance then the Tree View. The way to enable it will be out of the scope of this post, but just don't forget to enable the Publishing feature on your sites before you switch to this navigation. It's a prerequisite. 

The way it looks in a very quick and simple demo is this:


But it's not collapsible by default!... Even though there are some articles online suggesting the use of fly-out menu I personally didn't feel it's good enough (e.g. a lot of levels will take a lot of space oon the right of the designated navigation menu control)

There's another solution which uses jQuery and provides the "accordion" feeling. But this will generally work if your items that you want to expand don't have a hyperlink. E.g. if in the above screenshot Operations doesn't point anywhere, then it would make sense to expand it with a click and see its children. But in our scenario the 1st level items would be links to actual sites...the solution still works... but in order to expand the children, you'd need to wait for the parent link to load. Not good, could be annoying for users and the link might point you to a site which doesn't inherit the same navigation. 

So... to just quickly review the Managed Navigation against Structured Navigation and the alternative Tree View option... read further.

Pros:

- Consistent across all sites if you inherit navigation in the subsites
- Very good for public sites or extranets, where you don't want it to definitely reflect your site structure.
- Better performance than the structured navigation
- More compact than the Tree View and very good looking when customized

Cons:

- Sites are not automatically added, it requires some maintenance
- Not security trimmed.
- Not collapsible OOB for use in Current Navigation. Needs custom CSS and potentially JavaScript.
- By default it's set to display only 2 levels of hierarchy - e.g. Projects site -> Project X subsite. If you want to display libraries and lists for example, or anything else... you need to touch the master page.

Now on the collapsing functionality... you can achieve that by using some simple css. Take the example a few lines below and save it somewhere on your SharePoint site. For the demo I've used a file, called sideNavBox.css and I've put it in the Style Library.

I got the original idea from Dércia Silva at broculus, but that solution seems to work well only for small navigation structures. I don't see it working with more than 2 levels and it requires you to click on a menu item (e.g. a site) to see its children.By default SharePoint will load the site if there's a valid link behind the navigation menu item. Not too good, you might have clicked on it by mistake, and you might not want to wait the load time (imagine it's a heavily customized site).  It also uses jQuery, while I think this functionality can be achieved by CSS only. 

So I decided to use the :hover pseudo selector instead of the .selected class to address the need for the click issue.

/* Do not show nested ul by default */
#sideNavBox .ms-core-listMenu-verticalBox ul ul {
 display: none; !important
}

/* Show nested ul on hover only */
#sideNavBox .ms-core-listMenu-verticalBox ul li:hover ul {
 display: block; !important
}


Now you need to refer your site to the custom CSS file. Go to Site Settings -> Master Page -> Alternate CSS URL (preferred solution): 



...or if for some reason you can't do the above, then as a last resort insert it in a custom Master Page directly by putting this line in the <head>. (change the path to your CSS). Please have in mind that custom Master Pages  in SharePoint Online should be used if no other customization option exist. The reason behind this is that you''ll end up not getting regular updates on master page functionalities released by Microsoft (they only deploy these to the oslo and seattle master pages).

If you're interested in the way Office 365 Sites branding is going forward, I recommend this great explanatory session by Vesa Juvonen. Then you can decide... to brand... or not to brand :) 

If you do decide to ignore the recommendations, here's the control you need to insert in your master page...

 <SharePoint:CssRegistration Name="Style%20Library/en-us/Themable/sideNavBox.css" runat="server" />

So, with the hovering trick and some more customizations I've added the nav menu looks like this. Currently I am hovering over the PMO link which is a site in a site collection (could be anything) and Project 1/2/3 are sites under PMO (again could be anything you add in the Managed Navigation through the term store management tool)

The extra styling is just for some similarity to the Tree View menu (the icon is a shameless steal from there)...  The "Edit Links" item is hidden and colors/sizes are slightly changed. Some cheeky icons added on the left to make it look more intuitive, too. Pretty  basic for the means of our example today:



Here's the additional CSS I applied:


/* Any style you want for the left-hand nav control*/
#sideNavBox {
background-color: #DBE8F3;
}

/* Making some room for the icons on the left */
.ms-core-sideNavBox-removeLeftMargin {
margin-left: 5px; !important
}

/* Insert the plus icon for the ul */
#sideNavBox  ul {
list-style-image: url('/Style%20Library/Images/Expand_01.gif'); !important
}

/* SP treeview expand icon for the nested ul */
#sideNavBox  ul li ul{
list-style-image: url('/_layouts/15/images/tvclosed.png'); !important
}


/* Hide the Edit Links button in the current nav */

.ms-listMenu-editLink {
 display: none; !important
}

And now to the levels... we have the requirement to display more than the two level of hierarchy on the screenshot above. Now if you get to this, and you definitely want to use Current Navigation (rather than Global Navigation) for this (regardless of the fact if you use Structured or Managed Nav in the background) then you need to edit your Master Page e.g. use a custom Master Page in SPO.

So, in a bit more details:

1. Create a blank master page
2. Open your seattle master page and copy all the code to the new one.
3. Go to the V4QuickLaunchMenu control.

       <SharePoint:AspMenu id="V4QuickLaunchMenu" runat="server" EnableViewState="false" DataSourceId="QuickLaunchSiteMap" UseSimpleRendering="true" Orientation="Vertical" StaticDisplayLevels="3" AdjustForShowStartingNode="true" MaximumDynamicDisplayLevels="0" SkipLinkText="" />

To properly achieve your goals, you might need a bit of clarifications on this above piece of code.

StaticDisplayLevels are the hierarchical items that will show in the navigation control. You would imagine that this solution will work like a charm and display the navigation representing the term store hierarchy. The problem is, if you increase that to 4, for example, you'll get this due to the lack of space in the OOB control. To visualize what I mean I've shown a small part of the term store managed navigation and the way it was represented after I've increased the StaticDisplayLevels.

So the expectation would be to see the same structure as on the left hand-side.
 ... but the reality is different: 

Let's look at the solution for this:

MaximumDynamicDisplayLevels are the hierarchical items that will show outside of the control.
Increasing that number will give you the items, but outside of the Quick Launch menu. Not too bad.
This functionality works OOB in the Global Navigation, so it's a good idea to consider that as well.


So... just a slight tuning here, in order to achieve the same styling as on the regular list items, I've had to apply the below CSS (not needed if you didn't use custom styling for this at all).

/* customize the dynamic ul */
#sideNavBox .ms-core-listMenu-verticalBox .dynamic {
 background-color: #DBE8F3; !important

}


That's it folks, hope you enjoy your new collapsible current navigation. If not, you can always switch to the Global Managed Navigation - it will collapse by default, it kind of uses the space on the screen in a more rational way and could be customized to the same extent. It's the user preference -horizontal or vertical menus... you could even go for the trendy mega menus in the Global Navigation (more suitable for public websites in my personal opinion anyway).

Attach additional event listener to out of the box SharePoint ribbon control

Have you ever had a use case where you must do something additional when an out of the box ribbon control is clicked, like "Open With Explorer" or "Export to Excel"? Maybe not, until now?
What could make this use case valid is the fact that the ribbon is slowly being phased out and it is no longer available in the modern experience, in addition not all features available in the ribbon are supported by all browsers and clients.
Having something additional being executed when a button from the ribbon is clicked can help you collect usage data for this features and better plan the move to modern experience or (like it or not) making Edge default browser, which does not support "Open with Explorer".
I am not aware of any other way to collect this information in SharePoint on-prem or Online.
Here is an example script that can be added as Scriptlink user custom action and it will attach additional click event listener on the "Open With Explorer" button. Everything that the function will do is to log the action, user name and the document library title in the console, but you can do whatever you find for useful, like logging it in the ULS or calling an API that will record the event.
I have tested it in SharePoint 2016 but it should work in SharePoint 2013 and SharePoint Online classic experience lists, it requires JQuery.



The Script:

Conditionally Show/Hide and Require SharePoint fields with JavaScript

In my last project I worked on DMS system based on SharePoint Server 2016 and had a very common requirement for the document forms. The requirement was to have Document Status field, Approval Reason and Rejected Reason fields. It is logical to want to hide Approval Reason when the document status is Rejected or Rejected Reason when the document is Approved.The client also wanted to make the fields required when the corresponding document status is selected. 
All customizations were going to be deployed using the classic way, with farm solution. I also had Nintex Forms, but I was unable to use it in this case due to other technical constraints.
That's why I decided to solve this requirement using JQuery and JavaScript script that are deployed with the WSP solution and included in the mater page.
The end result was pretty good and this is why I decided to share the script and a way to safely deploy it in SharePoint Online without the need to edit the master page or the list forms. The script is really simple and can be used/deployed as it is or with minor changes by person with moderate JavaScript experience.
Few notes on the SPO environment that was used. There are 3 custom site columns with following Title, InternalNames and Type: 
- Title: Document Status, InternalName: DocumentStatus, Choice, radio buttons
- Title: Approval Reason, InternalName: ApprovalReason, Multi-line text, Not required by definition
- Title: Rejected Reason, InternalName: RejectedReason, Multi-line text, Not required by definition

You can see the script below:

There are two main functions, showOrHideFields that will be started when the page is loaded and will show or hide Approval Reason or Rejected Reason field depending on the value of the Document Status field in New,View and Edit forms. The second function is with the specific name PreSaveAction, it will be launched when Check In or Save button is clicked and will not allow the form to be saved if Approval Reason or Rejected Reason fields are empty and will pop-out an "error" message below the field, again depending on the Document Status field value.
Below you can see how the form looks like in New,Edit and View mode.

New, Edit and View forms

In order to deploy the script without modifying the forms or the master page we are going to use the SharePoint PnP PowerShell module for SharePoint Online. In order to "inject" the javascript links we are going to use Add-PnPJavaScriptLink command. In the example below I am uploading the JS file, adding ScriptLink to it and adding ScriptLink to Google hosted JQuery library.



Add-PnPFile -Path "C:\Users\Ivan\Documents\ShowHide.js" -Folder "Style Library/scripts/" `
    -Checkout -Publish -CheckInComment ""
 
Add-PnPJavaScriptLink -Name JQuery `
    -Url "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"
 
Add-PnPJavaScriptLink -Name ShowHide `
    -Url "https://mod44444.sharepoint.com/Style%20Library/scripts/ShowHide.js"


Once the commands are executed the scripts will be loaded in all classic pages in the web(default scope for this command).
Unfortunately this really useful way of injecting JavaScript will not work with the modern pages and the new Library and List experience. More info on this huge gap can be found in this post.

I hope that this was helpful!
❌
❌